Перейти к содержимому
Выберите тему

Производительность

Что протокол MCP редакции 2026-07-28 даёт для скорости и масштабирования - отсутствие сессий, подсказки кэширования, отмена, потоки SSE - и где начинается практика

описана редакция 2026-07-28, сверено со спецификацией и документацией nginx 4 октября 2026

Средство Что оно даёт Сила Где описано
Нет сессий запрос можно отдать любому экземпляру сервер не должен полагаться на прежние запросы основы протокола
ttlMs, cacheScope клиент реже запрашивает списки заново сервер обязан их указывать Caching
Постоянный порядок инструментов стабильный кэш списка и кэш запроса к модели серверу следует Tools
Постраничная выдача длинный список не приходит одним ответом размер страницы выбирает сервер Pagination
Отмена сервер не тратит ресурсы на ненужный запрос серверу следует остановить работу Cancellation
X-Accel-Buffering: no события SSE не задерживаются в прокси серверу следует Streamable HTTP
Заголовки Mcp-Method, Mcp-Name посредник направляет запрос, не разбирая тело Mcp-Method обязателен во всех запросах, Mcp-Name - в tools/call, resources/read и prompts/get там же

По основам протокола MCP в этой редакции - протокол без состояния: всё нужное для обработки запроса есть в самом запросе.

  • Сервер не должен полагаться на прежние запросы по тому же соединению, чтобы узнать версию протокола, возможности клиента или его имя. Эти сведения приходят в _meta каждого запроса.
  • Серверу не следует требовать, чтобы клиент выполнял связанные операции через то же соединение или тот же процесс.
  • Состояние, которое должно жить дольше одного запроса, обязано адресоваться явным идентификатором, который клиент передаёт в каждом запросе.

Журнал изменений редакции удаляет сессии протокола и заголовок Mcp-Session-Id из Streamable HTTP. Механизм MRTR описан в спецификации как способ получить от клиента дополнительные данные без общего хранилища между экземплярами и без балансировки с учётом состояния.

Следствие: самому протоколу Modern привязка клиента к экземпляру не нужна. Это не снимает вопроса о состоянии вашего приложения. Если инструмент создаёт что-то долгоживущее, все экземпляры должны уметь найти это по идентификатору из запроса. Как это устроить, спецификация не определяет.

Правила взяты со страницы Caching.

Сервер обязан включать подсказки в завершённые результаты шести операций: server/discover, tools/list, prompts/list, resources/list, resources/templates/list, resources/read. Промежуточные результаты с resultType: "input_required" не кэшируются и подсказок не несут.

Сколько миллисекунд клиент может считать результат свежим.

  • Сервер обязан указывать значение не меньше нуля.
  • 0 - результат следует считать устаревшим сразу.
  • Поля нет - клиенту следует принять 0. По спецификации так бывает только у старых серверов.
  • Отрицательное значение клиенту следует считать нулём.

Это подсказка, а не обещание: данные могут измениться раньше срока. Клиенту не следует превращать ttlMs в период опроса. Свежесть проверяется тогда, когда данные понадобились. Реализация, которая всё же опрашивает сервер по расписанию, обязана добавлять случайный разброс и увеличивать паузы.

Значение Кто может хранить ответ
"public" любой клиент, общий шлюз или кэширующий прокси, для любого пользователя
"private" только для того же контекста авторизации; делить кэш между разными контекстами нельзя

Спецификация советует "public" для списков, одинаковых у всех пользователей, и "private" для чтения ресурсов, зависящих от пользователя, и для списков, отфильтрованных под пользователя.

  • Ключ кэша - метод и параметры, влияющие на результат. Клиент не должен отдавать сохранённый ответ на запрос с другим методом или параметрами.
  • Результаты повторных запросов MRTR, то есть запросов с inputResponses или requestState, кэшировать нельзя.
  • Каждая страница списка кэшируется отдельно и несёт свой ttlMs. Сервер обязан ставить один и тот же cacheScope на все страницы одного списка.
  • Уведомление об изменении списка сразу делает сохранённый ответ устаревшим, даже если срок не вышел.
  • Клиент может отдать устаревший ответ, если повторный запрос не удался.

По странице Tools серверу следует возвращать инструменты в одном и том же порядке, пока набор не изменился. Спецификация называет две причины: клиент может надёжно кэшировать список, и чаще срабатывает кэш запроса к языковой модели, когда инструменты входят в её контекст.

Там же сказано, что набор инструментов не должен зависеть от соединения и меняться как побочное действие других запросов. Он может зависеть от авторизации, предъявленной в запросе.

