fix(mcp): move blocking stdio I/O off the cooperative pool (#431)
AnyMCPConnection.callTool carried a comment saying it ran blocking stdio I/O "off the cooperative thread pool" via Task.detached. Task.detached does not do that: it changes context inheritance -- priority, task-locals, cancellation -- not the executor. A detached task is still scheduled on Swift's cooperative executor, so the synchronous MCPConnection.callTool kept occupying a cooperative worker while it took an NSLock and blocked in read(2) on the subprocess. The cooperative pool is sized to the core count, so a handful of concurrent MCP tool calls could stall unrelated async work that had nothing to do with MCP. Now dispatched to DispatchQueue.global(qos: .userInitiated) and bridged back with withCheckedThrowingContinuation, which actually leaves the pool. Verified the MCP path still works end to end after the executor change: `apfel --mcp mcp/calculator/server.py "add 41 and 1"` -> tool executed, 42. Diff taken from candidate PR #442. Closes #431 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011ccLBbEaVVd4sJyUd5wyhA
A
Arthur Ficial committed
4f8fea9d8289501092b2cb46dc23ef09bd848bac
Parent: 2e06983