Skip to main content

Overview

MultiMCPHandler allows you to connect to multiple MCP servers at once, aggregating all their tools into a unified interface.

Basic Usage

from upsonic import Agent, Task
from upsonic.tools.mcp import MultiMCPHandler

# Create multi-handler with multiple servers
multi_handler = MultiMCPHandler(
    commands=[
        "uvx mcp-server-sqlite --db-path /tmp/db1.db",
        "uvx mcp-server-sqlite --db-path /tmp/db2.db",
    ],
    timeout_seconds=60
)

# Create agent
agent = Agent(
    name="Multi-MCP Agent",
    role="Multi-database operations specialist",
    goal="Demonstrate MultiMCPHandler with multiple SQLite databases",
    tool_call_limit=10
)

# Create task
task = Task(
    description="""
    IMPORTANT: You have access to TWO separate SQLite databases.
    - Database 1: Use tools from the first MCP server connection
    - Database 2: Use tools from the second MCP server connection
    
    Step 1: Using Database 1, create a 'users' table with:
    - id (integer primary key)
    - username (text)
    - email (text)
    - created_at (text)
    
    Insert 3 sample users into Database 1.
    
    Step 2: Using Database 2, create a 'posts' table with:
    - id (integer primary key)
    - user_id (integer)
    - title (text)
    - content (text)
    - published (boolean)
    
    Insert 4 sample posts into Database 2.
    
    Step 3: Query Database 1 to show all users.
    Step 4: Query Database 2 to show all posts.
    """,
    tools=[multi_handler]
)

# Execute
result = agent.do(task)
print(result)

Parameters

  • commands (List[str]): List of command strings for each server
  • server_params_list: List of server parameter objects
  • timeout_seconds (int): Connection timeout for all servers (default: 5)
  • include_tools (List[str]): Optional list of tool names to include from all servers
  • exclude_tools (List[str]): Optional list of tool names to exclude from all servers
  • tool_name_prefix (str): Optional single prefix for all servers (becomes prefix_0, prefix_1, etc.)
  • tool_name_prefixes (List[str]): Optional list of specific prefixes for each server (must match number of servers)

Features

  • Multiple Connections: Connect to multiple servers simultaneously
  • Unified Interface: All tools from all servers available in one place
  • Server Introspection: Get information about each server and its tools
  • Automatic Cleanup: Properly closes all connections after task completion

Server Introspection

from upsonic.tools.mcp import MultiMCPHandler

multi_handler = MultiMCPHandler(
    commands=[
        "uvx mcp-server-sqlite --db-path /tmp/db1.db",
        "uvx mcp-server-sqlite --db-path /tmp/db2.db",
    ],
    timeout_seconds=60
)

# Get tools first (this triggers connection if needed)
tools = multi_handler.get_tools()

# Get server information
print(f"Server Count: {multi_handler.get_server_count()}")
print(f"Tool Count: {multi_handler.get_tool_count()}")
print(f"Tools by Server: {multi_handler.get_tools_by_server()}")

# Get detailed server info
server_info = multi_handler.get_server_info()
for info in server_info:
    print(f"Server {info['index']}: {info['server_name']} ({len(info['tools'])} tools)")

Example with Structured Output

from upsonic import Agent, Task
from upsonic.tools.mcp import MultiMCPHandler
from pydantic import BaseModel

class MultiDatabaseReport(BaseModel):
    """Structured output for multi-database operations."""
    databases_used: int
    total_tables: int
    total_records: int
    operations_summary: str

# Create multi-handler
multi_handler = MultiMCPHandler(
    commands=[
        "uvx mcp-server-sqlite --db-path /tmp/companies.db",
        "uvx mcp-server-sqlite --db-path /tmp/employees.db",
    ],
    timeout_seconds=60
)

# Create agent
agent = Agent(
    name="Multi-MCP Structured Agent",
    role="Multi-database operations with structured reporting",
    goal="Demonstrate structured output with MultiMCPHandler",
    tool_call_limit=10
)

