使用说明
Rust-MCP服务器:一个完整的实现
Rust中功能齐全的模型上下文协议(MCP)服务器实现,为LLM集成提供工具、资源和提示。
目录
概述
此Rust MCP服务器实现了 模型上下文协议(MCP) 规范,实现LLM应用程序与外部工具、资源和知识库之间的无缝集成。
什么是MCP?
模型上下文协议是一个开放标准,允许:
- LLM应用 连接到外部数据源和工具
- 服务器 以标准化的方式公开功能(工具、资源、提示)
- 安全集成 无需修改客户端应用程序
关键利益
✅ 类型安全:利用Rust的类型系统确保安全
✅ 高性能:与Tokio异步/等待以实现高并发
✅ 模块化:易于添加自定义工具和资源
✅ 安全:内置验证和错误处理
✅ 基于标准:作为子流程进行简单部署
特性
内置工具
-
问候工具 (
greet)- 用个性化信息问候用户
- 输入:
name(字符串) - 输出:问候语
-
BMI计算器工具 (
calculate-bmi)- 计算体重指数
- 输入:
weightKg(数字),heightM(编号) - 输出:计算的BMI值
-
天气工具 (
fetch-weather)- 获取天气信息(模拟)
- 输入:
city(字符串) - 输出:天气数据(温度、条件、湿度等)
内置资源
- 应用程序配置 (
config://app)- 提供应用程序元数据和设置
- 返回JSON配置
内置提示
- 代码审查 (
review-code)- 为LLM生成检查代码的提示
- 论据:
code(必填),focus(可选:性能、安全性、风格、通用性)
协议支持
- ✅ 符合JSON-RPC 2.0标准
- ✅ 标准传输(换行符分隔的JSON)
- ✅ 使用标准错误代码进行正确的错误处理
- ✅ 记录到stderr
- ✅ 协议版本控制(2024-11-05)
项目结构
mcp-server-rust/
├── Cargo.toml # Project manifest
├── README.md # This file
├── src/
│ ├── main.rs # Entry point
│ ├── lib.rs # Library exports
│ ├── server.rs # MCP server implementation
│ ├── tools/
│ │ ├── mod.rs # Tool definitions
│ │ ├── greeting_tool.rs # Greeting tool implementation
│ │ ├── calculator_tool.rs # BMI calculator tool
│ │ └── weather_tool.rs # Weather tool (simulated)
│ ├── resources/
│ │ ├── mod.rs # Resource definitions
│ │ ├── config_resource.rs # App config resource
│ │ └── file_resource.rs # File-based resource
│ ├── prompts/
│ │ ├── mod.rs # Prompt definitions
│ │ └── code_review_prompt.rs # Code review prompt
│ ├── transport/
│ │ ├── mod.rs # Transport trait
│ │ └── stdio.rs # Stdio implementation
│ └── utils/
│ ├── mod.rs # Utility modules
│ ├── logger.rs # Logging utilities
│ └── error.rs # Error types
└── data/
└── (sample data files)
先决条件
系统要求
- 操作系统:macOS、Linux或Windows(带WSL2)
- 随机存取存储器:最低512 MB(建议2 GB)
- 磁盘空间:1 GB(主要用于依赖项)
所需软件
-
锈 (1.70或更高版本)
# Install from https://rustup.rs/ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -
货物 (随Rust一起提供)
cargo --version -
Git
git --version
验证安装
rustc --version
cargo --version
安装
步骤1:克隆存储库
git clone https://github.com/gitsudhir/mcp-server-rust.git
cd mcp-server-rust
或者从头开始创建一个新项目:
cargo new mcp-server-rust
cd mcp-server-rust
第二步:复制文件
将所有提供的源文件复制到 src/ 目录,如“项目结构”部分所示。
步骤3:更新Cargo.toml
确保您的 Cargo.toml 将提供的配置与所有必需的依赖项相匹配。
步骤4:验证依赖关系
cargo check
这将下载并验证所有依赖关系,而无需构建。
建设项目
开发版本
# Build with debug information (slower, larger binary)
cargo build
# Output: target/debug/mcp-server-rust
发布版本(推荐)
# Build optimized binary (faster execution)
cargo build --release
# Output: target/release/mcp-server-rust
构建验证
# Check without building
cargo check
# Run tests
cargo test
# View warnings
cargo clippy
运行服务器
基本执行
# Using debug binary
./target/debug/mcp-server-rust
# Using release binary
./target/release/mcp-server-rust
使用日志记录
# Enable debug logging
RUST_LOG=debug ./target/release/mcp-server-rust
# Enable specific module logging
RUST_LOG=rust_mcp_server::server=debug,rust_mcp_server::transport=debug ./target/release/mcp-server-rust
# All logs
RUST_LOG=trace ./target/release/mcp-server-rust
创建外壳包装器
为了更容易调用,创建一个shell脚本:
#!/bin/bash
exec /full/path/to/mcp-server-rust "$@"
使其可执行:
chmod +x mcp-server.sh
测试服务器
JSON-RPC手动测试
服务器运行时在另一个终端中进行测试:
初始化连接
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"TestClient","version":"1.0.0"}}}' | ./target/release/mcp-server-rust
调用工具
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"greet","arguments":{"name":"Alice"}}}' | ./target/release/mcp-server-rust
列出工具
echo '{"jsonrpc":"2.0","id":3,"method":"tools/list"}' | ./target/release/mcp-server-rust
计算BMI
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"calculate-bmi","arguments":{"weightKg":70,"heightM":1.75}}}' | ./target/release/mcp-server-rust
获取天气
echo '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"fetch-weather","arguments":{"city":"San Francisco"}}}' | ./target/release/mcp-server-rust
获取提示
echo '{"jsonrpc":"2.0","id":6,"method":"prompts/get","params":{"name":"review-code","arguments":{"code":"fn main() { println!(\"Hello!\"); }","focus":"performance"}}}' | ./target/release/mcp-server-rust
MCP检验员测试
官方MCP Inspector工具允许交互式测试:
-
安装检查器:
npm install -g @modelcontextprotocol/inspector -
运行服务器:
./target/release/mcp-server-rust -
运行检查器 (在另一个终端中):
mcp-inspector stdio ./target/release/mcp-server-rust -
在浏览器和测试工具中以交互方式打开检查器UI。
自动化测试
# Run built-in tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_name -- --nocapture
API 参考
JSON-RPC方法
1. initialize
目的:初始化MCP连接
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "ClientName",
"version": "1.0.0"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {},
"resources": {},
"prompts": {}
},
"serverInfo": {
"name": "RustMcpServer",
"version": "1.0.0"
}
}
}
2. tools/list
目的:列出可用工具
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "greet",
"description": "Greets a person with a friendly message",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the person to greet"
}
},
"required": ["name"]
},
"annotations": {
"title": "Greet Tool",
"readOnlyHint": true
}
}
]
}
}
3. tools/call
目的:调用工具
请求:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "greet",
"arguments": {
"name": "Alice"
}
}
}
响应(成功):
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Hello, Alice! Welcome to MCP."
}
],
"isError": false
}
}
响应(错误):
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Invalid params: Missing 'name' parameter"
}
}
4. resources/list
目的:列出可用资源
请求:
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"resources": [
{
"uri": "config://app",
"name": "Application Configuration",
"description": "Current application configuration",
"mimeType": "application/json"
}
]
}
}
5. resources/read
目的:阅读资源
请求:
{
"jsonrpc": "2.0",
"id": 5,
"method": "resources/read",
"params": {
"uri": "config://app"
}
}
响应:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"contents": [
{
"uri": "config://app",
"mimeType": "application/json",
"text": "{\"appName\": \"Rust MCP Server\", \"version\": \"1.0.0\", ...}"
}
]
}
}
6. prompts/list
目的:列出可用提示
请求:
{
"jsonrpc": "2.0",
"id": 6,
"method": "prompts/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"prompts": [
{
"name": "review-code",
"description": "Generates a prompt to ask the LLM to review code",
"arguments": [
{
"name": "code",
"description": "The code snippet to review",
"required": true
},
{
"name": "focus",
"description": "Optional area of focus",
"required": false
}
]
}
]
}
}
7. prompts/get
目的:获取提示
请求:
{
"jsonrpc": "2.0",
"id": 7,
"method": "prompts/get",
"params": {
"name": "review-code",
"arguments": {
"code": "fn main() { println!(\"Hello!\"); }",
"focus": "performance"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"description": "Requesting performance review for code snippet",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Please review the following code for potential issues and suggest improvements, focusing specifically on performance:\n\n```\nfn main() { println!(\"Hello!\"); }\n```"
}
]
}
]
}
}
添加自定义工具
步骤1:创建工具模块
use super::{Tool, CallToolResult, TextContent, ToolHandler};
use serde_json::{json, Value};
use async_trait::async_trait;
use crate::utils::{Result, Error, Logger};
pub struct CustomTool {
logger: Logger,
}
impl CustomTool {
pub fn new() -> Self {
Self {
logger: Logger::new("CustomTool"),
}
}
pub fn tool_definition() -> Tool {
Tool {
name: "custom-tool".to_string(),
description: "Description of your custom tool".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "First parameter"
},
"param2": {
"type": "number",
"description": "Second parameter"
}
},
"required": ["param1"]
}),
annotations: Some(json!({
"title": "Custom Tool",
"readOnlyHint": true
})),
}
}
}
impl Default for CustomTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ToolHandler for CustomTool {
async fn call(&self, arguments: Value) -> Result<CallToolResult> {
let param1 = arguments
.get("param1")
.and_then(|v| v.as_str())
.ok_or_else(|| Error::InvalidParams("Missing 'param1'".to_string()))?;
let param2 = arguments
.get("param2")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
self.logger.debug_with_context(
"Tool called",
&format!("param1={}, param2={}", param1, param2),
);
// Your custom logic here
let result = format!("Processed: {} and {}", param1, param2);
Ok(CallToolResult::success(vec![TextContent::new(result)]))
}
}
步骤2:在模块中注册
增添 src/tools/mod.rs:
pub mod custom_tool;
pub use custom_tool::CustomTool;
步骤3:添加到服务器
在 src/server.rs,更新 handle_tools_list:
async fn handle_tools_list(&self, _message: &Value) -> Result<Value> {
self.logger.debug("Listing tools");
let tools = vec![
GreetingTool::tool_definition(),
CalculatorTool::tool_definition(),
WeatherTool::tool_definition(),
CustomTool::tool_definition(), // Add this
];
Ok(json!({
"tools": tools
}))
}
在 handle_tools_call,添加匹配臂:
"custom-tool" => {
let handler = CustomTool::new();
handler.call(arguments).await?
}
步骤4:重建和测试
cargo build --release
# Test
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"custom-tool","arguments":{"param1":"test","param2":42}}}' | ./target/release/mcp-server-rust
故障排除
问题:服务器无法启动
# Check if executable exists
ls -la target/release/mcp-server-rust
# Try building again
cargo clean
cargo build --release
# Check for errors
cargo check
问题:连接被拒绝
- 验证服务器是否正在运行
- 检查是否有其他进程正在使用该端口
- 查看日志:
RUST_LOG=trace ./target/release/mcp-server-rust
问题:找不到工具
- 验证工具是否已在中注册
handle_tools_list - 检查工具名称是否完全匹配
- 验证匹配臂是否插入
handle_tools_call
问题:无效参数错误
- 检查JSON-RPC请求中的参数名称
- 验证类型(字符串与数字)
- 看看工具
inputSchema
问题:无输出/冻结
- 检查服务器是否正在等待输入
- 验证stdin/stdout未被阻止
- 启用日志记录:
RUST_LOG=trace ./target/release/mcp-server-rust
启用调试日志记录
# All modules
RUST_LOG=debug ./target/release/mcp-server-rust
# Specific module
RUST_LOG=rust_mcp_server::server=debug ./target/release/mcp-server-rust
# Very detailed
RUST_LOG=trace ./target/release/mcp-server-rust
使用MCP检查员进行测试
# Terminal 1: Start server
./target/release/mcp-server-rust
# Terminal 2: Run inspector
npx @modelcontextprotocol/inspector stdio ./target/release/mcp-server-rust
安全注意事项
输入验证
✅ 所有工具参数都使用JSON模式进行验证
✅ 检查文件路径是否有遍历尝试
✅ 刀具参数经过类型检查
输出消毒
✅ 工具结果安全地序列化为JSON
✅ 无原始命令执行
✅ 错误消息不公开内部详细信息
最佳实践
-
从不信任客户端输入
// BAD let path = arguments.get("file").unwrap(); // GOOD let path = arguments .get("file") .and_then(|v| v.as_str()) .ok_or_else(|| Error::InvalidParams("..."))?; -
验证文件路径
fn validate_path(&self, filename: &str) -> Result<PathBuf> { let requested = self.base_dir.join(filename); let resolved = std::fs::canonicalize(&requested)?; if !resolved.starts_with(&self.base_dir) { return Err(Error::ResourceError("Path traversal".into())); } Ok(resolved) } -
安全地处理错误
match operation() { Ok(result) => Ok(CallToolResult::success(...)), Err(e) => { self.logger.error(&e.to_string()); // Log internally Ok(CallToolResult::error("Operation failed")) // Generic response } } -
设置资源限制
const MAX_RESULT_SIZE: usize = 10_000_000; // 10MB if result.len() > MAX_RESULT_SIZE { return Err(Error::InternalError("Result too large".into())); }
高级主题
创建HTTP传输
虽然当前的实现使用Stdio,但您可以添加HTTP支持:
use crate::utils::Result;
use async_trait::async_trait;
use axum::{extract::Json, http::StatusCode, routing::post, Router};
use serde_json::Value;
#[async_trait]
pub async fn http_handler(
Json(payload): Json<Value>,
) -> (StatusCode, Json<Value>) {
// Handle JSON-RPC request
(StatusCode::OK, Json(payload))
}
pub fn create_router() -> Router {
Router::new()
.route("/mcp", post(http_handler))
}
添加持久状态
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct ServerState {
data: Arc<RwLock<HashMap<String, Value>>>,
}
impl ServerState {
pub async fn get(&self, key: &str) -> Option<Value> {
self.data.read().await.get(key).cloned()
}
pub async fn set(&self, key: String, value: Value) {
self.data.write().await.insert(key, value);
}
}
异步工具执行
#[async_trait]
impl ToolHandler for AsyncTool {
async fn call(&self, arguments: Value) -> Result<CallToolResult> {
// Can use tokio::time::sleep, reqwest, etc.
let result = tokio::time::timeout(
std::time::Duration::from_secs(30),
self.perform_async_work()
).await??;
Ok(CallToolResult::success(vec![TextContent::new(result)]))
}
}
贡献
欢迎投稿!拜托:
- 分叉存储库
- 创建要素分支
- 进行更改
- 添加测试
- 提交拉取请求
许可证
MIT许可证-有关详细信息,请参阅许可证文件
资源
- MCP规范: 模型上下文协议.io
- 防锈指南: doc.rust-lang.org
- 东京文件: 东京
常见问题解答
Q: 我可以运行多个MCP服务器吗?
A: 是的!每个应用程序都可以管理多个客户端-服务器连接。
Q: 这个生产准备好了吗?
A: 核心是稳定的,但在生产使用之前要审查安全考虑因素。
Q: 我可以添加数据库集成吗?
A: 当然!在工具处理程序中使用sqlx、tokio postgres等。
Q: 如何调试工具?
A: 启用日志记录 RUST_LOG=debug 并使用MCP检查器工具。
支持
对于问题和疑问:
- 查看此README和示例
- 启用调试日志
- 审查MCP规范
- 打开GitHub问题
最后更新: 2026-02-13
版本: 1.0.0
状态:稳定
