Blazingly fast and easily configurable Model Context Protocol (MCP) server and client SDK for Rust. With simple configuration and ergonomic APIs, it provides everything you need to quickly build MCP clients and servers, fully aligned with the latest MCP specification.
💡 Note: This project is currently in preview. Breaking changes can be introduced without prior notice.
Tutorial | API Docs | Examples
- Client & Server SDK - one library to build both MCP clients and servers with the powers of Rust.
- Performance - asynchronous and Tokio-powered.
- Transports - stdio for local integrations and Streamable HTTP for remote, bidirectional communication.
- Tools, Resources & Prompts - full-house support for defining and consuming the main MCP entities.
- Authentication & Authorization - bearer token authentication, role-based access control, and more to fit high security standards.
- Structured Data - output validation, embedded resources, and resource links out of the box.
- Safe Multi Round-Trip Requests - a handler that asks the client for input mid-call re-runs from the top on every round, so neva owns the idempotency:
ctx.memocomputes once,ctx.onceruns an effect once,ctx.on_commitdefers it to the final result, and a built-in store makes a lost-response retry replay the committed answer instead of charging the card twice. The protocol leaves this to the implementation; you don't hand-roll it per tool. - Confidential request state - the
requestStateblob that carries progress between rounds is sealed with ChaCha20-Poly1305, not merely signed, so the server-computed valuesctx.memocaches stay unreadable to the client that echoes them back. - Spec Alignment - designed to track the latest MCP specification and cover its core functionality.
[dependencies]
neva = { version = "0.5.0", features = ["client-full"] }
tokio = { version = "1", features = ["full"] }use neva::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Error> {
let mut client = Client::new()
.with_options(|opt| opt
.with_stdio("npx", ["-y", "@modelcontextprotocol/server-everything"])
.with_timeout(Duration::from_secs(5)));
client.connect().await?;
// List tools
let tools = client.list_tools(None).await?;
for tool in tools.tools {
println!("- {}", tool.name);
}
// Call a tool
let args = [
("message", "Hello MCP!")
];
let result = client.call_tool("echo", args).await?;
println!("{:?}", result.content);
client.disconnect().await
}[dependencies]
neva = { version = "0.5.0", features = ["server-full"] }
tokio = { version = "1", features = ["full"] }use neva::prelude::*;
#[tool(descr = "A say hello tool")]
async fn hello(name: String) -> String {
format!("Hello, {name}!")
}
#[resource(uri = "res://{name}", descr = "Some details about resource")]
async fn get_res(name: String) -> ResourceContents {
ResourceContents::new(format!("res://{name}"))
.with_mime("plain/text")
.with_text(format!("Some details about resource: {name}"))
}
#[prompt(descr = "Analyze code for potential improvements")]
async fn analyze_code(lang: String) -> PromptMessage {
PromptMessage::user()
.with(format!("Language: {lang}"))
}
#[tokio::main]
async fn main() {
App::new()
.with_options(|opt| opt
.with_stdio()
.with_name("Sample MCP server")
.with_version("1.0.0"))
.run()
.await;
}