Install
$ agentstack add mcp-mtiutin-mcp-bridge ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
mcp-bridge
A tiny Rust stdio ↔ HTTP transport bridge for the Model Context Protocol. It is a drop-in replacement for npx mcp-remote: it speaks JSON-RPC over stdin/stdout to a host agent, and proxies that traffic to a remote MCP server over streamable-HTTP (2025-03-26 spec) or legacy SSE.
It exists because the Node version was eating the host alive.
The problem we hit with Hermes
Our agent stack runs Hermes Agent (by Nous Research) on a single, memory-constrained host. Hermes connects to a couple dozen MCP servers — a mix of native streamable-HTTP backends and a handful that only speak legacy SSE.
Hermes can talk to a streamable-HTTP MCP server directly (mcp_servers..url). But for any server that only speaks the legacy SSE transport, the agent needs a stdio bridge subprocess in between. The canonical bridge is npx mcp-remote, a Node program.
That bridge turned out to be the single most expensive thing on the box:
- ~95 MB resident per instance. Six legacy-SSE backends meant ~570 MB just in bridge processes — for what is, functionally, a byte shuffler between a pipe and an HTTP socket.
- The gateway kept getting OOM-killed. Two things compounded: the gateway unit shipped with
oom_score_adj=100, marking it as the kernel's preferred victim, and the bridge processes left no headroom. Under any memory pressure, the kernel killed the gateway — taking down every messaging channel at once.
We fixed the operational side two ways:
- Moved most MCPs off bridges entirely. Where the upstream supports streamable-HTTP, Hermes connects directly via
url:+headers:— no subprocess at all. (In one case we rebuilt an upstream server from HEAD to pick up native streamable-HTTP and retired its bridge.) - Replaced the remaining bridges with this binary. For the backends that genuinely only speak legacy SSE,
mcp-bridgedoes the same job asnpx mcp-remoteat ~2 MB resident instead of ~95 MB.
We also set OOMScoreAdjust=-500 on the gateway unit so it's no longer the kernel's first pick. Net effect: the bridge layer went from ~570 MB to a couple of MB, and the OOM kills stopped.
What it does
host agent ──stdin/stdout (JSON-RPC lines)──▶ mcp-bridge ──HTTP──▶ MCP server
- Streamable-HTTP (default): POSTs each stdin line to the server; relays JSON or
text/event-streamresponses back to stdout. TracksMcp-Session-Id. Opens a backgroundGETsubscription for server-initiated messages, with exponential-backoff reconnect (and quietly gives up if the server answers405/404, meaning it doesn't support GET subscriptions). - Legacy SSE: connects
GET /sse, waits for the server'sendpointevent to learn the POST URL, then forwards stdin lines there. Reconnects with backoff if the stream drops. - Transport auto-detection: a URL path ending in
/sse(or containing/sse/) is treated as legacy SSE; everything else is streamable-HTTP. Override with--transport. - HTTPS by default: plain
http://is rejected unless the host is loopback or you pass--allow-http.
It is ~400 lines of Rust, built for size (opt-level = "z", LTO, stripped, panic = "abort"), producing a ~2 MB static binary.
Usage
mcp-bridge [--header "K: V"]... [--allow-http] [--transport http|sse|auto] [-v]
| Flag | Default | Meaning | |---|---|---| | ` | — | MCP server URL (…/mcp for streamable-HTTP, …/sse for legacy SSE) | | --header "K: V" | — | Add an HTTP header; repeatable (e.g. auth tokens) | | --allow-http | off | Permit non-loopback plain http:// URLs | | --transport | auto | Force http, sse, or auto-detect from the path | | -v, --verbose` | off | Diagnostic logging to stderr (stdout stays pure JSON-RPC) |
Examples:
# Legacy SSE backend on localhost (auto-detected from the /sse suffix)
mcp-bridge http://127.0.0.1:9801/sse
# Remote streamable-HTTP MCP with an auth header
mcp-bridge https://mcp.example.com/mcp --header "X-API-Key: $TOKEN"
# Force legacy SSE and watch the handshake
mcp-bridge https://mcp.example.com/stream --transport sse -v
> Note: diagnostics go to stderr only. stdout carries the JSON-RPC stream and must never be polluted, or the host agent's parser will choke.
Build
Standard Cargo project, no build scripts.
Native (build where you'll run it)
cargo build --release
# binary at target/release/mcp-bridge
Cross-compile from macOS to a Linux server (how we ship it)
We develop on macOS and run on Ubuntu x8664. A fully static musl binary cross-builds cleanly with cargo-zigbuild:
# one-time toolchain setup
brew install zig
cargo install cargo-zigbuild
rustup target add x86_64-unknown-linux-musl
# build the static binary
cargo zigbuild --release --target x86_64-unknown-linux-musl
# binary at target/x86_64-unknown-linux-musl/release/mcp-bridge (~2 MB, no libc dependency)
Deploy
scp -i ~/.ssh/your-key.pem \
target/x86_64-unknown-linux-musl/release/mcp-bridge \
root@:/usr/local/bin/mcp-bridge
ssh -i ~/.ssh/your-key.pem root@ 'chmod +x /usr/local/bin/mcp-bridge'
Wiring it into Hermes
> Built and tested against Hermes Agent. The CLI mirrors npx mcp-remote, so it also drops into any other MCP host that launches a stdio bridge subprocess (Claude Desktop, Cursor, etc.).
In ~/.hermes/config.yaml, point the MCP entry at the binary and pass the upstream URL as an argument:
mcp_servers:
mcp-foo:
command: /usr/local/bin/mcp-bridge
args: [http://127.0.0.1:9801/sse]
Then hermes gateway restart so the messaging path picks up the change. Verify with hermes mcp test mcp-foo.
Guidelines — when (and when not) to use this
The bridge is a fallback, not the default. Prefer the lightest transport the upstream supports.
- Direct
url:first. If the MCP server speaks streamable-HTTP, wire it into Hermes withmcp_servers.: { url: , headers: {...} }. No subprocess, no bridge — Hermes connects natively. This covers local FastMCP/supergateway servers and remote streamable-HTTP MCPs alike.
- Reach for
mcp-bridgeonly on legacy SSE. The tell: a directurl:config fails with405 Method Not Allowed(Hermes triesPOST /sse; a legacy server only acceptsGET /sseand replies with anendpointevent). That's the one case the native client can't handle. Switch the entry to thecommand:/args:form above.
- Never use
npx mcp-remote/command: npx. That's the ~95 MB-per-instance pattern this project was built to retire.mcp-bridgeis a drop-in replacement — same CLI shape, ~2 MB.
- Keep stdout clean. Anything the bridge needs to say goes to stderr (
-v). stdout is the JSON-RPC channel and nothing else.
- Don't relax HTTPS without reason.
--allow-httpis for trusted loopback/LAN backends only; leave it off for anything reachable over the network.
- One bridge process per backend. Like the rest of the local-MCP layout, treat each bridge as a long-lived singleton the agent connects to, not something to spawn per session.
Layout
src/main.rs # the whole bridge (~400 lines): arg parsing, streamable-HTTP, legacy SSE
Cargo.toml # deps + size-optimized release profile
Dependencies: tokio, reqwest (rustls, no OpenSSL), eventsource-stream, clap, serde_json, url, anyhow.
Credits & related
- Hermes Agent by Nous Research — the agent runtime this bridge was built for.
- mcp-remote — the Node tool whose CLI this mirrors and whose memory footprint motivated the rewrite.
- Model Context Protocol — transport spec (2025-03-26).
License
[Apache License 2.0](LICENSE) © 2026 Miha Tiutin.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mtiutin
- Source: mtiutin/mcp-bridge
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.