Skip to main content

mcp_proxy/
lib.rs

1//! Config-driven MCP reverse proxy with auth, resilience middleware, and observability.
2//!
3//! Aggregates multiple MCP backends behind a single HTTP endpoint with namespace
4//! isolation, per-backend middleware, and a comprehensive admin API. Built on
5//! [tower-mcp](https://docs.rs/tower-mcp) and the [tower](https://docs.rs/tower) ecosystem.
6//!
7//! # Quick Start
8//!
9//! ## From a config file
10//!
11//! ```rust,no_run
12//! use mcp_proxy::{Proxy, ProxyConfig};
13//!
14//! # async fn example() -> anyhow::Result<()> {
15//! let config = ProxyConfig::load("proxy.toml".as_ref())?;
16//! let proxy = Proxy::from_config(config).await?;
17//! proxy.serve().await?;
18//! # Ok(())
19//! # }
20//! ```
21//!
22//! ## Programmatic builder
23//!
24//! ```rust,no_run
25//! use mcp_proxy::ProxyBuilder;
26//!
27//! # async fn example() -> anyhow::Result<()> {
28//! let proxy = ProxyBuilder::new("my-proxy")
29//!     .listen("0.0.0.0", 9090)
30//!     .http_backend("api", "http://api:8080")
31//!     .timeout(30)
32//!     .rate_limit(100, 1)
33//!     .stdio_backend("files", "npx", &["-y", "@mcp/server-files"])
34//!     .build()
35//!     .await?;
36//!
37//! proxy.serve().await?;
38//! # Ok(())
39//! # }
40//! ```
41//!
42//! ## Embed in an existing axum app
43//!
44//! ```rust,no_run
45//! use mcp_proxy::{Proxy, ProxyConfig};
46//!
47//! # async fn example() -> anyhow::Result<()> {
48//! let config = ProxyConfig::load("proxy.toml".as_ref())?;
49//! let proxy = Proxy::from_config(config).await?;
50//! let (router, session_handle) = proxy.into_router();
51//! // Mount `router` in your axum app
52//! # Ok(())
53//! # }
54//! ```
55//!
56//! # Backend Transports
57//!
58//! | Transport | Config | Use Case |
59//! |-----------|--------|----------|
60//! | `stdio` | `command`, `args`, `env` | Local subprocess (npx, python, etc.) |
61//! | `http` | `url`, `bearer_token`, `headers` | Remote HTTP+SSE MCP server |
62//! | `websocket` | `url`, `bearer_token`, `headers` | Remote WebSocket MCP server |
63//!
64//! Backends are namespaced: a backend named `"files"` exposes tools as
65//! `files/read_file`, `files/write_file`, etc.
66//!
67//! # Per-Backend Middleware
68//!
69//! Each backend can independently configure:
70//!
71//! - **Timeout** -- per-request deadline
72//! - **Circuit breaker** -- failure-rate based with observable state handles
73//! - **Rate limit** -- request volume caps
74//! - **Retry** -- exponential backoff with budget control
75//! - **Hedging** -- parallel requests for tail latency reduction
76//! - **Outlier detection** -- passive health tracking with ejection
77//! - **Response caching** -- per-backend TTL with memory, Redis, or SQLite backends
78//! - **Argument injection** -- merge default args into tool calls
79//! - **Parameter overrides** -- hide or rename tool parameters
80//! - **Capability filtering** -- allowlist/denylist tools, resources, prompts
81//!   (glob patterns and `re:` regex support)
82//! - **Annotation filtering** -- hide destructive tools, read-only-only mode
83//!
84//! # Traffic Routing
85//!
86//! - **Failover** -- N-way priority chains with automatic fallback
87//! - **Canary routing** -- weight-based traffic splitting
88//! - **Traffic mirroring** -- fire-and-forget shadow traffic
89//! - **Composite tools** -- fan-out a single call to multiple backends
90//! - **Tool aliasing** -- rename tools across backends
91//!
92//! # Authentication
93//!
94//! Three auth modes, configured via `[auth]`:
95//!
96//! - **Bearer tokens** -- simple static tokens with optional per-token tool scoping
97//! - **JWT/JWKS** -- validate JWTs via remote JWKS endpoint with RBAC role mapping
98//! - **OAuth 2.1** -- auto-discovery (RFC 8414), token introspection (RFC 7662),
99//!   JWT+introspection fallback
100//!
101//! # Admin API
102//!
103//! REST API at `/admin/` for monitoring and management:
104//!
105//! - Backend health, history, and circuit breaker states
106//! - Session listing and termination
107//! - Cache stats and clearing
108//! - Config viewing, validation, and updates
109//! - Prometheus metrics and OpenAPI spec
110//! - Optional bearer token auth (`security.admin_token`)
111//!
112//! # Tool Discovery
113//!
114//! When `tool_discovery = true`, BM25 full-text search indexes all backend tools
115//! and exposes `proxy/search_tools`, `proxy/get_tool`, `proxy/similar_tools`, and
116//! `proxy/tool_categories` for finding tools across large deployments.
117//!
118//! Set `tool_exposure = "search"` to hide individual tools from listing and expose
119//! only meta-tools, scaling to hundreds of backends. Search for a tool, pass its
120//! returned ID to `proxy/get_tool` for the complete description and input schema,
121//! then invoke it through `proxy/call_tool`.
122//!
123//! # Agent Skills
124//!
125//! MCP prompts following the [agentskills.io](https://agentskills.io) specification
126//! for agent-assisted proxy management: setup, auth configuration, resilience tuning,
127//! config validation, diagnostics, and status reporting.
128//!
129//! # Config Formats
130//!
131//! - **TOML** (default): `proxy.toml`
132//! - **YAML** (`yaml` feature): `proxy.yaml` / `proxy.yml`
133//! - **`.mcp.json`**: `mcp-proxy --from-mcp-json .mcp.json` for zero-config mode
134//!
135//! # Hot Reload
136//!
137//! Enable `hot_reload = true` to watch the config file. Backends are added,
138//! removed, or replaced dynamically without restart. Discovery indexes are
139//! automatically re-indexed.
140//!
141//! # Feature Flags
142//!
143//! | Feature | Default | Description |
144//! |---------|---------|-------------|
145//! | `otel` | Yes | OpenTelemetry tracing export |
146//! | `metrics` | Yes | Prometheus metrics at `/admin/metrics` |
147//! | `oauth` | Yes | JWT/JWKS auth, OAuth 2.1, bearer scoping, RBAC |
148//! | `openapi` | Yes | OpenAPI spec at `/admin/openapi.json` |
149//! | `websocket` | Yes | WebSocket backend transport |
150//! | `discovery` | Yes | BM25 tool discovery via jpx-engine |
151//! | `yaml` | Yes | YAML config format support |
152//! | `skills` | Yes | agentskills.io management prompts |
153//! | `redis-cache` | No | Redis cache backend |
154//! | `sqlite-cache` | No | SQLite cache backend |
155//! | `protocol-2026-07-28` | No | Released MCP 2026-07-28 protocol support |
156//!
157//! Minimal build: `cargo install mcp-proxy --no-default-features`
158//!
159//! # Performance
160//!
161//! Middleware stack overhead is sub-microsecond (~115ns per request). Cache hits
162//! are 33x faster than backend round-trips. See `benches/proxy_overhead.rs`.
163
164#![warn(missing_docs)]
165
166pub mod access_log;
167pub mod admin;
168pub mod admin_tools;
169pub mod alias;
170#[cfg(feature = "oauth")]
171pub mod bearer_scope;
172pub mod builder;
173pub mod cache;
174pub mod canary;
175pub mod coalesce;
176pub mod composite;
177pub mod config;
178#[cfg(feature = "discovery")]
179pub mod discovery;
180pub mod failover;
181pub mod filter;
182pub mod inject;
183#[cfg(feature = "oauth")]
184pub mod introspection;
185pub mod mcp_json;
186#[cfg(feature = "metrics")]
187pub mod metrics;
188pub mod mirror;
189pub mod outlier;
190pub mod param_override;
191#[cfg(feature = "oauth")]
192pub mod rbac;
193pub mod reload;
194pub mod retry;
195#[cfg(feature = "skills")]
196pub mod skills;
197#[cfg(feature = "oauth")]
198pub mod token;
199pub mod validation;
200#[cfg(feature = "websocket")]
201pub mod ws_transport;
202
203#[cfg(test)]
204mod test_util;
205
206mod proxy;
207
208pub use builder::ProxyBuilder;
209pub use config::ProxyConfig;
210pub use proxy::Proxy;