TurboMCP Server
Server framework for the Model Context Protocol. Provides the McpHandlerExt
entry points, the ServerBuilder for runtime transport selection, typed
middleware (McpMiddleware / MiddlewareStack), configuration types
(ServerConfig, ProtocolConfig, rate limits, connection limits, origin
validation), and the JSON-RPC router shared by every transport.
Table of Contents
- Overview
- Quick Start
- Server Builder
- Server Configuration
- Protocol Version Negotiation
- Middleware
- Transports
- Feature Flags
- Related Crates
Overview
turbomcp-server is a Layer 5 crate that turns any McpHandler
(implemented by the #[server] macro, CompositeHandler, or a hand-written
type) into a running MCP server. It owns:
- Entry points (
McpHandlerExt::run,run_stdio,run_http,run_tcp,run_unix,run_websocket,handle_request). - The
ServerBuilderfluent API for runtime transport and config selection. - The JSON-RPC router (
router::route_requestet al.) shared by all transports. ServerConfigand its validated builder (try_build) plusProtocolConfigfor version negotiation.- The typed
McpMiddlewaretrait andMiddlewareStack<H>composition wrapper. - Progressive disclosure (
VisibilityLayer) and server composition (CompositeHandler).
Authentication (OAuth 2.1 / JWT / API keys) lives in turbomcp-auth.
Telemetry lives in turbomcp-telemetry. Session management lives in
turbomcp-protocol. This crate does not bundle them.
Quick Start
Any type that implements McpHandler (the #[server] macro generates one for
you) gets the run* and builder() methods automatically via blanket impls.
use *;
;
async
Server Builder
ServerBuilder<H> is obtained via McpServerExt::builder() (blanket impl
on every McpHandler). The methods available on it:
| Method | Description |
|---|---|
.transport(Transport) |
Select transport (default: Transport::Stdio) |
.with_rate_limit(u32, Duration) |
Enable token-bucket rate limiting (per client) |
.with_connection_limit(usize) |
Cap concurrent connections across TCP/HTTP/WS/Unix |
.with_graceful_shutdown(Duration) |
Wait up to this duration for in-flight requests on shutdown (HTTP transport) |
.with_max_message_size(usize) |
Reject messages larger than this (default: 10 MB) |
.with_protocol(ProtocolConfig) |
Configure protocol version negotiation |
.with_allowed_origin(impl Into<String>) |
Allow a specific HTTP origin |
.with_origin_validation(OriginValidationConfig) |
Replace the full origin config |
.allow_localhost_origins(bool) |
Accept/deny localhost origins |
.allow_any_origin(bool) |
Disable origin checks entirely |
.with_config(ServerConfig) |
Apply a fully constructed ServerConfig |
.serve() |
Start the server (async, blocks until shutdown) |
.into_axum_router() |
Return an axum::Router for BYO server integration (requires http) |
.into_service() |
Return a Tower service (requires http) |
.handler() / .into_handler() |
Borrow / consume the underlying handler |
use Duration;
use *;
async
BYO server (Axum integration)
use ;
use *;
async
Server Configuration
ServerConfig is constructed through ServerConfig::builder(). Fields:
| Field | Type | Default |
|---|---|---|
protocol |
ProtocolConfig |
See Protocol Version Negotiation |
rate_limit |
Option<RateLimitConfig> |
None |
connection_limits |
ConnectionLimits |
1000 per transport |
required_capabilities |
RequiredCapabilities |
none |
max_message_size |
usize |
10 MB |
origin_validation |
OriginValidationConfig |
allow_localhost = true, no explicit origins, allow_any = false |
Use .build() for an infallible build with defaults, or .try_build() to
validate. try_build() returns ConfigValidationError when:
max_message_sizeis below 1024 bytesRateLimitConfig::max_requestsis 0RateLimitConfig::windowisDuration::ZERO- All four fields of
ConnectionLimitsare 0
use Duration;
use ;
let config = builder
.max_message_size
.rate_limit
.try_build
.expect;
Protocol Version Negotiation
ProtocolConfig controls which MCP spec versions the server accepts.
Fields: preferred_version: ProtocolVersion, supported_versions: Vec<ProtocolVersion>, allow_fallback: bool.
Default (as of v3.1): preferred_version = ProtocolVersion::LATEST,
supported_versions = ProtocolVersion::STABLE.to_vec() (all stable spec
versions), allow_fallback = false. Older clients are accepted and responses
are filtered through the appropriate version adapter.
Use ProtocolConfig::strict(version) to restore exact-match negotiation
against a single version. Use ProtocolConfig::multi_version() to construct
the default multi-version config explicitly.
use *;
use ProtocolVersion;
// Exact-match against the latest version only
Calculator.builder
.with_protocol
.serve.await?;
// Explicit multi-version (same as default)
Calculator.builder
.with_protocol
.serve.await?;
ProtocolConfig::negotiate(client_version) returns the negotiated
ProtocolVersion or None if no compatible version is found (and fallback
is disabled).
Middleware
Middleware is typed around the MCP operation set. Implement McpMiddleware
and layer it onto any McpHandler via MiddlewareStack:
use ;
use RequestContext;
use ;
use ToolResult;
use Value;
use Future;
use Pin;
;
// MiddlewareStack wraps a handler; it itself implements McpHandler,
// so it participates in the same builder / transport pipeline.
let stack = new.with_middleware;
stack.builder.serve.await?;
The trait's other hooks (on_list_tools, on_list_resources,
on_list_prompts, on_read_resource, on_get_prompt, etc.) all have
pass-through default implementations — override only the ones you need.
Transports
Runtime transport selection is done through Transport. Each variant is
gated by the matching feature flag.
| Constructor | Feature flag | Notes |
|---|---|---|
Transport::stdio() |
stdio |
Default; line-based JSON-RPC over stdin/stdout (Claude Desktop) |
Transport::http(addr) |
http |
JSON-RPC over HTTP POST (Axum) |
Transport::websocket(addr) |
websocket |
Bidirectional JSON-RPC; depends on http |
Transport::tcp(addr) |
tcp |
Line-framed JSON-RPC over TCP |
Transport::unix(path) |
unix |
Line-framed JSON-RPC over Unix domain socket |
Each McpHandler also has direct run_stdio / run_http / run_websocket
/ run_tcp / run_unix methods (feature-gated) via McpHandlerExt, plus
handle_request(Value, RequestContext) for serverless-style one-shot use.
Feature Flags
| Feature | Description | Default |
|---|---|---|
stdio |
STDIO transport | ✅ |
http |
HTTP transport (Axum) | ❌ |
websocket |
WebSocket transport (implies http) |
❌ |
tcp |
TCP transport | ❌ |
unix |
Unix domain socket transport | ❌ |
channel |
In-process channel transport | ❌ |
all-transports |
stdio + http + websocket + tcp + unix + channel |
❌ |
full |
Alias for all-transports |
❌ |
experimental-tasks |
Opt into experimental Tasks API (SEP-1686) | ❌ |
Related Crates
- turbomcp — Main SDK that re-exports this crate's public API
- turbomcp-core —
McpHandler,McpError, JSON-RPC primitives - turbomcp-protocol — Protocol implementation, session management
- turbomcp-transport — Transport re-export hub
- turbomcp-auth — OAuth 2.1 / JWT / API keys (optional)
- turbomcp-telemetry — OpenTelemetry / Prometheus (optional)
License
Licensed under the MIT License.
Part of the TurboMCP Rust SDK for the Model Context Protocol.