Working repository name. The gateway baseline keeps this name; the strategic experiment above it is described neutrally as a capability control plane.
mcphub-rs is a Rust-native gateway for composing multiple Model
Context Protocol (MCP) servers behind a small, secure, observable HTTP surface.
The goal is not a line-by-line port of MCPHub. It is a clean implementation of the useful product idea: supervise upstream MCP servers, expose deterministic scopes, and enforce routing and access policy at one boundary.
The v0.0 proof of concept is runnable. It supervises one in-repo stdio MCP
fixture and re-exposes its tool catalog through modern Streamable HTTP at
http://127.0.0.1:3737/mcp/s/fixture.
The correct gateway primitive is frozen at v0.0.1-poc-mcp-gateway. Work after
that tag tests a separate question: whether richer business-capability identity
and execution history belong above MCP tools.
- Architecture and product design
- Implementation roadmap
- Capability experiment
- Control-plane domain contract
The experiment now models Capability, Principal, Policy, implementation
routing, and Execution above the gateway. SQLite stores immutable principal
snapshots, append-only policy decisions, routing explanations, runtime links,
and effects. Refund and employee-onboarding fixtures test whether one business
capability can remain stable while context and policy choose among multiple
implementations. Denied, approval-gated, unmatched, and ambiguous requests stop
before a runtime is created.
cargo run -- capability inspect
cargo run -- execution run refund_customer \
--principal alice --role support-agent \
--amount-cents 5000 --region us --customer-type consumer
cargo run -- execution listSee the experiment note and domain contract for its boundary and evaluation criteria.
The pinned toolchain is installed automatically by Rustup. In one terminal:
cargo run -- serveIn another terminal, use the included modern MCP probe:
cargo run -- probeThe probe performs server/discover, tools/list, and an echo tools/call,
then prints the result as JSON. Stop the gateway with Ctrl-C.
Run the complete local verification suite with:
cargo fmt --all --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --all-targets --all-features
cargo tree --locked --all-features --target all -i rsa
cargo audit --deny warnings --ignore RUSTSEC-2023-0071
cargo deny --all-features checkThe empty cargo tree result is a guard for the audit exception. Duroxide's
SQLx dependency records an optional MySQL/RSA package in Cargo.lock, but that
package is not reachable in any target's build graph. CI fails if it becomes
reachable before applying the lockfile-only RustSec exception.
modern MCP client
-> Streamable HTTP /mcp/s/fixture
-> rmcp gateway handler
-> shared rmcp client
-> supervised stdio child
-> tool result
The gateway uses rmcp's native protocol types and JSON-RPC codec. Its small
stdio transport wrapper adds an inbound frame limit while retaining explicit
ownership of the child process. The integration tests exercise the real child
and HTTP server, verify Origin and exact-path rejection, call echo, enforce
advertised output schemas and standardized-header annotations, prove that a
timed-out tool receives upstream MCP cancellation, interrupt a hung startup,
force-close partial HTTP requests, and verify child cleanup after task abortion
and SIGTERM.
This is an unauthenticated development proof of concept, not a network service. It deliberately:
- rejects non-loopback listeners;
- supports only MCP
2026-07-28with discovery (no legacy fallback); - disables legacy HTTP sessions and requires per-request protocol metadata;
- validates browser origins and caps request bodies at 1 MiB;
- caps HTTP connections and requests, applies header and total-request deadlines, and force-closes requests that miss the shutdown drain deadline;
- exact-matches the MCP route instead of accepting suffix paths;
- disables upstream response caching and publishes private, zero-TTL tool lists;
- caps stdio frames, catalog pages/tools/bytes, concurrent calls, and deadlines;
- propagates downstream cancellation and timeouts to the upstream request, with a separate hard deadline for the cancellation flush;
- validates upstream structured results against advertised output schemas and rejects invalid standardized HTTP-header annotations during discovery;
- returns gateway infrastructure failures as protocol errors;
- uses one-round tool calls, with tasks and multi-round interactions rejected;
- starts commands without a shell, clears their ambient environment, continuously drains stderr while retaining only a bounded prefix, and gives the Unix process group (or direct child elsewhere) a bounded shutdown;
- owns every HTTP connection and supervisor task, and handles both SIGINT and SIGTERM without detaching the upstream child.
It does not yet load configuration, authenticate callers, reconnect a failed child, aggregate servers, bridge resources or prompts, isolate principals, or offer production telemetry. The POC intentionally serves HTTP/1.1 so every request remains owned by a tracked connection task; HTTP/2 requires a tracked per-stream executor before it is enabled. Those capabilities remain roadmap work.
- One self-contained Rust binary
- Official Rust MCP SDK (
rmcp) - Modern-only Streamable HTTP downstream interface
- stdio and Streamable HTTP upstreams
- Explicit single-server and curated multi-server scopes
- Stable, collision-free names for aggregated tools and prompts
- Declarative TOML configuration with secret references
- Secure local defaults, structured telemetry, and graceful supervision
- Legacy two-endpoint HTTP+SSE transport
- Hosted multi-tenant control plane
- Marketplace or package installation
- OpenAPI-to-MCP conversion
- Vector-search-based smart routing
- Social login and a bundled web dashboard
The product direction was informed by the behavior of the Apache-2.0 licensed MCPHub project. This repository uses a new Rust architecture and should not copy its source, assets, documentation, or UI. Any future copied or adapted material must be identified and attributed according to its license.
Apache License 2.0. See LICENSE.