Aug 08, 2025
2 min read
Rust,
MCP,
AI,
LLM,

使用 Rust 实现 MCP 协议:为大模型构建外部工具插件

本文介绍了 MCP(Model Context Protocol)协议的概念和实现方式,详细讲解了如何使用 Rust 开发一个 MCP 服务,通过实际代码示例展示了 crate 文档查询工具的实现过程,并介绍了在 VS Code 中配置和使用 MCP Server 的方法。

MCP(Model Context Protocol) 协议很早就出来了,但是由于在早期支持 MCP协议 的客户端在国内就没几个,所以也没机会去搞 MCP server。早期 MCP 只有 Claude 自家的客户端支持得最好,但是你没点技术手段,还用不了Claude。

什么是 MCP?

大模型其实没有什么能力,本质上就是输入文本 => 输出文本。但是不妨碍用户在外部定义一些工具函数,让大模型在输出文本的时候,输出特写格式的数据(包括用哪个工具函数,参数是什么),然后再执行指定的工具函数。这就是 Function Call(Tool Call) 的功能。但是其实 Function Call 本质上还是内部函数,并没有什么外部的动态扩展能力。

MCP 本质上就是外部的“Function Call”,Agent 应用的插件。把函数调用做成了外部可拔插的标准化服务,客户端想用哪个服务直接注册即可。

这些能力能玩得转的前提是,大模型要有非常强的指令遵循能力。我主要使用 Qwen 模型,可以肯定的是,Qwen 模型在去年这个时间(2024 年 8 月)没有这个能力,甚至当时国内任何一家的大模型都没有这个能力,直到 DeepSeek V3/R1 的出现。

无论是函数调用还是 MCP,最简单的调用链路大致是这样的:

prompt -> 大模型理解  -> 返回输出
				    -> 判断需要调用工具(或者 mcp)->调用工具(或者 mcp)->合并结果再调用大模型理解 -> 返回输出

使用 Rust 实现一个 MCP 服务是比较简单的,因为 MCP 官方就直接 rust sdk。MCP 使用 json rpc 作为数据交换协议,而传输管道有两种:

  • 标准输入输出 (stdio)
  • 服务器发送事件 (SSE) |(以及后面的stream http)

前者适合本地,后者适合远程服务。

比如我觉得大模型应对 Rust 编程的时候效果太差了,很多时候根本是在胡说八道,无中生有。我希望大模型实现功能如果有使用到某些 crate 时,最好自己去查一下这个 crate 的最新文档,再好好给我干活。

依赖:

rmcp = {version = "0.5.0", features = ["transport-io","macros"]}
#[tool_router]
impl Docs {
    fn new() -> Self {
        Self {
            tool_router: Self::tool_router(),
        }
    }

    #[tool(name = "readme", description = "获取 rust crate 文档的信息")]
    async fn readme(&self, params: Parameters<LibraryRequest>) -> Result<CallToolResult, McpError> {
        let crate_name = params.0.name.as_str();
        let version = params.0.version.as_deref().unwrap_or("latest");
        let docs = reqwest::get(format!("https://docs.rs/{crate_name}/{version}")).await.unwrap().text().await.unwrap();
        Ok(CallToolResult::success(vec![Content::text(docs)]))
    }
}


#[tool_handler]
impl rmcp::ServerHandler for Docs {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            instructions: Some("crate 文档".into()),
            capabilities: ServerCapabilities::builder().enable_tools().build(),
            ..Default::default()
        }
    }
}

这部分就是用户要实现的工具函数。

注册一个 stdin 作为传输层的 mcp server:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create and run the server with STDIO transport
    let service = Docs::new().serve(stdio()).await.inspect_err(|e| {
        println!("Error starting server: {e}");
    })?;
    service.waiting().await?;

    Ok(())
}

如何使用?

据我所知, vscode 上的 ai code 插件现在基本都支持 mcp server。比如国内阿里的 lingma,腾讯的云代码助手,字节的 trae。我们只需要 cargo build 得到二进制包,在上面这些助手里配置 mcp server 即可。阿里的 lingma 配置是最方便的,不过它的插件整体质量一般。