Skip to main content
Glama
Simonc44
by Simonc44

OmniMCP Router

The Universal MCP Gateway — One Entry Point to Rule All Your AI Tools

Multi-role auth, hot-reload, auto-healing, Prometheus metrics

Release Python 3.10+ MCP Protocol License: MIT Tests Code style: black

Plug any MCP server. Claude sees them all as one.

FeaturesQuick StartConfigurationTestsClient SetupContributing


The Problem

You have 10 MCP servers: GitHub, Reddit, Notion, Stripe, a custom scraper…
Your Claude Desktop config is a mess. Each client can only talk to one server at a time.
Every crash brings everything down. There's no observability. No resilience.

OmniMCP fixes all of that.


Related MCP server: uni-mcp-gateway

Features

Feature

Description

Zero Hard-Coded Tools

Dynamically discovers tools from every sub-server at startup

Async Non-Blocking Routing

Parallel requests routed concurrently via anyio — no bottleneck

Auto-Healing

Exponential backoff reconnection when a sub-server crashes

Hot-Reload

Detects mcp_router_config.json changes live — no restart needed

Hook System

Mutate, intercept, and validate requests/responses in middleware pipelines

Performance Monitoring

Real-time profiling with PERF_WARNING for tools exceeding 5s

Isolated Lifecycle

Each sub-server has its own AsyncExitStack — one crash ≠ global failure

Safe Namespacing

Tools exposed as {server}__{tool}, sanitized to MCP spec ([a-zA-Z0-9_-]{1,64})

Persistent Logging

All logs written to mcp_router.log + stderr (captured by Claude)

JSON Schema Validation

Strict input validation before forwarding any tool call

Response Truncation Hook

Auto-truncates responses >50k chars to protect context windows

Built-in Status Tool

__router__status exposes live server health + per-tool usage stats

Per-Server Timeout

Optional timeout (seconds) prevents a hung sub-server from freezing the client

Multi-Transport

Exposez le routeur en stdio, Streamable HTTP (/mcp) ou WebSocket (/ws)

Prometheus Metrics

Endpoint /metrics : compteurs/gauges/histogrammes d'utilisation des outils

Bearer Auth

Protégez les transports /mcp et /ws par Authorization: Bearer <token>

Pluggable Hooks

Chargez des hooks depuis des modules Python externes via la config (hooks)

Docker Ready

Dockerfile + docker-compose.yml pour un déploiement conteneurisé

Windows + Linux

Signal handling for both platforms


Quick Start

# 1. Clone the repo
git clone https://github.com/Simonc44/OmniMCP.git
cd OmniMCP

# 2. Install dependencies (Python 3.10+ required)
pip install -r requirements.txt

# 3. Edit your config
notepad mcp_router_config.json   # Windows
# or: nano mcp_router_config.json

# 4. Run it
python router.py --config mcp_router_config.json          # stdio (default, for Claude Desktop / Cursor)

# Or serve it over the network:
python router.py --config mcp_router_config.json --transport http --port 8000       # Streamable HTTP at /mcp
python router.py --config mcp_router_config.json --transport websocket --port 8000  # WebSocket at /ws

# Or run it in a container:
docker compose up --build

That's it. OmniMCP starts, connects to all your sub-servers, and exposes a single unified MCP interface.

The http/websocket transports also expose a Prometheus endpoint at /metrics (tool call counts, latencies, server health).


Project Structure

OmniMCP/
├── router.py                  #  Core gateway — routing, healing, hot-reload, hooks
├── mock_server.py             #  Lightweight mock MCP server for testing
├── run_integration_test.py    #  stdio integration test suite (async, healing, hot-reload)
├── run_http_integration_test.py #  HTTP transport integration test (/mcp + /metrics)
├── mcp_router_config.json     #   Production config — your real MCP servers go here
├── test_config.json           #  Test config — uses mock_server.py instances
├── tests/                     #  Pytest unit tests (sanitization, validation, collisions)
├── requirements.txt           #  Dependencies: mcp, pydantic, jsonschema, anyio + http/metrics
├── Dockerfile                 #  Container image for the http transport
├── docker-compose.yml         #  One-command container deployment
├── docs/                      #  Architecture diagrams and assets
├── .github/
│   ├── workflows/ci.yml       #  GitHub Actions CI pipeline
│   └── ISSUE_TEMPLATE/        #  Bug report & feature request templates
├── CHANGELOG.md               #  Version history
├── CONTRIBUTING.md            #  Contribution guide
└── LICENSE                    #   MIT License

