thedotmack/claude-mem · error
Unknown tool: ${request.params.name}
Error message
Unknown tool: ${request.params.name} What it means
Thrown by the CallToolRequest handler when no entry in the tools array matches request.params.name. The MCP server advertises a fixed tool list in ListTools; if a client calls a name not in that list, the lookup finds undefined and this Error is thrown before any handler runs.
Source
Thrown at src/servers/mcp-server.ts:913
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
const advertisedTools = getAdvertisedMcpToolsForRuntime(tools, selectRuntime());
return {
tools: advertisedTools.map(tool => ({
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema
}))
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const tool = tools.find(t => t.name === request.params.name);
if (!tool) {
throw new Error(`Unknown tool: ${request.params.name}`);
}
try {
return await tool.handler(request.params.arguments || {});
} catch (error: unknown) {
logger.error('SYSTEM', 'Tool execution failed', { tool: request.params.name }, error instanceof Error ? error : new Error(String(error)));
return {
content: [{
type: 'text' as const,
text: `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
const HEARTBEAT_INTERVAL_MS = 30_000;
let heartbeatTimer: ReturnType<typeof setInterval> | null = null;View on GitHub (pinned to d768ba3643)
Solutions
- Re-list tools via tools/list and call only names that appear in the current response.
- Upgrade (or downgrade) the client and server to matching versions so advertised names align.
- Check the exact spelling and casing against the tools array in src/servers/mcp-server.ts.
Example fix
// before — client calls a non-existent tool
{ "method": "tools/call", "params": { "name": "remember", "arguments": {} } }
// throws 'Unknown tool: remember'
// after — use a name from tools/list
{ "method": "tools/call", "params": { "name": "observation_add", "arguments": { "content": "..." } } } Defensive patterns
Strategy: validation
Validate before calling
// Before calling tools/call, confirm the name was advertised by tools/list.
const advertised = (await client.listTools()).tools.map(t => t.name);
if (!advertised.includes(requestedName)) {
throw new Error(`Tool '${requestedName}' not advertised; available: ${advertised.join(', ')}`);
} Type guard
function isAdvertisedTool(name: string, advertised: string[]): boolean {
return advertised.includes(name);
} Try / catch
try {
await server.request({ method: 'tools/call', params: { name, arguments } });
} catch (e) {
if (e instanceof Error && /Unknown tool/.test(e.message)) {
// refresh the tool list and retry only if the name now exists
await client.refreshTools();
} else throw e;
} Prevention
- Re-discover tools via tools/list after every server upgrade; do not cache the list across versions.
- Match exact spelling and casing against the advertised names.
- Have clients surface 'Unknown tool' by refreshing the tool list rather than retrying blindly.
When it happens
Trigger: An MCP client sends tools/call with a name that is misspelled, removed in this version, or fabricated (e.g. 'memorize', 'remember'). Also when a client caches an older tool list after an upgrade that renamed/removed tools.
Common situations: Version skew: client discovered tools on an older server and calls a now-removed tool; typo in a hand-written JSON-RPC call; tool name was renamed (e.g. observation_add vs add_observation) and the caller uses the old spelling.
Related errors
- plugin/.mcp.json mcp-search launcher must include Codex cach
- plugin/.mcp.json mcp-search launcher must include Claude cac
- "${key}" is required
- Unknown tool: ${name}
- API key is scoped to a different project
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/a55496b07a61a089.
Report an issue: GitHub.