Two of my remote Streamable HTTP MCP servers reliably fail after Cursor idle-suspends the connection

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Two of my remote Streamable HTTP MCP servers reliably fail after Cursor idle-suspends the connection (idle-suspending transport after Ns idle). Resume attempts fail at the network layer (fetch failed / “Timed out waiting for connection”), not with an HTTP error, and Cursor retries five times with growing backoff before giving up. The server is not down — an external curl against the exact same URL, same TLS negotiation, same headers, at the same moment the exchange fails inside Cursor, returns 200 in well under 100ms every time I’ve checked.

Five other remote HTTP MCP servers in the same ~/.cursor/mcp.json / plugin setup, hit by the same Shared MCP process, do not show this failure — they resume cleanly after being idle for the same or longer.

Steps to Reproduce

  1. Configure a remote Streamable HTTP MCP server (either via mcp.json directly or via an Agent Plugin’s mcp.json).
  2. Use a tool from it once, successfully.
  3. Leave it idle for >10 minutes (Cursor’s own idle-suspend threshold).
  4. Call a tool from it again.

Expected Behavior

A normal reconnect — same as mcp.json-based n8n-mcp, clickup, github, Figma Desktop, and blindrelay all do for me after an equal or longer idle period.

Actual, for two specific servers only: MCP HTTP exchange failed / Transient error connecting to streamableHttp server: fetch failed, repeated 5 times with backoff, then silence until the plugin/window is reloaded.

Operating System

MacOS

Version Information

IDE:
Version: 3.18.9
Commit: (Menu → About Cursor → Copy, paste the exact commit hash here before posting)

For AI issues: which model did you use?

N/A — not a model/AI-quality issue, this is the MCP client’s remote transport layer.

For AI issues: add Request ID with privacy disabled

N/A (not applicable — no chat Request ID is associated with a background MCP transport failure).

Additional Information

What I ruled out

  • Server down / slow / misconfigured — ruled out. curl --http1.1 and curl --http2 both succeed in <500ms at every timestamp I checked, including deliberately reproducing 125s/150s/190s idle gaps against the live server from a standalone script. GET /mcp correctly 405s (stateless JSON-only server, no SSE), stale Mcp-Session-Id is ignored rather than erroring, DNS has a single A record (no IPv6 blackhole).
  • HTTP/2 vs HTTP/1.1 — ruled out. Set cursor.general.disableHttp2: true, fully quit and reopened Cursor, same failure recurred at the next idle-suspend (16:42 and 17:12 in the log above).
  • Stdio vs Streamable HTTP — ruled out as the fix. I run this server as type: "streamable-http"; a teammate/prior session in this same setup tried bridging it through a local stdio wrapper process specifically to work around this bug, which just traded a clean remote failure for local spawn-path breakage (Cannot find module, ${PLUGIN_ROOT} not resolving, cwd resolving to the workspace instead of the plugin install dir) without touching the underlying resume issue.
  • Registered via Agent Plugin vs directly in mcp.json — ruled out as the differentiator. A second, unrelated server (different host, different cloud provider, Google-hosted vs. GCE VM behind Traefik) shows the same class of failure (Timed out waiting for connection to "...") even though it’s registered as a plain entry in ~/.cursor/mcp.json, not through a plugin.

What’s different about the two affected servers

Both of the affected servers require the client to authenticate and return a 401 with a WWW-Authenticate/challenge response when the credential is missing or invalid — one implements the full MCP OAuth discovery flow (resource_metadata, /authorize, /token), the other just checks a static x-api-key header and 403s. All five servers that resume cleanly for me (ClickUp, GitHub, n8n, Figma Desktop, a Blindrelay API) either use a credential Cursor already has cached from a completed OAuth flow, or send a static header that’s accepted unconditionally.

My best guess, offered as a hint rather than a diagnosis: something in Cursor’s transport-resume path after idle-suspend/stopped connection behaves differently when the server enforces a 401 challenge than when it doesn’t — possibly retrying with a stale credential/session state in a way that surfaces as a network-layer failure (fetch failed, connection timeout) instead of a clean 401, on some but not all reconnect attempts. I was not able to capture the actual request/response bytes during a live failure to confirm this further.

Log sample (from the affected server’s MCP output channel)

