# Authenticating an AI agent with Kairo

Kairo has one programmatic surface for AI agents: the Kairo MCP server at `https://mcp.kairocalories.com/mcp` (Model Context Protocol, Streamable HTTP). It exposes the signed-in user's own nutrition diary: goals, daily totals, meals, weight and micronutrient history, plus tools to log meals and weight. There is no public REST API and no API-key product.

Every credential belongs to a real Kairo user. An agent never gets an account of its own: the user signs in with the same Apple or Google account they use in the iPhone app and approves the agent on a consent screen. Kairo therefore does not offer an `agent_auth` block, anonymous agent registration or `identity_assertion` (ID-JAG) token exchange.

## Discover

1. Call the MCP endpoint without a token. It answers `401` with
   `WWW-Authenticate: Bearer error="invalid_token", resource_metadata="https://mcp.kairocalories.com/.well-known/oauth-protected-resource/mcp"`.
2. Fetch that RFC 9728 protected-resource metadata. It names the resource (`https://mcp.kairocalories.com/mcp`) and its authorization server (`https://gvvknzeiszslsksxrzbm.supabase.co/auth/v1`).
3. Fetch the authorization server's RFC 8414 metadata at `https://gvvknzeiszslsksxrzbm.supabase.co/auth/v1/.well-known/oauth-authorization-server` for the authorize, token and registration endpoints.

The MCP server card at `https://kairocalories.com/.well-known/mcp/server-card.json` lists every tool, resource and prompt before you connect.

## Pick a method

OAuth 2.1 authorization code flow with PKCE (`S256`) is the only method. Public clients (`token_endpoint_auth_method: none`) are supported, which is what desktop and CLI agents should use.

## Register

Register your client with OAuth 2.0 Dynamic Client Registration (RFC 7591) at the `registration_endpoint`:

```
POST https://gvvknzeiszslsksxrzbm.supabase.co/auth/v1/oauth/clients/register
Content-Type: application/json

{"client_name": "My Agent", "redirect_uris": ["http://localhost:33418/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"]}
```

MCP clients such as Claude, ChatGPT, Claude Code, Codex and Gemini CLI do this automatically when you add `https://mcp.kairocalories.com/mcp` as a connector.

## Claim

Open the `authorization_endpoint` in the user's browser with `response_type=code`, your `client_id`, `redirect_uri`, a PKCE `code_challenge` and `resource=https://mcp.kairocalories.com/mcp`. The user signs in with Apple or Google on `https://mcp.kairocalories.com/oauth/consent` and approves access. Exchange the returned code at the `token_endpoint` for an access token and a refresh token.

The user needs an existing Kairo account, created in the iPhone app ([App Store](https://apps.apple.com/app/id6756936526)). Signing in with an account that has never used the app ends on a page that links to the App Store.

## Use the credential

Send the access token as `Authorization: Bearer <token>` on every `POST https://mcp.kairocalories.com/mcp`. The server is stateless: no session id, one JSON response per request. Tokens are only accepted if they were issued by the OAuth flow above (audience `https://mcp.kairocalories.com`); an ordinary Kairo app session token is rejected. Refresh with the `refresh_token` grant before the access token expires.

All data access runs under the user's own token and is limited to that user's rows. Write tools (`log_meal`, `relog_meal`, `update_meal`, `delete_meal`, `give_meal_feedback`, `log_weight`) change the user's real diary: call them only when the user asks for that change.

## Errors

- `401` with `WWW-Authenticate: Bearer error="invalid_token"`: missing, expired or wrong-audience token. Refresh it, or run the flow again.
- `405`: only `POST` is supported on `/mcp`.
- Tool results with `isError: true` carry a short reason, for example when the per-user limit of 30 tool calls per minute is reached. Wait a minute and retry.
- A meal in status `error` with `error_code: "subscription_required"` means the user has used their three free AI analyses and needs a Kairo subscription ([pricing](https://kairocalories.com/pricing.md)). `analysis_failed` means the analysis itself failed; logging the meal again usually works.

## Revocation

The user can see and revoke every connected agent at `https://mcp.kairocalories.com/connections`. Revoking removes the grant, so the agent has to run the authorization flow again.

## Contact

Questions about agent access: support@kairocalories.com
