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

CategoryCodes
Authenticationmissing_api_key, invalid_api_key, expired_api_key, revoked_api_key
Authorizationinsufficient_permissions, ip_not_allowed, environment_mismatch
Validationvalidation_error, required_field, invalid_value, invalid_format
Stateresource_not_found, invalid_state_transition, already_canceled
Idempotencyidempotency_key_in_use, idempotency_key_conflict
Rate limitingrate_limit_exceeded, global_rate_limit_exceeded
Paymentcard_declined, insufficient_funds, expired_card, invalid_vault_id, gateway_error, payment_failed
MCP-specificnot_implemented (e.g. pause_subscription returns this until the feature ships)

How an agent should react

Validation errors — surface to user

validation_error and friends mean the tool call was malformed. Return the message + field_errors to the user; do not retry.

Authentication / authorization — stop

invalid_api_key, insufficient_permissions, ip_not_allowed are configuration problems. Stop and notify the operator; retrying will not fix them.

Rate limit — back off

rate_limit_exceeded or global_rate_limit_exceeded — pause for a few seconds with jitter, then retry the same call.

Gateway / internal — retry idempotently

gateway_error, internal_error, service_unavailable are transient. Retry with the same idempotency_key.

Card declined — let the user choose

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"