anthropics / anthropics/claude-ai-mcp

claude.ai web broker abandons MCP handshake after successful initialize on authless servers (verified spec-compliant via MCP Inspector)

オープン
#262 コメント 5 件 リアクション 0 件 担当者 0 名 GitHub で見る
bug
主要言語
言語のデータがありません
スター
471
フォーク
76
PR マージ指標
30日以内にマージされた PR はありません

説明

### What happened?

Setting up a custom remote MCP connector for claude.ai web. The server is fully spec-compliant (verified via MCP Inspector — screenshot attached) but the broker silently fails to complete the MCP handshake.

**The handshake sequence the broker actually performs:**

1. Broker POSTs `initialize` to `/mcp`. My server returns **HTTP 200** with a valid JSON-RPC response: `Content-Type: application/json`, `mcp-session-id` response header set, populated `capabilities` and `serverInfo`. Confirmed in nginx access logs (User-Agent `python-httpx/0.28.1`, originating from Anthropic's IP range).
2. Broker probes `/.well-known/oauth-protected-resource/`, `/.well-known/oauth-protected-resource`, `/.well-known/oauth-authorization-server`, and `POST /register`. All return **404** — which per [Anthropic's own docs on authless connectors](https://support.claude.com/en/articles/11176164-pre-built-web-connectors-using-remote-mcp) is the documented signal that no auth is required.
3. **The broker then silently abandons the handshake.** No `notifications/initialized` is sent. No `tools/list` is called. No further requests of any kind reach the server.
4. UI displays `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_..."`.

**The same server works correctly via:**
- MCP Inspector (`npx @modelcontextprotocol/inspector`) — shows `Connected`, identifies the server as `Google Spreadsheet v1.27.0`, completes `initialize` cleanly
- Claude Code (uses native HTTP transport, bypasses the broker)
- Direct Anthropic API calls via the `mcp_servers` parameter

Only the claude.ai web broker (and presumably Claude Desktop, which routes through the same broker) fails.

**Support reference IDs from successive retries:**
- `ofid_ced1d41e2358fc25`
- `ofid_cb12aecfbbb86dd3`
- `ofid_5a448f564214eea6`
- `ofid_bab201e3a1803cdb`
- `ofid_df44c937cdd67430`
-

Image

### What did you expect to happen?

Per the documented authless flow: when the OAuth `.well-known` endpoints return 404, the broker should treat the server as authless and continue the standard MCP handshake — send `notifications/initialized`, call `tools/list` to enumerate available tools, then mark the connector as `Connected`.

Instead, the broker abandons the handshake silently and surfaces a user-facing error that points the user toward server-side diagnostics, even though the server is responding correctly to every request the broker actually makes.

At minimum: either honor the documented 404-equals-authless contract, or surface a more accurate error to the user (e.g. "MCP server returned authless signal but broker requires OAuth"), or update the docs to match actual behavior.

### Steps to reproduce

1. Deploy a spec-compliant authless MCP server using Streamable HTTP transport. I used `mcp-google-sheets` (xing5) fronted by `mcp-proxy` (sparfenyuk) as the stdio→HTTP bridge, in a Docker container.
2. Expose it on a publicly-routable HTTPS subdomain. Mine: nginx reverse proxy with a Cloudflare Origin Certificate, Cloudflare DNS proxied (Full strict SSL).
3. Verify spec compliance using **your own MCP Inspector**: `npx @modelcontextprotocol/inspector`, set Transport Type to "Streamable HTTP", paste the server URL, click Connect. Observe `Connected` status, recognized server name/version, successful `initialize` in History.
4. In claude.ai web → **Settings → Connectors → Add custom connector** → paste the same URL → leave OAuth Client ID/Secret blank → Save.
5. Click **Connect**.

**Observed:** UI shows `Couldn't reach the MCP server` with an `ofid_*` reference. Server-side logs show only the initialize POST (200) and OAuth well-known probes (404), then nothing.

**Expected:** Connector transitions to `Connected` state, tools available in chat.

### Area

MCP Connector (adding/managing servers)

### MCP Server (if applicable)

mcp-google-sheets (xing5/mcp-google-sheets) v1.27.0, fronted by mcp-proxy (sparfenyuk/mcp-proxy) acting as stdio→Streamable HTTP bridge

### Error messages or logs

```shell
**UI error:**

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_ced1d41e2358fc25"

**nginx access log (Cloudflare-fronted; one full handshake attempt):**

172.70.35.213 - - [06/May/2026:15:20:42 +0530] "POST //mcp HTTP/2.0" 200 294 "-" "python-httpx/0.28.1"
172.71.194.20 - - [06/May/2026:15:20:43 +0530] "GET /.well-known/oauth-protected-resource//mcp HTTP/2.0" 404 123 "-" "python-httpx/0.28.1"
172.68.15.149 - - [06/May/2026:15:20:44 +0530] "GET /.well-known/oauth-protected-resource HTTP/2.0" 404 123 "-" "python-httpx/0.28.1"
104.23.211.35 - - [06/May/2026:15:20:45 +0530] "GET /.well-known/oauth-authorization-server HTTP/2.0" 404 123 "-" "python-httpx/0.28.1"
172.70.42.51 - - [06/May/2026:15:20:46 +0530] "POST /register HTTP/2.0" 404 123 "-" "python-httpx/0.28.1"

After the `POST /register 404`, **no further requests from the broker arrive**. No `notifications/initialized`, no `tools/list`, no GET on the SSE/Streamable HTTP endpoint.

**mcp-proxy log (server side):**

[I 2026-05-06 09:50:42,799] mcp.server.streamable_http_manager Created new transport with session ID: 1220e3b1269542b08e74b99f56af845b
INFO: 172.22.0.1:37832 - "POST /mcp HTTP/1.1" 200 OK

Session is created and 200 returned cleanly. No errors, no crashes, no client disconnect mid-response.

**Initialize response body (HTTP 200, Content-Type: application/json, 294 bytes):**

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"experimental": {},
"prompts": { "listChanged": false },
"resources": { "subscribe": false, "listChanged": false },
"tools": { "listChanged": false },
"completions": {}
},
"serverInfo": { "name": "Google Spreadsheet", "version": "1.27.0" }
}
}

The response also includes an `mcp-session-id` header per the Streamable HTTP spec.
```

### Additional context

**MCP Inspector validation (this is the key piece of evidence):**

I connected your own MCP Inspector tool to the same URL. Inspector reports:

- Status: **Connected** (green indicator)
- Server identified: **Google Spreadsheet v1.27.0**
- Transport: **Streamable HTTP**
- Session established: client-side `dde7cb6b-...`, server-side `84cea2dda...`
- `initialize` step in History panel completed successfully
- Both POST and GET messages flowing cleanly through the proxy

Screenshot attached.

This rules out: server config, transport mismatch, network/firewall/Cloudflare issues, TLS chain problems, malformed JSON-RPC, missing capabilities. The server is verified spec-compliant by your own validator.

**Related issues — same broker bug pattern, multiple affected users:**
- #207 — "Anthropic's internal `/tool_result` and `/attach_resource` return 404/400 after successful OAuth" — same broker abandonment pattern with a different MCP server
- #251 — Salesforce hosted MCP, "MCP server returned 405 after successful OAuth" — server is spec-compliant per Inspector, fails only via the broker
- #200, #201 — referenced in #207 as the same cluster

Common thread across these: the same MCP server works via every other Claude entry point (Anthropic API direct, Claude Code CLI, MCP Inspector) but fails on claude.ai web and Claude Desktop, both of which route through the broker. The broker is the common failure point.

**Architecture (for context):**

```
claude.ai web (broker: python-httpx/0.28.1, Anthropic IP range)
│ HTTPS

Cloudflare (sheets.microdolphin.com, proxied)
│ HTTPS via Cloudflare Origin Cert (SSL mode: Full strict)

nginx host vhost (rewrites //mcp → /mcp)
│ HTTP localhost:8765

Docker container running mcp-proxy
│ stdio

uvx mcp-google-sheets (Google Sheets API via service account)
```

**What I'd find useful in a response:**
1. Confirmation whether this is a tracked broker-side bug, and if so, a tracking issue or ETA.
2. A documented workaround for affected authless servers, or a clear statement that authless mode is no longer supported (if that's the situation, the docs need updating).
3. Improved broker-side error messaging when the handshake is abandoned post-initialize. The current "Couldn't reach the MCP server" message is misleading — the broker did reach the server, got valid responses, and chose not to continue.

Image

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。