rohitg00/agentmemory · error · Error

Unknown tool: ${toolName}

Error message

Unknown tool: ${toolName}

What it means

The standalone MCP server validates incoming tool calls against the IMPLEMENTED_TOOLS set before argument parsing. A tool name outside that set throws this error, distinguishing unimplemented/typo'd tool names from per-tool argument errors.

Source

Thrown at src/mcp/standalone.ts:120

interface Validated {
  tool: string;
  content?: string;
  type?: string;
  concepts?: string[];
  files?: string[];
  project?: string;
  agentId?: string;
  query?: string;
  limit?: number;
  format?: string;
  tokenBudget?: number;
  memoryIds?: string[];
  reason?: string;
}

function validate(toolName: string, args: Record<string, unknown>): Validated {
  if (!IMPLEMENTED_TOOLS.has(toolName)) {
    throw new Error(`Unknown tool: ${toolName}`);
  }
  const v: Validated = { tool: toolName };
  switch (toolName) {
    case "memory_save": {
      const content = args["content"];
      if (typeof content !== "string" || !content.trim()) {
        throw new Error("content is required");
      }
      v.content = content;
      v.type = (args["type"] as string) || "fact";
      v.concepts = normalizeList(args["concepts"]);
      v.files = normalizeList(args["files"]);
      // The tool schema exposes project (and now agentId); dropping them
      // here silently broke project/agent scoping through the stdio
      // package specifically.
      if (typeof args["project"] === "string" && args["project"].trim()) {
        v.project = args["project"].trim();
      }

View on GitHub (pinned to e04ba88819)

Solutions

  1. Check the exact tool name against the tools advertised by the server (list tools via the MCP client).
  2. Set AGENTMEMORY_TOOLS=all on the server if the tool exists but is hidden by the default subset.
  3. Upgrade the standalone server / plugin to matching versions.
  4. Fix typos in hand-written calls; use snake_case names like memory_save.

Example fix

// before
await callTool("memory_search_all", { query: "x" }); // unknown
// after
await callTool("memory_smart_search", { query: "x" });
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = new Set(["memory_save", "memory_search", "memory_recall", "memory_smart_search", "memory_sessions", "memory_governance_delete", "memory_export", "memory_audit"]);
if (!KNOWN.has(toolName)) throw new Error(`refusing to call unknown tool: ${toolName}`);

Type guard

function isKnownTool(name: string): name is KnownTool {
  return KNOWN_TOOLS.includes(name as KnownTool);
}

Try / catch

try {
  return await callTool(toolName, args);
} catch (e) {
  if (String(e.message).startsWith("Unknown tool:")) {
    const tools = await listServerTools(); // resync client list
    throw new Error(`${toolName} not available; server offers: ${tools.join(", ")}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: An MCP client invoking a tool whose name is not in IMPLEMENTED_TOOLS — a typo (e.g. memory_serch), a tool from a newer/older plugin version than the running standalone server, or AGENTMEMORY_TOOLS visibility filtering excluding the tool the client believes exists.

Common situations: Plugin config listing tools the standalone build doesn't implement, stale cached tool lists in the MCP client after an upgrade, hand-written tool-call scripts with wrong names, default visible-tool subset (8 tools) hiding tools behind AGENTMEMORY_TOOLS=all.

Related errors


AI-assisted analysis of rohitg00/agentmemory@e04ba88819 (2026-08-30). Data as JSON: /api/errors/54e30e865f35dfd5. Report an issue: GitHub.