implement dedicated background event loop for MCP operations#4794
implement dedicated background event loop for MCP operations#4794lorenzejay wants to merge 3 commits intomainfrom
Conversation
- Introduced a shared event loop running in a background thread to manage MCP connections efficiently. - Updated the MCPNativeTool class to ensure all async operations are dispatched to this dedicated loop, preventing cross-loop cancel-scope issues. - Enhanced error handling during tool execution to ensure clean disconnection and reconnection processes.
…p code - Eliminated the unused _mcp_shared_loop_thread variable to simplify the MCPNativeTool class. - Updated the _ensure_loop method to remove redundant checks for the event loop's running state. - Improved logging formatting for better readability during error handling.
| name="mcp-native-tool-loop", | ||
| ) | ||
| thread.start() | ||
| _mcp_shared_loop = loop |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| """Submit *coro* to the dedicated loop and block until it completes.""" | ||
| loop = self._ensure_loop() | ||
| future = asyncio.run_coroutine_threadsafe(coro, loop) | ||
| return future.result() |
There was a problem hiding this comment.
Shared MCPClient races when tools run concurrently
High Severity
Multiple MCPNativeTool instances from the same MCP server share a single MCPClient (assigned in tool_resolver.py). The crew agent executor runs tools in parallel via ThreadPoolExecutor, and each tool now dispatches _run_async to the same dedicated event loop via run_coroutine_threadsafe. This creates concurrent async Tasks that interleave connect/disconnect/call_tool on the shared, unprotected MCPClient. One task can disconnect and replace the session while another task is mid-call_tool. Previously, each call used asyncio.run() on separate threads with isolated event loops, preventing this interleaving.
Additional Locations (1)
|
This PR is stale because it has been open for 45 days with no activity. |


Note
Medium Risk
Changes core MCP tool execution to use a shared background event loop and cross-thread coroutine dispatch, which can impact concurrency behavior (deadlocks/hangs) and connection lifecycle handling. Scope is limited to
MCPNativeToolbut affects all native MCP tool invocations.Overview
MCPNativeToolnow uses a single shared asyncio event loop running in a background thread, submitting each invocation viarun_coroutine_threadsafeinstead of creating per-call event loops/threads.Tool execution was adjusted to always run
connect → call_tool → disconnectwithin the same task on that loop, with more defensive cleanup and one-time reconnect retry (disconnect failures are logged at debug rather than raising).Written by Cursor Bugbot for commit 80f6c17. This will update automatically on new commits. Configure here.