Log MCPServer handler exceptions by kind and keep crash details off the wire (#3314)

Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
This commit is contained in:
Max 2026-08-24 15:51:18 +01:00 • committed by GitHub
commit 56af44727b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -122,23 +122,25 @@ async def test_get_prompt_with_a_wrong_type_argument_is_rejected_before_the_func
"""An argument that fails the function signature's type validation is rejected before the function runs.
The decorated function is wrapped in pydantic's validate_call, so a value that cannot be
coerced to the parameter's annotation fails before the body executes. The function body
raises NotImplementedError to prove it never ran. The error is wrapped in the SDK's stable
rendering-error prefix; the body of the message is raw pydantic output and is not asserted.
coerced to the parameter's annotation fails before the body executes; `ran` stays empty to
prove it. The client sees only the SDK's rendering-error message naming the prompt, with the
pydantic detail withheld.
"""
mcp = MCPServer("prompter")
ran: list[str] = []
@mcp.prompt()
def repeat(phrase: str, count: int) -> str:
"""A registered prompt; type validation rejects the call before the function runs."""
raise NotImplementedError
ran.append(phrase) # pragma: no cover
return phrase * count # pragma: no cover
async with connect(mcp) as client:
with pytest.raises(MCPError) as exc_info:
await client.get_prompt("repeat", {"phrase": "hi", "count": "many"})
assert exc_info.value.error.code == 0
assert exc_info.value.error.message.startswith("Error rendering prompt repeat: 1 validation error")
assert ran == []
assert exc_info.value.error == snapshot(ErrorData(code=0, message="Error rendering prompt repeat"))
@requirement("mcpserver:prompt:optional-args")