Skip to content

fix(mcp): deliver editor-bridge tool calls serially and hold the lease while calls are pending - #644

Open
ngocht wants to merge 1 commit into
CoreBunch:mainfrom
ngocht:fix/mcp-bridge-pending-lease
Open

ngocht wants to merge 1 commit into
CoreBunch:mainfrom
ngocht:fix/mcp-bridge-pending-lease

Conversation

@ngocht

@ngocht ngocht commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Summary

MCP edits routed to the live editor were slow and intermittently failed in production.

The editor executes relayed tools strictly one at a time (useMcpWorkspaceBridge awaits each tool and its result POST before reading the next line), but the server pushed a whole batch at once:

  • Every call's 90s timeout started at push time, so calls queued behind slow ones (render snapshots, a background tab) timed out before the editor even reached them.
  • The 120s idle lease was only re-armed by pushes. A batch whose serial execution outlasted it closed the stream mid-batch: the in-flight call was rejected ([ai/transport] bridge … closed with 1 pending tool result(s)., seen three times in one hour on a production site) and the editor's late result POST got a 404 from /admin/api/ai/tool-result.

Changes:

  • createBridge gains an opt-in serial option. The next request is emitted only after the previous one settles, and its timeout starts on emit. Queued calls still reject on abort/destroy without being emitted. The chat bridge is unchanged.
  • The MCP editor bridge uses serial delivery. Its idle lease re-arms instead of closing while any call is pending, queued or in flight. Each pending call is bounded by the per-call timeout, so an orphaned stream still drains and closes.
  • docs/features/mcp-connectors.md describes the new delivery and lease behavior.

Impact: no throughput loss (the editor was already serial); queued MCP calls no longer time out spuriously, and batches are no longer cut by the lease.

Verification

  • bun run build — ran tsc -p tsconfig.app.json and tsc -p tsconfig.node.json (clean)
  • bun test — ran bun test src/__tests__/ai/ server/ai/: 277 pass. New tests: serial ordering, timeout starts on emit, timeout releases the slot, destroy/abort reject queued calls unsent, a batch outlasting the lease survives, no recycle while a call is pending.
  • bun run lint — eslint on the changed files (clean)
  • Docker/deployment check, if relevant

Checklist

  • Tests cover behavior changes.
  • Docs were updated when behavior, config, deployment, or public surfaces changed.
  • No compatibility shim was added for old pre-release behavior.
  • No secrets, local databases, uploads, or generated artifacts are included.

🤖 Generated with Claude Code

…e while calls are pending

The editor runs relayed MCP tools strictly one at a time, but the server
pushed a whole batch at once. Every call's 90s timeout started at push time,
so calls queued behind slow ones (render snapshots, a background tab) timed
out before the editor reached them. The 120s idle lease was only re-armed by
pushes, so a batch whose serial execution outlasted it closed the stream
mid-batch: the in-flight call was rejected ("closed with 1 pending tool
result(s)") and the editor's late result POST got a 404.

- createBridge gains an opt-in `serial` option: the next request is emitted
  only after the previous one settles, and its timeout starts on emit.
  Queued calls still reject on abort/destroy without being emitted. The chat
  bridge is unchanged.
- The editor bridge uses serial delivery, and its idle lease re-arms instead
  of closing while any call is pending. Each pending call is bounded by the
  per-call timeout, so an orphaned stream still drains and closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ngocht
ngocht marked this pull request as ready for review October 14, 2026 18:12

This branch has not been deployed

No deployments
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