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.

  1. 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 ``

  1. Claude registers itself automatically (Dynamic Client Registration) and

sends you to Polis to sign in and approve the connection. Approve it.

  1. 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_estimatepolis_testpolis_statuspolis_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".

  1. That document lists authorization_servers: ["https://polis.sh"].
  2. The client fetches https://polis.sh/.well-known/oauth-authorization-server (RFC 8414).
  3. 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).

  1. 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.

  1. 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.

  1. The client calls https://polis.sh/api/mcp with Authorization: Bearer <access_token>.

Endpoints

PurposeEndpoint
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 + refreshhttps://polis.sh/api/oauth/token

Details

issued (token_endpoint_auth_method: none).

use) lasts 180 days. Authorization codes are single-use and expire in 10 minutes.

(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

Polis docs index · Full machine-readable index (llms.txt) · Everything inlined (llms-full.txt)