mcp-stdio-bridge
A generic, professional-grade gateway that bridges Model Context Protocol (MCP) servers between SSE (Server-Sent Events) and Stdio transports. It also ships a command-wrapper mode that turns any CLI tool directly into an MCP server without writing extra code.
Python · Unlicense · GitHub · PyPI
Why
MCP clients and servers do not always agree on transport: a remote client
that only speaks SSE over HTTP still needs to talk to a local process that
only speaks stdio, and vice versa. mcp-stdio-bridge sits in between and
translates. Its command-wrapper mode goes a step further -- instead of
proxying an existing MCP server, it hosts one internally and exposes
individual CLI invocations as MCP tools, with argument allowlisting,
environment scrubbing, and path traversal protection so the wrapped
command can't be turned into a shell.
Features
- Generic bridge -- works with any executable that speaks MCP over stdio.
- Command wrapper mode -- directly wrap any CLI utility (
wp-cli,git, custom scripts) into a restricted MCP server without external glue code. - Dual transport -- SSE (HTTP/HTTPS) for remote access or stdio for local use by MCP clients.
- 100% test coverage -- exhaustive suite across all transports, operational modes, and failure paths.
- YAML configuration -- central config file, layered with CLI flags
and
MCP_*environment variables. - Dynamic config reload -- opt-in live-reload from
config.yamlvia--watch-configorSIGHUPon POSIX systems. - Daemon mode --
--daemonizeperforms a POSIX double-fork to detach from the terminal; pairs with--pid-filefor supervisor integration. - Idle session timeouts -- automatically terminates stalled proxy and wrapper sessions to prevent resource leaks.
- Security -- API key authentication (header or query param), restricted argument prefixing and regex filtering for wrapped commands, directory traversal protection, environment allowlist/denylist scrubbing, secret masking in logs, connection limiting and message size throttling, and SSL/TLS with client certificate and CRL support.
Quick start
pip install mcp-stdio-bridge
# Proxy mode -- bridge an existing MCP stdio server over SSE
mcp-stdio-bridge --command "python my_mcp_server.py" --transport sse --port 8000
# Command-wrapper mode -- wrap a CLI tool as an MCP server
mcp-stdio-bridge --mode command-wrapper --config config.yaml
Minimal config.yaml:
Architecture
Two independent axes -- transport and mode -- combine orthogonally:
- Transport layer (
transport/sse.py,transport/stdio.py) -- SSE runs on Starlette + Uvicorn with API key auth, connection limits, and SSL/TLS; stdio uses raw stdin/stdout with logging forced to stderr to keep the JSON-RPC stream clean. - Mode layer (
mode/proxy.py,mode/wrapper.py) -- proxy mode spawns one subprocess per connection and bridges streams bidirectionally, with anActivityMonitorhandling idle-timeout termination; wrapper mode runs an internal MCP server where eachwrapped_commandsentry becomes an MCP tool, enforcing argument allowlist/denylist rules viashlexparsing (noshell=Trueanywhere).
main.py loads configuration, initializes logging, optionally starts a
config file watcher, then dispatches to the selected transport.
Security
- API key authentication -- timing-safe comparison via
APIKeyMiddleware. - Security headers -- CSP, HSTS, and X-Frame-Options via
SecurityHeadersMiddleware. - Argument sandboxing -- per-tool
allowed_args,allowed_patterns,forbidden_args,forbidden_patterns; allowlist and denylist rules are mutually exclusive. - Path traversal protection -- blocks
..segments and absolute paths outside the configured working directory. - Environment scrubbing -- sensitive variables stripped by default;
env_allowlistallows explicit pass-through. - No shell injection --
shlex.splitplus list-formanyio.run_process;shell=Trueis never used.
Deployment
Supports local execution, Docker, and Docker Compose:
docker build -t mcp-stdio-bridge .
docker run -p 8000:8000 -v $(pwd)/config.yaml:/app/config.yaml mcp-stdio-bridge
Examples
Ready-to-use configuration templates ship in the
examples/
directory:
| File | Description |
|---|---|
wp-cli-wrapper.yaml |
Manage WordPress via MCP using a mix of allowlist and denylist rules |
git-wrapper.yaml |
Expose Git operations to local clients (allowlist-only) |
sqlite-proxy.yaml |
Bridge an existing SQLite MCP server to SSE |
security-patterns.yaml |
Advanced regex-based security filtering |
docker-tool-wrapper.yaml |
Per-tool custom environment variables with Docker |