AUTH_MODE. Password and configured OIDC sign-in both authorize MCP clients. API keys, browser/mobile sessions, and enrolled-agent credentials continue to work.
Configure the canonical origin
Deploy the database migrations before enabling OAuth:APP_SECRET:
PUBLIC_BASE_URL takes precedence; otherwise OAuth uses the first configured exact APP_ORIGINS entry. A request’s Host cannot select the OAuth identity. HTTPS is required except for loopback development, such as http://localhost:3000.
The issuer is https://control.example.com/api/auth. The resource and token audience is always https://control.example.com/api/mcp, including connections whose URL selects ?preset=<id>. Query parameters select tools; they do not change the OAuth audience or grant permissions.
Signing keys, clients, consent, authorizations, and refresh credentials live in SQLite. Back up the database and APP_SECRET together; signing keys remain stable across restarts. Each access token lasts five minutes. Offline access uses rotating refresh tokens with a 30-day lifetime for each issued refresh token. Reusing a rotated refresh token fails.
Discovery and connectivity
These endpoints must be reachable without a browser session or localization redirects:
An unauthenticated MCP response returns
401 with WWW-Authenticate metadata so clients can discover the provider. Both the 2026-07-28 protocol and older stateless MCP clients use the same tool catalog. Outbound Streamable HTTP connections negotiate the protocol automatically; configured external SSE servers remain supported.
Choose permissions
New consent selects read access only. Write, destructive, and offline access require explicit selection, and the server grants only scopes requested by the client and selected by the user.
The server owns the classification independently of tool annotations. Unknown tools require all three MCP scopes. A preset narrows the tool selection and cannot grant scopes. Selected descriptors remain discoverable and advertise
aide/requiredScopes in their _meta, allowing clients to request additional consent. Missing scopes return HTTP 403 with an insufficient_scope challenge before a tool handler runs.
OAuth tokens authorize MCP only. They cannot act as application sessions, manage accounts, call GraphQL, use Tools REST, or access an enrolled agent’s run endpoint.
Connect Codex
Add the endpoint and sign in through the browser:Connect ChatGPT
In ChatGPT Plugins, choose Add custom MCP server, enter your public HTTPS MCP URL, and select OAuth authentication. Choose CIMD when offered, create/install the custom connection, and complete the control plane’s sign-in and consent pages. Workspace settings determine whether custom MCP connections are available. Start with read access and test a read tool. Request additional cumulative MCP scopes when the client supports selecting scopes, then explicitly select them in consent. Select offline access if you want refresh-based renewal. See OpenAI’s connection guide and OAuth guidance.Support older clients with DCR
CIMD is the default client identification method. The provider fetches and validates metadata documents through its SSRF-protected Node transport. Dynamic client registration is absent from discovery unless you explicitly set:Manage connected applications
Open System → Connected Applications in the sidebar at/system/connected-applications. You can also open it from Settings. The native iOS app exposes the same page in System navigation and Settings, with refresh, permission details, individual approval revocation, and application-wide disconnect. See Connected Applications for web and native screenshots and operating instructions. The page shows connections for your signed-in account, with:
- The application name and client ID, so you can identify which client you authorized.
- First authorized and Last authorized dates and the number of Current authorizations, including repeated approvals. These cover authorizations that have not been revoked; they do not indicate the application’s last activity or whether its tokens are still valid.
- Granted permissions, their scope names, and what they allow. The list combines permissions across current authorizations; each token retains only the permissions granted when it was issued.
- A Current authorizations table for each application, newest approval first, with its authorization date and individual permissions. This lets you distinguish an earlier read-only approval from a later approval with more access. Revoked authorizations and other users’ approvals do not appear. Authorization records can remain after their tokens expire.
- Offline access details. Without
offline_access, access tokens expire after five minutes and the client may ask you to sign in again. With offline access, the client can renew access using rotating refresh tokens, each with a 30-day lifetime.
Change permissions
To replace a connection’s permissions, disconnect it here, then reconnect from the client’s MCP settings. The client must request additional scopes before you can select them on the consent page. A read-only connection has onlymcp:read; this page cannot add scopes to an existing token.
Revoke one authorization
In an application’s Current authorizations table, choose Revoke beside an approval. Review the application name and approval date, then confirm. Its access tokens, refresh tokens, and pending authorization code stop working immediately. Other approvals for the same application and already-running jobs are unaffected. The revoked row disappears, and the application’s permission summary and authorization count update. Revoking its last current authorization removes the application from the list and clears its saved consent. Use Disconnect when you want to revoke every approval for an application at once.Disconnect an application
Choose Disconnect and confirm the application’s name. This revokes all its current authorizations for your account and immediately blocks its access tokens, refresh families, and outstanding authorization codes. Other users’ connections and API keys are unaffected. Already-running jobs continue under their existing lifecycle. Authorizing again creates a new authorization identifier. Old tokens remain invalid. Deleting an account also immediately blocks its MCP access and refresh attempts. Audit records identify the user and client without recording token values; arguments continue to be stored only as hashes.Roll out and roll back
- Deploy the SDK migration and additive database migration with
MCP_OAUTH_ENABLED=false. - Configure the canonical URL and network reachability, then enable OAuth in a test deployment.
- Verify password and OIDC sign-in, partial consent, read/write/destructive calls, refresh rotation, and disconnects with your target ChatGPT and Codex clients.
- Enable OAuth in production after that verification.
MCP_OAUTH_ENABLED=false and restart to disable OAuth discovery, issuance, and access-token authentication. Existing API-key, session, and enrolled-agent authentication continues working. Keep the additive tables and signing keys for a later rollout.
See Authentication, API reference, and Tools and presets.