Repository navigation
mcp: a host can pause between the calls of a run_batch - #1271
Merged
Merged
Conversation
A batch is one synchronous operation, so a long one holds the event loop for its whole length and the host's timers and I/O wait for it. core's batch is now a sequence that stops after each call; the synchronous operation runs it through as before. A host that gives betweenBatchCalls is awaited after each call. Only a host with a scene of its own per request should: the batch is planned on the scene as its first call found it and applied after its last. Without the hook a batch is uninterrupted. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
3 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
run_batchis one synchronous operation: its calls run back to back and nothing else on the server runs until the last one returns. A batch of several expensive calls (whole-scene checks on a large building) holds the event loop for its whole length, so a host's timers and I/O wait for it. A host that keeps a lease alive with a timer loses it during such a batch.This adds an opt-in pause after each call:
createBatchSteps, exported asRUN_BATCH_STEPS).AGENT_OPERATIONS.run_batchruns it through in one go, as before, so the chat and every existing caller are unchanged.createPascalMcpServer({ betweenBatchCalls }). When a host gives it, the batch tool runs one call at a time, each in the scene's scope, and awaits the host after each.Why opt-in. Today a batch plans on the scene and applies its changes in one uninterrupted stretch, so no other call can reach the scene in between. A server that serves concurrent calls on one bridge (the standalone server) relies on that. With a pause, the batch is planned on the scene as its first call found it and applied after its last, so only a host that builds a scene of its own for each request should give the hook. Without it nothing changes.
The batch's own behaviour is the same: calls in order, each on the scene the calls before it left;
stopapplies nothing when a call is refused,skipreports it and applies the rest; same result shape; one history step.How to test
cd packages/mcp && bun test src/tools/run-batch-pause.test.ts: with a pausing host, the pause runs after each of four calls and sees the scene as the batch found it; the batch then lands whole and one undo removes it. Four batches (plain, stopped by a refusal, past a refusal withskip, an unknown tool) answer the same with and without the pause.bun test src/toolsinpackages/mcp(1,290 pass) andbun test src/agent-operationsinpackages/core(1,558 pass).Screenshots / screen recording
N/A — non-visual change
Checklist
bun devbun checkto verify)mainbranch🤖 Generated with Claude Code
Note
Medium Risk
Touches shared batch semantics and MCP
run_batchexecution path; opt-in only, but hosts usingbetweenBatchCallsrely on planning on the initial scene snapshot until final apply—wrong usage on a shared bridge could race concurrent tool calls.Overview
Adds an opt-in hook so MCP hosts can yield the event loop between successive
run_batchtool calls instead of blocking for the whole batch.Core splits batch execution into a generator (
createBatchSteps/ exportedRUN_BATCH_STEPS) thatyields after each call while still planning on the same working scene and merging to one history step at the end.createBatchOperationandAGENT_OPERATIONS.run_batchunchanged—they drain the generator synchronously, so the chat and other existing callers behave as before.MCP accepts
createPascalMcpServer({ betweenBatchCalls }). When set,run_batchruns throughRUN_BATCH_STEPSinside the scene scope and awaits the host callback after every call; order, refusal policy (stop/skip), result shape, and single undo step stay the same. Hosts serving one shared bridge on concurrent requests should omit the hook.Docs in
agent-surfaces.mddescribe when to use it. New tests inrun-batch-pause.test.tsassert pauses see the pre-application scene and that paused vs uninterrupted batches agree.Reviewed by Cursor Bugbot for commit 4c60a75. Bugbot is set up for automated code reviews on this repo. Configure here.