| Filename | Latest commit message | Latest commit date |
|---|---|---|
A stateless streamable-HTTP request is one-shot (no session, no resumption), so if the client drops the response before the handler finishes, the request is terminal and should be cancelled. Previously the handler kept running with its `RequestContext::ct` never firing, so long-running or destructive tools could not observe a client disconnect. Give each stateless request its own cancellation token via `serve_directly_with_ct` and cancel it when the client disconnects. This covers both stateless paths: `serve_negotiated_request_directly` (per-request version negotiation) and the non-negotiated path. In each: - A disconnect while the handler is still producing its first message cancels it. The guard is disarmed once the handler emits anything, so a normal response is never cancelled. - The SSE response stream is wrapped in a guard that cancels the handler if the stream is dropped before it ends naturally. - When a negotiated request replies directly (JSON mode, or a non-OK status), the receiver is dropped, so a still-running handler is cancelled rather than left emitting into a closed channel. Without this its terminal send fails before adding the termination permit and the serve loop parks forever. Stateful (resumable) mode is intentionally left unchanged: there a disconnect may be recovered via `Last-Event-ID`, so cancelling on disconnect would break resumption. Adds a regression test covering both stateless sub-modes (SSE and JSON). |
||
| .. | ||
| src | ||
| tests | ||
| build.rs | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| README.md | ||
The official Rust SDK for the Model Context Protocol. Build MCP servers that expose tools, resources, and prompts to AI assistants — or build clients that connect to them.
For getting started, usage guides, and full MCP feature documentation (resources, prompts, sampling, roots, logging, completions, subscriptions, etc.), see the main README.
Feature Flags
| Feature | Description | Default |
|---|---|---|
server |
Server functionality and the tool system | ✅ |
client |
Client functionality | |
macros |
#[tool] / #[prompt] macros (re-exports rmcp-macros) |
✅ |
schemars |
JSON Schema generation for tool definitions | |
auth |
OAuth 2.0 authentication support | |
elicitation |
Elicitation support |
Transport features
| Feature | Description |
|---|---|
transport-io |
Server-side stdio transport |
transport-child-process |
Client-side stdio transport (spawns a child process) |
transport-async-rw |
Generic async read/write transport |
transport-streamable-http-client |
Streamable HTTP client (transport-agnostic) |
transport-streamable-http-client-reqwest |
Streamable HTTP client with default reqwest backend |
transport-streamable-http-server |
Streamable HTTP server transport |
TLS backend options (for HTTP transports)
| Feature | Description |
|---|---|
reqwest |
Uses rustls — pure Rust TLS (recommended default) |
reqwest-native-tls |
Uses platform-native TLS (OpenSSL / Secure Transport / SChannel) |
reqwest-tls-no-provider |
Uses rustls without a default crypto provider (bring your own) |
Transports
The transport layer is pluggable. Two built-in pairs cover the most common cases:
| Client | Server | |
|---|---|---|
| stdio | TokioChildProcess |
stdio |
| Streamable HTTP | StreamableHttpClientTransport |
StreamableHttpService |
Any type that implements the Transport trait can be used. The IntoTransport helper trait provides automatic conversions from:
(Sink, Stream)or a combinedSink + Stream(AsyncRead, AsyncWrite)or a combinedAsyncRead + AsyncWrite- A
Workerimplementation - A
Transportimplementation directly
License
This project is licensed under the terms specified in the repository's LICENSE file.