# Sakaira: sign-in for agents

Sakaira is a remote MCP server at https://mcp.sakaira.com/mcp. Every call is made for a person with a Sakaira account, who signs in once in a browser; the agent then holds an OAuth 2.1 access token for that person. No API keys, no shared secrets, and no token without that person's approval.

## Discover

Call https://mcp.sakaira.com/mcp without a token: it answers 401 with a `WWW-Authenticate: Bearer` header whose `resource_metadata` names the protected resource metadata (RFC 9728).

- Protected resource metadata: https://mcp.sakaira.com/.well-known/oauth-protected-resource/mcp (resource https://mcp.sakaira.com/mcp, scope mcp:tools)
- Authorization server metadata (RFC 8414): https://mcp.sakaira.com/.well-known/oauth-authorization-server

## Pick a method

One method: the OAuth 2.1 authorization code flow with PKCE (S256), as a public client (token_endpoint_auth_method none), for the mcp:tools scope. Claude, ChatGPT, Cursor, Codex and most other MCP clients run it on their own once the server URL is added.

Not offered: API keys, the client credentials grant, and the auth.md agent_auth methods (identity_endpoint, identity_assertion, service_auth): every token belongs to a person who approved it.

## Register

Use an https URL to your Client ID Metadata Document as the client_id (client_id_metadata_document_supported), or register with Dynamic Client Registration (RFC 7591): POST your client_name and redirect_uris to https://mcp.sakaira.com/oauth/register.

## Claim

Send the person to https://mcp.sakaira.com/oauth/authorize with response_type=code, client_id, redirect_uri, state, code_challenge, code_challenge_method=S256, scope=mcp:tools and resource=https://mcp.sakaira.com/mcp. They sign in to Sakaira (a new account starts with 100 free credits, no card) and approve your client; the browser returns to your redirect_uri with code, state and iss.

## Exchange

POST to https://mcp.sakaira.com/oauth/token (application/x-www-form-urlencoded) with grant_type=authorization_code, code, code_verifier, client_id, redirect_uri and resource. You get an access_token, valid for 1 hour, and a refresh_token, valid for 60 days and replaced on every use: POST grant_type=refresh_token with it for a new pair.

## Use the access_token

Send `Authorization: Bearer <access_token>` on every request to https://mcp.sakaira.com/mcp (Streamable HTTP). Every tool, its parameters and its price: https://sakaira.com/mcp.md.

## Errors

- 401 with `WWW-Authenticate: Bearer error="invalid_token"`: the token is missing, expired or revoked. Refresh it, or send the person through Claim again.
- The OAuth endpoints answer errors as JSON `{ error, error_description }` (RFC 6749), for example invalid_grant for a used or expired code or refresh token.
- A tool that fails returns `{ ok: false, error: { code, message, retryable } }`; the codes and what to do: https://sakaira.com/mcp.md.

## Revocation

POST token=<refresh_token> to https://mcp.sakaira.com/oauth/revoke (RFC 7009): it revokes that refresh token and every one issued from the same sign-in, and always answers 200. Access tokens are not revoked one by one; they expire within the hour.
