MCP authorization: OAuth 2.1 sign-in
This page is about authorization for Casafari's MCP servers on the Casafari API and MCP Platform: how an MCP client gets a token, following the Model Context Protocol's authorization flow (OAuth 2.1 with PKCE and protected resource metadata). The platform's REST API needs no OAuth flow: a platform API key from the console signs every call, see platform API keys. The existing REST API at api.casafari.com (contract clients) signs in differently again, with an email and password and a bearer token: see the existing API.
There is one authorization server, and each MCP server, the one server for every product (https://platform.casafari.com/mcp) and each product's own, is its own protected resource: a token works only on the server it was issued for. An access token acts for a person's platform account, and the account's plan, tokens and products decide what a call may do. The canonical, agent-facing version of this page is the platform's auth.md. mcp.casafari.com is the legacy gateway, still answering, moving to https://platform.casafari.com/mcp/<product>.
Discovery
A request without a token answers 401 with a WWW-Authenticate: Bearer resource_metadata="..." header. For Casafari Platform (https://platform.casafari.com/mcp) it points to:
- The protected resource metadata, https://platform.casafari.com/.well-known/oauth-protected-resource/mcp. Read
resource,authorization_serversandscopes_supported. Sendresourceas theresourceparameter in every authorization and token request: tokens are bound to it as their audience. - The authorization server metadata, https://platform.casafari.com/.well-known/oauth-authorization-server, for the registration, authorization and token endpoints.
Sign in on behalf of a person
- Register (once): use your Client ID Metadata Document URL as
client_id, or register with dynamic client registration (RFC 7591) as a public client (token_endpoint_auth_methodnone, grant typesauthorization_codeandrefresh_token). Keep theclient_id. - Authorize: send the person to the authorization endpoint with PKCE (
S256),stateandresource.scopeis optional (default: every scope of that resource). The person signs in, or creates an account and accepts the Platform Terms of Use, and allows your client. - Exchange the code at the token endpoint with the PKCE verifier. Access tokens last 15 minutes (
expires_in900) and come with a refresh token. - Call the server with
Authorization: Bearer <access_token>. - Refresh with
grant_type=refresh_token: each refresh returns a new pair; keep only the newest. Presenting a used refresh token again revokes the grant, and the person has to allow your client again.
For a product's own server, authorize again with that server's resource: one account, separate tokens.
Agents without a person
A client that registered itself cannot use client_credentials. For a job that runs unattended, the person creates an API key (cf_sk_..., sent as Authorization: Bearer, on MCP and REST alike) or a confidential OAuth client in the console at https://platform.casafari.com/console and hands it to the agent. A confidential OAuth client works over REST: request a token at https://platform.casafari.com/oauth/token with the client credentials grant and resource set to the product's URL, such as https://platform.casafari.com/v1/area-insights. That token lasts 15 minutes and has no refresh token, so ask for a new one when it expires; an API key does not need this exchange.
Errors
Every error is application/problem+json, and its type is a page at https://platform.casafari.com/errors/<code>.
| Status | Meaning | What to do |
|---|---|---|
401 invalid_credential | Token or key missing, revoked or expired, or a token for another resource | Refresh; if that fails, authorize again |
402 payment_required | The account's tokens ran out | Top up at the upgrade_url (the owner or a billing member pays); poll the payment link, then retry |
403 not_entitled, insufficient_scope | The plan or the credential's scopes do not cover the call | Do not retry |
429 | A request limit or usage window | Wait for Retry-After (Limits) |
5xx | Transient error | Retry with exponential backoff |