MCP Hub
An aggregating MCP (Model Context Protocol) server that runs multiple child MCP servers as subprocesses and provides a unified interface with automatic process supervision, hot reload, and fault tolerance.
MCP Hub is an aggregating MCP (Model Context Protocol) server that runs multiple child MCP servers as subprocesses and combines their tools into a unified interface for AI editors like Zed.
Features
🚀 Process Supervision - Automatic restart of failed processes with exponential backoff
🔌 Tool Aggregation - Combines tools from multiple MCP servers into one interface
🛡️ Circuit Breaker - Fault tolerance with automatic recovery (3 failures → 30s cooldown)
🏷️ Name Deduplication - Handles tool name conflicts with configurable prefixes
🔧 Tool Filtering - Whitelist/blacklist tools per server
📝 Description Enhancement - Add prefixes/suffixes to tool descriptions
🔄 Hot Reload - Reload configuration without restarting (planned)
⚡ Graceful Shutdown - Clean process termination on SIGINT/SIGTERM
Quick Start
Prerequisites
- Rust 1.75+ with Cargo
- MCP-compatible servers you want to aggregate
Installation
# Clone the repository
# Build the project
# The binary will be available at target/release/mcp-hub
Basic Usage
- Create a configuration file (see Configuration):
# config.toml
[[]]
= "filesystem"
= "python"
= ["-m", "mcp_filesystem"]
= "fs_"
[[]]
= "search"
= "exa_mcp"
= "search_"
[]
= "${EXA_API_KEY}"
- Run MCP Hub:
- Connect your AI editor (like Zed) to MCP Hub via stdio.
Configuration
MCP Hub uses TOML configuration files. Each [[server]] section defines one child MCP server:
Basic Server Configuration
[[]]
= "my_server" # Unique identifier
= "python" # Command to run
= ["-m", "my_mcp"] # Command arguments
Environment Variables
[[]]
= "api_server"
= "my-mcp-server"
[]
= "${MY_API_KEY}" # Expands from environment
= "30" # Literal value
= "${HOME:-/tmp}" # With fallback
Tool Filtering
[[]]
= "filtered_server"
= "dangerous-mcp"
# Include only these tools (takes precedence over blacklist)
= ["safe_tool1", "safe_tool2"]
# OR exclude these tools
= ["dangerous_tool", "risky_operation"]
Name Deduplication & Description Enhancement
[[]]
= "enhanced_server"
= "my-mcp"
= "enhanced_" # Prefix for conflicting tool names
= "🔧 Enhanced: " # Prefix for all descriptions
= " (via Enhanced API)" # Suffix for all descriptions
Complete Example
See example.toml for a comprehensive configuration with 10 different server types.
Architecture
Zed Editor ←→ MCP Hub ←→ [exa_mcp, filesystem_mcp, git_mcp, ...]
│
├── Hub Actor (coordinator)
├── Process Supervisors (one per child server)
├── Circuit Breakers (fault protection)
└── Configuration Hot Reload
How It Works
- Startup: MCP Hub spawns all configured child processes
- Initialization: Gathers tool lists from each server and applies filtering/deduplication
- Runtime: Routes tool calls to appropriate servers based on tool names
- Fault Tolerance: Monitors process health, restarts failed processes, and uses circuit breakers
- Shutdown: Gracefully terminates all child processes on SIGINT/SIGTERM
Process Supervision
- Exponential Backoff: 1s → 2s → 4s → 8s → 15s max delay between restarts
- Retry Limit: Maximum 5 restart attempts before marking as failed
- Isolation: Failed processes don't affect other servers
Circuit Breaker
- Failure Threshold: Opens after 3 consecutive failures
- Recovery Time: Stays open for 30 seconds
- Auto-Recovery: Automatically tries requests after cooldown period
Development
Building from Source
# Debug build
# Release build (optimized)
# With native CPU optimizations
RUSTFLAGS="-C target-cpu=native"
Running Tests
# All tests
# Unit tests only
# Integration tests only
# With clippy linting
Debugging
Enable tokio console for runtime inspection:
TOKIO_CONSOLE=1
Then connect with:
Logging
Control log levels with RUST_LOG:
# Default: info for mcp-hub, warn for rmcp
RUST_LOG=debug
# Detailed logging
RUST_LOG=mcp_hub=trace,rmcp=debug
Integration with Zed Editor
Add MCP Hub to your Zed settings:
Troubleshooting
Common Issues
Process fails to start:
- Check that the command and arguments are correct
- Verify environment variables are set
- Look at logs for detailed error messages
Tool name conflicts:
- Use
prefixin server configuration to disambiguate - Check logs for deduplication messages
Circuit breaker activated:
- Check if the underlying server is healthy
- Look for patterns in failure logs
- Consider increasing timeout values
Getting Help
- Check the STATUS.md for current development status
- Look at example configurations in example.toml
- Review test cases in
tests/directory for usage patterns
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b my-feature - Make changes and add tests
- Run tests:
cargo test - Run clippy:
cargo clippy - Commit changes:
git commit -am 'Add my feature' - Push to branch:
git push origin my-feature - Submit a Pull Request
Code Style
- Follow Rust standard formatting:
cargo fmt - Fix all clippy warnings:
cargo clippy - Add tests for new functionality
- Update documentation as needed
License
This project is licensed under the MIT License - see the LICENSE file for details.