Merge multiple instances of the same MCP server across environments into a single endpoint with a unified env parameter.
Project description
mcp-env-mux
Merge multiple instances of the same MCP server across environments into a single endpoint with a unified env parameter.
Problem
When you connect the same MCP server (e.g., Coralogix, Datadog) from multiple environments (prod, staging, dev), each instance exposes identical tool definitions. Your MCP client sees every tool duplicated per environment, wasting context window tokens and creating a confusing tool list.
Solution
mcp-env-mux sits in front of your MCP backends as a proxy. It discovers tools from each backend, merges identical definitions into a single tool with an injected env parameter, and routes calls to the correct backend based on the caller's env selection. One tool instead of N copies.
Quick Start
# Install
pip install -e .
# Set your API keys as environment variables
export BACKEND_PROD_API_KEY="your-prod-key"
export BACKEND_STAGING_API_KEY="your-staging-key"
# Create a config file (see Configuration below)
# Validate your config and check for schema mismatches
mcp-env-mux --config config.json --test-schema
# Start the proxy
mcp-env-mux --config config.json
Configuration
The config file is JSON with a single environments object. Each key is an environment name, and each value specifies the backend URL, a description, and optional HTTP headers.
Header values support $VAR substitution -- any value matching $SOME_NAME is resolved from the OS environment at startup.
{
"environments": {
"Prod": {
"description": "Production environment",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "$PROD_API_KEY"
}
},
"Staging": {
"description": "Staging environment",
"url": "https://api-staging.example.com/mcp",
"headers": {
"Authorization": "$STAGING_API_KEY"
}
}
}
}
Fields:
url(required) -- The MCP backend's HTTP endpoint.description(required) -- Human-readable label shown in the merged tool'senvparameter description.headers(optional) -- HTTP headers sent to this backend. Use$ENV_VARfor secrets.
How It Works
- Discovery -- Connects to each backend and calls
list_tools()to collect tool definitions. - Merge -- Groups tools by name across environments. For each group:
- Descriptions must match across environments (mismatch is an error).
- Parameter types must match (mismatch is an error).
- Tools available in only a subset of environments get a constrained
envenum. - Extra parameters present in some environments but not others are included as optional, with warnings.
- Proxy -- Builds a FastMCP server with one handler per merged tool. Each handler extracts the
envargument, strips parameters not supported by the target backend, and forwards the call.
CLI Reference
mcp-env-mux [OPTIONS]
| Flag | Default | Description |
|---|---|---|
--config PATH |
(required) | Path to the JSON configuration file. |
--host HOST |
0.0.0.0 |
Host to bind the proxy server to. |
--port PORT |
8080 |
Port to bind the proxy server to. |
--test-schema |
off | Validate config and tool schemas, print diagnostics, then exit. |
Schema Validation (CI Mode)
Use --test-schema to check for configuration errors and tool schema mismatches without starting the server. This connects to all backends, runs the merge, and reports errors and warnings to stdout.
mcp-env-mux --config config.json --test-schema
Exit code 0 means all tools merged cleanly. Exit code 1 means there are merge errors (description or type mismatches). Integrate this into your CI pipeline to catch schema drift between environments.
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run all tests
pytest tests/ -v --timeout=120
# Run unit tests only
pytest tests/ -v --ignore=tests/test_e2e.py
# Run E2E tests only (starts real backends and proxy subprocesses)
pytest tests/test_e2e.py -v --timeout=120
Requires Python >= 3.11.
Architecture
The package is organized into five modules under src/mcp_env_mux/: cli, config, discovery, merge, and proxy. The data flow is linear: CLI parses args, config is loaded, backends are discovered, schemas are merged, and the proxy server is built and started.
For detailed module documentation, see src/mcp_env_mux/mcp_env_mux_docs.md. For test documentation and coverage mapping, see tests/tests_docs.md.
Project Structure
mcp-env-mux/
pyproject.toml -- Package metadata, dependencies, CLI entrypoint
config.json -- Example configuration file
src/mcp_env_mux/
__init__.py -- Package init
cli.py -- CLI entrypoint and startup orchestration
config.py -- Config loading, validation, env var resolution
discovery.py -- Backend connection and tool discovery
merge.py -- Schema diffing and tool merging
proxy.py -- FastMCP server construction and call routing
mcp_env_mux_docs.md -- Detailed package documentation
tests/
conftest.py -- Shared fixtures: mock backends, proxy lifecycle
test_config.py -- Unit tests for config loading and env var substitution
test_merge.py -- Unit tests for schema merging logic
test_proxy.py -- Unit tests for call routing and parameter stripping
test_e2e.py -- End-to-end tests with real backends and proxy
tests_docs.md -- Test suite documentation
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 mcp_env_mux-0.1.0.tar.gz.
File metadata
- Download URL: mcp_env_mux-0.1.0.tar.gz
- Upload date:
- Size: 29.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6807fa197894d6ed7b892ceed6136b6fd641a2373f0cbba0ff222c3a0844ae5
|
|
| MD5 |
8507b97404837a5421de5f77e99f6ca0
|
|
| BLAKE2b-256 |
f1e601bb84d9b1b1209db83a901dd17202ebb0a73111d52659b35a31dc223408
|
File details
Details for the file mcp_env_mux-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_env_mux-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f63955f42588967db946047a635e29a5c98eef24d8b328e00759f9fae1bf321
|
|
| MD5 |
3a9036e54fb55bfe7d73f568d96e1a11
|
|
| BLAKE2b-256 |
760b2a306dd7b9819cc924bca37f609c3deeff55f5b11d1f40346ece99403432
|