Skip to main content

ServerConfig

Struct ServerConfig 

Source
#[non_exhaustive]
pub struct ServerConfig {
Show 35 fields pub listen_addr: String, pub listen_port: u16, pub tls_cert_path: Option<PathBuf>, pub tls_key_path: Option<PathBuf>, pub tls_handshake_timeout: String, pub max_concurrent_tls_handshakes: usize, pub shutdown_timeout: String, pub request_timeout: String, pub max_request_body: usize, pub allowed_origins: Vec<String>, pub stdio_enabled: bool, pub tool_rate_limit: Option<u32>, pub tool_rate_limit_burst: Option<u32>, pub extra_route_rate_limit: Option<u32>, pub extra_route_rate_limit_burst: Option<u32>, pub extra_route_rate_limit_exempt_paths: Vec<String>, pub key_eviction_policy: KeyEvictionPolicy, pub trusted_proxies: Vec<String>, pub trusted_forwarder_max_entries: usize, pub forwarded_header: Option<ForwardedHeaderMode>, pub session_idle_timeout: String, pub session_binding: bool, pub session_binding_secret: Option<SecretString>, pub task_binding: bool, pub sse_keep_alive: String, pub public_url: Option<String>, pub compression_enabled: bool, pub compression_min_size: u16, pub max_concurrent_requests: Option<usize>, pub admin_enabled: bool, pub admin_role: String, pub auth: Option<AuthConfig>, pub tool_list_filtering: bool, pub expose_build_metadata: bool, pub security_headers: SecurityHeadersConfig,
}
Expand description

Server listener configuration (reusable across MCP projects).

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§listen_addr: String

Listen address (IP or hostname). Default: 127.0.0.1.

§listen_port: u16

Listen TCP port. Default: 8443.

§tls_cert_path: Option<PathBuf>

Path to the TLS certificate (PEM). Required for TLS/mTLS.

§tls_key_path: Option<PathBuf>

Path to the TLS private key (PEM). Required for TLS/mTLS.

§tls_handshake_timeout: String

Per-handshake deadline on the TLS accept path, parsed via humantime. Idle or slow-loris connections are dropped once it elapses. Startup-only (not hot-reloadable); ignored unless TLS is configured. Default: 10s.

§max_concurrent_tls_handshakes: usize

Cap on concurrently in-flight TLS handshakes. At saturation the acceptor stops pulling new connections from the kernel backlog (backpressure). Startup-only (not hot-reloadable); ignored unless TLS is configured. Default: 256.

§shutdown_timeout: String

Graceful shutdown timeout, parsed via humantime.

§request_timeout: String

Per-request timeout, parsed via humantime.

§max_request_body: usize

Maximum request body size in bytes. Default: 1 MiB.

§allowed_origins: Vec<String>

Allowed Origin header values for DNS rebinding protection (MCP spec). Requests with an Origin not in this list are rejected with 403. Requests without an Origin header are always allowed (non-browser).

§stdio_enabled: bool

Allow the stdio transport subcommand. Disabled by default because stdio mode bypasses auth, RBAC, TLS, and Origin validation.

§tool_rate_limit: Option<u32>

Maximum tool invocations per source IP per minute. When set, enforced by the RBAC middleware on tools/call requests. Protects against both abuse and runaway LLM loops.

§tool_rate_limit_burst: Option<u32>

Burst capacity for the tool rate limiter (bucket size; sustained rate stays tool_rate_limit). Requires tool_rate_limit; must be greater than zero.

§extra_route_rate_limit: Option<u32>

Maximum requests per source IP per minute on application routes merged via McpServerConfig::with_extra_router (which bypass auth/RBAC). Opt-in; must be greater than zero when set. Keyed by the direct socket peer - no X-Forwarded-For interpretation. Startup-only.

§extra_route_rate_limit_burst: Option<u32>

Burst capacity for the extra-route rate limiter (bucket size; sustained rate stays extra_route_rate_limit). Requires extra_route_rate_limit; must be greater than zero.

§extra_route_rate_limit_exempt_paths: Vec<String>

Exact-match request paths exempt from the extra-route rate limiter. Raw string comparison against the request path - no globs, no normalization; fail-closed (anything not listed stays limited). Requires extra_route_rate_limit; entries must be non-empty and start with /. Startup-only.

§key_eviction_policy: KeyEvictionPolicy

Full-table policy for per-IP rate limiters. Default: evict_lru.

§trusted_proxies: Vec<String>

Trusted reverse-proxy networks (CIDRs or bare IPs) for trusted-forwarder mode. Empty (default) = off. When the direct peer is inside one of these networks, the client IP is resolved from the forwarding header (rightmost-untrusted walk) and all per-IP rate limiters key by it. Startup-only.

§trusted_forwarder_max_entries: usize

Maximum forwarding-chain entries scanned per request in trusted-forwarder mode. Longer chains are treated as a header bomb and resolution falls back to the direct peer. Default 16, valid range 1..=64. Startup-only.

§forwarded_header: Option<ForwardedHeaderMode>

