Multiple MCP Servers
Understanding how to connect to multiple MCP servers with Kern
Kern's MCP integration also supports handling connections to multiple servers, specifying server parameters and using your own MCP servers
There are two approaches to this:
- Using multiple
MCPToolsinstances - Using a single
MultiMCPToolsinstance
Using multiple MCPTools instances
1import asyncio2import os34from kern.agent import Agent5from kern.tools.mcp import MCPTools678async def run_agent(message: str) -> None:9 """Run the Airbnb and Google Maps agent with the given message."""1011 env = {12 **os.environ,13 "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"),14 }1516 # Initialize and connect to multiple MCP servers17 airbnb_tools = MCPTools(command="npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt")18 google_maps_tools = MCPTools(command="npx -y @modelcontextprotocol/server-google-maps", env=env)19 await airbnb_tools.connect()20 await google_maps_tools.connect()2122 try:23 agent = Agent(24 tools=[airbnb_tools, google_maps_tools],25 markdown=True,26 )2728 await agent.aprint_response(message, stream=True)29 finally:30 await airbnb_tools.close()31 await google_maps_tools.close()323334# Example usage35if __name__ == "__main__":36 # Pull request example37 asyncio.run(38 run_agent(39 "What listings are available in Cape Town for 2 people for 3 nights from 1 to 4 August 2025?"40 )41 )Using a single MultiMCPTools instance
1import asyncio2import os34from kern.agent import Agent5from kern.tools.mcp import MultiMCPTools678async def run_agent(message: str) -> None:9 """Run the Airbnb and Google Maps agent with the given message."""1011 env = {12 **os.environ,13 "GOOGLE_MAPS_API_KEY": os.getenv("GOOGLE_MAPS_API_KEY"),14 }1516 # Initialize and connect to multiple MCP servers17 mcp_tools = MultiMCPTools(18 commands=[19 "npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt",20 "npx -y @modelcontextprotocol/server-google-maps",21 ],22 env=env,23 )24 await mcp_tools.connect()2526 try:27 agent = Agent(28 tools=[mcp_tools],29 markdown=True,30 )3132 await agent.aprint_response(message, stream=True)33 finally:34 # Always close the connection when done35 await mcp_tools.close()363738# Example usage39if __name__ == "__main__":40 # Pull request example41 asyncio.run(42 run_agent(43 "What listings are available in Cape Town for 2 people for 3 nights from 1 to 4 August 2025?"44 )45 )Allowing partial failures with MultiMCPTools
If you are connecting to multiple MCP servers using the MultiMCPTools class, an error will be raised by default if connection to any MCP server fails.
If you want to avoid raising in that case, you can set the allow_partial_failures parameter to True.
This is useful if you are connecting to MCP servers that are not always available, and don't want to exit your program if one of the servers is not available.
1import asyncio2from os import getenv34from kern.agent import Agent5from kern.tools.mcp import MultiMCPTools678async def run_agent(message: str) -> None:9 # Initialize the MCP tools10 mcp_tools = MultiMCPTools(11 [12 "npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt",13 "npx -y @modelcontextprotocol/server-brave-search",14 ],15 env={16 "BRAVE_API_KEY": getenv("BRAVE_API_KEY"),17 },18 timeout_seconds=30,19 # Set the allow_partial_failure to True to allow for partial failure connecting to the MCP servers20 allow_partial_failure=True,21 )2223 # Connect to the MCP servers24 await mcp_tools.connect()2526 # Use the MCP tools with an Agent27 agent = Agent(28 tools=[mcp_tools],29 markdown=True,30 )31 await agent.aprint_response(message)3233 # Close the MCP connection34 await mcp_tools.close()353637# Example usage38if __name__ == "__main__":39 asyncio.run(run_agent("What listings are available in Barcelona tonight?"))40 asyncio.run(run_agent("What's the fastest way to get to Barcelona from London?"))Avoiding tool name collisions
When using multiple MCP servers, you may encounter tool name collisions. This often happens when the same tool is available in multiple of the servers you are using.
To avoid this, you can use the tool_name_prefix parameter. This will add the given prefix to all tool names coming from the MCPTools instance.
1import asyncio23from kern.agent import Agent4from kern.tools.mcp import MCPTools567async def run_agent():8 # Development environment tools9 dev_tools = MCPTools(10 transport="streamable-http",11 url="https://kern.ndx.rocks/mcp",12 # By providing this tool_name_prefix, all the tool names will be prefixed with "dev_"13 tool_name_prefix="dev",14 )15 await dev_tools.connect()1617 agent = Agent(tools=[dev_tools])18 await agent.aprint_response("Which tools do you have access to? List them all.")1920 await dev_tools.close()212223if __name__ == "__main__":24 asyncio.run(run_agent())