From 3d4144697830e2d90aea7dddbc5eb7082c92e61c Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 6 Dec 2024 13:01:56 -0600 Subject: [PATCH 1/3] check for mcp client attrubutes --- core/context/mcp/index.ts | 119 ++++++++++++++++------------ extensions/vscode/package-lock.json | 4 +- 2 files changed, 72 insertions(+), 51 deletions(-) diff --git a/core/context/mcp/index.ts b/core/context/mcp/index.ts index 984ba8f7b6..e411360279 100644 --- a/core/context/mcp/index.ts +++ b/core/context/mcp/index.ts @@ -87,6 +87,15 @@ class MCPConnectionSingleton { } } + async checkClientAttribute(func: () => Promise): Promise { + try { + const result = await func(); + return result; + } catch (e) { + return null; + } + } + async modifyConfig(config: ContinueConfig): Promise { try { await this.connectClient(); @@ -96,60 +105,72 @@ class MCPConnectionSingleton { return config; } } - + // Resources <—> Context Provider - const { resources } = await this.client.listResources(); - - const submenuItems = resources.map((resource: any) => ({ - title: resource.name, - description: resource.description, - id: resource.uri, - })); - - if (!config.contextProviders) { - config.contextProviders = []; + const rawResources = await this.checkClientAttribute(() => this.client.listResources()); + if (rawResources && rawResources.resources) { + const submenuItems = rawResources.resources.map((resource: any) => ({ + title: resource.name, + description: resource.description, + id: resource.uri, + })); + + if (!config.contextProviders) { + config.contextProviders = []; + } + + config.contextProviders.push( + new MCPContextProvider({ + submenuItems, + client: this.client, + }), + ); + } else { + console.warn("Failed to retrieve resources or resources are empty"); } - - config.contextProviders!.push( - new MCPContextProvider({ - submenuItems, - client: this.client, - }), - ); - + // Tools <—> Tools - const { tools } = await this.client.listTools(); - const continueTools: Tool[] = tools.map((tool) => ({ - displayTitle: tool.name, - function: { - description: tool.description, - name: tool.name, - parameters: tool.inputSchema, - }, - readonly: false, - type: "function", - wouldLikeTo: `use the ${tool.name} tool`, - uri: `mcp://${tool.name}`, - })); - - config.tools = [...config.tools, ...continueTools]; - - // Prompts <—> Slash commands - const { prompts } = await this.client.listPrompts(); - if (!config.slashCommands) { - config.slashCommands = []; + const rawTools = await this.checkClientAttribute(() => this.client.listTools()); + if (rawTools && rawTools.tools) { + const continueTools: Tool[] = rawTools.tools.map((tool: any) => ({ + displayTitle: tool.name, + function: { + description: tool.description, + name: tool.name, + parameters: tool.inputSchema, + }, + readonly: false, + type: "function", + wouldLikeTo: `use the ${tool.name} tool`, + uri: `mcp://${tool.name}`, + })); + + config.tools = [...config.tools, ...continueTools]; + } else { + console.warn("Failed to retrieve tools or tools are empty"); } - - const slashCommands: SlashCommand[] = prompts.map((prompt) => { - return constructMcpSlashCommand( - this.client, - prompt.name, - prompt.description, - prompt.arguments?.map((a) => a.name), + + // Prompts <—> Slash commands + const rawPrompts = await this.checkClientAttribute(() => this.client.listPrompts()); + if (rawPrompts && rawPrompts.prompts) { + if (!config.slashCommands) { + config.slashCommands = []; + } + + const slashCommands: SlashCommand[] = rawPrompts.prompts.map((prompt: any) => + constructMcpSlashCommand( + this.client, + prompt.name, + prompt.description, + prompt.arguments?.map((a: any) => a.name), + ) ); - }); - config.slashCommands!.push(...slashCommands); - + + config.slashCommands.push(...slashCommands); + } else { + console.warn("Failed to retrieve prompts or prompts are empty"); + } + return config; } } diff --git a/extensions/vscode/package-lock.json b/extensions/vscode/package-lock.json index 923f4c9b5a..ea5966c13a 100644 --- a/extensions/vscode/package-lock.json +++ b/extensions/vscode/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.9.244", + "version": "0.9.240", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "continue", - "version": "0.9.244", + "version": "0.9.240", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", From 4e3b3004ff7edffe36bb833af68d548e4ee33040 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 6 Dec 2024 13:57:27 -0600 Subject: [PATCH 2/3] add prefix to built in tools --- core/tools/builtIn.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/tools/builtIn.ts b/core/tools/builtIn.ts index 55e2c52148..d15db456c4 100644 --- a/core/tools/builtIn.ts +++ b/core/tools/builtIn.ts @@ -1,11 +1,11 @@ export enum BuiltInToolNames { - ReadFile = "read_file", - ReadCurrentlyOpenFile = "read_currently_open_file", - CreateNewFile = "create_new_file", - RunTerminalCommand = "run_terminal_command", - ViewSubdirectory = "view_subdirectory", - ViewRepoMap = "view_repo_map", - ExactSearch = "exact_search", - SearchWeb = "search_web", - ViewDiff = "view_diff", -} + ReadFile = "builtin_read_file", + ReadCurrentlyOpenFile = "builtin_read_currently_open_file", + CreateNewFile = "builtin_create_new_file", + RunTerminalCommand = "builtin_run_terminal_command", + ViewSubdirectory = "builtin_view_subdirectory", + ViewRepoMap = "builtin_view_repo_map", + ExactSearch = "builtin_exact_search", + SearchWeb = "builtin_search_web", + ViewDiff = "builtin_view_diff", +} \ No newline at end of file From 28617751b2df9d703dafc6a24a522b77f2a36a87 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Mon, 9 Dec 2024 17:21:05 -0600 Subject: [PATCH 3/3] use MCP interface to verify server capabilities --- core/context/mcp/index.ts | 46 ++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/core/context/mcp/index.ts b/core/context/mcp/index.ts index e411360279..772da78918 100644 --- a/core/context/mcp/index.ts +++ b/core/context/mcp/index.ts @@ -105,34 +105,34 @@ class MCPConnectionSingleton { return config; } } - + + const capabilities = this.client.getServerCapabilities(); + // Resources <—> Context Provider - const rawResources = await this.checkClientAttribute(() => this.client.listResources()); - if (rawResources && rawResources.resources) { - const submenuItems = rawResources.resources.map((resource: any) => ({ + if (capabilities?.resources) { + const { resources } = await this.client.listResources(); + const submenuItems = resources.map((resource: any) => ({ title: resource.name, description: resource.description, id: resource.uri, })); - + if (!config.contextProviders) { config.contextProviders = []; } - + config.contextProviders.push( new MCPContextProvider({ submenuItems, client: this.client, }), ); - } else { - console.warn("Failed to retrieve resources or resources are empty"); } - + // Tools <—> Tools - const rawTools = await this.checkClientAttribute(() => this.client.listTools()); - if (rawTools && rawTools.tools) { - const continueTools: Tool[] = rawTools.tools.map((tool: any) => ({ + if (capabilities?.tools) { + const { tools } = await this.client.listTools(); + const continueTools: Tool[] = tools.map((tool: any) => ({ displayTitle: tool.name, function: { description: tool.description, @@ -144,33 +144,29 @@ class MCPConnectionSingleton { wouldLikeTo: `use the ${tool.name} tool`, uri: `mcp://${tool.name}`, })); - + config.tools = [...config.tools, ...continueTools]; - } else { - console.warn("Failed to retrieve tools or tools are empty"); } - + // Prompts <—> Slash commands - const rawPrompts = await this.checkClientAttribute(() => this.client.listPrompts()); - if (rawPrompts && rawPrompts.prompts) { + if (capabilities?.prompts) { + const { prompts } = await this.client.listPrompts(); if (!config.slashCommands) { config.slashCommands = []; } - - const slashCommands: SlashCommand[] = rawPrompts.prompts.map((prompt: any) => + + const slashCommands: SlashCommand[] = prompts.map((prompt: any) => constructMcpSlashCommand( this.client, prompt.name, prompt.description, prompt.arguments?.map((a: any) => a.name), - ) + ), ); - + config.slashCommands.push(...slashCommands); - } else { - console.warn("Failed to retrieve prompts or prompts are empty"); } - + return config; } }