feat: merge source registry at startup

This commit is contained in:
lda
2026-06-04 00:29:44 +07:00 Verified
parent 4e8726f36d
commit 2433d58988
10 changed files with 273 additions and 24 deletions
+7 -2
View File
@@ -9,6 +9,7 @@ from ..control import BrokerConfigFile
from ..models import BrokerConfig
from ..runtime import McpRuntimePool, PersistentSessionFactory
from ..sdk import McpSdkAdapter
from ..source_registry import FileSourceRegistryStore
from ..storage import FileStore
from .service import WfMcpService
@@ -34,8 +35,12 @@ def build_service_from_config(config: BrokerConfig) -> WfMcpService:
# across sequential workflow nodes.
tool_executor=McpRuntimePool(runtime_factory.create),
)
for connection in config.connections:
service.register_connection(connection)
source_registry_store = FileSourceRegistryStore(config.store_root)
service.sync_connections_from_config(
config,
source_registry_store=source_registry_store,
)
for connection in service.connections.list_all():
if connection.server not in service.adapters:
service.register_adapter(connection.server, McpSdkAdapter())
return service
@@ -5,6 +5,7 @@ from dataclasses import dataclass, field
from ...connections import ConnectionRegistry, parse_connection_id
from ...models import BrokerConfig, ConnectionConfig
from ...shared.names import RESERVED_CONNECTION_IDS
from ...source_registry import SourceRegistryStore, registry_entry_to_connection_config
from .events import BrokerEventRecorder
from .source_catalog import SourceCatalogService
@@ -53,10 +54,35 @@ class ConnectionService:
payload={"server": connection.server, "account": connection.account},
)
def sync_connections_from_config(self, config: BrokerConfig) -> None:
def sync_connections_from_config(
self,
config: BrokerConfig,
*,
source_registry_store: SourceRegistryStore | None = None,
) -> None:
"""Reconcile registry/source state after the public server reloads config."""
# Config-defined connections win over registry entries with the same id;
# registry entries fill ids not present in config.
connections = list(config.connections)
config_ids = {connection.id for connection in connections}
if source_registry_store is not None:
registry = source_registry_store.load_registry()
for entry in registry.sources:
if entry.id in config_ids:
self.events.record_kind(
"source_registry_ignored_config_shadow",
connection_id=entry.id,
payload={
"server": entry.provider,
"account": entry.account,
"reason": "config_connection_takes_precedence",
},
)
continue
connections.append(registry_entry_to_connection_config(entry))
source_catalog = self._source_catalog()
next_ids = {connection.id for connection in config.connections}
next_ids = {connection.id for connection in connections}
previous_ids = set(self.connections.connections)
for connection_id in previous_ids - next_ids:
previous = self.connections.connections[connection_id]
@@ -71,7 +97,7 @@ class ConnectionService:
payload={"server": previous.server, "account": previous.account},
)
for connection in config.connections:
for connection in connections:
self._validate_connection_id(connection.id)
previous = self.connections.connections.get(connection.id)
self.connections.register(connection)
+11 -2
View File
@@ -32,6 +32,7 @@ from ...models import (
)
from ...sdk import BackendAdapter
from ...runtime import ToolExecutor
from ...source_registry import SourceRegistryStore
from .connection_service import ConnectionService
from .content_access import ContentAccessService
from ...storage import Store
@@ -138,8 +139,16 @@ class WfMcpService:
def register_connection(self, connection: ConnectionConfig) -> None:
self.connection_service.register_connection(connection)
def sync_connections_from_config(self, config: BrokerConfig) -> None:
self.connection_service.sync_connections_from_config(config)
def sync_connections_from_config(
self,
config: BrokerConfig,
*,
source_registry_store: SourceRegistryStore | None = None,
) -> None:
self.connection_service.sync_connections_from_config(
config,
source_registry_store=source_registry_store,
)
def register_adapter(self, server: str, adapter: BackendAdapter) -> None:
self.upstream.register_adapter(server, adapter)
+6 -2
View File
@@ -13,6 +13,7 @@ from ..broker.transport import normalize_transport
from ..documentation import build_local_documentation_source
from ..models import BrokerConfig
from ..sdk import McpSdkAdapter
from ..source_registry import FileSourceRegistryStore
from ..proxy.runtime import ProxyRuntime
from ..workflow_surface import register_workflow_tools
from .prompts import register_documentation_prompts
@@ -33,8 +34,11 @@ def create_server(
service = build_service_from_config(config)
def sync_service(config: BrokerConfig) -> None:
service.sync_connections_from_config(config)
for connection in config.connections:
service.sync_connections_from_config(
config,
source_registry_store=FileSourceRegistryStore(config.store_root),
)
for connection in service.connections.list_all():
if connection.server not in service.adapters:
service.register_adapter(connection.server, McpSdkAdapter())