A Go implementation of a proxy that connects MCP clients to remote MCP servers with OAuth support.
- Dual mode operation: Stdio (default) or HTTP/SSE server
- OAuth 2.0: Full support with PKCE, dynamic client registration, and token refresh
- Transport flexibility: HTTP and SSE with configurable fallback strategies
- Tool filtering: Block specific tools from being exposed to clients
brew install mikluko/tap/mcp-proxygo install github.com/mikluko/mcp-proxy/cmd/mcp-proxy@latestDownload from GitHub Releases.
Standard mode for MCP clients that communicate via stdio (Claude Code, Claude Desktop, Cursor, Windsurf).
claude mcp add remote-example mcp-proxy https://remote.mcp.server/sse{
"mcpServers": {
"remote-example": {
"command": "mcp-proxy",
"args": [
"https://remote.mcp.server/sse"
]
}
}
}Run as an HTTP server that accepts MCP client connections via SSE. Useful for:
- Web-based MCP clients
- Sharing a single upstream connection among multiple clients
- Environments where stdio isn't available
# Listen on port 8080
mcp-proxy https://remote.mcp.server/sse --listen :8080
# Listen on specific interface
mcp-proxy https://remote.mcp.server/sse --listen localhost:8080Clients connect via:
- SSE endpoint:
GET /sse- Establishes SSE stream for server→client messages - Message endpoint:
POST /message- Sends client→server messages
{
"mcpServers": {
"remote-example": {
"command": "mcp-proxy",
"args": [
"https://remote.mcp.server/sse",
"--header",
"Authorization:Bearer ${AUTH_TOKEN}"
],
"env": {
"AUTH_TOKEN": "your-token"
}
}
}
}| Flag | Description | Default |
|---|---|---|
--listen, -l |
Listen address for HTTP mode (e.g., :8080) | - |
--header, -H |
Custom headers (KEY:VALUE) | - |
--transport |
Upstream transport strategy (http-first, sse-first, http-only, sse-only) | http-first |
--host |
OAuth callback hostname | localhost |
--allow-http |
Allow non-HTTPS connections | false |
--log-level |
Log level (debug, info, warn, error) | info |
--enable-proxy |
Use HTTP_PROXY/HTTPS_PROXY | false |
--ignore-tool |
Ignore tools matching pattern (wildcards) | - |
--auth-timeout |
OAuth callback timeout (seconds) | 30 |
--resource |
OAuth resource parameter | - |
--static-oauth-client-metadata |
Static OAuth client metadata (JSON or @file) | - |
--static-oauth-client-info |
Static OAuth client info (JSON or @file) | - |
Controls how mcp-proxy connects to the upstream server:
http-first(default): Try HTTP, fall back to SSE on 404sse-first: Try SSE, fall back to HTTP on 405http-only/sse-only: No fallback
Use --resource to isolate OAuth sessions:
{
"mcpServers": {
"tenant1": {
"command": "mcp-proxy",
"args": [
"https://mcp.example.com/sse",
"--resource",
"https://tenant1.example.com/"
]
},
"tenant2": {
"command": "mcp-proxy",
"args": [
"https://mcp.example.com/sse",
"--resource",
"https://tenant2.example.com/"
]
}
}
}OAuth tokens and client registration are stored in:
- Linux:
~/.cache/mcp-proxy/ - macOS:
~/Library/Caches/mcp-proxy/ - Windows:
%LocalAppData%\mcp-proxy\
To clear authentication state:
rm -rf ~/.cache/mcp-proxy # Linux
rm -rf ~/Library/Caches/mcp-proxy # macOS ┌─────────────────────────────────────────┐
│ mcp-proxy │
│ │
┌──────────┐ │ ┌────────────┐ ┌────────────────┐ │ ┌──────────┐
│ Client │──────▶│ │ Downstream │──────│ Proxy │─│──────▶│ Upstream │
│ (stdio │ │ │ Transport │ │ (filtering, │ │ │ Server │
│ or SSE) │◀──────│ │ │◀─────│ modification) │◀│───────│ │
└──────────┘ │ └────────────┘ └────────────────┘ │ └──────────┘
│ stdio or HTTP or │
│ HTTP/SSE SSE │
└─────────────────────────────────────────┘
cmd/
└── mcp-proxy/ # Main CLI binary
internal/
├── auth/ # OAuth 2.0 implementation (PKCE, tokens, callback server)
├── config/ # Cross-platform cache directory management
├── proxy/ # Bidirectional JSON-RPC proxy with tool filtering
├── server/ # HTTP/SSE server for downstream client connections
├── stdio/ # Stdio transport for downstream client connections
└── transport/ # HTTP and SSE transports for upstream connections
pkg/
└── jsonrpc/ # JSON-RPC 2.0 message types
auth.Provider.Initialize()loads existing tokens or prepares for auth- On 401: start callback server, open browser to authorization URL
- Callback receives code, exchanges for tokens via PKCE
- Tokens persisted to cache dir, auto-refreshed on expiry
Releases via goreleaser + GitHub Actions. Creates:
- Multi-platform binaries (linux/darwin/windows × amd64/arm64)
- Homebrew formula in
mikluko/homebrew-tap
- geelen/mcp-remote - Original TypeScript implementation
- sparfenyuk/mcp-proxy - Python implementation
- Model Context Protocol - MCP specification