{"record":{"id":"20028a7023b9d401","repo":"CherryHQ/cherry-studio","slug":"methodnotfound-20028a","errorCode":"MethodNotFound","errorMessage":"Unknown tool: ${toolName}","messagePattern":"Unknown tool: (.+?)","errorType":"exception","errorClass":"McpError","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/servers/skills.ts","lineNumber":94,"sourceCode":"  }\n\n  private setupHandlers() {\n    this.mcpServer.server.setRequestHandler(ListToolsRequestSchema, async () => ({\n      tools: [SEARCH_TOOL, INSTALL_TOOL]\n    }))\n\n    this.mcpServer.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n      const toolName = request.params.name\n      const args = (request.params.arguments ?? {}) as Record<string, string | undefined>\n\n      try {\n        switch (toolName) {\n          case 'search_skills':\n            return await this.searchSkills(args)\n          case 'install_skill':\n            return await this.installSkill(args)\n          default:\n            throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${toolName}`)\n        }\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error)\n        logger.error(`Tool error: ${toolName}`, { agentId: this.agentId, error: message })\n        return {\n          content: [{ type: 'text' as const, text: `Error: ${message}` }],\n          isError: true\n        }\n      }\n    })\n  }\n\n  private async searchSkills(args: Record<string, string | undefined>) {\n    const query = args.query\n    if (!query) throw new McpError(ErrorCode.InvalidParams, \"'query' is required for search_skills\")\n\n    const results = await searchSkillMarketplaces(\n      query.replace(/[-_]+/g, ' ').trim(),","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/skills.ts#L76-L112","documentation":"The skills MCP server's CallTool handler only recognizes `search_skills` and `install_skill`. The `default` branch throws McpError MethodNotFound with the offending name. NOTE: unlike the memory server, this throw is INSIDE a try/catch (line 96) that converts every error — including this McpError — into a tool result `{ content: [{ text: \"Error: ...\" }], isError: true }`. So the client sees an error result, not a protocol-level MethodNotFound response.","triggerScenarios":"Calling any tool name other than `search_skills` or `install_skill` against this server: typos, deprecated names, or a call routed here by mistake.","commonSituations":"Version skew (a tool was renamed/removed); the model hallucinates a tool name (e.g. `list_skills`, `uninstall_skill`); routing mismatch.","solutions":["Call `tools/list` first and use only `search_skills` / `install_skill`.","Check the returned `isError: true` flag and the `Error: ...` text rather than expecting a thrown MethodNotFound.","Fix typos and reconcile client/server versions."],"exampleFix":"// before\n{ name: \"list_skills\" }\n// after\n{ name: \"search_skills\", arguments: { query: \"pdf\" } }","handlingStrategy":"validation","validationCode":"const SKILLS_TOOLS = new Set(['search_skills', 'install_skill'])\nfunction assertSkillsTool(name: string) {\n  if (!SKILLS_TOOLS.has(name)) throw new Error(`Unknown skills tool: ${name}. Only search_skills/install_skill exist.`)\n}","typeGuard":"const isSkillsTool = (name: string): boolean => SKILLS_TOOLS.has(name)","tryCatchPattern":"// This server converts errors to isError results — check the result, not a throw.\nconst result = await client.callTool({ name, arguments })\nif (result.isError) {\n  const text = (result.content[0] as any).text\n  if (/Unknown tool/.test(text)) {/* refresh tools/list, fix the name */}\n}","preventionTips":["Discover tools via `tools/list`; only `search_skills` and `install_skill` exist.","Check `isError` on every skills-server result — its handler swallows throws.","Treat an unknown-tool result as version skew and refresh capabilities."],"tags":["mcp","method-not-found","skills-server","routing","soft-error"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}