{"record":{"id":"271bd414735c17e7","repo":"CherryHQ/cherry-studio","slug":"methodnotfound-271bd4","errorCode":"MethodNotFound","errorMessage":"Tool ${name} not found","messagePattern":"Tool (.+?) not found","errorType":"exception","errorClass":"McpError","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/servers/python.ts","lineNumber":86,"sourceCode":"                timeout: {\n                  type: 'number',\n                  description: 'Timeout in milliseconds (default: 60000)',\n                  default: 60000\n                }\n              },\n              required: ['code']\n            }\n          }\n        ]\n      }\n    })\n\n    // Handle tool calls\n    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n      const { name, arguments: args } = request.params\n\n      if (name !== 'python_execute') {\n        throw new McpError(ErrorCode.MethodNotFound, `Tool ${name} not found`)\n      }\n\n      try {\n        const parsed = PythonExecuteArgsSchema.safeParse(args)\n        if (!parsed.success) {\n          throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for python_execute: ${parsed.error.message}`)\n        }\n\n        const { code, context } = parsed.data\n        // Clamp timeout to a sane range to prevent runaway or pointless executions.\n        const timeout = Math.min(Math.max(parsed.data.timeout, MIN_TIMEOUT_MS), MAX_TIMEOUT_MS)\n\n        logger.debug('Executing Python code via Pyodide')\n\n        const result = await application.get('PythonService').executeScript(code, context, timeout)\n\n        return {\n          content: [","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/python.ts#L68-L104","documentation":"The python MCP server only registers one tool, `python_execute`. The CallTool handler explicitly checks `if (name !== 'python_execute')` and throws McpError MethodNotFound for anything else. Unlike the memory server there is no switch; it is a single-tool server.","triggerScenarios":"Calling any tool name other than `python_execute` against this server — a typo, a deprecated name, or a call routed to the wrong server.","commonSituations":"Client/server version skew; a caller assumes the server exposes `run`, `exec`, or `eval`; the model hallucinates a tool name.","solutions":["Call `tools/list` and confirm only `python_execute` is exposed before invoking.","Verify the call is routed to the python server, not another MCP server.","Fix typos in the tool name at the call site."],"exampleFix":"// before\n{ name: \"python_run\" }\n// after\n{ name: \"python_execute\" }","handlingStrategy":"validation","validationCode":"const PYTHON_TOOL_NAME = 'python_execute'\nfunction assertPythonTool(name: string) {\n  if (name !== PYTHON_TOOL_NAME) {\n    throw new Error(`Unknown python tool: ${name}. Only 'python_execute' is supported.`)\n  }\n}","typeGuard":"const isPythonTool = (name: string): boolean => name === 'python_execute'","tryCatchPattern":"try {\n  assertPythonTool(name)\n  await client.callTool({ name, arguments })\n} catch (e) {\n  if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {\n    // this server is single-tool; refresh tools/list and confirm routing\n  }\n  throw e\n}","preventionTips":["This is a single-tool server — only `python_execute` exists; do not invent names.","Confirm the request is routed to the python server, not another MCP server.","Discover tools via `tools/list` once and cache the result."],"tags":["mcp","method-not-found","python-server","routing"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}