Streamable-HTTP MCP connector: 405 on SSE GET surfaces fatal "Client server capabilities not available" toast

Status Closed — not planned
Reported on v2.1.209
Maintainer reply None cached
Activity 14 comments · opened Jul 16, 2026 · closed Aug 24, 2026

What happened

Claude Desktop repeatedly shows a toast "Client server capabilities not available" when a remote Streamable-HTTP MCP connector is enabled (in my case an Atlassian remote connector, but the failure is in the client transport layer, not the server).

Enabling DevTools (developer_settings.json{"allowDevTools": true}) and watching the renderer console shows the toast corresponds 1:1 with this repeating error:

GET https://claude.ai/v1/toolbox/shttp/mcp/<connector-id>  405 (Method Not Allowed)
    at s
    at _startOrAuthSse
    at send
    at notification
    at connect
    at refreshClient
    at useClient
    at listTools

So the MCP client, while (re)connecting the connector, calls _startOrAuthSse to open the optional GET / SSE notification stream against the streamable-HTTP endpoint. The claude.ai proxy route for that connector answers 405 Method Not Allowed (it accepts POST only). The client treats that 405 as a failed connect → capabilities never load → the toast fires.

Per the MCP spec, a 405 on the standalone GET (SSE) stream is explicitly allowed and the client is supposed to simply not use that stream and continue with POST. Here it is being treated as a fatal connection failure instead.

Triggered from AutoSyncConnectorsToSession / refreshClient (the app re-syncing remote connectors to a session), and it recurs continuously.

Impact

Mostly cosmetic but persistent and noisy. The actual tool calls (POSTs) do succeed — e.g. the same connector's tools work when invoked, and a parallel probe of the same connector from the Claude Code CLI completed normally in ≤17s. Only the capability-refresh path fails, so the user gets a stream of scary "capabilities not available" toasts even though tools are working. It also appears to correlate with occasional multi-minute stalls on the first calls after a (re)connect.

Notable

  • No 401 / auth / token error anywhere in the console — it is not OAuth/credential related.
  • Only affects the remote Streamable-HTTP connector; local mcp-remote stdio bridges on the same machine are unaffected.

Steps to reproduce

  1. Enable a remote Streamable-HTTP MCP connector routed through claude.ai/v1/toolbox/shttp/mcp/<id> whose endpoint returns 405 on a GET (SSE stream open).
  2. Use it in a session so the app runs AutoSyncConnectorsToSession / refreshClient.
  3. Observe the recurring "Client server capabilities not available" toast; DevTools console shows the 405 (Method Not Allowed) on _startOrAuthSse → connect.

Tried / did not help

  • Disconnect + reconnect the connector.
  • Full machine reboot.

Both leave the toast recurring.

Expected

Client should tolerate a 405 on the optional SSE GET stream (per MCP spec), fall back to POST-only operation silently, and not surface a fatal "capabilities not available" toast when tool calls are actually succeeding.

Environment

  • Claude Desktop 1.21459.3.0 (x64, Windows)
  • Embedded Claude Code 2.1.209
  • Windows 11 Pro (26200)

(Connector ID, cloud ID, and internal item keys redacted — the repro is transport-layer and connector-agnostic.)

View original on GitHub ↗

11 Comments

davidkm123 · 1 month ago
Correction: the mechanism described below is partly wrong — I inferred the 405 rather than measuring it, and no GET ever actually reaches my origin. See my follow-up for what I measured. Original text kept below unchanged.

---

Reproduced with a different server stack — confirming this is client-side and transport-layer, not specific to the Atlassian connector.

Setup: custom remote MCP server built on Python FastMCP with stateless_http=True + json_response=True, i.e. no standalone SSE stream at all — GET on the streamable-HTTP endpoint returns 405 by design, which the MCP spec explicitly permits (client SHOULD fall back to POST-only).

Symptoms match 1:1:

  • Recurring "Client server capabilities not available" toast while the connector is enabled in a session.
  • The chat UI additionally renders an "Unable to reach \<connector\>" error card on the tool-call block.
  • Meanwhile the actual tool calls succeed — server access logs show the POST tools/call arriving and completing 200 in \<1s at the exact time the UI showed "Unable to reach", and the model's answer contained the correct data from the tool result.