Configuration

The config file follows the exact same syntax as claude_desktop_config.json — so you can copy-paste your existing Claude Desktop config directly.

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxx" }
    },
    "reddit": {
      "command": "python",
      "args": ["C:/path/to/reddit/server.py"],
      "env": {
        "REDDIT_CLIENT_ID": "your_client_id",
        "REDDIT_CLIENT_SECRET": "your_secret",
        "REDDIT_USER_AGENT": "OmniMCP/1.0"
      }
    },
    "trend-mining": {
      "command": "python",
      "args": ["-m", "trend_mining.server"],
      "env": { "PLAYWRIGHT_HEADLESS": "true" }
    }
  }
}

Tools are exposed as {server_name}__{tool_name} — e.g. github__create_issue, reddit__search_posts.

An optional timeout (in seconds) per server guards against a hung sub-server freezing the client (default 120):

"github": {
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-github"],
  "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxx" },
  "timeout": 60
}

Hot-Reload

OmniMCP watches your config file every 2 seconds. Add, remove, or modify a server — it reconnects live and sends notifications/tools/list_changed to your client. No restart needed.


Tests

The integration test suite validates the full feature set end-to-end:

python run_integration_test.py

#

Test

What it validates

1

Aggregation

All tools from all sub-servers are discovered and exposed

2

Async Parallelism

Two 2s calls finish in ~2s total, not 4s

3

Perf Monitoring

A 6s call triggers PERF_WARNING in logs

4

Auto-Healing

Server crash → automatic reconnect → real successful tool call (not a silent error)

5

Hot-Reload

Config change → list_changed notification → updated tool list

6

Status Tool

__router__status returns live health + routing stats

Additional suites:

python -m pytest tests/ -q                 # Unit tests (sanitization, validation, collisions, hooks, auth)
python run_http_integration_test.py        # HTTP: /mcp, /metrics, auth legacy, multi-roles, hot-reload, PERF_WARNING (parallel)

The HTTP suite runs 5 tests in parallel, each on its own port:

#

Test

What it validates

1

HTTP Transport

/mcp initialize, list, call + /metrics

2

Bearer legacy

401 without/wrong token, success with token, /metrics protected

3

Multi-role auth

read blocked from calls, write/admin allowed, /metrics admin-only

4

Hot-Reload HTTP

Config change → notifications/tools/list_changed → tool list updated live

5

PERF_WARNING HTTP

A 6s call over HTTP triggers the PERF_WARNING log


HTTP / WebSocket Deployment

When using --transport http or --transport websocket, the router exposes:

Endpoint

Description

POST /mcp (and GET for SSE)

MCP Streamable HTTP transport — point your MCP client here

/ws

MCP WebSocket transport

/metrics

Prometheus metrics (tool calls, latencies, server health)

Connect any Streamable-HTTP-capable MCP client to http://<host>:8000/mcp. In your config you can fine-tune connection per server (timeout) and load external hooks.

Authentication — Multi-Role Bearer

Protect the network transports with Bearer token authentication. Three role levels are supported:

Role

list_tools

call_tool

/metrics

read

Visible

Blocked

403 Forbidden

write

Visible

Allowed

403 Forbidden

admin

Visible

Allowed

200 OK

Each user can optionally be restricted to specific sub-servers via server_access.

{
  "mcpServers": { },
  "auth": {
    "users": [
      { "name": "reader",  "token": "tok-read",  "role": "read" },
      { "name": "writer",  "token": "tok-write",  "role": "write", "server_access": ["github"] },
      { "name": "admin",   "token": "tok-admin",   "role": "admin" }
    ]
  }
}

Legacy mode — a single token (admin by default):

{ "auth": { "bearer_token": "my-secret-token" } }

