> ## Documentation Index
> Fetch the complete documentation index at: https://docs.attention.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> How clients authenticate to the Attention MCP server — OAuth for end users, API keys for programmatic access, plus scopes and rate limits.

The Attention MCP server is exposed at:

```
https://api.attention.tech/mcp
```

It speaks **MCP over HTTP Streamable transport** and accepts two authentication methods on the `Authorization` header: **OAuth 2.1 with Dynamic Client Registration (DCR)** for human users connecting from MCP clients, and **API key JWTs** for programmatic integrations. Pick whichever matches your use case.

<Note>
  Whichever method you use, the server enforces your existing Attention permissions. The MCP layer cannot grant access beyond what your user or API key already has.
</Note>

## For Claude.ai users (OAuth)

When you add the Attention connector to Claude (or any MCP-compatible client that supports DCR), the client registers itself with Attention and walks you through an OAuth consent flow.

<Steps>
  <Step title="Add the connector">
    In Claude.ai go to **Settings → Connectors → Add custom connector** and enter `https://api.attention.tech/mcp`. Skip this step if Attention is already in the connector directory.
  </Step>

  <Step title="Authorize">
    The client redirects you to Attention's login page. Sign in with Google, SSO, or email/password — whichever method your org uses. After login, you'll see a consent screen showing the scopes Claude is requesting (`mcp:read`, `mcp:write`).
  </Step>

  <Step title="Approve">
    Approve the consent screen. The client receives an OAuth access token and starts using it on every MCP request.
  </Step>
</Steps>

The OAuth token is bound to **your** Attention user. Every tool call runs under your identity — your roles, your team memberships, your data scope. Admin-only tools (e.g. `create_team`, `delete_user`) only succeed if your account has the admin role.

### What the assistant can access

The MCP server enforces the same authorization rules as the Attention app:

* **Calls and transcripts** — only calls your account can see in the app are returned by `search_calls` / `get_call_details`.
* **Teams, users, scorecards, labels, etc.** — read access scoped to your organization; some tools narrow further based on team membership.
* **Write operations** — require the `mcp:write` scope plus, for most tools, the admin role.

Org-wide settings, other users' personal data, and other organizations are never accessible.

### Revoking access

<Steps>
  <Step title="Open Connectors">
    Go to **Settings → Connectors** in Claude.ai (or your MCP client's equivalent screen).
  </Step>

  <Step title="Disconnect">
    Find the Attention connector and click **Disconnect**. Outstanding access and refresh tokens are immediately invalidated server-side.
  </Step>
</Steps>

## For developers (API keys and Anthropic Messages API)

If you're building an integration that calls the MCP server directly — from a backend service, a CI pipeline, or the Anthropic Messages API — use an **API key** instead of OAuth.

### Create an API key

You can create keys from the Attention app under **Settings → API Keys**, or programmatically via the [`create_api_key`](/mcp/tools/api-keys#create_api_key) MCP tool itself once you have any other admin-authenticated session:

```text theme={null}
Tool: create_api_key
{
  "name": "CI/CD Pipeline",
  "org_level": true,
  "expiry_hours": 8760
}
```

The token is shown **only once** at creation time. Store it in a secrets manager — Attention cannot recover it later.

Two scopes:

* **Org-level keys** (`org_level: true`) — full org access, no user binding. Best for backend integrations.
* **User-level keys** (`org_level: false`) — scoped to the authenticated user, with that user's roles and team memberships.

### Use an API key

Send the key as a Bearer token on the `Authorization` header:

<CodeGroup>
  ```bash Curl theme={null}
  curl https://api.attention.tech/mcp \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    --data '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  ```

  ```python Python theme={null}
  import os
  import httpx

  api_key = os.environ["ATTENTION_API_KEY"]

  response = httpx.post(
      "https://api.attention.tech/mcp",
      headers={"Authorization": f"Bearer {api_key}"},
      json={"jsonrpc": "2.0", "id": 1, "method": "tools/list"},
  )
  ```

  ```javascript Node.js theme={null}
  const apiKey = process.env.ATTENTION_API_KEY;

  const response = await fetch("https://api.attention.tech/mcp", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
  });
  ```
</CodeGroup>

The token is a JWT carrying an `api-version: apiv2` claim. The server detects this claim with a zero-cost base64 peek before validating, so API key requests do not pay the OAuth-validation overhead.

### Use the MCP server from the Anthropic Messages API

To let Claude call Attention tools inside an Anthropic Messages API request, declare the MCP server in the `mcp_servers` array. The `authorization_token` is your Attention API key (or a user OAuth access token):

```json theme={null}
{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "mcp_servers": [
    {
      "type": "url",
      "url": "https://api.attention.tech/mcp",
      "name": "attention",
      "authorization_token": "YOUR_ATTENTION_TOKEN"
    }
  ],
  "messages": [
    { "role": "user", "content": "Summarize my last 10 calls with Acme." }
  ]
}
```

## Scopes

The server defines two scopes. OAuth tokens carry the scopes granted at consent time; API keys have implicit access to both scopes within their organization.

| Scope       | Required for                                                                                  |
| ----------- | --------------------------------------------------------------------------------------------- |
| `mcp:read`  | Every read tool — `get_me`, `search_calls`, `list_*`, `get_*`, `ask_attention`, etc.          |
| `mcp:write` | Every mutating tool — `create_*`, `update_*`, `delete_*`, `archive_*`, snippet creation, etc. |

Many `mcp:write` tools additionally require the **admin role** on your user — see each tool's reference page for the exact requirement. Tools that explicitly require user-level authentication (not org-level keys) are flagged on their reference pages and include `invite_user`, `update_invitation`, `delete_invitation`, `delete_user`, and the super agent tools. Conversely, `get_usage_report` requires an **org-level API key** and rejects OAuth and user-level keys.

If a tool call fails due to insufficient scope or role, the response contains a structured error such as `insufficient_scope`, `admin_required`, or `user_required`.

## Rate limits

The MCP server applies a multi-window rate limiter on every authenticated request. Limits are tracked per identity in this priority order:

1. `user-{user_id}` — for OAuth tokens and user-level API keys.
2. `org-{org_id}` — for org-level API keys.
3. `ip-{client_ip}` — fallback if neither user nor org could be resolved.

Three windows are enforced simultaneously: per-second, per-hour, and per-day. Default values come from server configuration; orgs can configure custom limits via Attention support.

When a limit is exceeded the server returns `429 Too Many Requests` with:

* A `Retry-After` header (seconds until the relevant window resets).
* A JSON body of the form `{"error":"rate limit exceeded","retry_after":"N s","limit_type":"second|hour|day"}`.

If the rate limiter itself is unavailable (e.g. Redis outage), the server **fails open** — requests are allowed through rather than blocked. Availability of the MCP server is prioritized over precise enforcement during infrastructure incidents.

## Error responses

Authentication failures return `401 Unauthorized` with a `WWW-Authenticate: Bearer resource_metadata="..."` header pointing to the well-known resource metadata document. The JSON body distinguishes:

* `invalid_token` with description `"The access token has expired..."` — use your refresh token (OAuth) or rotate the API key.
* `invalid_token` with description `"The access token is invalid."` — re-authenticate from scratch.
* `unauthorized` with description `"missing or invalid Authorization header"` — no Bearer token was sent.

Tool-level errors (insufficient scope, missing fields, validation) return `200 OK` with a structured `CallToolResult` containing an error message — they are application-level errors, not transport errors.
