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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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.
    24
    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

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Simonc44/OmniMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server