首页
/ Rust MCP 服务端开发实战:基于 awesome-copilot 的 rust-mcp-development 插件与 rmcp SDK 全流程指南

Rust MCP 服务端开发实战:基于 awesome-copilot 的 rust-mcp-development 插件与 rmcp SDK 全流程指南

2026-09-10 12:36:41作者:曹令琨Iris

导读

本篇文章聚焦 awesome-copilot 仓库中的 rust-mcp-development 插件,讲解如何借助官方 rmcp Rust SDK 构建高性能、类型安全的 Model Context Protocol(MCP)服务端。你将掌握插件提供的 /rust-mcp-development:rust-mcp-server-generator 斜杠命令与 rust-mcp-expert 智能体、rmcp-macros 过程宏工具链、四种传输方式(Stdio / SSE / Streamable HTTP / 自定义传输)、工具(Tools)、提示词(Prompts)、资源(Resources)三大能力实现,以及从单元测试到跨平台部署的完整落地路径。

插件是什么:一份集成化的 Rust MCP 开发工具箱

rust-mcp-developmentAwesome Copilot 社区插件体系中面向 Rust 语言的一款开发工具箱。它的目标非常聚焦:帮助开发者使用官方 rmcp SDK 快速构建高性能 MCP 服务端,核心技术栈为 Rust 的 async/await 异步模型、过程宏声明式开发以及强类型参数校验。

插件的元信息记录在 plugin.json 中,其声明如下:

{
  "name": "rust-mcp-development",
  "description": "Build high-performance Model Context Protocol servers in Rust using the official rmcp SDK with async/await, procedural macros, and type-safe implementations.",
  "version": "1.0.0",
  "license": "MIT",
  "keywords": ["rust", "mcp", "model-context-protocol", "server-development", "sdk", "tokio", "async", "macros", "rmcp"],
  "extensions": {
    "com.github.awesome-copilot": {
      "agents": ["./agents/rust-mcp-expert.md"],
      "skills": ["./skills/rust-mcp-server-generator/"]
    }
  }
}

