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
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 supporthttpx>=0.24.0- HTTP client for HTTP/SSE MCP serverswebsockets>=11.0.0- WebSocket support for real-time communicationpydantic>=2.6.0- Data validation and settings managementclick>=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/andscripts/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 endpointheaders: HTTP headers for authenticationtimeout: Request timeout in secondsenv: Environment variablescwd: Working directorydescription: 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 startedq-cli-agent.json- Complete configuration with all featuresexample_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 servertoolmux/examples/- Configuration examples and templatestoolmux/Prompt/AGENT_INSTRUCTIONS.md- Agent behavior guidetoolmux/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 setupq-cli-agent.json- Complete Q CLI configurationexample_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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e01a4f006b0f765e2c09c0778afa487acc0353837860572d597714623205d1fd
|
|
| MD5 |
d4097d56d81b915df05a46f7f4900ded
|
|
| BLAKE2b-256 |
cc5665a93318afcab36ee458ad896dcf42cb607ba30d82be674b05de4e0647d1
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc189162f83a8f5ac1593294d9ec4223c7a7e6f97754cc7f52d4b9376657d841
|
|
| MD5 |
bef1b662331e4ea44245d18278e6e443
|
|
| BLAKE2b-256 |
e0b073f7a5255d0199a4ccefd94deaf4474ba206c3ce11289865f57894b4232f
|