# Create task with structured output
task = Task(
    description="""
    IMPORTANT: You have access to TWO separate SQLite databases.
    - Database 1: Use tools from the first MCP server connection
    - Database 2: Use tools from the second MCP server connection
    
    Step 1: Using Database 1, create a 'companies' table with:
    - id (integer primary key)
    - name (text)
    - industry (text)
    - revenue (real)
    
    Insert 3 tech companies into Database 1.
    
    Step 2: Using Database 2, create an 'employees' table with:
    - id (integer primary key)
    - name (text)
    - position (text)
    - salary (real)
    - company_id (integer)
    
    Insert 5 sample employees into Database 2.
    
    Step 3: Provide a structured report with:
    - Number of databases used (should be 2)
    - Total tables created (should be 2)
    - Total records inserted (should be 8: 3 companies + 5 employees)
    - Operations summary describing what was done
    """,
    tools=[multi_handler],
    response_format=MultiDatabaseReport
)

# Execute
result = agent.do(task)
print(f"Databases Used: {result.databases_used}")
print(f"Total Tables: {result.total_tables}")
print(f"Total Records: {result.total_records}")
print(f"Operations Summary: {result.operations_summary}")

Tool Name Prefixes

When connecting to multiple servers of the same type, tools may have identical names (e.g., both SQLite servers have create_table). Use prefixes to distinguish them: Specify exact prefixes for each server:
from upsonic import Agent, Task
from upsonic.tools.mcp import MultiMCPHandler

# Create multi-handler with specific prefixes for each server
multi_handler = MultiMCPHandler(
    commands=[
        "uvx mcp-server-sqlite --db-path /tmp/users.db",
        "uvx mcp-server-sqlite --db-path /tmp/orders.db",
    ],
    tool_name_prefixes=["users_db", "orders_db"],  # Must match number of servers
    timeout_seconds=60
)

# Create agent
agent = Agent(
    name="Multi-DB Agent",
    role="Multi-database operations specialist",
    goal="Work with multiple databases using prefixed tools"
)

# Create task with clear tool prefixes
task = Task(
    description="""
    IMPORTANT: You have access to TWO separate databases with prefixed tools.
    - Users database: Use tools prefixed with 'users_db_' (e.g., users_db_create_table, users_db_read_query)
    - Orders database: Use tools prefixed with 'orders_db_' (e.g., orders_db_create_table, orders_db_read_query)
    
    Step 1: Using users_db tools, create a 'users' table with id, name, and email columns.
    Insert 3 sample users.
    
    Step 2: Using orders_db tools, create an 'orders' table with id, user_id, and product columns.
    Insert 4 sample orders.
    
    Step 3: Query both databases to show all records.
    """,
    tools=[multi_handler]
)

result = agent.do(task)
print(result)

Using tool_name_prefix (Auto-indexed)

Use a single base prefix that gets automatically indexed:
from upsonic.tools.mcp import MultiMCPHandler

# Single prefix becomes: db_0_create_table, db_1_create_table, etc.
multi_handler = MultiMCPHandler(
    commands=[
        "uvx mcp-server-sqlite --db-path /tmp/db1.db",
        "uvx mcp-server-sqlite --db-path /tmp/db2.db",
    ],
    tool_name_prefix="db",  # Becomes db_0_*, db_1_*, etc.
    timeout_seconds=60
)

Prefix Benefits

  • Prevents Collisions: Multiple servers with same tool names work together
  • Clear Identification: Agents know exactly which server’s tool to use
  • Better Instructions: Task descriptions can reference specific prefixed tools

When to Use

  • Need to work with multiple MCP servers simultaneously
  • Want to aggregate tools from different servers
  • Need to coordinate operations across multiple databases/services
  • Want unified tool interface for multiple connections
  • Use prefixes when servers have overlapping tool names