fix(mcp): clear prompt registry on refresh to prevent duplicates (#5385)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
Co-authored-by: Sandy Tao <sandytao520@icloud.com>
This commit is contained in:
Ramón Medrano Llamas 2025-08-05 23:59:31 +02:00 committed by GitHub
parent faf6a5497a
commit 29c3825604
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 40 additions and 12 deletions

View File

@ -53,4 +53,22 @@ export class PromptRegistry {
} }
return serverPrompts.sort((a, b) => a.name.localeCompare(b.name)); return serverPrompts.sort((a, b) => a.name.localeCompare(b.name));
} }
/**
* Clears all the prompts from the registry.
*/
clear(): void {
this.prompts.clear();
}
/**
* Removes all prompts from a specific server.
*/
removePromptsByServer(serverName: string): void {
for (const [name, prompt] of this.prompts.entries()) {
if (prompt.serverName === serverName) {
this.prompts.delete(name);
}
}
}
} }

View File

@ -172,6 +172,10 @@ describe('ToolRegistry', () => {
); );
vi.spyOn(config, 'getMcpServers'); vi.spyOn(config, 'getMcpServers');
vi.spyOn(config, 'getMcpServerCommand'); vi.spyOn(config, 'getMcpServerCommand');
vi.spyOn(config, 'getPromptRegistry').mockReturnValue({
clear: vi.fn(),
removePromptsByServer: vi.fn(),
} as any);
mockDiscoverMcpTools.mockReset().mockResolvedValue(undefined); mockDiscoverMcpTools.mockReset().mockResolvedValue(undefined);
}); });
@ -353,7 +357,7 @@ describe('ToolRegistry', () => {
mcpServerConfigVal, mcpServerConfigVal,
undefined, undefined,
toolRegistry, toolRegistry,
undefined, config.getPromptRegistry(),
false, false,
); );
}); });
@ -376,7 +380,7 @@ describe('ToolRegistry', () => {
mcpServerConfigVal, mcpServerConfigVal,
undefined, undefined,
toolRegistry, toolRegistry,
undefined, config.getPromptRegistry(),
false, false,
); );
}); });

View File

@ -150,6 +150,14 @@ export class ToolRegistry {
this.tools.set(tool.name, tool); this.tools.set(tool.name, tool);
} }
private removeDiscoveredTools(): void {
for (const tool of this.tools.values()) {
if (tool instanceof DiscoveredTool || tool instanceof DiscoveredMCPTool) {
this.tools.delete(tool.name);
}
}
}
/** /**
* Discovers tools from project (if available and configured). * Discovers tools from project (if available and configured).
* Can be called multiple times to update discovered tools. * Can be called multiple times to update discovered tools.
@ -157,11 +165,9 @@ export class ToolRegistry {
*/ */
async discoverAllTools(): Promise<void> { async discoverAllTools(): Promise<void> {
// remove any previously discovered tools // remove any previously discovered tools
for (const tool of this.tools.values()) { this.removeDiscoveredTools();
if (tool instanceof DiscoveredTool || tool instanceof DiscoveredMCPTool) {
this.tools.delete(tool.name); this.config.getPromptRegistry().clear();
}
}
await this.discoverAndRegisterToolsFromCommand(); await this.discoverAndRegisterToolsFromCommand();
@ -182,11 +188,9 @@ export class ToolRegistry {
*/ */
async discoverMcpTools(): Promise<void> { async discoverMcpTools(): Promise<void> {
// remove any previously discovered tools // remove any previously discovered tools
for (const tool of this.tools.values()) { this.removeDiscoveredTools();
if (tool instanceof DiscoveredMCPTool) {
this.tools.delete(tool.name); this.config.getPromptRegistry().clear();
}
}
// discover tools using MCP servers, if configured // discover tools using MCP servers, if configured
await discoverMcpTools( await discoverMcpTools(
@ -210,6 +214,8 @@ export class ToolRegistry {
} }
} }
this.config.getPromptRegistry().removePromptsByServer(serverName);
const mcpServers = this.config.getMcpServers() ?? {}; const mcpServers = this.config.getMcpServers() ?? {};
const serverConfig = mcpServers[serverName]; const serverConfig = mcpServers[serverName];
if (serverConfig) { if (serverConfig) {