ClientManager
The ClientManager class provides centralized management for multiple MCP (Model Context Protocol) server connections and tool registration.
Overview
ClientManager is a singleton class that extends MultiClientManager, inheriting all of its functionality while adding singleton pattern support for global accessibility. It handles multiple MCP clients, resolves tool name conflicts through automatic remapping, routes tool calls to appropriate servers, and automatically registers all discovered tools into the ToolsManager.
Inheritance
ClientManager → MultiClientManagerClientManager inherits all methods and properties from MultiClientManager and adds:
- Singleton instance management via
__new__() - Global single-instance access pattern
Properties
Inherited from MultiClientManager:
clients(list[MCPClient]): List of all registered MCP clientsscript_to_clients(dict[str, MCPClient]): Mapping from server script paths to clientsname_to_clients(dict[str, MCPClient]): Mapping from tool names to their owning clientstools_remapping(dict[str, str]): Tool name remapping (original → remapped)reversed_remappings(dict[str, str]): Reverse remapping (remapped → original)tools_manager(MultiToolsManager): The tool manager where MCP tools are registered_is_initialized(bool): Whether all clients have been initialized
Methods
__new__() -> Self
Creates or returns the singleton instance of ClientManager.
Returns:
Self: The singleton instance
Note: ClientManager implements the singleton pattern - only one instance exists per application. Every call to ClientManager() returns the same instance.
Example:
from amrita_core.tools.mcp import ClientManager
manager1 = ClientManager()
manager2 = ClientManager()
print(manager1 is manager2) # True - same instance__init__() -> None
Initializes the ClientManager (runs only once due to singleton pattern).
Note: Initialization logic executes only on the first instantiation.
All other methods are inherited from MultiClientManager:
get_client_by_script(server_script)- Get client by server scriptget_client_by_tool_name(tool_name)- Find client owning a specific toolregister_only(client)/register_only(server_script)- Register without initializinginitialize_this(server_script)- Register and initialize single serverinitialize_scripts_all(scripts)- Initialize multiple serversinitialize_all()- Connect to all registered serversupdate_tools(client)- Update tools from a clientunregister_client(script_name)- Remove a serverreinitialize_all()- Refresh all connections
See MultiClientManager documentation for detailed method descriptions.
Complete Usage Example
import asyncio
from amrita_core.tools.mcp import ClientManager
async def main():
# Get the singleton instance
manager = ClientManager()
# Method 1: Configuration-based setup (recommended)
# See AmritaConfig for declarative configuration
# Method 2: Programmatic setup
scripts = ["/path/to/weather.mcp", "/path/to/database.mcp", "/path/to/calendar.mcp"]
# Register and initialize all servers
await manager.initialize_scripts_all(scripts)
# Check available tools
available_tools = manager.tools_manager.get_tools()
print(f"Available tools: {list(available_tools.keys())}")
# Find which client owns a tool
weather_client = await manager.get_client_by_tool_name("get_weather")
print(f"Tool owner: {weather_client.server_script}")
# Handle duplicate tool names (automatic remapping)
# If two servers have "search" tool, second one becomes "referred_42_search"
# Dynamically add a new server
await manager.initialize_this("/dynamic/new-server.mcp")
# Remove a server
await manager.unregister_client("/path/to/old-server.mcp")
# Reinitialize all (refresh connections)
await manager.reinitialize_all()
asyncio.run(main())Key Features
Automatic Tool Registration
All tools from registered MCP servers are automatically added to ToolsManager and become available to agents.
Tool Name Conflict Resolution
When multiple servers provide tools with the same name:
- First registration keeps original name
- Subsequent registrations are auto-remapped (e.g.,
referred_42_search) - Warning logs are generated for conflicts
Intelligent Routing
When a tool is called, ClientManager automatically routes the request to the correct MCP server based on tool name mapping.
Thread Safety
All operations are protected by an async lock (_lock) to ensure thread-safe access to shared state.
Lifecycle Management
Handles connection establishment, tool discovery, registration, and cleanup for multiple servers simultaneously.
Error Handling
- Server initialization failure: Logs error, continues with other servers (unless
fail_then_raise=True) - Tool execution errors: Handled by individual
MCPClient, returns structured error JSON - Duplicate tools: Auto-remapped with warning logs
- Connection loss: Automatic retry on next tool call
Related Documentation
- MCPClient - Individual client management
- ToolsManager - Tool registration system
- MCP Server Integration - Comprehensive integration guide
- AmritaConfig - Configuration-based setup