extensions 字段可以清晰地看到插件的组成结构:它打包了一个 Agent(rust-mcp-expert 和一个 Skill(rust-mcp-server-generator,分别对应"专家问答与代码指导"和"一键生成完整项目"两种使用场景。

安装方式

使用 Copilot CLI 安装:

copilot plugin install rust-mcp-development@awesome-copilot

安装完成后即可在对话中使用插件的斜杠命令,并激活对应的智能体。

插件内置能力清单

插件在 Copilot 会话中暴露一个斜杠命令:

命令 说明
/rust-mcp-development:rust-mcp-server-generator 使用官方 rmcp SDK 生成一个完整的 Rust MCP Server 项目,包含工具、提示词、资源和测试

以及一个专家智能体:

智能体 说明
rust-mcp-expert 基于 rmcp SDK 与 tokio 异步运行时,为 Rust MCP 服务端开发提供专家级辅助(定义见 agents/rust-mcp-expert.agent.md

项目初始化:Cargo 依赖与工程结构

添加依赖

Cargo.toml 中加入核心依赖(对应 instructions/rust-mcp-server.instructions.md 的推荐配置):

[dependencies]
rmcp = { version = "0.8.1", features = ["server"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
tracing = "0.1"
tracing-subscriber = "0.3"

启用宏支持时追加:

[dependencies]
rmcp-macros = "0.8"
schemars = { version = "0.8", features = ["derive"] }

需要说明的要点:

  • rmcp 是官方 Rust MCP SDK(插件说明中标注 v0.8+),开启 server feature 后提供 ServerServerHandler 等服务端组件;
  • rmcp-macros 提供 #[tool]#[tool_router]#[tool_handler] 三个核心过程宏;
  • schemars::JsonSchema 负责为工具参数自动生成 JSON Schema,供客户端(如 Copilot)做参数校验与自动补全;
  • anyhow 用于应用层错误上下文链,tracing / tracing-subscriber 用于可观测性日志。

如果项目需要 HTTP 传输,插件生成的脚手架还提供可选的 HTTP feature(见 skills/rust-mcp-server-generator/SKILL.md):

axum = { version = "0.7", optional = true }
tower-http = { version = "0.5", features = ["cors"], optional = true }

[features]
default = []
http = ["dep:axum", "dep:tower-http"]

推荐的项目目录结构

无论是手写还是由生成器产出,官方推荐的工程布局如下:

my-mcp-server/
├── Cargo.toml
├── src/
│   ├── main.rs           # 服务端入口
│   ├── handler.rs        # ServerHandler 实现
│   ├── tools/
│   │   ├── mod.rs
│   │   ├── calculator.rs
│   │   └── greeter.rs
│   ├── prompts/
│   │   ├── mod.rs
│   │   └── code_review.rs
│   ├── resources/
│   │   ├── mod.rs
│   │   └── data.rs
│   └── state.rs
└── tests/
    └── integration_tests.rs

这种分层把"入口、处理器、工具、提示词、资源、共享状态、集成测试"拆分为独立模块,职责清晰、便于并行开发与测试。

服务端骨架:main 入口与 ServerHandler 实现

基本服务端搭建

使用 Stdio 传输的最小服务端入口如下:

use rmcp::{
    protocol::ServerCapabilities,
    server::{Server, ServerHandler},
    transport::StdioTransport,
};
use tokio::signal;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    tracing_subscriber::fmt().init();

    let handler = MyServerHandler::new();
    let transport = StdioTransport::new();

    let server = Server::builder()
        .with_handler(handler)
        .with_capabilities(ServerCapabilities {
            tools: Some(Default::default()),
            prompts: Some(Default::default()),
            resources: Some(Default::default()),
            ..Default::default()
        })
        .build(transport)?;

    server.run(signal::ctrl_c()).await?;

    Ok(())
}

其中 ServerCapabilities 是向客户端声明的能力开关:toolspromptsresources 分别对应 MCP 协议的三类核心能力,按需启用即可。server.run(signal::ctrl_c()) 让服务在收到 Ctrl+C 信号后优雅退出。

ServerHandler 的实现骨架

ServerHandler 是服务端的核心 trait,需要实现 list_tools / call_tool(以及可选的提示词、资源相关方法)。在接入工具路由后,典型实现如下:

use rmcp::{
    model::*,
    protocol::*,
    server::{RequestContext, ServerHandler, RoleServer, ToolRouter},
    ErrorData,
};

pub struct MyServerHandler {
    tool_router: ToolRouter,
}

#[async_trait::async_trait]
impl ServerHandler for MyServerHandler {
    async fn list_tools(
        &self,
        _request: Option<PaginatedRequestParam>,
        _context: RequestContext<RoleServer>,
    ) -> Result<ListToolsResult, ErrorData> {
        let items = self.tool_router.list_all();
        Ok(ListToolsResult::with_all_items(items))
    }

    async fn call_tool(
        &self,
        request: CallToolRequestParam,
        context: RequestContext<RoleServer>,
    ) -> Result<CallToolResult, ErrorData> {
        let tcc = ToolCallContext::new(self, request, context);
        self.tool_router.call(tcc).await
    }
}

从源码结构看,ToolRouter 承担了"工具注册表 + 分发器"的双重职责:list_all() 汇总所有已注册工具,call() 则根据请求中的工具名完成参数解析与调用。

工具开发:过程宏驱动的声明式实现

使用 #[tool] 宏定义工具

rmcp-macros#[tool] 宏是开发工具的最快路径。以下是一个带类型化参数的算术工具(与 agents/rust-mcp-expert.agent.md 示例一致):

use rmcp::tool;
use rmcp::model::Parameters;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

#[derive(Debug, Deserialize, JsonSchema)]
pub struct CalculateParams {
    pub a: f64,
    pub b: f64,
    pub operation: String,
}

#[tool(
    name = "calculate",
    description = "Performs basic arithmetic operations",
    annotations(read_only_hint = true, idempotent_hint = true)
)]
pub async fn calculate(params: Parameters<CalculateParams>) -> Result<f64, String> {
    let p = params.inner();
    match p.operation.as_str() {
        "add" => Ok(p.a + p.b),
        "subtract" => Ok(p.a - p.b),
        "multiply" => Ok(p.a * p.b),
        "divide" if p.b != 0.0 => Ok(p.a / p.b),
        "divide" => Err("Division by zero".to_string()),
        _ => Err(format!("Unknown operation: {}", p.operation)),
    }
}

要点解读:

  • Parameters<T> 包装params.inner() 取出反序列化后的 TT 同时派生 DeserializeJsonSchema,保证"反序列化 + Schema 生成"一条龙;
  • 返回值即工具结果Result<f64, String>Ok 会被封装为正常工具结果,Err 则映射为工具错误,无需手写 JSON 拼装;
  • 注解(annotations)read_only_hintidempotent_hint 向客户端声明工具的副作用语义,帮助大模型决定是否调用以及如何调用。

工具注解的完整取值

注解可以组合表达工具的调用语义(见 instructions/rust-mcp-server.instructions.md):

// 破坏性操作:明确声明 destructive + 非只读 + 非幂等
#[tool(
    name = "delete_file",
    annotations(
        destructive_hint = true,
        read_only_hint = false,
        idempotent_hint = false
    )
)]
pub async fn delete_file(params: Parameters<DeleteParams>) -> Result<(), String> { /* ... */ }