Or via the environment variable OMNIMCP_BEARER_TOKEN (config key takes precedence).

Every request to /mcp and /ws must include Authorization: Bearer <token> (returns 401 otherwise). Without any auth config the network transports are open.

Pluggable Hooks

Load request/response hooks from external Python files without modifying the router. In mcp_router_config.json:

{
  "mcpServers": { },
  "hooks": ["path/to/my_hooks.py"]
}

The referenced module must expose a register_hooks(hook_system) function:

def register_hooks(hook_system):
    @hook_system.register_request_hook
    async def inject_tenant(server, tool, args):
        args["tenant"] = "acme"
        return args

Client Setup

Claude Desktop

Replace your entire claude_desktop_config.json with just OmniMCP:

{
  "mcpServers": {
    "omni-mcp": {
      "command": "python",
      "args": [
        "C:/path/to/OmniMCP/router.py",
        "--config",
        "C:/path/to/OmniMCP/mcp_router_config.json"
      ]
    }
  }
}

Cursor

In Cursor MCP settings, add a stdio server:

  • Name: OmniMCP

  • Command: python C:/path/to/OmniMCP/router.py --config C:/path/to/OmniMCP/mcp_router_config.json


Hook System

OmniMCP ships with a middleware pipeline for request/response mutation:

# Register a custom request hook (e.g. inject auth)
@gateway.hook_system.register_request_hook
async def inject_auth(server_name: str, tool_name: str, arguments: dict) -> dict:
    if server_name == "my-api":
        arguments["api_key"] = os.environ["MY_SECRET_KEY"]
    return arguments

# Register a custom response hook (e.g. redact PII)
@gateway.hook_system.register_response_hook
async def redact_pii(server_name, tool_name, result):
    # process result.content here
    return result

Built-in hooks:

  • Response Truncation — auto-truncates responses >50,000 chars with a clear notice


Resilience Architecture

┌──────────────────────────────────────────────────────┐
│              Claude Desktop / Cursor                  │
└──────────────────────┬───────────────────────────────┘
                       │ stdio (single MCP connection)
┌──────────────────────▼───────────────────────────────┐
│                  OmniMCP Router                       │
│  ┌─────────────────────────────────────────────────┐ │
│  │  Hook System │  Schema Validator  │   Profiler   │ │
│  └─────────────────────────────────────────────────┘ │
│  ┌──────────────┐ ┌──────────────┐ ┌────────────┐   │
│  │SubServer A   │ │SubServer B   │ │SubServer C │   │
│  │ connected  │ │ reconnecting│ │ connected│   │
│  │Auto-Healing  │ │Backoff: 4s   │ │            │   │
│  └──────────────┘ └──────────────┘ └────────────┘   │
└──────────────────────────────────────────────────────┘

If Sub-Server B crashes:

  • Its tools are hidden from the tool list

  • A reconnect loop starts with exponential backoff (1s → 2s → 4s → 8s → 16s)

  • On success: tools reappear, client gets notifications/tools/list_changed

  • After 5 failed attempts: marked failed, loop stops

  • Sub-Servers A and C are completely unaffected


Contributing

PRs are welcome! See CONTRIBUTING.md for guidelines.

  1. Fork the repo

  2. Create your branch: git checkout -b feat/my-feature

  3. Run tests: python run_integration_test.py

  4. Open a PR against main


Changelog

See CHANGELOG.md.

Releases

  • v1.1.0 (2026-08-28) — multi-role auth, Streamable HTTP + WebSocket transports, Prometheus metrics, Docker, full test suite. See the release notes.

  • v1.0.0 (2025-07-14) — core gateway: aggregation, auto-healing, hot-reload, hooks, perf monitoring, stdio transport.


License

MIT — see LICENSE.


Made for the MCP ecosystem If this saved you hours, drop a star

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A universal MCP server that acts as a unified gateway for dynamically connecting and managing multiple MCP servers via a single HTTP endpoint.
    7 npm
    6
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A zero-dependency universal MCP gateway that multiplexes multiple MCP servers across stdio, HTTP, and SSE, providing unified tool access, circuit breaking, and an interactive inspector studio.
    MIT