1. Authentication / authorization failures (HTTP)
If the bearer token is missing, malformed, expired, or revoked, the MCP endpoint returns an HTTP401 Unauthorized before the request reaches the tool layer. The response carries an RFC 9728 WWW-Authenticate challenge:
realm, error, optional scope, resource_metadata).
Reactions:
- Re-run the OAuth flow. The
resource_metadataURL is the authoritative pointer to the AS — do not hard-code the token endpoint. - For revoked grants, the user must reconnect — see Manage connections.
- If the request authenticated with a platform API key instead of OAuth, a bad key gets the same
401shape with the bodyinvalid or expired API key— rotate or re-issue the key from the project settings; the OAuth challenge in the header does not apply to you.
2. Subscription / rate-limit failures (HTTP)
Requests that pass authentication but hit a subscription block or per-org rate limit return RFC 9457application/problem+json bodies — the same shape as the REST API. The response is HTTP, not an MCP tool result, because the request never reached a tool.
spend_limit_exceeded,credits_depleted,rate_limit_exceededsubscription_suspended,payment_past_due,subscription_inactivepro_required,not_a_member
error_code; surface resolve.message and resolve.url to the user. Agents that can take action programmatically should use resolve.action, resolve.method, and resolve.endpoint.
3. Tool-level failures (MCP isError: true)
When a request reaches a tool but the tool itself fails (missing required parameter, slug not found, invalid date, downstream handler error), the MCP server returns a 200 OK HTTP response carrying an MCP CallToolResult with isError: true and a single text content block:
**Error code:** <slug> line — a stable, machine-readable code to branch on without substring-matching the prose that follows. Two kinds of codes appear:
- MCP-only codes for failures that never reach the REST layer:
missing_parameter,invalid_parameter,invalid_input(malformed arguments), andunknown_tool(aparticle_calldispatch to a name that doesn’t exist on the public surface). - REST catalog codes reused as-is when the underlying handler fails — e.g.
not_found,bad_request,premium_required. See REST → Errors for the full catalog.
resolve guidance from the REST layer (message + URL) is folded into that suggestion; common statuses get a default:
- 404 suggests re-resolving the identifier first (
particle_podcast_resolve,particle_person_resolve,particle_company_resolve, orparticle_entity_resolve) and retrying with the returned slug. - 400/422 suggests checking the parameter constraints via
particle_catalogwith the tool’s category, which returns the full input schema.
- Branch on the
**Error code:**slug, then follow the suggestion in the text — it names the exact tool to call next. - For
missing_parameter/invalid_parameter, the text includes a usage hint (e.g.query="sam altman") — fix the call and retry. - For
internal_error, surface the message to the user and avoid retry loops — the resource server logs the underlying error with full structure for support follow-up.
Why three layers?
- HTTP 401 is the only path that’s defined by RFC 6750 / RFC 9728 — MCP clients that follow the OAuth spec already handle it. Putting auth errors anywhere else would break the discovery loop.
- HTTP 402/403/429 with RFC 9457 bodies stays consistent with the REST API: the same billing or rate-limit middleware runs in front of both surfaces, so the same problem-details shape comes out.
isError: trueMCP results are how the spec recommends per-tool failures be returned — a200 OKJSON-RPC response with the structured error in the result envelope, so the agent can keep the session open and fix the call.
See also
- REST → Errors — the canonical catalog of
error_codevalues and resolution actions. - Authentication — how 401s arise and what
WWW-Authenticatecarries. - Tool reference — every tool documents its required parameters and the failure modes it can raise.