A Model Context Protocol (MCP) implementation for Rust built on Tower.
An MCP server is a tower::Service, so standard tower middleware (tracing, metrics,
timeouts, rate limiting, auth) composes with .layer() on the whole server or on an
individual tool. The same router serves over any transport, and the HTTP and WebSocket
transports are axum routers, so they drop into an existing axum application.
The reference documentation lives on docs.rs; this README covers installation and a first server.
[dependencies]
tower-mcp = "0.22"
schemars = "1"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }Tool input types derive schemars::JsonSchema, and the derive must come from the same
schemars major version tower-mcp uses (currently 1.x). A version skew surfaces as an
opaque ExtractorHandler trait-bound error. To depend on schemars only through
tower-mcp's re-export, drop the direct schemars dependency and point the derive at it:
#[derive(Deserialize, tower_mcp::schemars::JsonSchema)]
#[schemars(crate = "tower_mcp::schemars")]
struct GreetInput { name: String }A complete server with one tool, served over stdio:
use schemars::JsonSchema;
use serde::Deserialize;
use tower_mcp::{BoxError, CallToolResult, McpRouter, StdioTransport, ToolBuilder};
#[derive(Debug, Deserialize, JsonSchema)]
struct GreetInput {
/// Who to greet.
name: String,
}
#[tokio::main]
async fn main() -> Result<(), BoxError> {
let greet = ToolBuilder::new("greet")
.title("Greet")
.description("Greet someone by name")
.read_only()
.handler(|input: GreetInput| async move {
Ok(CallToolResult::text(format!("Hello, {}!", input.name)))
})
.build();
let router = McpRouter::new()
.server_info("my-server", "1.0.0")
.tool(greet);
StdioTransport::new(router).run().await?;
Ok(())
}The input schema is derived from GreetInput. Resources, prompts, router composition,
per-tool middleware, state, and the trait-based and macro tool forms are covered in the
crate documentation.
The same McpRouter serves over any of these.
| Transport | Type | Feature |
|---|---|---|
| Stdio | StdioTransport |
none |
| Streamable HTTP with SSE | HttpTransport |
http |
| WebSocket | WebSocketTransport |
websocket |
| Unix domain socket | UnixSocketTransport |
unix |
For connecting to other MCP servers, tower_mcp::client provides stdio, HTTP, WebSocket,
and in-process channel client transports. ChildProcessTransport (feature childproc)
spawns a subprocess server and talks to it over its stdio.
No features are enabled by default.
| Feature | Description |
|---|---|
full |
All optional features |
http |
HTTP transport with SSE (adds axum, hyper) |
websocket |
WebSocket transport |
unix |
Unix domain socket transport (requires http) |
childproc |
Child process transport for spawning subprocess MCP servers |
oauth |
OAuth 2.1 resource server: JWT validation, protected resource metadata (requires http) |
jwks |
JWKS endpoint fetching for remote key sets (requires oauth) |
http-client |
HTTP client transport |
oauth-client |
OAuth client: authorization code with PKCE, registration, refresh, scope escalation, client credentials, discovery, token providers (requires http-client) |
testing |
TestClient for in-process server testing |
dynamic-tools |
Runtime registration and deregistration of tools, prompts, and resources |
proxy |
Multi-server aggregation proxy (McpProxy) |
macros |
Proc macros (#[tool_fn], #[prompt_fn], #[resource_fn], #[resource_template_fn]) |
resilience |
Re-export of tower-resilience circuit breaker, rate limiter, and bulkhead layers |
mcp-apps |
Typed server support for the MCP Apps extension; runtime advertisement stays explicit via McpRouter::with_mcp_apps() |
protocol-2026-07-28 |
Compile the 2026-07-28 protocol implementation |
stateless |
Compatibility alias for protocol-2026-07-28 |
tower-mcp-types carries the protocol and
error types with no tower, tokio, or axum dependency (only serde, serde_json,
thiserror, base64). Use it for editor integrations, code generators, and protocol
validators. tower-mcp re-exports all of it, so there is no duplication if you use both.
[dependencies]
tower-mcp-types = "0.22"| Guide | Covers |
|---|---|
| Client usage | Transport selection, connecting, callbacks, requests, caching, retry policy |
| HTTP deployment | Mounting, proxies and origins, session and scaling policy, middleware placement, timeouts |
| Protocol versions | Compile-time and runtime version support, lifecycle differences, interoperability, upgrades |
| OAuth authorization | Protecting a resource server, interactive and service clients, registration and storage, production checklist |
| MCP Apps | Typed app resources from tools, with negotiation and fallback |
examples/ holds the runnable programs, indexed in
examples/README.md. Start with
getting_started for a stdio server,
http_server for HTTP,
axum_embedding to mount MCP inside an existing axum app,
and middleware for layer composition.
cratesio-mcp is a server built with
tower-mcp in a separate repository.
Every build implements the 2025-11-25
and 2025-03-26 session protocols. The protocol-2026-07-28 feature compiles the
2026-07-28 implementation,
which is enabled at runtime once compiled; narrow the served set with
ProtocolSupport::stable(). HTTP dispatches per request on the MCP-Protocol-Version
header. See the
protocol-version guide
for the compile-time and runtime distinction and the upgrade path.
Across both revisions tower-mcp implements tools, resources (including templates and
subscriptions), prompts, completion, sampling, elicitation, roots, progress,
cancellation, logging, icons, implementation metadata, _meta on all protocol types,
session management, SSE event IDs with stream resumption, and extension declaration and
negotiation. Request batching is accepted on 2025-03-26 only, where the spec defines
it. The 2026-07-28 build adds sessionless dispatch, server/discover,
subscriptions/listen, per-request _meta, response-cache hints, Multi Round-Trip
Requests, and the Tasks extension (opt in with McpRouter::with_tasks).
Four of those are Deprecated by the specification as of 2026-07-28 and remain supported here: sampling, logging, and roots (SEP-2577), and Dynamic Client Registration (superseded by Client ID Metadata Documents, which this crate already prefers). They become eligible for removal from the specification in the first revision released on or after 2027-07-28. Nothing is scheduled for removal from this crate; see the deprecated features section for the migration paths.
The official MCP conformance suite
runs on every PR in
conformance.yml,
covering server and client for both revisions. All four suites pass with zero failures
and empty expected-failure baselines, pinned to conformance@0.2.0-alpha.10. The suite
is maintained upstream and grows with the spec, so scenario and check counts move; the
workflow is the current result.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets --all-features
RUSTDOCFLAGS="-Dwarnings" cargo doc --workspace --all-features --no-deps
cargo test --workspace --doc --all-featuresContributions are welcome; see CONTRIBUTING.md.
MSRV is 1.90.
MIT OR Apache-2.0