10 releases (4 breaking)
Uses new Rust 2024
| 0.5.0 | Dec 26, 2025 |
|---|---|
| 0.4.0 | Dec 24, 2025 |
| 0.3.0 | Dec 23, 2025 |
| 0.2.5 | Dec 17, 2025 |
| 0.1.0 | Dec 11, 2025 |
#429 in #sdk
222 downloads per month
Used in 3 crates
1MB
23K
SLoC
mcpkit
A Rust SDK for the Model Context Protocol (MCP) that simplifies server development through a unified #[mcp_server] macro.
Features
- Unified
#[mcp_server]macro for defining tools, resources, and prompts - Runtime-agnostic async support (Tokio, smol)
- Typestate builders for compile-time validation of server configuration
- Context-based error handling with
McpErrorand.context()chains - MCP 2025-11-25 protocol including Tasks, Elicitation, and OAuth 2.1
- Tower-compatible middleware via built-in Layer pattern
Why mcpkit?
mcpkit implements MCP 2025-11-25 — the latest protocol specification. As of December 2025, the official rmcp SDK documentation references protocol version 2024-11-05 (always verify current status). mcpkit supports the newest MCP features:
| Feature | Added In | Description |
|---|---|---|
| Tasks | 2025-11-25 | Long-running operations with progress tracking and cancellation |
| Elicitation | 2025-06-18 | Server-initiated requests for user input |
| OAuth 2.1 | 2025-03-26 | Modern authentication with mandatory PKCE |
| Tool Annotations | 2025-03-26 | readOnly, destructive, idempotent hints for tools |
| Structured Output | 2025-06-18 | Type-safe JSON responses with schema validation |
See the detailed comparison for a full overview of Rust MCP SDK options.
Quick Start
Add the dependency to your Cargo.toml:
[dependencies]
mcpkit = "0.5"
tokio = { version = "1", features = ["full"] }
serde_json = "1"
Create a simple MCP server:
use mcpkit::prelude::*;
use mcpkit::transport::stdio::StdioTransport;
struct Calculator;
#[mcp_server(name = "calculator", version = "1.0.0")]
impl Calculator {
#[tool(description = "Add two numbers")]
async fn add(&self, a: f64, b: f64) -> ToolOutput {
ToolOutput::text((a + b).to_string())
}
#[tool(description = "Multiply two numbers")]
async fn multiply(&self, a: f64, b: f64) -> ToolOutput {
ToolOutput::text((a * b).to_string())
}
}
#[tokio::main]
async fn main() -> Result<(), McpError> {
// Create transport - you choose the runtime!
let transport = StdioTransport::new();
// Build server with registered handlers
let server = ServerBuilder::new(Calculator)
.with_tools(Calculator)
.build();
// Serve on the transport
server.serve(transport).await
}
Note: This SDK is runtime-agnostic. You provide the transport, which lets you use Tokio, smol, or any other async runtime. The examples use Tokio, but the SDK itself doesn't depend on any specific runtime.
mcpkit Highlights
| Feature | Description |
|---|---|
| Protocol | MCP 2025-11-25 (supports all 4 protocol versions) |
| Macro | Single #[mcp_server] with #[tool], #[resource], #[prompt] |
| Parameters | Extracted directly from function signatures |
| Errors | Unified McpError with .context() chains |
| Transports | stdio, WebSocket, HTTP/SSE, Unix sockets |
| Middleware | Built-in Tower-compatible Layer system |
| Runtime | Agnostic (Tokio, smol) |
For comparisons with other Rust MCP SDKs (rmcp, rust-mcp-sdk, mcp-protocol-sdk), see the detailed comparison.
Crate Structure
mcpkit/
├── mcpkit/ # Facade crate (use this)
├── crates/
│ ├── mcpkit-core/ # Protocol types, traits
│ ├── mcpkit-transport/ # Transport abstractions
│ │ ├── stdio # Standard I/O transport
│ │ ├── http # Streamable HTTP transport
│ │ ├── websocket # WebSocket transport
│ │ └── unix # Unix domain sockets
│ ├── mcpkit-server/ # Server implementation
│ ├── mcpkit-client/ # Client implementation
│ ├── mcpkit-macros/ # Procedural macros
│ ├── mcpkit-testing/ # Test utilities
│ ├── mcpkit-axum/ # Axum web framework integration
│ └── mcpkit-actix/ # Actix-web framework integration
└── examples/ # Example servers
Examples
Minimal Server
use mcpkit::prelude::*;
struct MyServer;
#[mcp_server(name = "minimal", version = "1.0.0")]
impl MyServer {
#[tool(description = "Say hello")]
async fn hello(&self, name: Option<String>) -> ToolOutput {
let name = name.unwrap_or_else(|| "World".to_string());
ToolOutput::text(format!("Hello, {}!", name))
}
}
With Resources
use mcpkit::prelude::*;
struct ConfigServer;
#[mcp_server(name = "config", version = "1.0.0")]
impl ConfigServer {
#[resource(
uri_pattern = "config://app/{key}",
name = "Configuration",
mime_type = "application/json"
)]
async fn get_config(&self, uri: &str) -> ResourceContents {
ResourceContents::text(uri, r#"{"debug": true}"#)
}
}
With Prompts
use mcpkit::prelude::*;
struct PromptServer;
#[mcp_server(name = "prompts", version = "1.0.0")]
impl PromptServer {
#[prompt(description = "Review code for issues")]
async fn code_review(&self, code: String, language: Option<String>) -> GetPromptResult {
let lang = language.unwrap_or_else(|| "unknown".to_string());
GetPromptResult {
description: Some("Code review prompt".to_string()),
messages: vec![
PromptMessage::user(format!(
"Please review the following {} code:\n```{}\n{}```",
lang, lang, code
))
],
}
}
}
Transports
The SDK is runtime-agnostic. You choose the transport and the async runtime.
Standard I/O
use mcpkit_transport::stdio::StdioTransport;
let transport = StdioTransport::new();
HTTP (Streamable)
use mcpkit_transport::http::HttpTransport;
let transport = HttpTransport::new(HttpTransportConfig::new("http://localhost:8080"));
WebSocket
use mcpkit_transport::websocket::WebSocketTransport;
let transport = WebSocketTransport::new(WebSocketConfig::new("ws://localhost:9000"));
Unix Domain Socket (Unix only)
#[cfg(unix)]
use mcpkit_transport::unix::UnixTransport;
#[cfg(unix)]
let transport = UnixTransport::new("/tmp/mcp.sock");
Middleware
use mcpkit_transport::stdio::StdioTransport;
use mcpkit_transport::middleware::{LoggingLayer, TimeoutLayer, LayerStack};
use std::time::Duration;
use log::Level;
let transport = StdioTransport::new();
let stack = LayerStack::new(transport)
.with(LoggingLayer::new(Level::Debug))
.with(TimeoutLayer::new(Duration::from_secs(30)));
Error Handling
use mcpkit::prelude::*;
fn process() -> Result<(), McpError> {
let result = something_risky()
.context("while processing request")?;
Ok(())
}
Protocol Version
This SDK implements MCP protocol version 2025-11-25.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Documentation
- Getting Started
- Working with Tools
- Working with Resources
- Working with Prompts
- Error Handling
- Using Middleware
- Transport Options
- Architecture Decision Records
Contributing
Contributions are welcome! Please read our Contributing Guide before submitting a Pull Request.
Security
For security issues, please see our Security Policy.
Dependencies
~17–34MB
~407K SLoC