2026-09-03 16:22:46.184 [info] [Shared MCP process] Successfully connected to streamableHttp server
2026-09-03 16:22:46.208 [warning] [Shared MCP process] MCP HTTP exchange completed
2026-09-03 16:36:21.681 [info] [Shared MCP process] idle-suspending transport after 635s idle: plugin-talsec-opencti-opencti
2026-09-03 16:42:51.541 [warning] [Shared MCP process] MCP HTTP exchange failed
2026-09-03 16:42:51.541 [warning] [Shared MCP process] Transient error connecting to streamableHttp server: fetch failed
2026-09-03 16:42:58.200 [warning] [Shared MCP process] MCP HTTP exchange failed
2026-09-03 16:42:58.200 [warning] [Shared MCP process] Transient error connecting to streamableHttp server: fetch failed
2026-09-03 16:43:12.058 [warning] [Shared MCP process] MCP HTTP exchange failed
2026-09-03 16:43:12.058 [warning] [Shared MCP process] Transient error connecting to streamableHttp server: fetch failed
2026-09-03 16:43:41.813 [warning] [Shared MCP process] MCP HTTP exchange failed
2026-09-03 16:43:41.813 [warning] [Shared MCP process] Transient error connecting to streamableHttp server: fetch failed
2026-09-03 16:44:29.101 [warning] [Shared MCP process] MCP HTTP exchange failed
2026-09-03 16:44:29.102 [warning] [Shared MCP process] Transient error connecting to streamableHttp server: fetch failed

A curl against the same URL, from the same machine, one second after the 15:54:14 occurrence of this same failure earlier in the session, returned HTTP 200.

Aggregated over 3 days of logs for this one server: 1,165 fetch failed occurrences, always immediately preceded by either an idle-suspending transport line or a stopped connection / reconnect cycle, never a bare timeout with no preceding lifecycle event.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey @Efimster,

Quickest way to localize it is a two-setting bisection - one at a time, fully quit/reopen between each, then reproduce your idle gap:

  1. "http.fetchAdditionalSupport": false - routes MCP through a different network stack.
  2. (revert #1, then) "http.systemCertificates": false - keeps that stack but drops the system-cert merge.

Add these in Cmd+Shift+P → Preferences: Open User Settings (JSON). Whichever one makes it resume cleanly tells us exactly where it’s failing.

Two quick things:

  • Does it only fail after a sleep/wake or a network change, or also when the Mac stays awake on the same network the whole idle gap?
  • The commit hash from Cursor → About Cursor (the version field still has the placeholder).

Meantime, Reload Window (Cmd+Shift+P → Developer: Reload Window) clears the stuck state without a full restart. Once we know which setting flips it, I’ll get it in front of the team with a clear trigger and follow up here. (Side note: cursor.general.disableHttp2 doesn’t touch the MCP transport, so that test wouldn’t have changed anything.)

Thanks .

Build: Cursor 3.19.13 (stable), commit dd066f332fcea7382764400fde902f61920648d0

Idle pattern: Same as the original report — Cursor idle-suspends the Streamable HTTP transport after ~624s / ~10 min with no MCP traffic. This round I did not sleep/wake or change networks. Mac stayed awake on the same network the whole gap.

Test 1 — "http.fetchAdditionalSupport": false:
After ~12 minutes idle, the remote Streamable HTTP MCP resumed cleanly on the next tool call. Logs still show idle-suspending transport, then a later request succeeds instead of getting stuck.

I did not run test 2 ("http.systemCertificates": false). Test 1 already resumes, so I’m leaving that setting on.

(cursor.general.disableHttp2 — understood, not relevant to MCP transport.)

Hey @Efimster,
This isn’t your servers or auth; it’s on our side in how the MCP transport resumes after it parks an idle connection. We’ve let the team know and it’s an issue we’re tracking.

Worth trying to unblock you now - route MCP through the other network stack:

  1. Cmd+Shift+P → Preferences: Open User Settings (JSON)
  2. Add "http.fetchAdditionalSupport": false
  3. Fully quit (Cmd+Q) and reopen
  4. Idle one of the affected servers >12 min, then call a tool

If it resumes cleanly, that pins down the layer for us - could you let me know either way? I’ll post here when there’s an update.

Already did this on 3.19.13 (commit dd066f332fcea7382764400fde902f61920648d0).

"http.fetchAdditionalSupport": false is set. Fully quit/reopened. After >12 min idle on the same network (Mac awake, no sleep/wake), a tool call on the affected Streamable HTTP MCP resumed cleanly. Logs still show idle-suspending transport, then the next call succeeds.

So from here that stack unblocks resume. I’ll leave the setting on.

Are we ever going to fix this, Its killing my Product! I need this to work for all users using my MCP what is the fix supposed to be. The solution above is per client thats not tolerable.