По странице Pagination:

  • Размер страницы выбирает сервер. Клиент не должен рассчитывать на постоянный размер.
  • Курсор - непрозрачная строка. Клиент обязан не разбирать и не менять его.
  • Серверу следует выдавать устойчивые курсоры.

Числа записей на страницу спецификация не называет.

Предела на размер результата инструмента в разделе Tools спецификации нет. Есть одно относящееся к делу средство: инструмент может вернуть ссылку на ресурс (resource_link), то есть URI, по которому клиент сам запросит данные или подпишется на них. Спецификация не называет это способом уменьшить ответ, она лишь разрешает такой вид результата.

Пределы, которые ставит клиент или языковая модель, протоколом не описаны. Смотрите страницу своего клиента в разделе Клиенты MCP.

По странице Cancellation:

  • В Streamable HTTP отмена - это закрытие потока ответа. Сервер обязан считать разрыв соединения клиентом отменой этого запроса.
  • В stdio клиент обязан отправить уведомление notifications/cancelled с номером запроса.
  • Серверу следует прекратить обработку и освободить ресурсы.
  • Реализациям следует ставить время ожидания на все отправленные запросы. Уведомление о ходе выполнения может сбрасывать отсчёт, но предельное время следует соблюдать всегда.

Для производительности важен первый пункт. Сервер, который не замечает закрытия потока, продолжает считать ответ, который никто не прочтёт. В Legacy было наоборот: разрыв соединения отменой не считался.

Значений времени ожидания спецификация не задаёт.

По странице Streamable HTTP:

  • Открывая поток SSE, серверу следует отправить заголовок X-Accel-Buffering: no. Без него прокси может копить сообщения и отдавать их с задержкой.
  • Для долгих потоков, прежде всего у subscriptions/listen, спецификация в примечании предлагает время от времени отправлять строку-комментарий SSE, то есть строку, начинающуюся с двоеточия. Это совет, а не требование. Он не даёт посреднику или клиенту закрыть соединение в тихий период.
  • Возобновления потока по Last-Event-ID нет. Оборванный поток теряет запрос, и клиент обязан отправить его заново как новый, с новым номером запроса (это требование записано в перечне изменений редакции).

Ниже - общие приёмы эксплуатации. Спецификация MCP их не требует.

Спецификация не содержит ни одной цифры производительности. Любое число из чужой статьи относится к чужому серверу, чужим инструментам и чужой сети. Прежде чем что-то менять, измерьте свой сервер: время ответа по каждому инструменту, долю отменённых запросов, время до первого события в потоке.

Для проверки запросов к Streamable HTTP руководство по отладке на сайте MCP называет обычные средства HTTP: curl и вкладку сети в инструментах разработчика браузера. Нагрузочный запрос должен быть настоящим запросом Modern: POST на адрес MCP с заголовками MCP-Protocol-Version, Mcp-Method и, где нужно, Mcp-Name. Иначе вы измеряете скорость отказа с кодом 400.

По документации модуля proxy в nginx:

  • proxy_buffering по умолчанию включена, и nginx сначала собирает ответ в буферы. При выключенной буферизации ответ передаётся клиенту сразу по мере получения.
  • Заголовок ответа X-Accel-Buffering со значением no выключает буферизацию для этого ответа. Директива proxy_ignore_headers может отключить эту способность.
  • proxy_read_timeout отсчитывается между двумя чтениями, а не на весь ответ. Если сервер молчит дольше, соединение закрывается. Отсюда польза строк-комментариев в долгом потоке.

В Modern каждое сообщение клиента - отдельный POST. Сколько при этом открывается соединений TCP, зависит не от MCP, а от HTTP и от настройки посредников.

По документации nginx директива proxy_http_version задаёт версию HTTP для связи с сервером за прокси, и для постоянных соединений рекомендуется версия 1.1 или 2. Директива keepalive в блоке upstream включает хранение простаивающих соединений с серверами за прокси для повторного использования. Значения по умолчанию у обеих директив менялись между версиями nginx, поэтому сверяйтесь с документацией своей версии.

  • Измерений нет: ни числа запросов в секунду, ни объёма памяти, ни рекомендуемых значений времени ожидания. Их нет в спецификации, а чужие числа к вашему серверу не относятся.
  • Как каждый клиент пользуется ttlMs и cacheScope и соблюдает ли он их, по спецификации установить нельзя. Сведения по SDK - в разделе SDK.
  • Пределы на размер результата инструмента у клиентов и моделей протоколом не заданы.
  • Настройка ядра, пулы соединений с базами данных, очереди и автоматическое масштабирование не рассматриваются: к MCP они отношения не имеют.
  • Балансировка сессий Legacy разобрана не здесь, а на странице про сервер для двух эпох.