| Crates.io | mocopr |
| lib.rs | mocopr |
| version | 0.1.0 |
| created_at | 2025-08-14 12:48:34.290981+00 |
| updated_at | 2025-08-14 12:48:34.290981+00 |
| description | A comprehensive Rust implementation of the Model Context Protocol (MCP) |
| homepage | |
| repository | https://github.com/ciresnave/mocopr |
| max_upload_size | |
| id | 1794818 |
| size | 457,085 |
A comprehensive and developer-friendly Rust implementation of the Model Context Protocol (MCP), making it extremely simple to build MCP servers and clients with production-ready features.
MoCoPr is organized into several specialized crates for maximum flexibility:
Add MoCoPr to your Cargo.toml:
[dependencies]
mocopr = "0.1"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"
use mocopr::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
// Create a simple calculator server
let server = McpServer::builder()
.with_info("Calculator Server", "1.0.0")
.with_tool_handler(
"add",
"Add two numbers together",
json!({
"type": "object",
"properties": {
"a": {"type": "number", "description": "First number"},
"b": {"type": "number", "description": "Second number"}
},
"required": ["a", "b"]
}),
|params| async move {
let a = params["a"].as_f64().unwrap_or(0.0);
let b = params["b"].as_f64().unwrap_or(0.0);
Ok(ToolResult::text(format!("Result: {}", a + b)))
}
)
.with_resource_handler(
"memory://calculations",
"Access calculation history",
|_uri| async move {
Ok(ResourceResult::text("Recent calculations: ..."))
}
)
.build()?;
// Start server with stdio transport
server.run_stdio().await?;
Ok(())
}
use mocopr::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
// Connect to an MCP server
let client = McpClient::connect_stdio(
"python",
&["calculator_server.py"],
Implementation::new("Calculator Client", "1.0.0"),
ClientCapabilities::default(),
).await?;
// List available tools
let tools = client.list_tools().await?;
println!("Available tools: {:#?}", tools);
// Call a tool
let result = client.call_tool("add", json!({
"a": 42,
"b": 58
})).await?;
println!("Result: {:#?}", result);
// Read a resource
let resource = client.read_resource("memory://calculations").await?;
println!("Resource: {:#?}", resource);
Ok(())
}
The examples/ directory contains comprehensive examples:
| Example | Description | Transport | Complexity |
|---|---|---|---|
| simple-server | Basic MCP server with tools and resources | stdio | Beginner |
| simple-client | Basic MCP client usage | stdio | Beginner |
| calculator-server | Full-featured calculator with validation | stdio | Intermediate |
| file-server | File system operations with security | stdio | Intermediate |
| websocket-chat | Real-time chat server | WebSocket | Advanced |
| http-api | REST-like HTTP interface | HTTP | Advanced |
| production-server | Production-ready server with all features | All | Expert |
Run any example:
# Run the calculator server
cargo run --example calculator-server
# Run the file server
cargo run --example file-server
# Run with custom transport
cargo run --example websocket-chat -- --port 8080
MoCoPr supports multiple transport mechanisms with automatic failover:
// stdio transport (process communication)
server.run_stdio().await?;
// WebSocket transport (real-time web apps)
server.run_websocket("127.0.0.1:8080").await?;
// HTTP transport (stateless requests)
server.run_http("127.0.0.1:3000").await?;
// Multiple transports simultaneously
server.run_all(&[
TransportConfig::Stdio,
TransportConfig::WebSocket("127.0.0.1:8080".parse()?),
TransportConfig::Http("127.0.0.1:3000".parse()?),
]).await?;
let server = McpServer::builder()
.with_middleware(RateLimitMiddleware::new(100, Duration::from_secs(60)))
.with_middleware(AuthenticationMiddleware::new())
.with_middleware(LoggingMiddleware::with_level(Level::INFO))
.with_validation(true)
.build()?;
use mocopr::observability::*;
let server = McpServer::builder()
.with_metrics(PrometheusMetrics::new())
.with_tracing(TracingConfig::default())
.with_health_checks(true)
.build()?;
let client = McpClient::builder()
.with_retry_policy(RetryPolicy::exponential_backoff(3))
.with_timeout(Duration::from_secs(30))
.with_connection_recovery(true)
.connect_stdio("server", &["args"]).await?;
let result = a + b;
Ok(ToolsCallResponse::success(vec![
Content::from(format!("{} + {} = {}", a, b, result))
]))
}
);
// Build and run the server
let server = McpServer::builder()
.with_info("Calculator Server", "1.0.0")
.with_tools()
.with_tool(calculator)
.build()?;
server.run_stdio().await?;
Ok(())
}
### Creating an MCP Client
```rust
use mocopr_client::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
// Connect to a server
let client = McpClientBuilder::new()
.with_info("My Client".to_string(), "1.0.0".to_string())
.connect_stdio("my-mcp-server", &[])
.await?;
// List available tools
let tools = client.list_tools().await?;
println!("Available tools: {:?}", tools.tools);
// Call a tool
let result = client.call_tool(
"add".to_string(),
Some(json!({"a": 5, "b": 3}))
).await?;
println!("Result: {:?}", result);
client.close().await?;
Ok(())
}
use mocopr_macros::*;
#[derive(Tool)]
#[tool(name = "weather", description = "Get weather information")]
struct WeatherTool;
#[async_trait]
impl ToolHandler for WeatherTool {
async fn call(&self, args: Option<serde_json::Value>) -> Result<ToolsCallResponse> {
// Your implementation here
Ok(ToolsCallResponse::success(vec![
Content::from("Sunny, 72ยฐF")
]))
}
}
#[derive(Resource)]
#[resource(uri = "file:///config.json", name = "Configuration")]
struct ConfigResource {
data: serde_json::Value,
}
let file_resource = file_resource!(
uri: "file:///data/example.txt",
name: "Example Data",
path: "./data/example.txt",
description: "Example data file",
mime_type: "text/plain"
);
let prompt = template_prompt!(
name: "summarize",
description: "Summarize text content",
template: "Please summarize the following text: {text}",
arguments: [
PromptArgument::new("text")
.with_description("Text to summarize")
.required(true)
]
);
// Server
server.run_stdio().await?;
// Client
let client = McpClientBuilder::new()
.with_info("Client", "1.0.0")
.connect_stdio("./my-server", &["--arg1", "value1"])
.await?;
// Server
server.run_websocket("127.0.0.1:8080").await?;
// Client
let client = McpClientBuilder::new()
.with_info("Client", "1.0.0")
.connect_websocket("ws://127.0.0.1:8080/mcp")
.await?;
The repository includes several complete examples:
Run examples:
# Start the simple server
cargo run --example simple-server
# In another terminal, run the client
cargo run --example simple-client
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ MCP Client โ โ MCP Server โ
โ โ โ โ
โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ
โ โ Session โ โโโโโโค โ Session โ โ
โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ
โ โ Transport โ โโโโโโค โ Transport โ โ
โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ โ
โโโ stdio/websocket โโโโโโ
# Run all tests
cargo test
# Run tests for a specific crate
cargo test -p mocopr-core
# Run with logging
RUST_LOG=debug cargo test
Cargo.toml for full listLicensed under either of:
at your option.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
MoCoPr - Making MCP integration in Rust as easy as adding copper to your project! โก