Как настроить MCP-сервер на Python без обрыва ответов: разбор параметров max_sse_event_size и httpx в SDK 2.3.0

Как настроить MCP-сервер на Python без обрыва ответов: разбор параметров max_sse_event_size и httpx в SDK 2.3.0

Официальный релиз SDK 2.3.0 требует библиотеку httpx2 не ниже 2.10.0 и позволяет снять ограничение в 1 МБ на размер SSE-события.

  • 2 октября 2026 года команда Model Context Protocol опубликовала релиз официального Python SDK v2.3.0 под авторством мейнтейнера maxisbey.
  • Официальный репозиторий проекта на GitHub на 2 ноября 2026 года собрал 24 737 звёзд и 4 094 форка.
  • Ключевым техническим изменением стало решение давней проблемы обрыва соединений при передаче больших объёмов данных через протокол Streamable HTTP и транспорт Server-Sent Events (SSE).
  • Ранее при возврате инструментом объёмных текстов, структурированных дампов или фрагментов кода свыше 1 МБ клиент аварийно завершал сессию из-за жёсткого лимита парсера.

Настройка размера SSE-события через max_sse_event_size

  • В релизе SDK 2.3.0 в клиент streamable_http_client и класс конфигурации StreamableHttpParameters добавлен параметр max_sse_event_size.
  • По умолчанию значение параметра сохранено на уровне 1 МиБ (1 048 576 байт), чтобы защитить клиент от переполнения памяти при обработке некорректных потоков данных.
  • Для серверов, возвращающих большие полезные нагрузки, лимит можно увеличить до требуемого объёма в байтах или полностью отключить, передав значение None.
  • Настройка применяется ко всем операциям транспорта: обработке ответов на POST-запросы, чтению входящего потока GET, возобновлению сессий и процедурам повторного подключения.
from mcp.client.streamable_http import StreamableHttpParameters, streamable_http_client # Подключение клиента с увеличенным лимитом SSE-событий до 10 МБ params = StreamableHttpParameters( url="http://localhost:8000/sse", max_sse_event_size=10 * 1024 * 1024, # Число байт или None для снятия лимита ) async with streamable_http_client(params.url, sse_read_timeout=60.0) as session: # Сессия удерживает входящий поток данных без аварийных разрывов pass
Релиз SDK 2.3.0 в официальном репозитории modelcontextprotocol/python-sdk. Источник: GitHub
Релиз SDK 2.3.0 в официальном репозитории modelcontextprotocol/python-sdk. Источник: GitHub

Требования к окружению: библиотека httpx2 не ниже 2.10.0

  • Реализация нового механизма контроля буфера потребовала обновления сетевого стека: минимальная версия библиотеки httpx2 повышена с 2.5.0 до 2.10.0.
  • Вместе с ней в дереве зависимостей обновлён низкоуровневый пакет httpcore2 до версии 2.10.0.
  • Установка и обновление пакета в окружении Python выполняются через официальный репозиторий PyPI.
  • Если в файле pyproject.toml зафиксирована строгая версия httpx2 ниже 2.10.0, её требуется повысить, иначе менеджер пакетов заблокирует обновление.
pip install -U mcp
Пуллреквест <a href="/tag/3600">#3600</a> с добавлением параметра max_sse_event_size в клиенты Streamable HTTP. Источник: GitHub
Пуллреквест #3600 с добавлением параметра max_sse_event_size в клиенты Streamable HTTP. Источник: GitHub

Валидация заголовков x-mcp-header и ошибка InvalidSignature

  • Второе важное изменение версии 2.3.0 затрагивает проверку метаданных инструментов: ранее инструмент с некорректной аннотацией x-mcp-header успешно регистрировался при старте сервера, но клиенты спецификации от 28 июля 2026 года молча удаляли его из списка инструментов.
  • В новой версии декоратор @mcp.tool(), методы add_tool и Tool.from_function сразу вызывают исключение InvalidSignature при попытке зарегистрировать некорректный заголовок.
  • Напрямую разрешены только базовые скалярные типы str, int и bool; типы str | None, float, списки и перечисления напрямую отклоняются.
  • Для создания опционального параметра заголовка документация SDK предписывает явно передавать схему через аннотацию WithJsonSchema.
from typing import Annotated from pydantic import WithJsonSchema from mcp.server.fastmcp import FastMCP mcp = FastMCP("AnalyticsServer") # Корректное объявление опционального заголовка x-mcp-header RegionHeader = Annotated[ str | None, WithJsonSchema({"type": "string", "x-mcp-header": "Region"}), ] @mcp.tool() def query_metrics(metric_name: str, region: RegionHeader = None) -> str: """Запрос метрик с передачей региона через заголовок.""" return f"Метрика {metric_name} для региона: {region or 'глобальный'}"

Повтор запросов и оптимизация обработки вызовов

  • В клиентский метод Client.call_tool встроен автоматический механизм восстановления при ошибке HeaderMismatch (код -32020): получив отказ сервера, клиент заново опрашивает список инструментов и однократно повторяет вызов.
  • Серверный класс MCPServer оптимизировал проверку заголовков Mcp-Param-*: теперь схема инструмента запрашивается по имени напрямую из локального реестра, без вызова тяжеловесного обработчика tools/list на каждый запрос.
  • Для серверов без динамических обновлений добавлен флаг MCPServer(subscriptions=False): он отключает маршрут subscriptions/listen и передаёт клиентам false в полях listChanged и subscribe.
  • Для устаревших соединений по спецификации от 25 ноября 2025 года исключена отправка пустых структур _meta и params, что решило проблемы совместимости со сторонними строгими серверами.
  • Таймауты сетевых запросов больше не сгорают во время интерактивного входа через OAuth: ожидание внутри обработчиков redirect_handler и callback_handler не списывается со счётчика таймаута.

Сводная таблица параметров и настроек SDK 2.3.0

  • max_sse_event_size: по умолчанию равен 1 МиБ (1 048 576 байт), поддерживает целые числа в байтах или None (снятие ограничения).
  • Минимальная версия httpx2: 2.10.0 (ранее допускалась 2.5.0).
  • Минимальная версия httpcore2: 2.10.0.
  • Режим валидации заголовков: мгновенная ошибка InvalidSignature при старте сервера вместо тихого пропуска инструмента на стороне клиента.
  • Флаг subscriptions: MCPServer(subscriptions=False) для полного отключения подписок на изменения списков.
  • Повтор при несовпадении заголовков: 1 автоматическая попытка вызова инструмента после обновления списка.

Всё самое интересное — в нашем Telegram-канале «Claude без воды».