Skip to main content

Efficient MCP server aggregation with HTTP/SSE support and 98% schema token reduction

Project description

ToolMux 🛠️

🚀 98.65% Token Reduction - Efficient MCP server aggregation with HTTP/SSE support and on-demand loading

Python 3.10+ License: MIT MCP Compatible

The Problem

Traditional MCP bridges load all tool schemas upfront, consuming 15-20% of your token budget before you even start:

  • Large deployments can have hundreds of tools across multiple servers
  • Each schema consumes tokens even if never used
  • Mixed stdio/HTTP servers require separate client implementations
  • Result: Token budgets exhausted before real work begins

The Solution

ToolMux exposes only 4 meta-tools with unified stdio/HTTP support and loads servers on-demand:

Approach Tools Loaded Token Usage Transport Support Functionality
Traditional Bridge All schemas 15-20% tokens Single protocol ✅ Full access
ToolMux 4 meta-tools 1.35% tokens Mixed stdio/HTTP ✅ Full access

Real Performance

In a deployment with 200+ tools across 11 MCP servers (stdio + HTTP):

  • Before: ~20% token usage for schema loading
  • After: 1.35% token usage with ToolMux
  • Savings: 98.65% reduction in overhead
  • Bonus: Unified interface for mixed transport protocols

Requirements

  • Python 3.10+ (required for fastmcp dependency)
  • pip3 (Python package manager)
  • Virtual environment support (recommended)

Dependencies:

  • fastmcp>=0.2.0 - FastMCP runtime for MCP protocol support
  • httpx>=0.24.0 - HTTP client for HTTP/SSE MCP servers
  • websockets>=11.0.0 - WebSocket support for real-time communication
  • pydantic>=2.6.0 - Data validation and settings management
  • click>=8.0.0 - CLI interface and command handling

Note: Python 3.10+ is required for full functionality including HTTP/SSE transport support.

Installation

Quick Install (Recommended)

uvx toolmux

That's it! ToolMux will auto-configure on first run.

🎉 Now available on PyPI: https://pypi.org/project/toolmux/

Latest Updates (v1.2.0)

  • Enhanced: Moved Prompt/ and scripts/ folders into package for uv/uvx installations
  • Improved: Agent instructions and scripts now bundled with package installation
  • Updated: Documentation reflects new package structure and resource locations

Alternative Methods

Install as Persistent Tool

uv tool install toolmux

Install from Git (Development)

uvx --from git+https://github.com/subnetangel/ToolMux toolmux

Install Specific Version

uvx toolmux@1.2.0

Manual Install (Development)

# Clone the repository
git clone https://github.com/subnetangel/ToolMux.git
cd ToolMux

# Install dependencies
pip install -r requirements.txt

# Run directly
python toolmux.py

Quick Start

1. Install and First Run

# Install ToolMux
uvx toolmux

# First run creates configuration
toolmux --list-servers

On first run, ToolMux creates:

  • ~/toolmux/mcp.json - Your main configuration file
  • ~/toolmux/examples/ - Reference configurations for copy-paste

2. Configure Your Servers

Edit ~/toolmux/mcp.json to add your MCP servers:

{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
      "description": "Local filesystem access"
    },
    "brave-search": {
      "command": "uvx", 
      "args": ["mcp-server-brave-search"],
      "env": {"BRAVE_API_KEY": "your-key"},
      "description": "Web search using Brave Search API"
    },
    "remote-api": {
      "transport": "http",
      "base_url": "https://api.example.com/mcp",
      "headers": {"Authorization": "Bearer your-token"},
      "timeout": 30,
      "description": "Remote HTTP MCP server"
    }
  }
}

3. Run ToolMux

# Basic usage
toolmux

# With custom config
toolmux --config /path/to/custom.json

# List configured servers
toolmux --list-servers

# See all options
toolmux --help

How It Works

ToolMux exposes 4 efficient meta-tools:

🔍 Discovery

catalog_tools  # List all available tools from all servers

📋 Schema

get_tool_schema({"name": "read_file"})  # Get parameters for specific tool

⚡ Execute

invoke({"name": "read_file", "args": {"path": "/tmp/test.txt"}})  # Run any tool

📊 Stats

get_tool_count  # Show tool count by server

HTTP/SSE MCP Support 🌐

ToolMux supports mixed configurations with both stdio and HTTP/SSE MCP servers:

Architecture

