Skip to main content

rmcp_server_kit/
lib.rs

1#![forbid(unsafe_code)]
2#![cfg_attr(
3    test,
4    allow(
5        clippy::unwrap_used,
6        clippy::expect_used,
7        clippy::panic,
8        clippy::panic_in_result_fn,
9        clippy::indexing_slicing,
10        clippy::unwrap_in_result,
11        clippy::print_stdout,
12        clippy::print_stderr,
13        reason = "test-only relaxations; production code uses ? and tracing"
14    )
15)]
16
17//! `rmcp-server-kit` - production-grade reusable framework for building
18//! [Model Context Protocol](https://modelcontextprotocol.io/) servers in Rust.
19//!
20//! Application crates depend on `rmcp-server-kit` and supply their own
21//! [`rmcp::handler::server::ServerHandler`] implementation; the kit provides
22//! transport, security, and observability around it.
23//!
24//! # What you get
25//!
26//! - **Streamable HTTP transport** with TLS / mTLS termination, configurable
27//!   keep-alive and session idle timeouts, CORS, compression, body-size and
28//!   concurrency caps, and graceful shutdown on `SIGINT`/`SIGTERM`.
29//! - **Authentication**: API keys (Argon2-hashed, constant-time compared),
30//!   mTLS client certificates with optional CDP-driven CRL revocation, and -
31//!   under the `oauth` feature - OAuth 2.1 Bearer JWT validation against a
32//!   cached JWKS endpoint.
33//! - **RBAC** with per-tool argument allow-lists and per-IP per-tool rate
34//!   limiting; policies and API keys are hot-reloadable at runtime via
35//!   [`transport::ReloadHandle`] (lock-free [`arc_swap`] swaps).
36//! - **Observability**: `tracing` with JSON or pretty formats, optional audit
37//!   file sink, `/healthz` + `/readyz` probes, `/version`, `/admin/*`
38//!   diagnostics, and - under the `metrics` feature - a Prometheus
39//!   `/metrics` endpoint on a separate listener.
40//! - **OWASP-grade defaults**: HSTS, CSP, `X-Frame-Options`, MCP `Origin`
41//!   validation, and per-hop SSRF guards on outbound HTTP.
42//!
43//! # Quick start
44//!
45//! ```no_run
46//! use rmcp::{
47//!     handler::server::ServerHandler,
48//!     model::{ServerCapabilities, ServerConfig},
49//! };
50//! use rmcp_server_kit::{
51//!     config::ObservabilityConfig,
52//!     observability::init_tracing_from_config_strict,
53//!     transport::{McpServerConfig, serve},
54//! };
55//!
56//! #[derive(Clone)]
57//! struct MyHandler;
58//!
59//! impl ServerHandler for MyHandler {
60//!     fn get_info(&self) -> ServerConfig {
61//!         ServerConfig::new(ServerCapabilities::builder().enable_tools().build())
62//!     }
63//! }
64//!
65//! #[tokio::main]
66//! async fn main() -> rmcp_server_kit::Result<()> {
67//!     let mut observability = ObservabilityConfig::default();
68//!     observability.log_level = "info".into();
69//!     let _tracing_guard = init_tracing_from_config_strict(&observability)?;
70//!
71//!     let config = McpServerConfig::new(
72//!         "127.0.0.1:8080",
73//!         "my-mcp-server",
74//!         env!("CARGO_PKG_VERSION"),
75//!     );
76//!
77//!     serve(config.validate()?, || MyHandler).await
78//! }
79//! ```
80//!
81//! See [`examples/`](https://github.com/andrico21/rmcp-server-kit/tree/main/examples)
82//! for richer setups (API-key + RBAC, OAuth resource server) and
83//! [`docs/GUIDE.md`](https://github.com/andrico21/rmcp-server-kit/blob/main/docs/GUIDE.md)
84//! for the full TOML configuration reference.
85//!
86//! # Cargo features
87//!
88//! All features are **off by default**:
89//!
90//! - `oauth` - OAuth 2.1 Bearer JWT validation, JWKS cache, and optional
91//!   OAuth proxy endpoints. Pulls in [`jsonwebtoken`] and [`urlencoding`].
92//!   Required to use the [`oauth`] module.
93//! - `oauth-mtls-client` - RFC 8705 §2 mTLS client authentication for the
94//!   OAuth token-exchange endpoint. Implies `oauth`. Without this feature,
95//!   [`oauth::OAuthConfig::validate`] rejects any configuration that sets
96//!   [`oauth::TokenExchangeConfig::client_cert`].
97//! - `metrics` - Prometheus registry and `/metrics` listener. Pulls in
98//!   the [`prometheus`] crate. Required to use the [`metrics`] module.
99//! - `test-helpers` - exposes test-only helpers from [`mtls_revocation`] and,
100//!   when `oauth` is also enabled, [`oauth`], for downstream integration tests.
101//!   **Not part of the stable API surface** - no semver guarantees across minor
102//!   releases. **never enable in a production build:** some helpers deliberately
103//!   bypass SSRF screening, the JWKS refresh cooldown, the CDP discovery rate
104//!   limiter, and CRL verifier publication.
105//!
106//! # ⚠️ stdio transport is unauthenticated
107//!
108//! [`transport::serve_stdio`] runs MCP over the process's stdin/stdout for
109//! local subprocess scenarios (desktop clients, IDE integrations). It
110//! **bypasses authentication, RBAC, TLS, Origin validation, and rate
111//! limiting** - the surrounding OS process boundary is the only trust
112//! boundary. Never expose `serve_stdio` to untrusted callers; for any
113//! network-reachable deployment use [`transport::serve`] over HTTPS instead.
114
115/// Reusable server and observability configuration primitives.
116pub mod config;
117/// Process-global switches controlling plaintext-vs-redacted diagnostics.
118pub mod diagnostics;
119/// Generic error type and `Result` alias for server-side code.
120pub mod error;
121/// Tracing / JSON logs / audit file initialization.
122pub mod observability;
123/// Streamable HTTP transport and server entry points.
124pub mod transport;
125
126/// Authentication state (API keys, mTLS, OAuth JWT) and middleware.
127pub mod auth;
128/// Role-based access control policy engine and middleware.
129pub mod rbac;
130
131/// Memory-bounded keyed rate limiter (LRU + idle eviction).
132pub mod bounded_limiter;
133
134// Module-level docs live in cancel.rs (`//!`); an outer doc here would
135// concatenate into an over-long first rustdoc paragraph.
136pub mod cancel;
137
138/// Admin diagnostic endpoints (status, auth keys metadata, counters, RBAC).
139pub mod admin;
140
141/// Re-exports for the [`secrecy`] crate's secret-wrapper types.
142pub mod secret;
143
144pub(crate) mod forwarded;
145pub(crate) mod rbac_context;
146pub(crate) mod session_binding;
147pub(crate) mod ssrf;
148pub(crate) mod ssrf_resolver;
149pub(crate) mod task_binding;
150
151/// Opt-in tool-call hooks (before/after) and result-size cap.
152pub mod tool_hooks;
153
154#[cfg(feature = "oauth")]
155/// OAuth 2.1 JWKS cache, token validation, and token exchange helpers.
156pub mod oauth;
157
158#[cfg(feature = "metrics")]
159/// Prometheus metrics registry shared across server components.
160pub mod metrics;
161
162/// CDP-driven CRL revocation support for mTLS.
163pub mod mtls_revocation;
164
165// Explicit re-exports rather than a glob. A `pub use crate::error::*;` would
166// silently promote every future `pub` item added to `error.rs` into the crate
167// root's stable API surface -- `cargo-semver-checks` flags removals, not
168// accidental additions, so the mistake would ship unnoticed. Listing the three
169// items keeps the root surface a deliberate choice.
170#[allow(
171    deprecated,
172    reason = "`McpxError` is itself deprecated but must stay re-exported at the \
173              crate root until its removal in the next major; re-exporting it \
174              is not itself a use of the deprecated path"
175)]
176pub use crate::error::McpxError;
177pub use crate::error::{Result, RmcpServerKitError};