anthropics / anthropics/claude-ai-mcp

MCP OAuth flow ignores PRM authorization_servers and user is redirected to <mcp_host>/authorize → 404

Offen
#341 4 Kommentare 9 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
auth bug server-developer-report
Vorherrschende Sprache
Keine Sprachdaten
Sterne
471
Forks
76
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

### MCP server URL

https:///mcp

### Where does the issue occur?

When pressing the Connect button

### Transport used

streamable-http

### Client registration type

Static

### SSE only: Does your server return the expected status code for POST requests?

Not applicable (my server does not use SSE)

### When did you last reproduce this?

2026-05-22 10:25 UTC (11:25 WEST)

### Browser and OS

Chrome 148 on macOS 10.15.7 (per User-Agent in server logs)

### Describe the issue

When connecting to an MCP server that returns a valid `Protected Resource Metadata (PRM)` document with `authorization_servers` set to an external authorization server, Claude.ai correctly fetches the PRM but then ignores the `authorization_servers` field. Instead of redirecting the user to the configured authorization server's `authorization_endpoint`, Claude redirects the user browser to `/authorize`, treating the MCP server itself as the OAuth authorization server. This results in a 404 (the MCP server has no such endpoint) and the OAuth flow cannot complete.

This appears to be a deviation from the MCP `2025-06-18 authorization spec`, which mandates `RFC 9728` (Protected Resource Metadata) + `RFC 8414 `(Authorization Server Metadata) discovery flow.

## Environment

- **MCP client**: Claude.ai (web), connector configured via Settings → Connectors → Add custom connector
- **MCP server**: `googleapis/mcp-toolbox` v1.2.0 with `--prebuilt=looker`
- **Authorization server**: Looker (`https://.com`), which exposes `RFC 8414` OAuth metadata but not OIDC
- **Reproduction date**: 2026-05-22

### Issue details

MCP server: `googleapis/mcp-toolbox` v1.2.0 with --prebuilt=looker, deployed in K8s.
Authorization server (per our PRM):

```
prm.json: |
{
"resource": "https:///mcp",
"authorization_servers": ["https://.com"],
"scopes_supported": ["cors_api"],
"bearer_methods_supported": ["header"]
}
```
Steps to reproduce:
1. Deploy mcp-toolbox configured with `LOOKER_USE_CLIENT_OAUTH=true` and a PRM that advertises Looker as the authorization server.
2. In Claude.ai, add a custom connector with the MCP server URL and `claude-desktop` as OAuth Client ID (no secret — PKCE).
3. Click Connect.

Observed: browser is redirected to `https:///authorize?response_type=code&client_id=claude-desktop&redirect_uri=https%3A%2F%2Fclaude.ai%2Fapi%2Fmcp%2Fauth_callback&code_challenge=<...>&code_challenge_method=S256&state=<...>` and gets 404.

Between the PRM fetch and the user redirect, Claude makes **no** request to `https:///.well-known/oauth-authorization-server`. The RFC 8414 discovery step required by the MCP 2025-06-18 authorization spec is skipped.

Looker AS metadata (returns 200, was never fetched by Claude):
```
{
"issuer": "https://",
"authorization_endpoint": "`https:///auth",
"token_endpoint": "`https:///api/token",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"scopes_supported": ["cors_api", "api"]
}
```

### Expected behavior

Per the MCP `2025-06-18 authorization spec (`https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization), the client should:

1. Fetch the PRM at `/.well-known/oauth-protected-resource`.
2. Read `authorization_servers[0]`
3. Fetch the AS metadata at `/.well-known/oauth-authorization-server` (RFC 8414) to discover `authorization_endpoint`.
4. Redirect the user to that `authorization_endpoint` with the standard OAuth 2.0 + PKCE query parameters.

In our case, this would mean redirecting to `https:///auth?response_type=code&client_id=claude-desktop&...`.

## Actual behavior

Claude.ai fetches the PRM successfully (200 OK, confirmed in MCP server logs, see below), then redirects the user's browser to:

`https:///authorize?response_type=code&client_id=claude-desktop&redirect_uri=https%3A%2F%2Fclaude.ai%2Fapi%2Fmcp%2Fauth_callback&code_challenge<...>&code_challenge_method=S256&state=<...>`

The MCP server has no `/authorize` endpoint and returns 404.

## Evidence

### PRM document served by the MCP server

```
{
"resource": "https:///mcp",
"authorization_servers": ["https://"],
"scopes_supported": ["cors_api"],
"bearer_methods_supported": ["header"]
}
```

Authorization server metadata (RFC 8414) exposed by Looker

GET https:///.well-known/oauth-authorization-server returns:
```
{
"issuer": "",
"authorization_endpoint": "https:///auth",
"token_endpoint": "https:///api/token",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "none"],
"scopes_supported": ["cors_api", "api"],
"code_challenge_methods_supported": ["S256"]
}
```

So authorization_endpoint is correctly discoverable. Claude.ai is not fetching this document.

MCP server access logs (Claude → MCP server, in order)

```
10:25:57.683 GET /.well-known/oauth-protected-resource → 200 (python-httpx/0.28.1) # Claude backend
10:25:58.065 GET /authorize?response_type=code&... → 404 (Chrome 148 / browser) # ~382ms later
```
The first request is Claude's backend fetching the PRM. The second is the user's browser being redirected by Claude to a /authorize path on the MCP host — that path does not exist on the MCP server, and the authorization_endpoint in the PRM's authorization_servers[0] was never consulted.

Authorization server metadata is NOT being fetched

There is no request from Claude.ai to https:///.well-known/oauth-authorization-server between the PRM fetch and the user redirect. The discovery step from PRM → AS metadata is being skipped entirely.

**Impact**

This blocks the integration documented in the upstream googleapis/mcp-toolbox Claude Desktop sample (https://github.com/googleapis/mcp-toolbox/blob/main/docs/en/integrations/looker/samples/looker_claude_oauth/_index.md), which relies on PRM + RFC 8414 discovery to authenticate end-users against Looker via PKCE.

### Logs from your server

MCP server access logs (Claude → MCP server, in order)

```
10:25:57.683 GET /.well-known/oauth-protected-resource → 200 (python-httpx/0.28.1) # Claude backend
10:25:58.065 GET /authorize?response_type=code&... → 404 (Chrome 148 / browser) # ~382ms later
```

The first request is Claude's backend fetching the PRM. The second is the user's browser being redirected by Claude to a /authorize path on the MCP host — that path does not exist on the MCP server, and the authorization_endpoint in the PRM's authorization_servers[0] was never consulted.

### Additional context

**Upstream sample doc that this configuration follows:**
https://github.com/googleapis/mcp-toolbox/blob/main/docs/en/integrations/looker/samples/looker_claude_oauth/_index.md

**Suggested fix on Claude.ai's side:**
After fetching the PRM, take authorization_servers[0], fetch its /.well-known/oauth-authorization-server metadata, and use the returned authorization_endpoint / token_endpoint instead of constructing paths on the resource host.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.