mcp-proxy
A config-driven Model Context Protocol (MCP) reverse proxy built in Rust. Aggregates multiple MCP backends behind a single endpoint with per-backend middleware, authentication, and observability.
Built on tower-mcp and the tower middleware ecosystem.
Features
Proxy
- Multi-backend proxy -- connect stdio and HTTP MCP servers behind one endpoint
- Capability filtering -- allow/deny lists for tools, resources, and prompts per backend
- Tool aliasing -- rename tools exposed by backends
- Argument injection -- merge default or per-tool arguments into tool calls
- Hot reload -- watch config file and add new backends without restart
- Library mode -- embed the proxy in your own Rust application
Resilience
- Timeout -- per-backend request timeouts
- Rate limiting -- per-backend request rate limits
- Concurrency limiting -- per-backend max concurrent requests
- Circuit breaker -- trip open on failure rate threshold
- Retry -- automatic retries with exponential backoff and optional budget
- Request hedging -- parallel redundant requests to reduce tail latency
- Outlier detection -- passive health checks that eject unhealthy backends
Traffic Management
- Traffic mirroring -- shadow traffic to a canary backend (fire-and-forget)
- Response caching -- per-backend TTL-based caching for tool calls and resource reads
- Request coalescing -- deduplicate identical concurrent requests
Security
- Bearer token auth -- static token validation
- JWT/JWKS auth -- token verification with RBAC (role-based access control)
- Token passthrough -- forward client auth tokens to backends
- Request validation -- argument size limits
Observability
- Prometheus metrics -- request counts and duration histograms
- OpenTelemetry tracing -- distributed trace export via OTLP
- Audit logging -- structured logging of all MCP requests
- Admin API -- health checks, backend status, cache stats
- Admin MCP tools -- introspection tools under
proxy/namespace
Quick Start
Create a proxy.toml:
[]
= "my-proxy"
= "/"
[]
= "127.0.0.1"
= 8080
[[]]
= "files"
= "stdio"
= "npx"
= ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
Run:
All tools from the filesystem server are now available under the files/ namespace at http://127.0.0.1:8080/mcp.
Configuration
See config.example.toml for the full configuration reference with all options documented.
Per-backend middleware
[[]]
= "github"
= "stdio"
= "npx"
= ["-y", "@modelcontextprotocol/server-github"]
[]
= "${GITHUB_TOKEN}"
[]
= 60
[]
= 30
= 1
[]
= 0.5
= 5
= 30
[]
= 3
= 100
= 5000
= 20.0
[]
= 200
= 1
[]
= 5
= 30
= 50
[]
= 60
= 300
Argument injection
[[]]
= "db"
= "http"
= "http://db.internal:8080"
# Inject into all tool calls for this backend
[]
= 30
# Inject into a specific tool (overrides default_args for matching keys)
[[]]
= "query"
= { = true, = 1000 }
# Force overwrite existing arguments
[[]]
= "dangerous_op"
= { = true }
= true
Traffic mirroring
[[]]
= "api"
= "http"
= "http://api-v1:8080"
[[]]
= "api-v2"
= "http"
= "http://api-v2:8080"
= "api"
= 10
Authentication
# Bearer token
[]
= "bearer"
= ["my-secret-token"]
# Or JWT with RBAC
[]
= "jwt"
= "https://auth.example.com"
= "mcp-proxy"
= "https://auth.example.com/.well-known/jwks.json"
[[]]
= "reader"
= ["files/read_file", "files/list_directory"]
[[]]
= "admin"
[]
= "scope"
= { = "reader", = "admin" }
Capability filtering
[[]]
= "files"
= "stdio"
= "npx"
= ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
# Only expose these tools
= ["read_file", "list_directory"]
# Or hide specific tools
# hide_tools = ["write_file", "delete_file"]
Library Usage
Add to your Cargo.toml:
[]
= "0.1"
use ;
let config = load?;
let proxy = from_config.await?;
// Embed in an existing axum app
let = proxy.into_router;
// Or serve standalone
proxy.serve.await?;
Admin API
HTTP endpoints:
GET /admin/backends-- list backends with health status and proxy infoGET /admin/health-- health check summary (healthy/degraded)GET /admin/metrics-- Prometheus metricsGET /admin/cache/stats-- per-backend cache hit/miss ratesPOST /admin/cache/clear-- clear all caches
MCP tools (under proxy/ namespace):
proxy/list_backends-- list backends with health statusproxy/health_check-- cached health check resultsproxy/session_count-- active session countproxy/add_backend-- dynamically add an HTTP backendproxy/config-- dump current config
Architecture
Client
|
v
[Auth] -> [Audit] -> [Metrics] -> [Token Passthrough] -> [RBAC]
-> [Alias] -> [Filter] -> [Validation] -> [Coalesce] -> [Cache]
-> [Mirror] -> [Inject Args]
-> McpProxy
|
v (per-backend)
[Retry] -> [Hedge] -> [Concurrency] -> [Rate Limit]
-> [Timeout] -> [Circuit Breaker] -> [Outlier Detection]
-> Backend
Global middleware wraps the entire proxy. Per-backend middleware is applied individually to each backend connection. All middleware is built with tower Service layers.
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.