fix(coding-agent/acp): MCP tools from Zed not activated in ACP sessions
When Zed provisions MCP servers through `session/new.mcpServers`, the
ACP agent
correctly connects to them and registers their tools via
`refreshMCPTools`, but
the tools were never activated. `refreshMCPTools` builds the next
active tool
set from `getSelectedMCPToolNames()`, which — with discovery disabled —
returns
only MCP tools already in the active set. Since ACP sessions start with
no MCP
tools, this created a circular deadlock: tools could only become active
if they
were already active.
Added an optional `{ activateAll?: boolean }` parameter to
`refreshMCPTools`.
When true, every newly registered tool is force-activated regardless of
prior
selection. `AcpAgent#configureMcpServers` passes `activateAll: true` on
both
call sites so client-provisioned tools are immediately usable.
This commit is contained in:
@@ -1981,7 +1981,7 @@ export class AcpAgent implements Agent {
|
||||
}
|
||||
if (servers.length === 0) {
|
||||
record.mcpManager = undefined;
|
||||
await record.session.refreshMCPTools([]);
|
||||
await record.session.refreshMCPTools([], { activateAll: true });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2008,7 +2008,7 @@ export class AcpAgent implements Agent {
|
||||
}
|
||||
|
||||
record.mcpManager = manager;
|
||||
await record.session.refreshMCPTools(result.tools);
|
||||
await record.session.refreshMCPTools(result.tools, { activateAll: true });
|
||||
}
|
||||
|
||||
#toMcpConfig(server: McpServer): MCPServerConfig {
|
||||
|
||||
@@ -3617,8 +3617,13 @@ export class AgentSession {
|
||||
/**
|
||||
* Replace MCP tools in the registry and recompute the visible MCP tool set immediately.
|
||||
* This allows /mcp add/remove/reauth to take effect without restarting the session.
|
||||
*
|
||||
* @param mcpTools The new MCP tools to register.
|
||||
* @param options.activateAll When true, force-activates every newly registered MCP tool
|
||||
* regardless of prior selection state. Used when an ACP client provisions MCP servers
|
||||
* for a session where MCP discovery is disabled.
|
||||
*/
|
||||
async refreshMCPTools(mcpTools: CustomTool[]): Promise<void> {
|
||||
async refreshMCPTools(mcpTools: CustomTool[], options?: { activateAll?: boolean }): Promise<void> {
|
||||
const previousSelectedMCPToolNames = this.getSelectedMCPToolNames();
|
||||
const existingNames = Array.from(this.#toolRegistry.keys());
|
||||
for (const name of existingNames) {
|
||||
@@ -3659,6 +3664,18 @@ export class AgentSession {
|
||||
this.#getConfiguredDefaultSelectedMCPToolNames(),
|
||||
);
|
||||
|
||||
if (options?.activateAll) {
|
||||
// Force-activate every newly registered MCP tool. This path is used
|
||||
// when an ACP client provisions MCP servers for a session where MCP
|
||||
// discovery is disabled — without it, getSelectedMCPToolNames()
|
||||
// returns only already-active tools (circular deadlock: tools can
|
||||
// only become active if they're already active).
|
||||
const newMcpNames = mcpTools.map(t => t.name);
|
||||
const nextActive = [...new Set([...this.#getActiveNonMCPToolNames(), ...newMcpNames])];
|
||||
await this.#applyActiveToolsByName(nextActive, { previousSelectedMCPToolNames });
|
||||
return;
|
||||
}
|
||||
|
||||
const nextActive = [...this.#getActiveNonMCPToolNames(), ...this.getSelectedMCPToolNames()];
|
||||
await this.#applyActiveToolsByName(nextActive, { previousSelectedMCPToolNames });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user