So the failed capability-refresh (GET/SSE → 405 treated as fatal) not only fires the toast but also mislabels successful tool calls as unreachable in the transcript UI, which makes users suspect their server is down when it isn't.

Agree with the expected behavior: tolerate 405 on the optional GET stream and continue silently POST-only.

davidkm123 · 1 month ago

Correction to my earlier comment — I overstated the mechanism there. The part I can actually measure points somewhere slightly different, so I want to fix the record.

Two things I got wrong:

  1. I wrote that GET on my streamable-HTTP endpoint "returns 405 by design". I inferred that from the FastMCP config (stateless_http=True + json_response=True) rather than measuring it. Measured: an unauthenticated GET on /mcp returns 401, because the OAuth gate sits in front of the transport. I never verified what an authenticated GET returns.
  1. More importantly, I asserted the causal chain "server returns 405 → client treats it as fatal". I can't support that from my own logs. No GET /mcp ever reaches my origin at all. Across the request windows I can still see (≈17:14–17:18Z and ≈20:48–21:12Z today), the connector's traffic is exclusively POST /mcp — all 200, sub-second — plus platform health checks on a separate path. Zero GETs on the MCP endpoint, authenticated or not.

So on my side the toast fires without the SSE/GET leg ever being attempted against the upstream server.

Worth noting the failing request in the OP's trace is GET https://claude.ai/v1/toolbox/shttp/mcp/<connector-id> — that is the claude.ai proxy route, not the upstream endpoint. I can't tell from outside whether that route forwards the GET leg upstream at all; from my origin's perspective it does not.

That may matter for where the fix belongs: "tolerate a 405 on the optional GET stream and fall back to POST-only" is correct per spec, but if the 405 originates inside the toolbox route rather than at the upstream server, then the tolerant handling — or the missing GET/SSE leg — needs to live there, and hardening only the upstream-facing path would not clear the toast.

The rest of my earlier comment stands as observed: the toasts recur, the chat UI additionally renders an "Unable to reach \<connector\>" card on the tool-call block, and the tool calls themselves succeed — the POST tools/call arrives and completes 200 in under a second at the exact timestamps the UI reports the connector unreachable.

mike-phipps · 1 month ago

We have this as well with a custom MCP integration. It seems to have started last night with the most recent Claude Desktop updates: 1.21459.3.0 or 1.21459.3.1.

njdawn · 1 month ago

++++1 -> we have this as well.

mike-phipps · 1 month ago

For anyone using MCP Apps-based integrations, this is a critical bug that breaks the integration. MCP Apps depend on the negotiated host capabilities and the client↔server notification channel, so with this bug they fail to load within the Claude client.

You can see this in the renderer console as it repeats:

"[MCP Apps] oncalltool handler replaced. Previous handler will no longer be called."

The widget starts to render and then collapses into an "Unable to reach [connector]" error where the widget should be. The tool call itself actually succeeds (it returns a result, e.g. a review_id), so it's not that the tool is unreachable or blocked. It looks like the widget loses the host connection it needs when the capability refresh fails, and it tears itself down to that error state.

0xultravioleta · 1 month ago

Adding an independent MCP Apps reproduction that may help narrow the impact beyond the recurring toast.

Our setup is a remote Streamable-HTTP MCP connector serving an MCP App. The app uses the official MCP Apps bridge and the supported external-navigation flow:

  1. initialize the App bridge;
  2. check the negotiated openLinks host capability;
  3. render an ordinary HTTPS URL returned by the tool;
  4. on a direct user click, call App.openLink({ url }).

The same app bundle, remote server, and HTTPS URL have succeeded in non-Windows Claude clients. On Windows, the host-mediated action does not complete reliably, which is consistent with the capability/connection failure described in this issue. A copy-to-clipboard fallback can reduce the damage, but it is not equivalent and does not help when the widget loses its host connection entirely.

I have not independently proven that the upstream cause is the GET/405 path, so I do not want to overstate that mechanism. The useful narrowing from this reproduction is:

  • the URL is a normal HTTPS URL;
  • the app does not use window.open, a raw popup, or direct iframe navigation;
  • the same MCP App code path can succeed on another client/run;
  • the failure affects a negotiated host capability and a user-initiated bridge call, not just background capability display;
  • the underlying tool flow can reach the point where an external user action is required, so losing the bridge can strand an otherwise valid workflow.

