# rmcp: the official Rust SDK for the Model Context Protocol

> rmcp is the Model Context Protocol SDK maintained by the protocol's own organisation, built on tokio. It is a good fit if you are writing an MCP server in Rust and want the lifecycle, transports and macro wiring handled for you, and a poor fit if you cannot commit to edition 2024 and Rust 1.88.

**modelcontextprotocol/rust-sdk** — The official Rust SDK for the Model Context Protocol

- Repository: https://github.com/modelcontextprotocol/rust-sdk
- Website: https://docs.rs/rmcp
- Stars: 3,963 · Forks: 651
- Language: Rust
- License: NOASSERTION
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/modelcontextprotocol-rust-sdk

## What rmcp solves, and who it is for

MCP is a wire protocol. A server has to negotiate a protocol version, advertise capabilities, answer list_tools and call_tool, emit notifications, and do all of that over a transport the client chose. Writing that by hand in Rust means writing a lot of serde types before you write a single line of your actual tool. rmcp exists to remove that work. It is the official Rust implementation of the Model Context Protocol, published as two crates: rmcp, the protocol implementation, and rmcp-macros, the procedural macro crate that generates tool implementations. The audience is narrow and specific: Rust developers who are building an MCP server or client and who already use tokio. The README states the SDK is built with the tokio async runtime, and the workspace lists tokio and serde as its basic dependencies, with schemars used for JSON Schema generation at version 2020-12. If you are not in that group, nothing here is aimed at you.

## How the crate is laid out and how a request flows

The workspace has two default members, crates/rmcp and crates/rmcp-macros, plus examples and a conformance directory. The split matters: rmcp-macros holds the procedural macros, so a build that only needs the protocol types does not have to pull in macro expansion machinery. On the server side, the flow the README describes is transport, then service, then serve. You build a transport, for example the pair of standard input and output, construct a type that implements ServerHandler (or use the macro-generated one), and call serve on it. That call finishes the initialization handshake. After it returns you hold a running service you can send requests and notifications through, and you can await its shutdown with waiting() or cancel(). Clients mirror this: ().serve(transport) starts a client, and the README's example spawns npx with @modelcontextprotocol/server-everything as a child process and serves over TokioChildProcess. The interesting part is lifecycle. serve() uses the legacy MCP lifecycle: the client sends initialize, gets the negotiated server information back, then sends notifications/initialized. The newer path, ClientServiceExt::serve_with_lifecycle, lets you pick ClientLifecycleMode::Discover, which starts with server/discover and puts client metadata on every request instead of sending notifications/initialized at all. There is also ClientLifecycleMode::Auto, which probes discovery and falls back when a legacy server reports server/discover is not implemented or does not respond within 10 seconds. That fallback window is a fixed number, and it is the kind of detail that decides whether your client feels fast against old servers.

## Installing rmcp and building a first tools-only server

The README gives the install as a cargo add with the server feature enabled. The crate is published on crates.io, and the README also documents a dev channel that pulls from the main branch of the repository if you need unreleased changes.

```bash
cargo add rmcp --features server
```

The README's tool example is a calculator with a single add tool. The macros do the wiring: #[tool_router(server_handler)] on the impl block generates the server handler, so a tools-only server does not need a separate ServerHandler implementation. The parameter struct derives serde::Deserialize and schemars::JsonSchema, which is where the JSON Schema for the tool's arguments comes from.

```rust
use rmcp::{handler::server::wrapper::Parameters, schemars, tool, tool_router, ServiceExt, transport::stdio};

#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
struct AddParams {
    a: i32,
    b: i32,
}

#[derive(Clone)]
struct Calculator;

#[tool_router(server_handler)]
impl Calculator {
    #[tool(description = "Add two numbers")]
    fn add(&self, Parameters(AddParams { a, b }): Parameters<AddParams>) -> String {
        (a + b).to_string()
    }
}
```

The main function then serves that type over stdio and waits. Note that the README snippet for this final step is truncated mid-expression in the text available, so treat the shape as the contract rather than the exact characters: construct the service, call serve(stdio()), and await waiting().

```rust
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let service = Calculator.serve(stdio()).await?;
    service.waiting().await?;
    Ok(())
}
```

What you should see is a process that speaks MCP over standard input and output and exposes one tool named add. The repository keeps runnable examples under examples/servers, examples/clients, examples/transport and examples/wasi, which is where to look when the README snippets are not enough.

## The 3.x migration is the first thing to check

The README opens its notes with a migration pointer: migrating to 3.x means reading the migration guide at discussion 969 for breaking changes and upgrade instructions. That sentence is doing real work. The release history shows rmcp-v3.2.0 on 2026-08-31 and rmcp-v3.3.0 on 2026-09-10, so the 3.x line is moving in small increments, and the crate has already been through a major version boundary that the maintainers felt needed a dedicated guide. If you are starting fresh, this costs you nothing. If you have an existing server on 2.x, budget for reading that discussion before you touch Cargo.toml. The workspace also carries VERSIONING.md and DEPENDENCY_POLICY.md at the repository root, which is where the project states its own compatibility promises; the README does not summarise them, so read the files rather than assuming a policy.

