Skip to content

Stop evicting standalone MCP listeners - #1754

Merged
RhysSullivan merged 1 commit into
mainfrom
fix-standalone-listener-supersede
Aug 26, 2026
Merged

Stop evicting standalone MCP listeners#1754
RhysSullivan merged 1 commit into
mainfrom
fix-standalone-listener-supersede

Conversation

@RhysSullivan

Copy link
Copy Markdown
Collaborator

Problem

Every standalone SSE listener (bare GET) on a streamable-HTTP session shares one stream id, and handleGetRequest applied latest-listener-wins to it: each new listener closed the previous one. Clients that hold two listeners — mcp-remote opens one at connect and a second when it forwards notifications/initialized — evict each other forever, since every eviction triggers the SDK reconnect that evicts the other side. One production session showed ~55,600 listener GETs over 6.75h (~2.3/s) against 106 POSTs, and the affected user saw permanent disconnect/reconnect churn. Reproduced end-to-end with stock mcp-remote 0.1.37: a 4-minute idle session settles into ~0.8 GET/s with every response delivered twice.

Fix

In patches/agents@0.17.3.patch:

  • Standalone listeners now attach alongside each other instead of superseding; supersedePriorStreamConnections only applies to single-owner POST streams. Dead listeners are reaped by keepalive write failures and max-age rotation.
  • sendStandalone routes server-initiated messages to the newest attachment (most likely live), still exactly one stream per message.
  • Concurrent fresh GETs no longer both replay the same undelivered stream (first live replayer wins; at-least-once is preserved if it dies before acking).
  • onConnect closes the WS with 1011 when the transport is missing instead of silently dropping the request, which previously left clients hanging ~30s against a half-initialized DO.

Verification

  • New cloud e2e scenario repro-listener-supersede.test.ts: two reconnecting listeners previously produced 1,581 stream opens in 15s (median life 16ms); with the fix both stay open (passes; single-listener control unchanged).
  • Same scenario as the production repro against a deployed worker running this patch: stock mcp-remote 0.1.37, one routine deploy mid-run — 20 GETs over 6 minutes (was 1,049 in 9.5 min), tool calls keep working through the deploy, GET rate settles instead of ramping.
  • format:check, lint, typecheck, test all green.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing ccdaa36 Commit Preview URL

Branch Preview URL
Aug 26 2026, 06:21 AM

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud ccdaa36 Aug 26 2026, 06:22 AM

@RhysSullivan
RhysSullivan marked this pull request as ready for review August 26, 2026 06:23
@RhysSullivan
RhysSullivan merged commit 6574ab1 into main Aug 26, 2026
43 checks passed
@RhysSullivan
RhysSullivan deleted the fix-standalone-listener-supersede branch August 26, 2026 06:24
RhysSullivan added a commit to jadch/executor that referenced this pull request Aug 28, 2026
The agents@0.17.3 patch was rewritten on main by UsefulSoftwareCo#1754 (standalone
listeners attach alongside each other instead of superseding, plus the
_replayInFlight guard). Re-rolled this branch's change with bun patch on
top of main's patched dist rather than merging the patch file textually:
the Last-Event-ID branch no longer drains other streams, and the helper
is now replayUndeliveredResponsesOnFreshGet, called only from the
cursorless GET path. The fresh-GET fallback and its in-flight guard are
unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant