mcp-call-orchestrator-proxy
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-call-orchestrator-proxycheck the backend status and tell me if it's reachable right now"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-call-orchestrator-proxy
A resilient, session-terminating, call-serializing MCP proxy that sits in front of a single backend MCP server and makes it safe for multiple concurrent clients.
Some MCP servers have session-routing bugs or no call serialization, so two concurrent MCP clients (e.g. two agents, or an agent plus a manual test) can hang or step on each other. This proxy terminates each client's MCP session, serializes the calls it forwards to the one backend, and exposes the backend's exact same tools with exact schema parity — so clients see a well-behaved server, unchanged except for the added stability.
Features
Exact tool parity — mirrors the backend's tools with identical names and schemas; nothing to keep in sync by hand.
Multi-session safe — independent MCP clients can connect over HTTP at the same time without cross-talk or hangs.
Call serialization — calls to the backend are queued and orchestrated (configurable concurrency) instead of racing each other.
Resilient to the backend coming and going — starts cleanly whether or not the backend is running yet, reconnects automatically (gentle, bounded backoff — never hammers a down endpoint) after the backend starts, restarts, or drops mid-session, and shuts down promptly on
SIGTERMeven mid-backoff.backend_statustool — lets a client ask "is the backend reachable right now?" without triggering a failing call. Returnsconnected,backend_url,last_connected_at,last_error,consecutive_failures, andcurrent_backoff_seconds.Exposure control — optional exact-name allow-lists or deny-lists for tools, resources (including resource templates) and prompts. Hidden items are absent from listings and uncallable by name. Off by default (full parity). See Exposure control.
Related MCP server: mcp-gateway
Requirements
Python 3.12+
A backend MCP server to front.
Linux with a user-level
systemdif you want the proxy to run as a background service (optional; see Run as a service).
Installation
From the root of this repository:
uv syncThis creates .venv/ with all dependencies and installs the
mcp-call-orchestrator-proxy console script into it. Verify it worked:
uv run mcp-call-orchestrator-proxy --helpConfiguration
Settings load from environment variables (or a .env file in the current
working directory) via pydantic-settings, all prefixed MCP_PROXY_. There are
two ways to point the proxy at its backend.
Option 1 (recommended): a standard mcpServers JSON config file
Point the proxy at a JSON file in the same mcpServers format Claude Desktop /
Cursor / Copilot use. FastMCP parses and validates it, so there's no schema to
hand-write:
{
"mcpServers": {
"some-mcp-server": {
"url": "https://127.0.0.1:27124/mcp/",
"transport": "http",
"auth": "YOUR_BEARER_TOKEN"
}
}
}export MCP_PROXY_BACKEND_CONFIG="/path/to/backend.json"The config must define exactly one server — this proxy fronts a single
backend. The auth string is sent as a Bearer token. TLS verification is not
part of the mcpServers format, so it stays a separate knob
(MCP_PROXY_BACKEND_VERIFY_TLS, default false). An example lives at
deploy/systemd/backend.example.json.
The backend can just as well be a stdio server — most of the MCP ecosystem ships this way — described the same way any MCP client would describe it: command, arguments, and (optionally) environment and working directory:
{
"mcpServers": {
"some-mcp-server": {
"command": "uv",
"args": ["run", "some-mcp-server"],
"env": { "SOME_VAR": "value" }
}
}
}The proxy owns that process's whole life: it starts the backend on connect,
keeps the same process across reconnects, and kills it on disconnect or
shutdown — nothing is left running behind. (A keep_alive field in this JSON
is accepted by the format but has no effect here; the proxy always manages the
process itself.) This is independent of the client-facing transport covered
next — a proxy listening over HTTP can front a stdio backend, and vice versa.
Option 2: individual environment variables
If MCP_PROXY_BACKEND_CONFIG is unset, the proxy builds the connection from
these instead. MCP_PROXY_BACKEND_API_KEY is required in this mode.
Variable | Default | Meaning |
| (unset) | Path to an |
| (required in Option 2) | Bearer token for the backend. |
|
| Backend's Streamable HTTP MCP endpoint. |
|
| Verify the backend's TLS cert. |
|
| Name the proxy reports as its MCP server identity (the |
|
| Host the proxy itself binds to. |
|
| Port the proxy itself listens on. |
|
| Concurrent calls allowed to the backend ( |
|
| Timeout for a single backend tool call. |
|
| Timeout for a single backend connect/initialize attempt. |
|
| First delay before retrying a failed connection. |
|
| Cap on the exponential reconnect backoff. |
|
| Growth factor applied to the backoff after each failure. |
|
| How often a held connection is locally re-checked (no network traffic). |
|
|
|
| (unset) | Comma-separated tool names to expose (exact match). When set, only these tools are visible; |
| (unset) | Comma-separated tool names to hide (exact match). Ignored when |
| (unset) | Comma-separated resource URIs / template |
| (unset) | Comma-separated resource URIs / template |
| (unset) | Comma-separated prompt names to expose (exact match). When set, |
| (unset) | Comma-separated prompt names to hide. Ignored when allow is set. |
The most commonly tuned values are also available as CLI flags
(--host, --port, --transport, --backend-config, --connect-timeout,
--reconnect-initial-backoff, --reconnect-max-backoff, --log-level) — run
uv run mcp-call-orchestrator-proxy --help for the full list. CLI flags win over
environment variables.
Exposure control
By default the proxy exposes the backend's full tool / resource / prompt surface
(plus backend_status). When an agent should only see a subset, set an
allow-list or deny-list per surface:
# Only these tools (and nothing else — include backend_status if you want it):
export MCP_PROXY_TOOL_ALLOW="echo,slow_echo,backend_status"
# Or hide specific tools while leaving the rest visible:
export MCP_PROXY_TOOL_DENY="hang,crash"Rules:
Exact names only — no globs or regex. Names match the backend's real tool/prompt
name, a resource's URI string, or a template'suriTemplate.Blank means unset —
MCP_PROXY_TOOL_ALLOW=is the same as leaving the variable out (not "allow nothing").Allow beats deny on the same surface — if both are set, the allow-list decides alone and a
WARNINGnames that surface at startup.Hidden is uncallable — filtered items are absent from listings and return a protocol-level "not found" if invoked by name.
backend_statusis not special — it is filtered like any other tool. If a tool allow-list omits it (or a deny-list names it), aWARNINGis logged once at startup; the filter is still honoured.Unknown filter names — after the first successful discovery for a surface, each name that does not exist on the backend is reported once per process as a
WARNING(typos / stale lists). Startup is never blocked by a misconfigured filter.Resource lists cover concrete resources and resource templates with the same name set (a template that could synthesize a hidden URI would otherwise bypass a resource allow-list).
Usage
Run it manually
# Option 1 — JSON backend config:
export MCP_PROXY_BACKEND_CONFIG="/path/to/backend.json"
uv run mcp-call-orchestrator-proxy run
# Option 2 — individual env vars:
export MCP_PROXY_BACKEND_API_KEY="your-real-api-key"
export MCP_PROXY_BACKEND_MCP_URL="https://127.0.0.1:27124/mcp/" # only if not the default
uv run mcp-call-orchestrator-proxy runBy default it serves Streamable HTTP on http://127.0.0.1:27125/mcp/. Point your
MCP client(s) there instead of at the backend directly. It's safe to start this
before the backend is running — it will sit connectable and reconnect
automatically once the backend appears (see backend_status).
For stdio transport instead (e.g. for a client that spawns the process
itself): uv run mcp-call-orchestrator-proxy run --transport stdio.
Check backend health
Any connected client can call the backend_status tool to check whether the
backend is currently reachable, instead of guessing from a failed call:
{"connected": true, "backend_url": "https://127.0.0.1:27124/mcp/",
"last_connected_at": "2026-07-11T18:02:03+00:00", "last_error": null,
"consecutive_failures": 0, "current_backoff_seconds": 1.0}Run as a service
The intended deployment is a systemd --user service that starts at login (or at
boot, with lingering enabled) and stays up whether or not the backend is running.
Unit templates are in deploy/systemd/, and
docs/deployment.md walks through installing them.
Logs
MCP_PROXY_LOG_LEVEL (or --log-level) controls verbosity: DEBUG, INFO (default),
WARNING, ERROR, or CRITICAL. WARNING+ is just backend outages and recoveries;
INFO adds a record per call as it's queued and as it completes; DEBUG adds internal
detail for fault-finding.
Records go to stdout/stderr, so under systemd they land in the journal:
journalctl --user -u mcp-call-orchestrator-proxy -p warning # outages/recoveries only
journalctl --user -u mcp-call-orchestrator-proxy -f # follow at the configured levelDevelopment
uv run poe gate # lint + format-check + mypy + unit + component + integration*
uv run poe format # auto-format
uv run poe test-int # integration tests only, as a standalone shortcut
uv run poe check-py313 # optional: full gate on Python 3.13, own venv (forward-compat only; floor stays 3.12)* The integration tier runs against your own backend, read from
tests/integration/backend.json (a gitignored mcpServers file — copy
tests/integration/backend.example.json). Without it, that step skips itself
cleanly and says why; the gate stays green. Everything else is offline: no
network and no backend of your own is needed.
Documentation
ARCHITECTURE.md— canonical technical overview: components, call flow, invariants, resilience model.docs/deployment.md— running the proxy as a systemd user service.docs/testing.md— the test tiers and how to add to them.docs/coding-standards.md— code conventions.docs/roadmap.md— what's done and what's next.docs/issues.md— observed defects, each with its root cause and fix.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProxy-style MCP tool multiplexer that aggregates multiple downstream stdio MCP servers into one, offering meta-tools for status, search, call, parallel, batch, and pipeline operations with concurrency control and caching.-
- FlicenseNot gradedqualityDmaintenanceAggregates multiple child MCP servers into a single MCP server endpoint, enabling clients to use various tools (e.g., filesystem, Brave Search) through one interface.25 npm-
- AlicenseAqualityDmaintenanceSelf-healing proxy for MCP servers that wraps tool calls with automatic retry, circuit breaker protection, and observability.530 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables clients to connect once and access the union of multiple backend MCP servers' tools through a single unified interface, with namespaced tool routing, capability search, and health isolation.MIT