Skip to content

Conversation

@pradeeptac
Copy link

@pradeeptac pradeeptac commented Jan 17, 2026

This PR ensures that synchronous tools are never executed inline on the event loop.
All sync functions invoked through call_fn_with_arg_validation are now offloaded to worker threads using anyio.to_thread.run_sync, preventing event loop starvation.


Motivation and Context

Previously, synchronous tool functions were executed directly when fn_is_async=False, which could block the event loop if the function performed blocking operations (e.g., time.sleep, I/O, CPU-heavy work).
This caused:
Event loop starvation
Delayed scheduling of other async tasks
Subtle concurrency bugs in FastMCP tool execution

This change guarantees that sync tools behave safely in async contexts, aligning with AnyIO best practices and expected MCP runtime behavior.


How Has This Been Tested?

Added regression tests to verify that:
A blocking synchronous tool does not block the event loop
Concurrent async tasks continue to run while a sync tool executes
Added a thread-identity test to assert that synchronous tools run in a worker thread rather than the event loop thread
All existing tests pass locally


Breaking Changes

No breaking changes.
Behavior is now correct and consistent with expectations for async execution environments.


Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

This change brings FastMCP tool execution in line with AnyIO’s concurrency model.
Prevents a class of hard-to-debug latency and scheduling issues when tools perform blocking work.
The new tests act as regression guards against future accidental inline execution of sync tools.

@pradeeptac pradeeptac changed the title Offload sync tool execution Run synchronous tools in worker threads to avoid blocking the event loop Jan 17, 2026
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