Skip to content

Deliver MCP responses larger than the DO storage value cap - #1503

Merged
RhysSullivan merged 2 commits into
mainfrom
fix-oversize-mcp-response
Jul 30, 2026
Merged

Deliver MCP responses larger than the DO storage value cap#1503
RhysSullivan merged 2 commits into
mainfrom
fix-oversize-mcp-response

Conversation

@RhysSullivan

Copy link
Copy Markdown
Collaborator

Problem

Rendering an artifact through a remote MCP client still hung after #1502. That PR fixed what the ui://executor/shell.html resource serves (the real ~5 MB shell document instead of an inert placeholder) — but the DO transport could not deliver it. sendOnStream persisted every outbound message with storage.put for reconnect replay BEFORE writing the live SSE frame, and DO storage caps each value at 128 KiB, so the put threw, the live write never ran, and the client sat on keepalives forever. Confirmed against production: resources/read of the shell resource returned 200 + keepalives and never a frame, while tools/list on the same session worked.

Fix (patches/agents@0.17.3.patch)

  • DurableObjectEventStore.storeEvent skips persistence for messages over a 120 KiB guard (headroom under the 128 KiB cap), logs mcp_event_store_skipped_oversize, and resolves undefined — the caller then writes the live SSE frame without a replay id:. The stream sequence does not advance on a skip.
  • sendOnStream treats any storeEvent failure (cap, storage outage) as best-effort: log mcp_event_store_put_failed, surface via onerror, and still deliver the live frame.
  • The documented cost: an oversize response that races a dropped connection is not replayable on reconnect. Delivered-usually strictly dominates delivered-never.

Verification

  • New unit tests pin the skip contract (oversize skip + warning, sequence untouched, byte-cap eviction on storable sizes) — 9/9 green, full packages/hosts/cloudflare suite 56/56.
  • New e2e cloud/mcp-oversize-response.test.ts: real workerd topology, resources/read of the actual shell resource with a 60 s hang guard, asserting the >128 KiB document arrives with its identity marker. Failed with a hang before the patch, passes after.
  • typecheck, lint, format all green.

The DO transport persisted every outbound message for reconnect replay
BEFORE writing the live SSE frame, and storage.put of a value over the
128 KiB DO cap throws — so an oversize response (the ~5MB
ui://executor/shell.html resource) was neither stored nor delivered and
the client hung on keepalives forever. Found live in prod after #1502
made the shell resource actually serve its bytes.

- storeEvent skips persistence for messages over a 120 KiB guard,
  logging mcp_event_store_skipped_oversize and returning undefined; the
  caller delivers the live frame without a replay id.
- sendOnStream treats any storeEvent failure as best-effort: log, then
  still write the live SSE frame.
- New e2e (cloud/mcp-oversize-response.test.ts) drives resources/read of
  the shell over real workerd and fails on a hang.
- Event-store unit tests updated for the skip contract.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 30, 2026

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 failed
View logs
executor-cloud 8a0d00e Jul 30 2026, 04:34 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 30, 2026

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 8a0d00e Commit Preview URL

Branch Preview URL
Jul 30 2026, 04:33 AM

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@1503

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@1503

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@1503

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@1503

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@1503

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@1503

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@1503

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@1503

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@1503

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@1503

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@1503

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@1503

executor

npm i https://pkg.pr.new/executor@1503

commit: 64a3faf

@RhysSullivan
RhysSullivan marked this pull request as ready for review July 30, 2026 04:32
@RhysSullivan
RhysSullivan merged commit a7c4689 into main Jul 30, 2026
17 of 19 checks passed
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