Which forwarding header trusted-forwarder mode reads: "x-forwarded-for" (default when unset) or "forwarded" (RFC 7239). Requires trusted_proxies to be nonempty.

§session_idle_timeout: String

Idle timeout for MCP sessions. Sessions with no activity for this duration are closed automatically. Default: 20 minutes.

§session_binding: bool

Bind MCP session IDs to the authenticated identity using a stateless signed wrapper. Default: true. Disabling reinstates CWE-384 risk.

§session_binding_secret: Option<SecretString>

Shared HMAC secret used for session binding across server instances.

Necessary but not sufficient for cross-instance session continuity: this makes a session token minted by one instance verifiable by another. The session itself lives in rmcp’s session store, so continuity also requires a shared store via crate::transport::McpServerConfig::with_session_store. Without one, a session does not survive a restart or a hop to another instance even when this secret is shared.

Also used by Self::task_binding; the two are domain-separated.

§task_binding: bool

Bind MCP task IDs (SEP-2663) to the authenticated identity that created them, preventing cross-identity tasks/get, tasks/update, and tasks/cancel. Default: false, because enabling it changes the wire format of taskId values.

This is an opt-in compatibility control, not a staged default-flip promise.

§sse_keep_alive: String

Interval for SSE keep-alive pings sent to the client. Prevents proxies and load balancers from killing idle connections. Default: 15 seconds.

§public_url: Option<String>

Externally reachable base URL (e.g. https://mcp.example.com). When set, OAuth metadata endpoints advertise this URL instead of the listen address. Required when the server binds to 0.0.0.0 behind a reverse proxy or inside a container.

§compression_enabled: bool

Enable gzip/br response compression for MCP responses.

§compression_min_size: u16

Minimum response size (bytes) before compression kicks in. Only used when compression_enabled is true. Default: 1024.

§max_concurrent_requests: Option<usize>

Global cap on in-flight HTTP requests. When reached, excess requests receive 503 Service Unavailable (via load shedding).

§admin_enabled: bool

Enable /admin/* diagnostic endpoints.

§admin_role: String

RBAC role required to access admin endpoints.

§auth: Option<AuthConfig>

Authentication configuration (API keys, mTLS, OAuth).

§tool_list_filtering: bool

Filter tools/list through RBAC visibility when RBAC is enabled. Default: true.

§expose_build_metadata: bool

Expose build metadata on the unauthenticated /version endpoint.

§security_headers: SecurityHeadersConfig

Per-header OWASP security-header overrides.

Implementations§

Source§

impl ServerConfig

Source

pub fn apply_env_overrides( &mut self, ) -> Result<Vec<EnvOverride>, RmcpServerKitError>

Applies RMCP_SERVER_KIT__SERVER__* environment overrides onto this config.

Includes the nested OAuth variables under RMCP_SERVER_KIT__SERVER__AUTH__OAUTH__*. This method is opt-in: constructors, validators, and server startup do not call it.

§Errors

Returns RmcpServerKitError::Config when an override cannot be parsed, when an OAuth override lacks a declared [server.auth.oauth] parent, or when an OAuth override is used in a build without the oauth feature.

§Examples

The full config-file pipeline lives in examples/config_file_server.rs.

use rmcp_server_kit::config::ServerConfig;

let mut server = ServerConfig::default();
// Do not set process env in doctests: rustdoc examples share a process.
let report = server.apply_env_overrides()?;
let _applied_fields: Vec<&str> = report
    .iter()
    .map(|entry| entry.target_field.as_str())
    .collect();
Source

pub fn apply_to_mcp_config( &self, base: McpServerConfig, ) -> Result<McpServerConfig, RmcpServerKitError>

Apply this TOML server schema to a programmatic MCP server base.

Replacement semantics are used for every bridgeable transport field: None and false values in TOML clear the corresponding value from base. Only runtime-only fields such as name, version, RBAC, readiness callbacks, extra routers, reload callbacks, and metrics listener settings are preserved from base.

Chain application-code builder overrides after this method when those overrides should take precedence over TOML. This method is side-effect free and never reads process environment variables.

§Errors

Returns RmcpServerKitError::Config when a duration string cannot be parsed.

§Examples

The full config-file pipeline lives in examples/config_file_server.rs.

use rmcp_server_kit::config::{ServerConfig, validate_server_config};
use rmcp_server_kit::transport::McpServerConfig;

let server = ServerConfig::default();
validate_server_config(&server)?;
let config = server.apply_to_mcp_config(McpServerConfig::new(
    "placeholder:0",
    "my-server",
    "0.1.0",
))?;
let _validated = config.validate()?;

Trait Implementations§

Source§

impl Debug for ServerConfig

Hand-written so tls_key_path never reaches a log.

SECURITY: a derived Debug renders the private-key path verbatim, and the whole config is easy to log accidentally (tracing::debug!(?config), a panic message, an error chain). Presence is still reported so diagnostics remain useful; only the location is withheld.

Every field is listed deliberately rather than using finish_non_exhaustive, and server_config_debug_lists_every_field fails if a field is added here without being rendered.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ServerConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for ServerConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more