quickoauth
← All guides

One MCP server, three connectors: Claude, ChatGPT, Grok

The same OAuth 2.1 server can pass Claude, ChatGPT, and Grok connector validation, provided your discovery, registration, and redirect handling account for how each client differs.

Updated

On this page

Claude, ChatGPT, and Grok all speak MCP and all use OAuth 2.1 with the same discovery machinery: protected-resource metadata (RFC 9728), authorization server metadata (RFC 8414), PKCE, and Streamable HTTP. Build the flow once (the connector checklist and the Auth0 proxy pattern both apply to all three), then handle the per-client differences below.

The differences that actually matter

Claude (claude.ai) ChatGPT Grok (grok.com)
Where users add it Customize → Connectors Settings → Connectors (developer mode) grok.com/connectors → New Connector → Custom
Client identification Dynamic client registration CIMD, DCR, or a predefined client OAuth flow in-app; register via DCR
Redirect URI https://claude.ai/api/mcp/auth_callback and https://claude.com/api/mcp/auth_callback https://chatgpt.com/connector_platform_oauth_redirect Capture from the DCR request (see below)
DCR frequency Per connector setup Once per MCP server connection, then the registered client is reused Per connector setup

Redirect URIs: allow what registers, don’t hardcode

The single most common cross-client failure is a redirect-URI allowlist written for one client. Claude’s callback is not ChatGPT’s (connector_platform_oauth_redirect), and clients occasionally append callback IDs or paths; the full derived redirect_uri must be honored, not just the base host.

The pattern for a DCR endpoint that serves all three:

  1. Accept the registration and store the exact redirect_uris the client sends.
  2. Validate the host against a short allowlist of client origins: claude.ai, claude.com, chatgpt.com, openai.com, grok.com, x.ai.
  3. At /authorize time, verify the requested redirect_uri exactly matches one stored for that client, then let it through.

This also future-proofs you: when a client changes its callback path (it has happened), your server keeps working without a redeploy.

ChatGPT: CIMD is preferred, DCR is the fallback

ChatGPT identifies itself three ways, in order of preference:

  1. Client ID Metadata Documents (CIMD): the client presents a URL as its client_id; your authorization server fetches that URL for the client’s metadata. Support it if your stack can.
  2. Dynamic client registration: used when you advertise a registration_endpoint and CIMD isn’t available. ChatGPT registers once per connection and reuses the client.
  3. A predefined OAuth client: you paste a client ID/secret into the connector configuration. This is the escape hatch when your identity provider can’t do either of the above.

If you built the thin DCR proxy, option 2 works as-is; just add ChatGPT’s redirect to the allowed origins.

Grok: same flow, younger surface

Grok’s “Bring Your Own MCP” (grok.com/connectors → New Connector → Custom) takes your MCP server URL and runs the OAuth flow inside Grok. The discovery sequence is the standard one; the practical differences:

  • Don’t hardcode a Grok callback URL from a blog post (including this one). Log the redirect_uris in your DCR endpoint’s requests the first time you connect, and let the allow-what-registers pattern above handle it.
  • The DNS and TLS pre-flight rules from the failure map apply unchanged: a public hostname and a publicly-trusted certificate, no tunnels with non-public DNS.

One test matrix

For each client, run the same four checks from the checklist: 401 probe, both metadata documents, DCR, then connect for real. Log every request your server sees during the first connection of each client; the logs are the authoritative documentation of what that client actually does, and they’re what you’ll want when one of the three changes behavior.

Next steps

To finish the rollout:

  1. Run the connector checklist once per client: the same four curls, three times.
  2. Connect each client for real and keep the first-connection logs.
  3. If one client fails where the others succeed, debugging connector failures isolates the step.

For the authorization server side, each provider has its own walkthrough: Auth0, Stytch, Supabase, and Hydra. The prompt library has a per-client prompt to paste.

Put it into practice

Add OAuth to a FastMCP server

Point an agent at your FastMCP codebase and have it wire bearer-token auth plus the discovery endpoints MCP clients require.

Preview prompt
Add OAuth 2.1 protection to my FastMCP server so it passes claude.ai's custom connector validation.

Requirements:
1. Every /mcp request without a valid bearer token must return 401 with a WWW-Authenticate header of the form: Bearer resource_metadata="https://MY_DOMAIN/.well-known/oauth-protected-resource"
2. Serve GET /.well-known/oauth-protected-resource returning {"resource": "https://MY_DOMAIN/mcp", "authorization_servers": ["https://MY_DOMAIN"]}
3. Serve GET /.well-known/oauth-authorization-server (RFC 8414) advertising authorization_endpoint, token_endpoint, and registration_endpoint on MY_DOMAIN, with code_challenge_methods_supported including "S256" and grant_types_supported including "authorization_code" and "refresh_token".
4. Validate incoming JWTs: signature against my provider's JWKS, plus iss, exp, and aud claims. Reject failures with 401, never 403.
5. Use FastMCP's auth hooks if the installed version has them; otherwise wrap the ASGI app with middleware. Do not fork or vendor the library.

My identity provider is: [Auth0 / other — fill in]. My domain is: [fill in].

Before writing code, read the current FastMCP version in my lockfile and check what auth support it ships. Show me the endpoint map you intend to implement before touching files, then implement it and give me curl commands to verify all four discovery steps.

Use this site from your agent

Add this URL as a connector in Claude, ChatGPT, or Grok. No sign-in required.

https://quickoauth.com/mcp
Explore more guides →

Search prompts & guides

24 results