| Crates.io | miyabi-mcp-template |
| lib.rs | miyabi-mcp-template |
| version | 0.1.0 |
| created_at | 2025-11-22 09:33:01.023929+00 |
| updated_at | 2025-11-22 09:33:01.023929+00 |
| description | MCP Server Template for Miyabi - Use this as a starting point for new MCP servers |
| homepage | |
| repository | https://github.com/ShunsukeHayashi/Miyabi |
| max_upload_size | |
| id | 1945109 |
| size | 49,461 |
Template for creating new MCP servers in Rust
This is a template crate for creating new MCP (Model Context Protocol) servers in the Miyabi ecosystem using the official Rust SDK (rmcp).
# Copy this template to create a new server
cp -r crates/miyabi-mcp-template crates/miyabi-mcp-<your-server-name>
# Example: Creating a rules server
cp -r crates/miyabi-mcp-template crates/miyabi-mcp-rules
Edit Cargo.toml:
[package]
name = "miyabi-mcp-<your-server-name>"
description = "Your server description"
Edit src/server.rs:
#[derive(Debug, Deserialize, JsonSchema)])#[tool] macro# Build
cargo build -p miyabi-mcp-<your-server-name>
# Run tests
cargo test -p miyabi-mcp-<your-server-name>
# Run the server
cargo run -p miyabi-mcp-<your-server-name>
# Build release binary
cargo build --release -p miyabi-mcp-<your-server-name>
# Start MCP Inspector
npx @modelcontextprotocol/inspector
# In the Inspector UI:
# - Command: ./target/release/miyabi-mcp-<your-server-name>
# - Args: (leave empty for stdio)
# - Click "Connect"
crates/miyabi-mcp-template/
├── Cargo.toml # Dependencies and metadata
├── README.md # This file
└── src/
├── main.rs # Entry point with transport setup
└── server.rs # Server implementation with tools
This template includes 4 example tools:
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct MyToolArgs {
/// Field description (becomes part of the schema)
pub field1: String,
/// Optional field
#[serde(default)]
pub field2: Option<i32>,
}
#[tool(description = "Your tool description")]
async fn my_tool(
&self,
args: MyToolArgs,
) -> Result<CallToolResult, McpError> {
tracing::info!("my_tool called: {:?}", args);
// Your implementation here
Ok(CallToolResult::success(vec![
Content::text("Success!")
]))
}
#[tokio::test]
async fn test_my_tool() {
let server = TemplateServer::new();
let args = MyToolArgs { /* ... */ };
let result = server.my_tool(args).await;
assert!(result.is_ok());
}
#[derive(Clone)]
pub struct MyServer {
tool_router: ToolRouter<MyServer>,
database: Arc<Mutex<Database>>, // Add state here
}
#[tool_router]
impl MyServer {
pub fn new() -> Self {
Self {
tool_router: Self::tool_router(),
database: Arc::new(Mutex::new(Database::new())),
}
}
#[tool(description = "Access database")]
async fn query_db(&self, args: QueryArgs) -> Result<CallToolResult, McpError> {
let db = self.database.lock().await;
// Use db
Ok(/* ... */)
}
}
#[tool(description = "Tool that might fail")]
async fn risky_operation(&self, args: Args) -> Result<CallToolResult, McpError> {
// Return custom error
if args.invalid {
return Err(McpError {
code: -32000,
message: "Invalid input".to_string(),
data: Some(serde_json::json!({
"reason": "field was invalid"
})),
});
}
// Or convert from anyhow::Error
let result = some_operation()
.map_err(|e| McpError {
code: -32001,
message: e.to_string(),
data: None,
})?;
Ok(CallToolResult::success(vec![Content::text(result)]))
}
Ok(CallToolResult::success(vec![
Content::text("Text response"),
Content::image(ImageContent {
data: base64_image,
mime_type: "image/png".to_string(),
}),
]))
Edit Cargo.toml:
[dependencies]
# HTTP client
reqwest = { workspace = true }
# Database
sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "sqlite"] }
# CLI parsing (if needed)
clap = { version = "4", features = ["derive"] }
let service = server.serve(stdio()).await?;
use rmcp::transport::sse;
let service = server
.serve(sse::SseServer::new("127.0.0.1:8000"))
.await?;
use rmcp::transport::http;
let service = server
.serve(http::HttpServer::new("127.0.0.1:8000"))
.await?;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_tool() {
let server = MyServer::new();
let result = server.my_tool(args).await;
assert!(result.is_ok());
}
}
Create tests/integration.rs:
use miyabi_mcp_myserver::server::MyServer;
#[tokio::test]
async fn test_server_lifecycle() {
let server = MyServer::new();
// Test server
}
cargo build --release -p miyabi-mcp-<your-server>
Binary location: target/release/miyabi-mcp-<your-server>
Add to .mcp.json:
{
"mcpServers": {
"my-server": {
"command": "/path/to/target/release/miyabi-mcp-<your-server>",
"args": []
}
}
}
If you're migrating from a TypeScript MCP server:
index.ts to identify all tools#[tool] macroSee: docs/MCP_MIGRATION_MASTER_PLAN.md
Same as Miyabi project