Skip to content

mcp: run tool calls in worker threads - #312

Merged
aliceinwire merged 1 commit into
kernelci:mainfrom
bhcopeland:mcp-offload-tool-calls
Sep 17, 2026
Merged

aliceinwire merged 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.

@bhcopeland
bhcopeland force-pushed the mcp-offload-tool-calls branch 4 times, most recently from 704d043 to 759b821 Compare September 3, 2026 10:35
@aliceinwire

Copy link
Copy Markdown
Member

rebase

@bhcopeland
bhcopeland force-pushed the mcp-offload-tool-calls branch from 759b821 to a1f0044 Compare September 17, 2026 08:57
@bhcopeland

Copy link
Copy Markdown
Member Author

Rebased

@aliceinwire

aliceinwire commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

rebase, this conflicts with your previous PR

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 a1f0044 to 326ed9c Compare September 17, 2026 09:28
@aliceinwire
aliceinwire merged commit add5daa into kernelci:main Sep 17, 2026
7 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.

2 participants