MCP HTTP Proxy
Expose any stdio-based MCP server (like @browsermcp/mcp) to the internet via HTTP/SSE transport. Perfect for remote agents that need to access MCP tools over a network.
Features
- ๐ Standard MCP SSE Transport - Follows MCP HTTP transport specification
- ๐ API Key Authentication - Secure access with Bearer token
- ๐ Multiple Exposure Options - Tailscale, ngrok, Cloudflare Tunnel
- ๐ Session Management - Multiple concurrent sessions supported
- ๐ฆ Works with any MCP server - Defaults to
@browsermcp/mcp
Quick Start
1. Install Dependencies
npm install
2. Configure (Optional)
cp .env.example .env
# Edit .env to set your API key
Generate a secure API key:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
3. Build and Run
npm run build
npm start
Or for development:
npm run dev
API Endpoints (Standard MCP SSE Transport)
| Endpoint | Method | Description |
|---|---|---|
/sse |
GET | Establish SSE connection (returns endpoint URL) |
/message?sessionId=xxx |
POST | Send JSON-RPC messages |
/health |
GET | Health check (no auth required) |
/sessions |
GET | List active sessions (auth required) |
Exposing to the Internet
Option 1: Tailscale (Recommended for Private Access)
Tailscale provides secure, private access without exposing to the public internet.
# Install Tailscale if not already installed
# Then serve via Tailscale
tailscale serve --bg --http 3000
Or use your Tailscale IP directly:
tailscale status # Find your Tailscale IP
Your MCP server will be available at:
https://your-machine.tailnet-name.ts.net(via serve)http://your-tailscale-ip:3000(direct IP)
Use from your agent:
{
"mcpServers": {
"browser-remote": {
"url": "http://your-tailscale-ip:3000/sse",
"headers": {
"Authorization": "Bearer your-api-key"
}
}
}
}
Option 2: ngrok (Public URL)
# Install ngrok if not already installed
ngrok http 3000
ngrok will provide a public URL like https://abc123.ngrok.io.
Option 3: Cloudflare Tunnel
# Install cloudflared if not already installed
cloudflared tunnel --url http://localhost:3000
How the SSE Transport Works
- Client GETs
/sse- Server creates session, sendsendpointevent with message URL - Client POSTs to
/message?sessionId=xxx- Server forwards JSON-RPC to MCP process - Server streams responses - MCP responses sent as SSE
messageevents
Usage Examples
Test Health Check
curl http://localhost:3000/health
Response:
{
"status": "healthy",
"sessions": 0,
"uptime": 10.5,
"transport": "sse",
"endpoints": {
"sse": "/sse (GET - establishes SSE connection)",
"message": "/message?sessionId=xxx (POST - send JSON-RPC messages)"
}
}
Connect via SSE (JavaScript)
const eventSource = new EventSource('http://localhost:3000/sse', {
headers: { 'Authorization': 'Bearer your-api-key' }
});
eventSource.addEventListener('endpoint', (e) => {
console.log('Message endpoint:', e.data);
// e.data = "/message?sessionId=xxx"
});
eventSource.addEventListener('message', (e) => {
console.log('MCP response:', JSON.parse(e.data));
});
Send MCP Request
curl -X POST "http://localhost:3000/message?sessionId=your-session-id" \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Configuration
| Environment Variable | Description | Default |
|---|---|---|
PORT |
Server port | 3000 |
HOST |
Host to bind to | 0.0.0.0 |
MCP_API_KEY |
API key for authentication | (none) |
MCP_COMMAND |
Command to run MCP server | npx |
MCP_ARGS |
JSON array of arguments | ["@browsermcp/mcp@latest"] |
Using Different MCP Servers
You can use this proxy with any stdio-based MCP server:
# Example: Use a custom MCP server
MCP_COMMAND=node
MCP_ARGS=["/path/to/your/mcp-server/dist/index.js"]
# Example: Use Python MCP server
MCP_COMMAND=python
MCP_ARGS=["-m", "your_mcp_server"]
Security Notes
- Always use API key authentication when exposing to the internet
- Use HTTPS (Tailscale, ngrok, and Cloudflare all provide this)
- Tailscale is recommended for private access within your tailnet
- Rotate API keys periodically
- Monitor sessions via
/sessionsendpoint
Troubleshooting
MCP Server Not Starting
Check the console logs for errors. The MCP server stderr is forwarded to the proxy's console.
Connection Refused
- Ensure server is running:
curl http://localhost:3000/health - Check Tailscale connectivity:
tailscale status
Authentication Failed
- Check the API key in
.envmatches your request header - Ensure "Bearer " prefix is included in Authorization header
SSE Not Working
- Ensure you're connecting to
/sseendpoint (not just base URL) - Check that Authorization header is sent with GET request too
License
MIT