anthropics / anthropics/claude-ai-mcp
OAuth completes (POST /token 200) but claude.ai never sends the authenticated MCP call — only for endpoint paths other than exactly /mcp
- Linguagem predominante
- Sem dados de linguagem
- Estrelas
- 471
- Forks
- 76
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Descrição
## Summary
claude.ai completes the **entire OAuth flow** for a custom connector (discovery → DCR → `/authorize` → callback → `POST /token` **200**) and then **never sends any request to the MCP server again** — no `initialize`, not even an unauthenticated probe. The UI reports:
> Your account was authorized, but the integration rejected the credentials it just issued. Reconnecting may not help; if it keeps happening, contact whoever manages this integration.
The server never "rejected" anything: **zero post-token traffic reaches the origin** (verified with an ASGI shim logging every inbound POST and whether it carried an `Authorization` header — nothing arrives after `/token`).
The decisive pattern: this happens **only for MCP endpoints whose URL path is anything other than exactly `/mcp`**. A connector at the root `…/mcp` on the *same server, same OAuth AS, same GitHub identity* connects fine every time. Endpoints at `…/quinn/mcp` or `…/quinn-mcp` fail 12+ consecutive times.
Likely same family as #100, #196, #240, #690.
## Setup
- Server: FastMCP **3.4.7** `OAuthProxy`/`GitHubProvider` (GitHub OAuth upstream), one authorization server at the domain root, multiple MCP resource endpoints told apart by path.
- Transport: Cloudflare named tunnel → `https://mcp.quinnfrederick.com` (`:443` only), streamable HTTP.
- Endpoints: `/mcp` (works in claude.ai), `/quinn-mcp`, `/seealso-mcp`, `/promethean-mcp` (all fail in claude.ai, all work everywhere else).
- Discovery metadata is spec-correct per endpoint: `401` carries `WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource/"`; each PRM returns the exact `resource` and `authorization_servers`; AS metadata at root.
## What the origin sees for a failing connect (from the access log)
```
POST /quinn-mcp 401 ← pre-auth probe (expected)
GET /.well-known/oauth-protected-resource/quinn-mcp 200
GET /.well-known/oauth-authorization-server 200
GET /authorize?...&resource=https%3A%2F%2Fmcp.quinnfrederick.com%2Fquinn-mcp 302
GET /auth/callback?code=… 302
POST /token 200 ← token issued
(silence — no further request from claude.ai, ever)
```
For the working `/mcp` connector the same sequence is followed **immediately** by authenticated `POST /mcp` calls (200/202) and the connector shows Connected with the full tool list.
## Proof the failing endpoint itself is healthy
1. **Independent OAuth client** (fresh DCR registration, PKCE, real GitHub auth, `resource=…/quinn-mcp`): token issued with `aud` = exact resource, then authenticated `initialize` on `/quinn-mcp` → **HTTP 200, `mcp-session-id` issued, full MCP result in 0.12–0.93 s**.
2. **ChatGPT** (developer-mode connector) connects to the identical `…/quinn-mcp` URL and lists/uses all 13 tools without issue.
## Variables eliminated (each tested explicitly, failure identical)
- **CIMD vs DCR client**: fails with the shared CIMD client id (`https://claude.ai/oauth/mcp-oauth-client-metadata`) *and* with per-connector DCR UUID clients (server advertises no CIMD support → claude.ai registered via `/register`, 201).
- **Token audience**: server mints `aud` = the exact RFC 8707 `resource` claude.ai sends (verified by decoding issued JWTs). Also tried `aud = issuer`. No difference.
- **Path shape**: multi-segment `/quinn/mcp` and single-segment `/quinn-mcp` both fail; only the literal root `/mcp` connects.
- **Connector record state**: brand-new connectors (fresh UUID, never-seen URL) fail on first Connect.
- **Whether the working `/mcp` connector is connected or disconnected at the time**: no difference.
- **GitHub health / sudo-mode**: reproduced with GitHub API fully healthy and an active sudo session; the GitHub grant is authorized (`/auth/callback` fires with a valid code and the upstream exchange succeeds server-side).
- **Refresh vs first connect, Cowork vs web settings surface**: identical.
## Recent flow IDs (all this failure, 2026-08-17, account xxi@quinnmagick.com / GitHub QuinnFrederick)
`ofid_33082ae8391cb7b5`, `ofid_4477320f29f62599`, `ofid_f561b93ff00d98f8`, `ofid_d5c453d666b37a61`, `ofid_8e47f0471a8781d8`, `ofid_c29d9ed05089b800`, `ofid_a6f821ab94f36387`, `ofid_4dbb8cb3b3723b7a`, `ofid_5efac3af5f2043e9`, `ofid_7e8a0a67e0570c98`
(Working root-path connects for contrast, same server/day: the "Quinn Personal" connector at `…/mcp`, multiple `step=success` flows.)
## Expected
After `POST /token` succeeds, claude.ai's backend should call the MCP endpoint (the connector's URL / the `resource` it itself requested) with the issued Bearer token — as it does for root-path `/mcp` connectors, and as ChatGPT and spec-compliant clients do for the non-root endpoints.
## Actual
For any connector whose endpoint path ≠ `/mcp`, the backend abandons the flow after token issuance without contacting the server, and surfaces "the integration rejected the credentials it just issued".
Happy to provide server-side logs, run test connects on demand, or try candidate fixes — the server is live and instrumented.
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Avaliação
Esta issue ainda não foi avaliada.