mcp-hub
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
A dual-era Model Context Protocol (MCP) gateway: it
serves many stdio MCP servers from **one container**, published over HTTPS, and speaks
**both MCP revisions on every endpoint** — 2026-07-28 and 2025-11-25. The client
picks, and cannot tell which one it is on from the answers. On the 2026 revision that
includes **elicitation** — a child server's question reaches the person at the far end
instead of dying at the gateway
(how) — and **subscriptions**: the hub
serves subscriptions/listen to its clients and subscribes to its children on
whichever revision _they_ speak, so a server that has never heard of it still reaches
a client that speaks nothing else
(how).
Lets MCP clients that cannot spawn a local process — ChatGPT connectors, Claude on
the Web and in Code, Mistral Le Chat, Cursor, LibreChat and any other
Streamable-HTTP client — reach every server behind it, with a built-in OAuth 2.1
login protected by a single password, plus long-lived API tokens for clients that
cannot do OAuth (OpenAI Responses API, xAI API, Gemini API). Per-client recipes:
client compatibility.
is resolved against the colour scheme of the page showing it, so GitHub
picks the variant that matches its own theme toggle. npm strips and
when it sanitises the README and keeps the , which is why that
fallback brings its own dark card instead of relying on a media query. -->
**Want to poke at it first?** demo/ is a throwaway hub with three
fake servers — docker compose up -d, then point the
MCP Inspector or
MCPJam at it. Nothing to
configure, nothing to clean up but a volume.
Why
Wrapping each stdio MCP server in its own auth-proxy container costs a full
image, an OAuth stack, a hostname and a compose stack _per server_. mcp-hub
replaces N containers with one process:
- **Config is exactly Claude Code's mcpServers format** — copy entries 1:1.
- **Path-based routing**: https://host/paperless, https://host/homeassistant, …
- **/hub aggregate**: register a _single_ connector and reach every server
through 6 meta-tools (list_servers, list_tools, get_tool_schema,
call_tool, wake_server, sleep_server) without flooding the model
context with N×tools schemas.
- **Per-server tool filtering**: allowTools / denyTools on any server decide
which of its tools the hub exposes — exact names or list_* prefixes. A
filtered tool is hidden from tools/list _and_ refused if a client calls it
anyway, before the server is even woken, so a client holding a stale schema
cannot reach it.
- **Also without HTTP**: mcp-hub --stdio serves that same aggregate on
stdin/stdout for clients that can only spawn a local process (Claude Desktop,
Codex, …) — same mcp.json, no TLS, no reverse proxy, no login. Auth exists
for the network endpoints; over stdio the trust boundary is the local user.
- **On-demand lifecycle**: stdio and docker servers start when used and sleep
after 60 idle minutes, answering initialize/tools/list from a persistent
snapshot meanwhile — a dozen servers cost only the memory of the ones in
use. keepAlive: true exempts a server, IDLE_TIMEOUT_MINUTES=0 the hub.
- **CIMD-first OAuth 2.1**: clients identify themselves with a Client ID
Metadata Document — the
registration-free path the MCP spec now prefers — including private_key_jwt
against the keys in their own document (metadata-document clients only). RFC
7591 dynamic registration stays advertised beside it for older clients,
mcp-hub-admin clients add issues credentials by hand for anything that can
do neither, and CLIENT_REGISTRATION turns either mechanism off.
- **OAuth outwards, too**: a remote server that speaks OAuth gets an oauth
block instead of a static header. The hub registers itself — with credentials
the upstream issued, via RFC 7591, or with its own client metadata document —
then obtains and refreshes the token. client_credentials upstreams need no
attention at all; where a person must sign in, mcp-hub-admin upstream login
prints one URL. An upstream that needs re-authorizing shows up as one server
unauthorized, not as a confusing 401 in your client.
- **Supervision**: children are pinged and restarted with exponential backoff
when they die. A down server answers 503, not silence; a crash-looping
server nobody uses is parked instead of restarted forever.
- **Hot reload**: edits to mcp.json start/stop/restart only the affected
servers.
- **Stateless Streamable HTTP**: no session state, so claude.ai's
reconnect-without-DELETE behaviour cannot leak processes or memory.
- **Dual-era**: every endpoint — /hub, / /mcp and --stdio — answers