π 98.65% Token Reduction - Efficient MCP server aggregation with HTTP/SSE support and on-demand loading
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
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 |
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
- 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.
uvx toolmuxThat's it! ToolMux will auto-configure on first run.
π Now available on PyPI: https://pypi.org/project/toolmux/
- β
Fixed: First-time setup now properly copies all bundled resources (
Prompt/,scripts/,examples/) - β Enhanced: Complete local access to agent instructions and scripts after installation
- β
Improved: Better user experience with all resources available in
~/toolmux/
uv tool install toolmuxuvx --from git+https://github.com/subnetangel/ToolMux toolmuxuvx toolmux@1.2.1# 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# Install ToolMux
uvx toolmux
# First run creates configuration
toolmux --list-serversOn first run, ToolMux creates:
~/toolmux/mcp.json- Your main configuration file~/toolmux/examples/- Reference configurations for copy-paste
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"
}
}
}# Basic usage
toolmux
# With custom config
toolmux --config /path/to/custom.json
# List configured servers
toolmux --list-servers
# See all options
toolmux --helpToolMux exposes 4 efficient meta-tools:
catalog_tools # List all available tools from all serversget_tool_schema({"name": "read_file"}) # Get parameters for specific toolinvoke({"name": "read_file", "args": {"path": "/tmp/test.txt"}}) # Run any toolget_tool_count # Show tool count by serverToolMux supports mixed configurations with both stdio and HTTP/SSE MCP servers:
Q CLI (stdio) β ToolMux (stdio) β Mixed MCP Servers
βββ stdio servers
βββ HTTP/SSE servers
- 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
{
"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"
}
}
}- 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
# 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.jsonToolMux uses a single mcp.json configuration file. Copy examples from ~/toolmux/examples/ into your main config.
"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-api-key"},
"description": "Web search using Brave Search API"
}"sqlite": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "/path/to/database.sqlite"],
"description": "SQLite database queries"
}"github": {
"command": "uvx",
"args": ["mcp-server-github"],
"env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"},
"description": "GitHub repository and issue management"
}"remote-api": {
"transport": "http",
"base_url": "https://api.example.com/mcp",
"headers": {"Authorization": "Bearer your-token"},
"timeout": 30,
"description": "Remote HTTP MCP server"
}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
{
"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."
}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
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.1)
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'))"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
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.1)
β
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
Perfect for:
- AI Assistants with multiple MCP servers
- Token-constrained environments
- Large MCP deployments (10+ servers)
- Development workflows with many tools
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
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
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
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
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
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
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
MIT License - see LICENSE file for details
Built for the MCP community to make AI assistants more efficient π€