// 只读查询:read_only + idempotent + open_world
#[tool(
    name = "search_data",
    annotations(
        read_only_hint = true,
        idempotent_hint = true,
        open_world_hint = true
    )
)]
pub async fn search_data(params: Parameters<SearchParams>) -> Vec<String> { /* ... */ }

返回富内容(Rich Content)

工具不仅可返回字符串,还能返回结构化的多段内容:

use rmcp::model::{ToolResponseContent, TextContent, ImageContent};

#[tool]
async fn analyze_code(params: Parameters<CodeParams>) -> ToolResponseContent {
    ToolResponseContent::from(vec![
        TextContent::text(format!("Analysis of {}:", params.inner().filename)),
        TextContent::text("No issues found."),
    ])
}

ToolResponseContent 支持 TextContentImageContent 等 MCP 内容类型,为向客户端返回文本、图片等多媒体结果提供了统一出口。

使用 #[tool_router]#[tool_handler] 组织多个工具

当工具数量增多时,可以用 #[tool_router] 将一组工具聚合到同一实现类型上:

use rmcp::{tool_router, tool_handler};
use rmcp::server::{ServerHandler, ToolRouter};

pub struct MyHandler {
    state: ServerState,
    tool_router: ToolRouter,
}

#[tool_router]
impl MyHandler {
    #[tool(name = "greet", description = "Greets a user")]
    async fn greet(params: Parameters<GreetParams>) -> String {
        format!("Hello, {}!", params.inner().name)
    }

    #[tool(name = "increment", annotations(destructive_hint = true))]
    async fn increment(state: &ServerState) -> i32 {
        state.increment().await
    }

    pub fn new() -> Self {
        Self {
            state: ServerState::new(),
            tool_router: Self::tool_router(),
        }
    }
}

#[tool_handler]
impl ServerHandler for MyHandler {
    // Prompt 与 Resource 处理器...
}

从宏的实现逻辑可以推断:#[tool_router] 会在 impl 块内扫描所有 #[tool] 标记的方法,自动生成 tool_router() 构造函数;#[tool_handler] 则把宏生成的路由逻辑嫁接到 ServerHandler trait 实现上。值得注意的细节是,工具方法可以直接接收 &ServerState 参数,宏会将其解释为从处理器实例借用共享状态。

