One server to rule all your MCP tools.
A meta-MCP server that aggregates multiple backend MCP servers into one unified interface.
Your host agent (Claude, Codex, OpenClaw) sees only one MCP server, but gets tools from all of them.
Quick Start β’ What It Does β’ Config β’ Tools Reference β’ Contributing
git clone https://github.com/factspark23-hash/mcp-handler.git
cd mcp-handler
pip install -e .
cp config.example.yaml mcp_hub.yaml
# Edit mcp_hub.yaml with your serversAdd to your host agent config (Claude Desktop example):
{
"mcpServers": {
"mcp-hub": {
"command": "python3",
"args": ["-m", "src.server"],
"cwd": "/path/to/mcp-hub"
}
}
}Restart your host agent. All tools from all servers are available. β
|
|
|
|
hub:
name: "My MCP Hub"
database: "data/hub.db"
health_check_interval: 30 # seconds between health pings
auto_restart: true
max_restart_attempts: 3
restart_delay: 5 # seconds between restart attempts
servers:
filesystem:
transport: "stdio"
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
enabled: true
aliases:
read_file: "fs_read"
write_file: "fs_write"
list_directory: "fs_ls"
depends_on: []
sqlite:
transport: "stdio"
command: "uvx"
args: ["mcp-server-sqlite", "--db", "/tmp/app.db"]
enabled: true
aliases:
query: "db_query"
depends_on: [filesystem]
namespacing:
mode: "auto" # auto | always | never
tracking:
enabled: true
max_records: 100000
track_params: false # privacy: don't log params by default
session_tracking: true
hotreload:
enabled: true
watch_interval: 5servers:
github:
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"Status & Discovery (5 tools)
| Tool | Description |
|---|---|
hub_status |
Hub and all servers status |
hub_tools |
List all tools. Optional: server, search |
hub_tool_info |
Detailed info: schema, server, alias, cost |
hub_search_tools |
Search tools by name or description |
hub_refresh |
Re-discover tools from all servers |
Usage Analytics (6 tools)
| Tool | Description |
|---|---|
hub_stats |
Aggregated stats. Optional: since_hours |
hub_stats_detailed |
Filtered call history |
hub_top_tools |
Most used tools |
hub_error_summary |
Recent errors grouped by message |
hub_session_stats |
Current session stats |
hub_slow_tools |
Slowest tools by average duration |
Server Management (5 tools)
| Tool | Description |
|---|---|
hub_server_info |
Server details: connected, transport, tool count |
hub_enable_server |
Enable and connect a disabled server |
hub_disable_server |
Disconnect a server |
hub_restart_server |
Restart a server |
hub_server_logs |
Server health history |
Tool Control (6 tools)
| Tool | Description |
|---|---|
hub_quiet_on |
Temporarily disable tools/servers |
hub_quiet_off |
Re-enable |
hub_quiet_status |
Show currently quieted items |
hub_alias_set |
Set alias for a tool |
hub_alias_remove |
Remove alias |
hub_alias_list |
List all aliases |
Cross-Server Composition (2 tools)
| Tool | Description |
|---|---|
hub_compose |
Chain tools from different servers |
hub_compose_template |
Save/load/run composition templates |
Example:
{
"steps": [
{"tool": "fs_read", "arguments": {"path": "data.csv"}},
{"tool": "db_query", "arguments": {"sql": "INSERT INTO imports VALUES ('{{step_1.output}}')"}}
]
}Stateful Sessions (2 tools)
| Tool | Description |
|---|---|
hub_session_begin |
Start session with optional context |
hub_session_step |
Execute step with auto-injected context |
Cost Estimation (2 tools)
| Tool | Description |
|---|---|
hub_cost_register |
Register cost for a tool |
hub_cost_estimate |
Check cost before calling |
Advanced (6 tools)
| Tool | Description |
|---|---|
hub_replay |
Replay last N calls |
hub_replay_one |
Replay specific call by ID |
hub_config_reload |
Reload config file |
hub_config_show |
Show current config as JSON |
hub_health_history |
Health history per server |
hub_export_stats |
Export all stats as JSON |
User: "read the config file"
β
βΌ
Claude decides: call tool "fs_read" (alias)
β
βΌ
MCP Hub receives call
βββ Check quiet mode β not quieted
βββ Registry: "fs_read" β server="filesystem", original="read_file"
βββ Router: get connector for "filesystem"
βββ connector.call_tool("read_file", {path: "config.yaml"})
βββ Track: log_call(filesystem, fs_read, 45ms, success)
β
βΌ
Return response to Claude β Claude tells user
mcp-hub/
βββ pyproject.toml # Package config + dependencies
βββ config.example.yaml # Example config
βββ src/
β βββ server.py # Main MCP Server (34 hub_* tools)
β βββ router.py # Routes calls to backends
β βββ registry.py # Tool discovery + namespacing
β βββ connector.py # MCP server connections (stdio/HTTP)
β βββ db.py # SQLite layer (4 tables)
β βββ config.py # YAML config loader + validation
β βββ aliases.py # Bidirectional alias mapping
β βββ namespacing.py # Auto/prefix/never modes
β βββ quiet.py # Temporary tool/server disabling
β βββ session.py # Per-session statistics
β βββ health.py # Health checks + uptime
β βββ autorun.py # Auto-restart with dependency ordering
β βββ replay.py # Replay past tool calls
β βββ hotreload.py # Config file watching
βββ data/ # SQLite database (auto-created)
βββ tests/
βββ test_core.py # 19 unit tests
βββ test_integration.py # Integration tests
pip install pytest pytest-asyncio
pytest tests/ -v
# 19/19 tests pass β
| Layer | Technology |
|---|---|
| Language | Python 3.10+ |
| Protocol | MCP SDK 1.6+ |
| Config | YAML (PyYAML) |
| Storage | SQLite (aiosqlite) |
| Async | asyncio |
| HTTP | httpx |
Contributions welcome! Here's how:
- Fork this repo
- Create a feature branch (
git checkout -b feat/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feat/amazing-feature) - Open a Pull Request
- WebSocket transport support
- Tool usage dashboard (web UI)
- Rate limiting per tool
- Authentication layer
- Docker support
- More transport types (SSE, gRPC)
MIT β use it however you want.
Built with β€οΈ for the MCP community
β Star this repo if you find it useful!