Просмотр исходного кода

feat: auto-omit MCP content when no servers are configured (#5889)

* feat: auto-omit MCP content when no servers are configured

- Modify system prompt generation to detect when no MCP servers are defined
- Only include MCP sections when mode has mcp group AND servers exist
- Pass undefined mcpHub to capabilities and tools when no servers available
- Reduces system prompt verbosity when MCP functionality is not in use

* fix: add missing Uri and RelativePattern exports to VSCode mocks

- Added Uri and RelativePattern exports to global VSCode mock in __mocks__/vscode.js
- Fixed McpHub.spec.ts VSCode mock to include Uri and RelativePattern
- Fixed Task.spec.ts VSCode mock to include Uri and RelativePattern with proper TypeScript typing
- Resolves unhandled rejection errors in unit tests caused by missing VSCode API mocks

* fix: add proper TypeScript typing for RelativePattern in McpHub test mock

* fix: resolve unit test failures in PR #5889

- Fix VSCode mock onDidChangeWorkspaceFolders to accept callback parameter
- Update MCP test mocks to properly test auto-omit functionality
- Update test snapshots to reflect new MCP content omission behavior
- All core functionality tests now passing

* chore: remove package-lock.json as project uses npm

* fix: remove unrelated mock changes from PR

---------

Co-authored-by: Roo Code <[email protected]>
Co-authored-by: Daniel Riccio <[email protected]>
roomote[bot] 5 месяцев назад
Родитель
Сommit
cfda8392fb

+ 0 - 62
src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap

@@ -269,55 +269,6 @@ Examples:
 <ignore_case>true</ignore_case>
 <ignore_case>true</ignore_case>
 </search_and_replace>
 </search_and_replace>
 
 
-## use_mcp_tool
-Description: Request to use a tool provided by a connected MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.
-Parameters:
-- server_name: (required) The name of the MCP server providing the tool
-- tool_name: (required) The name of the tool to execute
-- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
-Usage:
-<use_mcp_tool>
-<server_name>server name here</server_name>
-<tool_name>tool name here</tool_name>
-<arguments>
-{
-  "param1": "value1",
-  "param2": "value2"
-}
-</arguments>
-</use_mcp_tool>
-
-Example: Requesting to use an MCP tool
-
-<use_mcp_tool>
-<server_name>weather-server</server_name>
-<tool_name>get_forecast</tool_name>
-<arguments>
-{
-  "city": "San Francisco",
-  "days": 5
-}
-</arguments>
-</use_mcp_tool>
-
-## access_mcp_resource
-Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
-Parameters:
-- server_name: (required) The name of the MCP server providing the resource
-- uri: (required) The URI identifying the specific resource to access
-Usage:
-<access_mcp_resource>
-<server_name>server name here</server_name>
-<uri>resource URI here</uri>
-</access_mcp_resource>
-
-Example: Requesting to access an MCP resource
-
-<access_mcp_resource>
-<server_name>weather-server</server_name>
-<uri>weather://san-francisco/current</uri>
-</access_mcp_resource>
-
 ## ask_followup_question
 ## ask_followup_question
 Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
 Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
 Parameters:
 Parameters:
@@ -508,18 +459,7 @@ It is crucial to proceed step-by-step, waiting for the user's message after each
 
 
 By waiting for and carefully considering the user's response after each tool use, you can react accordingly and make informed decisions about how to proceed with the task. This iterative process helps ensure the overall success and accuracy of your work.
 By waiting for and carefully considering the user's response after each tool use, you can react accordingly and make informed decisions about how to proceed with the task. This iterative process helps ensure the overall success and accuracy of your work.
 
 
-MCP SERVERS
-
-The Model Context Protocol (MCP) enables communication between the system and MCP servers that provide additional tools and resources to extend your capabilities. MCP servers can be one of two types:
 
 
-1. Local (Stdio-based) servers: These run locally on the user's machine and communicate via standard input/output
-2. Remote (SSE-based) servers: These run on remote machines and communicate via Server-Sent Events (SSE) over HTTP/HTTPS
-
-# Connected MCP Servers
-
-When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool.
-
-(No MCP servers currently connected)
 
 
 ====
 ====
 
 
@@ -531,8 +471,6 @@ CAPABILITIES
 - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task.
 - You can use the list_code_definition_names tool to get an overview of source code definitions for all files at the top level of a specified directory. This can be particularly useful when you need to understand the broader context and relationships between certain parts of the code. You may need to call this tool multiple times to understand various parts of the codebase related to the task.
     - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed.
     - For example, when asked to make edits or improvements you might analyze the file structure in the initial environment_details to get an overview of the project, then use list_code_definition_names to get further insight using source code definitions for files located in relevant directories, then read_file to examine the contents of relevant files, analyze the code and suggest improvements or make necessary edits, then use the write_to_file tool to apply the changes. If you refactored code that could affect other parts of the codebase, you could use search_files to ensure you update other files as needed.
 - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance.
 - You can use the execute_command tool to run commands on the user's computer whenever you feel it can help accomplish the user's task. When you need to execute a CLI command, you must provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, since they are more flexible and easier to run. Interactive and long-running commands are allowed, since the commands are run in the user's VSCode terminal. The user may keep commands running in the background and you will be kept updated on their status along the way. Each command you execute is run in a new terminal instance.
-- You have access to MCP servers that may provide additional tools and resources. Each server may provide different capabilities that you can use to accomplish tasks more effectively.
-
 
 
 ====
 ====
 
 

+ 1 - 1
src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap

@@ -519,7 +519,7 @@ The Model Context Protocol (MCP) enables communication between the system and MC
 
 
 When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool.
 When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool.
 
 
-(No MCP servers currently connected)
+
 ## Creating an MCP Server
 ## Creating an MCP Server
 
 
 The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this:
 The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this:

+ 1 - 1
src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap

@@ -519,7 +519,7 @@ The Model Context Protocol (MCP) enables communication between the system and MC
 
 
 When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool.
 When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool.
 
 
-(No MCP servers currently connected)
+
 ## Creating an MCP Server
 ## Creating an MCP Server
 
 
 The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this:
 The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this:

+ 4 - 4
src/core/prompts/__tests__/add-custom-instructions.spec.ts

@@ -168,9 +168,9 @@ const mockContext = {
 } as unknown as vscode.ExtensionContext
 } as unknown as vscode.ExtensionContext
 
 
 // Instead of extending McpHub, create a mock that implements just what we need
 // Instead of extending McpHub, create a mock that implements just what we need
