CherryHQ/cherry-studio · error · Error
Unknown tool: ${name}
Error message
Unknown tool: ${name} What it means
Default branch of the filesystem server's tool dispatch switch. Reached when request.params.name is not glob/ls/grep/read/edit/write/delete. Unlike the fetch server, the handler is wrapped in try/catch (server.ts:80-117) so this throw is converted into an isError tool result, not a transport error. It signals that the client called a tool the server never advertised in ListTools.
Source
Thrown at src/main/ai/mcp/servers/filesystem/server.ts:107
return await handleLsTool(args, this.baseDir)
case 'grep':
return await handleGrepTool(args, this.baseDir)
case 'read':
return await handleReadTool(args, this.baseDir)
case 'edit':
return await handleEditTool(args, this.baseDir)
case 'write':
return await handleWriteTool(args, this.baseDir)
case 'delete':
return await handleDeleteTool(args, this.baseDir)
default:
throw new Error(`Unknown tool: ${name}`)
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
logger.error(`Tool execution error for ${request.params.name}:`, { error })
return {
content: [{ type: 'text', text: `Error: ${errorMessage}` }],
isError: true
}
}
})
}
}
export default FileSystemServer
View on GitHub (pinned to 726446b54c)
Solutions
- Verify the called name is exactly one of: glob, ls, grep, read, edit, write, delete (lowercase, no prefix).
- Have the client re-fetch the tool list via ListTools before dispatching, rather than trusting a stale cache.
- When adding/removing tools, keep the ListTools array (server.ts:65-77) and the switch cases in lockstep.
Example fix
// before
default:
throw new Error(`Unknown tool: ${name}`)
// after — record the miss so version skew is diagnosable
const KNOWN = ['glob','ls','grep','read','edit','write','delete']
default:
logger.warn('Unknown tool called', { name, known: KNOWN })
throw new Error(`Unknown tool: ${name}. Available: ${KNOWN.join(', ')}`) Defensive patterns
Strategy: validation
Validate before calling
// Validate the tool name against the registered filesystem tools.
const FS_TOOLS = new Set(['glob', 'ls', 'grep', 'read', 'edit', 'write', 'delete'])
function isFsTool(name: unknown): name is string {
return typeof name === 'string' && FS_TOOLS.has(name)
} Type guard
function isKnownFsTool(name: string): boolean {
return ['glob', 'ls', 'grep', 'read', 'edit', 'write', 'delete'].includes(name)
} Prevention
- Refresh the client's tool list via ListTools before dispatching.
- Keep the ListTools array and the switch cases in server.ts in lockstep when adding/removing tools.
- Bump the server version when the tool set changes so clients can detect drift.
- Log unknown-tool calls so version skew between client and server is visible.
When it happens
Trigger: An MCP client sends a CallToolRequest with a name outside the seven registered tools — a typo, a future/legacy tool name, or a name belonging to a different MCP server the client is confusing this with.
Common situations: Client built against an older or newer server version that had a different tool set; a model inventing a tool name like 'move' or 'copy' that was never implemented; orchestrator routing a request to the wrong server.
Related errors
- Tool not found
- Invalid arguments for delete: ${parsed.error}
- Path not found: ${targetPath}
- Directory not empty: ${targetPath}. Use recursive=true to de
- Invalid arguments for edit: ${parsed.error}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/a0195ae986de1d70.
Report an issue: GitHub.