mcp-hub
mcp-hub is a tools-only Model Context Protocol
(MCP) aggregation server. It starts configured stdio MCP servers and exposes their
available tools through one stdio MCP endpoint.
The hub itself is lightweight and ships as a compact single binary, with no separate runtime service to deploy or manage.
Use it to give an MCP client one curated tool inventory instead of configuring every upstream server separately, while retaining control over the names, availability, and safety metadata of exposed tools. Prefixes prevent tool-name collisions, and named instances let the same upstream run with different settings.
Features
- Aggregates tools from multiple stdio upstream MCP servers and routes calls to the owning upstream.
- Supports optional visible prefixes such as
github.search_issuesto prevent tool-name collisions; unprefixed tools keep their original names. Ambiguous outward names fail startup rather than being silently shadowed. - Curates each upstream with
includeorexcludepatterns.*is a full-name, case-sensitive wildcard andincludetakes precedence when both are set. - Preserves tool descriptions, schemas, annotations, and result content; configuration
can override the
read_only,destructive, andopen_worldannotations. - Allows several independently configured instances of the same upstream binary, with different arguments, environment variables, prefixes, and tool filters; unavailable or slow upstreams do not take down the remaining inventory.
- Advertises only MCP tools. Prompts, resources, roots, sampling, elicitation, and task-required tools are intentionally out of scope.
Install
Install the latest published release from crates.io:
Prebuilt binaries
Download the matching archive from the latest GitHub release:
| Platform | Archive |
|---|---|
| Linux x86_64 (GNU) | mcp-hub-x86_64-unknown-linux-gnu.tar.xz |
| Linux ARM64 (GNU) | mcp-hub-aarch64-unknown-linux-gnu.tar.xz |
| Linux x86_64 (static musl) | mcp-hub-x86_64-unknown-linux-musl.tar.xz |
| Linux ARM64 (static musl) | mcp-hub-aarch64-unknown-linux-musl.tar.xz |
| macOS Intel | mcp-hub-x86_64-apple-darwin.tar.xz |
| macOS Apple silicon | mcp-hub-aarch64-apple-darwin.tar.xz |
| Windows x86_64 | mcp-hub-x86_64-pc-windows-msvc.zip |
Every archive is also available at
https://github.com/gleb-chipiga/mcp-hub/releases/latest/download/<archive-name>.
For example, install the static x86_64 Linux build:
On macOS, download the matching .tar.xz archive, unpack it with tar -xJf, and
install the mcp-hub file from its top-level directory. On Windows, download the
.zip archive, extract it, and run mcp-hub.exe from the extracted top-level directory.
Each release also includes sha256.sum and a per-archive .sha256 checksum file.
On Linux, verify a downloaded archive with:
Verify the archive provenance with GitHub CLI and its artifact attestation:
mise
Install the latest GitHub Release for the current platform:
Run
The first command-line argument is the TOML configuration path. Alternatively, set
MCP_HUB_CONFIG. The hub speaks MCP over standard input/output and writes tracing
logs to standard error.
Logging and tracing
mcp-hub uses tracing and writes log records to standard error through a
non-blocking writer. Standard output is reserved exclusively for MCP traffic; never
send logs to standard output.
By default, or when RUST_LOG is invalid, the filter is info,mcp_hub=debug:
dependency logs at info and above, and hub logs at debug and above. Set
RUST_LOG in the environment of the mcp-hub process to replace that filter:
# Show only warnings and errors from all crates.
RUST_LOG=warn
# Keep normal dependency logs and enable verbose hub diagnostics.
RUST_LOG=info,mcp_hub=debug
# Diagnose MCP transport behaviour as well.
RUST_LOG=warn,mcp_hub=trace,rmcp=debug
To retain logs when starting the binary directly, redirect standard error. The hub does not create log files or rotate them; use a supervisor or your system's log rotation for long-running processes.
When an MCP client starts mcp-hub, configure RUST_LOG in that client's process
environment or MCP-server entry. The [servers.<instance_id>.env] table in the hub
configuration is passed only to the upstream child process; it does not configure
the hub's own tracing.
Configuration
Configuration files use TOML 1.1. They must define at least one
[servers.<instance_id>] table. An instance ID identifies an upstream in logs and
startup errors; it is not exposed to MCP clients unless it is also used as prefix.
Instance IDs and prefixes may contain ASCII letters, digits, -, and _, but not
..
Server fields
| Field | Required | Description |
|---|---|---|
command |
Yes | Executable path or command name for the upstream stdio server. |
args |
No | Array of command-line arguments. Defaults to []. |
env |
No | Environment variables added to or overriding the child process environment. |
prefix |
No | Outward name prefix. A tool named search becomes <prefix>.search. |
tools.include |
No | Allowlist of original upstream tool names or * masks. |
tools.exclude |
No | Denylist used only when include is absent. |
tools.overrides.<tool> |
No | Annotation overrides for one original upstream tool name. |
Minimal server
The smallest configuration starts one upstream process and exposes all of its non-task-required tools with their original names:
[]
= "npx"
= ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
Multiple upstreams and prefixes
Every server entry starts an independent upstream process. Use prefixes when two servers could expose the same tool names, or when namespacing makes the client-facing inventory clearer:
[]
= "npx"
= ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
[]
= "gh"
= "uvx"
= ["mcp-server-github"]
[]
= "replace-with-token"
= "acme"
= "platform"
The filesystem tool read_file remains read_file; a GitHub tool search_issues
is exposed as gh.search_issues. Without distinct prefixes, two active upstreams
that expose the same outward name cause startup to fail.
env values are forwarded verbatim to the child process. The hub does not expand
${VAR} placeholders, so provide already-resolved values through your deployment
configuration and do not commit secrets.
Select tools
Filters match the original upstream name, before applying prefix. A filter
without * is an exact match; * matches zero or more characters across the whole,
case-sensitive name.
[]
= "gh"
= "uvx"
= ["mcp-server-github"]
[]
= ["list_*", "read_*", "search_*", "create_comment"]
This exposes only matching tools, such as gh.list_issues and gh.create_comment.
Other useful masks include "*webhook", "read_*shot", and "resource_*".
Use exclude to remove a small set of tools from an otherwise complete inventory:
[]
= "gh_admin"
= "uvx"
= ["mcp-server-github", "--mode", "admin"]
[]
= ["list_*", "read_*", "search_*"]
If both include and exclude are present, include wins and exclude is ignored.
Literal * is reserved for filters: an upstream tool name or an override target that
contains * is rejected.
Override safety annotations
The hub preserves upstream tool metadata by default. Set only the annotation hints that need correction; unspecified hints remain unchanged:
[]
= false
= true
[]
= true
Supported fields are read_only, destructive, and open_world. The latter also
accepts the aliases external, external_side_effect, and sends_external_data.
An override must use the exact original name of a tool advertised by that upstream;
a misspelled target fails startup.
Run and startup behavior
Pass the configuration path as the first argument, or set MCP_HUB_CONFIG:
MCP_HUB_CONFIG=mcp-hub.toml
At startup, the hub connects to each upstream and discovers its tools. The default
connection and discovery timeout is five seconds and can be changed with
MCP_HUB_STARTUP_TIMEOUT_MS. An unavailable or timed-out upstream is omitted while
the remaining tools stay available. Configuration errors, duplicate outward tool
names, invalid tool names, and unknown annotation-override targets fail startup.
See mcp-hub.example.toml for a compact combined example.
Roadmap
The current implementation connects to local upstream servers over stdio only. Support for remote upstream MCP servers over a network transport is planned.