[BUG] Custom MCP connector: tool calls dropped before reaching origin — Claude Code, claude.ai Chat and Cowork
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Tool calls to a custom self-hosted remote MCP connector are intermittently dropped before reaching the origin server. The client reports an error blaming my infrastructure; the origin's access logs prove no request ever arrived.
Observed on three separate surfaces, same account, same connector, same day:
- Claude Code (desktop app, on my own Windows machine) —
This connector's server hostname doesn't resolve or isn't reachable from this network. - claude.ai Chat — same message, and usefully it carries a
request_id:
{"error": "This connector's server hostname doesn't resolve or isn't reachable from this network. The connector may be misconfigured.", "request_id": "req_011CezoxwxEMbE9gCwJv9e5u"}
- Claude Cowork (cloud-hosted on Anthropic infrastructure, not local) — Cloudflare 502 carrying
"zone":"api.anthropic.com"and"error_category":"origin".
That spread matters: my local network, DNS and machine cannot account for failures originating from cloud Cowork and from claude.ai, and a client-side defect would have to exist independently in three unrelated clients.
Measured rate: 2 drops in 62 calls (~3%) across six batches. The two clearest instances:
- Claude Code, 6 concurrent calls — 5 arrived at origin (
200 OK), 1 never arrived - claude.ai Chat, 18 sequential calls — 17 arrived (
200 OK), 1 never arrived (03_voice), with therequest_idabove
The second is important twice over: that batch was dispatched sequentially, one call per turn-step, so concurrency is not required; and re-running the identical 18-path request immediately afterwards returned 18/18, including the exact path that had failed — so it is not path-, payload- or content-dependent either.
The origin was healthy throughout — 0 errors, 0 restarts, and zero 5xx responses in its entire access log history. It has never returned a 502 to anything.
Origin setup: self-hosted Python MCP server (mcp SDK / FastMCP), Streamable HTTP, json_response=True, behind a Caddy reverse proxy, MCP-native OAuth + bearer token. Seven such services on the same host behind the same proxy and auth.
Already ruled out — origin-side session state. Suspecting the client and origin were disagreeing about session identity, I switched the server from stateless_http=False to stateless_http=True, so there is no in-memory session to lose and no Mcp-Session-Id to go stale. The symptom persisted unchanged.
What Should Happen?
Tool calls to a custom remote MCP connector should reach the origin — or, when they cannot, fail with an error that names the actual failure.
Specifically:
- Tool calls should not be silently dropped in transit. Two vanished out of 44, on two different surfaces, one of them from a purely sequential batch. The origin never saw either.
- A delivery failure should not be reported as an origin failure. "This connector's server hostname doesn't resolve or isn't reachable from this network" is actively misleading: at the moment it was shown, the hostname resolved on public DNS, the host was reachable, and it was returning
200 OKto Anthropic's own egress addresses immediately before and after — in the 18-call batch, on the calls either side of the one that failed. That message cost me roughly a day investigating DNS, tunnel config, reverse-proxy routing and service health before the origin's access logs showed nothing was arriving at all.
- Likewise the 502 should not carry
"error_category":"origin"when the origin received no request.
- Surface the
request_idconsistently. claude.ai Chat returns one with this error —req_011CezoxwxEMbE9gCwJv9e5u— which should be enough to trace the failing request server-side. Claude Code's version of the same error surfaces no identifier at all, and Cowork's 502 gives only a Cloudflareray_id. Same failure, three different levels of traceability.
retry_aftershould be usable. Every 502 advertises"retryable": true, "retry_after": 60, but a retry at +81 seconds returned another 502; recovery took roughly three minutes and two attempts.
Error Messages/Logs
=== THE MOST TRACEABLE INSTANCE (claude.ai Chat) ===
One call out of 18 failed. Verbatim error, including the request_id:
{"error": "This connector's server hostname doesn't resolve or isn't reachable from this
network. The connector may be misconfigured.", "request_id": "req_011CezoxwxEMbE9gCwJv9e5u"}
Origin side for that same batch:
CallToolRequest received: 17 (Caddy: 17 x 200, 1 x 400 handshake probe)
CallToolRequest missing: 1 <- the 03_voice call above
service errors: 0
NRestarts: 0
The 17 that arrived include the calls immediately before and after the one that vanished,
so the origin was reachable and answering throughout.
=== SAME ERROR, CLAUDE CODE (no request_id surfaced) ===
This connector's server hostname doesn't resolve or isn't reachable from this network.
The connector may be misconfigured.
Origin side, 6 concurrent calls from Claude Code:
CallToolRequest received: 5 (all 200 OK)
CallToolRequest missing: 1
service errors: 0, NRestarts: 0
Caddy access log, same window (the 400s are normal handshake probes):
12:10:59 400 160.79.106.165
12:11:00 200 160.79.106.168
12:11:00 400 160.79.106.185
12:11:01 200 160.79.106.160
12:11:02 200 160.79.106.179
12:11:02 200 160.79.106.164
12:11:03 200 160.79.106.36
=== CLAUDE COWORK (cloud-hosted) ===
Error POSTing to endpoint: {"title":"Error 502: Bad gateway","status":502,
"error_name":"origin_bad_gateway","error_category":"origin","zone":"api.anthropic.com",
"cloudflare_error":true,"retryable":true,"retry_after":60}
Cloudflare ray IDs (all 2026-09-13, all on vault_edit):
03:17:43Z a3a4002208b827e1 502
backoff 70s
03:19:04Z a3a402185a21cd80 502 again (+81s, past the advertised retry_after of 60)
backoff 100s
200, write applied (~+187s after the first failure)
03:39:39Z a3a4203f2d7c22b9 502 -> backoff 95s -> 200
03:46:41Z a3a42a922a3e2322 502 -> backoff 95s -> 200
Every retry used a byte-identical payload, so payload size/shape is not the trigger.
=== EARLIER FAILURE WINDOW - CallTool counts per connector ===
Tool invocations not arriving while session setup for the same connectors did:
vault CallTool=5 last 01:58:43 <- 11:19 call never arrived
search CallTool=3 last 11:11:14 <- 11:19 call never arrived
evidence CallTool=0 none that day
legal CallTool=0 none that day
rkb CallTool=1 last 11:19:38 <- arrived, 200 OK
assets CallTool=1 last 11:19:46 <- arrived, 200 OK
During that window the origin logged a COMPLETE, successful session for one of the
"failing" connectors: "Created new transport" followed by ListToolsRequest -> 200 OK.
The connection was established and the tool list served; only the invocation was lost.
=== ORIGIN HEALTH ACROSS ALL OF THE ABOVE ===
NRestarts = 0 throughout (no crash, no automatic restart)
uptime ~19 days at the first failure; ~19 hours at the later ones, the only restart
in between being my own deliberate one for the stateless_http change
5xx responses in the entire access log: 0
401s present and correct (unauthenticated internet scanner probes)
Steps to Reproduce
No deterministic reproduction — it is a low-rate intermittent fault. Reporting the measurement rather than a recipe, because my first attempt at a recipe did not survive testing.
- Add a custom remote MCP connector (claude.ai → Settings → Connectors) pointing at a self-hosted Streamable HTTP MCP server you control — one whose access logs and application logs you can read.
- Issue batches of tool calls to it and record the client-side success count.
- Compare that against the origin's access log and application log for the same window.
Measured across six batches on three surfaces:
| batch | client | sent | arrived at origin | dropped |
|---|---|---|---|---|
| 1 | Claude Code | 6 (concurrent) | 5 | 1 |
| 2 | Cowork (cloud) | 6 | 6 | 0 |
| 3 | Claude Code | 8 (concurrent) | 8 | 0 |
| 4 | claude.ai Chat | 6 (sequential) | 6 | 0 |
| 5 | claude.ai Chat | 18 (sequential) | 17 | 1 |
| 6 | claude.ai Chat | 18 (sequential) | 18 | 0 |
| total | | 62 | 60 | 2 |
Roughly 3%, on at least two different surfaces. Per-surface: Claude Code 1 drop in 14, claude.ai Chat 1 drop in 42 — numbers far too small to claim any surface is more affected than another.
Concurrency is not the trigger. I initially thought it was, because the first batch dropped one immediately. Batch 5 disproves it: 18 calls dispatched sequentially, one per turn-step, and one still vanished. Batch 6 was byte-for-byte the same request as batch 5 and came back clean, including the exact path that had failed. Larger batches simply give the fault more chances to fire.
Step 3 is the one that matters. Comparing the client's success count against the origin's own logs is what distinguishes a delivery failure from an origin failure. Without it this presents as an origin or network fault — exactly what all three error messages assert, and where I wasted a day.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude 1.52386.3 (41896e) 2026-09-11T17:35:10.000Z — Claude for Windows desktop app
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
Versions and surfaces
- Claude for Windows desktop app —
Claude 1.52386.3 (41896e) 2026-09-11T17:35:10.000Z - claude.ai Chat — web, Opus 4.6
- Claude Cowork, cloud-hosted — not local. The currently-active status.claude.com incident "Degraded functionality for Claude Cowork on Windows" concerns local Cowork and a Sep 8 Windows update blocking local command execution, so it does not apply to these sessions.
- Windows 11
- The bundled Claude Code CLI version could not be read separately — the app ships as an MSIX package under
Program Files\WindowsApps, which is ACL-protected, andclaude --versionis not on PATH for this install. The app version string above is what the app itself reports. - status.claude.com reported "Claude API: Operational" throughout every failure described here.
Possibly relevant: gateway egress rotates between requests
Within a single logical session, requests reach the origin from many distinct Anthropic egress addresses. Observed across one day: 160.79.106.36, .37, .160, .161, .163, .164, .165, .168, .173, .175, .176, .178, .179, .183, .184, .185, .187. Consecutive requests in one round-trip routinely come from different nodes — e.g. a 400 from .184 at 15:12:39 followed by the 200 OK CallToolRequest from .187 at 15:12:40.
Recording this as an observation only, not a claim about cause.
Related issues
- #48277, #48291 — same
Error POSTing to endpoint … 502string, butmcp-proxy.anthropic.comand Anthropic-hosted connectors; #48291 closed as not planned - #69426 — a 502 on a connected MCP server driving a retry loop that drained a session's token budget
- #6341 — closed as duplicate; different root cause (file token limits)
- #64414 — different layer (custom model API gateway, not MCP), but a documented case of Cowork and Code diverging against custom infrastructure; closed as not planned
- #61682 — Anthropic-hosted GitHub connector reporting "Connected" while exposing no tools; similar "connected but non-functional" presentation, but no custom origin and no delivery failure
This report differs from all of them in being a custom self-hosted connector, failing across three surfaces (local Claude Code, claude.ai Chat, and cloud Cowork), with origin-side logs proving non-arrival, a measured drop rate over 44 calls, a request_id for one failing request, and origin session state experimentally eliminated.
Note
The origin hostname is deliberately omitted — it is a publicly-reachable endpoint fronting private material. Happy to share it privately with Anthropic if that helps trace req_011CezoxwxEMbE9gCwJv9e5u or the ray IDs above.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