{"record":{"id":"c9b5a8631fc71677","repo":"mastra-ai/mastra","slug":"mcp-server-tool-execute-preparation-failed","errorCode":"MCP_SERVER_TOOL_EXECUTE_PREPARATION_FAILED","errorMessage":"Unknown tool: ${toolId}","messagePattern":"Unknown tool: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/server/server.ts","lineNumber":2946,"sourceCode":"   * const result = await server.executeTool(\n   *   'getWeather',\n   *   { location: 'London' },\n   *   { toolCallId: 'call_123' }\n   * );\n   * console.log(result);\n   * ```\n   */\n  public async executeTool(\n    toolId: string,\n    args: any,\n    executionContext?: { messages?: any[]; toolCallId?: string; requestContext?: RequestContext },\n  ): Promise<any> {\n    const tool = this.convertedTools[toolId];\n    let validatedArgs = args;\n    try {\n      if (!tool) {\n        this.logger.warn('Unknown tool requested', { tool: toolId, server: this.name });\n        throw new Error(`Unknown tool: ${toolId}`);\n      }\n\n      this.logger.debug('Invoking tool', { tool: toolId, args });\n\n      const paramsSchema = tool.parameters as {\n        validate?: (value: unknown) => any;\n        safeParse?: (value: unknown) => any;\n      };\n\n      const validation =\n        typeof paramsSchema?.validate === 'function'\n          ? paramsSchema.validate(args ?? {})\n          : typeof paramsSchema?.safeParse === 'function'\n            ? paramsSchema.safeParse(args ?? {})\n            : null;\n\n      if (validation) {\n        const success = typeof validation.success === 'boolean' ? validation.success : !validation.issues?.length;","sourceCodeStart":2928,"sourceCodeEnd":2964,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/server/server.ts#L2928-L2964","documentation":"MCPServer.executeTool() looks the tool up in this.convertedTools; if the toolId is not registered on this server it logs a warning and throws `Unknown tool: ${toolId}` (surfaced under code MCP_SERVER_TOOL_EXECUTE_PREPARATION_FAILED). This happens before any argument validation or execution, so the args are irrelevant — the tool name itself doesn't exist on this server instance.","triggerScenarios":"Calling executeTool with a tool name that was never registered in the server's `tools` option; a typo or casing mismatch in the toolId; calling the tool on the wrong MCPServer instance; a tool registered after the server converted its tool list (stale convertedTools snapshot); an MCP client requesting a tool name from a different server's tool list.","commonSituations":"Renaming a tool and forgetting to update calling code; configuring multiple MCP servers and pointing the request at the wrong one; dynamically added tools that require server recreation; LLM hallucinating a tool name from a stale tools/list response; listing tools from a registry while executing against a different server.","solutions":["Print Object.keys(server.getTools()) (or the server's convertedTools) and confirm the exact toolId spelling.","Register the tool in the MCPServer `tools` option or recreate/restart the server so convertedTools includes it.","Verify you are calling executeTool on the MCPServer instance that actually defines the tool.","Check for casing/whitespace differences in the toolId.","If tools are added dynamically, re-create the server instance or re-run tool conversion so the registry is current."],"exampleFix":"// before\nawait server.executeTool('getWeahter', { location: 'London' });\n// after\nconst toolId = 'getWeather';\nif (!(toolId in server.getTools())) throw new Error(`Tool ${toolId} not registered`);\nawait server.executeTool(toolId, { location: 'London' });","handlingStrategy":"validation","validationCode":"const tools = server.getTools?.() ?? {};\nif (!(toolId in tools)) {\n  throw new Error(`Tool '${toolId}' is not registered on MCP server; available: ${Object.keys(tools).join(', ')}`);\n}","typeGuard":"function isKnownTool(server: MCPServer, toolId: string): boolean {\n  return Object.prototype.hasOwnProperty.call(server.getTools?.() ?? {}, toolId);\n}","tryCatchPattern":"try {\n  return await server.executeTool(toolId, args, ctx);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Unknown tool:')) {\n    logger.warn(`Tool ${toolId} missing on server ${server.name}; available: ${Object.keys(server.getTools()).join(',')}`);\n    return { error: 'TOOL_NOT_FOUND' };\n  }\n  throw e;\n}","preventionTips":["Derive tool IDs dynamically from server.getTools() / tools/list instead of hardcoding strings.","List tools via tools/list (or getTools) and surface the catalog to the LLM so it can't hallucinate names.","After renaming or adding tools, recreate/restart the MCPServer so convertedTools is refreshed.","Confirm the target MCPServer instance is the one that registers the tool when multiple servers exist.","Validate toolId casing/whitespace in shared constants rather than ad-hoc literals."],"tags":["mcp","tools","unknown-tool","invalid-params"],"backgroundTag":"unknown-tool","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}