Update: correlated evidence and 405 boundary

After correlating another failure/recovery and inspecting the public host-side MCP Apps implementation, the immediate failure mode is more concrete:

  • The public AppBridge.connect() implementation documents that this happens when the bridge connects before the MCP client has completed server initialization. It calls getServerCapabilities() and throws the exact string Client server capabilities not available when the result is absent.
  • In the correlated reproduction, server-side application events showed that the underlying tool POST had succeeded and created the expected workflow state while Claude rendered the connector as unreachable. Refreshing the same conversation at the same viewport remounted the widget and allowed that same workflow to finish. This argues against an origin outage, a lost tool result, or iframe dimensions as the primary failure.
  • The 405 evidence must remain scoped carefully. A direct unauthenticated GET to the live origin returned 401 at the OAuth gate. Separately, local authenticated transport tests confirm that a stateless server without the optional notification stream returns the spec-valid 405 Allow: POST. However, we have not captured Claude sending that authenticated GET to the origin during a failure. The only measured failing 405 in this thread is on Claude's claude.ai/v1/toolbox/shttp/mcp/<connector-id> route.

So the evidence supports this chain:

capabilities absent during refresh → AppBridge.connect() throws → widget/host bridge is torn down or never becomes usable

It does not yet prove why the capabilities became absent. The proxy's GET/405 handling, capability-cache invalidation during refreshClient, and bridge-mount sequencing are the layers that need investigation. A legal optional-GET 405 should not clear otherwise valid POST-negotiated capabilities or collapse an MCP App whose tool result already exists.

The external-link symptom above was first isolated on Windows, but the underlying capabilities/widget failure should not be treated as Windows-only; the newer macOS reproduction in this thread shows the same lifecycle can recover after relaunch and degrade again later.

Please prioritize this as an integration-breaking host lifecycle regression rather than a cosmetic toast. MCP Apps rely on stable capability negotiation and the client/server notification bridge; when that state is lost, essential user actions and the entire embedded UI can become unusable even while the remote MCP server and POST tool flow are healthy.

ozgurozalp · 1 month ago

we have same issue

davidkm123 · 1 month ago

macOS reproduction on a newer build — the platform:windows label looks too narrow.

  • Client: Claude Desktop 1.22209.0 (com.anthropic.claudefordesktop), i.e. newer than the 1.21459.3.0 / 1.21459.3.1 builds named above.
  • OS: macOS 26.5 (25F71). No Windows machine involved anywhere in this reproduction.
  • Server: remote Streamable-HTTP MCP connector (details in my earlier comments).

It is not fixed in 1.22209.0, and the recurrence pattern may be the most useful part:

The update installed and relaunched the app today at 11:08 local. Immediately afterwards the connector looked completely healthy — no toast, and MCP Apps widgets rendered normally, including widgets in previous transcripts that had previously collapsed into the "Unable to reach \<connector\>" card. Those re-rendered fine from the stored tool results, which supports @mike-phipps's read that the tool result was intact all along and only the widget's host connection was lost.

After continued use in the same session, the toast and the "Unable to reach" card came back.

So on macOS this behaves like a lifecycle/degradation issue rather than a static failure at connect time: healthy immediately after a fresh client launch, degrading after some usage. That is consistent with the periodic capability-refresh path in the OP's trace (AutoSyncConnectorsToSessionrefreshClientlistTools) rather than with a handshake that fails deterministically on first connect. Relaunching the client clears it temporarily, which may serve as a stopgap for others but obviously is not a fix.

Origin-side observation from my earlier comment still holds at the same timestamps: the POST tools/call arrives and completes 200 in under a second exactly when the UI reports the connector unreachable, and no GET ever reaches my origin at all — so from the server's perspective there is nothing failing to observe.

njdawn · 1 month ago

Noting that this issue also occurs on the Claude web app (along the desktop app). The issue does not occur on mobile.

xuanyuzhou98 · 1 month ago

Happened to us as well

mike-phipps · 1 month ago

It seems like this issue was fixed? Haven't seen it reappear since Friday, at least on Windows + Claude Desktop.

Showing cached comments. Read the full discussion on GitHub ↗