-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: validate MCP tool exists before execution #7632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
3a30a21
326268a
854d101
97945bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,6 +81,81 @@ async function validateParams( | |
| } | ||
| } | ||
|
|
||
| async function validateToolExists( | ||
| cline: Task, | ||
| serverName: string, | ||
| toolName: string, | ||
| pushToolResult: PushToolResult, | ||
| ): Promise<{ isValid: boolean; availableTools?: string[] }> { | ||
| try { | ||
| // Get the MCP hub to access server information | ||
| const provider = cline.providerRef.deref() | ||
| const mcpHub = provider?.getMcpHub() | ||
|
|
||
| if (!mcpHub) { | ||
| // If we can't get the MCP hub, we can't validate, so proceed with caution | ||
| return { isValid: true } | ||
| } | ||
|
|
||
| // Get all servers to find the specific one | ||
| const servers = mcpHub.getAllServers() | ||
| const server = servers.find((s) => s.name === serverName) | ||
|
|
||
| if (!server) { | ||
| // Server not found - this will be caught later in the flow | ||
| return { isValid: true } | ||
|
||
| } | ||
|
|
||
| // Check if the server has tools defined | ||
| if (!server.tools || server.tools.length === 0) { | ||
| // No tools available on this server | ||
| cline.consecutiveMistakeCount++ | ||
| cline.recordToolError("use_mcp_tool") | ||
| await cline.say( | ||
| "error", | ||
| t("mcp:errors.toolNotFound", { | ||
| toolName, | ||
| serverName, | ||
| availableTools: "No tools available", | ||
| }), | ||
| ) | ||
|
|
||
| pushToolResult(formatResponse.unknownMcpToolError(serverName, toolName, [])) | ||
| return { isValid: false, availableTools: [] } | ||
| } | ||
|
|
||
| // Check if the requested tool exists | ||
| const toolExists = server.tools.some((tool) => tool.name === toolName) | ||
|
|
||
| if (!toolExists) { | ||
| // Tool not found - provide list of available tools | ||
| const availableToolNames = server.tools.map((tool) => tool.name) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this take into account tools that the user has disabled?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After the bug fix release, I see that disabled tools are being ignored, and the prompt mentions all tools, including the disabled ones. I have additionally checked the system prompt, and everything is correct there - disabled tools are not included in the description. |
||
|
|
||
| cline.consecutiveMistakeCount++ | ||
| cline.recordToolError("use_mcp_tool") | ||
| await cline.say( | ||
| "error", | ||
| t("mcp:errors.toolNotFound", { | ||
| toolName, | ||
| serverName, | ||
| availableTools: availableToolNames.join(", "), | ||
| }), | ||
| ) | ||
|
|
||
| pushToolResult(formatResponse.unknownMcpToolError(serverName, toolName, availableToolNames)) | ||
| return { isValid: false, availableTools: availableToolNames } | ||
| } | ||
|
|
||
| // Tool exists | ||
| return { isValid: true, availableTools: server.tools.map((tool) => tool.name) } | ||
| } catch (error) { | ||
| // If there's an error during validation, log it but don't block the tool execution | ||
| // The actual tool call might still fail with a proper error | ||
| console.error("Error validating MCP tool existence:", error) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider surfacing validation errors to users for better debugging visibility. The error is only logged to console which might make troubleshooting harder. |
||
| return { isValid: true } | ||
| } | ||
| } | ||
|
|
||
| async function sendExecutionStatus(cline: Task, status: McpExecutionStatus): Promise<void> { | ||
| const clineProvider = await cline.providerRef.deref() | ||
| clineProvider?.postMessageToWebview({ | ||
|
|
@@ -193,6 +268,12 @@ export async function useMcpToolTool( | |
|
|
||
| const { serverName, toolName, parsedArguments } = validation | ||
|
|
||
| // Validate that the tool exists on the server | ||
| const toolValidation = await validateToolExists(cline, serverName, toolName, pushToolResult) | ||
| if (!toolValidation.isValid) { | ||
| return | ||
| } | ||
|
|
||
| // Reset mistake count on successful validation | ||
| cline.consecutiveMistakeCount = 0 | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a test case for when the MCP hub itself is unavailable to ensure the fallback behavior works correctly.