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 — invalid arguments, not found, an endpoint rule, insufficient scope or permission — comes back as a successful JSON-RPC response whose result is flagged isError, carrying the error envelope as text:
{ "jsonrpc": "2.0", "id": 2, "result": {
"isError": true,
"content": [{ "type": "text",
"text": "{ \"error\": { \"code\": \"NOT_FOUND\", \"message\": \"Charge not found\" } }" }]
} }
When the endpoint refuses, the body is the API's own, unchanged — { "error": { "code", "message", "details"? } } with the REST API's code vocabulary. The ones you will meet most:
code | When |
|---|---|
VALIDATION_ERROR | The arguments failed validation — an unknown argument on a read tool, or the endpoint's own checks; details names the fields. |
NOT_FOUND | No such record, or it belongs to another organization. |
CONFLICT | The operation clashes with existing data. |
409 transition codes | The record is not in a state that allows the operation — for example, CHARGE_NOT_SETTLED when asking for the settlement letter of a charge that is not paid. |
INSUFFICIENT_SCOPE / FORBIDDEN | Refused by the /v1 endpoint itself, which repeats the scope check. |
The full API vocabulary is in API → Introduction.
And the codes MCP adds of its own:
code | Who resolves it |
|---|---|
insufficient_scope | The token scope does not reach the tool: the resource is not in the token, or write access to it is missing. Authorize again or use a token with that access — through the OAuth flow access is read-only today; a personal token can carry write access. |
insufficient_permission | An organization admin, by granting the permission the error names. |
membership_inactive | Reactivating the person who owns the token — no permission fixes an inactive membership. |
key_owner_not_member | The person signing in to the Régua de Cobrança dashboard with their Kobana account, or asking for an invitation to the organization. |
USER_DECLINED | On the 2026-07-28 era, the user declined or cancelled the confirmation of a destructive tool. Nothing was changed. |
confirmation_required | The tool is destructive and the client cannot confirm: it is on the 2025 era or did not declare form elicitation. Nothing was executed. |
confirmation_replayed | The confirmation sent had already been used — each one runs a call once. Call the tool again to be asked again. Nothing was executed. |
confirmation_unavailable | The server could not record the confirmation right now, so it refused the tool. Nothing was executed; try again later. |
The four authorization codes are separate on purpose: they are different conversations, with different people. A single error would say "you may not" without saying whom to ask. See Authentication.
input_required is not an error
On the 2026-07-28 era, the first tools/call to 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 re-sends the same call 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 array (batching is not supported) |
-32601 | Method not found |
-32602 | Invalid params — unknown tool, prompt or argument; on the 2026-07-28 era, also resource not found |
-32002 | Resource not found — 2025 era only (2026-07-28 uses -32602) |
-32603 | Internal error — an unexpected failure while handling the message |
{ "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: missing or invalid token, unsupported protocol version, header mismatch, disallowed Origin, wrong host, a body over 2 MB, rate limit, authorization server unreachable. They are listed in Authentication → Failure modes.
Why isError and not a JSON-RPC error
A 404 on a charge is not a defect in the MCP client — it is information about the world, and the model on the other side needs it to correct itself. Burying it in a protocol error would make the client treat it as a transport failure, hide the text and, at best, retry identically. Hence the rule: if the caller can act on it, it is a result; if the request is broken, it is an error.
Observability
Every tools/call writes a structured log line with the tool, the organization, the token id (jti), the token kind (oauth or personal), the membership, the status and the duration. Writes also appear in the organization's audit trail, written by the dispatched endpoint itself and attributed to the token (api-token:<jti>) — what an agent did shows up next to what a person did, on the same screen.