mcp试剂盒
    
一个符合人体工程学、类型安全的建筑Rust库 模型上下文协议(MCP) 服务器。
MCP使AI助手能够通过标准化协议安全地访问工具、数据源和提示。该库提供了一个现代的、异步优先的实现,具有强大的过程宏,可用于快速开发。
______________________________________________________________________
🎉 v0.4.0的新增功能
🌐 WASM插件系统
- WebAssembly插件支持wasmtime集成
- 完全类型安全:i32、i64、f32、f64和字符串参数
- WASM函数签名的自动参数类型自检
- 用于字符串处理的WASM线性内存操作
- 生产就绪性能(1000+呼叫/秒)
- 跨平台沙盒执行
🧩 增强插件系统
- 动态加载工具、资源和提示
- 原生插件支持(.so、.dylib、.dll)
- WASM插件支持(.WASM模块)
- 正在进行插件注册
- 插件配置和生命周期管理
📦 真正的API集成
- ✅ GitHub插件 -创建问题、列出存储库、管理PR(4个工具)
- ✅ Jira插件 -创建/搜索问题,添加评论(4个工具)
- ✅ Confluence插件 -创建/搜索维基页面(4个工具)
- ✅ ClickHouse插件 -运行查询、生成报告、分析(6个工具)
- 所有这些都与工作的REST API实现有关!
🔧 增强的开发人员体验
- 生产就绪插件示例
- 带有4个演示模块的WASM插件示例
- 全面的插件文档
- 易于集成:只需
export API_TOKEN并运行
______________________________________________________________________
特性
- 🚀 异步优先 --基于Tokio构建,用于高性能并发操作
- 🛡️ 类型安全 --利用Rust的类型系统自动生成JSON模式
- 🎯 人体工程学宏 —
#[tool],#[resource],#[prompt]最小样板的属性 - 🔌 多个传输 --stdio、SSE/HTTP、流式HTTP、WebSocket和HTTPS/TLS
- 🔐 认证 -承载、API密钥、基本、OAuth 2.0和mTLS支持
- 🧩 插件系统 --从本机库(.so/.dll)和WASM模块动态加载
- 🌐 WASM插件 --沙盒WebAssembly模块,支持全类型系统
- 📦 真正的API集成 --GitHub、Jira和Confluence的生产就绪插件
- 📊 进度跟踪 --报告长时间运行操作的进度
- 📢 通知 --向客户端推送更新(资源更改、日志消息)
- 🔄 订阅 --订阅资源更改以获取实时更新
- ⛔ 取消 --取消长时间运行的请求
- 🤖 采样 --服务器向客户端发起LLM请求
- 💬 引出 --在工具执行期间向客户端请求用户输入
- 📁 根 --使用客户端提供的根进行文件系统沙盒
- 🧩 模块化 --具有门控架构,WASM兼容内核
- 📦 包括电池 --状态管理、错误处理、跟踪集成
- 🎨 灵活的API --在基于宏或手动构建器模式之间进行选择
- 📡 客户端SDK —
mcp-kit-client用于连接MCP服务器的机箱 - 🌐 网关 —
mcp-kit-gateway用于代理/聚合上游MCP服务器的机箱
🌟 亮点
插件系统 --构建模块化、可扩展的MCP服务器:
McpServer::builder()
.load_plugin("./plugins/github.so")? // Load from file
.with_plugin_manager(manager) // Or use plugin manager
.build()真正的API集成 --生产就绪插件包括:
# WASM Plugins - sandboxed WebAssembly modules
cargo run --example wasm_plugin --features plugin,plugin-wasm
# GitHub - manage repos, issues, PRs
export GITHUB_TOKEN=ghp_xxx
cargo run --example plugin_github --features plugin
# Jira - create/search issues, add comments
export JIRA_API_TOKEN=xxx
cargo run --example plugin_jira --features plugin
# Confluence - create/search wiki pages
export CONFLUENCE_API_TOKEN=xxx
cargo run --example plugin_confluence --features plugin
# ClickHouse - run SQL queries and generate reports
export CLICKHOUSE_URL=http://localhost:8123
cargo run --example plugin_clickhouse --features plugin类型安全&符合人体工程学 --使用宏的最小样板:
#[tool(description = "Add numbers")]
async fn add(a: f64, b: f64) -> String {
format!("{}", a + b)
}MCP网关 --聚合来自多个上游MCP服务器的工具:
use mcp_kit_gateway::{GatewayManager, UpstreamConfig, UpstreamTransport};
let mut gw = GatewayManager::new();
gw.add_upstream(UpstreamConfig {
name: "weather".into(),
transport: UpstreamTransport::Sse("http://localhost:3001/sse".into()),
prefix: Some("weather".into()),
client_name: None,
client_version: None,
});
let server = gw.build_server(
McpServer::builder().name("gateway").version("1.0.0")
).await?;______________________________________________________________________
安装
添加到您的 Cargo.toml:
[dependencies]
mcp-kit = "0.3" # Latest with gateway support
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
schemars = "0.8"
anyhow = "1" # For error handling对于插件开发,请添加:
[dependencies]
mcp-kit = { version = "0.2", features = ["plugin", "plugin-native"] }
reqwest = { version = "0.12", features = ["json"] } # For API calls支持的最低Rust版本(MSRV): 1.85
______________________________________________________________________
快速开始
使用宏(推荐)
构建具有自动模式生成功能的MCP服务器的最快方法:
use mcp_kit::prelude::*;
/// Add two numbers
#[tool(description = "Add two numbers and return the sum")]
async fn add(a: f64, b: f64) -> String {
format!("{}", a + b)
}
#[tokio::main]
async fn main() -> anyhow::Result {
McpServer::builder()
.name("calculator")
.version("1.0.0")
.tool_def(add_tool_def()) // Generated by #[tool] macro
.build()
.serve_stdio()
.await?;
Ok(())
}API手册
要对模式和行为进行更多控制:
use mcp_kit::prelude::*;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Deserialize, JsonSchema)]
struct AddInput {
/// First operand
a: f64,
/// Second operand
b: f64,
}
#[tokio::main]
async fn main() -> anyhow::Result {
let schema = serde_json::to_value(schemars::schema_for!(AddInput))?;
McpServer::builder()
.name("calculator")
.version("1.0.0")
.tool(
Tool::new("add", "Add two numbers", schema),
|params: AddInput| async move {
CallToolResult::text(format!("{}", params.a + params.b))
},
)
.build()
.serve_stdio()
.await?;
Ok(())
}______________________________________________________________________
核心概念
工具
工具是AI模型可以调用的功能。用以下方式定义它们 #[tool] 宏或手动:
// Macro approach
#[tool(description = "Multiply two numbers")]
async fn multiply(x: f64, y: f64) -> String {
format!("{}", x * y)
}
// Manual approach
let schema = serde_json::to_value(schemars::schema_for!(MultiplyInput))?;
builder.tool(
Tool::new("multiply", "Multiply two numbers", schema),
|params: MultiplyInput| async move {
CallToolResult::text(format!("{}", params.x * params.y))
}
);错误处理:
#[tool(description = "Divide two numbers")]
async fn divide(a: f64, b: f64) -> Result {
if b == 0.0 {
return Err("Cannot divide by zero".to_string());
}
Ok(format!("{}", a / b))
}资源
资源将数据(文件、API、数据库)暴露给AI模型:
// Static resource
#[resource(
uri = "config://app",
name = "Application Config",
mime_type = "application/json"
)]
async fn get_config(_req: ReadResourceRequest) -> McpResult {
let config = serde_json::json!({"version": "1.0", "debug": false});
Ok(ReadResourceResult::text(
"config://app",
serde_json::to_string_pretty(&config)?
))
}
// Template resource (dynamic URIs)
#[resource(uri = "file://{path}", name = "File System")]
async fn read_file(req: ReadResourceRequest) -> McpResult {
let path = req.uri.trim_start_matches("file://");
let content = tokio::fs::read_to_string(path).await
.map_err(|e| McpError::ResourceNotFound(e.to_string()))?;
Ok(ReadResourceResult::text(req.uri.clone(), content))
}提示
提示为AI交互提供了可重用的模板:
#[prompt(
name = "code-review",
description = "Generate a code review prompt",
arguments = ["code:required", "language:optional"]
)]
async fn code_review(req: GetPromptRequest) -> McpResult {
let code = req.arguments.get("code").cloned().unwrap_or_default();
let lang = req.arguments.get("language").cloned().unwrap_or("".into());
Ok(GetPromptResult::new(vec![
PromptMessage::user_text(format!(
"Review this {lang} code:\n\n```{lang}\n{code}\n```"
))
]))
}______________________________________________________________________
运输
标准(默认)
本地过程通信的标准输入/输出传输:
server.serve_stdio().await?;SSE(服务器发送事件)
基于HTTP的web客户端传输:
// Requires the "sse" feature
server.serve_sse(([0, 0, 0, 0], 3000)).await?;启用 Cargo.toml:
[dependencies]
mcp-kit = { version = "0.1", features = ["sse"] }可流式HTTP(MCP 2025-03-26)
具有可以返回JSON或SSE的单个端点的现代HTTP传输:
// Requires the "sse" feature
server.serve_streamable(([0, 0, 0, 0], 3000)).await?;协议:
POST /mcp
Content-Type: application/json
Mcp-Session-Id:
{"jsonrpc":"2.0","method":"tools/list","id":1}
Response (JSON for simple requests):
200 OK
Content-Type: application/json
Mcp-Session-Id:
{"jsonrpc":"2.0","result":{"tools":[...]},"id":1}
Response (SSE for streaming):
200 OK
Content-Type: text/event-stream
Mcp-Session-Id:
data: {"jsonrpc":"2.0","method":"notifications/progress",...}
data: {"jsonrpc":"2.0","result":{...},"id":1}与SSE相比的优势:
- 单端点(而不是
/sse+/message) - 服务器根据请求选择JSON或流
- 更适合无服务器/边缘部署
- 会话管理通过
Mcp-Session-Id头球
TLS/HTTPS
使用可选的mTLS进行安全的HTTPS传输:
use mcp_kit::transport::tls::{TlsConfig, ServeSseTlsExt};
let tls = TlsConfig::builder()
.cert_pem("server.crt")
.key_pem("server.key")
.client_auth_ca_pem("ca.crt") // Enable mTLS
.build()?;
server.serve_tls("0.0.0.0:8443".parse()?, tls).await?;双向通信
用于实时通信的双向WebSocket传输:
// Requires the "websocket" feature
server.serve_websocket("0.0.0.0:3001".parse()?).await?;启用 Cargo.toml:
[dependencies]
mcp-kit = { version = "0.1", features = ["websocket"] }______________________________________________________________________
认证
使用各种身份验证方法保护您的MCP服务器。所有身份验证功能都是可组合的,可以组合使用。
承载令牌身份验证
use mcp_kit::prelude::*;
use mcp_kit::auth::{BearerTokenProvider, IntoDynProvider};
use mcp_kit::Auth;
use std::sync::Arc;
// Protected tool - requires auth parameter
#[tool(description = "Say hello to the authenticated user")]
async fn greet(message: String, auth: Auth) -> McpResult {
Ok(CallToolResult::text(format!(
"Hello, {}! Message: {}", auth.subject, message
)))
}
#[tokio::main]
async fn main() -> anyhow::Result {
let provider = Arc::new(BearerTokenProvider::new(["my-secret-token"]));
McpServer::builder()
.name("secure-server")
.version("1.0.0")
.auth(provider.into_dyn())
.tool_def(greet_tool_def())
.build()
.serve_sse("0.0.0.0:3000".parse()?)
.await?;
Ok(())
}测试: curl -H "Authorization: Bearer my-secret-token" http://localhost:3000/sse
API密钥验证
use mcp_kit::auth::{ApiKeyProvider, IntoDynProvider};
// Supports both header and query param
let provider = Arc::new(ApiKeyProvider::new(["api-key-123", "api-key-456"]));
McpServer::builder()
.auth(provider.into_dyn())
// ...测试:
- 头球
curl -H "X-Api-Key: api-key-123" http://localhost:3000/sse - 查询:
curl "http://localhost:3000/sse?api_key=api-key-123"
基本认证
use mcp_kit::auth::{AuthenticatedIdentity, BasicAuthProvider, IntoDynProvider};
let provider = Arc::new(BasicAuthProvider::new(|username, password| {
Box::pin(async move {
if username == "admin" && password == "secret" {
Ok(AuthenticatedIdentity::new("admin")
.with_scopes(["read", "write", "admin"]))
} else {
Err(McpError::Unauthorized("invalid credentials".into()))
}
})
}));测试: curl -u admin:secret http://localhost:3000/sse
OAuth 2.0(JWT/JWKS)
use mcp_kit::auth::oauth2::{OAuth2Config, OAuth2Provider};
// JWT validation with JWKS endpoint
let provider = Arc::new(OAuth2Provider::new(OAuth2Config::Jwt {
jwks_url: "https://auth.example.com/.well-known/jwks.json".to_owned(),
required_audience: Some("https://my-api.example.com".to_owned()),
required_issuer: Some("https://auth.example.com/".to_owned()),
jwks_refresh_secs: 3600,
}));
// Or token introspection (RFC 7662)
let provider = Arc::new(OAuth2Provider::new(OAuth2Config::Introspection {
introspection_url: "https://auth.example.com/introspect".to_owned(),
client_id: "my-client".to_owned(),
client_secret: "my-secret".to_owned(),
cache_ttl_secs: 60,
}));mTLS(双向TLS)
use mcp_kit::auth::mtls::MtlsProvider;
use mcp_kit::transport::tls::{TlsConfig, ServeSseTlsExt};
let mtls = MtlsProvider::new(|cert_der: &[u8]| {
// Validate client certificate, extract subject
Ok(AuthenticatedIdentity::new("client-cn"))
});
let tls = TlsConfig::builder()
.cert_pem("server.crt")
.key_pem("server.key")
.client_auth_ca_pem("ca.crt")
.build()?;
McpServer::builder()
.auth(Arc::new(mtls))
.build()
.serve_tls("0.0.0.0:8443".parse()?, tls)
.await?;复合身份验证
组合多种身份验证方法:
use mcp_kit::auth::{
BearerTokenProvider, ApiKeyProvider, BasicAuthProvider,
CompositeAuthProvider, IntoDynProvider,
};
let composite = CompositeAuthProvider::new(vec![
BearerTokenProvider::new(["service-token"]).into_dyn(),
ApiKeyProvider::new(["api-key"]).into_dyn(),
BasicAuthProvider::new(/* validator */).into_dyn(),
]);
McpServer::builder()
.auth(Arc::new(composite))
// ...工具中的身份提取器
访问工具处理程序中的身份验证信息:
use mcp_kit::Auth;
#[tool(description = "Protected operation")]
async fn secure_op(data: String, auth: Auth) -> McpResult {
// Access authenticated identity
println!("User: {}", auth.subject);
println!("Scopes: {:?}", auth.scopes);
println!("Metadata: {:?}", auth.metadata);
// Check scopes
if !auth.has_scope("write") {
return Err(McpError::Unauthorized("write scope required".into()));
}
Ok(CallToolResult::text("Success!"))
}______________________________________________________________________
完成
为提示和资源参数提供自动完成建议:
use mcp_kit::prelude::*;
use mcp_kit::types::messages::{CompleteRequest, CompletionReference};
McpServer::builder()
.name("completion-demo")
.version("1.0.0")
// Prompt with completion handler
.prompt_with_completion(
Prompt::new("search")
.with_description("Search with auto-complete")
.with_arguments(vec![
PromptArgument::required("query"),
PromptArgument::optional("category"),
]),
// Prompt handler
|req: mcp_kit::types::messages::GetPromptRequest| async move {
Ok(GetPromptResult::new(vec![
PromptMessage::user_text(format!("Search: {}", req.arguments.get("query").unwrap()))
]))
},
// Completion handler
|req: CompleteRequest| async move {
let values = match req.argument.name.as_str() {
"category" => vec!["books", "movies", "music", "games"],
_ => vec![],
};
Ok(CompleteResult::new(values))
},
)
// Global completion for resources
.completion(|req: CompleteRequest| async move {
match &req.reference {
CompletionReference::Resource { uri } if uri.starts_with("file://") => {
Ok(CompleteResult::new(vec!["file:///src/", "file:///docs/"]))
}
_ => Ok(CompleteResult::empty()),
}
})
.build();______________________________________________________________________
通知
将更新从服务器推送到客户端:
use mcp_kit::prelude::*;
// Create notification channel
let (notifier, mut receiver) = NotificationSender::channel(100);
// In a tool handler - notify about resource changes
async fn update_data(notifier: NotificationSender) {
// ... update data ...
// Notify clients the resource changed
notifier.resource_updated("data://config").await.ok();
// Notify about list changes
notifier.resources_list_changed().await.ok();
notifier.tools_list_changed().await.ok();
notifier.prompts_list_changed().await.ok();
// Send log messages
notifier.log_info("update", "Data updated successfully").await.ok();
notifier.log_warning("update", "Some items skipped").await.ok();
}可用通知:
resource_updated(uri)--特定资源的内容已更改resources_list_changed()--可用资源列表已更改tools_list_changed()--可用工具列表已更改prompts_list_changed()--可用提示列表已更改log_debug/info/warning/error()--记录消息
______________________________________________________________________
进度跟踪
报告长时间运行操作的进度:
use mcp_kit::prelude::*;
async fn process_files(notifier: NotificationSender, files: Vec) {
let tracker = ProgressTracker::new(notifier, Some("token-123".into()));
for (i, file) in files.iter().enumerate() {
// Process file...
// Report progress
tracker.update_with_message(
i as f64 + 1.0,
files.len() as f64,
format!("Processing {}", file),
).await;
}
tracker.complete("All files processed").await;
}ProgressTracker方法:
update(progress, total, message)--发送进度更新update_percent(0.0..1.0, message)--进度百分比complete(message)--标记操作完成is_tracking()--检查是否提供了进度令牌
---
## Elicitation
Request user input from clients during tool execution:
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方法:**
- `confirm(message)` --是/否确认对话框
- `prompt_text(message)` --请求文本输入
- `prompt_number(message)` --请求数字输入
- `choose(message, options)` --多项选择
- `elicit(request)` --发送自定义启发请求
______________________________________________________________________
## 高级功能
### 状态管理
跨工具调用共享状态:
use std::sync::Arc; use tokio::sync::Mutex;
#[derive(Clone)] struct AppState { counter: Arc>, }
// In your tool handler let state = AppState { counter: Arc::new(Mutex::new(0)) };
builder.tool( Tool::new("increment", "Increment counter", schema), { let state = state.clone(); move |_: serde_json::Value| { let state = state.clone(); async move { let mut counter = state.counter.lock().await; *counter += 1; CallToolResult::text(format!("Counter: {}", *counter)) } } } );
### 日志记录
与集成 `tracing` 对于结构化日志记录:
tracing_subscriber::fmt() .with_writer(std::io::stderr) // Log to stderr for stdio transport .with_env_filter("my_server=debug,mcp_kit=info") .init();
tracing::info!("Server starting");
设置日志级别:
RUST_LOG=my_server=debug cargo run
### 错误处理
图书馆使用 `McpResult` 和 `McpError`:
use mcp_kit::{McpError, McpResult};
async fn my_tool() -> McpResult { // Automatic conversion from std::io::Error, serde_json::Error, etc. let data = tokio::fs::read_to_string("file.txt").await?;
// Custom errors if data.is_empty() { return Err(McpError::InvalidParams("File is empty".into())); }
Ok(CallToolResult::text(data)) }
______________________________________________________________________
## 插件系统
插件系统允许您从外部库、进程内模块或沙盒WebAssembly模块动态加载和管理工具、资源和提示。
### WASM插件支持🌐
**WebAssembly插件提供:**
- **沙盒执行** --为了安全起见,与主机系统隔离
- **跨平台兼容性** --到处都可以运行相同的.wasm文件
- **类型安全性** --完全支持i32、i64、f32、f64和字符串参数
- **内存操作** --通过WASM线性存储器正确处理字符串
- **高性能** --每秒1000+次函数调用
**WASM插件示例:**
cargo run --example wasm_plugin --features plugin,plugin-wasm
这将创建并加载4个WASM模块,演示:
- **整数运算** (i32+i32→ i32)
- **浮动操作** (f32×f32→ f32)
- **混合类型** (i32×f32×f64→ f64)
- **字符串处理** (字符串→ 长度通过内存操作)
**WASM模块示例(WAT格式):**
(module (func (export "add") (param i32 i32) (result i32) local.get 0 local.get 1 i32.add))
插件系统自动:
1. 分析WASM函数签名
1. 为每个导出的函数生成MCP工具
1. 处理从JSON到WASM值的类型转换
1. 管理字符串参数的内存分配
1. 将返回值转换回JSON
### 原生插件支持
### 快速开始
use mcp_kit::prelude::*; use mcp_kit::plugin::{McpPlugin, PluginConfig, PluginManager, ToolDefinition};
// Define a plugin struct WeatherPlugin;
impl McpPlugin for WeatherPlugin { fn name(&self) -> &str { "weather" } fn version(&self) -> &str { "1.0.0" }
fn register_tools(&self) -> Vec { vec![ ToolDefinition::new( Tool::new("get_weather", "Get current weather", schema), |params: WeatherInput| async move { CallToolResult::text(format!("Weather: {}", params.city)) }, ), ] }
fn on_load(&mut self, config: &PluginConfig) -> McpResult { // Initialize from config Ok(()) } }
// Load plugin into server #[tokio::main] async fn main() -> anyhow::Result { let mut plugin_manager = PluginManager::new();
// Register in-process plugin plugin_manager.register_plugin(WeatherPlugin, PluginConfig::default())?;
// Or load from dynamic library // plugin_manager.load_from_path("./plugins/weather.so")?;
let server = McpServer::builder() .name("my-server") .with_plugin_manager(plugin_manager) .build() .serve_stdio() .await?;
Ok(()) }
### 真实世界插件示例
图书馆包括 **与REAL API集成的PRODUCTION-READY插件**:
**✅ 天气插件** -使用mock API的完整工作示例
cargo run --example plugin_weather --features plugin,plugin-native
- 获取各城市的当前天气
- 获取多日预报
- 模拟实现(开箱即用)
**✅ GitHub插件(真实API)** -生产就绪的GitHub REST API v3
export GITHUB_TOKEN=ghp_your_token_here cargo run --example plugin_github --features plugin,plugin-native
- ✅ 使用实时数据获取存储库信息
- ✅ 列出用户存储库
- ✅ 创建问题
- ✅ 列出拉取请求
**✅ Jira插件(真正的API)** -生产就绪Jira REST API v3
export JIRA_BASE_URL="https://your-domain.atlassian.net" export JIRA_EMAIL="your-email@example.com" export JIRA_API_TOKEN="your-api-token" export JIRA_PROJECT_KEY="PROJ" cargo run --example plugin_jira --features plugin,plugin-native
- ✅ 用真实数据制造问题
- ✅ 获取问题详细信息
- ✅ JQL的搜索问题
- ✅ 添加注释
**✅ Confluence插件(真实API)** -生产就绪的Confluence REST API
export CONFLUENCE_BASE_URL="https://your-domain.atlassian.net" export CONFLUENCE_EMAIL="your-email@example.com" export CONFLUENCE_API_TOKEN="your-api-token" export CONFLUENCE_SPACE_KEY="TEAM" cargo run --example plugin_confluence --features plugin,plugin-native
- ✅ 创建wiki页面
- ✅ 获取页面内容
- ✅ 使用CQL搜索
- ✅ 在空间中列出页面
**✅ ClickHouse插件(真实数据库)** --生产就绪的ClickHouse集成
Start ClickHouse (Docker):
docker run -d -p 8123:8123 clickhouse/clickhouse-server
Configure and run:
export CLICKHOUSE_URL="http://localhost:8123" export CLICKHOUSE_DATABASE="default" cargo run --example plugin_clickhouse --features plugin,plugin-native
- ✅ 执行SQL查询
- ✅ 获取表架构和统计信息
- ✅ 生成分析报告(每日/每小时/顶级用户)
- ✅ 列出所有表格
- ✅ 数据库统计
- ✅ 插入数据
看 [`examples/PLUGINS.md`](examples/PLUGINS.md) 获取详细的设置指南。
______________________________________________________________________
cargo run --example plugin_jira --features plugin,plugin-native
- 创建、更新、搜索问题
- 管理冲刺和过渡
- 添加评论和附件
- 为Jira REST API集成做好准备
**🚧 Confluence插件** --完整模板(8个工具,559行)
cargo run --example plugin_confluence --features plugin,plugin-native
- 创建/更新wiki页面
- 使用CQL搜索
- 管理空间和附件
- 为Confluence REST API集成做好准备
**✅ GitHub插件(模拟)** --带有8个工具的扩展模板
cargo run --example plugin_github --features plugin,plugin-native
- 管理仓库、问题、PR
- 列出提交和分支
- 触发GitHub操作
- 使用模拟数据(用于参考和学习)
看 [`examples/PLUGINS.md`](examples/PLUGINS.md) 获取每个插件的详细指南。
### 插件配置
加载时通过配置:
let config = PluginConfig { config: serde_json::json!({ "api_key": "secret-key-123", "base_url": "https://api.example.com" }), enabled: true, priority: 10, // Higher = loads first permissions: PluginPermissions { network: true, filesystem: false, ..Default::default() }, };
plugin_manager.register_plugin(MyPlugin::new(), config)?;
### 生成器集成
直接在构建器中加载插件:
McpServer::builder() .name("my-server") .load_plugin("./plugins/jira.so")? // Load from file .load_plugin("./plugins/github.so")? // Chain multiple .build()
### 插件管理
// List all loaded plugins for plugin in plugin_manager.list_plugins() { println!("{} v{}: {} tools, {} resources", plugin.name, plugin.version, plugin.tool_count, plugin.resource_count); }
// Get plugin metadata if let Some(meta) = plugin_manager.get_metadata("weather") { println!("Weather plugin: {:?}", meta); }
// Unload a plugin plugin_manager.unload("weather")?;
### 本机插件(共享库)
创建一个插件作为 `.so`, `.dylib`,或 `.dll`:
// Plugin crate: lib.rs use mcp_kit::plugin::McpPlugin;
struct MyPlugin; impl McpPlugin for MyPlugin { /* ... */ }
// Export constructor #[no_mangle] pub extern "C" fn _mcp_plugin_create() -> *mut dyn McpPlugin { Box::into_raw(Box::new(MyPlugin)) }
构建为动态库:
[lib] crate-type = ["cdylib"]
[dependencies] mcp-kit = { version = "0.1", features = ["plugin"] }
cargo build --release
Produces: target/release/libmy_plugin.so
服务器加载:
plugin_manager.load_from_path("./target/release/libmy_plugin.so")?;
### 功能标志
[dependencies] mcp-kit = { version = "0.1", features = ["plugin", "plugin-native"] }
**可用插件功能:**
- `plugin` --核心插件系统(必填)
- `plugin-native` --加载本机共享库
- `plugin-wasm` --加载WASM插件(即将推出)
- `plugin-hot-reload` --开发热装(即将推出)
### 插件资源
- 📖 [插件系统文档](docs/PLUGINS.md) --完整指南
- 📦 [插件示例](examples/PLUGINS.md) --Jira、Confluence、GitHub模板
- 🌐 例子: [`examples/wasm_plugin.rs`](examples/wasm_plugin.rs) --WebAssembly插件演示
- 🔌 例子: [`examples/plugin_weather.rs`](examples/plugin_weather.rs) --本地插件示例
______________________________________________________________________
## MCP网关
这 `mcp-kit-gateway` crate允许您构建一个MCP网关服务器,该服务器连接到一个或多个上游MCP服务器,发现它们的工具/资源/提示,并通过单个网关端点公开它们。每个上游的功能都用前缀隔开,以避免冲突。
### 安装
[dependencies] mcp-kit-gateway = "0.1" mcp-kit = { version = "0.3", features = ["sse"] } # or "websocket", etc. tokio = { version = "1", features = ["full"] }
### 快速开始
use mcp_kit::prelude::*; use mcp_kit_gateway::{GatewayManager, UpstreamConfig, UpstreamTransport};
#[tokio::main] async fn main() -> anyhow::Result { let mut gw = GatewayManager::new();
// Add upstream servers gw.add_upstream(UpstreamConfig { name: "weather".into(), transport: UpstreamTransport::Sse("http://localhost:3001/sse".into()), prefix: Some("weather".into()), client_name: None, client_version: None, });
gw.add_upstream(UpstreamConfig { name: "tools".into(), transport: UpstreamTransport::WebSocket("ws://localhost:3002/ws".into()), prefix: Some("tools".into()), client_name: None, client_version: None, });
// Build gateway server — connects to upstreams and discovers capabilities let server = gw.build_server( McpServer::builder() .name("my-gateway") .version("1.0.0") // You can mix local tools with proxied upstream tools .tool( Tool::no_params("gateway/status", "Check gateway status"), |_args: serde_json::Value| async move { CallToolResult::text("Gateway is running") }, ) ).await?;
server.serve_sse(([0, 0, 0, 0], 3000)).await?; Ok(()) }
### 运作原理
1. **配置上游** --定义要连接到哪些MCP服务器以及如何连接(SSE、WebSocket、流式HTTP或stdio)
1. **连接并发现** --网关通过以下方式连接到每个上游 `McpClient`,呼叫 `list_tools()`/`list_resources()`/`list_prompts()` 发现能力
1. **命名空间和注册** --每个发现的功能都以前缀(例如上游工具)注册在本地服务器路由器中 `get_weather` 成为 `weather/get_weather`)
1. **代理请求** --当客户端调用代理工具/资源/提示符时,网关将请求转发到相应的上游并返回结果
### 上游运输
// SSE (HTTP Server-Sent Events) UpstreamTransport::Sse("http://localhost:3001/sse".into())
// WebSocket UpstreamTransport::WebSocket("ws://localhost:3002/ws".into())
// Streamable HTTP (MCP 2025-03-26) UpstreamTransport::StreamableHttp("http://localhost:3003/mcp".into())
// Stdio (spawn subprocess) UpstreamTransport::Stdio { program: "/path/to/mcp-server".into(), args: vec!["--flag".into()], env: vec![("API_KEY".into(), "secret".into())], }
### 功能标志
[dependencies] mcp-kit-gateway = { version = "0.1", default-features = false, features = ["sse"] }
- `full` (默认)--所有传输功能
- `sse` --SSE上游支持
- `websocket` --WebSocket上游支持
- `streamable-http` --流式HTTP上游支持
- `stdio` --Stdio子流程上游支持
### 错误处理
无法连接的上游会被记录为警告并跳过——网关服务器仍将从剩余的上游开始。单个发现失败(列出工具、资源或提示)也不是致命的。
看 [`gateway/README.md`](gateway/README.md) 获取完整的网关文档。
______________________________________________________________________
## 宏引用
### `#[tool]`
从异步函数生成工具:
#[tool(description = "Description here")] async fn my_tool(param: Type) -> ReturnType { // Implementation }
**属性:**
- `description = "..."` --工具说明(必填)
- `name = "..."` --工具名称(可选,默认为功能名称)
**支持的返回类型:**
- `String` → 转换为 `CallToolResult::text`
- `CallToolResult` → 直接使用
- `Result` → 错误处理支持
### `#[resource]`
生成资源处理程序:
#[resource( uri = "scheme://path", name = "Resource Name", description = "Optional description", mime_type = "text/plain" )] async fn handler(req: ReadResourceRequest) -> McpResult { // Implementation }
**URI模板:**
使用 `{variable}` 动态资源的语法:
#[resource(uri = "file://{path}", name = "Files")]
### `#[prompt]`
生成提示处理程序:
#[prompt( name = "prompt-name", description = "Prompt description", arguments = ["arg1:required", "arg2:optional"] )] async fn handler(req: GetPromptRequest) -> McpResult { // Implementation }
______________________________________________________________________
## 生成器API参考
McpServer::builder() // Server metadata .name("server-name") .version("1.0.0") .instructions("What this server does")
// Register tools .tool(tool, handler) // Manual API .tool_def(macro_generated_def) // From #[tool] macro
// Register resources .resource(resource, handler) // Static resource .resource_template(template, handler) // URI template .resource_def(macro_generated_def) // From #[resource] macro
// Register prompts .prompt(prompt, handler) .prompt_def(macro_generated_def) // From #[prompt] macro
.build()
______________________________________________________________________
## 示例
运行附带的示例以查看所有功能的运行情况:
Comprehensive showcase - all features
cargo run --example showcase
Showcase with SSE transport on port 3000
cargo run --example showcase -- --sse
WebSocket transport example
cargo run --example websocket
Macro-specific examples
cargo run --example macros_demo
Completion auto-complete example
cargo run --example completion
Notifications and progress example
cargo run --example notifications
Authentication examples
cargo run --example auth_bearer --features auth-full cargo run --example auth_apikey --features auth-full cargo run --example auth_basic --features auth-full cargo run --example auth_composite --features auth-full cargo run --example auth_oauth2 --features auth-oauth2 cargo run --example auth_mtls --features auth-mtls
Plugin examples
cargo run --example plugin_weather --features plugin,plugin-native # ✅ Working (mock) cargo run --example plugin_github --features plugin,plugin-native # ✅ Real GitHub API cargo run --example plugin_jira --features plugin,plugin-native # ✅ Real Jira API cargo run --example plugin_confluence --features plugin,plugin-native # ✅ Real Confluence API cargo run --example plugin_clickhouse --features plugin,plugin-native # ✅ Real ClickHouse DB
Client SDK example (requires running server first)
cargo run -p mcp-kit-client --example client_demo
Gateway example (requires running upstream server first)
UPSTREAM_URL=http://localhost:3001/sse cargo run -p mcp-kit-gateway --example gateway
**示例特征:**
- ✅ 多种工具类型(数学、异步、状态管理)
- ✅ 静态和模板资源
- ✅ 用论据提示
- ✅ 参数完成(自动完成)
- ✅ 通知(资源更新、日志记录)
- ✅ 长期操作的进度跟踪
- ✅ 资源订阅
- ✅ 请求取消
- ✅ 错误处理模式
- ✅ 请求之间的状态共享
- ✅ JSON内容类型
- ✅ Stdio、SSE和WebSocket传输
- ✅ 承载,API密钥,基本,OAuth 2.0,mTLS身份验证
- ✅ 复合身份验证(多种方法)
- ✅ 插件系统(原生和WASM)
- ✅ 真正的API集成(GitHub、Jira、Confluence、ClickHouse)
- ✅ 数据库集成(ClickHouse)
- ✅ 用于连接到服务器的客户端SDK
- ✅ 用于代理上游服务器的MCP网关
源代码: [`examples/`](examples/)
______________________________________________________________________
## 功能标志
控制要编译的功能:
[dependencies] mcp-kit = { version = "0.2", default-features = false, features = ["server", "stdio"] }
**可用功能:**
- `full` (默认)--启用所有功能
- `server` --核心服务器功能
- `stdio` --标准I/O传输
- `sse` --HTTP服务器发送事件传输
- `websocket` --WebSocket传输
**身份验证功能:**
- `auth` --核心身份验证类型和特征
- `auth-bearer` --承载令牌身份验证
- `auth-apikey` -API密钥验证
- `auth-basic` --HTTP基本身份验证
- `auth-oauth2` --OAuth 2.0(JWT/JWKS+自省)
- `auth-mtls` --双向TLS/客户端证书
- `auth-full` --所有身份验证功能(承载、apikey、基本)
**插件功能:**
- `plugin` --核心插件系统(特性、管理器、生命周期)
- `plugin-native` --加载本机共享库(.so、.dylib、.dll)
- `plugin-wasm` --加载WASM插件(即将推出)
- `plugin-hot-reload` --开发过程中的热重载(即将推出)
**WASM兼容性:**
使用 `default-features = false` 用于WASM目标(仅核心协议类型)。
______________________________________________________________________
## 建筑
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)
**板条箱结构:**
- `mcp-kit` --主服务器库
- `mcp-kit-macros` --程序宏(`#[tool]`等等)
- `mcp-kit-client` --用于连接MCP服务器的客户端SDK
- `mcp-kit-gateway` --代理上游MCP服务器的网关
______________________________________________________________________
## 客户端SDK
这 `mcp-kit-client` crate提供了一个用于连接到MCP服务器的客户端库:
[dependencies] mcp-kit-client = "0.2"
### 快速开始
use mcp_kit_client::prelude::*;
#[tokio::main] async fn main() -> anyhow::Result { // Connect via WebSocket let client = McpClient::websocket("ws://localhost:3001/ws").await?;
// Initialize connection let server_info = client.initialize("my-app", "1.0.0").await?; println!("Connected to: {}", server_info.name);
// List and call tools let tools = client.list_tools().await?; let result = client.call_tool("greet", serde_json::json!({ "name": "World" })).await?;
Ok(()) }
### 运输选项
// Stdio - spawn subprocess let client = McpClient::stdio("/path/to/mcp-server").await?;
// SSE - HTTP Server-Sent Events let client = McpClient::sse("http://localhost:3000").await?;
// WebSocket let client = McpClient::websocket("ws://localhost:3001/ws").await?;
### 可用操作
|方法|说明|
|--------|-------------|
| `initialize()` |初始化MCP连接|
| `list_tools()` |列出可用工具|
| `call_tool()` |调用带有参数的工具|
| `list_resources()` |列出可用资源|
| `read_resource()` |按URI读取资源|
| `list_prompts()` |列出可用提示|
| `get_prompt()` |按名称获取提示|
| `subscribe()` |订阅资源更新|
| `unsubscribe()` |取消订阅更新|
看 [`client/README.md`](client/README.md) 获取完整文档。
______________________________________________________________________
## 测试
Run all tests
cargo test --workspace --all-features
Check formatting
cargo fmt --all -- --check
Run lints
cargo clippy --workspace --all-features -- -D warnings
Check MSRV
cargo check --workspace --all-features
______________________________________________________________________
## 资源
- **MCP规范:** https://modelcontextprotocol.io/
- **文档:** https://docs.rs/mcp-kit
- **存储库:** https://github.com/KSD-CO/mcp-kit
- **示例:** [`examples/`](examples/)
- **CI/CD:**
______________________________________________________________________
## 贡献
欢迎投稿!拜托:
1. 分叉存储库
1. 创建要素分支
1. 通过测试进行更改
1. 确保 `cargo fmt` 和 `cargo clippy` 通过
1. 提交拉取请求
看 [`AGENTS.md`](AGENTS.md) 发展指南。
______________________________________________________________________
## 许可证
该项目根据 [MIT许可证](LICENSE).
______________________________________________________________________
## 更新日志
看 版本历史。
______________________________________________________________________
**建于❤️ 在Rust**
• [📦 crates.io上的视图](https://crates.io/crates/mcp-kit) • [📖 阅读文档](https://docs.rs/mcp-kit)