A generic stdio-to-streamable-HTTP proxy for MCP (Model Context Protocol) servers
Project description
mcp-streamablehttp-proxy
A generic stdio-to-StreamableHTTP bridge for MCP (Model Context Protocol) servers. This proxy enables any stdio-based MCP server to be accessed via HTTP endpoints, making them compatible with web-based clients and HTTP infrastructure like API gateways.
Overview
The mcp-streamablehttp-proxy acts as a translation layer between:
- MCP clients that speak StreamableHTTP (like Claude.ai, web-based IDEs)
- MCP servers that only speak stdio JSON-RPC (like the official MCP servers)
It manages sessions, spawns server subprocesses, and handles the protocol translation transparently.
Features
- Universal MCP Server Support - Works with any stdio-based MCP server
- Session Management - Each client gets an isolated server subprocess
- Full Protocol Support - Handles the complete MCP lifecycle
- Configurable - Flexible timeout, host, and port configuration
- Production Ready - Async implementation with proper cleanup
- Gateway Compatible - Designed for use with Traefik and OAuth gateways
Installation
Via pip
pip install mcp-streamablehttp-proxy
Via pixi
pixi add --pypi mcp-streamablehttp-proxy
Usage
Basic Usage
# Proxy a Python MCP server module
mcp-streamablehttp-proxy python -m mcp_server_fetch
# Proxy an executable MCP server
mcp-streamablehttp-proxy /usr/local/bin/mcp-server-filesystem --root /data
# Proxy an npm-based MCP server
mcp-streamablehttp-proxy npx @modelcontextprotocol/server-memory
Command Line Options
mcp-streamablehttp-proxy [OPTIONS] <server_command> [server_args...]
Options:
--host TEXT Host to bind to (default: 127.0.0.1)
--port INTEGER Port to bind to (default: 3000)
--timeout INTEGER Session timeout in seconds (default: 300)
--log-level TEXT Log level: debug/info/warning/error (default: info)
--help Show this message and exit
Environment Variables
MCP_BIND_HOST- Override default bind hostMCP_PORT- Override default portLOG_FILE- Enable file logging to specified path
How It Works
- Client sends HTTP request to
/mcpendpoint - Proxy creates session on first
initializerequest - Proxy spawns subprocess running the specified MCP server
- Proxy translates between HTTP and stdio protocols
- Client includes session ID in subsequent requests
- Sessions timeout after period of inactivity
API
Endpoint
- POST /mcp - Single endpoint for all MCP protocol messages
Headers
- Mcp-Session-Id - Required for all requests after initialization
- Content-Type - Must be
application/json
Request Format
Standard JSON-RPC 2.0 messages:
{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
},
"id": 1
}
Response Format
JSON-RPC 2.0 responses with session ID header:
{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
},
"id": 1
}
Response includes header: Mcp-Session-Id: <uuid>
Examples
Testing with curl
# Start the proxy
mcp-streamablehttp-proxy python -m mcp_server_fetch
# Initialize session
SESSION_ID=$(curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05"},"id":1}' \
-i | grep -i mcp-session-id | cut -d' ' -f2 | tr -d '\r')
# List available tools
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":2}'
Docker Deployment
FROM python:3.11-slim
RUN pip install mcp-streamablehttp-proxy mcp-server-fetch
# Bind to 0.0.0.0 for container networking
CMD ["mcp-streamablehttp-proxy", "--host", "0.0.0.0", "python", "-m", "mcp_server_fetch"]
Docker Compose with Traefik
services:
mcp-fetch:
build: .
environment:
- MCP_BIND_HOST=0.0.0.0
- MCP_PORT=3000
labels:
- "traefik.enable=true"
- "traefik.http.routers.mcp-fetch.rule=Host(`mcp-fetch.example.com`)"
- "traefik.http.services.mcp-fetch.loadbalancer.server.port=3000"
- "traefik.http.routers.mcp-fetch.middlewares=mcp-auth"
- "traefik.http.middlewares.mcp-auth.forwardauth.address=http://auth:8000/verify"
Session Management
Session Lifecycle
- Creation - New session created on
initializerequest - Active - Session kept alive by requests
- Timeout - Session expires after inactivity (default: 300s)
- Cleanup - Subprocess terminated and resources freed
Session Limits
- One subprocess per session
- Sessions are isolated from each other
- No built-in session limit (manage via container resources)
Error Handling
Common Errors
| Error | Cause | Solution |
|---|---|---|
| Session not found | Invalid or expired session ID | Initialize new session |
| Request timeout | Server took >30s to respond | Check server health |
| Subprocess died | Server crashed | Check server logs |
| Invalid request | Malformed JSON-RPC | Verify request format |
Debugging
Enable debug logging:
mcp-streamablehttp-proxy --log-level debug python -m mcp_server_fetch
# Or with file logging
export LOG_FILE=/tmp/mcp-proxy.log
mcp-streamablehttp-proxy --log-level debug python -m mcp_server_fetch
Performance Considerations
- One subprocess per session - Plan resources accordingly
- 30-second request timeout - Not suitable for very long operations
- Async I/O - Handles concurrent requests within sessions
- No request queuing - Requests processed in parallel
For high-load scenarios, consider:
- Running multiple proxy instances behind a load balancer
- Adjusting session timeout based on usage patterns
- Monitoring subprocess resource usage
Security
⚠️ This proxy provides NO authentication or authorization!
Always deploy behind an authenticating reverse proxy like Traefik with:
- OAuth2/JWT authentication
- Rate limiting
- Access control
- HTTPS termination
Never expose the proxy directly to the internet!
Integration with MCP OAuth Gateway
This proxy is designed to work seamlessly with the MCP OAuth Gateway:
- Proxy exposes MCP servers as HTTP endpoints
- Traefik provides routing and authentication
- OAuth gateway handles client registration and tokens
- Clients access MCP servers with OAuth bearer tokens
Development
Running Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# Run with coverage
pytest --cov=mcp_streamablehttp_proxy tests/
Type Checking
mypy src/
Linting
ruff check src/
ruff format src/
Troubleshooting
Proxy won't start
- Verify the MCP server command is correct
- Check that the server is installed and in PATH
- Ensure port 3000 (or custom port) is available
Sessions immediately timeout
- Increase timeout with
--timeoutoption - Check if server is responding to initialize
- Verify server stdout is line-buffered JSON
Requests hang
- Enable debug logging to see communication
- Check if server is actually responding
- Verify JSON-RPC request format
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built for the Model Context Protocol
- Designed for integration with HTTP infrastructure
- Part of the MCP OAuth Gateway ecosystem
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_streamablehttp_proxy-0.2.0.tar.gz.
File metadata
- Download URL: mcp_streamablehttp_proxy-0.2.0.tar.gz
- Upload date:
- Size: 20.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20c6df747e4a859ef69435e8b880e46c6e42849e43be846220ae08bdf36ca2c4
|
|
| MD5 |
46c0c9c71cafd4ad13c4e6c86dbfa107
|
|
| BLAKE2b-256 |
92937a757c2f4703fe78901c92edb23688a326ee1fe4d9bb497742ac9c4b0335
|
File details
Details for the file mcp_streamablehttp_proxy-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_streamablehttp_proxy-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3d459e18a33935d6da533292d2e2e64c8368c493d3b50c290e50608ce1b1577
|
|
| MD5 |
2c1e0a0ba7ea70f47a6d6a5ff3f561d6
|
|
| BLAKE2b-256 |
b53a8f2e9e752fe936d3eb9d0c03237874437f974af5a0889c5e75f0de78b30e
|