Prompt 与 Resource:补齐 MCP 三大能力

提示词处理器(Prompts)

提示词能力由 list_promptsget_prompt 两个方法承载:

async fn list_prompts(
    &self,
    _request: Option<PaginatedRequestParam>,
    _context: RequestContext<RoleServer>,
) -> Result<ListPromptsResult, ErrorData> {
    let prompts = vec![
        Prompt {
            name: "code-review".to_string(),
            description: Some("Review code for best practices".to_string()),
            arguments: Some(vec![
                PromptArgument {
                    name: "language".to_string(),
                    description: Some("Programming language".to_string()),
                    required: Some(true),
                },
                PromptArgument {
                    name: "code".to_string(),
                    description: Some("Code to review".to_string()),
                    required: Some(true),
                },
            ]),
        },
    ];
    Ok(ListPromptsResult { prompts })
}

async fn get_prompt(
    &self,
    request: GetPromptRequestParam,
    _context: RequestContext<RoleServer>,
) -> Result<GetPromptResult, ErrorData> {
    match request.name.as_str() {
        "code-review" => {
            let args = request.arguments.as_ref()
                .ok_or_else(|| ErrorData::invalid_params("arguments required"))?;
            let language = args.get("language")
                .ok_or_else(|| ErrorData::invalid_params("language required"))?;
            let code = args.get("code")
                .ok_or_else(|| ErrorData::invalid_params("code required"))?;

            Ok(GetPromptResult {
                description: Some(format!("Code review for {}", language)),
                messages: vec![
                    PromptMessage::user(format!(
                        "Review this {} code for best practices:\n\n{}",
                        language, code
                    )),
                ],
            })
        }
        _ => Err(ErrorData::invalid_params("Unknown prompt")),
    }
}

模式小结:list_prompts 负责声明可用的提示词模板及其参数;get_prompt 按名称取出模板,把客户端传入的 arguments 注入到 PromptMessage 中。参数缺失时统一使用 ErrorData::invalid_params 返回协议级错误。

资源处理器(Resources)

资源能力通过 list_resources / read_resource 实现,资源以 URI 寻址,携带 MIME 类型:

async fn list_resources(
    &self,
    _request: Option<PaginatedRequestParam>,
    _context: RequestContext<RoleServer>,
) -> Result<ListResourcesResult, ErrorData> {
    let resources = vec![
        Resource {
            uri: "file:///config/settings.json".to_string(),
            name: "Server Settings".to_string(),
            description: Some("Server configuration".to_string()),
            mime_type: Some("application/json".to_string()),
        },
    ];
    Ok(ListResourcesResult { resources })
}

async fn read_resource(
    &self,
    request: ReadResourceRequestParam,
    _context: RequestContext<RoleServer>,
) -> Result<ReadResourceResult, ErrorData> {
    match request.uri.as_str() {
        "file:///config/settings.json" => {
            let settings = self.load_settings().await
                .map_err(|e| ErrorData::internal_error(e.to_string()))?;
            let json = serde_json::to_string_pretty(&settings)
                .map_err(|e| ErrorData::internal_error(e.to_string()))?;

            Ok(ReadResourceResult {
                contents: vec![
                    ResourceContents::text(json)
                        .with_uri(request.uri)
                        .with_mime_type("application/json"),
                ],
            })
        }
        _ => Err(ErrorData::invalid_params("Unknown resource")),
    }
}

ResourceContents::text(...).with_uri(...).with_mime_type(...) 的链式调用表明内容载体与 URI、MIME 元数据可以灵活组合,同一资源可返回文本或二进制(如图片)内容。

传输层:Stdio、SSE、Streamable HTTP 与自定义传输

MCP 服务端支持多种传输方式,插件文档与指令文档给出了完整示例:

