> Full machine-readable index: https://polis.sh/llms.txt

[Polis](https://polis.sh) · [All docs](https://polis.sh/docs) · [llms.txt](https://polis.sh/llms.txt) · [llms-full.txt](https://polis.sh/llms-full.txt)

# Connect via OAuth (optional)

Polis has **two** ways to authenticate to the MCP server. They reach the same
account, the same tools, and the same billing — pick whichever your client
supports.

1. **Bearer API key** (`sk_live_...`) — the primary, simplest path. If your
   client lets you paste a token/header, use this and ignore the rest of this
   page. See [Agent quickstart](https://polis.sh/docs/quickstart).
2. **OAuth 2.1** (authorization code + PKCE, with Dynamic Client Registration)
   — **optional**, for platforms whose connector UI only speaks OAuth and has
   no field for a raw key. The clearest example is a **Claude.ai custom
   connector**; **ChatGPT** custom connectors can use it too.

## Who should use OAuth

Use OAuth only if your platform requires it. Signs you need it: the "add a
connector / MCP server" dialog asks only for a URL and then sends you through a
sign-in screen, with nowhere to paste `Authorization: Bearer`. If you *can*
paste a bearer token, the API key is less setup.

## Connect Claude.ai (custom connector)

1. In Claude.ai, go to **Settings → Connectors → Add custom connector**.
2. For the server URL, enter the Polis MCP endpoint:

   ```
   https://polis.sh/api/mcp
   ```

3. Claude registers itself automatically (Dynamic Client Registration) and
   sends you to Polis to **sign in and approve** the connection. Approve it.
4. You're returned to Claude and the `polis_*` tools are available. No API key
   to copy or store.

ChatGPT (custom connectors / developer mode) follows the same idea: add the MCP
URL and complete the Polis sign-in + consent when prompted.

After connecting, it works exactly like the API-key path: call
`polis_account`, then `polis_estimate` → `polis_test` → `polis_status`
→ `polis_report`. Billing, trial tokens, plans, and the spend cap are all the
same — they belong to the Polis account you signed in as.

## The flow (for implementers)

Standard OAuth 2.1 for MCP. A spec-compliant client needs no special handling:

1. An unauthenticated MCP request returns `401` with
   `WWW-Authenticate: Bearer resource_metadata="https://polis.sh/.well-known/oauth-protected-resource"`.
2. That document lists `authorization_servers: ["https://polis.sh"]`.
3. The client fetches `https://polis.sh/.well-known/oauth-authorization-server` (RFC 8414).
4. **Dynamic Client Registration** (RFC 7591): the client POSTs its
   `redirect_uris` to `https://polis.sh/api/oauth/register` and gets a `client_id`
   (public client; PKCE, no client secret).
5. **Authorize**: the client opens `https://polis.sh/oauth/authorize` with
   `response_type=code`, `client_id`, `redirect_uri`, `code_challenge`
   (`code_challenge_method=S256`), and `state`. The human signs in to Polis
   and approves; Polis redirects back with a single-use `code`.
6. **Token**: the client POSTs to `https://polis.sh/api/oauth/token` with
   `grant_type=authorization_code`, the `code`, the PKCE `code_verifier`,
   `redirect_uri`, and `client_id`, and receives an `access_token` (Bearer)
   plus a `refresh_token`.
7. The client calls `https://polis.sh/api/mcp` with `Authorization: Bearer <access_token>`.

### Endpoints

| Purpose | Endpoint |
|---------|----------|
| Protected resource metadata (RFC 9728) | `https://polis.sh/.well-known/oauth-protected-resource` |
| Authorization server metadata (RFC 8414) | `https://polis.sh/.well-known/oauth-authorization-server` |
| Dynamic Client Registration (RFC 7591) | `https://polis.sh/api/oauth/register` |
| Authorization (sign-in + consent) | `https://polis.sh/oauth/authorize` |
| Token + refresh | `https://polis.sh/api/oauth/token` |

### Details

- **PKCE is required** (`S256` only). Public clients only; no client secret is
  issued (`token_endpoint_auth_method: none`).
- **Scope**: a single `mcp` scope grants access to the Polis MCP tools.
- **Lifetimes**: access tokens last 30 days; a `refresh_token` (rotated on
  use) lasts 180 days. Authorization codes are single-use and expire in 10
  minutes.
- **Revocation**: disconnect a connected app anytime from the Polis dashboard
  (`https://polis.sh/app`). That immediately invalidates its tokens.

API keys are unaffected by any of this — they remain the simplest path and
never expire unless you revoke them.

---

## All docs

- [What Polis is](https://polis.sh/docs/overview.md): The concept, inputs, and what you get back.
- [Agent quickstart](https://polis.sh/docs/quickstart.md): Connect, get a key, run a test, read the report.
- [How to run a test](https://polis.sh/docs/run-a-test.md): The workflow, a worked example, and how to read the report.
- [Test options reference](https://polis.sh/docs/test-options.md): Every input, every variation, and the full report schema.
- [MCP tools](https://polis.sh/docs/mcp-tools.md): Every tool, its inputs, and cost.
- [Detail levels & follow-up](https://polis.sh/docs/detail-and-followup.md): Richer per-persona output, and asking personas follow-ups.
- [Pricing & billing](https://polis.sh/docs/pricing.md): Polis tokens, plans, free trial, metered usage, spend limit.
- [Connect via OAuth (Claude, ChatGPT)](https://polis.sh/docs/oauth.md) (you are here): Optional OAuth 2.1 for connectors that don't take a raw API key.
- [Discovery & well-known endpoints](https://polis.sh/docs/discovery.md): How agents and clients discover Polis.

[Polis docs index](https://polis.sh/docs) · [Full machine-readable index (llms.txt)](https://polis.sh/llms.txt) · [Everything inlined (llms-full.txt)](https://polis.sh/llms-full.txt)