thedotmack/claude-mem · error

Unknown tool

Error message

Unknown tool: ${name}

What it means

dispatchToolCall() resolves the requested tool name to a handler; if the name does not match any registered tool, it throws `Unknown tool: <name>`. This signals the MCP server received a call for a tool it does not expose.

Solutions

  1. Check the server's tool list (tools/list) and use an exact registered tool name
  2. Fix typos and case in the tool name on the client
  3. Restart/refresh the client so it re-fetches the current tool registry
  4. Verify the client is connected to the recall MCP server that actually exposes the tool

Example fix

// before
await client.callTool('recent_observations', args);
// after (registered name is 'observations')
await client.callTool('observations', args);
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_TOOLS = ['observations', 'recent'];
if (!KNOWN_TOOLS.includes(toolName)) {
  throw new Error(`Unknown tool: ${toolName}`);
}

Try / catch

try {
  const result = await dispatchToolCall(name, args);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unknown tool:')) {
    // refresh tool registry and/or fall back to tools/list to find the right name
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the MCP server with a tool name not in its registry — typos, renamed tools, or tools from a different MCP server.

Common situations: Client tool list cached from an older server version after a rename; hard-coded tool names in scripts; pointing a client at the wrong MCP server that lacks the tool; case-sensitivity mismatches.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/fff104eb67d7d28e. Report an issue: GitHub.

Appendix: source

Thrown at src/server/mcp/recall-mcp-server.ts:133

    const observations = await backend.context({
      projectId: requireString(args, 'projectId'),
      query: requireString(args, 'query'),
      limit: clampLimit(args.limit, CONTEXT_LIMIT),
    });
    const context = observations
      .map((o) => (o as { content?: unknown }).content)
      .filter((t): t is string => typeof t === 'string' && t.length > 0)
      .join('\n\n');
    return jsonResult({ observations, context });
  }
  if (name === 'recent') {
    const observations = await backend.recent({
      projectId: requireString(args, 'projectId'),
      limit: clampLimit(args.limit, RECENT_LIMIT),
    });
    return jsonResult({ observations });
  }
  throw new Error(`Unknown tool: ${name}`);
}

/**
 * Build a read-only recall MCP server bound to `backend`. The caller owns the
 * transport (stdio in the CLI, streamable-HTTP in Server Beta).
 */
export function createRecallMcpServer(backend: RecallBackend, version: string): Server {
  const server = new Server(
    { name: 'claude-mem', version },
    { capabilities: { tools: {} } },
  );

  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));

  server.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {
    const name = request.params.name;
    const args = (request.params.arguments ?? {}) as Record<string, unknown>;
    try {

View on GitHub (pinned to d8bc9755e7)