anthropics / anthropics/claude-ai-mcp

Custom MCP connector fails with "Failed to start MCP authorization" before any request reaches the server (PKCE-only, no client_secret)

Aberta
#724 1 comentário 2 reações 0 responsáveis Ver no GitHub
bug
Linguagem predominante
Sem dados de linguagem
Estrelas
471
Forks
76
Métricas de merge de PRs
Nenhum PR com merge em 30d

Descrição

### What happened?

## Summary

Connecting a custom MCP connector fails at the very start of the OAuth flow. The client-side console shows `Failed to start MCP authorization` and a `400 Bad Request` on an internal `claude.ai/api/organizations/.../...` call — before any network request is ever sent to our MCP server. We've independently verified our server-side OAuth/MCP implementation is fully spec-compliant and working (details below), which points to a bug in Claude's connector/authorization client itself.

## Environment

- MCP server URL: `https://conpoc.graniteshares.com/mcp`
- Connector config: custom connector, "Individual sign-in" method
- OAuth Client ID / Client Secret fields: left blank (relying on Dynamic Client Registration + PKCE)
- Tested via: claude.ai in Edge (browser), and Claude Desktop (same failure in both)
- Underlying MCP server: Microsoft Data API Builder (DAB) 2.0.9, fronted by a custom Node/Express OAuth shim (auth server + reverse proxy)

## What we verified works correctly (server-side)

1. `/.well-known/oauth-protected-resource` — returns valid RFC 9728 metadata, `resource` matches the `/mcp` endpoint, `authorization_servers` populated correctly.
2. `/.well-known/oauth-authorization-server` and `/.well-known/openid-configuration` — both return consistent metadata with `token_endpoint_auth_methods_supported: ["none"]` (public client, PKCE-only).
3. `POST /register` (Dynamic Client Registration, RFC 7591) — accepts a registration request and returns a spec-compliant response (client_id, echoed redirect_uris, token_endpoint_auth_method: "none").
4. `GET /authorize` → user approval → redirect to `https://claude.ai/api/mcp/auth_callback?code=...&state=...` — confirmed working via manual browser test, correct `code` and `state` passed through.
5. `POST /token` — correctly validates the PKCE `code_verifier` against the stored `code_challenge` (S256), issues and persists a Bearer access token. Verified directly via curl with a real authorization code and works correctly, returning `invalid_grant` for garbage codes as expected.
6. `GET/POST /mcp` — correctly enforces auth, returning `401` with a proper `WWW-Authenticate: Bearer resource_metadata="https://conpoc.graniteshares.com/.well-known/oauth-protected-resource"` header when no/invalid token is present.
7. The underlying MCP server (DAB) correctly implements the MCP `initialize` handshake — verified directly via curl with a valid JSON-RPC `initialize` request, returns a proper `2024-11-05` protocol response with `serverInfo`, `capabilities`, and a `Mcp-Session-Id` header.

Server-side (IIS + Node) logs confirm: during real connect attempts from Claude, **no requests at all reach our server** — not even the initial discovery fetch. Manual curl tests to every endpoint above succeed; only Claude-initiated attempts fail silently before leaving the browser/backend.

## Console error captured during a failed connect attempt (claude.ai, Edge)

```
GET https://claude.ai/api/organizations//...
400 (Bad Request)

[REACT_QUERY_CLIENT] QueryClient error:
ye: Failed to start MCP authorization
at we (shared-0-B6nQ_22V.js:1:3925)
at shared-0-B6nQ_22V.js:1:124260
at async Object.mutationFn (shared-2-DxokTDcv.js:2:225608)
```

This error fires immediately on clicking "Connect" — before any request to our domain (`conpoc.graniteshares.com`) appears in the Network tab. It appears the failure originates in Claude's own backend/frontend, at the step that should initiate the OAuth authorization request.

## UI-facing error

> Couldn't register with Azure Sql Mcp's sign-in service. You can try again, or add an OAuth Client ID in the connector settings. If this persists, share this reference with support: "ofid_..."

Reference IDs collected across multiple attempts:
- `ofid_8f0488db9eae43a8`
- `ofid_9aca44551e7027a8`
- `ofid_ebf0fa70e2b4c621`
- `ofid_b617af81e7f2e506`

When a Client ID is manually supplied (copied from a prior `/register` response) instead of left blank, the error changes to:
> Couldn't connect to the server. Check that the URL points to a valid MCP server.
(Also with an `ofid_...` reference, `ofid_9aca44551e7027a8`.)

## Steps to reproduce

1. Add a custom connector with URL `https://conpoc.graniteshares.com/mcp`, leave OAuth Client ID and Client Secret blank, "Individual sign-in" enabled.
2. Click "Connect".
3. Observe: UI shows "Couldn't register with [connector]'s sign-in service", with an `ofid_...` reference.
4. Open browser DevTools Console during the attempt: see `Failed to start MCP authorization` and a `400` on an internal `claude.ai/api/organizations/...` endpoint, with zero requests to the connector's domain in the Network tab.

## Expected behavior

Given the server implements RFC 9728 (protected resource metadata), RFC 8414 (authorization server metadata), RFC 7591 (dynamic client registration), and PKCE (RFC 7636) correctly and completely — verified via direct manual testing of every endpoint — the connector should be able to complete the full discovery → registration → authorize → token exchange flow.

## Suspicion

Possibly a bug specific to connectors configured with **no manually-provided Client ID/Secret** (i.e., relying entirely on Dynamic Client Registration with `token_endpoint_auth_method: "none"`), where Claude's client-side authorization-initiation code may be hitting an error before making any outbound request — plausibly related to how the organization-scoped `/api/organizations/.../...` call is constructed or validated.

### What did you expect to happen?

Given the server implements RFC 9728 (protected resource metadata), RFC 8414 (authorization server metadata), RFC 7591 (dynamic client registration), and PKCE (RFC 7636) correctly and completely — verified via direct manual testing of every endpoint — the connector should be able to complete the full discovery → registration → authorize → token exchange flow.

Suspicion

Possibly a bug specific to connectors configured with no manually-provided Client ID/Secret (i.e., relying entirely on Dynamic Client Registration with token_endpoint_auth_method: "none"), where Claude's client-side authorization-initiation code may be hitting an error before making any outbound request — plausibly related to how the organization-scoped /api/organizations/.../... call is constructed or validated.

### Steps to reproduce

Steps to reproduce
Add a custom connector with URL https://conpoc.graniteshares.com/mcp, leave OAuth Client ID and Client Secret blank, "Individual sign-in" enabled.
Click "Connect".
Observe: UI shows "Couldn't register with [connector]'s sign-in service", with an ofid_... reference.
Open browser DevTools Console during the attempt: see Failed to start MCP authorization and a 400 on an internal claude.ai/api/organizations/... endpoint, with zero requests to the connector's domain in the Network tab.

### Area

MCP Connector (adding/managing servers)

### MCP Server (if applicable)

MS SQL MCP

### Error messages or logs

```shell

```

### Additional context

_No response_

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.