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
- Visibility
- 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).
Visibility
VisibilityLayer wraps any McpHandler and filters tools/list,
resources/list, resources/templates/list, and prompts/list. Disabled
tools, resources, and prompts are also rejected on call/read/get paths as not
found; hidden components stay callable but are omitted from list responses.
Use it for both human UX and LLM-facing AX: expose only the tools relevant to a deployment profile, disable unsafe operations, and keep client context focused.
use ;
let config = new
.with_allowed_tools
.with_disabled_tools
.with_hidden_tools
.require_read_only_tools;
let server = new.with_visibility_config;
server.builder.serve.await?;
For config files, map user choices into VisibilityConfig: exact tool
allowlists reduce context load, disabled tools remove risky operations, hidden
tools stay callable without consuming tools/list context, and
require_read_only_tools() only exposes tools annotated with readOnlyHint: true.
Direct call/read/get authorization is registry-backed. The registry is populated
from list responses and lazily initialized on first direct use, so dispatch does
not re-enumerate components on every request. Dynamic servers that add or remove
advertised components at runtime can call refresh_component_registry() or
clear_component_registry() on the layer.
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.