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

未关闭
#708 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
bug
主要语言
没有语言数据
星标
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 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。