Rust插件模板
一个WebAssembly插件模板,用于使用hyper-MCP框架在Rust中构建MCP(模型上下文协议)插件。
概述
此模板提供了一个创建作为WebAssembly模块运行的MCP插件的入门项目。它包括实现MCP协议处理程序所需的所有依赖关系和样板代码。
项目结构
.
├── .github/workflows # Example Github Actions workflows
|-- src/
│ ├── lib.rs # Main plugin implementation
│ └── pdk/ # Plugin Development Kit types and utilities
├── Cargo.toml # Rust dependencies and project metadata
├── Dockerfile # Simple dockerfile for deploying to WASM
└── .cargo/ # Cargo configuration入门指南
先决条件
- 锈1.88或更高版本
wasm32-wasip1目标已安装:
rustup target add wasm32-wasip1发展
- 克隆或使用此模板 启动插件项目
- 实现插件处理程序 在
src/lib.rs:
> 注: 你只需要实现与你的插件相关的处理程序。例如,如果你的插件只提供工具,那么只实现 list_tools() 和 call_tool()。所有其他处理程序都有开箱即用的默认实现。
- list_tools() -描述可用工具 - call_tool() -执行工具 - list_resources() -列出可用资源 - read_resource() -读取资源内容 - list_prompts() -列出可用提示 - get_prompt() -获取提示详细信息 - complete() -提供自动完成建议
- 本地建设 (需要WASM目标):
cargo build --release --target wasm32-wasip1编译后的WASM模块将位于: target/wasm32-wasip1/release/plugin.wasm
依赖项
该模板包括关键依赖项:
- 灭绝pdk -Extism插件开发工具包
- Serde/Serde JSON -JSON序列化/反序列化
- 无论如何 -错误处理
- base64 -Base64编码/解码
- 计时 -日期/时间处理
插件处理函数
您的插件可以实现以下处理程序的任意组合。 只实现插件所需的处理程序 -该模板为其他所有内容提供了合理的默认值:
| 处理程序 | 用途 | 必需 |
|---|---|---|
list_tools() | 声明可用工具 | 提供插件的工具 |
call_tool() | 执行工具 | 提供插件的工具 |
list_resources() | 声明可用资源 | 资源提供插件 |
list_resource_templates() | 声明资源模板 | 动态资源插件 |
read_resource() | 读取资源内容 | 资源提供插件 |
list_prompts() | 声明可用提示 | 提示提供插件 |
get_prompt() | 检索特定提示 | 提示提供插件 |
complete() | 提供自动补全功能 | 支持补全的插件 |
on_roots_list_changed() | 处理根更改 | 插件对根更改做出反应 |
示例:仅限工具的插件
如果你的插件只提供工具,你只需要实现:
pub(crate) fn list_tools(_input: ListToolsRequest) -> Result
{
// Return your tools
}
pub(crate) fn call_tool(input: CallToolRequest) -> Result {
// Execute the requested tool
}所有其他处理程序将使用其默认实现。
主机功能
您的插件可以调用这些宿主函数与客户端和MCP服务器进行交互。从 pdk 模块:
use crate::pdk::imports::*;用户交互
create_elicitation(input: ElicitRequestParamWithTimeout) -> Result
通过客户端的启发界面请求用户输入。当您的插件在执行过程中需要用户指导、决策或确认时,请使用此功能。
let result = create_elicitation(ElicitRequestParamWithTimeout {
request: ElicitRequestParam {
// Define what input you're requesting
..Default::default()
},
timeout_ms: Some(30000), // 30 second timeout
})?;消息生成
create_message(input: CreateMessageRequestParam) -> Result
通过客户端的采样接口请求消息创建。当您的插件需要人工智能辅助的智能文本生成或分析时,请使用此功能。
let result = create_message(CreateMessageRequestParam {
messages: vec![/* conversation history */],
model_preferences: Some(/* model preferences */),
system: Some("You are a helpful assistant".to_string()),
..Default::default()
})?;资源发现
list_roots() -> Result
列出客户端的根目录或资源。使用此功能可以发现可用的根资源(通常是文件系统根),并了解插件可以访问的资源范围。
let roots = list_roots()?;
for root in roots.roots {
println!("Root: {} at {}", root.name, root.uri);
}日志记录
notify_logging_message(input: LoggingMessageNotificationParam) -> Result
向客户端发送诊断、信息、警告或错误消息。客户端的日志记录级别决定了要处理和显示哪些消息。
notify_logging_message(LoggingMessageNotificationParam {
level: "info".to_string(),
logger: Some("my_plugin".to_string()),
data: serde_json::json!({"message": "Processing started"}),
})?;进度报告
notify_progress(input: ProgressNotificationParam) -> Result
报告长时间运行操作期间的进度。允许客户端向用户显示进度条或状态信息。
notify_progress(ProgressNotificationParam {
progress: 50,
total: Some(100),
})?;列表更改通知
当插件的可用项更改时通知客户端:
notify_tool_list_changed() -> Result
- 在添加、删除或修改可用工具时调用此命令
notify_resource_list_changed() -> Result
- 在添加、删除或修改可用资源时调用此命令
notify_prompt_list_changed() -> Result
- 在添加、删除或修改可用提示时调用此命令
notify_resource_updated(input: ResourceUpdatedNotificationParam) -> Result
- 当您修改特定资源的内容时调用此命令
// When your plugin's tools change
notify_tool_list_changed()?;
// When a specific resource is updated
notify_resource_updated(ResourceUpdatedNotificationParam {
uri: "resource://my-resource".to_string(),
})?;示例:带有进度的交互式工具
pub(crate) fn call_tool(input: CallToolRequest) -> Result {
match input.name.as_str() {
"long_task" => {
// Log start
notify_logging_message(LoggingMessageNotificationParam {
level: "info".to_string(),
data: serde_json::json!({"message": "Starting long task"}),
..Default::default()
})?;
// Do work with progress updates
for i in 0..10 {
// ... do work ...
notify_progress(ProgressNotificationParam {
progress: (i + 1) * 10,
total: Some(100),
})?;
}
Ok(CallToolResult {
content: vec![Content {
type_: "text".to_string(),
text: Some("Task completed".to_string()),
..Default::default()
}],
..Default::default()
})
},
_ => Err(anyhow!("Unknown tool")),
}
}配电楼
使用Docker
包括 Dockerfile 提供了一个简单的构建,将您的插件打包到容器中:
cargo auditable build --release --target wasm32-wasip1
cp target/wasm32-wasip1/release/plugin.wasm plugin.wasm
docker push your-registry/your-plugin-name手动构建
要在没有Docker的情况下手动构建:
# Install dependencies
rustup target add wasm32-wasip1
cargo install cargo-auditable
# Build
cargo auditable build --release --target wasm32-wasip1
# Result is at: target/wasm32-wasip1/release/plugin.wasm实施指南
创建工具
下面是一个实现简单工具的示例:
pub(crate) fn list_tools(_input: ListToolsRequest) -> Result
{
Ok(ListToolsResult {
tools: vec![
Tool {
name: "greet".to_string(),
description: Some("Greet a person".to_string()),
input_schema: json!({
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The person's name"
}
},
"required": ["name"]
}),
},
],
..Default::default()
})
}
pub(crate) fn call_tool(input: CallToolRequest) -> Result {
match input.name.as_str() {
"greet" => {
let name = input.arguments
.get("name")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow!("name argument required"))?;
Ok(CallToolResult {
content: vec![Content {
type_: "text".to_string(),
text: Some(format!("Hello, {}!", name)),
..Default::default()
}],
..Default::default()
})
},
_ => Err(anyhow!("Unknown tool: {}", input.name)),
}
}创建资源
实现资源的示例:
pub(crate) fn list_resources(_input: ListResourcesRequest) -> Result
{
Ok(ListResourcesResult {
resources: vec![
ResourceDescription {
uri: "resource://example".to_string(),
name: Some("Example Resource".to_string()),
description: Some("An example resource".to_string()),
mime_type: Some("text/plain".to_string()),
},
],
..Default::default()
})
}
pub(crate) fn read_resource(input: ReadResourceRequest) -> Result {
match input.uri.as_str() {
"resource://example" => Ok(ReadResourceResult {
contents: vec![ResourceContents {
mime_type: Some("text/plain".to_string()),
text: Some("Resource content here".to_string()),
..Default::default()
}],
}),
_ => Err(anyhow!("Unknown resource: {}", input.uri)),
}
}hyper-mcp中的配置
构建并发布插件后,在hyper-mcp中配置它:
{
"plugins": {
"my_plugin": {
"url": "oci://your-registry/your-plugin-name:latest"
}
}
}对于本地开发/测试:
{
"plugins": {
"my_plugin": {
"url": "file:///path/to/target/wasm32-wasip1/release/plugin.wasm"
}
}
}测试
要在本地测试您的插件:
- 构建它:
cargo build --release --target wasm32-wasip1 - 更新hyper-mcp的配置以指向
file://统一资源定位符 - 使用以下命令启动hyper-mcp
RUST_LOG=debug - 通过Claude Desktop、Cursor IDE或其他MCP客户端进行测试
资源
许可证
与hyper-mcp相同-Apache 2.0
