Errors
Failures arrive on two different channels, and the difference matters: one is a broken request, the other is something the model is meant to read and react to.
Tool errors
Anything the caller can act on — validation, not found, insufficient scope, insufficient permission, an endpoint error — comes back as a successful JSON-RPC response whose result is flagged isError, carrying the API's own error envelope as text:
{ "jsonrpc": "2.0", "id": 2, "result": {
"isError": true,
"content": [{ "type": "text", "text": "{ \"error\": { \"code\": \"not_found\", \"message\": \"not_found\" } }" }]
} }
The code vocabulary is the REST API's, unchanged — see API errors for the full list. The codes you will meet most:
code | When |
|---|---|
validation_failed | Arguments failed schema validation; details names the fields |
not_found | No such record, or it belongs to another workspace |
conflict | external_id in use, or an idempotency_key replayed with a different body |
unprocessable_entity | Business rule violation, e.g. reprocessing an e-mail in a status that does not allow it |
insufficient_scope | The connected client's token does not reach the tool: the resource is not in the token, or write access to it is missing. Through the OAuth flow access is read-only today; a personal token can carry write |
insufficient_permission | The person does not hold the permission the tool needs, in this organization |
method_not_allowed | The tool's operation is not supported on that route |
user_declined | On protocol 2026-07-28, the user declined or cancelled the confirmation of a destructive tool. Nothing changed |
confirmation_required | A destructive tool called by a client that cannot confirm it — era 2025, or 2026-07-28 without elicitation forms. Nothing ran |
confirmation_replayed | A confirmation already used was sent again. Nothing ran; call the tool without requestState to ask again |
confirmation_unavailable | The server could not take the confirmation at that moment. Nothing ran; try again later |
insufficient_scope and insufficient_permission are separate because different people resolve them: the first by whoever owns the connected client and its token, the second by the organization's administrator in the dashboard.
input_required is not an error
On protocol 2026-07-28, the first tools/call of a destructive tool may come back with resultType: "input_required" and a confirmation request for the user. That is the normal flow, not a failure: the client shows the question and sends the same call again with the answer. See Confirming destructive tools.
Protocol errors
A malformed message gets a JSON-RPC error object instead of a result:
| Code | Meaning |
|---|---|
-32700 | Parse error — the body is not valid JSON |
-32600 | Invalid request — not a JSON-RPC object, or an unsupported array batch |
-32601 | Method not found |
-32602 | Invalid params — unknown tool, prompt or argument, or name missing; on 2026-07-28, also a resource not found |
-32002 | Resource not found — on the 2025 revisions only (2026-07-28 uses -32602) |
-32020 | Header mismatch — on 2026-07-28, an MCP-Protocol-Version, Mcp-Method or Mcp-Name header that does not match the body (HTTP 400) |
-32022 | Unsupported protocol version — data.supported lists the supported ones (HTTP 400) |
-32603 | Internal error — an unexpected failure while running the tool |
A request body over 1 MB (1,048,576 bytes) is refused with HTTP 413 and -32600 before anything runs — and, when Content-Length declares it, before authentication:
{ "jsonrpc": "2.0", "id": null, "error": { "code": -32600, "message": "Request body too large (limit 1048576 bytes)" } }
{ "jsonrpc": "2.0", "id": 3, "error": { "code": -32601, "message": "Method not found: tools/describe" } }
Transport errors
Rejections that happen before the JSON-RPC message is read are plain HTTP responses with the API's error envelope — missing token, invalid token or one issued for another resource, disallowed origin, unselected workspace, person not a member, rate limit, authorization server unavailable (503). They are listed in Authentication.
Correlation
Every response carries an X-Request-Id header. Include it when reporting an issue so the trace can be pulled. Every tool call is also written to the audit log with the tool name, the workspace, the token jti, whether the token came from the OAuth flow or is a personal token, the person, the resulting status and the duration — never the address, subject or body of an e-mail.