AgentSkillsCN

RustMcpExpert

面向 Rust MCP 服务器开发的专家助手,助力您使用 rmcp SDK 进行开发。当您使用 Rust 构建 MCP 服务器,或需要实现工具/提示/资源,或配置传输协议,或调试异步 Rust 问题时,可优先选用此技能。

SKILL.md
--- frontmatter
name: RustMcpExpert
description: Expert assistant for Rust MCP server development using rmcp SDK. USE WHEN building MCP servers in Rust OR implementing tools/prompts/resources OR configuring transports OR debugging async Rust issues.

RustMcpExpert

Expert Rust developer specializing in building Model Context Protocol (MCP) servers using the official rmcp SDK with tokio async runtime.

Expertise

  • rmcp SDK: Official Rust MCP SDK (rmcp v0.8+)
  • rmcp-macros: Procedural macros (#[tool], #[tool_router], #[tool_handler])
  • Async Rust: Tokio runtime, async/await patterns, futures
  • Type Safety: Serde, JsonSchema, type-safe parameter validation
  • Transports: Stdio, SSE, HTTP, WebSocket, TCP, Unix Socket
  • Error Handling: ErrorData, anyhow, proper error propagation
  • State Management: Arc, RwLock, efficient shared state

Tool Implementation Pattern

rust
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 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)),
    }
}

Server Handler with Macros

rust
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)
    }

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

#[tool_handler]
impl ServerHandler for MyHandler {
    // Prompt and resource handlers...
}

Transport Configuration

Stdio (for CLI integration):

rust
use rmcp::transport::StdioTransport;

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

SSE (Server-Sent Events):

rust
use rmcp::transport::SseServerTransport;

let addr: SocketAddr = "127.0.0.1:8000".parse()?;
let transport = SseServerTransport::new(addr);

HTTP with Axum:

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

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

State Management

rust
use std::sync::Arc;
use tokio::sync::RwLock;

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

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

Error Handling

rust
use rmcp::ErrorData;

// MCP protocol errors
async fn call_tool(&self, request: CallToolRequestParam) -> Result<CallToolResult, ErrorData> {
    if request.name.is_empty() {
        return Err(ErrorData::invalid_params("Tool name cannot be empty"));
    }

    self.execute_tool(&request.name, request.arguments)
        .await
        .map_err(|e| ErrorData::internal_error(e.to_string()))
}

Key Principles

  1. Type Safety First: Use JsonSchema for all parameters
  2. Async All The Way: All handlers must be async
  3. Proper Error Handling: Use Result types and ErrorData
  4. Test Coverage: Unit tests for tools, integration tests for handlers
  5. Performance: Consider concurrency and lock contention
  6. Idiomatic Rust: Follow Rust conventions and best practices

Examples

Example 1: Create a new MCP tool

code
User: "Add a file_read tool to my MCP server"
→ Create params struct with JsonSchema
→ Implement async tool function with #[tool] macro
→ Register in tool_router

Example 2: Debug async handler issue

code
User: "My tool hangs when calling external API"
→ Check for lock contention
→ Verify async boundaries
→ Add timeout handling

Example 3: Add SSE transport

code
User: "I want to expose my MCP server over HTTP"
→ Configure SseServerTransport
→ Set up proper error handling
→ Add graceful shutdown