## Where rmcp is the wrong tool

The toolchain requirement is the hardest constraint. The workspace package section sets edition 2024 and a minimum Rust version of 1.88. If your project is pinned to an older toolchain, or you depend on a crate that has not moved to edition 2024, rmcp is simply not available to you, and no feature flag changes that. The second constraint is the runtime. The README describes the SDK as built with the tokio async runtime, and tokio is listed as a basic dependency. If your application is built on a different async runtime, or is synchronous by design, adopting rmcp means adopting tokio as well. Third, the macro path is convenient but it is a macro path: the #[tool_router(server_handler)] shortcut is documented as a way to skip the separate ServerHandler impl for tools-only servers, which means servers with more complex handler needs fall back to implementing the trait by hand. Finally, the README's own snippet for starting a tools-only server is incomplete in the text available, and rollback behaviour after a failed initialization is not documented in the README at all. If your deployment depends on knowing exactly what happens when the handshake fails halfway, you will be reading crates/rmcp source, not the README.

## Alternatives, and the actual difference in approach

The comparison that matters is against implementing the protocol yourself on top of serde and tokio. That is not a strawman: MCP is a JSON-RPC-shaped protocol with a documented specification at modelcontextprotocol.io, and a small server that exposes two tools over stdio is genuinely a few hundred lines. The difference is what you inherit. Writing it yourself gives you an API surface you control and no dependency on a crate that has crossed a major version in the last few months. Using rmcp gives you the official implementation, which the README says implements the stable 2026-07-28 specification while remaining compatible with 2025-11-25 and earlier, plus the features that arrived with 2026-07-28: server discovery and negotiation, transport-neutral subscriptions, long-running tasks, response caching, multi-round-trip requests and standard HTTP routing headers. Reproducing that set, and keeping it correct as the specification moves, is the cost you are accepting when you write your own. The honest framing is that rmcp is the right default for a server that needs the newer specification features, and hand-rolling is defensible for a stdio server that will only ever expose a handful of tools against an older protocol revision.

## Licence, maintenance and upgrade cost

The repository metadata reports the licence as NOASSERTION, while the workspace Cargo.toml declares license = "Apache-2.0" and the repository root carries a LICENSE file. Treat the Cargo.toml and LICENSE file as the authoritative pair and read them yourself; this is a description of what the files say, not legal advice. On maintenance, the last push to the default branch was on 2026-09-10, and rmcp-v3.3.0 was released the same day, with rmcp-macros-v3.3.0 published seconds earlier. The repository is not archived. That is a recent release cadence, and it also means the upgrade cost is real rather than theoretical: two releases, 3.2.0 and 3.3.0, landed within eleven days of each other, and the 3.x line already has a migration guide. The justfile shows the project's own verification loop, which is a useful signal of what a contribution or a local fork has to satisfy: cargo clippy --all-targets --all-features with -D warnings, cargo test --all-features, and a second test pass over every non-internal feature combination enumerated from cargo metadata. If you vendor or patch rmcp, that is the bar.

## Conclusion

Adopt rmcp if you are building an MCP server or client in Rust, you are on edition 2024 with Rust 1.88 or newer, and you want the protocol lifecycle, transports and tool wiring handled by the official implementation rather than by hand. Do not adopt it if you need a stable API surface across minor releases, if your toolchain is pinned below 1.88, or if you are not writing Rust at all. Before you start, read the 3.x migration guide linked from the README, check the VERSIONING.md and DEPENDENCY_POLICY.md files at the repository root for the project's own compatibility promises, and confirm that the transport you need (stdio, or streamable HTTP including the stateless mode) is the one your host actually speaks.

## FAQ

### What is a Rust SDK?

In this context it is a software development kit for a specific protocol, written in Rust. rmcp is the official Rust implementation of the Model Context Protocol, published as the rmcp and rmcp-macros crates and built on the tokio async runtime.

### How do you use the Rust SDK?

The README shows adding it with cargo add rmcp --features server, then building a transport and a service and calling serve on the service. For a tools-only server, the #[tool_router(server_handler)] macro generates the handler so you do not write a separate ServerHandler implementation.

### What is the Rust SDK used for?

rmcp is used to build Model Context Protocol servers and clients in Rust: tools, resources, prompts, sampling, elicitation, roots, logging, completions and the transports the protocol defines. The README states it implements the stable 2026-07-28 specification while remaining compatible with 2025-11-25 and earlier.

### What does Rust SDK mean?

It means a development kit for a service or protocol, distributed as Rust crates. For rmcp that is two crates in one workspace: rmcp for the protocol implementation and rmcp-macros for the procedural macros that generate tool implementations.

## Sources

- [Issues](https://github.com/modelcontextprotocol/rust-sdk/issues)
- [modelcontextprotocol/rust-sdk on GitHub](https://github.com/modelcontextprotocol/rust-sdk)
- [Project website](https://docs.rs/rmcp)
- [README](https://github.com/modelcontextprotocol/rust-sdk/blob/main/README.md)
- [Releases](https://github.com/modelcontextprotocol/rust-sdk/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/modelcontextprotocol-rust-sdk
