# Calories Club MCP — Agent Connection Guide

## Endpoint

```
https://api.recordo.app/api/mcp/calories/mcp
```

## Authentication

### Option 1: Device Flow (recommended for agents)

No localhost callback needed. Works from Telegram, CLI, headless servers.

**Step 1 — Request a device code:**

```
POST https://api.recordo.app/api/mcp/auth/device
Content-Type: application/json

{
  "client_id": "your-agent-id",
  "app": "calories",
  "scope": "read:entries write:entries"
}
```

Response:

```json
{
  "device_code": "...",
  "user_code": "ABCD-EFGH",
  "verification_uri": "https://api.recordo.app/mcp/calories/verify",
  "verification_uri_complete": "https://api.recordo.app/mcp/calories/verify?code=ABCD-EFGH",
  "expires_in": 900,
  "interval": 5
}
```

**Step 2 — Show the user `verification_uri_complete` and the code.** They open the link on any device, log in, and approve.

**Step 3 — Poll for tokens:**

```
POST https://api.recordo.app/api/mcp/auth/token
Content-Type: application/json

{
  "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
  "device_code": "...",
  "client_id": "your-agent-id"
}
```

Poll every `interval` seconds until you get tokens:

| Response | Meaning |
|---|---|
| `{"error": "authorization_pending"}` | User hasn't acted yet — keep polling |
| `{"error": "slow_down"}` | Polling too fast — increase interval by 5s |
| `{"error": "access_denied"}` | User denied the request |
| `{"error": "expired_token"}` | Code expired (15 min) — start over |
| `200` with tokens | Success |

Access tokens expire in 30 days. Use `grant_type=refresh_token` to renew.

**Important:** Token values in the response may be auto-redacted by your terminal or chat platform. Do NOT rely on displayed output — capture and store the token programmatically in the same script that polls. For example, parse the JSON response and write it directly to your config file or secrets store.

**Step 4 — Use the token:**

```
Authorization: Bearer <access_token>
```

### Option 2: Personal Access Token (simplest)

User creates a long-lived token and pastes it into agent config.

```
POST https://api.recordo.app/api/mcp/auth/pat
Content-Type: application/json
Authorization: Bearer <user_session_token>

{
  "name": "My Agent",
  "scopes": ["read:entries", "write:entries"],
  "app_id": "calories"
}
```

Response includes `token` (shown once). PATs expire in 1 year.

Agent config:

```yaml
mcp_servers:
  calories_club:
    url: "https://api.recordo.app/api/mcp/calories/mcp"
    headers:
      Authorization: "Bearer <token>"
```

### Option 3: OAuth Authorization Code + PKCE

Standard browser-based OAuth for desktop clients with localhost callback.

Register the client first so the server knows which `redirect_uri` values are allowed for that `client_id`.

Example registration:

```
POST https://api.recordo.app/api/mcp/auth/register
Content-Type: application/json

{
  "client_name": "My Desktop Agent",
  "redirect_uris": ["http://127.0.0.1:8787/callback"]
}
```

```
GET https://api.recordo.app/api/mcp/auth/authorize?client_id=...&redirect_uri=...&code_challenge=...&code_challenge_method=S256&scope=read:entries write:entries&app=calories
```

## Scopes

| Scope | Access |
|---|---|
| `read:entries` | Read entries |
| `write:entries` | Create, edit, and delete entries |

Default scope (if omitted): `read:entries`.

## Token Refresh

```
POST https://api.recordo.app/api/mcp/auth/token
Content-Type: application/json

{
  "grant_type": "refresh_token",
  "refresh_token": "...",
  "client_id": "your-agent-id"
}
```

Returns new `access_token` + `refresh_token`. Old tokens are revoked.

## Discovery

```
GET https://api.recordo.app/.well-known/oauth-authorization-server/api/mcp/calories/mcp
GET https://api.recordo.app/.well-known/oauth-protected-resource/api/mcp/calories/mcp
```

