# auth.md — Latitude

You are an agent. This document tells you how to register for **Latitude** and obtain OAuth credentials to call the [Latitude MCP server](https://docs.latitude.so/getting-started/mcp). Follow the steps in order; do not skip ahead.

Latitude is an open-source AI agent observability platform. The MCP server exposes your Latitude workspace — projects, traces, annotations, datasets, monitors, and more — as tools your agent can call.

This is the **user claimed** flow: the user signs in to Latitude and selects the organization to grant access via the claim ceremony at `claim_uri`.

Hostnames used throughout:

| Role | Host |
| --- | --- |
| Resource server (MCP/API) | `https://api.latitude.so` |
| Authorization server (registration + tokens) | `https://console.latitude.so` |
| This file | `https://latitude.so/auth.md` |
| MCP endpoint | `https://api.latitude.so/v1/mcp` |

Machine-readable discovery:

- Protected Resource Metadata (site): https://latitude.so/.well-known/oauth-protected-resource
- Protected Resource Metadata (API/MCP): https://api.latitude.so/.well-known/oauth-protected-resource
- Authorization Server metadata (includes `agent_auth`): https://latitude.so/.well-known/oauth-authorization-server

## Audience

This file is for AI agents (Cursor, Claude Code, Codex, Gemini CLI, Zed, OpenCode, and similar) that need to connect to a user's Latitude organization on their behalf.

## Step 1 — Register an OAuth client

Register (or reuse) a public OAuth client with PKCE support. Most agents perform Dynamic Client Registration automatically.

```http
POST /api/auth/mcp/register HTTP/1.1
Host: console.latitude.so
Content-Type: application/json

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

Response (201):

```json
{
  "client_id": "client_01ABC123...",
  "client_secret": null,
  "client_id_issued_at": 1710000000,
  "redirect_uris": ["http://127.0.0.1/callback"]
}
```

Persist `client_id` for the authorization and token steps.

## Step 2 — Start user authorization (claim ceremony)

Open the authorization URL in the user's browser. The user signs in to Latitude and selects the organization to grant access. Use PKCE (`code_challenge` / `code_verifier` with method `S256`).

```http
GET /api/auth/mcp/authorize?response_type=code&client_id=<client_id>&redirect_uri=<redirect_uri>&scope=openid%20profile%20email%20offline_access&code_challenge=<code_challenge>&code_challenge_method=S256 HTTP/1.1
Host: console.latitude.so
```

After the user completes sign-in, Latitude redirects to your `redirect_uri` with an authorization `code` query parameter. Capture that code for Step 3.

## Step 3 — Exchange the authorization code

```http
POST /api/auth/mcp/token HTTP/1.1
Host: console.latitude.so
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=<code>&redirect_uri=<redirect_uri>&client_id=<client_id>&code_verifier=<code_verifier>
```

Response (200):

```json
{
  "access_token": "eyJ...",
  "refresh_token": "rt_...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid profile email offline_access"
}
```

What each field is:

- `access_token` — short-lived bearer credential for MCP and API calls.
- `refresh_token` — used to obtain new access tokens without repeating the user consent flow.

## Step 4 — Use the credential

Connect to the MCP server with the access token:

```http
POST /v1/mcp HTTP/1.1
Host: api.latitude.so
Authorization: Bearer <access_token>
Content-Type: application/json
```

The MCP exposes Latitude workspace operations as tools. See the [API reference](https://docs.latitude.so) for the live tool catalog.

If you get a 401 on a previously-working `access_token`, the user revoked access or the token expired. Use the `refresh_token` at the same token endpoint with `grant_type=refresh_token`, or restart at Step 2 if refresh fails.

## Scopes

| Scope | Description |
| --- | --- |
| `openid` | OpenID Connect identity |
| `profile` | User profile (name) |
| `email` | User email address |
| `offline_access` | Refresh token for long-lived agent sessions |

## Quick setup

For most agents, add Latitude as a **Remote Streamable HTTP MCP server**:

- **URL:** `https://api.latitude.so/v1/mcp`
- **Auth:** OAuth (enabled)

Then follow your agent's OAuth connect flow. Installation steps for every major agent are in the [MCP docs](https://docs.latitude.so/getting-started/mcp).

### Example MCP config (Cursor)

```json
{
  "mcpServers": {
    "latitude": {
      "url": "https://api.latitude.so/v1/mcp"
    }
  }
}
```

## Discovery details

### Protected Resource Metadata

Site-level metadata (RFC 9728 — `resource` matches the serving origin):

```http
GET https://latitude.so/.well-known/oauth-protected-resource
```

API/MCP metadata (use this `resource` value in OAuth token requests):

```http
GET https://api.latitude.so/.well-known/oauth-protected-resource
```

Key fields:

- `resource` — `https://latitude.so` (site) or `https://api.latitude.so` (API/MCP)
- `authorization_servers` — `["https://latitude.so"]`
- `scopes_supported` — `openid`, `profile`, `email`, `offline_access`
- `bearer_methods_supported` — `["header"]`

### Authorization Server metadata

```http
GET https://latitude.so/.well-known/oauth-authorization-server
```

Read the standard OAuth fields (`issuer`, `token_endpoint`, `registration_endpoint`, `authorization_endpoint`, `grant_types_supported`) and the `agent_auth` block:

```json
{
  "skill": "https://latitude.so/auth.md",
  "register_uri": "https://console.latitude.so/api/auth/mcp/register",
  "claim_uri": "https://console.latitude.so/api/auth/mcp/authorize",
  "identity_endpoint": "https://console.latitude.so/api/auth/mcp/register",
  "claim_endpoint": "https://console.latitude.so/api/auth/mcp/authorize",
  "identity_types_supported": ["anonymous", "service_auth"],
  "anonymous": {
    "credential_types_supported": ["access_token", "refresh_token"]
  },
  "identity_assertion": {
    "assertion_types_supported": ["verified_email"],
    "credential_types_supported": ["access_token", "refresh_token"]
  },
  "service_auth": {
    "credential_types_supported": ["access_token", "refresh_token"]
  }
}
```

## Revocation

Users can revoke any connected agent from **Settings → Keys → OAuth Keys** in the Latitude console. Revocation immediately cuts off the agent's access.

## Links

- [MCP installation guide](https://docs.latitude.so/getting-started/mcp)
- [Latitude documentation](https://docs.latitude.so)
- [Privacy policy](https://latitude.so/privacy)
- [Terms of service](https://latitude.so/terms)
