MCP-сервер GitHub стал без состояния и удалил хранилище сессий в Redis
2026-07-23 GitHub выпустил поддержку ревизии MCP 2026-07-28 раньше даты спецификации. Примечательно именно вычитание: нет handshake initialize, нет Mcp-Session-Id, нет Redis.
2026-07-23 GitHub объявил, что MCP-сервер GitHub поддерживает следующую спецификацию MCP, ревизию с датой 2026-07-28, за несколько дней до наступления этой даты. Выставлять ещё не опубликованную ревизию под боевой трафик - это ставка. Читать анонс стоит потому, что все ключевые изменения там являются вычитанием: хранилище сессий в Redis, инспекция пакетов на уровне прокси и запись в базу данных при каждом подключении клиента.
Handshake и заголовок сессии исчезли
Ревизия 2026-07-28 убирает handshake из initialize и notifications/initialized, а также убирает заголовок Mcp-Session-Id из Streamable HTTP. Всё, что раньше устанавливал handshake, теперь едет в каждом отдельном запросе внутри _meta и дублируется в HTTP-заголовках, чтобы балансировщик нагрузки мог маршрутизировать, не разбирая тело:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Seattle, WA" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
Тело остаётся источником истины. Если заголовок с ним расходится, сервер обязан ответить 400 Bad Request с ошибкой JSON-RPC -32020 (HeaderMismatch), что не даёт шлюзу маршрутизировать по одному значению, пока сервер выполняет запрос по другому.
Именно из-за этого изменения зависимость от Redis смогла уйти. Хранилище сессий существовало только для того, чтобы второй запрос клиента нашёл состояние, созданное первым. Без handshake состояния искать не нужно, поэтому любой запрос может попасть на любой экземпляр, а инициализация перестаёт писать в базу данных.
Два изменения, которые требуют реальной работы
Запросы, инициированные сервером, исчезли. Sampling, roots и elicitation раньше приходили как JSON-RPC-запросы со стороны сервера. По модели Multi Round-Trip Requests (SEP-2322) сервер вместо этого возвращает resultType: "input_required" с массивом inputRequests, а клиент повторяет исходный вызов, неся в нём inputResponses. GitHub закрыл обе эпохи обёрткой над Go SDK, а не сломал старых клиентов.
Возобновляемость тоже исчезла. Заголовок Last-Event-ID и идентификаторы событий SSE удалены, поэтому оборванный поток ответа теряет выполняемый запрос, и клиент обязан отправить его заново с новым идентификатором запроса. Если ваш сервер рассчитывал на повтор при переподключении, теперь это ваша забота.
Ещё стоит учесть до планирования миграции: Tasks вынесены из ядра в расширение io.modelcontextprotocol/tasks, метод tasks/list удалён, а Roots, Sampling и Logging формально объявлены устаревшими с окном в двенадцать месяцев.
Что это значит для вашего сервера
Если вы уже используете Streamable HTTP без генератора идентификаторов сессии, большая часть пути пройдена, и это практический аргумент в пользу того, чтобы выбирать Streamable HTTP вместо stdio или устаревшего транспорта SSE для всего, что работает по сети. SDK первого уровня выпустили бета-поддержку с сохранением обратной совместимости, поэтому существующим развёртываниям ничего делать не нужно, чтобы продолжать работать. Прочитайте полный список изменений, прежде чем считать, что то же самое верно и для вашего кода.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.