From cbace8af70abcdddb374aa81bd6b500ea3dc1024 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Thu, 27 Aug 2026 09:51:08 +0200 Subject: [PATCH] ui: initialize only policy-enabled MCP servers for a flow ensureInitialized accepts an optional server id set; the agentic flow passes the servers its tool policy leaves usable, so servers disabled for the conversation no longer get connected. Callers without arguments keep the global behavior. Assisted-by: pi --- .../ui/src/lib/stores/agentic/index.svelte.ts | 22 ++++++++++--------- tools/ui/src/lib/stores/mcp/index.svelte.ts | 17 +++++++++++--- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/tools/ui/src/lib/stores/agentic/index.svelte.ts b/tools/ui/src/lib/stores/agentic/index.svelte.ts index bbf2526ce0..bf39b5e34f 100644 --- a/tools/ui/src/lib/stores/agentic/index.svelte.ts +++ b/tools/ui/src/lib/stores/agentic/index.svelte.ts @@ -329,18 +329,20 @@ class AgenticStore { const disabledToolCategories = new Set( toolPolicy?.disabledToolCategories ?? toolsStore.disabledToolCategories ); - // skip MCP init when the policy leaves no usable server: either the whole - // MCP category is off, or every globally-enabled server has its group key - // disabled for this flow - const hasMcpServers = - mcpStore.hasEnabledServers() && - !disabledToolCategories.has(ToolSource.MCP) && - mcpStore - .getServers() - .some((s) => s.enabled && !disabledTools.has(toolsStore.getMcpServerToolsKey(s.id))); + // servers usable under this flow's policy: globally enabled, category on, + // and their server-scoped group key not disabled + const policyEnabledServerIds = new Set( + disabledToolCategories.has(ToolSource.MCP) + ? [] + : mcpStore + .getServers() + .filter((s) => s.enabled && !disabledTools.has(toolsStore.getMcpServerToolsKey(s.id))) + .map((s) => s.id) + ); + const hasMcpServers = policyEnabledServerIds.size > 0; if (hasMcpServers) { - const initialized = await mcpStore.ensureInitialized(); + const initialized = await mcpStore.ensureInitialized(policyEnabledServerIds); if (!initialized) { console.log('[AgenticStore] MCP not initialized'); diff --git a/tools/ui/src/lib/stores/mcp/index.svelte.ts b/tools/ui/src/lib/stores/mcp/index.svelte.ts index 0b9eddf6bf..cb8be06c82 100644 --- a/tools/ui/src/lib/stores/mcp/index.svelte.ts +++ b/tools/ui/src/lib/stores/mcp/index.svelte.ts @@ -306,12 +306,18 @@ class MCPStore implements McpHealthHost { return extras; } - async ensureInitialized(): Promise { + /** + * Initialize connections. Callers can restrict which servers connect by + * passing their ids (e.g. a conversation's tool policy); a different set + * changes the config signature and re-initializes, same as a settings + * change. + */ + async ensureInitialized(serverIds?: ReadonlySet): Promise { if (!browser) { return false; } - const mcpConfig = this.buildMcpClientConfig(settingsStore.config); + const mcpConfig = this.buildMcpClientConfig(settingsStore.config, serverIds); const signature = mcpConfig ? JSON.stringify(mcpConfig) : null; if (!signature) { @@ -1157,7 +1163,10 @@ class MCPStore implements McpHealthHost { /** * Builds MCP client configuration from settings. */ - private buildMcpClientConfig(cfg: SettingsConfigType): MCPClientConfig | undefined { + private buildMcpClientConfig( + cfg: SettingsConfigType, + serverIds?: ReadonlySet + ): MCPClientConfig | undefined { const rawServers = parseMcpServerSettings(cfg.mcpServers); if (!rawServers.length) { @@ -1169,6 +1178,8 @@ class MCPStore implements McpHealthHost { for (const [index, entry] of rawServers.entries()) { if (!entry.enabled) continue; + if (serverIds && !serverIds.has(entry.id)) continue; + const normalized = this.buildServerConfig(entry); if (normalized) servers[this.generateServerId(entry.id, index)] = normalized;