rupinder2/mcp-orchestrator
š š š šŖ© š§ - Central hub that aggregates tools from multiple MCP servers with unified BM25/regex search and deferred loading.
Quick Install
{
"mcpServers": {
"rupinder2-mcp-orchestrator": {
"command": "npx",
"args": [
"-y",
"rupinder2-mcp-orchestrator"
]
}
}
}Using an AI coding agent (Claude Code, Cursor, etc.)? Copy a ready-made prompt that tells it to fetch the setup instructions and install this server for you.
Documentation Overview
MCP Orchestrator
A central hub that connects to multiple downstream MCP servers, aggregates their tools, and provides unified access with powerful tool search capabilities.
Built around deferred tool loading ā search across all your servers without blowing Claude's context window.
Features
- Config-based Server Registration: Add downstream MCP servers via JSON config file
- Tool Namespacing: Automatic
server_name__tool_nameformat - Tool Search: Unified BM25/regex search with deferred loading support
- Flexible Authentication: Static saved headers or token forwarding
- Multiple Transports: stdio or HTTP
- Tool Definition Caching: Cached definitions, raw result passthrough
- Storage Backends: In-memory (development) or Redis (production)
Quick Start
Installation
pip install mcp-orchestrator
Running the MCP Server
# Run as stdio MCP server (for Claude Desktop, Cursor, etc.)
mcp-orchestrator
# Or run with Python directly
python -m mcp_orchestrator.main
HTTP Transport:
ORCHESTRATOR_TRANSPORT=http ORCHESTRATOR_PORT=8080 python -m mcp_orchestrator.main
This starts the server on http://localhost:8080/mcp with CORS enabled.
Configuring Servers
Add downstream MCP servers in server_config.json:
{
"servers": [
{
"name": "my-server",
"url": "http://localhost:8080/mcp",
"transport": "http",
"auth_type": "static",
"auth_headers": {
"Authorization": "Bearer my-token"
}
},
{
"name": "my-stdio-server",
"url": "server.py",
"transport": "stdio",
"command": "uv",
"args": ["run", "python", "server.py"]
}
]
}
Searching for Tools
The orchestrator provides unified tool search (BM25 by default, regex optional):
# BM25 search (default - natural language)
results = await mcp_client.call_tool("tool_search", {
"query": "get weather information",
"max_results": 3
})
# Regex search (set use_regex=true)
results = await mcp_client.call_tool("tool_search", {
"query": "weather|forecast",
"use_regex": true,
"max_results": 3
})
Architecture
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā MCP Orchestrator ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā FastMCP Server ā ā
ā ā āāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāā ā ā
ā ā ā tool_search ā ā call_remote_tool ā ā ā
ā ā āāāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāā ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāā āāāāāāāāāāāā āāāāāāāāāāāāāāāā ā
ā ā Server ā ā Tool ā ā Storage ā ā
ā ā Registry ā ā Search ā ā(Memory/Redis)ā ā
ā āāāāāāāāāāāā āāāāāāāāāāāā āāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
āāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāā
ā¼ ā¼ ā¼
āāāāāāāāāāā āāāāāāāāāāā āāāāāāāāāāā
ā MCP Svr ā ā MCP Svr ā ā MCP Svr ā
ā #1 ā ā #2 ā ā #N ā
āāāāāāāāāāā āāāāāāāāāāā āāāāāāāāāāā
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
STORAGE_BACKEND | memory | Storage backend (memory or redis) |
REDIS_URL | redis://localhost:6379/0 | Redis connection URL |
MCP_ORCHESTRATOR_TOOL_CACHE_TTL | 300 | Tool schema cache TTL in seconds |
MCP_ORCHESTRATOR_DEFAULT_CONNECTION_MODE | stateless | Default connection mode |
MCP_ORCHESTRATOR_CONNECTION_TIMEOUT | 30.0 | Connection timeout in seconds |
MCP_ORCHESTRATOR_MAX_RETRIES | 3 | Maximum retry attempts |
ORCHESTRATOR_TRANSPORT | stdio | MCP transport (stdio or http) |
ORCHESTRATOR_PORT | 8080 | Port for HTTP transport |
ORCHESTRATOR_HOST | 0.0.0.0 | Host for HTTP transport |
ORCHESTRATOR_LOG_LEVEL | INFO | Logging level |
SERVER_CONFIG_PATH | server_config.json | Path to server configuration file |
Claude Desktop Integration
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"mcp-orchestrator": {
"command": "mcp-orchestrator",
"env": {
"STORAGE_BACKEND": "memory",
"ORCHESTRATOR_LOG_LEVEL": "INFO"
}
}
}
}
MCP Tools
tool_search
Search for tools using BM25 relevance ranking or regex pattern matching.
@mcp.tool()
async def tool_search(
query: str,
max_results: int = 3,
use_regex: bool = False,
) -> dict:
"""Search for tools using BM25 or regex.
By default uses BM25 natural language search. Set use_regex=True
to search using Python regex patterns instead.
"""
discover_tools
Discover tools from a registered downstream server.
@mcp.tool()
async def discover_tools(
server_name: str,
) -> dict:
"""Discover tools from a registered server and index them for search.
Returns the list of discovered tools with their schemas.
"""
call_remote_tool
Call a tool directly on a downstream MCP server.
@mcp.tool()
async def call_remote_tool(
tool_name: str,
arguments: Optional[dict] = None,
auth_header: Optional[str] = None,
) -> Any:
"""Call a tool on a downstream server.
Args:
tool_name: Namespaced tool name (server_name__tool_name)
arguments: Tool arguments
auth_header: Optional auth header to override server's configured auth
"""
Tool Search Results
The search tools return results in the format expected by Claude's tool search system:
{
"success": true,
"tool_references": [
{
"type": "tool_reference",
"tool_name": "server_name__tool_name"
}
],
"total_matches": 5,
"query": "weather"
}
Testing
Run the test suite:
uv run pytest
Run with coverage:
uv run pytest --cov=mcp_orchestrator
Project Structure
mcp-orchestrator/
āāā src/mcp_orchestrator/
ā āāā __init__.py
ā āāā main.py # Entry point
ā āāā models.py # Pydantic models
ā āāā mcp_server.py # FastMCP server
ā āāā config_loader.py # Config file loader
ā āāā server/
ā ā āāā registry.py # Server registry
ā āāā tools/
ā ā āāā router.py # Tool router
ā ā āāā search.py # Tool search service
ā āāā storage/
ā āāā base.py # Storage interface
ā āāā memory.py # In-memory backend
ā āāā redis.py # Redis backend
āāā tests/
ā āāā test_registry.py
ā āāā test_search.py
ā āāā test_storage.py
ā āāā test_models.py
ā āāā test_integration.py
āāā server_config.json # Pre-configured downstream servers
āāā pyproject.toml
āāā README.md
āāā .env # Environment variables (not committed)
License
MIT License
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.