Q CLI (stdio) ↔ ToolMux (stdio) ↔ Mixed MCP Servers
                                  ├── stdio servers
                                  └── HTTP/SSE servers

Benefits

  • Unified Interface: Q CLI sees all tools as single stdio server
  • Mixed Deployments: Combine local stdio + remote HTTP servers
  • Transparent Routing: ToolMux handles protocol translation
  • Backward Compatible: Existing stdio configs unchanged
  • Scalable: Add HTTP servers without Q CLI changes

HTTP Server Configuration

{
  "servers": {
    "local-stdio": {
      "command": "python", 
      "args": ["server.py"]
    },
    "remote-http": {
      "transport": "http",
      "base_url": "https://api.example.com/mcp",
      "headers": {"Authorization": "Bearer token"},
      "timeout": 30,
      "sse_endpoint": "/events"
    }
  }
}

Authentication Options

  • Bearer Tokens: "Authorization": "Bearer your-token"
  • API Keys: "X-API-Key": "your-api-key"
  • OAuth: "Authorization": "Bearer oauth-token"
  • Custom Headers: Any additional headers needed

Testing HTTP Support

# Start test HTTP server
python test_http_server.py

# Test mixed configuration
python test_http_transport.py

# Run ToolMux with mixed servers
./toolmux.py --config mixed_servers.json

Adding Servers

ToolMux uses a single mcp.json configuration file. Copy examples from ~/toolmux/examples/ into your main config.

Popular MCP Servers

Filesystem Access

"filesystem": {
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
  "description": "Local filesystem access"
}

Web Search (Brave)

"brave-search": {
  "command": "uvx",
  "args": ["mcp-server-brave-search"],
  "env": {"BRAVE_API_KEY": "your-api-key"},
  "description": "Web search using Brave Search API"
}

Database Access (SQLite)

"sqlite": {
  "command": "uvx",
  "args": ["mcp-server-sqlite", "--db-path", "/path/to/database.sqlite"],
  "description": "SQLite database queries"
}

GitHub Integration

"github": {
  "command": "uvx",
  "args": ["mcp-server-github"],
  "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"},
  "description": "GitHub repository and issue management"
}

HTTP MCP Server

"remote-api": {
  "transport": "http",
  "base_url": "https://api.example.com/mcp",
  "headers": {"Authorization": "Bearer your-token"},
  "timeout": 30,
  "description": "Remote HTTP MCP server"
}

Configuration Reference

All server configurations support:

  • command + args: Command to run (stdio servers)
  • transport: "http" for HTTP servers (default: stdio)
  • base_url: HTTP server endpoint
  • headers: HTTP headers for authentication
  • timeout: Request timeout in seconds
  • env: Environment variables
  • cwd: Working directory
  • description: Human-readable description

Agent Integration

Q CLI Integration

Quick Start (Recommended)

{
  "name": "simple-toolmux-agent",
  "mcpServers": {
    "toolmux": {
      "command": "uvx",
      "args": ["toolmux"],
      "timeout": 30000
    }
  },
  "tools": ["*"],
  "systemPrompt": "Use catalog_tools to see available tools, get_tool_schema for parameters, and invoke to execute tools."
}

Complete Configuration

See toolmux/examples/q-cli-agent.json for a comprehensive Q CLI configuration with:

  • Detailed system prompt explaining ToolMux workflow
  • All 4 meta-tools explicitly listed
  • Hooks and examples
  • Alternative installation methods

Available Examples

After installation, examples are available in the package:

# Find example configurations
python -c "import toolmux; import os; print(os.path.join(os.path.dirname(toolmux.__file__), 'examples'))"
  • q-cli-simple.json - Minimal configuration to get started
  • q-cli-agent.json - Complete configuration with all features
  • example_agent_config.json - Legacy example (updated for v1.2.0)

Other AI Clients

Include the agent instructions from the installed package to ensure proper meta-tool usage:

# After installing with uvx/uv, find the instructions at:
python -c "import toolmux; import os; print(os.path.join(os.path.dirname(toolmux.__file__), 'Prompt', 'AGENT_INSTRUCTIONS.md'))"

Files Included

Core Package

  • toolmux/main.py - Main multiplexer server
  • toolmux/examples/ - Configuration examples and templates
  • toolmux/Prompt/AGENT_INSTRUCTIONS.md - Agent behavior guide
  • toolmux/scripts/toolmux_hook.sh - Q CLI agent hook

