Summary
Every MCP tool call fails with:
_ainl_unavailable_payload() takes 0 positional arguments but 2 were given
This affects all memory_*, ainl_*, and a2a_* tools — the entire MCP surface is non-functional. Hooks and direct DB writes are unaffected (they bypass the tool dispatcher), so the graph memory DB keeps updating and the breakage is easy to miss until you actually invoke a tool.
Root cause
In mcp_server/server.py, the @server.call_tool() decorator is attached to the wrong function. It sits on the 0-argument helper _ainl_unavailable_payload() (~line 833) instead of the real async dispatcher call_tool(name, arguments) (~line 843):
@server.call_tool() # ❌ registers the 0-arg helper as THE handler
def _ainl_unavailable_payload() -> Dict[str, Any]:
return { "ok": False, "error": "AINL tools not available...", ... }
async def call_tool(name: str, arguments: dict) -> list[TextContent]: # ❌ never registered
...
The MCP SDK therefore registers _ainl_unavailable_payload as the call-tool handler and invokes it with (name, arguments) for every call → TypeError. The actual dispatcher call_tool is never wired up.
Introduced in commit 068521a; present on main (a6052b0).
Fix
Move the decorator off the helper and onto the dispatcher:
-@server.call_tool()
def _ainl_unavailable_payload() -> Dict[str, Any]:
return { "ok": False, "error": "AINL tools not available...", ... }
+@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""Handle tool calls"""
_ainl_unavailable_payload is still called internally with 0 args (e.g. the ainl_* branches when ainl_tools is unavailable), so it stays a plain helper.
Verified
py_compile clean.
- Imported the patched module in a separate process and called
call_tool("memory_store_semantic", {...}) → returned a node_id (success, no TypeError).
Operational note for the fix
/reload-plugins does not restart an already-running MCP server subprocess, so the patch won't take effect until the existing mcp_server.server process is killed (or Claude Code is fully restarted). After killing the stale process, a /reload-plugins spawns a fresh server with the fix.
Summary
Every MCP tool call fails with:
This affects all
memory_*,ainl_*, anda2a_*tools — the entire MCP surface is non-functional. Hooks and direct DB writes are unaffected (they bypass the tool dispatcher), so the graph memory DB keeps updating and the breakage is easy to miss until you actually invoke a tool.Root cause
In
mcp_server/server.py, the@server.call_tool()decorator is attached to the wrong function. It sits on the 0-argument helper_ainl_unavailable_payload()(~line 833) instead of the real async dispatchercall_tool(name, arguments)(~line 843):The MCP SDK therefore registers
_ainl_unavailable_payloadas the call-tool handler and invokes it with(name, arguments)for every call →TypeError. The actual dispatchercall_toolis never wired up.Introduced in commit
068521a; present onmain(a6052b0).Fix
Move the decorator off the helper and onto the dispatcher:
_ainl_unavailable_payloadis still called internally with 0 args (e.g. theainl_*branches whenainl_toolsis unavailable), so it stays a plain helper.Verified
py_compileclean.call_tool("memory_store_semantic", {...})→ returned anode_id(success, no TypeError).Operational note for the fix
/reload-pluginsdoes not restart an already-running MCP server subprocess, so the patch won't take effect until the existingmcp_server.serverprocess is killed (or Claude Code is fully restarted). After killing the stale process, a/reload-pluginsspawns a fresh server with the fix.