Skip to content

MCPServer answers an unknown prompt name or a missing required argument with code 0 / -32603; the spec uses -32602 #3669

Description

@ANcpLua

Initial Checks

Release line

2.x (current stable)

Description

prompts/get for a prompt name that isn't registered, or without one of the prompt's required arguments, should fail with JSON-RPC -32602 (Invalid params). The spec's prompts Error Handling section says so for both cases, in 2025-11-25 and in 2026-07-28. The TypeScript SDK's McpServer throws InvalidParams for an unknown prompt (mcp.ts:657).

MCPServer raises a plain ValueError in both cases. With the script below, on mcp 2.3.0 and on main@91941ed:

Case 2025-11-25 2026-07-28
unknown prompt name code 0, Unknown prompt: does_not_exist -32603, Internal server error
missing required argument code 0, Missing required arguments: {'name'} -32603, Internal server error
prompt function raises code 0, Error rendering prompt boom -32603, Internal server error

The first two rows should be -32602. On 2026-07-28 the client isn't even told which name was wrong. The third row is only there for contrast: it is a real internal error. docs/servers/prompts.md currently documents the missing-argument case as -32603, so fixing it changes documented behaviour.

The interaction suite already records the first two rows as divergences for 2025-11-25 (mcpserver:prompt:unknown-name and prompts:get:missing-required-args in tests/interaction/_requirements.py; the 2026-07-28 arm is excluded), but I couldn't find an issue tracking them. Draft #2999 keeps both as divergences.

#1872 (approved in March) fixes the unknown-name case, though not missing arguments, and it now conflicts with main in 11 files, including server.py. If #1872 is refreshed, it covers the first row and this issue can track the second. Otherwise I'd like to fix both myself, if you take an outside PR for it.

Related: #3659 (an unknown tool gets an isError result instead of -32602), #3342 (missing-argument errors are logged with a traceback).

Disclosure: an AI assistant helped with the investigation and this write-up.

Example Code

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

server = MCPServer("repro")

@server.prompt()
def greet(name: str) -> str:
    return f"Hello, {name}"

@server.prompt()
def boom() -> str:
    raise RuntimeError("kaboom")

CASES = [
    ("unknown prompt", "does_not_exist", {}),
    ("valid call", "greet", {"name": "Ada"}),
    ("missing argument", "greet", {}),
    ("prompt raises", "boom", {}),
]

async def main() -> None:
    for mode in ("legacy", "2026-07-28"):
        async with Client(server, mode=mode) as c:
            print(f"== mode={mode} negotiated={c.protocol_version}")
            for label, name, args in CASES:
                try:
                    r = await c.get_prompt(name, args)
                    print(f"  {label:17} -> GetPromptResult {r.messages[0].content.text!r}")
                except MCPError as e:
                    print(f"  {label:17} -> MCPError code={e.error.code} message={e.error.message!r}")

anyio.run(main)

Python & MCP Python SDK

Python 3.13.16
mcp 2.3.0 (PyPI); same result on main@91941ed

Activity

  1. added
    bugSomething isn't working
    v2Affects the v2 line (2.x on main)
    v1Affects the v1.x maintenance line
    on Oct 10, 2026
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