Skip to main content

mcp-combiner

An MCP aggregator — fronts multiple MCP servers behind a single Streamable HTTP endpoint, so one connection exposes every backend server's tools. Built on FastMCP. Shareable across clients (via sharedserver), it powers the mcp-companion Neovim plugin and the mcp-combiner Claude Code plugin, and works standalone with any MCP client.

PyPI package · command · import package: mcp-combiner / mcp-combiner / mcp_combiner.

⚠️ Renamed from mcp-bridge. If you ran an earlier build:

  • command/import are now mcp-combiner / mcp_combiner; reinstall: uv tool uninstall mcp-bridge then uv tool install … (see Install below).
  • config env vars MCP_BRIDGE_*MCP_COMBINER_* (and MCP_COMPANION_COMBINER_URLMCP_COMPANION_COMBINER_URL).
  • OAuth token storage moved to ~/.cache/mcp-combiner/ — you'll re-authenticate each MCP server once (old tokens under ~/.cache/mcp-companion/ are no longer read).

Install

Needs only uvuvx fetches and runs it, no venv to manage:

uvx mcp-combiner --help                                                # once published to PyPI
# before PyPI (or to track main) — the package lives in the combiner/ subdirectory:
uvx --from "git+https://github.com/georgeharker/mcp-companion#subdirectory=combiner" mcp-combiner

Or install it: uv pip install mcp-combiner (PyPI), or from the repo subdir uv pip install "git+https://github.com/georgeharker/mcp-companion#subdirectory=combiner".

Usage

mcp-combiner --config /path/to/servers.json --port 9741

Inbound authentication

By default the /mcp endpoint is unauthenticated — fine on loopback, but a hole the moment you bind beyond 127.0.0.1 (--host) or share the box. Set a bearer token and every request to /mcp must present Authorization: Bearer <token>:

MCP_COMBINER_AUTH_TOKEN=$(cat ~/secrets/combiner-token) \
  mcp-combiner --config  --port 9741
# or, daemon-side:
mcp-combiner --config  --auth-token-file ~/secrets/combiner-token
  • Unset (both) → endpoint stays open (default; nothing changes).
  • --auth-token-file wins over the env var; a blank/unreadable file → stays open.
  • Scope: /mcp and the control routes that mutate the running server — /sessions* (session filters) and /handover* (restart handover). /health stays open for liveness probes. Because the control routes are gated, the combiner's own callers present the token too: the mcp-combiner ctl and the Neovim host's REST client both read MCP_COMBINER_AUTH_TOKEN.
  • A missing/wrong token gets a plain 401 — no WWW-Authenticate: Bearer, so standards clients surface an honest auth error instead of falling into OAuth / Dynamic Client Registration. Clients present the token pre-emptively.

The companion clients pick the token up from the same MCP_COMBINER_AUTH_TOKEN env var (Claude Code, OpenCode, Pi, and the Neovim host) — provision it once in your environment (or via each client's documented hook) and it flows to all of them.

Reusing the gate on other FastMCP servers

The middleware lives in mcp_combiner/inbound_auth.py and is self-contained (stdlib + starlette only), so a sibling FastMCP server (e.g. cribsheet, svg-mcp) can vendor the file and gate its own /mcp. Each server names its own env var — set them to the same value for one shared secret, or distinct values for per-service isolation:

server env var
mcp-combiner MCP_COMBINER_AUTH_TOKEN
cribsheet CRIBSHEET_AUTH_TOKEN
svg-mcp SVG_MCP_AUTH_TOKEN
from inbound_auth import BearerAuthMiddleware, resolve_auth_token

token = resolve_auth_token("CRIBSHEET_AUTH_TOKEN")   # or a --auth-token-file
if token:
    app.add_middleware(
        BearerAuthMiddleware, token=token,
        is_protected=lambda path: path != "/health",  # plain servers: gate all but health
    )

The combiner, in turn, presents the backend's token when it connects — add it to that server's servers.json entry: {"auth": {"bearer": "${CRIBSHEET_AUTH_TOKEN}"}} (or a headers map). See Authentication → Bearer token in the top-level README.

Development

uv sync
pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_combiner-0.13.1.tar.gz (302.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_combiner-0.13.1-py3-none-any.whl (161.9 kB view details)

Uploaded Python 3

File details

Details for the file mcp_combiner-0.13.1.tar.gz.

File metadata

  • Download URL: mcp_combiner-0.13.1.tar.gz
  • Upload date:
  • Size: 302.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mcp_combiner-0.13.1.tar.gz
Algorithm Hash digest
SHA256 8be0da31ba669510bf5e57fc3f3b6864e02dc63d11838e56cd7fbbd23b8fd10e
MD5 fbd67589da2ed5c0cbab8a8d488869be
BLAKE2b-256 2cb5ad6e3c9036c8f585d28f4f0531c270d5565623ed1cbff8756fd0177dcecb

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_combiner-0.13.1.tar.gz:

Publisher: release.yml on georgeharker/mcp-companion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mcp_combiner-0.13.1-py3-none-any.whl.

File metadata

  • Download URL: mcp_combiner-0.13.1-py3-none-any.whl
  • Upload date:
  • Size: 161.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mcp_combiner-0.13.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bcf2e5893945086657c06709e6f60ce1cfd136e0b3ec28aa0ece0f2cf50dafac
MD5 8e837e38653c6424e938be39599f9020
BLAKE2b-256 82f9833d9b892e7f299c6126ba94755f1df4a4511deccd9726c60f9aa9e16e97

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_combiner-0.13.1-py3-none-any.whl:

Publisher: release.yml on georgeharker/mcp-companion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.13.4

2 files

0.13.3

2 files

0.13.2

2 files

This release

0.13.1 This release

2 files

0.13.0

2 files

0.12.0

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.0

2 files

0.7.6

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.2

2 files

0.6.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page