Удаленные серверы MCP используют OAuth 2.0 с шаблоном обнаружения, определенным в RFC 9728 (Protected Resource Metadata, или PRM). RFC 9728 требует, чтобы поле ресурса в документе PRM соответствовало URL, который клиент фактически вызвал — байт за байтом. Это единственное правило, которое заставляет разместить обратный прокси перед удаленным сервером MCP: клиент вызывает URL прокси, PRM поставщика upstream рекламирует URL поставщика, две строки не совпадают, и OAuth-поток прерывается до начала.
В этом посте рассматриваются причины несоответствия, почему простое перенаправление не может работать, а также небольшая служба переписывания PRM на MuleSoft Omni Gateway, которая решает эту проблему, не затрагивая авторизационный сервер поставщика. В результате стандартизированные клиенты MCP (VS Code, Claude Code, Cursor) могут общаться с Figma, GitHub, Atlassian, Linear, Notion и внутренними серверами MCP через единственный контролируемый предприятием путь без отклонения клиентом рукопожатия.
Примечание: О названных поставщиках. Figma, GitHub, Atlassian, Linear, Sentry, Notion и AWS названы в качестве иллюстративных примеров поставщиков, которые на момент написания статьи публично выпустили удаленные конечные точки MCP. Это не исчерпывающий список, и шаблон не является специфичным для поставщика. Он применим к любому HTTP-серверу MCP, который рекламирует метаданные защищенного ресурса (PRM) в соответствии с RFC 9728.
Что дает шаблон прокси?
- Единый шлюз перед каждым удаленным или внутренним сервером MCP, который становится точкой подключения для любых политик шлюза, которые предприятие уже использует для исходящего API-трафика.
- Сохранен нативный UX OAuth — браузерный поток авторизационного кода + PKCE работает напрямую между клиентом и авторизационным сервером поставщика (например, api.figma.com, github.com/login/oauth).
- Подключение нового утвержденного сервера MCP осуществляется путем изменения конфигурации, а не путем разработки нового проекта.
- Совместимость со стандартизированными клиентами MCP (VS Code, Claude Code, Cursor).
Как работает удаленная аутентификация MCP (RFC 9728)
Удаленный сервер MCP — это HTTP-конечная точка (обычно SSE / streamable), которая использует JSON-RPC в соответствии со спецификацией MCP. Когда неаутентифицированный клиент пытается с ним связаться, сервер выдает вызов OAuth 2.0 с использованием шаблона, определенного в RFC 9728 (Protected Resource Metadata).
Полный процесс рукопожатия от VS Code (IDE) → Omni Gateway → MCP Server (пример удаленного сервера Figma MCP) выглядит следующим образом:
Три фазы рукопожатия
Фаза А — Вызов: клиент (например, VS Code) отправляет неаутентифицированный запрос инициализации JSON-RPC. Шлюз отклоняет его с кодом 401 Unauthorized, содержащим заголовок WWW-Authenticate: Bearer, указывающий клиенту на необходимость обнаружения.
Фаза B — Обнаружение и OAuth-танец: клиент переходит по ссылке обнаружения, чтобы получить метаданные защищенного ресурса (PRM) и метаданные сервера авторизации. Затем он запускает браузерный поток авторизационного кода + PKCE напрямую против реального сервера авторизации (например, api.figma.com), чтобы получить токен Bearer.
Фаза C — Аутентифицированный трафик MCP: клиент прикрепляет токен доступа ко всем последующим запросам JSON-RPC (открытие потоков SSE, перечисление подсказок, обнаружение инструментов).
Техническая проблема: строгое соответствие PRM
RFC 9728 определяет правило проверки, чтобы предотвратить фишинг и кражу учетных данных: строка ресурса внутри полезной нагрузки PRM должна соответствовать запрошенному URL байт за байтом.
Это соответствие предотвращает возможность для атакующего подделать метаданные ресурса или обмануть AI-клиент, чтобы тот запустил OAuth-поток против несанкционированного или вредоносного сервера авторизации. Это также означает, что центральный шлюз не может просто передать необработанный ответ PRM поставщика upstream без изменений.
Почему простое перенаправление не работает
Когда прокси пересылает нативный ответ PRM поставщика upstream, несоответствие URL прерывает аутентификацию:
Клиент оценивает ответ по адресу, который он фактически вызвал https://mulesoft-omni-gateway.cloudhub.io/figma/, и прерывает выполнение:
Архитектура и конфигурации
Чтобы решить проблему несоответствия метаданных, ответ PRM должен быть динамически переписан в процессе передачи, чтобы поле ресурса отражало имя хоста корпоративного прокси, ожидаемое клиентом, оставляя при этом авторизационные цели поставщика нетронутыми.
Эта архитектура использует три API-инстанса на Anypoint API Manager (перед которыми стоит Flex Gateway), сочетающиеся с приложением Mule 4 для обработки преобразований метаданных.
Маршрутизация Omni Gateway
Примечание: Чистые прокси поставщиков передают заголовки (Authorization, Accept, Content-Type, Mcp-Protocol-Version, Mcp-Session-Id) и полезные нагрузки JSON-RPC напрямую upstream без преобразования.
Конфигурация на стороне клиента (mcp.json)
Разработчики настраивают свои локальные AI-инструменты с использованием конечных точек корпоративного шлюза:
Служба преобразования PRM Mule
- Имя приложения Mule: mcp-oauth-prm-metadata
- Путь прослушивателя: /* (шлюз удаляет префикс /.well-known/oauth-protected-resource/ перед передачей пути)
- Метод: GET
- Логика: перехватывает исходящие запросы метаданных PRM, переписывает поле ресурса, чтобы оно соответствовало URI корпоративного прокси, ожидаемому клиентом, и возвращает измененную полезную нагрузку метаданных.
Полный скрипт DataWeave
var host = attributes.headers["x-forwarded-host"] default "mulesoft-omni-gateway.cloudhub.io" var upstream = ((attributes.requestPath splitBy "/") filter (!isEmpty($)))[0] default ""
var registry = { "figma": { resource_name: "Figma MCP Server (via customer proxy)", authorization_servers: ["https://api.figma.com"], scopes_supported: ["mcp:connect"] }, "github": { resource_name: "GitHub MCP Server (via customer proxy)", authorization_servers: ["https://github.com/login/oauth"], scopes_supported: [ "repo", "read:org", "read:user", "user:email", "read:packages", "write:packages", "read:project", "project", "gist", "notifications", "workflow", "codespace" ] }}
var entry = registry[upstream]---if (entry == null) { error: "unknown_upstream", upstream: upstream }else { resource: "https://" ++ host ++ "/" ++ upstream ++ "/", resource_name: entry.resource_name, authorization_servers: entry.authorization_servers, scopes_supported: entry.scopes_supported, bearer_methods_supported: ["header"] }
Защита самой службы переписывания PRM
Конечная точка обнаружения PRM намеренно неаутентифицирована — RFC 9728 требует, чтобы клиент мог достичь /.well-known/oauth-protected-resource, прежде чем у него появится какой-либо токен. Это не означает, что конечная точка является ненадежной зоной. Ответ сообщает клиенту, с каким сервером авторизации поговорить; если атакующий мог бы повлиять на этот ответ, он мог бы перенаправить OAuth-поток на поддельный сервер авторизации. Конкретные меры по усилению защиты этой службы основаны на следующем:
- Статический реестр, не отражающий ненадежный ввод. Значения authorization_servers и scopes_supported извлекаются из встроенного реестра, ключом которого является slug upstream. Ничто из тела запроса, строки запроса или произвольных заголовков не выводится в эти поля. Единственное значение, полученное из запроса, в ответе — это хост, используемый для построения ресурса, который берется из доверенного заголовка x-forwarded-host, установленного шлюзом (см. следующий пункт).
- Только доверенный x-forwarded-host. Поскольку заголовок x-forwarded-host учитывается, конечная точка должна быть доступна только через Flex Gateway, который устанавливает этот заголовок в обязательном порядке. Прямой доступ к URL-адресу CloudHub (mcp-oauth-prm-metadata.cloudhub.io) должен быть заблокирован на сетевом уровне или путем требования учетных данных клиента, выданных шлюзом, на внутреннем переходе, чтобы злоумышленник не мог напрямую внедрить контролируемое им значение x-forwarded-host.
- Только HTTPS, HSTS. TLS принудительно используется шлюзом; переход на HTTP позволил бы сетевому злоумышленнику переписать ответ и обойти все остальные перечисленные здесь средства контроля.
- Доступность только через корпоративную VPN / сеть. Подобно тому, как SSO ограничивает круг лиц, которые могут пройти аутентификацию, это ограничивает места, откуда вообще можно получить доступ к конечной точке. Поскольку конечная точка PRM намеренно не требует аутентификации, ограничение на сетевом уровне является самой важной мерой защиты — клиент вне сети не может выполнить TCP-рукопожатие со шлюзом, не говоря уже о перечислении зарегистрированных восходящих потоков. Типичные уровни обеспечения безопасности в порядке строгости: Частный DNS + частная сеть. Шлюз защищен частной конечной точкой (например, AWS PrivateLink, Azure Private Endpoint или CloudHub VPC без публичного входящего трафика). Его DNS-имя разрешается только внутри корпоративной сети / VPN с разделенным туннелированием; клиенты вне сети получают NXDOMAIN или немаршрутизируемый адрес. Белый список IP-адресов. Шлюз или его входной WAF принимает соединения только из диапазонов исходящего трафика корпоративной VPN и известных CIDR офиса. Аттестация устройств / mTLS с управляемых устройств. В дополнение к вышесказанному: шлюз требует клиентский сертификат, предоставленный MDM на ноутбук разработчика, поэтому злоумышленник, который каким-то образом попал в VPN, все равно не сможет получить доступ к шлюзу с неуправляемого устройства.
- Частный DNS + частная сеть. Шлюз защищен частной конечной точкой (например, AWS PrivateLink, Azure Private Endpoint или CloudHub VPC без публичного входящего трафика). Его DNS-имя разрешается только внутри корпоративной сети / VPN с разделенным туннелированием; клиенты вне сети получают NXDOMAIN или немаршрутизируемый адрес.
- Белый список IP-адресов. Шлюз или его входной WAF принимает соединения только из диапазонов исходящего трафика корпоративной VPN и известных CIDR офиса.
- Аттестация устройств / mTLS с управляемых устройств. В дополнение к вышесказанному: шлюз требует клиентский сертификат, предоставленный MDM на ноутбук разработчика, поэтому злоумышленник, который каким-то образом попал в VPN, все равно не сможет получить доступ к шлюзу с неуправляемого устройства.
Результатом являются два независимых барьера для этой конечной точки: сетевая доступность (VPN / корпоративная сеть) и целостность ответа (указанные выше элементы управления static-registry и x-forwarded-host). Компрометация одного не позволяет обойти другой.
Двигаясь вперед
Шаблон OAuth PRM Proxy предоставляет командам безопасности единую точку обзора трафика инструментов агентского ИИ, не требуя от разработчиков внедрения фрагментированных потоков аутентификации или пользовательской инфраструктуры.
Централизация удаленного трафика MCP через Anypoint Omni Gateway позволяет предприятиям использовать растущую экосистему инструментов для разработчиков ИИ в рамках тех же средств аудита, белых списков и DLP, которые уже применяются к другому исходящему трафику.
Команды корпоративной безопасности, ИТ и инженерии могут применять шаблон OAuth PRM Proxy для масштабирования подключения агентов ИИ в рамках существующих политик контроля.












