diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index 3f38789fdc..8c0dc7acc2 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -18,23 +18,23 @@ export const formatResponse = { rooIgnoreError: (path: string) => `Access to ${path} is blocked by the .rooignore file settings. You must try to continue in the task without using this file, or ask the user to update the .rooignore file.`, - noToolsUsed: () => + noToolsUsed: (hasMcpTools?: boolean) => `[ERROR] You did not use a tool in your previous response! Please retry with a tool use. -${toolUseInstructionsReminder} +${getToolUseInstructionsReminder(hasMcpTools)} # Next Steps -If you have completed the user's task, use the attempt_completion tool. -If you require additional information from the user, use the ask_followup_question tool. -Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task. +If you have completed the user's task, use the attempt_completion tool. +If you require additional information from the user, use the ask_followup_question tool. +Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task. (This is an automated message, so do not respond to it conversationally.)`, tooManyMistakes: (feedback?: string) => `You seem to be having trouble proceeding. The user has provided the following feedback to help guide you:\n\n${feedback}\n`, - missingToolParameterError: (paramName: string) => - `Missing value for required parameter '${paramName}'. Please retry with complete response.\n\n${toolUseInstructionsReminder}`, + missingToolParameterError: (paramName: string, hasMcpTools?: boolean) => + `Missing value for required parameter '${paramName}'. Please retry with complete response.\n\n${getToolUseInstructionsReminder(hasMcpTools)}`, lineCountTruncationError: (actualLineCount: number, isNewFile: boolean, diffStrategyEnabled: boolean = false) => { const truncationMessage = `Note: Your response may have been truncated because it exceeded your output limit. You wrote ${actualLineCount} lines of content, but the line_count parameter was either missing or not included in your response.` @@ -66,7 +66,7 @@ Otherwise, if you have not completed the task and do not need additional informa `RECOMMENDED APPROACH:\n` + `${existingFileApproaches.join("\n")}\n` - return `${isNewFile ? newFileGuidance : existingFileGuidance}\n${toolUseInstructionsReminder}` + return `${isNewFile ? newFileGuidance : existingFileGuidance}\n${getToolUseInstructionsReminder()}` }, invalidMcpToolArgumentError: (serverName: string, toolName: string) => @@ -190,7 +190,34 @@ const formatImagesIntoBlocks = (images?: string[]): Anthropic.ImageBlockParam[] : [] } -const toolUseInstructionsReminder = `# Reminder: Instructions for Tool Use +const getToolUseInstructionsReminder = (hasMcpTools?: boolean) => { + if (hasMcpTools) { + return `# Reminder: Instructions for MCP Tool Use + +MCP tools must be called using the use_mcp_tool format: + + +server name here +tool name here + +{ + "param1": "value1", + "param2": "value2" +} + + + +For regular tools, use the standard XML format: + + +value1 +value2 +... + + +Always use the correct format for the type of tool you are calling.` + } else { + return `# Reminder: Instructions for Tool Use Tool uses are formatted using XML-style tags. The tool name itself becomes the XML tag name. Each parameter is enclosed within its own set of tags. Here's the structure: @@ -209,3 +236,8 @@ I have completed the task... Always use the actual tool name as the XML tag name for proper parsing and execution.` + } +} + +// Legacy constant for backward compatibility +const toolUseInstructionsReminder = getToolUseInstructionsReminder() diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index a6a9d89986..232ee8900f 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -709,7 +709,8 @@ export class Task extends EventEmitter { relPath ? ` for '${relPath.toPosix()}'` : "" } without value for required parameter '${paramName}'. Retrying...`, ) - return formatResponse.toolError(formatResponse.missingToolParameterError(paramName)) + const hasMcpTools = await this.hasMcpToolsAvailable() + return formatResponse.toolError(formatResponse.missingToolParameterError(paramName, hasMcpTools)) } // Start / Abort / Resume @@ -1128,7 +1129,8 @@ export class Task extends EventEmitter { // the user hits max requests and denies resetting the count. break } else { - nextUserContent = [{ type: "text", text: formatResponse.noToolsUsed() }] + const hasMcpTools = await this.hasMcpToolsAvailable() + nextUserContent = [{ type: "text", text: formatResponse.noToolsUsed(hasMcpTools) }] this.consecutiveMistakeCount++ } } @@ -1517,7 +1519,8 @@ export class Task extends EventEmitter { const didToolUse = this.assistantMessageContent.some((block) => block.type === "tool_use") if (!didToolUse) { - this.userMessageContent.push({ type: "text", text: formatResponse.noToolsUsed() }) + const hasMcpTools = await this.hasMcpToolsAvailable() + this.userMessageContent.push({ type: "text", text: formatResponse.noToolsUsed(hasMcpTools) }) this.consecutiveMistakeCount++ } @@ -1622,6 +1625,32 @@ export class Task extends EventEmitter { })() } + private async hasMcpToolsAvailable(): Promise { + try { + const { mcpEnabled } = (await this.providerRef.deref()?.getState()) ?? {} + if (!(mcpEnabled ?? true)) { + return false + } + + const provider = this.providerRef.deref() + if (!provider) { + return false + } + + const mcpHub = await McpServerManager.getInstance(provider.context, provider) + if (!mcpHub) { + return false + } + + // Check if there are any connected MCP servers with tools + const servers = mcpHub.getServers() + return servers.some((server) => server.tools && server.tools.length > 0) + } catch (error) { + console.error("Error checking MCP tools availability:", error) + return false + } + } + public async *attemptApiRequest(retryAttempt: number = 0): ApiStream { const state = await this.providerRef.deref()?.getState() const {