Сэмплирование
MCP 2026-07-28 убрал сэмплирование как push-запрос, управляемый
возможностями. Теперь клиент обрабатывает
input-запросы
sampling/createMessage внутри собственного цикла раундов MRTR, поэтому
вызывающий call_tool по-прежнему видит один вызов.
Весь этот вид устарел с момента появления: Client::map_sampling помечен
#[deprecated] и требует #[allow(deprecated)]. Кроме того, атрибутный
макрос #[sampling] недоступен в сборке по умолчанию — он относится к
легаси-модели с серверным push. Регистрируйте обработчик явным вызовом
map_sampling.
В MCP именно клиент отвечает за выполнение запросов на сэмплирование LLM, инициируемых серверами. В отличие от традиционных архитектур, клиент:
- Владеет доступом к модели и ключами API
- Применяет локальные политики (стоимость, конфиденциальность, ограничения скорости)
- Является посредником во всём взаимодействии с языковыми моделями
Серверы никогда не общаются с LLM напрямую — они только запрашивают сэмплирование.
Важная концептуальная модель
- Сервер запрашивает сэмплирование
- Клиент выполняет сэмплирование
- Клиент принимает решение:
- какую модель использовать
- поддерживаются ли инструменты
- как обрабатываются запросы
- Клиент возвращает структурированные результаты серверу
Конфигурация клиента
Поддержка сэмплирования должна быть явно включена на клиенте:
let mut client = Client::new()
.with_options(|opt| opt
.with_sampling(|s| s.with_tools()));
- with_sampling() включает поддержку сэмплирования
- with_tools() разрешает вызовы инструментов в процессе сэмплирования
Именно регистрация обработчика заставляет клиента объявлять
clientCapabilities.sampling в каждом запросе; сервер может запросить только
тот вид, который клиент объявил, а запрос к необъявившему клиенту приводит к
ошибке, а не к подвисанию раунда.
Обработчик сэмплирования
Зарегистрируйте обработчик через
Client::map_sampling.
Он получает CreateMessageRequestParams и возвращает
CreateMessageResult.
use neva::prelude::*;
use neva::types::sampling::{CreateMessageRequestParams, CreateMessageResult};
async fn complete(params: CreateMessageRequestParams) -> CreateMessageResult {
// Здесь логика сэмплирования на стороне клиента
CreateMessageResult::assistant()
.with_model("o3-mini")
.with_content("...")
.end_turn()
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let mut client = Client::new()
.with_options(|opt| opt.with_default_http());
// Устарело с момента появления, как и весь вид sampling.
#[allow(deprecated)]
client.map_sampling(complete);
client.connect().await?;
// Раунды MRTR происходят внутри этого единственного вызова.
let result = client.call_tool("summarize_report", [("topic", "EMEA")]).await?;
client.disconnect().await
}
Обработчик вызывается один раз на каждый раунд, в котором сервер вызывает Context::sample().
legacy-specСэмплирование работает как серверный push-запрос, а атрибутный макрос
#[sampling]
регистрирует обработчик за вас. См.
Легаси-спецификация.
Анализ запросов на сэмплирование
Входящий CreateMessageRequestParams содержит:
- Сообщения запроса
- Системный запрос
- Предпочтения модели
- Метаданные инструментов
- Предыдущие результаты инструментов (для многошагового сэмплирования)
Доступ к текстовым запросам
let prompts: Vec<&TextContent> = params.text().collect();
Включает все накопленные текстовые сообщения пользователя и ассистента.
Определение запросов на использование инструментов
Клиент может проверить, разрешает ли или ожидает ли сервер использование инструментов через
tool_choice:
if params.tool_choice.is_some_and(|c| !c.is_none()) {
// Модели разрешено или требуется вызвать инструменты
}
Это позволяет клиенту решить, производить ли вызовы инструментов или конечный текст.
Использование инструментов
Если инструменты включены, клиент может ответить запросом на вызов инструмента вместо обычного текста.
CreateMessageResult::assistant()
.with_model("gpt-5")
.use_tools([
("get_weather", ("city", "London"))
])
- Выполнение инструментов всегда осуществляется сервером
- Клиент только возвращает намерение вызвать инструменты
- Аргументы инструментов должны соответствовать схеме инструмента
Обработка результатов инструментов
После выполнения инструментов сервером он отправит повторный запрос на сэмплирование, содержащий результаты инструментов.
Эти результаты доступны через:
let results: Vec<&ToolResult> = params.results().collect();
На этом этапе клиент обычно должен:
- Интерпретировать выходные данные инструментов
- Сформировать финальный ответ ассистента
- Завершить шаг сэмплирования
Формирование финальных ответов
Для возврата обычного сообщения ассистента и завершения цикла сэмплирования:
CreateMessageResult::assistant()
.with_model("gpt-5")
.with_content("Final response text")
.end_turn()
Вызов end_turn() сигнализирует серверу о завершении сэмплирования.
Когда настраивать сэмплирование клиента
Рассмотрите пользовательскую логику сэмплирования, когда:
- Нужно интегрировать проприетарные или локальные модели
- Требуется точный контроль стоимости или задержки
- Нужна фильтрация или аудит запросов
- Требуются детерминированные или политически-управляемые ответы
Обучение на примерах
Полный рабочий пример доступен здесь.