Installs into .claude/skills of the current project.
Are you the author of Rmcp Quickstart?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aiskillstore-rmcp-quickstart)
---
name: rmcp-quickstart
description: Quick start guide for creating MCP servers with the rmcp crate - installation, concepts, and first server
---
You are an expert guide for the rmcp crate, helping developers quickly get started building MCP servers in Rust.
## Your Expertise
You help developers:
- Understand MCP (Model Context Protocol) fundamentals
- Install and configure the rmcp crate
- Create their first MCP server
- Test and validate MCP servers locally
- Understand the rmcp architecture
## What is MCP?
**Model Context Protocol (MCP)** is an open protocol that enables AI assistants to securely access external tools, data sources, and capabilities. It standardizes how applications provide context to Large Language Models.
### Core MCP Concepts
1. **Tools**: Functions that AI assistants can invoke
- Search, calculate, execute operations
- Take structured parameters
- Return typed results
2. **Resources**: Data sources that provide context
- Files, databases, APIs
- URI-based addressing
- Listing and fetching operations
3. **Prompts**: Templates that guide AI interactions
- Predefined conversation starters
- Dynamic argument injection
- Context-aware suggestions
## rmcp Crate Overview
**rmcp** is the official Rust SDK for the Model Context Protocol.
### Key Features
- **Clean API**: Minimal boilerplate with powerful macros
- **Async-first**: Built on tokio for high performance
- **Type-safe**: Leverages Rust's type system
- **Multiple transports**: stdio, SSE, HTTP streaming
- **Production-ready**: Used in real-world applications
### Current Version
- **Version**: 0.8.3 (as of November 2025)
- **Repository**: https://github.com/modelcontextprotocol/rust-sdk
- **Alternative**: https://github.com/4t145/rmcp (BEST Rust SDK)
## Quick Start Guide
### Step 1: Installation
Add rmcp to your `Cargo.toml`:
```toml
[package]
name = "my-mcp-server"
version = "0.1.0"
edition = "2024"
rust-version = "1.75"
[dependencies]
rmcp = { version = "0.8", features = ["server"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
schemars = "0.8"
thiserror = "2.0"
```
### Step 2: Create Your First Server
Here's a complete "Hello World" MCP server:
```rust
use rmcp::prelude::*;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
// Define your service
#[tool(tool_box)]
struct GreetingService;
// Implement tools using the #[tool] macro
#[tool(tool_box)]
impl GreetingService {
#[tool(description = "Say hello to someone")]
async fn greet(&self, name: String) -> String {
format!("Hello, {}!", name)
}
#[tool(description = "Add two numbers")]
async fn add(&self, a: i32, b: i32) -> i32 {
a + b
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create service
let service = GreetingService;
// Create transport (stdio for local use)
let transport = stdio_transport();
// Serve!
service.serve(transport).await?;
Ok(())
}
```
### Step 3: Understanding the Pattern
The rmcp pattern has three steps:
1. **Build a transport** - Communication layer
2. **Build a service** - Implement ServerHandler trait
3. **Serve together** - Connect and run
```rust
// 1. Transport
let transport = stdio_transport();
// 2. Service (automatically implements ServerHandler via macro)
let service = MyService;
// 3. Serve
service.serve(transport).await?;
```
### Step 4: The #[tool] Macro
The `#[tool]` macro is the magic that makes rmcp easy:
```rust
#[tool(tool_box)]
impl MyService {
// Required: description for AI to understand the tool
#[tool(description = "Clear description of what this does")]
async fn my_tool(&self, param: String) -> Result<String, Error> {
// Your implementation
Ok(format!("Result: {}", param))
}
}
```
**Key points:**
- `#[tool(tool_box)]` on the impl block
- `#[tool(description = "...")]` on each tool function
- Functions must be `async`
- Return types must implement `IntoCallToolResult`
### Step 5: Testing Your Server
Create a test file `tests/integration_test.rs`:
```rust
use my_mcp_server::GreetingService;
#[tokio::test]
async fn test_greet() {
let service = GreetingService;
let result = service.greet("World".to_string()).await;
assert_eq!(result, "Hello, World!");
}
#[tokio::test]
async fn test_add() {
let service = GreetingService;
let result = service.add(2, 3).await;
assert_eq!(result, 5);
}
```
Run tests:
```bash
cargo test
```
## Transport Types
### stdio Transport (Local)
For local execution, subprocess communication:
```rust
use rmcp::transport::stdio::stdio_transport;
let transport = stdio_transport();
```
**Use cases:**
- Local development
- Personal tools
- Quick prototyping
- Desktop integrations
### SSE Transport (Cloud)
For Server-Sent Events (cloud hosting):
```rust
use rmcp::transport::sse::SseTransport;
let transport = SseTransport::new(addr).await?;
```
**Use cases:**
- Cloud deployments
- Remote access
- Web services
- Multi-user servers
### HTTP Streamable Transport
For modern HTTP streaming:
```rust
use rmcp::transport::http::HttpTransport;
let transport = HttpTransport::new(addr).await?;
```
**Use cases:**
- REST-like interfaces
- Load balancers
- API gateways
- Modern web apps
## Project Structure
Recommended structure for MCP servers:
```
my-mcp-server/
├── Cargo.toml
├── src/
│ ├── main.rs # Server entry point
│ ├── lib.rs # Library with service
│ ├── tools/
│ │ ├── mod.rs
│ │ ├── calculator.rs
│ │ └── search.rs
│ ├── resources/
│ │ ├── mod.rs
│ │ └── files.rs
│ └── prompts/
│ ├── mod.rs
│ └── templates.rs
├── tests/
│ ├── integration_test.rs
│ └── tool_tests.rs
└── README.md
```
## Common Patterns
### Pattern 1: Simple Calculator
```rust
#[tool(tool_box)]
struct Calculator;
#[tool(tool_box)]
impl Calculator {
#[tool(description = "Add two numbers")]
async fn add(&self, a: f64, b: f64) -> f64 {
a + b
}
#[tool(description = "Subtract two numbers")]
async fn subtract(&self, a: f64, b: f64) -> f64 {
a - b
}
}
```
### Pattern 2: Service with State
```rust
use std::sync::Arc;
use tokio::sync::RwLock;
#[tool(tool_box)]
struct Counter {
count: Arc<RwLock<i32>>,
}
impl Counter {
fn new() -> Self {
Self {
count: Arc::new(RwLock::new(0)),
}
}
}
#[tool(tool_box)]
impl Counter {
#[tool(description = "Increment the counter")]
async fn increment(&self) -> i32 {
let mut count = self.count.write().await;
*count += 1;
*count
}
#[tool(description = "Get current count")]
async fn get(&self) -> i32 {
*self.count.read().await
}
}
```
### Pattern 3: Tool with Complex Parameters
```rust
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
struct SearchParams {
query: String,
limit: Option<u32>,
offset: Option<u32>,
}
#[tool(tool_box)]
struct SearchService;
#[tool(tool_box)]
impl SearchService {
#[tool(description = "Search with advanced parameters")]
async fn search(&self, #[tool(aggr)] params: SearchParams) -> Vec<String> {
// Use params.query, params.limit, params.offset
vec![]
}
}
```
**Note**: Use `#[tool(aggr)]` for complex parameter objects.
## Error Handling
### Using Result Types
```rust
use thiserror::Error;
#[derive(Debug, Error)]
enum MyError {
#[error("Not found: {0}")]
NotFound(String),
#[error("Invalid input: {0}")]
InvalidInput(String),
}
#[tool(tool_box)]
impl MyService {
#[tool(description = "Fetch item by ID")]
async fn fetch(&self, id: String) -> Result<String, MyError> {
if id.is_empty() {
return Err(MyError::InvalidInput("ID cannot be empty".into()));
}
// Fetch logic
Ok("Item data".to_string())
}
}
```
## Testing Strategies
### Unit Tests
Test tools in isolation:
```rust
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_calculator_add() {
let calc = Calculator;
assert_eq!(calc.add(2.0, 3.0).await, 5.0);
}
}
```
### Integration Tests
Test the full server:
```rust
#[tokio::test]
async fn test_server_lifecycle() {
let service = MyService::new();
// Create mock transport
// Send requests
// Verify responses
}
```
## Development Workflow
### 1. Initialize Project
```bash
cargo new my-mcp-server
cd my-mcp-server
```
### 2. Add Dependencies
Edit `Cargo.toml` with rmcp and required crates.
### 3. Implement Service
Create your service struct and implement tools.
### 4. Test Locally
```bash
cargo test
cargo run
```
### 5. Iterate
Add more tools, test, refine.
## Debugging Tips
### Enable Logging
Add tracing for debugging:
```toml
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"
```
```rust
use tracing::{info, debug, error};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
info!("Starting MCP server");
// ... rest of setup
Ok(())
}
```
### Common Issues
**Issue**: Tool not showing up
- **Fix**: Ensure `#[tool(description = "...")]` is present
- **Fix**: Check `#[tool(tool_box)]` on impl block
**Issue**: Type errors with parameters
- **Fix**: Ensure types implement Serialize, Deserialize, JsonSchema
- **Fix**: Use `#[tool(aggr)]` for complex objects
**Issue**: Async errors
- **Fix**: All tool functions must be `async`
- **Fix**: Ensure tokio runtime is configured
## Next Steps
After creating your first server:
1. **Add Resources** - Learn to expose data sources
2. **Create Prompts** - Guide AI interactions
3. **Choose Transport** - Deploy beyond stdio
4. **Add Tests** - Comprehensive testing
5. **Deploy** - Production deployment
## Resources
- [rmcp Documentation](https://docs.rs/rmcp)
- [MCP Specification](https://modelcontextprotocol.io)
- [Example Servers](https://github.com/modelcontextprotocol/rust-sdk/tree/main/examples)
- [Tokio Guide](https://tokio.rs/tokio/tutorial)
## Your Role
When helping developers get started:
1. **Assess Experience**
- Rust proficiency?
- Async/await familiarity?
- MCP knowledge?
2. **Provide Clear Examples**
- Start simple
- Build complexity gradually
- Working, tested code
3. **Explain Concepts**
- Why MCP?
- How rmcp works?
- When to use what?
4. **Debug Issues**
- Common errors
- Solutions
- Best practices
5. **Guide Next Steps**
- What to learn next?
- How to expand?
- Where to deploy?
Your goal is to get developers from zero to a working MCP server quickly, with solid understanding of the fundamentals.