new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

MCP · Building servers and clients · all subjects

error handling

19 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Tool errors surface as result.is_error, not exceptions

A tool that raises on the server does not raise in the client's `call_tool`. Instead the result comes back with `is_error` set to true. Best practice is to check `result.is_error` rather than expecting a failing tool to raise, and to pass the flag through to the model (as `is_error` on the `tool_result` block) so it can read the message and try something else.

Raise read_timeout_seconds on the Python Client for timeout errors

If the Python MCP client reports a `Timeout error`, the fix is to raise `read_timeout_seconds` on the `Client`.

Report query errors without ending the MCP session

An interactive MCP client should catch exceptions around each query and print them rather than exiting, so a failing query is reported without ending the session. Typing `quit` or closing standard input (EOF) exits cleanly, and cleanup must run even when connection or chat-loop operations fail.

Tool errors arrive as isError: true, not transport failures

MCP tool errors arrive as a successful response with `isError: true` rather than a transport failure. Generated sandbox wrappers should convert this into a thrown exception so model-authored code can use try/catch. If an uncaught error terminates the script, surface it as the script's result so the model can self-correct; the model is responsible for reporting any partial side effects already committed.

UnsupportedProtocolVersionError handling

If a server does not support the protocol version requested in a message, it responds with an `UnsupportedProtocolVersionError` that lists the versions it does support. The client can then retry the request with a mutually supported version, or surface an error to the user if there is no overlap. Clients that do not handle this error will appear broken against servers pinned to other versions.

MissingRequiredClientCapabilityError (-32021)

If a server needs a capability that the request's `clientCapabilities` did not declare, such as elicitation, it returns a MissingRequiredClientCapabilityError with code -32021 naming the missing capabilities.

Shell recipe: branch on Inspector CLI failure class

Example branching on exit codes: `if out=$(mcp-inspector --cli "$URL" --transport http --method tools/list 2>err.json); then echo "$out"; else case $? in 3) echo "needs auth: run the web inspector once to sign in";; 4) echo "server unreachable";; *) jq .error < err.json;; esac; fi`.

Inspector CLI exit code table

Inspector CLI exit codes: 0 = success; 1 = usage or unexpected error (catch-all); 2 = no MCP App found on the tool (--app-info probe); 3 = server requires authentication (401/403, WWW-Authenticate, OAuth); 4 = server unreachable (DNS, connection refused, timeout, `fetch failed`); 5 = tool error, meaning `tools/call` returned `isError: true` or the tool was not found.

Non-zero exits write a single JSON error line to stderr

On any non-zero exit the Inspector CLI writes a single JSON line to stderr of the form {"error":{"code":"auth_required","message":"Unauthorized","status":401,"url":"https://api.example/mcp"}}. Because it is one line, a caller can parse it with `2>&1 | tail -1 | jq .error`.

tools/call with isError:true prints payload but exits 5

A `tools/call` whose result has `isError: true` still prints its payload, but the CLI exits with code 5, so an `&&` chain does not proceed after a failed tool call.

-32602 covers both unknown tool and invalid parameters

Both legacy and modern eras reject a bad `tools/call` with `-32602`. Two distinct cases share the code: 'Unknown Tool' when the message names a tool the server does not list, and 'Invalid Parameters' for any other `-32602`. Clients must read the error message to distinguish them.

Modern JSON-RPC error taxonomy: -32020, -32021, -32022, -32601

The modern era (SEP-2243 / SEP-2575) introduces a richer error taxonomy paired with real HTTP statuses: `-32020` HeaderMismatch with HTTP 400 (a required mirrored header was missing or wrong); `-32021` with HTTP 400 (the request omitted a client capability the server requires); `-32022` UnsupportedProtocolVersion with HTTP 400 (supported versions listed in `data.supported`); and `-32601` with HTTP 404 (method not found).

Go: returning tool results as TextContent

A Go SDK tool returns `&mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: result}}}, nil, nil`. Recoverable failures (e.g. an upstream API error) are returned as a normal result with an explanatory text message rather than as a Go error, so the model sees the message.

Tool execution errors

Tool execution errors contain actionable feedback that language models can use to self-correct and retry with adjusted parameters. These include API failures, input validation errors (e.g., date in wrong format, value out of range), and business logic errors. They are reported in tool results with isError: true in a content array item of type text.

Protocol errors for tools

Protocol errors in tool invocation indicate issues with the request structure itself that models are less likely to be able to fix. These include: unknown tool, malformed requests (failing to satisfy CallToolRequest schema), and server errors. They are returned as standard JSON-RPC errors with code and message fields.

Client handling of protocol errors vs tool execution errors

Clients MAY provide protocol errors to language models, though these are less likely to result in successful recovery. Clients SHOULD provide tool execution errors to language models to enable self-correction.

Prompt error handling codes

Servers SHOULD return standard JSON-RPC errors for common failure cases: -32602 (Invalid params) for invalid prompt name or missing required arguments, -32603 (Internal error) for internal errors.

Completion error handling

Servers SHOULD return standard JSON-RPC errors for common failure cases: method not found uses error code -32601 (Capability not supported); invalid prompt name uses -32602 (Invalid params); missing required arguments uses -32602 (Invalid params); internal errors use -32603 (Internal error).

Resource error handling: use error code -32602 for not found

If the requested resource does not exist, servers must return a JSON-RPC error with code -32602 (Invalid Params). Servers should return -32603 for internal errors. For backwards compatibility, clients should also accept -32002 as a resource not found error, as earlier protocol versions used this code. Servers must not return an empty contents array for a non-existent resource, as an empty array is ambiguous.

Give your agent this brain