hanzo-mcp-client

Async MCP (Model Context Protocol) client for Rust.
Overview
This crate provides an async client for communicating with MCP servers. It handles the JSON-RPC transport layer, message framing, and provides a clean API for tool discovery and execution.
Installation
[dependencies]
hanzo-mcp-client = "0.6"
tokio = { version = "1", features = ["full"] }
Quick Start
use hanzo_mcp_client::McpClient;
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = McpClient::spawn(
"npx",
&["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
).await?;
let tools = client.list_tools().await?;
println!("Available tools: {:?}", tools.iter().map(|t| &t.name).collect::<Vec<_>>());
let result = client.call_tool("read_file", json!({
"path": "README.md"
})).await?;
println!("Result: {:?}", result);
Ok(())
}
Features
- Async/await - Built on Tokio for high-performance async I/O
- Subprocess management - Spawn and manage MCP server processes
- JSON-RPC - Full implementation of MCP's JSON-RPC protocol
- Type-safe - Strongly typed requests and responses via
hanzo-mcp-types
- Error handling - Comprehensive error types with context
API Reference
McpClient
impl McpClient {
pub async fn spawn(command: &str, args: &[&str]) -> Result<Self>;
pub async fn connect(stdin: ChildStdin, stdout: ChildStdout) -> Result<Self>;
pub async fn initialize(&self) -> Result<InitializeResult>;
pub async fn list_tools(&self) -> Result<Vec<Tool>>;
pub async fn call_tool(&self, name: &str, arguments: Value) -> Result<CallToolResult>;
pub async fn list_resources(&self) -> Result<Vec<Resource>>;
pub async fn read_resource(&self, uri: &str) -> Result<ReadResourceResult>;
pub async fn list_prompts(&self) -> Result<Vec<Prompt>>;
pub async fn get_prompt(&self, name: &str, arguments: Value) -> Result<GetPromptResult>;
}
Example: Multiple Servers
use hanzo_mcp_client::McpClient;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let filesystem = McpClient::spawn(
"npx", &["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
).await?;
let github = McpClient::spawn(
"npx", &["-y", "@modelcontextprotocol/server-github"]
).await?;
let files = filesystem.call_tool("list_directory", json!({"path": "."})).await?;
let issues = github.call_tool("list_issues", json!({"repo": "hanzoai/dev"})).await?;
Ok(())
}
Error Handling
use hanzo_mcp_client::{McpClient, McpError};
match client.call_tool("unknown_tool", json!({})).await {
Ok(result) => println!("Success: {:?}", result),
Err(McpError::ToolNotFound(name)) => println!("Tool not found: {}", name),
Err(McpError::InvalidParams(msg)) => println!("Invalid params: {}", msg),
Err(McpError::Transport(e)) => println!("Transport error: {}", e),
Err(e) => println!("Other error: {}", e),
}
Related Crates
License
MIT License - Copyright 2025 Hanzo AI Inc.