mcp-kit
An ergonomic, type-safe Rust library for building Model Context Protocol (MCP) servers.
MCP enables AI assistants to securely access tools, data sources, and prompts through a standardized protocol. This library provides a modern, async-first implementation with powerful procedural macros for rapid development.
🎉 What's New in v0.4.0
🌐 WASM Plugin System
- WebAssembly plugin support with wasmtime integration
- Complete type safety: i32, i64, f32, f64, and string parameters
- Automatic parameter type introspection from WASM function signatures
- WASM linear memory operations for string handling
- Production-ready performance (1000+ calls/second)
- Cross-platform sandboxed execution
🧩 Enhanced Plugin System
- Dynamic loading of tools, resources, and prompts
- Native plugin support (.so, .dylib, .dll)
- WASM plugin support (.wasm modules)
- In-process plugin registration
- Plugin configuration and lifecycle management
📦 Real API Integrations
- ✅ GitHub Plugin - Create issues, list repos, manage PRs (4 tools)
- ✅ Jira Plugin - Create/search issues, add comments (4 tools)
- ✅ Confluence Plugin - Create/search wiki pages (4 tools)
- ✅ ClickHouse Plugin - Run queries, generate reports, analytics (6 tools)
- All with working REST API implementations!
🔧 Enhanced Developer Experience
- Production-ready plugin examples
- WASM plugin example with 4 demonstration modules
- Comprehensive plugin documentation
- Easy integration: just
export API_TOKENand run
Features
- 🚀 Async-first — Built on Tokio for high-performance concurrent operations
- 🛡️ Type-safe — Leverage Rust's type system with automatic JSON Schema generation
- 🎯 Ergonomic macros —
#[tool],#[resource],#[prompt]attributes for minimal boilerplate - 🔌 Multiple transports — stdio, SSE/HTTP, Streamable HTTP, WebSocket, and HTTPS/TLS
- 🔐 Authentication — Bearer, API Key, Basic, OAuth 2.0, and mTLS support
- 🧩 Plugin system — Dynamic loading from native libraries (.so/.dll) and WASM modules
- 🌐 WASM plugins — Sandboxed WebAssembly modules with full type system support
- 📦 Real API integrations — Production-ready plugins for GitHub, Jira, and Confluence
- 📊 Progress tracking — Report progress for long-running operations
- 📢 Notifications — Push updates to clients (resource changes, log messages)
- 🔄 Subscriptions — Subscribe to resource changes for real-time updates
- ⛔ Cancellation — Cancel long-running requests
- 🤖 Sampling — Server-initiated LLM requests to clients
- 💬 Elicitation — Request user input from clients during tool execution
- 📁 Roots — File system sandboxing with client-provided roots
- 🧩 Modular — Feature-gated architecture, WASM-compatible core
- 📦 Batteries included — State management, error handling, tracing integration
- 🎨 Flexible APIs — Choose between macro-based or manual builder patterns
- 📡 Client SDK —
mcp-kit-clientcrate for connecting to MCP servers - 🌐 Gateway —
mcp-kit-gatewaycrate for proxying/aggregating upstream MCP servers
🌟 Highlights
Plugin System — Build modular, extensible MCP servers:
builder
.load_plugin? // Load from file
.with_plugin_manager // Or use plugin manager
.build
Real API Integrations — Production-ready plugins included:
# WASM Plugins - sandboxed WebAssembly modules
# GitHub - manage repos, issues, PRs
# Jira - create/search issues, add comments
# Confluence - create/search wiki pages
# ClickHouse - run SQL queries and generate reports
Type-Safe & Ergonomic — Minimal boilerplate with macros:
async
MCP Gateway — Aggregate tools from multiple upstream MCP servers:
use ;
let mut gw = new;
gw.add_upstream;
let server = gw.build_server.await?;
Installation
Add to your Cargo.toml:
[]
= "0.3" # Latest with gateway support
= { = "1", = ["full"] }
= { = "1", = ["derive"] }
= "0.8"
= "1" # For error handling
For plugin development, add:
[]
= { = "0.2", = ["plugin", "plugin-native"] }
= { = "0.12", = ["json"] } # For API calls
Minimum Supported Rust Version (MSRV): 1.85
Quick Start
Using Macros (Recommended)
The fastest way to build an MCP server with automatic schema generation:
use *;
/// Add two numbers
async
async
Manual API
For more control over schema and behavior:
use *;
use JsonSchema;
use Deserialize;
async
Core Concepts
Tools
Tools are functions that AI models can invoke. Define them with the #[tool] macro or manually:
// Macro approach
async
// Manual approach
let schema = to_value?;
builder.tool;
Error Handling:
async
Resources
Resources expose data (files, APIs, databases) to AI models:
// Static resource
async
// Template resource (dynamic URIs)
async
Prompts
Prompts provide reusable templates for AI interactions:
async
Transports
Stdio (Default)
Standard input/output transport for local process communication:
server.serve_stdio.await?;
SSE (Server-Sent Events)
HTTP-based transport for web clients:
// Requires the "sse" feature
server.serve_sse.await?;
Enable in Cargo.toml:
[]
= { = "0.1", = ["sse"] }
Streamable HTTP (MCP 2025-03-26)
Modern HTTP transport with a single endpoint that can return JSON or SSE:
// Requires the "sse" feature
server.serve_streamable.await?;
Protocol:
POST /mcp
Content-Type: application/json
Mcp-Session-Id: <optional session id>
{"jsonrpc":"2.0","method":"tools/list","id":1}
Response (JSON for simple requests):
200 OK
Content-Type: application/json
Mcp-Session-Id: <session id>
{"jsonrpc":"2.0","result":{"tools":[...]},"id":1}
Response (SSE for streaming):
200 OK
Content-Type: text/event-stream
Mcp-Session-Id: <session id>
data: {"jsonrpc":"2.0","method":"notifications/progress",...}
data: {"jsonrpc":"2.0","result":{...},"id":1}
Advantages over SSE:
- Single endpoint (instead of
/sse+/message) - Server chooses JSON or stream per-request
- Better for serverless/edge deployments
- Session management via
Mcp-Session-Idheader
TLS/HTTPS
Secure HTTPS transport with optional mTLS:
use ;
let tls = builder
.cert_pem
.key_pem
.client_auth_ca_pem // Enable mTLS
.build?;
server.serve_tls.await?;
WebSocket
Bidirectional WebSocket transport for real-time communication:
// Requires the "websocket" feature
server.serve_websocket.await?;
Enable in Cargo.toml:
[]
= { = "0.1", = ["websocket"] }
Authentication
Protect your MCP server with various authentication methods. All auth features are composable and can be combined.
Bearer Token Authentication
use *;
use ;
use Auth;
use Arc;
// Protected tool - requires auth parameter
async
async
Test with: curl -H "Authorization: Bearer my-secret-token" http://localhost:3000/sse
API Key Authentication
use ;
// Supports both header and query param
let provider = new;
builder
.auth
// ...
Test with:
- Header:
curl -H "X-Api-Key: api-key-123" http://localhost:3000/sse - Query:
curl "http://localhost:3000/sse?api_key=api-key-123"
Basic Authentication
use ;
let provider = new;
Test with: curl -u admin:secret http://localhost:3000/sse
OAuth 2.0 (JWT/JWKS)
use ;
// JWT validation with JWKS endpoint
let provider = new;
// Or token introspection (RFC 7662)
let provider = new;
mTLS (Mutual TLS)
use MtlsProvider;
use ;
let mtls = new;
let tls = builder
.cert_pem
.key_pem
.client_auth_ca_pem
.build?;
builder
.auth
.build
.serve_tls
.await?;
Composite Authentication
Combine multiple auth methods:
use ;
let composite = new;
builder
.auth
// ...
Auth Extractor in Tools
Access authentication info in tool handlers:
use Auth;
async
Completion
Provide auto-complete suggestions for prompt and resource arguments:
use *;
use ;
builder
.name
.version
// Prompt with completion handler
.prompt_with_completion
// Global completion for resources
.completion
.build;
Notifications
Push updates from server to clients:
use *;
// Create notification channel
let = channel;
// In a tool handler - notify about resource changes
async
Available Notifications:
resource_updated(uri)— A specific resource's content changedresources_list_changed()— Available resources list changedtools_list_changed()— Available tools list changedprompts_list_changed()— Available prompts list changedlog_debug/info/warning/error()— Log messages
Progress Tracking
Report progress for long-running operations:
use *;
async
ProgressTracker Methods:
update(progress, total, message)— Send progress updateupdate_percent(0.0..1.0, message)— Progress as percentagecomplete(message)— Mark operation completeis_tracking()— Check if progress token was provided
---
## Elicitation
Request user input from clients during tool execution:
```rust
use mcp_kit::prelude::*;
// Create elicitation client
let (client, mut rx) = ChannelElicitationClient::channel(10);
// Simple yes/no confirmation
let confirmed = client.confirm("Delete all temporary files?").await?;
if confirmed {
// User confirmed, proceed
}
// Request text input
if let Some(name) = client.prompt_text("Enter project name").await? {
println!("Creating project: {}", name);
}
// Multiple choice
let options = vec!["small".into(), "medium".into(), "large".into()];
if let Some(size) = client.choose("Select deployment size", options).await? {
println!("Selected: {}", size);
}
// Complex form with builder
let request = ElicitationRequestBuilder::new("Configure your project")
.text_required("name", "Project Name")
.boolean("private", "Private Repository")
.number("port", "Port Number")
.select("language", "Language", &["rust", "python", "javascript"])
.build();
let result = client.elicit(request).await?;
if result.is_accepted() {
// Process user input from result.content
}
ElicitationClientExt Methods:
confirm(message)— Yes/no confirmation dialogprompt_text(message)— Request text inputprompt_number(message)— Request numeric inputchoose(message, options)— Multiple choice selectionelicit(request)— Send custom elicitation request
Advanced Features
State Management
Share state across tool invocations:
use Arc;
use Mutex;
// In your tool handler
let state = AppState ;
builder.tool;
Logging
Integrate with tracing for structured logging:
fmt
.with_writer // Log to stderr for stdio transport
.with_env_filter
.init;
info!;
Set log level:
RUST_LOG=my_server=debug
Error Handling
The library uses McpResult<T> and McpError:
use ;
async
Plugin System
The plugin system allows you to dynamically load and manage tools, resources, and prompts from external libraries, in-process modules, or sandboxed WebAssembly modules.
WASM Plugin Support 🌐
WebAssembly plugins provide:
- Sandboxed execution — Isolated from host system for security
- Cross-platform compatibility — Same .wasm file runs everywhere
- Type safety — Full support for i32, i64, f32, f64, and string parameters
- Memory operations — Proper string handling via WASM linear memory
- High performance — 1000+ function calls per second
Example WASM Plugin:
This creates and loads 4 WASM modules demonstrating:
- Integer arithmetic (i32 + i32 → i32)
- Float operations (f32 × f32 → f32)
- Mixed types (i32 × f32 × f64 → f64)
- String processing (string → length via memory operations)
WASM Module Example (WAT format):
(module
(func (export "add") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add))
The plugin system automatically:
- Analyzes WASM function signatures
- Generates MCP tools for each exported function
- Handles type conversion from JSON to WASM values
- Manages memory allocation for string parameters
- Converts return values back to JSON
Native Plugin Support
Quick Start
use *;
use ;
// Define a plugin
;
// Load plugin into server
async
Real-World Plugin Examples
The library includes PRODUCTION-READY plugins with REAL API integration:
✅ Weather Plugin — Fully working example with mock API
- Get current weather for cities
- Get multi-day forecasts
- Mock implementation (works out of the box)
✅ GitHub Plugin (Real API) — Production-ready GitHub REST API v3
- ✅ Get repository info with live data
- ✅ List user repositories
- ✅ Create issues
- ✅ List pull requests
✅ Jira Plugin (Real API) — Production-ready Jira REST API v3
- ✅ Create issues with real data
- ✅ Get issue details
- ✅ Search issues with JQL
- ✅ Add comments
✅ Confluence Plugin (Real API) — Production-ready Confluence REST API
- ✅ Create wiki pages
- ✅ Get page content
- ✅ Search with CQL
- ✅ List pages in space
✅ ClickHouse Plugin (Real Database) — Production-ready ClickHouse integration
# Start ClickHouse (Docker):
# Configure and run:
- ✅ Execute SQL queries
- ✅ Get table schema and stats
- ✅ Generate analytics reports (daily/hourly/top users)
- ✅ List all tables
- ✅ Database statistics
- ✅ Insert data
See examples/PLUGINS.md for detailed setup guides.
- Create, update, search issues
- Manage sprints & transitions
- Add comments & attachments
- Ready for Jira REST API integration
🚧 Confluence Plugin — Complete template (8 tools, 559 lines)
- Create/update wiki pages
- Search with CQL
- Manage spaces & attachments
- Ready for Confluence REST API integration
✅ GitHub Plugin (Mock) — Extended template with 8 tools
- Manage repos, issues, PRs
- List commits & branches
- Trigger GitHub Actions
- Uses mock data (for reference and learning)
See examples/PLUGINS.md for detailed guides on each plugin.
Plugin Configuration
Pass configuration at load time:
let config = PluginConfig ;
plugin_manager.register_plugin?;
Builder Integration
Load plugins directly in the builder:
builder
.name
.load_plugin? // Load from file
.load_plugin? // Chain multiple
.build
Plugin Management
// List all loaded plugins
for plugin in plugin_manager.list_plugins
// Get plugin metadata
if let Some = plugin_manager.get_metadata
// Unload a plugin
plugin_manager.unload?;
Native Plugin (Shared Library)
Create a plugin as a .so, .dylib, or .dll:
// Plugin crate: lib.rs
use McpPlugin;
;
// Export constructor
pub extern "C"
Build as dynamic library:
[]
= ["cdylib"]
[]
= { = "0.1", = ["plugin"] }
# Produces: target/release/libmy_plugin.so
Load in server:
plugin_manager.load_from_path?;
Feature Flags
[]
= { = "0.1", = ["plugin", "plugin-native"] }
Available plugin features:
plugin— Core plugin system (required)plugin-native— Load native shared librariesplugin-wasm— Load WASM plugins (coming soon)plugin-hot-reload— Development hot reload (coming soon)
Plugin Resources
- 📖 Plugin System Documentation — Complete guide
- 📦 Plugin Examples — Jira, Confluence, GitHub templates
- 🌐 Example:
examples/wasm_plugin.rs— WebAssembly plugin demo - 🔌 Example:
examples/plugin_weather.rs— Native plugin example
MCP Gateway
The mcp-kit-gateway crate lets you build an MCP gateway server that connects to one or more upstream MCP servers, discovers their tools/resources/prompts, and exposes them through a single gateway endpoint. Each upstream's capabilities are namespaced with a prefix to avoid collisions.
Installation
[]
= "0.1"
= { = "0.3", = ["sse"] } # or "websocket", etc.
= { = "1", = ["full"] }
Quick Start
use *;
use ;
async
How It Works
- Configure upstreams — Define which MCP servers to connect to and how (SSE, WebSocket, Streamable HTTP, or stdio)
- Connect & discover — The gateway connects to each upstream via
McpClient, callslist_tools()/list_resources()/list_prompts()to discover capabilities - Namespace & register — Each discovered capability is registered in the local server router with a prefix (e.g., upstream tool
get_weatherbecomesweather/get_weather) - Proxy requests — When a client calls a proxied tool/resource/prompt, the gateway forwards the request to the appropriate upstream and returns the result
Upstream Transports
// SSE (HTTP Server-Sent Events)
Sse
// WebSocket
WebSocket
// Streamable HTTP (MCP 2025-03-26)
StreamableHttp
// Stdio (spawn subprocess)
Stdio
Feature Flags
[]
= { = "0.1", = false, = ["sse"] }
full(default) — All transport featuressse— SSE upstream supportwebsocket— WebSocket upstream supportstreamable-http— Streamable HTTP upstream supportstdio— Stdio subprocess upstream support
Error Handling
Upstreams that fail to connect are logged as warnings and skipped — the gateway server will still start with the remaining upstreams. Individual discovery failures (listing tools, resources, or prompts) are also non-fatal.
See gateway/README.md for the full gateway documentation.
Macro Reference
#[tool]
Generate tools from async functions:
async
Attributes:
description = "..."— Tool description (required)name = "..."— Tool name (optional, defaults to function name)
Supported return types:
String→ Converted toCallToolResult::textCallToolResult→ Used directlyResult<T, E>→ Error handling support
#[resource]
Generate resource handlers:
async
URI Templates:
Use {variable} syntax for dynamic resources:
#[prompt]
Generate prompt handlers:
async
Builder API Reference
builder
// Server metadata
.name
.version
.instructions
// Register tools
.tool // Manual API
.tool_def // From #[tool] macro
// Register resources
.resource // Static resource
.resource_template // URI template
.resource_def // From #[resource] macro
// Register prompts
.prompt
.prompt_def // From #[prompt] macro
.build
Examples
Run the included examples to see all features in action:
# Comprehensive showcase - all features
# Showcase with SSE transport on port 3000
# WebSocket transport example
# Macro-specific examples
# Completion auto-complete example
# Notifications and progress example
# Authentication examples
# Plugin examples
# Client SDK example (requires running server first)
# Gateway example (requires running upstream server first)
UPSTREAM_URL=http://localhost:3001/sse
Example Features:
- ✅ Multiple tool types (math, async, state management)
- ✅ Static and template resources
- ✅ Prompts with arguments
- ✅ Argument completion (auto-complete)
- ✅ Notifications (resource updates, logging)
- ✅ Progress tracking for long operations
- ✅ Resource subscriptions
- ✅ Request cancellation
- ✅ Error handling patterns
- ✅ State sharing between requests
- ✅ JSON content types
- ✅ Stdio, SSE, and WebSocket transports
- ✅ Bearer, API Key, Basic, OAuth 2.0, mTLS authentication
- ✅ Composite authentication (multiple methods)
- ✅ Plugin system (native and WASM)
- ✅ Real API integrations (GitHub, Jira, Confluence, ClickHouse)
- ✅ Database integrations (ClickHouse)
- ✅ Client SDK for connecting to servers
- ✅ MCP Gateway for proxying upstream servers
Source code: examples/
Feature Flags
Control which features to compile:
[]
= { = "0.2", = false, = ["server", "stdio"] }
Available features:
full(default) — All features enabledserver— Core server functionalitystdio— Standard I/O transportsse— HTTP Server-Sent Events transportwebsocket— WebSocket transport
Authentication features:
auth— Core auth types and traitsauth-bearer— Bearer token authenticationauth-apikey— API key authenticationauth-basic— HTTP Basic authenticationauth-oauth2— OAuth 2.0 (JWT/JWKS + introspection)auth-mtls— Mutual TLS / client certificatesauth-full— All auth features (bearer, apikey, basic)
Plugin features:
plugin— Core plugin system (trait, manager, lifecycle)plugin-native— Load native shared libraries (.so, .dylib, .dll)plugin-wasm— Load WASM plugins (coming soon)plugin-hot-reload— Hot reload during development (coming soon)
WASM compatibility:
Use default-features = false for WASM targets (only core protocol types).
Architecture
mcp-kit/
├── src/
│ ├── lib.rs # Public API and re-exports
│ ├── error.rs # Error types
│ ├── protocol.rs # JSON-RPC 2.0 implementation
│ ├── types/ # MCP protocol types
│ ├── server/ # Server implementation [feature = "server"]
│ └── transport/ # Transport implementations
├── macros/ # Procedural macros crate
├── client/ # Client SDK crate
└── gateway/ # Gateway crate (upstream proxying)
Crate structure:
mcp-kit— Main server librarymcp-kit-macros— Procedural macros (#[tool], etc.)mcp-kit-client— Client SDK for connecting to MCP serversmcp-kit-gateway— Gateway for proxying upstream MCP servers
Client SDK
The mcp-kit-client crate provides a client library for connecting to MCP servers:
[]
= "0.2"
Quick Start
use *;
async
Transport Options
// Stdio - spawn subprocess
let client = stdio.await?;
// SSE - HTTP Server-Sent Events
let client = sse.await?;
// WebSocket
let client = websocket.await?;
Available Operations
| Method | Description |
|---|---|
initialize() |
Initialize the MCP connection |
list_tools() |
List available tools |
call_tool() |
Call a tool with arguments |
list_resources() |
List available resources |
read_resource() |
Read a resource by URI |
list_prompts() |
List available prompts |
get_prompt() |
Get a prompt by name |
subscribe() |
Subscribe to resource updates |
unsubscribe() |
Unsubscribe from updates |
See client/README.md for full documentation.
Testing
# Run all tests
# Check formatting
# Run lints
# Check MSRV
Resources
- MCP Specification: https://modelcontextprotocol.io/
- Documentation: https://docs.rs/mcp-kit
- Repository: https://github.com/KSD-CO/mcp-kit
- Examples:
examples/ - CI/CD: GitHub Actions
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Ensure
cargo fmtandcargo clippypass - Submit a pull request
See AGENTS.md for development guidelines.
License
This project is licensed under the MIT License.
Changelog
See GitHub Releases for version history.
Built with ❤️ in Rust