fix(cli): include subagent-specific MCP tools in /mcp list display

Fixes #22884

Currently, /mcp list in interactive mode only retrieves tools from the main ToolRegistry. This means that MCP servers configured exclusively for a subagent (which exist in isolated registries) do not have their active tools displayed, even though the server correctly shows as 'Connected'.

This commit introduces a unified `getAllDiscoveredMcpTools()`, `getAllDiscoveredPrompts()`, and `getAllDiscoveredResources()` methods in `McpClientManager` to aggregate these from all registered registries via `McpClient`. The `listAction` command has been updated to use these unified accessors, ensuring an accurate representation of all active MCP capabilities regardless of which registry they reside in.
This commit is contained in:
Akhilesh Kumar
2026-03-18 02:54:08 +00:00
parent bd34a42ec3
commit eafa3d9ae5
3 changed files with 102 additions and 15 deletions
+10 -14
View File
@@ -12,7 +12,6 @@ import type {
import { CommandKind } from './types.js';
import type { MessageActionReturn } from '@google/gemini-cli-core';
import {
DiscoveredMCPTool,
getMCPDiscoveryState,
getMCPServerStatus,
MCPDiscoveryState,
@@ -210,21 +209,18 @@ const listAction = async (
discoveryState === MCPDiscoveryState.IN_PROGRESS ||
connectingServers.length > 0;
const allTools = toolRegistry.getAllTools();
const mcpTools = allTools.filter((tool) => tool instanceof DiscoveredMCPTool);
const mcpClientManager = config.getMcpClientManager();
const mcpTools = mcpClientManager
? mcpClientManager.getAllDiscoveredMcpTools()
: [];
const promptRegistry = config.getPromptRegistry();
const mcpPrompts = promptRegistry
.getAllPrompts()
.filter(
(prompt) =>
'serverName' in prompt && serverNames.includes(prompt.serverName),
);
const mcpPrompts = mcpClientManager
? mcpClientManager.getAllDiscoveredPrompts()
: [];
const resourceRegistry = config.getResourceRegistry();
const mcpResources = resourceRegistry
.getAllResources()
.filter((entry) => serverNames.includes(entry.serverName));
const mcpResources = mcpClientManager
? mcpClientManager.getAllDiscoveredResources()
: [];
const authStatus: HistoryItemMcpStatus['authStatus'] = {};
const tokenStorage = new MCPOAuthTokenStorage();
+42 -1
View File
@@ -15,7 +15,9 @@ import {
MCPDiscoveryState,
MCPServerStatus,
populateMcpServerCommand,
type DiscoveredMCPPrompt,
} from './mcp-client.js';
import type { DiscoveredMCPTool } from './mcp-tool.js';
import { getErrorMessage, isAuthenticationError } from '../utils/errors.js';
import type { EventEmitter } from 'node:events';
import { coreEvents } from '../utils/events.js';
@@ -24,7 +26,10 @@ import { debugLogger } from '../utils/debugLogger.js';
import { createHash } from 'node:crypto';
import { stableStringify } from '../policy/stable-stringify.js';
import type { PromptRegistry } from '../prompts/prompt-registry.js';
import type { ResourceRegistry } from '../resources/resource-registry.js';
import type {
ResourceRegistry,
MCPResource,
} from '../resources/resource-registry.js';
/**
* Manages the lifecycle of multiple MCP clients, including local child processes.
@@ -645,6 +650,42 @@ export class McpClientManager {
return this.discoveryState;
}
/**
* Retrieves all discovered MCP tools across all connected servers
* and their respective registries.
*/
getAllDiscoveredMcpTools(): DiscoveredMCPTool[] {
const allTools: DiscoveredMCPTool[] = [];
for (const client of this.clients.values()) {
allTools.push(...client.getAllDiscoveredTools());
}
return allTools;
}
/**
* Retrieves all discovered MCP prompts across all connected servers
* and their respective registries.
*/
getAllDiscoveredPrompts(): DiscoveredMCPPrompt[] {
const allPrompts: DiscoveredMCPPrompt[] = [];
for (const client of this.clients.values()) {
allPrompts.push(...client.getAllDiscoveredPrompts());
}
return allPrompts;
}
/**
* Retrieves all discovered MCP resources across all connected servers
* and their respective registries.
*/
getAllDiscoveredResources(): MCPResource[] {
const allResources: MCPResource[] = [];
for (const client of this.clients.values()) {
allResources.push(...client.getAllDiscoveredResources());
}
return allResources;
}
/**
* All of the MCP server configurations (including disabled ones).
*/
+50
View File
@@ -274,6 +274,56 @@ export class McpClient implements McpProgressReporter {
this.registeredRegistries.delete(registries);
}
/**
* Gets all discovered tools registered by this client across all of its
* associated registry sets.
*/
getAllDiscoveredTools(): DiscoveredMCPTool[] {
const tools = new Map<string, DiscoveredMCPTool>();
for (const registries of this.registeredRegistries) {
const serverTools =
registries.toolRegistry.getToolsByServer(this.serverName) || [];
for (const tool of serverTools) {
if (tool instanceof DiscoveredMCPTool) {
tools.set(tool.name, tool);
}
}
}
return Array.from(tools.values());
}
/**
* Gets all discovered prompts registered by this client across all of its
* associated registry sets.
*/
getAllDiscoveredPrompts(): DiscoveredMCPPrompt[] {
const prompts = new Map<string, DiscoveredMCPPrompt>();
for (const registries of this.registeredRegistries) {
const serverPrompts =
registries.promptRegistry.getPromptsByServer(this.serverName) || [];
for (const prompt of serverPrompts) {
prompts.set(prompt.name, prompt);
}
}
return Array.from(prompts.values());
}
/**
* Gets all discovered resources registered by this client across all of its
* associated registry sets.
*/
getAllDiscoveredResources(): MCPResource[] {
const resources = new Map<string, MCPResource>();
for (const registries of this.registeredRegistries) {
const serverResources =
registries.resourceRegistry.getResourcesByServer(this.serverName) || [];
for (const resource of serverResources) {
resources.set(resource.uri, resource);
}
}
return Array.from(resources.values());
}
/**
* Disconnects from the MCP server.
*/