Skip to main content

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:

codeWhen
VALIDATION_ERRORThe arguments failed validation — an unknown argument on a read tool, or the endpoint's own checks; details names the fields.
NOT_FOUNDNo such record, or it belongs to another organization.
CONFLICTThe operation clashes with existing data.
409 transition codesThe 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 / FORBIDDENRefused 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:

codeWho resolves it
insufficient_scopeThe 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_permissionAn organization admin, by granting the permission the error names.
membership_inactiveReactivating the person who owns the token — no permission fixes an inactive membership.
key_owner_not_memberThe person signing in to the Régua de Cobrança dashboard with their Kobana account, or asking for an invitation to the organization.
USER_DECLINEDOn the 2026-07-28 era, the user declined or cancelled the confirmation of a destructive tool. Nothing was changed.
confirmation_requiredThe tool is destructive and the client cannot confirm: it is on the 2025 era or did not declare form elicitation. Nothing was executed.
confirmation_replayedThe confirmation sent had already been used — each one runs a call once. Call the tool again to be asked again. Nothing was executed.
confirmation_unavailableThe 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:

CodeMeaning
-32700Parse error — the body is not valid JSON
-32600Invalid request — not a JSON-RPC object, or an array (batching is not supported)
-32601Method not found
-32602Invalid params — unknown tool, prompt or argument; on the 2026-07-28 era, also resource not found
-32002Resource not found — 2025 era only (2026-07-28 uses -32602)
-32603Internal 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.