Summary
Adding a self-hosted OAuth 2.1 + DCR MCP server as a custom connector fails consistently in both Claude Desktop (v1.3883.0) and claude.ai web. The error shown is:
Couldn't reach the MCP server. You can check the server URL and verify the server is running. If this persists, share this reference with support: ofid_c58995a431270861
Our edge/ingress logs show zero inbound requests from Anthropic on every Connect click — not to /.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server, /oauth/register, /oauth/authorize, nor /mcp. The broker appears to error out inside Anthropic's start step before dispatching any HTTP request to the advertised server. This is the same symptom pattern as #111, #199, and #214.
The same server connects and works end-to-end in Cursor (full DCR + PKCE + auth code + refresh token + tool calls) and in Postman (manual OAuth 2.1 flow), confirming the server and its OAuth layer are fully functional.
Reference IDs (for backend lookup)
ofid_c58995a431270861 — latest failed Connect attempt (claude.ai web, ~2026-04-24 20:30 UTC, same result on Desktop).
request_id req_011CaNmqAmgXYeGpumG8bDcZ — related Claude Desktop startup 403 (separate scope entitlement issue, included in case it's relevant).
- Server URL, account UUID, org UUID intentionally omitted from this public issue — happy to share privately with the Anthropic team via support or a DM. The
ofid_ above should be enough to look up the failed flow server-side.
Reproduction
- claude.ai web → Settings → Connectors → Add custom connector.
- Paste the MCP server URL (self-hosted OAuth 2.1 + DCR + PKCE S256 endpoint). Advanced settings blank.
- Click Add → connector appears in list.
- Click Connect.
- Browser never redirects to the server's
/oauth/authorize endpoint. Claude shows the "Couldn't reach the MCP server" toast with the ofid_ reference above.
- Same steps reproduce identically in Claude Desktop 1.3883.0.
Evidence the server is healthy and spec-compliant
All probes run from the public internet with User-Agent: Claude-User (+https://docs.anthropic.com/claude-code) — the exact UA we believe Anthropic's broker uses. We intentionally tested this to rule out WAF / bot-UA blocking (the resolution in #76 and #64). The server host is redacted as <dev-host> in the samples below.
1. /mcp returns a proper 401 with RFC 9728 WWW-Authenticate
HTTP/2 401
content-type: application/json
www-authenticate: Bearer realm="https://<dev-host>/mcp",
resource_metadata="https://<dev-host>/.well-known/oauth-protected-resource/mcp",
error="missing_token"
{"error":"missing_token","error_description":"Authentication required"}
Also passes identically with UAs curl/*, Claude-User, ClaudeBot, and anthropic-ai — no UA-based WAF block.
2. Protected Resource Metadata (RFC 9728)
GET /.well-known/oauth-protected-resource/mcp — 200:
{
"resource": "https://<dev-host>/mcp",
"authorization_servers": ["https://<dev-host>"],
"scopes_supported": ["mcp:read", "mcp:write"],
"bearer_methods_supported": ["header"]
}
3. Authorization Server Metadata (RFC 8414)
GET /.well-known/oauth-authorization-server — 200:
{
"issuer": "https://<dev-host>",
"authorization_endpoint": "https://<dev-host>/oauth/authorize",
"token_endpoint": "https://<dev-host>/oauth/token",
"registration_endpoint": "https://<dev-host>/oauth/register",
"scopes_supported": ["mcp:read", "mcp:write"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"token_endpoint_auth_methods_supported": ["none"],
"code_challenge_methods_supported": ["S256"]
}
4. Dynamic Client Registration works for both claude.ai and claude.com callbacks
POST /oauth/register with redirect_uris: ["https://claude.ai/api/mcp/auth_callback"] returns 201 with a valid client_id, correct echo of redirect_uris, grant_types: ["authorization_code","refresh_token"], response_types: ["code"], token_endpoint_auth_method: "none".
Same request with redirect_uris: ["https://claude.com/api/mcp/auth_callback"] also returns 201 (we accept both per the sunpeak guide note about dual-domain callbacks).
5. Server-side OAuth flow is end-to-end verified in other clients
- Cursor: full DCR → authorize → token → authenticated
/mcp → tool calls all work.
- Postman: manual OAuth 2.1 auth-code flow (PKCE,
client_credentials_in_body) completes successfully and returns valid JWTs.
What our pod logs show during a failed Connect
With kubectl logs -f on the MCP pod running during a Connect attempt: no inbound requests at all during the attempt window. No /.well-known/*, no /oauth/*, no /mcp. Combined with the WAF tests above, this rules out our edge as the cause — the broker isn't emitting the request.
Hypothesis
Given:
- Our server passes every OAuth 2.1 / MCP spec requirement (PRM, AS metadata, DCR,
WWW-Authenticate with resource_metadata, PKCE S256, authorization_code + refresh_token).
- Our server works end-to-end in Cursor and Postman.
- No request ever reaches our edge during a Claude Connect attempt.
- Multiple UAs including
Claude-User pass our WAF cleanly.
...the failure is inside the Anthropic-side broker start step — matching the exact pattern of #111 (fix was a server-side allowlist on the Anthropic backend) and #199 / #214.
Environment
- Claude Desktop: 1.3883.0 (CCD 2.1.111), macOS 15 (Darwin 25.x), Apple Silicon.
- claude.ai web: tested on Chrome, reproduces in incognito with fresh cookies.
- Server: FastAPI + FusionAuth-backed OAuth 2.1 behind AWS ALB + AWS WAF (
AWSManagedRulesCommonRuleSet). Strictly follows RFC 7591 DCR, RFC 8414, RFC 9728, and the MCP 2025-06-18 spec.
- Tested cleanly after full Claude Desktop + claude.ai cache wipe (filesystem, localStorage, cookies, IDB, Redis-side OAuth state all cleared). Post-wipe behaviour is identical.
Ask
@crondinini-ant — could you look up ofid_c58995a431270861 against the broker-side logs? Based on the identical signature to #111 / #214, we suspect the start step is rejecting our server (possibly on a default-scope or URL-validation step) before dispatching. If so, an allowlist exception for our dev host would unblock us while the root cause is investigated. I can share the hostname + account/org UUIDs privately on request. Thanks!
Summary
Adding a self-hosted OAuth 2.1 + DCR MCP server as a custom connector fails consistently in both Claude Desktop (v1.3883.0) and claude.ai web. The error shown is:
Our edge/ingress logs show zero inbound requests from Anthropic on every
Connectclick — not to/.well-known/oauth-protected-resource,/.well-known/oauth-authorization-server,/oauth/register,/oauth/authorize, nor/mcp. The broker appears to error out inside Anthropic'sstartstep before dispatching any HTTP request to the advertised server. This is the same symptom pattern as #111, #199, and #214.The same server connects and works end-to-end in Cursor (full DCR + PKCE + auth code + refresh token + tool calls) and in Postman (manual OAuth 2.1 flow), confirming the server and its OAuth layer are fully functional.
Reference IDs (for backend lookup)
ofid_c58995a431270861— latest failed Connect attempt (claude.ai web, ~2026-04-24 20:30 UTC, same result on Desktop).request_id req_011CaNmqAmgXYeGpumG8bDcZ— related Claude Desktop startup 403 (separate scope entitlement issue, included in case it's relevant).ofid_above should be enough to look up the failed flow server-side.Reproduction
/oauth/authorizeendpoint. Claude shows the "Couldn't reach the MCP server" toast with theofid_reference above.Evidence the server is healthy and spec-compliant
All probes run from the public internet with
User-Agent: Claude-User (+https://docs.anthropic.com/claude-code)— the exact UA we believe Anthropic's broker uses. We intentionally tested this to rule out WAF / bot-UA blocking (the resolution in #76 and #64). The server host is redacted as<dev-host>in the samples below.1.
/mcpreturns a proper 401 with RFC 9728WWW-AuthenticateAlso passes identically with UAs
curl/*,Claude-User,ClaudeBot, andanthropic-ai— no UA-based WAF block.2. Protected Resource Metadata (RFC 9728)
GET /.well-known/oauth-protected-resource/mcp— 200:{ "resource": "https://<dev-host>/mcp", "authorization_servers": ["https://<dev-host>"], "scopes_supported": ["mcp:read", "mcp:write"], "bearer_methods_supported": ["header"] }3. Authorization Server Metadata (RFC 8414)
GET /.well-known/oauth-authorization-server— 200:{ "issuer": "https://<dev-host>", "authorization_endpoint": "https://<dev-host>/oauth/authorize", "token_endpoint": "https://<dev-host>/oauth/token", "registration_endpoint": "https://<dev-host>/oauth/register", "scopes_supported": ["mcp:read", "mcp:write"], "response_types_supported": ["code"], "grant_types_supported": ["authorization_code", "refresh_token"], "token_endpoint_auth_methods_supported": ["none"], "code_challenge_methods_supported": ["S256"] }4. Dynamic Client Registration works for both
claude.aiandclaude.comcallbacksPOST /oauth/registerwithredirect_uris: ["https://claude.ai/api/mcp/auth_callback"]returns 201 with a validclient_id, correct echo ofredirect_uris,grant_types: ["authorization_code","refresh_token"],response_types: ["code"],token_endpoint_auth_method: "none".Same request with
redirect_uris: ["https://claude.com/api/mcp/auth_callback"]also returns 201 (we accept both per the sunpeak guide note about dual-domain callbacks).5. Server-side OAuth flow is end-to-end verified in other clients
/mcp→ tool calls all work.client_credentials_in_body) completes successfully and returns valid JWTs.What our pod logs show during a failed Connect
With
kubectl logs -fon the MCP pod running during a Connect attempt: no inbound requests at all during the attempt window. No/.well-known/*, no/oauth/*, no/mcp. Combined with the WAF tests above, this rules out our edge as the cause — the broker isn't emitting the request.Hypothesis
Given:
WWW-Authenticatewithresource_metadata, PKCE S256,authorization_code+refresh_token).Claude-Userpass our WAF cleanly....the failure is inside the Anthropic-side broker
startstep — matching the exact pattern of #111 (fix was a server-side allowlist on the Anthropic backend) and #199 / #214.Environment
AWSManagedRulesCommonRuleSet). Strictly follows RFC 7591 DCR, RFC 8414, RFC 9728, and the MCP 2025-06-18 spec.Ask
@crondinini-ant — could you look up
ofid_c58995a431270861against the broker-side logs? Based on the identical signature to #111 / #214, we suspect the start step is rejecting our server (possibly on a default-scope or URL-validation step) before dispatching. If so, an allowlist exception for our dev host would unblock us while the root cause is investigated. I can share the hostname + account/org UUIDs privately on request. Thanks!