Errors in MCP
What MCP error envelopes look like and how an agent should react.
Where errors show up
MCP responses come back as JSON-RPC result objects with a content array. When a tool call fails, the result still includes structured error info — usually as a JSON object inside a text content block.
{
"content": [
{
"type": "text",
"text": "{\"error\":{\"type\":\"invalid_request_error\",\"code\":\"resource_not_found\",\"message\":\"Customer cus_xxx not found.\",\"request_id\":\"req_...\"}}"
}
],
"isError": true
}
The inner error object follows EPD’s standard REST error shape — same fields, same codes. Read REST errors for the full reference; everything there applies here.
Common error codes by category
| Category | Codes |
|---|---|
| Authentication | missing_api_key, invalid_api_key, expired_api_key, revoked_api_key |
| Authorization | insufficient_permissions, ip_not_allowed, environment_mismatch |
| Validation | validation_error, required_field, invalid_value, invalid_format |
| State | resource_not_found, invalid_state_transition, already_canceled |
| Idempotency | idempotency_key_in_use, idempotency_key_conflict |
| Rate limiting | rate_limit_exceeded, global_rate_limit_exceeded |
| Payment | card_declined, insufficient_funds, expired_card, invalid_vault_id, gateway_error, payment_failed |
| MCP-specific | not_implemented (e.g. pause_subscription returns this until the feature ships) |
How an agent should react
validation_error and friends mean the tool call was malformed. Return the message + field_errors to the user; do not retry.
invalid_api_key, insufficient_permissions, ip_not_allowed are configuration problems. Stop and notify the operator; retrying will not fix them.
rate_limit_exceeded or global_rate_limit_exceeded — pause for a few seconds with jitter, then retry the same call.
gateway_error, internal_error, service_unavailable are transient. Retry with the same idempotency_key.
card_declined, insufficient_funds, expired_card need a human decision — collect a different card or wait. Do not silently retry.
Where to find request_id
Every error includes a request_id. When opening a support ticket about an MCP call, paste it — it lets support trace your exact call instantly.
"request_id": "req_a1b2c3d4e5f67890abcdef0123456789"