Tool routing across servers

Now let's build the actual multi-server client. The core pattern: connect to all servers, collect all tools, build a routing map, and let the LLM use them all transparently.

10-mcp-client-multi.py
python
async def connect_to_server(self, server_name, server_config):
    """Connect to a single MCP server and register its tools."""
    server_params = StdioServerParameters(
        command=server_config["command"],
        args=server_config.get("args", []),
        env=None,
    )
    # AsyncExitStack manages multiple concurrent connections
    stdio_transport = await self.exit_stack.enter_async_context(
        stdio_client(server_params)
    )
    read, write = stdio_transport
    session = await self.exit_stack.enter_async_context(
        ClientSession(read, write)
    )
    await session.initialize()

    # Discover tools and build routing map
    tools_result = await session.list_tools()
    for tool in tools_result.tools:
        self.tool_to_session[tool.name] = session
        self.tool_server_map[tool.name] = server_name
        self.available_tools.append({
            "type": "function",
            "function": {
                "name": tool.name,
                "description": tool.description,
                "parameters": tool.inputSchema,
            }
        })

Connect to one server, discover its tools, register them in the routing map.

The key data structures: - tool_to_session: maps tool name to the session that owns it - tool_server_map: maps tool name to server name (for UI display) - available_tools: merged list of all tools in OpenAI format When the LLM calls a tool, we look up which session owns it and route the call.

10-mcp-client-multi.py
python
async def execute_tool(self, tool_name, tool_args):
    """Route a tool call to the correct server."""
    session = self.tool_to_session.get(tool_name)
    if not session:
        return f"Unknown tool: {tool_name}"
    result = await session.call_tool(
        tool_name, arguments=tool_args
    )
    return result

Tool routing: look up the session, call the tool. Same call_tool() as before.

Ordering exercise: Multi-server connection flow

Loading practice…

Validation checklist: Multi-server validation

Loading practice…

Quiz: Quiz

Loading practice…