Stdio(CLI 集成首选)

use rmcp::transport::StdioTransport;

let transport = StdioTransport::new();
let server = Server::builder()
    .with_handler(handler)
    .build(transport)?;
server.run(signal::ctrl_c()).await?;

Stdio 通过标准输入输出通信,是最适合本地 CLI 工具与桌面客户端(如 Claude Desktop)的传输方式。

SSE(Server-Sent Events)

use rmcp::transport::SseServerTransport;
use std::net::SocketAddr;

let addr: SocketAddr = "127.0.0.1:8000".parse()?;
let transport = SseServerTransport::new(addr);
let server = Server::builder()
    .with_handler(handler)
    .build(transport)?;
server.run(signal::ctrl_c()).await?;

SSE 基于 HTTP 长连接单向推送,适用于远程部署场景。

Streamable HTTP(配合 Axum)

use rmcp::transport::StreamableHttpTransport;
use axum::{Router, routing::post};

let transport = StreamableHttpTransport::new();
let app = Router::new()
    .route("/mcp", post(transport.handler()));

let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
axum::serve(listener, app).await?;

这是现代 MCP 推荐的方式:借助 axum 路由将 /mcp 端点交给 StreamableHttpTransport::handler(),支持请求-响应与流式响应两种模式,天然适配 HTTPS、负载均衡等基础设施。

自定义传输(TCP / Unix Socket / WebSocket)

use rmcp::transport::Transport;
use tokio::net::TcpListener;
// TCP、Unix Socket、WebSocket 的自定义实现可参考 SDK 的 examples/transport/ 目录

Transport trait 是 rmcp 对传输层的抽象,接入新协议只需实现该 trait,服务端业务逻辑无需改动。

状态管理与错误处理

基于 Arc + RwLock 的共享状态

MCP 服务端通常要处理并发的工具调用,官方推荐 Arc<RwLock<T>> 作为共享状态容器:

use std::sync::Arc;
use tokio::sync::RwLock;
use std::collections::HashMap;

#[derive(Clone)]
pub struct ServerState {
    counter: Arc<RwLock<i32>>,
    cache: Arc<RwLock<HashMap<String, String>>>,
}

