Skip to content

MCPServer answers an unknown tool with an isError result; the spec (and the TS SDK) use JSON-RPC -32602 #3659

Description

@ANcpLua

Summary

The spec's error-handling section for tools lists "Unknown tool" under protocol errors, returned as a standard JSON-RPC error with code: -32602. This is in both 2025-11-25 and 2026-07-28: server/tools.mdx in 2026-07-28, around line 742.

MCPServer (mcp 2.3.0) instead returns a successful CallToolResult with is_error=True and the text Unknown tool: <name>. It comes from ToolError in src/mcp/server/mcpserver/tools/tool_manager.py, at lines 72 and 85. The behaviour is described in docs/troubleshooting.md. Meanwhile docs/whats-new.md (the low-level example, note 5) says -32602 "is the spec's own answer for an unknown tool". The TypeScript SDK returns -32602 ("Tool nope not found").

Reproduction

import anyio
from mcp import Client, MCPError
from mcp.server import MCPServer

mcp = MCPServer("demo")

@mcp.tool()
def echo(text: str) -> str:
    """Echo the text."""
    return text

async def main() -> None:
    for mode in ("2026-07-28", "legacy"):
        async with Client(mcp, mode=mode) as client:
            try:
                result = await client.call_tool("does_not_exist", {})
                print(f"{mode}: CallToolResult is_error={result.is_error} text={result.content[0].text!r}")
            except MCPError as e:
                print(f"{mode}: JSON-RPC error code={e.code} message={e.message!r}")

anyio.run(main)

Output with mcp 2.3.0:

2026-07-28: CallToolResult is_error=True text='Unknown tool: does_not_exist'
legacy: CallToolResult is_error=True text='Unknown tool: does_not_exist'

Expected, per the spec:

2026-07-28: JSON-RPC error code=-32602 message='Unknown tool: does_not_exist'

Notes

  • The conformance probe in server-stateless (sep-2575-server-rejects-undeclared-capability) calls a tool name the server does not list. With this behaviour the probe reports "Server executed 'test_missing_capability'…", where for the TS SDK it reports "not testable". So the deviation also produces a confusing conformance finding for ordinary servers.
  • If the current behaviour is deliberate (the model can read an isError result), the 2026-07-28 spec text would need to change, or the docs could say the high-level server deviates here.

Activity

  1. added
    bugSomething isn't working
    v2Affects the v2 line (2.x on main)
    v1Affects the v1.x maintenance line
    on Oct 8, 2026
  2. TINGyu123644 commented on Oct 9, 2026

    @TINGyu123644

    Reproduced on current main (91941ed) and read the full path through the code:

    • ToolManager.call_tool raises ToolError("Unknown tool: nope") for an unknown name (src/mcp/server/mcpserver/tools/tool_manager.py:85).
    • _handle_call_tool catches it and returns CallToolResult(content=[...], is_error=True) (src/mcp/server/mcpserver/server.py:456), so the client sees a successful result with is_error, never a JSON-RPC error.
    • The resource side already does the right thing: _handle_read_resource maps an unknown resource to MCPError(code=INVALID_PARAMS) (server.py:474-475), i.e. -32602.

    So the fix can mirror the resource path: distinguish "tool not found" from other ToolErrors (for example a ToolNotFoundError subclass, raised in tool_manager.py at both sites), and in _handle_call_tool re-raise it as MCPError(code=INVALID_PARAMS, message=...) instead of returning is_error=True. Argument-validation failures keep returning isError results as they do today, since the spec treats invalid arguments as a tool error, not a protocol error.

    Happy to prepare the patch if it's wanted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingv1Affects the v1.x maintenance linev2Affects the v2 line (2.x on main)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions