Многошаговые запросы (MRTR)
Multi Round-Trip Requests в MCP 2026-07-28 - как сервер запрашивает у клиента дополнительные данные через InputRequiredResult, inputRequests, inputResponses и requestState
появился в редакции 2026-07-28, сверено со спецификацией 4 октября 2026
Источник - страница Multi Round-Trip Requests спецификации. Порядок введён изменением SEP-2322.
Что он заменил
Заголовок раздела «Что он заменил»До редакции 2026-07-28 сервер отправлял клиенту собственные запросы: elicitation/create, sampling/createMessage, roots/list. Когда сервер работает в нескольких экземплярах, для этого требовалось общее хранилище или привязка клиента к одному экземпляру. Теперь сервер обязан использовать MRTR; прежний способ не поддерживается. Спецификация прямо называет это несовместимым изменением.
Четыре шага
Заголовок раздела «Четыре шага»- Клиент отправляет обычный запрос.
- Сервер понимает, что данных не хватает, и отвечает результатом с
resultType: "input_required". - Клиент получает нужное у пользователя или из других источников и повторяет исходный запрос, добавив ответы.
- Сервер выполняет запрос и возвращает итог.
Два запроса полностью независимы. Серверу, который обрабатывает повтор, не нужно ничего, кроме самого повтора. Поэтому повтор может попасть на другой экземпляр сервера.
Где это разрешено
Заголовок раздела «Где это разрешено»Сервер может вернуть «нужны данные» только на три запроса клиента.
| Запрос | Можно |
|---|---|
tools/call |
да |
resources/read |
да |
prompts/get |
да |
| любой другой | нет |
Первый ответ сервера
Заголовок раздела «Первый ответ сервера»{ "jsonrpc": "2.0", "id": 1, "result": { "resultType": "input_required", "inputRequests": { "github_login": { "method": "elicitation/create", "params": { "mode": "form", "message": "Please provide your GitHub username", "requestedSchema": { "type": "object", "properties": { "name": { "type": "string" } }, "required": ["name"] } } } }, "requestState": "eyJzdGVwIjoxfQ" }}| Поле | Что это |
|---|---|
inputRequests |
набор вопросов к клиенту; ключи придумывает сервер, они уникальны в пределах запроса |
requestState |
непрозрачная строка, понятная только серверу |
В ответе обязано быть хотя бы одно из двух полей.
Вопросом может быть один из трёх запросов: elicitation/create (вопрос пользователю), sampling/createMessage или roots/list. Последние два относятся к функциям, которые объявлены устаревшими. Сервер не должен задавать вопрос, поддержку которого клиент не объявил в своих возможностях.
Повтор от клиента
Заголовок раздела «Повтор от клиента»{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "location": "New York" }, "inputResponses": { "github_login": { "action": "accept", "content": { "name": "octocat" } } }, "requestState": "eyJzdGVwIjoxfQ" }}Требования к клиенту:
- если в ответе есть
inputRequests, клиент обязан собрать ответы до повтора; если нет - может повторить сразу; requestStateвозвращается точно таким, каким пришёл; разбирать и менять его нельзя; если сервер его не присылал, добавлять его в повтор нельзя;- у повтора обязан быть другой
id: это отдельный запрос; inputRequestsиrequestStateотносятся только к повтору этого запроса, в других запросах их использовать нельзя.
Сервер не должен рассчитывать, что клиент обязательно ответит или повторит запрос. Если в повторе не хватает нужных данных, серверу следует снова вернуть «нужны данные», а не ошибку.
requestState - данные от возможного злоумышленника
Заголовок раздела «requestState - данные от возможного злоумышленника»Строка проходит через клиента, поэтому сервер обязан считать её входом, которым управляет атакующий.
- Если от
requestStateзависят права, доступ к ресурсам или логика, сервер обязан защитить её целостность (например, HMAC) и отклонять строку, не прошедшую проверку. - От повторного использования серверу следует защищаться, включив в защищённую часть: кто сделал запрос, короткий срок действия и признак исходного запроса.
- Эти меры сокращают окно для повтора, но не гарантируют одноразовость. Если строка должна сработать ровно один раз, сервер обязан обеспечить это сам.
Защиту целостности можно не делать только тогда, когда подделка не даёт ничего, кроме отказа запроса.
Результат «нужны данные» не кэшируется. Итог запроса, полученный после повтора с inputResponses или requestState, кэшировать тоже нельзя.
Что читать дальше
Заголовок раздела «Что читать дальше»- Elicitation - самый частый вопрос сервера: спросить пользователя.
- Ядро без состояния - почему протокол отказался от запросов со стороны сервера.
- Переход на 2026-07-28 - что менять в сервере, который раньше сам отправлял запросы.