Configuration Files

  • mcp.json - Default server configuration (created on first run)
  • Example configurations in toolmux/examples/:
    • q-cli-simple.json - Minimal Q CLI setup
    • q-cli-agent.json - Complete Q CLI configuration
    • example_agent_config.json - Legacy example (updated for v1.2.0)

Benefits

98.65% token reduction - Only 4 tools vs hundreds of schemas
On-demand loading - Servers start when needed
Standard config - Uses familiar mcp.json format
Zero breaking changes - Works with any MCP server
Full functionality - Access all tools through meta-tools

Use Cases

Perfect for:

  • AI Assistants with multiple MCP servers
  • Token-constrained environments
  • Large MCP deployments (10+ servers)
  • Development workflows with many tools

Architecture

System Overview

graph TB
    subgraph "AI Client Layer"
        QCli["Q CLI Agent"]
        Claude["Claude Desktop"]
        Custom["Custom AI Client"]
    end
    
    subgraph "ToolMux Core"
        TM["ToolMux Server<br/>(4 Meta-Tools)"]
        Cache["Tool Cache"]
        Router["Protocol Router"]
    end
    
    subgraph "MCP Server Layer"
        subgraph "Stdio Servers"
            FS["Filesystem<br/>Server"]
            SQLite["SQLite<br/>Server"]
            Git["Git<br/>Server"]
        end
        
        subgraph "HTTP/SSE Servers"
            API1["Remote API<br/>Server"]
            Search["Search<br/>Service"]
            Cloud["Cloud<br/>Service"]
        end
    end
    
    QCli -.->|stdio| TM
    Claude -.->|stdio| TM
    Custom -.->|stdio| TM
    
    TM --> Cache
    TM --> Router
    
    Router -->|stdio| FS
    Router -->|stdio| SQLite
    Router -->|stdio| Git
    Router -->|HTTP/SSE| API1
    Router -->|HTTP/SSE| Search
    Router -->|HTTP/SSE| Cloud
    
    style TM fill:#e1f5fe
    style Router fill:#f3e5f5
    style Cache fill:#e8f5e8

Token Usage Comparison

pie title Token Usage: Traditional vs ToolMux
    "Traditional: Schema Loading" : 18.65
    "Traditional: Actual Work" : 81.35
    "ToolMux: Meta-Tools" : 1.35
    "ToolMux: Actual Work" : 98.65

Mixed Transport Architecture

graph LR
    subgraph "Client"
        Agent["AI Agent<br/>(Q CLI)"]
    end
    
    subgraph "ToolMux"
        Core["ToolMux Core<br/>stdio interface"]
        HTTP["HTTP Client"]
        Stdio["Stdio Manager"]
    end
    
    subgraph "MCP Servers"
        S1["Local Server 1<br/>(stdio)"]
        S2["Local Server 2<br/>(stdio)"]
        S3["Remote Server 1<br/>(HTTP)"]
        S4["Remote Server 2<br/>(SSE)"]
    end
    
    Agent -->|stdio| Core
    Core --> HTTP
    Core --> Stdio
    
    Stdio -->|subprocess| S1
    Stdio -->|subprocess| S2
    HTTP -->|HTTPS| S3
    HTTP -->|WebSocket/SSE| S4
    
    style Core fill:#e1f5fe
    style HTTP fill:#fff3e0
    style Stdio fill:#e8f5e8

Interaction Flow

Tool Discovery and Execution Flow

sequenceDiagram
    participant Agent as AI Agent
    participant TM as ToolMux
    participant Cache as Tool Cache
    participant Server as MCP Server
    
    Note over Agent,Server: 1. Discovery Phase
    Agent->>TM: catalog_tools()
    TM->>Cache: Check cached tools
    alt Cache Miss
        TM->>Server: Start server (on-demand)
        Server-->>TM: Server ready
        TM->>Server: List tools
        Server-->>TM: Tool list
        TM->>Cache: Cache tools
    else Cache Hit
        Cache-->>TM: Return cached tools
    end
    TM-->>Agent: All available tools
    
    Note over Agent,Server: 2. Schema Retrieval
    Agent->>TM: get_tool_schema({"name": "read_file"})
    TM->>Cache: Check schema cache
    alt Schema Cached
        Cache-->>TM: Return schema
    else Schema Not Cached
        TM->>Server: Get tool schema
        Server-->>TM: Tool schema
        TM->>Cache: Cache schema
    end
    TM-->>Agent: Tool schema
    
    Note over Agent,Server: 3. Tool Execution
    Agent->>TM: invoke({"name": "read_file", "args": {...}})
    TM->>Server: Execute tool
    Server-->>TM: Tool result
    TM-->>Agent: Execution result

