Сразу вывод: шлюз сыграет роль MCP Server. Контракт обнаружения — по-прежнему JSON-документ. 24 сентября 2026 блог разработчиков Google написал: Cloud API Gateway в Public Preview может выставить уже развёрнутые операции OpenAPI 3.x как удалённые MCP-инструменты — без отдельного MCP Server, который нужно писать и хостить. Документация вышла раньше: в release notes от 11 сентября уже стоит Enable MCP. Шлюз принимает стандартный JSON-RPC на /mcp, транскодирует tools/call в существующий REST-запрос и держит JWT, API Key, квоты и логи на одном пути политик. Агент видит не «REST стал магией». Он видит имена инструментов и input schema из tools/list — всё ещё JSON.
Текст актуален на 30 сентября 2026, по тому посту и документации API Gateway, которые в тот день ещё действовали. На сайте уже есть что такое MCP, почему обнаружение Skill всё ещё JSON и вредоносный JSON и Tool Calling. Этот текст только отвечает: какой слой JSON проверять первым, когда OpenAPI сел на шлюз, и какой слой по умолчанию открыт.
Что на самом деле вышло как «шлюз как MCP Server»
Официальная формулировка короткая: большая часть корпоративных возможностей сидит за REST; агенты её не видят. Обычно команды поднимают второй MCP Server и заново реализуют маршрутизацию, auth и квоты. API Gateway — лёгкий вход в линейке шлюзов Google Cloud. Сервис на Cloud Run, который нужно за минуты взять под управление и отдать агентам, идёт сюда. Полный жизненный цикл, тяжёлые политики трафика и монетизация остаются на Apigee. Исходящие вызовы агента, включая такие MCP Server, идут через Agent Gateway. Исходящая маршрутизация модели — другое направление, и её нельзя писать в одном API config с MCP.
Поддерживаются только четыре метода жизненного цикла: initialize, notifications/initialized, tools/list и tools/call. Всё остальное (resources/*, prompts/*) возвращает JSON-RPC -32601. Транспорт — HTTP POST. stdio нет. Пример заголовка — MCP-Protocol-Version: 2025-11-25. Сама спецификация сдвинула рукопожатие в 2026-07-28; этот preview фиксирует 2025-11-25. Даже строка версии — поле, которое сначала выравнивают в JSON-конверте.
Это не писать ещё один MCP Server
Транскодированный REST-запрос неотличим от вызова из браузера или SDK. Квота считается по операции; MCP и REST делят один лимит. Бэкенд не растит второй интерфейс для агентов. Меняется обнаружение: раньше люди читали OpenAPI; теперь модель читает JSON Schema внутри tools/list.
| Слой | Раньше | После Gateway MCP |
|---|---|---|
| Человеческий контракт | OpenAPI 2.0 / 3.x, часто YAML | Сначала нужно поднять до OpenAPI 3.0.x или 3.1.x |
| Обнаружение агентом | Свой hosted tools/list | Шлюз собирает tools/list из той же спецификации |
| Вызов | REST или свой tools/call | JSON-RPC tools/call → исходный REST |
| Auth / квота | Политика шлюза, иногда написанная дважды | По-прежнему политика шлюза; обнаружение — отдельный дефолт |
Так что «не нужно держать MCP Server» — не «не нужно держать JSON-контракт». Пустые описания, глубокие объекты и остатки 2.0 всплывают на обнаружении или при транскодинге. См. что такое MCP.
Контракт вырастает из OpenAPI 3.x
MCP включают на уровне документа через x-google-api-management.mcp. На отдельной операции x-google-mcp-tool может переименовать, переписать описание или поставить false, чтобы выйти. Каждая выставляемая операция нужна с бэкендом и непустым description. Подходят только GET / POST / PUT / PATCH / DELETE. Имена инструментов должны совпадать с [A-Za-z0-9_.-]{1,128} и быть уникальными на всём шлюзе.
Официальная минимальная форма (на странице YAML; семантика — JSON-объект):
x-google-api-management:
mcp: true
paths:
/orders/{orderId}:
get:
operationId: getOrderStatus
description: Returns the current status, carrier, and ETA for an order.
x-google-mcp-tool:
name: get_order_status
description: "Look up the delivery status and ETA of a customer order."
parameters:
- name: orderId
in: path
required: true
schema:
type: string
Описание — главный сигнал, по которому модель решает, когда вызывать. Google просит when / why, а не только что возвращается. Schema пути, query, body и заголовков становятся arguments инструмента. Вложенные объекты в tools/list могут раскрыться не полностью — задокументированное ограничение preview, не сломанный валидатор. Сначала разгладьте OpenAPI локально, затем сделайте Diff с input schema шлюза.
tools/list по умолчанию без аутентификации
По умолчанию кто угодно может сделать POST /mcp и получить каталог: имена, описания, input schema. Для разработки удобно. В продакшене это публикует контракт параметров. Google рекомендует JWT на tools/list. В Public Preview API Key этот метод не защитит. Объектная форма тоже включает MCP глобально; операции, которые не хотите выставлять, нужно пометить x-google-mcp-tool: false.
x-google-api-management:
mcp:
tools-list:
security:
orderServiceJwt: []
tools/call всегда применяет auth нижележащего REST — заперто обнаружение или нет. Открытый каталог и запертый вызов — разные вещи. Если имена инструментов и schema — секрет, заприте tools/list до выкладки. Это тот же слой, что гайд по вредоносному JSON: чем шире контракт, который видит модель, тем шире поверхность инъекции.
tools/call по-прежнему JSON-RPC
На проводе официальная форма такая:
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"get_order_status","arguments":{"orderId":"A-1042"}}}
Шлюз раскладывает arguments обратно в path / query / body / header, прогоняет политику и заворачивает ответ бэкенда в MCP result. При отладке разделяйте слои: внешний конверт — JSON-RPC; внутренняя нагрузка — бизнес-JSON. Ошибка parse принадлежит одному слою или другому. Пример ADK направляет Streamable HTTP на …/mcp и по-прежнему может слать те credentials, которые шлюз уже ждёт.
Подключите шлюз к API hub — конфиг с включённым MCP публикуется с MCP-метаданными и появляется в Agent Registry. Каталог обнаружения сменился. Полевой контракт — нет: это всё та же schema, выросшая из вашего OpenAPI. Обнаружение Skill — другой JSON-документ; см. SEP-2640 и skill://index.json. Не сливайте эти два каталога в одну таблицу.
Ограничения, которые стоит прочитать в Public Preview
- OpenAPI 2.0 не поддерживается. Сначала поднимите до 3.x.
- Операции с пустым телом (HTTP 204) не выставляются как инструменты.
- Слишком глубокие object schema в
tools/listмогут обрезаться. - Один шлюз отдаёт примерно до 1 000 инструментов.
- MCP и маршрутизация модели не делят один API config.
- resources / prompts, потоковые ответы и проверки Model Armor ещё на roadmap.
Это не «потом отполируем». Операция с 204 исчезает из каталога, и модель вызовет что-то другое. Обрезанная schema не сойдётся со строгим валидатором и с настоящим бэкендом. Гайд миграции MCP 2026 про версии протокола. Эта статья добавляет: список, который генерирует шлюз, может не равняться полному OpenAPI в репозитории.
Четыре JSON-документа до включения тумблера
- OpenAPI 3.x в репозитории. Сначала поднимите 2.0. У каждой выставляемой операции — непустой description, бэкенд и допустимое имя инструмента.
tools/listшлюза. Смотрите, не обрезана ли input schema и не утекли ли лишние операции.- Один настоящий
tools/call. Раскладываются ли arguments обратно в REST? Конверт — JSON-RPC 2.0? - Объект безопасности обнаружения. Не выкатывайте с открытым
tools/list. Имя JWT-схемы должно уже быть вcomponents.securitySchemes.
Смотреть спецификацию локальными JSON-инструментами
Прежде чем включать MCP, разложите в браузере три текста: OpenAPI (YAML сначала в JSON), один ответ tools/list и объект arguments, который отправите в tools/call.
- Валидатор JSON — легальна ли грамматика; если есть Schema — сразу required и лишние ключи.
- JSON ↔ YAML — большинство OpenAPI лежит YAML; сначала конвертируйте, потом Diff с list.
- JSON Diff — сравните parameters schema в репозитории с inputSchema, который вернул шлюз.
Ничего не уходит из браузера. Разгладьте контракт, потом включайте тумблер шлюза. Шлюз транскодирует. Имена полей и список required не должны разъезжаться вместе с обрезкой preview.
FAQ
Это GA? Свой MCP Server всё ещё нужен?
На 30 сентября 2026 это Public Preview. REST плюс OpenAPI 3.x и четыре метода жизненного цикла можно посадить на шлюз. Resources, prompts, стриминг, stdio или больше примерно 1 000 инструментов — по-прежнему свой сервер.
Если tools/list открыт, разве API Key не защищает вызовы?
Вызовы идут по политике REST. Каталог по умолчанию публикует имена и input schema. API Key не защитит tools/list. В продакшене заприте обнаружение JWT.
Спецификация всё ещё OpenAPI 2.0 / Swagger. Можно включить?
Нет. Сначала поднимите до 3.0.x или 3.1.x, затем добавьте расширение mcp.
Это то же самое, что обнаружение Skill по SEP-2640 в сентябре?
Нет. Обнаружение Skill — skill://index.json или skills/list. Путь шлюза превращает REST-операции в tools/list. Два JSON-документа, два набора полей.
Почему schema в tools/list мельче, чем в OpenAPI?
Preview пишет: глубокие объекты могут раскрыться не полностью. Верьте ответу шлюза. Diff с спецификацией в репозитории покажет, какие required пропали.
Куда делся DELETE, который возвращает 204?
Операции с пустым телом не выставляются как инструменты. Модель не увидит это имя и не вызовет его.
Итог
API Gateway забирает процесс MCP Server. JSON-контракт он не забирает. OpenAPI 3.x вырастает в tools/list. tools/call остаётся JSON-RPC. Политика — та же REST, что уже есть. Открытый каталог, обрезанная вложенная schema и пропавшая операция с 204 — проверки до запуска, не «preview включили и готово».
Сначала разгладьте OpenAPI, ответ list и образец call локально, потом ставьте mcp: true. Шлюз транскодирует. Полевой контракт не должен разъезжаться вместе с ограничениями preview.