feat(mcp_client): adopt per-instance context–manager pattern from smolagents
This PR updates the mcp_client implementation to use a per-instance context-manager pattern borrowed from smolagents, fixing cross-talk and cancel-scope errors when multiple clients are connected concurrently.
Changes Made
- Per-instance context management: Each MCPClient now maintains its own AsyncExitStack, preventing cancel scope conflicts between multiple client instances
- Improved error handling: Better cleanup logic that prevents cascade failures when one client fails
- Enhanced async context manager support: Added proper
__aenter__and__aexit__methods for async context manager usage - Backward compatibility: Maintains existing API while adding new functionality
- Better logging: Enhanced debug logging for troubleshooting connection issues
Problem Solved
The original implementation had a shared cancel scope issue where closing one MCP client would interfere with others, causing the error:
tinyagent.mcp_client - ERROR - Error during client cleanup: Attempted to exit a cancel scope that isn't the current tasks's current cancel scope
This implementation adopts the proven pattern from smolagents that isolates each client's context, allowing multiple MCP clients to coexist without interference.
Testing
The updated implementation maintains full backward compatibility with existing code while fixing the multi-client issue. The example usage demonstrates both legacy and new async context manager patterns.
A developer on Askdev.AI requested this update