feat(core): enforce server prefixes for MCP tools in agent definitions (#17574)

This commit is contained in:
Abhi
2026-01-26 23:53:05 -05:00
committed by GitHub
parent 9fcdc0cdc1
commit eccc200f4f
5 changed files with 94 additions and 5 deletions
+8 -2
View File
@@ -23,6 +23,12 @@ import { ToolErrorType } from './tool-error.js';
import type { Config } from '../config/config.js';
import type { MessageBus } from '../confirmation-bus/message-bus.js';
/**
* The separator used to qualify MCP tool names with their server prefix.
* e.g. "server_name__tool_name"
*/
export const MCP_QUALIFIED_NAME_SEPARATOR = '__';
type ToolParams = Record<string, unknown>;
// Discriminated union for MCP Content Blocks to ensure type safety.
@@ -82,7 +88,7 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
super(
params,
messageBus,
`${serverName}__${serverToolName}`,
`${serverName}${MCP_QUALIFIED_NAME_SEPARATOR}${serverToolName}`,
displayName,
serverName,
);
@@ -261,7 +267,7 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
}
getFullyQualifiedPrefix(): string {
return `${this.serverName}__`;
return `${this.serverName}${MCP_QUALIFIED_NAME_SEPARATOR}`;
}
getFullyQualifiedName(): string {
+17 -1
View File
@@ -13,7 +13,7 @@ import { ApprovalMode } from '../policy/types.js';
import { ToolRegistry, DiscoveredTool } from './tool-registry.js';
import { DISCOVERED_TOOL_PREFIX } from './tool-names.js';
import { DiscoveredMCPTool } from './mcp-tool.js';
import { DiscoveredMCPTool, MCP_QUALIFIED_NAME_SEPARATOR } from './mcp-tool.js';
import type { FunctionDeclaration, CallableTool } from '@google/genai';
import { mcpToTool } from '@google/genai';
import { spawn } from 'node:child_process';
@@ -568,6 +568,22 @@ describe('ToolRegistry', () => {
expect(retrievedTool).toBeDefined();
expect(retrievedTool?.name).toBe(validToolName);
});
it('should resolve qualified names in getFunctionDeclarationsFiltered', () => {
const serverName = 'my-server';
const toolName = 'my-tool';
const mcpTool = createMCPTool(serverName, toolName, 'description');
toolRegistry.registerTool(mcpTool);
const fullyQualifiedName = `${serverName}${MCP_QUALIFIED_NAME_SEPARATOR}${toolName}`;
const declarations = toolRegistry.getFunctionDeclarationsFiltered([
fullyQualifiedName,
]);
expect(declarations).toHaveLength(1);
expect(declarations[0].name).toBe(toolName);
});
});
describe('DiscoveredToolInvocation', () => {
+2 -2
View File
@@ -488,8 +488,8 @@ export class ToolRegistry {
getFunctionDeclarationsFiltered(toolNames: string[]): FunctionDeclaration[] {
const declarations: FunctionDeclaration[] = [];
for (const name of toolNames) {
const tool = this.allKnownTools.get(name);
if (tool && this.isActiveTool(tool)) {
const tool = this.getTool(name);
if (tool) {
declarations.push(tool.schema);
}
}