-const createMockMcpHub = (): McpHub =>
+const createMockMcpHub = (withServers: boolean = false): McpHub =>
 	({
 	({
-		getServers: () => [],
+		getServers: () => (withServers ? [{ name: "test-server", disabled: false }] : []),
 		getMcpServersPath: async () => "/mock/mcp/path",
 		getMcpServersPath: async () => "/mock/mcp/path",
 		getMcpSettingsFilePath: async () => "/mock/settings/path",
 		getMcpSettingsFilePath: async () => "/mock/settings/path",
 		dispose: async () => {},
 		dispose: async () => {},
@@ -236,7 +236,7 @@ describe("addCustomInstructions", () => {
 	})
 	})
 
 
 	it("should include MCP server creation info when enabled", async () => {
 	it("should include MCP server creation info when enabled", async () => {
-		const mockMcpHub = createMockMcpHub()
+		const mockMcpHub = createMockMcpHub(true)
 
 
 		const prompt = await SYSTEM_PROMPT(
 		const prompt = await SYSTEM_PROMPT(
 			mockContext,
 			mockContext,
@@ -262,7 +262,7 @@ describe("addCustomInstructions", () => {
 	})
 	})
 
 
 	it("should exclude MCP server creation info when disabled", async () => {
 	it("should exclude MCP server creation info when disabled", async () => {
-		const mockMcpHub = createMockMcpHub()
+		const mockMcpHub = createMockMcpHub(false)
 
 
 		const prompt = await SYSTEM_PROMPT(
 		const prompt = await SYSTEM_PROMPT(
 			mockContext,
 			mockContext,

+ 3 - 3
src/core/prompts/__tests__/system-prompt.spec.ts

@@ -168,9 +168,9 @@ const mockContext = {
 } as unknown as vscode.ExtensionContext
 } as unknown as vscode.ExtensionContext
 
 
 // Instead of extending McpHub, create a mock that implements just what we need
 // Instead of extending McpHub, create a mock that implements just what we need
-const createMockMcpHub = (): McpHub =>
+const createMockMcpHub = (withServers: boolean = false): McpHub =>
 	({
 	({
-		getServers: () => [],
+		getServers: () => (withServers ? [{ name: "test-server", disabled: false }] : []),
 		getMcpServersPath: async () => "/mock/mcp/path",
 		getMcpServersPath: async () => "/mock/mcp/path",
 		getMcpSettingsFilePath: async () => "/mock/settings/path",
 		getMcpSettingsFilePath: async () => "/mock/settings/path",
 		dispose: async () => {},
 		dispose: async () => {},
@@ -250,7 +250,7 @@ describe("SYSTEM_PROMPT", () => {
 	})
 	})
 
 
 	it("should include MCP server info when mcpHub is provided", async () => {
 	it("should include MCP server info when mcpHub is provided", async () => {
-		mockMcpHub = createMockMcpHub()
+		mockMcpHub = createMockMcpHub(true)
 
 
 		const prompt = await SYSTEM_PROMPT(
 		const prompt = await SYSTEM_PROMPT(
 			mockContext,
 			mockContext,

+ 8 - 3
src/core/prompts/system.ts

@@ -71,9 +71,14 @@ async function generatePrompt(
 	const modeConfig = getModeBySlug(mode, customModeConfigs) || modes.find((m) => m.slug === mode) || modes[0]
 	const modeConfig = getModeBySlug(mode, customModeConfigs) || modes.find((m) => m.slug === mode) || modes[0]
 	const { roleDefinition, baseInstructions } = getModeSelection(mode, promptComponent, customModeConfigs)
 	const { roleDefinition, baseInstructions } = getModeSelection(mode, promptComponent, customModeConfigs)
 
 
+	// Check if MCP functionality should be included
+	const hasMcpGroup = modeConfig.groups.some((groupEntry) => getGroupName(groupEntry) === "mcp")
+	const hasMcpServers = mcpHub && mcpHub.getServers().length > 0
+	const shouldIncludeMcp = hasMcpGroup && hasMcpServers
+
 	const [modesSection, mcpServersSection] = await Promise.all([
 	const [modesSection, mcpServersSection] = await Promise.all([
 		getModesSection(context),
 		getModesSection(context),
-		modeConfig.groups.some((groupEntry) => getGroupName(groupEntry) === "mcp")
+		shouldIncludeMcp
 			? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation)
 			? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation)
 			: Promise.resolve(""),
 			: Promise.resolve(""),
 	])
 	])
@@ -93,7 +98,7 @@ ${getToolDescriptionsForMode(
 	codeIndexManager,
 	codeIndexManager,
 	effectiveDiffStrategy,
 	effectiveDiffStrategy,
 	browserViewportSize,
 	browserViewportSize,
-	mcpHub,
+	shouldIncludeMcp ? mcpHub : undefined,
 	customModeConfigs,
 	customModeConfigs,
 	experiments,
 	experiments,
 	partialReadsEnabled,
 	partialReadsEnabled,
@@ -104,7 +109,7 @@ ${getToolUseGuidelinesSection(codeIndexManager)}
 
 
 ${mcpServersSection}
 ${mcpServersSection}
 
 
-${getCapabilitiesSection(cwd, supportsComputerUse, mcpHub, effectiveDiffStrategy, codeIndexManager)}
+${getCapabilitiesSection(cwd, supportsComputerUse, shouldIncludeMcp ? mcpHub : undefined, effectiveDiffStrategy, codeIndexManager)}
 
 
 ${modesSection}
 ${modesSection}
 
 

+ 0 - 1
src/services/mcp/__tests__/McpHub.spec.ts

@@ -93,7 +93,6 @@ describe("McpHub", () => {
 		// Mock console.error to suppress error messages during tests
 		// Mock console.error to suppress error messages during tests
 		console.error = vi.fn()
 		console.error = vi.fn()
 
 
-
 		const mockUri: Uri = {
 		const mockUri: Uri = {
 			scheme: "file",
 			scheme: "file",
 			authority: "",
 			authority: "",