impl ServerState {
    pub fn new() -> Self {
        Self {
            counter: Arc::new(RwLock::new(0)),
            cache: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    pub async fn increment(&self) -> i32 {
        let mut counter = self.counter.write().await;
        *counter += 1;
        *counter
    }

    pub async fn set_cache(&self, key: String, value: String) {
        let mut cache = self.cache.write().await;
        cache.insert(key, value);
    }

    pub async fn get_cache(&self, key: &str) -> Option<String> {
        let cache = self.cache.read().await;
        cache.get(key).cloned()
    }
}

设计要点:#[derive(Clone)] 使状态可以跨任务克隆共享;读多写少的场景用 RwLock(读锁可并发),写多读少则改用 Mutex;要求更高的并发哈希表场景可评估 DashMap

双层错误模型:anyhow 与 ErrorData

指令文档明确了错误处理的分工:

  • 应用层错误用 anyhow:负责文件读取、JSON 解析等内部操作,借助 .context() 提供上下文信息;
use anyhow::{Context, Result};

async fn load_config() -> Result<Config> {
    let content = tokio::fs::read_to_string("config.json")
        .await
        .context("Failed to read config file")?;
    let config: Config = serde_json::from_str(&content)
        .context("Failed to parse config")?;
    Ok(config)
}
  • 协议层错误用 ErrorData:凡是返回给 MCP 客户端的错误必须转换为 ErrorData,常用构造方法有 ErrorData::invalid_params(...)(参数非法)与 ErrorData::internal_error(...)(服务端内部错误)。
async fn call_tool(
    &self,
    request: CallToolRequestParam,
    context: RequestContext<RoleServer>,
) -> Result<CallToolResult, ErrorData> {
    if request.name.is_empty() {
        return Err(ErrorData::invalid_params("Tool name cannot be empty"));
    }
    let result = self.execute_tool(&request.name, request.arguments)
        .await
        .map_err(|e| ErrorData::internal_error(e.to_string()))?;

    Ok(CallToolResult {
        content: vec![TextContent::text(result)],
        is_error: Some(false),
    })
}

进阶能力:进度通知与 OAuth 鉴权

进度通知

长耗时操作(如大文件处理)应通过 context.notify_progress(...) 向客户端推送进度:

use rmcp::model::ProgressNotification;

#[tool]
async fn process_large_file(
    params: Parameters<ProcessParams>,
    context: RequestContext<RoleServer>,
) -> Result<String, String> {
    let total = 100;
    for i in 0..=total {
        // Do work...
        if i % 10 == 0 {
            context.notify_progress(ProgressNotification {
                progress: i,
                total: Some(total),
            }).await.ok();
        }
    }
    Ok("Processing complete".to_string())
}

这里的关键是工具方法可以额外注入 context: RequestContext<RoleServer> 参数,宏会自动注入运行时上下文。

OAuth 集成

面向外部访问的服务端可启用 OAuth:

use rmcp::oauth::{OAuthConfig, OAuthProvider};

let oauth_config = OAuthConfig {
    authorization_endpoint: "https://auth.example.com/authorize".to_string(),
    token_endpoint: "https://auth.example.com/token".to_string(),
    client_id: env::var("CLIENT_ID")?,
    client_secret: env::var("CLIENT_SECRET")?,
    scopes: vec!["read".to_string(), "write".to_string()],
};

let oauth_provider = OAuthProvider::new(oauth_config);
// 完整实现可参考 SDK examples/servers/complex_auth_sse.rs

注意 client_id / client_secret 应从环境变量注入,避免硬编码泄密。

测试策略:单元测试与集成测试

工具单元测试

直接以 tokio::test 驱动工具函数(见 instructions/rust-mcp-server.instructions.md):

#[cfg(test)]
mod tests {
    use super::*;
    use rmcp::model::Parameters;

    #[tokio::test]
    async fn test_calculate_add() {
        let params = Parameters::new(CalculateParams {
            a: 5.0,
            b: 3.0,
            operation: "add".to_string(),
        });
        let result = calculate(params).await.unwrap();
        assert_eq!(result, 8.0);
    }

    #[tokio::test]
    async fn test_divide_by_zero() {
        let params = Parameters::new(CalculateParams {
            a: 5.0,
            b: 0.0,
            operation: "divide".to_string(),
        });
        assert!(calculate(params).await.is_err());
    }
}

处理器集成测试

ServerHandler 层做端到端验证,例如断言工具列表内容:

#[tokio::test]
async fn test_server_list_tools() {
    let handler = MyServerHandler::new();
    let context = RequestContext::default();

    let result = handler.list_tools(None, context).await.unwrap();

    assert!(!result.tools.is_empty());
    assert!(result.tools.iter().any(|t| t.name == "calculate"));
}

rust-mcp-server-generator 生成的脚手架还会附赠覆盖 list_toolscall_toollist_promptslist_resources 的完整集成测试模板(见 skills/rust-mcp-server-generator/SKILL.md),生成后直接 cargo test 即可运行。

性能优化建议

专家智能体总结了四条可落地的性能建议:

  1. 按场景选锁:读多写少用 RwLock,写多读少用 Mutex,高并发哈希表考虑 DashMap
  2. 缩短持锁时间:不要在持有锁的临界区内执行异步操作,先克隆数据再释放锁:
// 推荐:锁内克隆,锁外处理
let value = {
    let data = self.data.read().await;
    data.clone()
};
process(value).await;

// 不推荐:锁内 await,锁持有时间过长
let data = self.data.read().await;
process(&*data).await;
  1. 使用有缓冲通道tokio::sync::mpsc::channel(100) 提升生产者-消费者吞吐;
  2. 批量并行处理:用 futures::future::join_all 并发执行独立任务:
async fn batch_process(&self, items: Vec<Item>) -> Vec<Result<(), Error>> {
    use futures::future::join_all;
    join_all(items.into_iter().map(|item| self.process(item))).await
}

日志与可观测性

tracing 统一埋点,服务启动时初始化订阅器:

fn init_logging() {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::DEBUG)
        .with_target(false)
        .with_thread_ids(true)
        .init();
}

#[tool]
async fn my_tool(params: Parameters<MyParams>) -> String {
    debug!("Tool called with params: {:?}", params);
    info!("Processing request");
    // Tool logic...
    info!("Request completed");
    "Done".to_string()
}

运行时可借助环境变量动态调整级别:RUST_LOG=debug cargo run

部署:跨平台编译、Docker 与客户端接入

发布版二进制与跨平台编译

# 原生发布构建
cargo build --release --target x86_64-unknown-linux-gnu
cargo build --release --target x86_64-pc-windows-msvc
cargo build --release --target x86_64-apple-darwin

# 使用 cross 交叉编译(无需目标平台工具链)
cargo install cross
cross build --release --target aarch64-unknown-linux-gnu

Docker 多阶段构建

FROM rust:1.75 as builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src ./src
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my-mcp-server /usr/local/bin/
CMD ["my-mcp-server"]

第二阶段仅保留运行所需的最小系统镜像与 ca-certificates(保证 TLS 访问正常),符合镜像瘦身的最佳实践。

在 MCP 客户端中注册服务端

以 Claude Desktop 为例,在配置中注册 Stdio 类型的服务端:

{
  "mcpServers": {
    "my-rust-server": {
      "command": "/path/to/target/release/my-mcp-server",
      "args": []
    }
  }
}

对于支持 HTTP 的服务端,command / args 亦可替换为 SSE 或 Streamable HTTP 的 URL 配置。

一键生成:/rust-mcp-development:rust-mcp-server-generator 实战

如果不想从零手写,可以直接在 Copilot 会话中调用插件的斜杠命令生成完整项目。生成器(skills/rust-mcp-server-generator/SKILL.md)会先向用户收集五项需求:

  1. 项目名称(如 my-mcp-server);
  2. 服务端描述(如 "A weather data MCP server");
  3. 传输类型(stdio、sse、http 或全部);
  4. 要包含的工具(如 "weather lookup"、"forecast"、"alerts");
  5. 是否包含提示词与资源

随后生成覆盖 Cargo.toml.gitignoreREADME.mdsrc/main.rssrc/handler.rssrc/state.rssrc/tools/src/prompts/src/resources/tests/integration_test.rs 的完整工程,其中 Cargo.toml 已按 feature 开关组织 http 传输依赖,main.rs 默认使用 Stdio 传输,handler.rs 通过 #[tool_router]#[tool_handler] 组装工具、提示词与资源。生成后依次执行:

cd {project-name}
cargo build
cargo test
cargo run

即可完成从生成到运行验证的闭环。

核心原则速览

结合 agents/rust-mcp-expert.agent.md 的总结,开发时应坚持以下原则:

  1. 类型安全优先:所有工具参数都派生 JsonSchema
  2. 全异步:所有处理器必须为 async,绝不阻塞 tokio 运行时;
  3. 正确错误处理:统一使用 Result 类型与 ErrorData 协议错误;
  4. 测试覆盖:工具配单元测试,处理器配集成测试;
  5. 文档完备:所有公开项添加 doc 注释;
  6. 性能意识:关注并发模型与锁竞争;
  7. 符合 Rust 惯例:遵循所有权、生命周期与 async 的惯用法。

参考资源(仓库内)

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
927
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.89 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
602
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
396
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
526