HTTP vs Stdio Server Handling

flowchart TD
    Start([Tool Request]) --> Check{Server Type?}
    
    Check -->|stdio| StdioFlow[Stdio Flow]
    Check -->|HTTP| HTTPFlow[HTTP Flow]
    
    subgraph "Stdio Processing"
        StdioFlow --> StartProc[Start subprocess]
        StartProc --> SendJSON[Send JSON-RPC]
        SendJSON --> ReadResp[Read response]
        ReadResp --> StdioResult[Return result]
    end
    
    subgraph "HTTP Processing"
        HTTPFlow --> HTTPReq[HTTP Request]
        HTTPReq --> Auth[Add authentication]
        Auth --> SendHTTP[Send to endpoint]
        SendHTTP --> ParseHTTP[Parse response]
        ParseHTTP --> HTTPResult[Return result]
    end
    
    StdioResult --> End([Result to Agent])
    HTTPResult --> End
    
    style StdioFlow fill:#e8f5e8
    style HTTPFlow fill:#fff3e0

On-Demand Server Loading

stateDiagram-v2
    [*] --> Idle: ToolMux starts
    
    Idle --> CheckCache: Tool request received
    CheckCache --> ServerRunning: Server already running
    CheckCache --> StartServer: Server not running
    
    StartServer --> Initializing: Launch server process
    Initializing --> Ready: Server responds
    Initializing --> Failed: Server fails to start
    
    Ready --> ServerRunning: Server available
    ServerRunning --> ExecuteTool: Forward request
    ExecuteTool --> ServerRunning: Tool executed
    
    ServerRunning --> Idle: Request complete
    Failed --> [*]: Error returned
    
    note right of StartServer
        Only starts when
        tool is requested
    end note
    
    note right of ServerRunning
        Server stays running
        for subsequent requests
    end note

Error Handling Flow

flowchart TD
    Request[Tool Request] --> Validate{Valid Request?}
    
    Validate -->|No| ValidationError[Return validation error]
    Validate -->|Yes| FindServer{Server exists?}
    
    FindServer -->|No| ServerError[Return server not found]
    FindServer -->|Yes| CheckRunning{Server running?}
    
    CheckRunning -->|No| StartServer[Start server]
    CheckRunning -->|Yes| ExecuteTool[Execute tool]
    
    StartServer --> StartSuccess{Start successful?}
    StartSuccess -->|No| StartError[Return startup error]
    StartSuccess -->|Yes| ExecuteTool
    
    ExecuteTool --> ToolSuccess{Tool executed?}
    ToolSuccess -->|No| ToolError[Return execution error]
    ToolSuccess -->|Yes| Success[Return result]
    
    ValidationError --> ErrorResponse[Format error response]
    ServerError --> ErrorResponse
    StartError --> ErrorResponse
    ToolError --> ErrorResponse
    
    ErrorResponse --> End[Return to agent]
    Success --> End
    
    style ValidationError fill:#ffebee
    style ServerError fill:#ffebee
    style StartError fill:#ffebee
    style ToolError fill:#ffebee
    style Success fill:#e8f5e8

License

MIT License - see LICENSE file for details


Built for the MCP community to make AI assistants more efficient 🤖

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

toolmux-1.2.0.tar.gz (36.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

toolmux-1.2.0-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file toolmux-1.2.0.tar.gz.

File metadata

  • Download URL: toolmux-1.2.0.tar.gz
  • Upload date:
  • Size: 36.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for toolmux-1.2.0.tar.gz
Algorithm Hash digest
SHA256 e01a4f006b0f765e2c09c0778afa487acc0353837860572d597714623205d1fd
MD5 d4097d56d81b915df05a46f7f4900ded
BLAKE2b-256 cc5665a93318afcab36ee458ad896dcf42cb607ba30d82be674b05de4e0647d1

See more details on using hashes here.

File details

Details for the file toolmux-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: toolmux-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for toolmux-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fc189162f83a8f5ac1593294d9ec4223c7a7e6f97754cc7f52d4b9376657d841
MD5 bef1b662331e4ea44245d18278e6e443
BLAKE2b-256 e0b073f7a5255d0199a4ccefd94deaf4474ba206c3ce11289865f57894b4232f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page