Rate limits and errors
Limits you should design around, and what the failure modes actually look like on the wire.
MCP requests are limited to 60 per minute per bucket, measured over a sliding window. An API key is its own bucket. An OAuth connection's bucket is the DCR client application, not the individual account — so multiple accounts authorized through the same client registration share one 60-requests-per-minute allowance. Exceeding it returns 429.
HTTP-level errors
Some failures happen before your call reaches a tool, and surface as ordinary HTTP status codes:
- 401 — the credential is missing, invalid, expired, revoked, or re-authorization is required. The response carries a WWW-Authenticate header pointing an OAuth-capable client at the discovery document.
- 429 — the bucket's rate limit is exceeded. A Retry-After header names the wait in seconds.
- 402 — the tenant's subscription is not active (canceled, unpaid, or trial expired). This is unrelated to your credential or your call; retrying will not help until the operator resolves billing in the app.
- 503 — Connect is disabled in this environment. This is an operational condition, not something your call caused or can work around.
Tool-call errors
A credential that authenticates fine can still be denied a specific tool. That denial is not an HTTP status — the HTTP response is a normal 200 carrying an MCP tool result with isError: true and a JSON error code such as role_or_module_denied (the credential's role or modules do not cover this tool), read_only_key (a read-only credential tried to call a write tool), confirmation_required (a confirmation-gated tool was called without _confirm: true in the arguments), or plan_upgrade_required (the tenant's plan does not include agent tool access). Check the tool result, not the HTTP status code, for these.