anthropics / anthropics/claude-ai-mcp
Custom connector 'Connect' fails intermittently: roots/list timeout (root cause found) + a separate step that fails without ever reaching the server
- 主要语言
- 没有语言数据
- 星标
- 471
- 派生
- 76
- PR 合并指标
- 30 天内没有已合并 PR
描述
### What happened?
I run a self-hosted, remote custom MCP connector (no OAuth — a secret path segment acts as a bearer token) served over Streamable HTTP via `supergateway`, wrapping `@modelcontextprotocol/server-filesystem`, exposed publicly via a Tailscale Funnel. It reliably fails claude.ai's "Connect" health check, via two distinct, separate problems:
**Problem 1 — root cause found and fixed (with a client-side workaround): a server-initiated `roots/list` request never gets answered.**
When "Connect" is clicked, claude.ai connects with `clientInfo: {"name":"claude-code","title":"Claude Code","version":"2.1.220"}` and declares `"capabilities":{"roots":{"listChanged":true},"elicitation":{}}` in its `initialize` call. My MCP server (a standard, unmodified `@modelcontextprotocol/server-filesystem`) responds to that by sending a `roots/list` request back to the client, per normal MCP behavior. claude.ai never answers it. It times out after ~5s (`McpError: MCP error -32001: Request timed out`), and claude.ai reports "Couldn't reach [connector]" — even though `initialize` and `tools/list` both already succeeded cleanly on the same connection moments earlier. I confirmed this exact sequence directly in my server's stdio logs across multiple attempts, with the identical timeout every time.
I worked around it by writing a thin stdio shim that intercepts the server's `roots/list` request and answers it locally instead of letting it reach claude.ai. Confirmed via logs that this got a subsequent "Connect" attempt past that step cleanly for the first time. But a properly-behaving remote connector shouldn't need a client-side patch for something this fundamental — this seems like a real gap in claude.ai's connector-client implementation of server-initiated `roots/list` over remote Streamable HTTP (it may work fine over stdio, where the client and server share a process).
**Problem 2 — separate, still-unresolved: "Connect" attempts fail with different errors, without the request ever reaching my server at all.**
After the shim fix, I made several more "Connect" attempts. They failed with three different messages: a repeat of the "couldn't reach" message, and — with no OAuth configured on this connector at all — "Couldn't register with [connector]'s sign-in service." I verified via my server's access logs, with second-precision timestamps, that **none of these attempts produced any corresponding request on my server** — e.g. one "Connect" click at 11:12:24 produced zero log activity through 11:13:00+, on a log file that was otherwise being actively written to by other traffic. This means the failure happens entirely within claude.ai's own connector-setup flow, before any request is sent to the configured URL — most likely some client-side pre-flight check (possibly an OAuth discovery step assumed for all custom connectors) failing on claude.ai's own infrastructure.
Interestingly, I also found evidence in my server logs of a **different, third client** — `clientInfo: {"name":"Anthropic/ClaudeAI","version":"1.0.0"}` — connecting successfully multiple times, with production Sentry trace headers (`sentry-environment=production`). This client never declares `roots` capability, so it never hits Problem 1 either. I don't yet know what this third client is used for (possibly background monitoring/health-checks, since the connector never actually appears as available to attach to a real chat), but it demonstrates the server and network path are genuinely reachable and correctly implemented — the failures are specific to whatever client/flow the Settings "Connect" button and real chat-attachment use.
### What did you expect to happen?
The connector should show "Connected" reliably, and be usable as a tool source in real chats — the same way it apparently already is for whatever client corresponds to the "Anthropic/ClaudeAI" traffic in my logs.
### Steps to reproduce
1. Add a custom connector via Customize > Connectors > Add > Add custom connector, with a Remote MCP server URL only (no OAuth Client ID/Secret) pointing to a self-hosted, publicly reachable Streamable HTTP MCP server.
2. 2. Click "Connect" on the newly added connector.
3. 3. Observe: fails with "Couldn't reach [connector]" (before the roots/list fix) or intermittently with "Couldn't register with [connector]'s sign-in service" / repeats of "Couldn't reach" (after the fix) — verified via server-side logs that these later failures never produce a corresponding request on the server at all.
### Area
MCP Connector (adding/managing servers)
### MCP Server (if applicable)
custom self-hosted server: supergateway (stdio→StreamableHTTP bridge) wrapping @modelcontextprotocol/server-filesystem
### Error messages or logs
```shell
Server-side (from my supergateway logs), the roots/list timeout:
Child → StreamableHttp: {"method":"roots/list","jsonrpc":"2.0","id":0}
(tools/list succeeds normally in between)
Child → StreamableHttp: {"jsonrpc":"2.0","method":"notifications/cancelled","params":{"requestId":0,"reason":"McpError: MCP error -32001: Request timed out"}}
Child stderr: Failed to request initial roots from client: MCP error -32001: Request timed out
claude.ai UI, across separate attempts:
"Couldn't reach [connector]. You can check the server URL and verify the server is running. If this persists, share this reference with support: \"ofid_7f6d2845b73ef2bc\""
"Couldn't register with [connector]'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_925e01b0ad20c2d5\""
```
### Additional context
Two more reference IDs from further "Connect" attempts (repeats of "Couldn't reach"): `ofid_776965cb2278b4ae`, `ofid_6884474f5bc22089`.
Environment: server reachable over the public internet via a Tailscale Funnel (not a firewall/NAT issue — confirmed reachable directly via curl, and confirmed reachable by claude.ai's own infrastructure per the successful Anthropic/ClaudeAI sessions noted above). No OAuth Client ID/Secret configured on the connector — it authenticates via a long random secret in the URL path only.
Happy to share more log excerpts or test anything else that would help narrow this down.
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。