Rust SDK (rmcp)
Официальный Rust SDK для MCP - пакет rmcp 3.5.0, установка, редакции протокола, режимы жизненного цикла клиента и то, что обычный вызов serve остаётся в эпохе Legacy.
сверено с выпуском 3.5.0 4 октября 2026
Что это
Заголовок раздела «Что это»Это SDK из репозитория modelcontextprotocol/rust-sdk. В списке официальных SDK он отнесён к первому уровню (Tier 1).
В репозитории два пакета: rmcp - основная реализация протокола, и rmcp-macros - процедурные макросы для описания инструментов. Ветка одна, 3.x. Выпуск 3.5.0 опубликован на crates.io 28 сентября 2026.
Клиент и сервер включаются признаками Cargo. По Cargo.toml пакета, по умолчанию включены base64, macros и server; клиентская часть включается признаком client.
Установка и среда
Заголовок раздела «Установка и среда»cargo add rmcp --features serverКоманда взята из README выпуска. Нужен Rust 1.88 или новее, редакция языка 2024: так записано в корневом Cargo.toml и в данных crates.io. Основные зависимости по README - tokio и serde; схемы JSON в диалекте 2020-12 строит schemars.
Какие редакции понимает выпуск
Заголовок раздела «Какие редакции понимает выпуск»Список версий в model.rs: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25, 2026-07-28.
В том же файле две константы, которые нужно различать:
ProtocolVersion::LATEST- самая новая известная версия, в этом выпуске 2026-07-28;ProtocolVersion::LATEST_WITH_INITIALIZE- самая новая версия, в которой ещё есть рукопожатиеinitialize, то есть 2025-11-25.
README формулирует поддержку так: SDK реализует редакцию 2026-07-28 и остаётся совместимым с 2025-11-25 и более ранними версиями. Чем эпохи различаются, описано на странице о версиях протокола.
Что отправляет клиент по умолчанию
Заголовок раздела «Что отправляет клиент по умолчанию»По README, serve() использует старый жизненный цикл: клиент отправляет initialize, получает согласованные сведения о сервере и отправляет notifications/initialized. Комментарий в service/client.rs подтверждает: поведение ServiceExt::serve осталось старой инициализацией.
Другой порядок выбирается явно, вызовом ClientServiceExt::serve_with_lifecycle с одним из значений ClientLifecycleMode:
| Режим | Что уходит в сеть | Со старым сервером |
|---|---|---|
Initialize | рукопожатие initialize; то же, что serve() | работает |
Discover | server/discover, затем данные клиента в каждом запросе | ошибка, отката нет |
Auto | пробный server/discover | откат на initialize |
В режиме Auto откат происходит, когда сервер сообщает, что он старый, или не отвечает 10 секунд. Версию для отката задаёт поле legacy_version.
use rmcp::{ClientLifecycleMode, ClientServiceExt, ProtocolVersion, model::ClientConfig};
// Start directly with server/discover and include client metadata on every request.let client = ClientConfig::default() .serve_with_lifecycle( transport, ClientLifecycleMode::Discover { preferred_versions: vec![ProtocolVersion::V_2026_07_28], }, ) .await?;
// Or probe the discover lifecycle and fall back when a legacy server reports// that server/discover is not implemented or does not respond within 10 seconds.let client = ClientConfig::default() .serve_with_lifecycle( transport, ClientLifecycleMode::Auto { preferred_versions: vec![ProtocolVersion::V_2026_07_28], legacy_version: Some(ProtocolVersion::V_2025_11_25), }, ) .await?;Пример взят из документации выпуска 3.5.0 и здесь не запускался.
Это отрывок из README: переменная transport в нём создаётся отдельно. По README, при запуске через server/discover уведомление notifications/initialized не отправляется, а каждый следующий запрос несёт версию протокола, сведения о клиенте и его возможности в _meta.
Что принимает сервер
Заголовок раздела «Что принимает сервер»Серверный обработчик в handler/server.rs содержит метод discover и отвечает на запрос server/discover.
Для Streamable HTTP README описывает правило так: редакцию 2026-07-28 rmcp обслуживает без сеансов сам. В ней нет Mcp-Session-Id, отдельного потока GET и DELETE, возобновления по Last-Event-ID.
Настройка legacy_session_mode в StreamableHttpServerConfig относится только к версиям старше 2026-07-28. По tower.rs, её значение по умолчанию - true: старые клиенты получают сеанс. Вызов with_legacy_session_mode(false) обслуживает без сеансов и старые версии.
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() }}
#[tokio::main]async fn main() -> anyhow::Result<()> { let service = Calculator.serve(stdio()).await?; service.waiting().await?; Ok(())}Пример взят из документации выпуска 3.5.0 и здесь не запускался.
Транспорты подключаются признаками Cargo. По таблице в README: stdio - transport-io, запуск дочернего процесса на стороне клиента - transport-child-process, сервер Streamable HTTP - transport-streamable-http-server (служба Tower, которую можно подключить к любому маршрутизатору), клиент Streamable HTTP - transport-streamable-http-client-reqwest.
Расширения
Заголовок раздела «Расширения»Tasks. Реализовано. По README, rmcp реализует расширение MCP Tasks (SEP-2663, io.modelcontextprotocol/tasks). Клиент объявляет расширение в своих возможностях, а сервер для каждого запроса решает, оформлять ли вызов tools/call как задачу. Клиент опрашивает tasks/get, отвечает на запросы ввода через tasks/update и может запросить отмену через tasks/cancel. На стороне сервера задачами управляет rmcp::task_manager::TaskManager.
MCP Apps. Отдельной реализации нет. В выпуске есть только общая карта возможностей extensions, а идентификатор io.modelcontextprotocol/ui встречается как пример ключа в одном тесте в capabilities.rs. Программного интерфейса для Apps и раздела о них в README нет. То есть объявить возможность можно, а всё остальное вы пишете сами.
Что такое расширения и как о них договариваются стороны - на странице о расширениях.
Устаревшее, что выпуск ещё содержит
Заголовок раздела «Устаревшее, что выпуск ещё содержит»- Roots, Sampling, Logging. В README каждая из трёх возможностей помечена как устаревшая по SEP-2577 с оговоркой, что пока она полностью работает и будет удалена в одном из будущих выпусков.
- Сеансы и
initialize. Сохранены для версий старой эпохи:legacy_session_modeна сервере иserve()на клиенте. - Динамическая регистрация клиента. По документу об OAuth, клиент выбирает способ регистрации по порядку: заранее выданные данные клиента, затем Client ID Metadata Documents, затем динамическая регистрация как запасной путь.
- HTTP+SSE. Старого транспорта из двух адресов в выпуске нет, и это решение проекта: README выпуска называет его осознанным отказом и сообщает, что ни клиентского, ни серверного транспорта HTTP+SSE SDK не поставляет и возвращать не будет. К серверу, который умеет только HTTP+SSE, клиент на
rmcpне подключится. Признакclient-side-sse- это разбор потока SSE внутри клиента Streamable HTTP, а не старый транспорт.
Общий список - на странице об устаревших возможностях.
Выпуск и ветка main
Заголовок раздела «Выпуск и ветка main»На 4 октября 2026 ветка main опережает метку rmcp-v3.5.0 на четыре изменения: два касаются служебной автоматики репозитория, одно - уведомления хранилищ учётных данных при отклонённом токене обновления, одно - примера. Константы версий протокола совпадают с выпуском, номер версии пакета в main по-прежнему 3.5.0. Пробных выпусков новее 3.5.0 на crates.io нет.
Что неизвестно
Заголовок раздела «Что неизвестно»- Помечена ли динамическая регистрация клиента как устаревшая в коде выпуска: документ об OAuth называет её запасным путём, но об устаревании не говорит.
- Содержимое опубликованного архива пакета отдельно не распаковывалось: сверялись исходники по метке выпуска и данные crates.io.