Skip to content

mcp: run tool calls in worker threads - #312

Open
bhcopeland wants to merge 1 commit into
kernelci:mainfrom
bhcopeland:mcp-offload-tool-calls
Open

mcp: run tool calls in worker threads#312
bhcopeland wants to merge 1 commit into
kernelci:mainfrom
bhcopeland:mcp-offload-tool-calls

Conversation

@bhcopeland

Copy link
Copy Markdown
Member

FastMCP awaits an async tool but calls a sync one inline on the event loop. Every tool here is sync and makes a blocking request, so calls were serialised across all sessions: measured against a running server, a trivial list_trees took 58.66s instead of 0.14s while one slow call was in flight.

Register an async wrapper that hands the call to a worker thread. The dashboard tools funnel through one registration site and inherit this; the Maestro tools are wrapped individually, so a new one needs the decorator adding.

Concurrency also makes the per-call stdout redirect unsafe, as it mutates a global that overlapping calls can restore out of order, so that becomes a single redirect for the life of the server, entered inside the stdio transport once it has taken stdout for the protocol writer. anyio is imported where it is used, since kcidev.main imports every subcommand at startup and anyio comes only with the mcp extra.

FastMCP awaits an async tool but calls a sync one inline on the event
loop. Every tool here is sync and makes a blocking request, so calls
were serialised across all sessions: measured against a running
server, a trivial list_trees took 58.66s instead of 0.14s while one
slow call was in flight.

Register an async wrapper that hands the call to a worker thread. The
dashboard tools funnel through one registration site and inherit this;
the Maestro tools are wrapped individually, so a new one needs the
decorator adding.

Concurrency also makes the per-call stdout redirect unsafe, as it
mutates a global that overlapping calls can restore out of order, so
that becomes a single redirect for the life of the server, entered
inside the stdio transport once it has taken stdout for the protocol
writer. anyio is imported where it is used, since kcidev.main imports
every subcommand at startup and anyio comes only with the mcp extra.

Signed-off-by: Ben Copeland <ben.copeland@linaro.org>
@bhcopeland
bhcopeland force-pushed the mcp-offload-tool-calls branch from 7f19cd2 to 376d7d4 Compare September 1, 2026 10:39
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