使用 rmcp 官方 SDK 构建 Rust MCP Server:Awesome Copilot 仓库实践指南
本文基于 awesome-copilot 仓库中的 rust-mcp-server.instructions.md 开发规范,结合仓库内置的 rust-mcp-server-generator 技能、rust-mcp-expert Agent 与 rust-mcp-development 插件,系统讲解如何用官方
rmcpSDK 以 async/await 模式构建生产可用的 Model Context Protocol(MCP)服务器。读完本文,你将掌握从依赖配置、服务端骨架、宏化 Tool/Prompt/Resource 开发,到多种传输协议、错误处理、测试、性能优化与跨平台部署的完整链路,能够独立生成并交付一个类型安全的 Rust MCP Server 项目。
一、环境准备与依赖配置
在 Rust 生态中构建 MCP Server,核心依赖是官方 SDK rmcp(Rust Model Context Protocol 实现)。rust-mcp-server.instructions.md 给出了最小依赖集,你可以在 Cargo.toml 中按需组合。
1.1 基础依赖
[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"
各依赖在工程中的职责:
rmcp(启用serverfeature):提供Server、ServerHandler、ServerCapabilities、ToolRouter等核心服务端构件,以及ErrorData、各类请求/响应模型;tokio(fullfeatures):异步运行时,支撑#[tokio::main]、signal::ctrl_c()、异步 I/O 与锁;serde/serde_json:Tool 参数的序列化/反序列化与 JSON 编解码;anyhow:应用层错误的上抛与上下文增强(配合.context());tracing/tracing-subscriber:结构化日志与可观测性。
1.2 宏支持依赖
为了使用声明式宏简化 Tool 开发,还需引入宏与 JSON Schema 生成依赖:
[dependencies]
rmcp-macros = "0.8"
schemars = { version = "0.8", features = ["derive"] }
rmcp-macros提供#[tool]、#[tool_router]、#[tool_handler]三个过程宏;schemars为 Tool 参数结构体自动生成 JSON Schema,供 MCP 客户端理解参数契约,是实现类型安全与自动参数校验的基础。
1.3 生产级模板:HTTP 传输的可选依赖与特性开关
仓库内置的 rust-mcp-server-generator 技能 在生成项目时给出了更完整的 Cargo.toml 模板,其通过 [features] 将 HTTP 相关依赖做成可选项,避免基础版本膨胀:
[dependencies]
rmcp = { version = "0.8.1", features = ["server"] }
rmcp-macros = "0.8"
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"
schemars = { version = "0.8", features = ["derive"] }
async-trait = "0.1"
# Optional: for HTTP transports
axum = { version = "0.7", optional = true }
tower-http = { version = "0.5", features = ["cors"], optional = true }
[dev-dependencies]
tokio-test = "0.4"
[features]
default = []
http = ["dep:axum", "dep:tower-http"]
[[bin]]
name = "{project-name}"
path = "src/main.rs"
要点说明:
async-trait用于为ServerHandler的异步 trait 方法提供支持;axum与tower-http(含 CORS)作为可选依赖,仅在启用httpfeature 时编译,对应文档中的 SSE/Streamable HTTP 传输场景;tokio-test作为 dev-dependency,用于测试环境;- 显式声明
[[bin]],保证cargo run指向src/main.rs。
二、项目结构规划
文档建议按“能力模块”组织源码,这与 rust-mcp-server-generator 生成的骨架一致:
my-mcp-server/
├── Cargo.toml
├── src/
│ ├── main.rs # Server entry point
│ ├── handler.rs # ServerHandler implementation
│ ├── tools/
│ │ ├── mod.rs
│ │ ├── calculator.rs
│ │ └── greeter.rs
│ ├── prompts/
│ │ ├── mod.rs
│ │ └── code_review.rs
│ └── resources/
│ ├── mod.rs
│ └── data.rs
└── tests/
└── integration_tests.rs
生成器模板在此基础上额外补充了 src/state.rs(共享状态模块)、.gitignore、README.md,并把 tests/integration_test.rs 用作端到端集成测试,形成一套可直接落地的工程化布局。README 中还会给出 Claude Desktop 等客户端的 JSON 接入配置,方便生成后立刻联调。
三、服务端实现
3.1 基本服务搭建(stdio 传输)
在 main.rs 中创建基于 stdio 传输的服务器,[rust-mcp-server.instructions.md](https://gitcode.com/GitHub_Trending/aw/awesome-copilot/blob/87ba8b1780d0e2655fc19fa3f8d4fc7879881744/instructions/rust-mcp-server.instructions.md?utm_source=gitcode_repo_files) 提供的入口代码如下:
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(())
}
这段代码的语义拆解:
StdioTransport::new()创建标准输入/输出传输,让服务可直接被本地 MCP 客户端以子进程方式拉起;ServerCapabilities通过三个字段声明服务器对外暴露的能力维度——tools、prompts、resources,Some(Default::default())表示启用对应能力并使用默认配置;Server::builder().with_handler(handler).with_capabilities(...)组装处理器与能力声明;server.run(signal::ctrl_c())以异步方式持续服务,收到 Ctrl+C 信号后优雅退出。
3.2 ServerHandler 实现
处理器是 MCP Server 的核心,必须实现 rmcp::server::ServerHandler trait。文档中的手写实现如下:
use rmcp::{
model::*,
protocol::*,
server::{RequestContext, ServerHandler, RoleServer},
ErrorData,
};
pub struct MyServerHandler {
tool_router: ToolRouter,
}
impl MyServerHandler {
pub fn new() -> Self {
Self {
tool_router: Self::create_tool_router(),
}
}
fn create_tool_router() -> ToolRouter {
// Initialize and return tool router
ToolRouter::new()
}
}
#[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作为 Tool 注册与分发的中央路由,list_tools时调用list_all()返回全部工具,call_tool时构造ToolCallContext交由路由器执行; - 每个 trait 方法都接收
RequestContext<RoleServer>,其中包含会话上下文与进度通知通道(详见后文“进度通知”); - 返回值统一为
Result<_, ErrorData>,确保协议层错误语义一致。
从仓库的 rust-mcp-server-generator 技能 生成模板可见,更推荐的组合方式是:结构体持有 state: ServerState 与 tool_router: ToolRouter,用 #[tool_router] 宏把工具方法自动生成路由注册表,再用 #[tool_handler] 宏自动生成 ServerHandler 的 list_tools/call_tool 胶水代码,从而省去上例中手写 trait 的样板:
#[tool_router]
impl McpHandler {
#[tool(name = "example_tool", description = "An example tool",
annotations(read_only_hint = true))]
async fn example_tool(params: Parameters<tools::ExampleParams>) -> Result<String, String> {
tools::example::execute(params).await
}
pub fn new() -> Self {
Self {
state: ServerState::new(),
tool_router: Self::tool_router(),
}
}
}
#[tool_handler]
#[async_trait]
impl ServerHandler for McpHandler {
// Prompt and resource handlers...
}
四、Tool 开发
4.1 用 #[tool] 宏声明式定义工具
文档推荐使用 rmcp::tool 宏把普通 async 函数变成 MCP Tool,参数结构体只需派生 Deserialize 与 JsonSchema 即可获得自动化的参数 Schema 与反序列化:
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,
}
/// Performs mathematical calculations
#[tool(
name = "calculate",
description = "Performs basic arithmetic operations",
annotations(read_only_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 {
Err("Division by zero".to_string())
} else {
Ok(p.a / p.b)
}
}
_ => Err(format!("Unknown operation: {}", p.operation)),
}
}
关键点:
Parameters<T>是参数包装类型,params.inner()取出反序列化后的T;- 函数上的
///文档注释会并入 Tool 描述,description与name属性可覆盖或补充; - 返回
Result<T, String>,其中Err的字符串会成为对调用方可见的错误信息,如除零、未知操作符。
4.2 用 #[tool_router] 聚合多个工具
当工具数量变多时,文档展示了用 #[tool_router] + #[tool_handler] 组合在一个结构体上批量注册工具的方式:
use rmcp::{tool_router, tool_handler};
pub struct ToolsHandler {
tool_router: ToolRouter,
}
#[tool_router]
impl ToolsHandler {
#[tool]
async fn greet(params: Parameters<GreetParams>) -> String {
format!("Hello, {}!", params.inner().name)
}
#[tool(annotations(destructive_hint = true))]
async fn reset_counter() -> String {
"Counter reset".to_string()
}
pub fn new() -> Self {
Self {
tool_router: Self::tool_router(),
}
}
}
#[tool_handler]
impl ServerHandler for ToolsHandler {
// Other handler methods...
}
值得注意的细节:
- 宏会为结构体生成
tool_router()关联函数,new()中通过Self::tool_router()完成路由表初始化; - 无参数工具(如
reset_counter)可直接省略params参数; - 无副作用、只读的工具应标注
read_only_hint,而会修改状态的工具(如重置计数器)标注destructive_hint,帮助 MCP 客户端(以及 Copilot 等 AI 客户端)判断调用风险。
在 rust-mcp-expert Agent 中,还演示了带共享状态的工具写法——工具方法可以直接接收 &ServerState 引用作为参数:
#[tool(name = "increment", annotations(destructive_hint = true))]
async fn increment(state: &ServerState) -> i32 {
state.increment().await
}
4.3 Tool 注解(Annotations)的语义
Tool 注解是面向 MCP 客户端的行为提示,文档给出了两类典型组合:
#[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> {
// Delete file logic
}
#[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> {
// Search logic
}
三个 hint 的含义:
read_only_hint:标记只读操作(查询、搜索),客户端可安全地重复调用;destructive_hint:标记破坏性操作(删除、重置),客户端会谨慎处理并可能要求确认;idempotent_hint:标记幂等操作,重复执行结果一致,可安全重试;open_world_hint:标记“开放世界”工具(如数据搜索),结果随外部数据变化,不可缓存。
4.4 返回富内容
工具不仅能返回纯字符串,还能返回结构化内容列表。文档展示了使用 ToolResponseContent 组合多条 TextContent:
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."),
])
}
从导入可见,ImageContent 等类型同样可用于返回图片类内容,使工具能够向客户端交付多模态结果,而不仅是文本。
五、Prompt 实现
MCP 的 Prompt 能力让服务端向客户端提供可复用的提示词模板。文档实现 list_prompts 与 get_prompt 两个处理器方法:
use rmcp::model::{Prompt, PromptArgument, PromptMessage, GetPromptResult};
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),
},
]),
},
];
Ok(ListPromptsResult { prompts })
}
async fn get_prompt(
&self,
request: GetPromptRequestParam,
_context: RequestContext<RoleServer>,
) -> Result<GetPromptResult, ErrorData> {
match request.name.as_str() {
"code-review" => {
let language = request.arguments
.as_ref()
.and_then(|args| args.get("language"))
.ok_or_else(|| ErrorData::invalid_params("language required"))?;
Ok(GetPromptResult {
description: Some("Code review prompt".to_string()),
messages: vec![
PromptMessage::user(format!(
"Review this {} code for best practices and suggest improvements",
language
)),
],
})
}
_ => Err(ErrorData::invalid_params("Unknown prompt")),
}
}
实现要点:
PromptArgument描述参数(名称、说明、是否必填),required: Some(true)表示必填;get_prompt按request.name分发,参数缺失或未知 prompt 时统一返回ErrorData::invalid_params;- 使用
PromptMessage::user(...)构造用户角色的消息内容。
rust-mcp-expert Agent 给出了更复杂的多参数示例(如 code-review 同时要求 language 与 code 两个参数,并把用户代码拼入消息体),说明同一模式可轻松扩展为任意参数化模板。
六、Resource 实现
Resource 让服务器向客户端暴露结构化数据(文件、配置、数据集)。文档示例:
use rmcp::model::{Resource, ResourceContents, ReadResourceResult};
async fn list_resources(
&self,
_request: Option<PaginatedRequestParam>,
_context: RequestContext<RoleServer>,
) -> Result<ListResourcesResult, ErrorData> {
let resources = vec![
Resource {
uri: "file:///data/config.json".to_string(),
name: "Configuration".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:///data/config.json" => {
let content = r#"{"version": "1.0", "enabled": true}"#;
Ok(ReadResourceResult {
contents: vec![
ResourceContents::text(content.to_string())
.with_uri(request.uri)
.with_mime_type("application/json"),
],
})
}
_ => Err(ErrorData::invalid_params("Unknown resource")),
}
}
关键细节:
Resource通过uri(协议化资源标识符)、name、description、mime_type描述资源元数据;read_resource依据request.uri分发,返回的ResourceContents::text(...)通过.with_uri()与.with_mime_type()补齐内容元数据;- rust-mcp-expert Agent 进一步演示了从共享状态加载设置并以
serde_json::to_string_pretty序列化后返回的写法,ErrorData::internal_error负责把内部错误映射为协议错误。
七、传输(Transport)选项
rmcp 支持多种传输方式,覆盖本地 CLI、远程 HTTP 与流式场景。
7.1 Stdio 传输(本地 CLI 集成)
use rmcp::transport::StdioTransport;
let transport = StdioTransport::new();
let server = Server::builder()
.with_handler(handler)
.build(transport)?;
这是最简单的模式,客户端以子进程方式启动服务并通过标准输入输出通信,适合 Claude Desktop、VS Code 等本地客户端集成。
7.2 SSE 传输(HTTP 事件流)
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 长连接方式暴露,客户端通过 Server-Sent Events 接收服务端推送。
7.3 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?;
Streamable HTTP 是最现代的 MCP 传输形态:服务通过 Axum 路由把 /mcp 端点交给 transport.handler() 处理,同时支持流式响应。注意:此模式需要启用 http feature(对应生成器模板中的 axum/tower-http 可选依赖),运行时用 cargo run --features http 启动。
7.4 自定义传输
use rmcp::transport::Transport;
use tokio::net::TcpListener;
// See examples/transport/ for TCP, Unix Socket, WebSocket implementations
Transport trait 是扩展点,TCP、Unix Socket、WebSocket 等传输均可按需实现;rust-mcp-expert Agent 的能力清单同样覆盖 Stdio、SSE、HTTP、WebSocket、TCP、Unix Socket 六类传输的咨询支持。
八、错误处理
8.1 协议层:ErrorData
ErrorData 是 MCP 协议层的错误载体,与 ServerHandler 方法的 Result<_, ErrorData> 返回类型严格对应:
use rmcp::ErrorData;
fn validate_params(value: &str) -> Result<(), ErrorData> {
if value.is_empty() {
return Err(ErrorData::invalid_params("Value cannot be empty"));
}
Ok(())
}
async fn call_tool(
&self,
request: CallToolRequestParam,
context: RequestContext<RoleServer>,
) -> Result<CallToolResult, ErrorData> {
validate_params(&request.name)?;
// Tool execution...
Ok(CallToolResult {
content: vec![TextContent::text("Success")],
is_error: Some(false),
})
}
ErrorData::invalid_params(...)表示参数类错误,其余还包括internal_error(...)等构造器(rust-mcp-expert Agent 中有明确使用示例);- 成功的
CallToolResult显式携带is_error: Some(false),向客户端表明执行成功。
8.2 应用层:anyhow
对服务器内部的非协议错误(文件读取、配置解析、网络请求),文档推荐用 anyhow 携带上下文逐层上抛:
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)
}
anyhow::Context 为底层错误追加“在哪一步失败”的说明,最终可在边界处用 ErrorData::internal_error(e.to_string()) 转换为协议错误(rust-mcp-expert Agent 的错误处理示例展示了这一完整链路)。
九、测试策略
9.1 单元测试(工具级)
文档为 calculate 工具编写了直接调用函数并断言返回值的测试:
#[cfg(test)]
mod tests {
use super::*;
#[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(),
});
let result = calculate(params).await;
assert!(result.is_err());
}
}
由于工具本身就是普通 async 函数,Parameters::new(...) 直接构造入参即可测试,无需启动完整服务器。生成器模板的工具模块(tools/example.rs)同样内嵌 #[cfg(test)] 单元测试,保持这一约定。
9.2 集成测试(处理器级)
集成测试直接实例化 ServerHandler 并调用其 trait 方法,验证完整服务器行为:
#[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 的 tests/integration_test.rs 模板把这一模式扩展为四类断言:list_tools 非空且包含目标工具、call_tool 返回 Ok、list_prompts 非空、list_resources 非空,覆盖了 Handler 的四大能力入口。由于 McpHandler 被放入 crate 根模块,集成测试可 use my_mcp_server::handler::McpHandler 直接引用。
十、进度通知
对于耗时操作,服务器应通过 RequestContext 发送进度通知,让客户端感知执行进度:
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())
}
要点:工具方法把 RequestContext<RoleServer> 作为额外参数即可获得通知能力;ProgressNotification 携带 progress(当前进度)与 total(总量,可选);每完成 10% 上报一次,避免通知风暴。文档强调发送失败用 .ok() 容忍(通知是尽力而为的)。
十一、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);
OAuthConfig声明授权端点、令牌端点、客户端凭据与 scope;client_id/client_secret从环境变量读取,避免硬编码泄露;- 完整示例可参考官方 rust-sdk 示例中的 complex_auth_sse 实现(文档原文指向外部示例,此处仅作实现思路说明)。
十二、性能最佳实践
12.1 全程异步化
所有处理器与工具方法都应保持 async,阻塞 I/O 场景使用 tokio 的异步版本:
#[tool]
async fn fetch_data(params: Parameters<FetchParams>) -> Result<String, String> {
let client = reqwest::Client::new();
let response = client
.get(¶ms.inner().url)
.send()
.await
.map_err(|e| e.to_string())?;
let text = response.text().await.map_err(|e| e.to_string())?;
Ok(text)
}
网络请求通过 reqwest 异步执行,.await 挂起而不阻塞 tokio 工作线程,确保高并发下吞吐稳定。
12.2 共享状态:Arc + RwLock
跨工具共享的可变状态用 Arc 包裹 RwLock,实现多任务安全访问:
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct ServerState {
counter: Arc<RwLock<i32>>,
}
impl ServerState {
pub fn new() -> Self {
Self {
counter: Arc::new(RwLock::new(0)),
}
}
pub async fn increment(&self) -> i32 {
let mut counter = self.counter.write().await;
*counter += 1;
*counter
}
}
生成器模板的 state.rs 实现 还补充了 get() 只读方法与 #[derive(Clone)](配合 Arc 实现零拷贝克隆共享)。
12.3 锁与并发细节
rust-mcp-expert Agent 的性能建议值得沉淀为工程准则:
- 按负载选锁:读多写少用
RwLock,写多读少用Mutex,高并发哈希表可考虑DashMap; - 缩短持锁时间:不要在持锁状态下执行 async 操作,应先把数据 clone 出锁再处理——例如
let value = { self.data.read().await.clone() };后再做耗时处理; - 使用带缓冲的 channel:如
tokio::sync::mpsc::channel(100)缓冲任务队列; - 批量并发处理:用
futures::future::join_all对一批任务并发执行。
十三、日志与追踪
tracing 提供从结构化日志到分布式追踪的统一抽象,文档给出了初始化与使用示例:
use tracing::{info, warn, error, debug};
use tracing_subscriber;
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()
}
配置项说明:
.with_max_level(DEBUG)设置全局最大日志级别;.with_target(false)隐藏模块路径,日志更清爽;.with_thread_ids(true)输出线程 ID,便于排查并发问题;- 在工具内部用
debug!/info!记录入参与执行阶段,运行时可通过RUST_LOG=debug cargo run(生成器 README 中的方式)动态控制日志详略。
十四、部署与分发
14.1 发布二进制
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
14.2 交叉编译
使用 cross 工具在单一构建机上产出多平台产物:
cargo install cross
cross build --release --target aarch64-unknown-linux-gnu
rust-mcp-expert Agent 补充了 ARM 目标(aarch64-unknown-linux-gnu)等典型场景,方便为树莓派、ARM 服务器交付。
14.3 Docker 部署
文档给出的 Dockerfile 采用两阶段构建,缩小最终镜像体积:
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates
COPY --from=builder /app/target/release/my-mcp-server /usr/local/bin/
CMD ["my-mcp-server"]
- 第一阶段用
rust:1.75编译发布产物; - 第二阶段基于
debian:bookworm-slim仅复制二进制与ca-certificates(保证 TLS/HTTPS 调用可用); - rust-mcp-expert Agent 的版本进一步优化了缓存(先拷贝
Cargo.toml Cargo.lock再拷src)并在 RUN 后清理 apt 缓存,值得采纳。
14.4 客户端接入配置
编译完成后,在 MCP 客户端(如 Claude Desktop)的配置文件中以 JSON 注册 stdio 服务器:
{
"mcpServers": {
"{project-name}": {
"command": "path/to/target/release/{project-name}",
"args": []
}
}
}
command 指向发布二进制绝对路径,args 为空数组(无额外参数)。
十五、在 Awesome Copilot 仓库中的配套资源
本指南对应的规范文档是 rust-mcp-server.instructions.md,它声明 applyTo: '**/*.rs',即该规范面向仓库内所有 Rust 文件生效。围绕同一主题,仓库还提供了一整套可直接使用的配套资源:
- rust-mcp-server-generator 技能:一次对话即可生成完整工程——它会询问项目名、服务描述、传输类型(stdio/sse/http/all)、工具清单以及是否需要 prompts/resources,然后按模板产出
Cargo.toml、main.rs、handler.rs、state.rs、tools/、prompts/、resources/、tests/与README.md,生成后执行cargo build && cargo test && cargo run即可运行; - rust-mcp-expert Agent:专门的 MCP Server 开发专家,覆盖 rmcp v0.8+ SDK、宏体系、tokio 异步、serde/JsonSchema 类型安全、六类传输、错误处理、测试、性能优化与部署咨询;
- rust-mcp-development 插件:将上述技能与 Agent 打包为插件,可通过
copilot plugin install rust-mcp-development@awesome-copilot安装,其 plugin.json 声明了/rust-mcp-development:rust-mcp-server-generator斜杠命令与rust-mcp-expertAgent 的关联关系。
三者与规范文档共同构成“规范 + 生成器 + 专家 + 一键安装”的完整开发闭环:规范文档约束写法,生成器输出骨架,专家 Agent 答疑解惑,插件实现分发集成。开发者可以直接以本指南为纲,配合上述资源快速落地自己的 Rust MCP Server。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.2 K634
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown300
jforgamejforgame是一个一站式游戏服务器开发框架。包含游戏服务器开发所需要的各种组件,比如网关,socket服务端与客户端,自定义高效消息编解码,游戏热更新,游戏通用工具等等。包含游戏服,跨服,匹配服,后台管理系统等实现,同时提供大量业务案例以供学习。亦可用于其他socket应用,例如及时聊天等。Java101
fizz-gateway-nodeAn Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。Java60
certd开源SSL证书管理工具;全自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔;https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署JavaScript60
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python280