Follow Discord
Sweep 25 Sep 2026 · 19:33Z Build v2.1.283 504 read Stable v2.1.274 Latest v2.1.283 Next v2.1.283 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-docs

Authentication for connectors changedconnectors/building/authentication

Nearest release: v2.1.283, published under an hour after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 25 Sep 2026 18:00 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 25 Sep 2026 18:07 UTC.

Upstream edited
Recorded here
Lines+169added
Lines−130removed
From line 1 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits5to this page, all time

### Static credentials in request headers ### Servers with per-customer URLs ## Register Claude as an OAuth client ### DCR and CIMD details ### Anthropic-held client credentials ### Credentials entered at connection time ### PKCE and requested scopes ## OAuth discovery and redirect URIs ### Serve discovery metadata ### Callback URLs ## Token endpoint requirements ### Token refresh ### Endpoint latency ## Enterprise and custom connector authentication ### Enterprise authentication ### Custom connectors ## Next steps ## Servers with per-customer URLs ## Anthropic-held client credentials ## Credentials entered at connection time ## DCR and CIMD details ## Cross-host authorization servers ## Callback URLs ## Token refresh ## Enterprise authentication ## Custom connectors ## Endpoint latency

The whole hunk

from line 1, old and new numbered
/
lines
from line 1
11# Authentication for connectors
22 
3> OAuth and authentication options for MCP servers in Claude
3> Meet Claude's OAuth requirements for remote MCP servers: supported authentication types, client registration, discovery, callback URLs, and token refresh.
44 
5Authentication is the most common source of partner questions. Claude's auth support differs in a few places from the generic MCP specification, so read this page even if you're already familiar with MCP auth.
5A remote MCP server can let Claude in one of three ways:
66 
7* **OAuth 2.0**: each user signs in to your service with their own account when they connect
8* **A static credential**: an organization Owner enters an API key or bearer token once when adding the connector, and Claude sends it in a request header on every call. This is in beta
9* **No authentication**: the server accepts requests from anyone who has its URL
10 
11This page is for developers building a remote MCP server that people use in Claude. The same authentication infrastructure backs claude.ai, Claude Desktop, Claude mobile, Claude Code, and Cowork, so the requirements here apply to all of them.
12 
13If you already know MCP authorization, these are the places where Claude's OAuth client is stricter or more specific than the specification:
14 
15* A `401` is required to start sign-in, and Claude ignores a `WWW-Authenticate` header on a `200` response, as [Serve discovery metadata](#serve-discovery-metadata) describes
16* Claude uses only the first entry in your metadata's `authorization_servers` list, as [Serve discovery metadata](#serve-discovery-metadata) describes
17* Claude uses a Client ID Metadata Document only when your authorization server metadata advertises both values in [DCR and CIMD details](#dcr-and-cimd-details), and otherwise falls back to DCR
18* Claude Code's loopback redirect needs a port-agnostic match for `localhost` as well as `127.0.0.1`, as [Callback URLs](#callback-urls) describes
19* Claude gives your discovery, registration, and token endpoints 10 seconds to respond and refresh requests 30 seconds, as [Endpoint latency](#endpoint-latency) describes
20* A machine-to-machine `client_credentials` grant isn't supported, and [Anthropic-held client credentials](#anthropic-held-client-credentials) are the consent-gated alternative
21 
22<Note>
23 - If some of your tools work without the user's account, see [Lazy authentication](/docs/connectors/building/lazy-authentication) to let people use those right away and sign in only when Claude reaches a tool that needs their account
24 - If you want enterprise users to connect through their organization's SSO without a consent screen, see [Enterprise Managed Auth](/docs/connectors/building/enterprise-managed-auth)
25</Note>
26 
27Use this page to [pick an authentication type](#supported-authentication-types), [register Claude as an OAuth client](#register-claude-as-an-oauth-client), [make discovery and redirects work](#oauth-discovery-and-redirect-uris), and [meet the token endpoint requirements](#token-endpoint-requirements).
28 
729## Supported authentication types
830 
9Claude supports the following authentication types for remote MCP servers. The same infrastructure backs Claude.ai, Claude Desktop, Claude mobile, Claude Code, and Cowork.
31Claude supports the following authentication types for remote MCP servers.
1032 
11| Type | Description | Availability |
12| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
13| `oauth_dcr` | OAuth 2.0 with Dynamic Client Registration ([RFC 7591](https://www.rfc-editor.org/rfc/rfc7591)) | Supported out of the box |
14| `oauth_cimd` | OAuth 2.0 with [Client ID Metadata Document](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents) | Supported out of the box |
15| `oauth_anthropic_creds` | OAuth 2.0 with [Anthropic-held client credentials](#anthropic-held-client-credentials) | Contact `[email protected]` |
16| `custom_connection` | Custom URL or OAuth client credentials [entered at connection time](#credentials-entered-at-connection-time) | Contact `[email protected]` |
17| `static_headers` | Fixed credential (API key or bearer token) entered by an organization administrator as a request header when adding the connector | Beta |
18| `none` | No authentication (authless server) | Supported. An optional partial-auth mode is experimental. |
33| Type | Description | Availability |
34| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
35| `oauth_dcr` | OAuth 2.0 with Dynamic Client Registration ([RFC 7591](https://www.rfc-editor.org/rfc/rfc7591)) | Supported by default |
36| `oauth_cimd` | OAuth 2.0 with [Client ID Metadata Document](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#client-id-metadata-documents) | Supported by default |
37| `oauth_anthropic_creds` | OAuth 2.0 with [Anthropic-held client credentials](#anthropic-held-client-credentials) | Contact `[email protected]` |
38| `custom_connection` | Custom URL or OAuth client credentials [entered at connection time](#credentials-entered-at-connection-time) | Contact `[email protected]` |
39| `static_headers` | Fixed credential (API key or bearer token) entered by an organization Owner as a request header when adding the connector | Beta, for a limited set of organizations |
40| `none` | No authentication (authless server) | Supported by default. To leave some tools open and require sign-in for others, see [Lazy authentication](/docs/connectors/building/lazy-authentication) |
1941 
2042If your server URL varies per customer, read [Servers with per-customer URLs](#servers-with-per-customer-urls) before you pick a type.
2143 
22Static bearer tokens and API keys are supported in beta through request headers (`static_headers`). An organization administrator enters the credential once when adding the connector, and Claude sends it on every request. The credential is shared by the organization rather than pasted per user. Standard header names such as `authorization` and `x-api-key` work for every connector; Anthropic reviews and approves any other header name before administrators can save the connector. See [Authenticating with request headers](/docs/connectors/custom/remote-mcp#authenticating-with-request-headers) for what administrators see and how to document the expected header for them.
44### Static credentials in request headers
2345 
24Tokens or API keys passed in the connector URL (for example, `?token=`, `?apiKey=`, or `?userToken=` query parameters) are **not recommended**. A credential in a URL is a security vulnerability: URLs are routinely recorded in server logs, proxies, and browsing history, so a query-string credential is easy to leak. The MCP authorization specification explicitly [prohibits access tokens in the URI query string](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#token-requirements). Use OAuth or [request headers](/docs/connectors/custom/remote-mcp#authenticating-with-request-headers) instead.
46With a static credential, an organization Owner enters an API key or bearer token once when they add your connector, and Claude sends it in a request header on every call from anyone in that organization. This type is in beta and available to a limited set of organizations. Owners whose organization doesn't have access don't see the **Request headers** section when they add a connector. If your server uses it:
2547 
26## Servers with per-customer URLs
48* **Read the credential from a request header**: standard authentication header names such as `authorization`, `x-api-key`, and `x-auth-token` work for every connector. If you need a different header name, Anthropic has to approve it before Owners can save the connector, so ask `[email protected]` first
49* **Never accept it in the URL**: don't read tokens from query parameters such as `?token=` or `?apiKey=`. URLs end up in server logs, proxies, and browser history, and the MCP authorization specification [prohibits access tokens in the query string](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#token-requirements)
50* **Treat it as the organization's credential, not a person's**: every member's requests carry the same key, so don't use it to identify which user is calling. If your tools need to act as the individual user, use OAuth instead
51* **Tell Owners what to enter**: document the header name and where they get the key. [Authenticate with request headers](/docs/connectors/custom/add-unlisted#authenticate-with-request-headers) shows what the Owner sees when adding the connector
2752 
28The submission portal's **Connection** step asks how users reach your server. There are three choices:
53### Servers with per-customer URLs
2954 
30* **Universal URL**: every user connects to the same URL.
31* **Multiple URLs**: you list a fixed set of labeled URLs, such as one per region. Users pick one when they connect.
32* **URL pattern**: you give an anchored regular expression that every customer's URL must match, such as `^https://[a-z0-9-]+\.mcp\.example\.com/mcp$`. Each user enters their own URL when they connect, and Claude accepts it only if it matches.
55The submission portal's **Connection** step asks how users reach your server, and you pick one of these options:
3356 
34Keep the host part of a URL pattern lowercase, because Claude lowercases the host of the URL the user enters before checking it.
57* **Universal URL**: every user connects to the same URL
58* **Multiple URLs**: you list a fixed set of labeled URLs, such as one per region, and users pick one when they connect
59* **URL pattern**: you give an anchored regular expression that every customer's URL must match, such as `^https://[a-z0-9-]+\.mcp\.example\.com/mcp$`. Each user enters their own URL when they connect, and Claude accepts it only if it matches. Keep the host part of the pattern lowercase, because Claude lowercases the host of the URL the user enters before checking it
3560 
3661Listings with **Multiple URLs** or a **URL pattern** take longer to review.
3762 
38You choose the URL option and the authentication type separately, but the URL option limits which authentication types work. Request headers (`static_headers`) are set up by the organization administrator who adds the connector and aren't covered by this table.
63You choose the URL option and the authentication type separately, but the URL option limits which authentication types work. The table shows which combinations work. Request headers (`static_headers`) are set up by the organization Owner who adds the connector and aren't covered here.
3964 
4065| Type | Universal URL | Multiple URLs | URL pattern |
4166| ----------------------- | ------------- | ------------- | ----------- |
from line 70
4570| `custom_connection` | Yes | No | Yes |
4671| `none` | Yes | Yes | Yes |
4772 
48Anthropic-held client credentials are tied to exact server URLs, and a URL pattern matches URLs Anthropic doesn't know in advance. Credentials entered at connection time can't be combined with **Multiple URLs**.
73For a URL pattern, use these authentication types in order of preference:
4974 
50For a URL pattern, use these in order of preference:
51 
52751. Client ID Metadata Document (CIMD). Every customer's authorization server must advertise both CIMD values listed in [DCR and CIMD details](#dcr-and-cimd-details).
53762. [Dynamic Client Registration](#dcr-and-cimd-details) (DCR). Every customer's authorization server must expose a `registration_endpoint`.
54773. [Credentials entered at connection time](#credentials-entered-at-connection-time), if your customers' authorization servers support neither. Each customer then has to create an OAuth client for Claude themselves.
5578 
56## Anthropic-held client credentials
79## Register Claude as an OAuth client
5780 
58A pure machine-to-machine `client_credentials` grant—where a server-to-server token is issued with no user in the loop—is **not supported**. Every connection requires user consent.
81For the OAuth types, Claude needs a client identity at your authorization server. Claude can register itself through DCR or identify itself with a CIMD, Anthropic can hold a client you create, or each customer can enter their own client when they connect.
5982 
60`oauth_anthropic_creds` is the consent-gated alternative. The flow works like this:
83### DCR and CIMD details
6184 
621. You create an OAuth `client_id` and `client_secret` in your own authorization server and send them to Anthropic.
632. Anthropic stores those credentials securely and associates them with your directory entry.
643. When a user connects your server, they go through a standard OAuth consent screen.
654. After consent, Anthropic uses the stored client credentials to complete the token exchange on the user's behalf.
85If your authorization server doesn't support DCR, meaning it exposes no `registration_endpoint`, you have these options:
6686 
67This gives you a stable, registered OAuth client without requiring DCR or CIMD on your end, while keeping the user-consent step. Anthropic stores your credentials securely and uses them only for token exchange on behalf of consenting users; they are shared across the hosted Claude surfaces (Claude.ai web, Desktop, mobile, and Cowork). Claude Code runs its own OAuth flow on the user's machine and identifies itself with its own [Client ID Metadata Document](#callback-urls), so it does not use Anthropic-held credentials. Claude Managed Agents uses a separate credential set.
87* Expose a `registration_endpoint`
88* Support CIMD instead. Claude selects CIMD only when your authorization server metadata advertises both `"client_id_metadata_document_supported": true` and `"none"` in `token_endpoint_auth_methods_supported`. The second is required because Claude's CIMD client authenticates as a public client at your token endpoint. If either is missing, Claude falls back to DCR. See [lazy authentication](/docs/connectors/building/lazy-authentication#identify-claude-with-a-client-id-metadata-document) for a worked CIMD example
89* Switch to `oauth_anthropic_creds`, if your listing doesn't use a URL pattern
6890 
69Anthropic-held credentials are bound to the authorization server that issued them. If you migrate to a new authorization server, email `[email protected]` with the new `client_id` and `client_secret` before cutting over. CIMD-based connectors don't have this constraint — a CIMD `client_id` is a self-hosted URL, so it works against any authorization server that fetches it.
91If your server URL varies per customer and DCR isn't available, CIMD is the recommended path. Every customer's authorization server must advertise both CIMD values. Otherwise Claude falls back to DCR for that customer, which needs a `registration_endpoint`.
7092 
71<Note>
72 Anthropic-held credentials are also tied to exact server URLs. They can't be used with a URL pattern, where each customer enters their own server URL. See [Servers with per-customer URLs](#servers-with-per-customer-urls) for the alternatives.
73</Note>
93For servers expecting high traffic from the directory, prefer CIMD or `oauth_anthropic_creds` over DCR. DCR causes Claude to register a new client on every fresh connection, which can result in very large numbers of registered clients on your authorization server. CIMD and Anthropic-held credentials avoid the registration call entirely.
7494 
75To use this flow, email `[email protected]` with your `client_id` and secret.
95### Anthropic-held client credentials
7696 
77## Credentials entered at connection time
97With `oauth_anthropic_creds`, you create an OAuth client for Claude in your own authorization server and Anthropic holds its credentials, so Claude has a stable, registered client without DCR or CIMD on your end. Users still go through your standard OAuth consent screen when they connect. A pure machine-to-machine `client_credentials` grant, where a token is issued with no user in the loop, isn't supported.
7898 
79`custom_connection` (**Custom URL or credentials at connection time** in the submission portal) asks each customer for the OAuth client that Claude should use, instead of Claude registering one or Anthropic holding one.
99To use this type:
80100 
101* **Create a confidential client**: create a `client_id` and `client_secret` for Claude in your authorization server
102* **Send the credentials to Anthropic**: email `[email protected]` with the `client_id` to set up Anthropic-held credentials. Anthropic replies with how to transfer the client secret securely, so don't put the secret in the email. Anthropic uses the credentials only for token exchange on behalf of consenting users
103* **Plan for Claude Code separately**: the hosted Claude apps, which are claude.ai on the web, Desktop, mobile, and Cowork, share this client. Claude Code doesn't use it: it runs its own OAuth flow on the user's machine, identifies itself with its own [Client ID Metadata Document](#callback-urls), and redirects to a loopback callback URL
104* **Tell Anthropic before you migrate authorization servers**: the credentials are bound to the authorization server that issued them. Email `[email protected]` with the new `client_id` before cutting over, and transfer the new secret the same way as the first
105* **Don't combine it with a URL pattern**: the credentials are tied to exact server URLs, so they can't be used where each customer enters their own server URL. See [Servers with per-customer URLs](#servers-with-per-customer-urls) for the alternatives
106 
107### Credentials entered at connection time
108 
109`custom_connection`, labeled **Custom URL or credentials at connection time** in the submission portal, asks each customer for the OAuth client that Claude should use, instead of Claude registering one or Anthropic holding one.
110 
81111Each customer must be able to create an OAuth client in your product, which usually means an administrator sets up the connector for their organization. If your customers can't create OAuth clients, use CIMD or DCR instead.
82112 
83113When a user adds your connector, Claude shows a form with these fields:
84114 
85* **Server URL**, if your listing uses a URL pattern. Claude accepts the URL only if it matches the pattern.
86* **OAuth client ID** and **OAuth client secret**. You choose which of the two to ask for, and whether each is required or optional.
115* **Server URL**, if your listing uses a URL pattern. Claude accepts the URL only if it matches the pattern
116* **OAuth client ID** and **OAuth client secret**. You choose which of the two to ask for, and whether each is required or optional
87117 
88118The form links to pages you supply: one for where the customer finds their server URL, and one for how they get the credentials. The credentials page must explain how a customer creates an OAuth client for Claude in your product and registers the redirect URI `https://claude.ai/api/mcp/auth_callback`.
89119 
90If a user leaves an optional client secret blank, Claude uses the client ID as a public client. If a user leaves an optional client ID blank, Claude falls back to the same order as any other listing: Anthropic-held credentials for that URL if Anthropic holds any, then CIMD, then DCR. See [DCR and CIMD details](#dcr-and-cimd-details).
120If a user leaves an optional client secret blank, Claude uses the client ID as a public client. If a user leaves an optional client ID blank, Claude falls back to its standard order: Anthropic-held credentials for that URL if Anthropic holds any, then CIMD, then DCR. See [DCR and CIMD details](#dcr-and-cimd-details).
91121 
92If you later stop asking for credentials, connections already made with user-entered credentials keep using them. An organization gets the new behavior only once no one in it still has the connector. The next person to add it starts fresh.
122If you later stop asking for credentials, connections already made with user-entered credentials keep using them, and an organization keeps the form until no one in it still has the connector.
93123 
94124To use this flow, email `[email protected]` with which fields you need, whether each is required, and the page each one should link to.
95125 
96## DCR and CIMD details
126### PKCE and requested scopes
97127 
98If your authorization server does **not** expose a `registration_endpoint` (i.e., does not support DCR), you have several options:
128Claude includes a [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) `code_challenge` with `code_challenge_method=S256` on every authorization request, regardless of which registration mechanism it uses. Your authorization server must support S256 PKCE. The [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-code-protection) also requires it to advertise `"code_challenge_methods_supported": ["S256"]` in its metadata so spec-compliant clients can verify support before starting the flow.
99129 
100* Expose a `registration_endpoint`
101* Support CIMD instead. Claude selects CIMD only when your authorization server metadata advertises **both** `"client_id_metadata_document_supported": true` **and** `"none"` in `token_endpoint_auth_methods_supported` — the second is required because Claude's CIMD client authenticates as a public client at your token endpoint. If either is missing, Claude falls back to DCR. See [lazy authentication](/docs/connectors/building/lazy-authentication#identify-the-client-with-cimd) for a worked CIMD example.
102* Switch to `oauth_anthropic_creds`, if your listing doesn't use a URL pattern
130To control which scopes Claude requests, include a `scope` parameter in the `WWW-Authenticate` header on your `401` response. If you don't, Claude requests the scopes your protected resource metadata advertises in `scopes_supported`. Claude also appends `offline_access` when your authorization server metadata lists it in `scopes_supported`, to obtain a refresh token. See [lazy authentication](/docs/connectors/building/lazy-authentication#answer-a-protected-call-with-401-before-the-mcp-sdk-runs) for the canonical `401` shape.
103131 
104If your server URL varies per customer and DCR isn't available, CIMD is the recommended path. Every customer's authorization server must advertise both values above. Otherwise Claude falls back to DCR for that customer, which needs a `registration_endpoint`.
132## OAuth discovery and redirect URIs
105133 
106For servers expecting high traffic from the directory, prefer **CIMD or `oauth_anthropic_creds` over DCR**. DCR causes Claude to register a new client on every fresh connection, which can result in very large numbers of registered clients on your authorization server. CIMD and Anthropic-held credentials avoid the registration call entirely.
134Claude finds your authorization server by reading your protected resource metadata, then sends the user back to a redirect URI that depends on which Claude surface they're using. Both steps have requirements your server and authorization server must meet.
107135 
108Claude includes a [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) `code_challenge` with `code_challenge_method=S256` on every authorization request, regardless of which registration mechanism it uses. Your authorization server must support S256 PKCE, and the [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-code-protection) requires it to advertise `"code_challenge_methods_supported": ["S256"]` in its metadata so spec-compliant clients can verify support before starting the flow.
136### Serve discovery metadata
109137 
110To control which scopes Claude requests, include a `scope` parameter in the `WWW-Authenticate` header on your `401` response. If you don't, Claude requests the scopes your protected resource metadata advertises in `scopes_supported`. Claude also appends `offline_access` when your authorization server metadata lists it in `scopes_supported`, to obtain a refresh token. See [lazy authentication](/docs/connectors/building/lazy-authentication#return-401-not-a-tool-error) for the canonical `401` shape.
138Claude locates your authorization server through your [protected resource metadata](https://www.rfc-editor.org/rfc/rfc9728) document, and the authorization server it names can be on a different host from your MCP server. For Claude to find and use that document:
111139 
112## Cross-host authorization servers
140* **Return `401` with a `resource_metadata` pointer**: answer unauthenticated requests with a `401` whose `WWW-Authenticate` header points at the document
141* **Make `resource` match your MCP server URL exactly**: the document's `resource` field must equal the URL as the user enters it in Claude, including any path component
142* **List your primary issuer first**: the document's `authorization_servers` field must list your authorization server's issuer URL. If you list more than one, Claude uses the first entry and doesn't fall back to later entries
143* **Serve authorization server metadata Claude can reach**: your authorization server must serve its own discovery metadata, either [RFC 8414](https://www.rfc-editor.org/rfc/rfc8414) authorization server metadata or [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html), at its `/.well-known/` paths. That host must also be reachable from Anthropic's [published egress range](https://platform.claude.com/docs/en/api/ip-addresses). Discovery requests to the authorization server come from the same IP range as requests to your MCP server, so a WAF in front of your identity provider can break the flow even when your MCP server is reachable
113144 
114A cross-host authorization server doesn't need anything special on its own. The `authorization_servers` field in your [protected resource metadata](https://www.rfc-editor.org/rfc/rfc9728) tells Claude where the authorization server is, and Claude resolves it regardless of which host it points at. The thing to get right is making sure Claude can find the protected resource metadata in the first place.
145The `401` response carries the pointer in its `WWW-Authenticate` header. This is the same handshake described in [Answer a protected call with 401 before the MCP SDK runs](/docs/connectors/building/lazy-authentication#answer-a-protected-call-with-401-before-the-mcp-sdk-runs):
115146 
116**Always return a `401` with a `WWW-Authenticate` header** whose `resource_metadata` parameter points at your protected resource metadata document — the same handshake described in [Return 401, not a tool error](/docs/connectors/building/lazy-authentication#return-401-not-a-tool-error):
117 
118147```http theme={null}
119148HTTP/1.1 401 Unauthorized
120149WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
121150```
122151 
123The `401` status is required — Claude does not honor a `WWW-Authenticate` header on a `200` response — and the `resource_metadata` URL doesn't have to be on the MCP server's origin; it can be any HTTPS location that serves the JSON document. That's what makes this the most reliable path for hosting platforms that can't serve `/.well-known/*` at the root, such as Supabase Edge Functions, Cloudflare Workers without a `/.well-known/*` route, and Lambda function URLs that only route a path prefix.
152The `401` status is required, because Claude doesn't honor a `WWW-Authenticate` header on a `200` response. The `resource_metadata` URL doesn't have to be on the MCP server's origin. It can be any HTTPS location that serves the JSON document, which makes this the most reliable path on serverless or edge platforms that only route requests under a path prefix and can't serve `/.well-known/*` at the root.
124153 
125If your `401` doesn't include a `resource_metadata` pointer, Claude can still infer the metadata location by probing your MCP server's origin: `/.well-known/oauth-protected-resource/<your-mcp-path>` first, then `/.well-known/oauth-protected-resource`. Treat this as a fallback — it only works when your platform serves `/.well-known/*` paths, and it adds round-trips to every connection.
154If your `401` doesn't include a `resource_metadata` pointer, Claude can still infer the metadata location by probing your MCP server's origin: `/.well-known/oauth-protected-resource/<your-mcp-path>` first, then `/.well-known/oauth-protected-resource`. Treat this as a fallback, because it works only when your platform serves `/.well-known/*` paths.
126155 
127Whichever way Claude finds the document:
128 
129* The protected resource metadata document's `resource` field must match your MCP server URL exactly as the user enters it in Claude, including any path component.
130* The metadata's `authorization_servers` field must list your authorization server's issuer URL. If you list more than one, Claude uses the first entry and does not fall back to later entries — list your primary issuer first.
131* Your authorization server must serve its own discovery metadata — [RFC 8414](https://www.rfc-editor.org/rfc/rfc8414) authorization server metadata or [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) — at its `/.well-known/` paths, and that host must also be reachable from Anthropic's [published egress range](https://platform.claude.com/docs/en/api/ip-addresses). Discovery requests to the authorization server come from the same IP range as requests to your MCP server, so a WAF in front of your identity provider can break the flow even when your MCP server is reachable.
132 
133156<Note>
134 If your authorization server is Microsoft Entra ID, you must also register the MCP server URL as an Application ID URI on your Entra app registration, or the token request fails with `AADSTS9010010`. By default, Entra accepts that URL as an Application ID URI only when it's on a domain your tenant has verified (see [Microsoft's identifier URI restrictions](https://learn.microsoft.com/en-us/entra/identity-platform/identifier-uri-restrictions)), so an MCP server on a platform hostname such as `*.azurewebsites.net` needs a custom domain first. See [the troubleshooting entry](/docs/connectors/building/troubleshooting#microsoft-entra-id-rejects-the-resource-value) for the fix.
157 If your authorization server is Microsoft Entra ID, you must also register the MCP server URL as an Application ID URI on your Entra app registration, or the token request fails with `AADSTS9010010`. By default, Entra accepts that URL as an Application ID URI only when it's on a domain your tenant has verified, as described in [Microsoft's identifier URI restrictions](https://learn.microsoft.com/en-us/entra/identity-platform/identifier-uri-restrictions), so an MCP server on a platform hostname such as `*.azurewebsites.net` needs a custom domain first. See [the troubleshooting entry](/docs/connectors/building/troubleshooting#microsoft-entra-id-rejects-the-resource-value) for the fix.
135158</Note>
136159 
137160If you control both hosts, an alternative is to serve the MCP endpoint and the authorization server behind a single custom domain that can route both `/.well-known/*` and your MCP path.
from line 163
140163 A common symptom of a discovery failure is that your MCP server receives the initial request but your authorization server sees no traffic at all. That happens when neither path works: there's no `WWW-Authenticate: Bearer resource_metadata=…` header on your `401`, and the well-known paths on your MCP server's origin return `404`. With no metadata to read, Claude never learns where your authorization server is, and the connection fails with "Couldn't reach the MCP server." See [troubleshooting](/docs/connectors/building/troubleshooting) for the full diagnostic flow.
141164</Tip>
142165 
143## Callback URLs
166### Callback URLs
144167 
145For the hosted Claude surfaces (Claude.ai web, Desktop, mobile, and Cowork), register the following redirect URI:
168The redirect URI Claude sends depends on which surface the user connects from: the hosted Claude apps use one fixed callback URL and Claude Code uses a loopback redirect. Your authorization server must accept both.
146169 
147```
170For the hosted Claude apps, which are claude.ai on the web, Desktop, mobile, and Cowork, register exactly this redirect URI:
171 
172```text theme={null}
148173https://claude.ai/api/mcp/auth_callback
149174```
150175 
151**Claude Code** is a native client and uses an RFC 8252 loopback redirect on an ephemeral port — for example:
176For Claude Code, accept a loopback redirect on any port. Claude Code is a native client and uses an [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252) loopback redirect on an ephemeral port that varies per session, such as:
152177 
153```
178```text theme={null}
154179http://localhost:3118/callback
155180```
156181 
157The port varies per session. Claude Code declares `http://localhost/callback` and `http://127.0.0.1/callback` in its [Client ID Metadata Document](https://claude.ai/oauth/claude-code-client-metadata), so your authorization server must accept both with the port component ignored. [RFC 8252 section 7.3](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) requires this for the IP-literal form (`127.0.0.1`); apply the same port-agnostic match to `localhost` so Claude Code works, even though RFC 8252 section 8.3 discourages `localhost`. See [lazy authentication](/docs/connectors/building/lazy-authentication) for implementation details.
182Claude Code declares `http://localhost/callback` and `http://127.0.0.1/callback` in its [Client ID Metadata Document](https://claude.ai/oauth/claude-code-client-metadata), so match both with the port component ignored. [RFC 8252 section 7.3](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) requires this for the IP-literal form (`127.0.0.1`). Apply the same port-agnostic match to `localhost` so Claude Code works, even though RFC 8252 section 8.3 discourages `localhost`. See [lazy authentication](/docs/connectors/building/lazy-authentication#match-loopback-redirect-uris-without-the-port) for implementation details.
158183 
159A Client ID Metadata Document can't prevent loopback impersonation on its own — any local process can bind a port and claim to be the legitimate client. The [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#localhost-redirect-uri-risks) requires authorization servers to display the redirect URI hostname clearly on the consent screen and recommends an extra warning when the only registered redirect URIs are loopback addresses.
184On your consent screen, display the redirect URI's hostname clearly. The [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#localhost-redirect-uri-risks) requires this and recommends an extra warning when the only registered redirect URIs are loopback addresses, because any local process can bind a port and claim to be the client.
160185 
161## Token refresh
186## Token endpoint requirements
162187 
163Claude refreshes tokens **reactively on a 401 response**, with a proactive refresh up to five minutes before the stored expiry. To avoid refresh failures:
188Your token endpoint handles Claude's initial code exchange and every later refresh, and Claude enforces response-time limits on it and on your other OAuth endpoints.
164189 
165* Return RFC 6749-compliant error codes (`invalid_grant`, not `invalid_request` or a custom code) when a refresh token is no longer valid
166* Rotate refresh tokens for public-client connections. DCR and CIMD register Claude as a public client, and the [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#token-theft) adopts OAuth 2.1's requirement to rotate or sender-constrain refresh tokens for public clients. If you rotate, return the new refresh token in the same response that invalidates the old one.
190### Token refresh
167191 
168Your `/token` endpoint must accept `Content-Type: application/x-www-form-urlencoded` per [RFC 6749 section 4.1.3](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3). Claude sends both the initial token exchange and refresh requests with this content type. Some web frameworks default to JSON-only body parsing—if your endpoint returns `415 Unsupported Media Type`, register a form-urlencoded body parser. Dynamic client registration (`/register`) uses `application/json` per [RFC 7591 section 3.1](https://www.rfc-editor.org/rfc/rfc7591#section-3.1), so don't assume the same parser works for both.
192Claude refreshes tokens reactively on a `401` response, and proactively up to five minutes before the stored expiry. To avoid refresh failures:
169193 
170## Enterprise authentication
194* Return RFC 6749-compliant error codes when a refresh token is no longer valid: `invalid_grant`, not `invalid_request` or a custom code
195* Rotate refresh tokens for public-client connections. DCR and CIMD register Claude as a public client, and the [MCP authorization spec](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#token-theft) adopts OAuth 2.1's requirement to rotate or sender-constrain refresh tokens for public clients. If you rotate, return the new refresh token in the same response that invalidates the old one
171196 
172<Note>
173 Organizations using SSO can also connect their users to your server without an interactive OAuth consent step, using an identity assertion signed by their identity provider. See [Enterprise Managed Auth](./enterprise-managed-auth) for what your authorization server needs to support.
174</Note>
197Your `/token` endpoint must accept `Content-Type: application/x-www-form-urlencoded` per [RFC 6749 section 4.1.3](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3). Claude sends both the initial token exchange and refresh requests with this content type. Some web frameworks default to JSON-only body parsing, so if your endpoint returns `415 Unsupported Media Type`, register a form-urlencoded body parser. Dynamic client registration at `/register` uses `application/json` per [RFC 7591 section 3.1](https://www.rfc-editor.org/rfc/rfc7591#section-3.1), so don't assume the same parser works for both.
175198 
176Most directory connectors use a **single shared OAuth application per connector**. Enterprise customers connect to the same OAuth app as everyone else, and access is scoped by the user's own permissions on your service. For a listing that asks for [credentials entered at connection time](#credentials-entered-at-connection-time), each customer supplies its own OAuth client instead. Custom connectors are different: an admin can supply their own OAuth client credentials when adding the connector, which scopes the OAuth client to that organization. See [custom connectors](#custom-connectors).
199### Endpoint latency
177200 
178## Custom connectors
201Claude waits up to 10 seconds for a response from your OAuth discovery, registration, and token endpoints, and up to 30 seconds for refresh token requests. If no response arrives within that window, Claude treats the flow as a failure, even if your server eventually completes the request. Aim well under these limits. A token endpoint that takes several seconds to respond produces intermittent connection failures for users.
179202 
180When a user adds a custom connector by URL, the OAuth Client Secret field is **optional**. Supply it only if your authorization server requires confidential-client authentication.
203If your token endpoint depends on slow downstream calls, return the HTTP response headers and body without buffering behind upstream work, and check that any reverse proxy, API gateway, or WAF in front of the endpoint isn't holding the response.
181204 
182Supplying your own pre-registered client ID (and secret, if your server requires one) as static client credentials is a good option when you want a stable OAuth client per organization: it avoids dynamic client registration entirely, and the credentials are scoped to the organization that entered them.
205## Enterprise and custom connector authentication
183206 
184For servers that authenticate with a fixed API key or token rather than OAuth, request header authentication (`static_headers`) is available in beta. See [Supported authentication types](#supported-authentication-types) above and [Authenticating with request headers](/docs/connectors/custom/remote-mcp#authenticating-with-request-headers) for what administrators see.
207You don't need a separate OAuth application for each enterprise customer, but a customer's organization can supply its own OAuth client or connect its users through SSO without a consent screen.
185208 
186## Endpoint latency
209### Enterprise authentication
187210 
188Claude waits up to **10 seconds** for a response from your OAuth discovery, registration, and token endpoints, and up to **30 seconds** for refresh token requests. If no response arrives within that window the flow is treated as a failure, even if your server eventually completes the request. Aim well under these limits; a token endpoint that takes several seconds to respond will produce intermittent connection failures for users.
211Unless your listing asks for credentials at connection time, enterprise customers connect through the same OAuth application as everyone else. Scope what each user can reach with your service's own per-user permissions rather than with a per-tenant OAuth app. These cases work differently:
189212 
190If your token endpoint depends on slow downstream calls, return the HTTP response headers and body without buffering behind upstream work, and check that any reverse proxy, API gateway, or WAF in front of the endpoint isn't holding the response.
213* **SSO without a consent screen**: organizations using SSO can connect their users with an identity assertion signed by their identity provider instead of an interactive OAuth consent step. See [Enterprise Managed Auth](/docs/connectors/building/enterprise-managed-auth) for what your authorization server needs to support
214* **Customer-supplied OAuth client**: a listing that asks for [credentials entered at connection time](#credentials-entered-at-connection-time) has each customer supply its own OAuth client, and an administrator who adds your server as a [custom connector](#custom-connectors) can enter one too
191215 
216### Custom connectors
217 
218When a customer adds your server by URL as a custom connector, Claude identifies itself to your authorization server in one of three ways: with the Client ID Metadata Document that Anthropic hosts for it, through Dynamic Client Registration, or with an OAuth client ID the customer registered with you and enters in the dialog. [Choose authentication settings](/docs/connectors/custom/add-unlisted#choose-authentication-settings) shows the dialog the customer sees. On your side:
219 
220* **Support CIMD or DCR**: customers can then connect without registering a client with you first. See [DCR and CIMD details](#dcr-and-cimd-details) for what each needs from your authorization server
221* **Require a client secret only for confidential clients**: the secret is optional in the dialog, so customers need one only if your authorization server requires confidential-client authentication
222* **Use request headers for a fixed API key or token**: for servers that authenticate with a fixed credential rather than OAuth, request header authentication (`static_headers`) is available in beta. See [Supported authentication types](#supported-authentication-types) and [Authenticate with request headers](/docs/connectors/custom/add-unlisted#authenticate-with-request-headers) for what Owners see
223 
192224## Network reference
193225 
194226Anthropic's outbound traffic to your server originates from `160.79.104.0/21`. See the [IP address reference](https://platform.claude.com/docs/en/api/ip-addresses) if you need to allowlist Anthropic for conditional access or firewall rules.
227 
228## Next steps
229 
230* [Lazy authentication](/docs/connectors/building/lazy-authentication): let people use the tools that don't need their account right away, and ask them to sign in only when Claude reaches one that does
231* [Enterprise Managed Auth](/docs/connectors/building/enterprise-managed-auth): accept identity assertions from enterprise SSO instead of an interactive consent step
232* [Test your connector](/docs/connectors/building/testing): add your server as a custom connector and exercise the auth flow
233* [Troubleshoot your connector](/docs/connectors/building/troubleshooting): diagnose "Couldn't reach the MCP server" and "Authorization with the MCP server failed"
195234 
Feedback