tower-mcp
Tower-native Model Context Protocol (MCP) implementation for Rust.
Overview
tower-mcp provides a composable, middleware-friendly approach to building MCP servers using the Tower service abstraction. Unlike framework-style MCP implementations, tower-mcp treats MCP as just another protocol that can be served through Tower's Service trait.
This means:
- Standard tower middleware (tracing, metrics, rate limiting, auth) just works
- Same service can be exposed over multiple transports (stdio, HTTP, WebSocket)
- Easy integration with existing tower-based applications (axum, tonic)
Live Demo
A demo MCP server for querying crates.io is deployed at:
https://crates-mcp-demo.fly.dev
Connect with any MCP client that supports HTTP transport, or add to Claude Code's .mcp.json:
The demo includes 7 tools (search, info, versions, dependencies, reverse deps, downloads, owners), 2 prompts (analyze, compare), and 1 resource (recent searches). See examples/crates-mcp for the full source.
Status
Active development - Core protocol, routing, and transports are implemented. Used in production for MCP server deployments.
Implemented
- JSON-RPC 2.0 message types, validation, and batch request handling
- MCP protocol types (tools, resources, prompts)
- Tool builder with type-safe handlers and JSON Schema generation via schemars
McpTooltrait for complex toolsMcpRouterimplementing Tower'sServicetraitJsonRpcServicelayer for protocol framing- Session state management with reconnection support
- Protocol version negotiation
- Tool annotations (behavior hints for trust/safety)
- Transports: stdio, HTTP (with SSE and stream resumption), WebSocket, child process
- Resources: list, read, subscribe/unsubscribe with change notifications
- Prompts: list and get with argument support
- Authentication: API key and Bearer token middleware helpers
- Elicitation: Server-to-client user input requests (form and URL modes)
- Client support: MCP client for connecting to external servers
- Progress notifications: Via
RequestContextin tool handlers - Request cancellation: Via
CancellationTokenin tool handlers - Completion: Autocomplete for prompt arguments and resource URIs
- Sampling types:
CreateMessageParams/CreateMessageResultfor LLM requests - Sampling runtime: Full support on stdio, WebSocket, and HTTP transports
- Async tasks: Task ID generation, status tracking, TTL-based cleanup for long-running operations
Installation
Add to your Cargo.toml:
[]
= "0.2"
Feature Flags
| Feature | Description |
|---|---|
full |
Enable all optional features |
http |
HTTP transport with SSE support (adds axum, hyper dependencies) |
websocket |
WebSocket transport for full-duplex communication |
childproc |
Child process transport for spawning subprocess MCP servers |
client |
MCP client support for connecting to external servers |
Example with features:
[]
= { = "0.2", = ["full"] }
Quick Start
use ;
use JsonSchema;
use Deserialize;
// Define your input type - schema is auto-generated
// Build a tool with type-safe handler
let greet = new
.description
.handler
.build;
// Create router with tools
let router = new
.server_info
.instructions
.tool;
// The router implements tower::Service and can be composed with middleware
Tool Definition
Builder Pattern (Recommended)
use ;
use JsonSchema;
use Deserialize;
let add = new
.description
.read_only // Hint: this tool doesn't modify state
.handler
.build;
Trait-Based (For Complex Tools)
use McpTool;
use ;
use JsonSchema;
use ;
use Arc;
// Convert to Tool and register
let calc = Calculator ;
let router = new.tool;
Handler with Context (Progress/Sampling)
use ;
let search = new
.description
.handler_with_context
.build;
Tool with Icons and Title
let tool = new
.title // Human-readable display name
.description
.icon
.read_only
.idempotent
.build;
Raw JSON Handler (Escape Hatch)
let echo = new
.description
.raw_handler;
Resource Definition
use ResourceBuilder;
// Static resource with inline content
let config = new
.name
.description
.json;
// Dynamic resource with handler
let status = new
.name
.description
.handler;
let router = new
.resource
.resource;
Prompt Definition
use ;
let greet = new
.description
.required_arg
.optional_arg
.handler;
let router = new.prompt;
Transports
Stdio (CLI/local)
use ;
let router = new
.server_info
.tool;
// Serve over stdin/stdout
new.serve.await?;
HTTP with SSE
use ;
let router = new
.server_info
.tool;
let transport = new;
let app = transport.into_router;
// Serve with axum
let listener = bind.await?;
serve.await?;
With Authentication Middleware
use extract_api_key;
use middleware;
// Add auth layer to the HTTP transport
let app = transport.into_router
.layer;
Architecture
+-----------------+
| Your App |
+-----------------+
|
+-----------------+
| Tower Middleware| <-- tracing, metrics, auth, etc.
+-----------------+
|
+-----------------+
| JsonRpcService | <-- JSON-RPC 2.0 framing
+-----------------+
|
+-----------------+
| McpRouter | <-- Request dispatch
+-----------------+
|
+------------+------------+
| | |
+--------+ +--------+ +--------+
| Tool 1 | | Tool 2 | | Tool N |
+--------+ +--------+ +--------+
Design Philosophy
| Aspect | tower-mcp |
|---|---|
| Style | Library, not framework |
| Tool definition | Builder pattern or trait-based |
| Middleware | Native tower layers |
| Transport | Pluggable (stdio, HTTP, WebSocket, child process) |
| Integration | Composable with axum/tonic |
Protocol Compliance
tower-mcp targets the MCP specification 2025-11-25. Current compliance:
- JSON-RPC 2.0 message format
- Protocol version negotiation
- Capability negotiation
- Initialize/initialized lifecycle
- tools/list and tools/call
- Tool annotations
- Batch requests
- resources/list, resources/read, resources/subscribe
- prompts/list, prompts/get
- Icons on tools/resources/prompts (SEP-973)
- Implementation metadata
- Sampling with tools/toolChoice (SEP-1577)
- Elicitation (user input requests)
- Session management
- Progress notifications
- Request cancellation
- Completion (autocomplete)
- Roots (filesystem discovery)
- Sampling (all transports)
- Async tasks (task ID, status tracking, TTL cleanup)
- SSE event IDs and stream resumption (SEP-1699)
We track all MCP Specification Enhancement Proposals (SEPs) as GitHub issues. A weekly workflow syncs status from the upstream spec repository.
Development
# Format, lint, and test
License
MIT OR Apache-2.0