Перейти к основному содержимому
БЛОГ

OAuth discovery для ИИ-агентов: RFC 9728 и RFC 8414

OAuth discovery для ИИ-агентов: 401 ведёт к метаданным ресурса RFC 9728, а те — к метаданным сервера RFC 8414. 2 JSON-файла, 8 ошибок и когда их не публиковать.

Автор: IMozzОбновлено 2026-10-26
OAuth discovery для ИИ-агентов — aiSiteReady

OAuth discovery для ИИ-агентов — это цепочка из двух документов с метаданными: защищённый API отвечает 401 и указывает на метаданные ресурса по RFC 9728, те называют сервер авторизации, а метаданные этого сервера по RFC 8414 перечисляют нужные агенту эндпоинты. Если на вашем сайте ничто не требует токена доступа, обнаруживать нечего, и публиковать не нужно ни один из документов.

Это слой после доступности сайта для вызова агентами. MCP Server Card или каталог API говорят агенту, где живёт ваш API, но не как в него войти. Защищённый API должен ответить на это в машиночитаемом виде. Поддержка зависит от клиента: в MCP она обязательна для MCP-клиентов, а другой агент может вместо неё использовать учётные данные, которые настроил человек.

Ключевые выводы

  • Цепочка: 401 с WWW-Authenticate: Bearer resource_metadata="…", затем /.well-known/oauth-protected-resource (RFC 9728, апрель 2025), затем /.well-known/oauth-authorization-server (RFC 8414, июнь 2018) или OpenID Connect discovery.
  • Каждый документ называет сам себя (resource, issuer). Если значение не идентично идентификатору, из которого построен URL, клиент НЕ ДОЛЖЕН (MUST NOT) использовать данные.
  • Спецификация авторизации MCP (ревизия 2026-07-28, текущая на 2 октября 2026 года) требует от серверов, использующих авторизацию, реализовать RFC 9728 (MCP), а от клиентов — отказываться от сервера авторизации без PKCE (security considerations).
  • Публичным сайтам только для чтения, собственным логинам и API на ключах не нужен ни один из документов. Подделка хуже честного 404.
  • Наше собственное наблюдение по коду проверок aiSiteReady: обе OAuth-проверки становятся неприменимыми, если сигналов OAuth нет, а одна лишь MCP-карточка таким сигналом не считается.

Что такое OAuth discovery и зачем он ИИ-агентам?

OAuth discovery — это способ, которым клиент узнаёт у самого сервера, где получить токен: RFC 9728 описывает защищённый ресурс, RFC 8414 — сервер авторизации. У агента на защищённом эндпоинте нет ни вкладки браузера, ни страницы документации, ни письма с онбордингом — только HTTP-ответ, поэтому следующий шаг должен нести сам ответ. Документ ресурса называет его идентификатор, доверенные серверы авторизации и scope; документ сервера — issuer, эндпоинты и возможности (RFC 9728, RFC 8414).

RFC 9728 прямо описывает последовательность. Клиент обращается без токена. Ресурс отвечает заголовком WWW-Authenticate с URL метаданных. Клиент проверяет эти метаданные, строит URL метаданных сервера авторизации из указанного issuer, запрашивает их, проходит авторизацию и повторяет запрос уже с токеном (RFC 9728, раздел 5).

Диаграмма последовательности: 401 ведёт агента к метаданным ресурса RFC 9728, затем к метаданным сервера RFC 8414, затем поток code с PKCE S256 выдаёт токен.

Шаг 1 — заголовок в ответе 401. Он несёт и параметр scope (RFC 6750, раздел 3), который MCP-серверам СЛЕДУЕТ (SHOULD) указывать (перенос строки — для читаемости):

GET /mcp HTTP/1.1
Host: api.example.com

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp",
                  scope="scans:read"

RFC 9728 вводит один новый параметр, resource_metadata, а его собственный пример — голый Bearer resource_metadata="…" (RFC 9728, раздел 5.1). MCP допускает заголовок, well-known URI или оба способа сразу. Клиенты обязаны поддерживать оба и отдавать приоритет URL из заголовка (MCP, discovery).

Что входит в метаданные защищённого ресурса (RFC 9728)?

Обязательно одно поле — resource. Остальное в RFC необязательно или рекомендуется, и именно здесь MCP строже (RFC 9728, раздел 2).

ПолеСтатус в RFC 9728Что сообщает агенту
resourceREQUIREDИдентификатор ресурса: URL с https без фрагмента
authorization_serversOPTIONAL (в MCP обязательно, минимум один)Issuer серверов, которые выдают токены для этого ресурса
scopes_supportedRECOMMENDEDЗначения scope для запроса доступа
bearer_methods_supportedOPTIONALКак можно передавать токен: header, body или query
resource_nameRECOMMENDEDНазвание для людей

Спецификация MCP требует, чтобы документ ОБЯЗАТЕЛЬНО содержал authorization_servers минимум с одной записью, а клиенты передавали токен в заголовке Authorization, а не в строке запроса (MCP, discovery, MCP, authorization). Поэтому честное значение bearer_methods_supported для MCP-сервера — ["header"]. Минимальный документ для https://api.example.com/mcp:

{
  "resource": "https://api.example.com/mcp",
  "authorization_servers": ["https://auth.example.com"],
  "scopes_supported": ["scans:read", "scans:write"],
  "bearer_methods_supported": ["header"],
  "resource_name": "Example API"
}

Он лежит по адресу https://api.example.com/.well-known/oauth-protected-resource/mcp. Суффикс вставляется между хостом и путём; завершающий слэш после хоста перед этим удаляется. Идентификатор без пути использует «голый» /.well-known/oauth-protected-resource.

Что входит в метаданные сервера авторизации (RFC 8414)?

RFC 8414 требует issuer и response_types_supported. Эндпоинты обязательны, если хотя бы один поддерживаемый grant ими пользуется (RFC 8414, раздел 2).

ПолеСтатус в RFC 8414Зачем это агенту
issuerREQUIREDURL с https без query и фрагмента; идентификатор, с которым документ обязан совпадать
authorization_endpointREQUIRED, если его использует хоть один grantГде пользователь подтверждает доступ
token_endpointREQUIRED, если поддерживается не только implicitГде код меняется на токен
response_types_supportedREQUIRED["code"] для потока authorization code
grant_types_supportedOPTIONALЕсли опущено, подразумевается ["authorization_code", "implicit"]
scopes_supportedRECOMMENDEDScope, которые может запросить агент
registration_endpointOPTIONALДинамическая регистрация клиентов (RFC 7591)
code_challenge_methods_supportedOPTIONALЕсли опущено, PKCE не поддерживается
{
  "issuer": "https://auth.example.com",
  "authorization_endpoint": "https://auth.example.com/authorize",
  "token_endpoint": "https://auth.example.com/token",
  "registration_endpoint": "https://auth.example.com/register",
  "client_id_metadata_document_supported": true,
  "scopes_supported": ["scans:read", "scans:write"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"]
}

Важны две детали. code_challenge_methods_supported — единственный способ узнать, что сервер поддерживает PKCE. А агенты обычно публичные клиенты: none — значение RFC 7591 именно для них, тогда как при опущенном token_endpoint_auth_methods_supported по умолчанию берётся client_secret_basic. Оставляйте registration_endpoint, только если всё ещё поддерживаете Dynamic Client Registration.

Где лежит документ, если у issuer есть путь?

Для issuer https://auth.example.com/tenant1 документ лежит по адресу /.well-known/oauth-authorization-server/tenant1: RFC 8414 вставляет суффикс между хостом и путём issuer. OpenID Connect Discovery, наоборот, добавляет суффикс в конец. Раздел 5 RFC 8414 описывает разницу и разрешает на переходный период публиковать документ в обоих местах (RFC 8414). MCP-клиенты пробуют по порядку: /.well-known/oauth-authorization-server/tenant1, /.well-known/openid-configuration/tenant1, /tenant1/.well-known/openid-configuration (MCP, discovery).

Как строится well-known URL: суффикс встаёт между хостом и путём; для issuer с путём MCP-клиенты пробуют три URL в фиксированном порядке.

Отдавайте оба документа как 200 OK с Content-Type: application/json: этого требует каждый RFC. RFC 9728 добавляет, что действует обычное HTTP-кэширование, и советует Cache-Control с max-age (RFC 9728, раздел 7.10). Ни один RFC не упоминает CORS, но браузерному клиенту, читающему документы с другого origin, нужен Access-Control-Allow-Origin (MDN). Для публичных метаданных без секретов разумно значение *. Это моя рекомендация, а не требование. В nginx это выглядит так:

location = /.well-known/oauth-protected-resource/mcp {
    default_type application/json;
    add_header Cache-Control "public, max-age=3600" always;
    add_header Access-Control-Allow-Origin "*" always;
    alias /srv/metadata/oauth-protected-resource.json;
}

Как авторизация MCP использует эти документы?

MCP требует эту цепочку от каждого HTTP-сервера, который использует авторизацию: сервер публикует метаданные RFC 9728, его сервер авторизации — метаданные RFC 8414 или OpenID Connect, а клиенты проходят по обоим документам. Сама авторизация остаётся необязательной. Ревизия 2026-07-28 значится текущей на странице версий по состоянию на 2 октября 2026 года и задаёт следующие правила (MCP, authorization).

РольТребование в ревизии 2026-07-28
MCP-серверMUST реализовать RFC 9728, указав в authorization_servers минимум один сервер
MCP-серверMUST объявить метаданные через resource_metadata в ответе 401 или по well-known URI
Сервер авторизацииMUST предоставлять метаданные RFC 8414 или OpenID Connect Discovery
MCP-клиентMUST поддерживать оба механизма; сначала URL из заголовка, затем well-known URI
MCP-клиентMUST отвергать метаданные, где issuer отличается от идентификатора, из которого построен URL
MCP-клиентMUST проверять PKCE по code_challenge_methods_supported и отказываться, если поля нет; MUST использовать S256, когда способен

Источники: discovery и security considerations. Строка про PKCE объясняет, почему code_challenge_methods_supported — не украшение: опустите его, и совместимый клиент остановится ещё до экрана согласия.

Регистрация клиентов менялась между ревизиями. В 2025-11-25 Client ID Metadata Documents были SHOULD, а Dynamic Client Registration (RFC 7591) — MAY, оставленным для совместимости (2025-11-25). Ревизия 2026-07-28 объявляет Dynamic Client Registration устаревшей и направляет новые реализации к Client ID Metadata Documents, поддержку которых объявляют через client_id_metadata_document_supported: true. Серверы, которые всё ещё поддерживают Dynamic Client Registration, продолжают объявлять её через registration_endpoint (MCP, client registration).

OAuth 2.1 и Client ID Metadata Documents на 2 октября 2026 года всё ещё были Internet-Draft (ревизии 16 и 02; MCP ссылается в основном на 13 и 00), так что эта часть может снова измениться.

Гайд по Server Card объясняет, где находится MCP-эндпоинт и какой транспорт он использует. Два OAuth-документа говорят, как получить к нему токен. Карточку публикуйте в любом случае, а OAuth-документы — только если сервер защищён.

Какие ошибки ломают OAuth discovery?

Чаще всего это несовпавший идентификатор или ответ, который выглядит как успех, но им не является.

ОшибкаЧто ломаетсяКак исправить
issuer отличается от issuer, из которого построен URL (завершающий слэш, http, прокси подменяет хост)Клиент не должен его использовать (RFC 8414, раздел 3.3); aiSiteReady сообщает issuer_mismatch и ставит PARTIALСтройте issuer и URL из одного значения конфигурации
resource нет или он не равен URL, который запросил клиентПоле обязательно (RFC 9728, раздел 2); несовпадение использовать нельзя (раздел 3.3)Отдавайте канонический URL ресурса
Эндпоинты, которые отвечают 404 или перенаправляют на страницу входаDiscovery работает, а поток падает на authorization_endpoint или token_endpointПрогоните через curl каждый указанный URL; уберите registration_endpoint, если регистрации нет
200 с HTML-страницей на отсутствующий well-known URL (fallback одностраничного приложения)Soft 404: выглядит как успех, затем не парсится как JSON. Сканер фиксирует неподдерживаемый тип содержимого, но не метаданныеОтдавайте JSON раньше fallback-маршрута; для отсутствующего документа возвращайте настоящий 404
Неверный Content-Type, например text/plainОба RFC требуют application/json; сканер помечает unexpected_content_type у метаданных ресурсаЗадайте тип явно, как в блоке nginx
Поля code_challenge_methods_supported нетЗначит, PKCE не поддерживается; MCP-клиенты отказываются продолжатьОбъявите ["S256"], но только если сервер требует PKCE
В code_challenge_methods_supported нет S256 (например, только plain)MCP-клиенты обязаны использовать S256, когда способны; aiSiteReady ставит серверу PARTIALПоддержите и объявите S256
Суффикс дописан в конец для oauth-authorization-serverНе находится: RFC 8414 вставляет суффикс, а в конец его добавляет только OpenID Connect DiscoveryСледуйте порядку поиска выше

«Совпадает» значит «совпадает точно». RFC 8414 сравнивает две строки посимвольно по кодовым точкам, без нормализации, поэтому https://auth.example.com и https://auth.example.com/ — разные значения (RFC 8414, раздел 4). Сейчас aiSiteReady ожидает issuer в корне домена без завершающего слэша, поэтому провайдер, который его ставит (Auth0 публикует https://<tenant>.auth0.com/), получает issuer_mismatch, хотя клиент, построивший URL из этой самой строки, такие метаданные принимает.

Как проверить свой OAuth discovery?

Проверяйте снаружи, как это делает агент: один запрос за challenge и по одному на каждый документ, по публичным URL.

# 1. Challenge: указывает ли защищённый эндпоинт на свои метаданные?
curl -sS -D - -o /dev/null https://api.example.com/mcp | grep -i -E '^(HTTP|www-authenticate)'
# 2. Метаданные ресурса: статус, тип содержимого, тело
curl -sS -D - https://api.example.com/.well-known/oauth-protected-resource/mcp
# 3. Сервер авторизации из authorization_servers
curl -sS -D - https://auth.example.com/.well-known/oauth-authorization-server

Первая команда должна вывести примерно такое (перенос строки — для читаемости):

HTTP/2 401
www-authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp",
                  scope="scans:read"

Две другие должны вернуть 200 с application/json.

Затем проверьте идентификаторы — именно там прячется большинство реальных поломок. Этот smoke-тест для CI начинает с URL ресурса, а не с 401, и дальше идёт по цепочке: применяет правило вставки пути, пробует адреса OpenID Connect, если адрес RFC 8414 не ответил, и точно сравнивает resource и issuer:

#!/usr/bin/env bash
set -euo pipefail
RESOURCE="${1:?usage: check-oauth.sh https://api.example.com/mcp}"
origin()  { sed -E 's#^(https://[^/]+).*#\1#' <<<"$1"; }
# urlpath отбрасывает завершающий слэш, как и сканер aiSiteReady; RFC 9728 его сохраняет
urlpath() { local p; p="$(sed -E 's#^https://[^/]+##' <<<"$1")"; echo "${p%/}"; }

PRM="$(curl -sSf -H 'Accept: application/json' \
  "$(origin "$RESOURCE")/.well-known/oauth-protected-resource$(urlpath "$RESOURCE")")"
jq -e --arg r "$RESOURCE" '.resource == $r' <<<"$PRM" >/dev/null \
  || { echo 'FAIL: resource does not match the URL'; exit 1; }

ISSUER="$(jq -er '.authorization_servers[0]' <<<"$PRM")"
AS="$(curl -sf -H 'Accept: application/json' \
    "$(origin "$ISSUER")/.well-known/oauth-authorization-server$(urlpath "$ISSUER")" \
  || curl -sf -H 'Accept: application/json' \
    "$(origin "$ISSUER")/.well-known/openid-configuration$(urlpath "$ISSUER")" \
  || curl -sSf -H 'Accept: application/json' \
    "$(origin "$ISSUER")$(urlpath "$ISSUER")/.well-known/openid-configuration")"
jq -e --arg i "$ISSUER" '.issuer == $i' <<<"$AS" >/dev/null \
  || { echo 'FAIL: issuer mismatch'; exit 1; }
jq -e '.code_challenge_methods_supported | index("S256") != null' <<<"$AS" >/dev/null \
  || { echo 'FAIL: no S256'; exit 1; }
echo OK

Наконец, негативный тест для сайта, которому публиковать нечего. Отсутствующий well-known URL должен давать настоящий 404, а не дружелюбную страницу:

curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' \
  https://example.com/.well-known/oauth-authorization-server
# ожидаемо: 404 ...   подозрительно: 200 text/html (страница-заглушка приложения)

Нужен ли вам OAuth discovery вообще?

Часто нет. Эти документы описывают OAuth-развёртывание, так что без него публиковать нечего. Пройдите дерево решений, прежде чем писать JSON.

Дерево решений: публикуйте метаданные OAuth discovery, только если агенты получают Bearer-токены через OAuth; публичные сайты и API на ключах ничего не публикуют.

Ваша ситуацияДокумент RFC 9728Документ RFC 8414
Публичный контентный сайт только для чтенияНе публиковатьНе публиковать
Публичный API или MCP-сервер без входаНе публиковатьНе публиковать
Только API-ключи или статические токеныНе публиковать; описать ключи в документацииНе публиковать
Только собственный вход для вашего приложенияНе публиковатьНе публиковать
Защищённый API, токены выдаёт внешний провайдерПубликовать, назвав провайдераЕго отдаёт провайдер; проверьте его URL
Защищённый API, сервер авторизации вашПубликоватьПубликовать

Не публикуйте метаданные-заглушки ради зелёной проверки. Оба RFC существуют для того, чтобы документ, не совпадающий с идентификаторами, которые ожидает клиент, можно было отбросить. Выдуманная запись в authorization_servers отправит агента на сервер, который никогда не выдаст ему токен, а 404 честнее и дешевле в отладке.

Есть и обратная ловушка: aiSiteReady считает голый WWW-Authenticate: Bearer на сканируемом URL сигналом OAuth. Если вы отправляете этот заголовок, добавьте указатель resource_metadata. Если OAuth у вас нет, не отправляйте его.

Как aiSiteReady проверяет OAuth discovery?

Эту статью покрывают две проверки aiSiteReady из категории Protocol/API: OAuth protected resource (oauth_protected_resource) и OAuth authorization server (oauth_authorization_server). Обе относятся к опции сканирования oauth_discovery. Для профиля Контентный сайт (content_site) категория отключена, а в профиле API/приложение (api_application) она даёт 40% оценки (20% в профиле по умолчанию Все проверки). Точные проверки и веса описаны на странице методологии.

Для сервера авторизации сканер пробует /.well-known/oauth-authorization-server и /.well-known/openid-configuration, добавляет варианты со вставкой и добавлением, если у сканируемого URL есть путь, и идёт по заголовкам Link сканируемого URL с отношениями oauth-authorization-server или openid-configuration. Ни один RFC таких отношений не определяет; сканер принимает их как подсказку.

Для ресурса он пробует well-known URL со вставкой пути и «голый», затем делает один анонимный запрос и читает challenge из WWW-Authenticate. В целях защиты от SSRF он идёт по URL из resource_metadata, только если тот HTTPS, на том же хосте и порту и под /.well-known/oauth-protected-resource. Затем запрашивает каждый issuer из authorization_servers, до пяти, по адресам RFC 8414 и OpenID со вставкой (адрес с добавлением пока не проверяется), через SSRF-безопасный fetcher. Удалённый JavaScript не выполняется.

Как сканер оценивает каждый документ?

Отсутствующий или невалидный authorization_servers делает документ ресурса невалидным: это строже RFC 9728, зато совпадает с MCP. Неверный Content-Type записывается в доказательства и статус не меняет; отсутствие scopes_supported оставляет документ пригодным для цепочки issuer, но ограничивает результат уровнем PARTIAL. Готовым для агентов считается сервер с валидными по RFC 8414 метаданными, поддержкой потока authorization code и объявленными S256 и scopes_supported.

СтатусПроверка ресурсаПроверка сервера авторизации
PASSВалидный документ, нет несовпадения resource, хотя бы один готовый для агентов сервер, есть scopes_supportedХотя бы один готовый для агентов сервер
PARTIALНайден, но: resource не совпал, нет scope, сервер неполный или не провалидировался, либо документ невалиденВалиден, но нет S256 или scope; несовпадение issuer; либо невалиден
FAILНичего не найдено, и есть сигнал OAuthТо же
N/AНичего не найдено, и сигнала OAuth нетТо же
UNKNOWNЗагрузка не удалась или заблокирована как бот (таймаут, 403, 429)То же

Когда отсутствующий документ получает статус N/A?

Когда я встраивал это в пайплайн сканирования, рассуждение было простым. Уверенное «опубликуйте метаданные RFC 8414» на сайте без OAuth — ложное срабатывание: оно снижает оценку за то, чего сайту делать не нужно. Поэтому один шаг запускается после всех проверок и переписывает только «ничего не найдено» FAIL, и только когда ничто не указывает на OAuth. Результат N/A затем исключается из знаменателя оценки.

Сигналы: профиль API/приложение, заголовок WWW-Authenticate: Bearer на сканируемом URL, заголовок Link там же с oauth-authorization-server или openid-configuration, а также найденные метаданные защищённого ресурса или любой Bearer-challenge, замеченный проверкой ресурса.

Одно следствие: профиль API/приложение сам считается сигналом, поэтому с ним отсутствующий документ остаётся FAIL даже у API на ключах. Если OAuth у вас нет, сканируйте с профилем по умолчанию или исключите опцию OAuth discovery из пользовательского набора проверок.

Одна лишь MCP-карточка, A2A-карточка или каталог API сигналом сознательно не считаются: агентская поверхность может работать на API-ключах. PASS, PARTIAL и UNKNOWN не переписываются никогда, поэтому настоящее развёртывание получает балл за то, что публикует. Сканируйте URL самого ресурса: раз resource обязан совпадать со сканируемым URL, документ для https://api.example.com/mcp, найденный при сканировании https://example.com, получит PARTIAL с resource_mismatch — так задумано.

aiSiteReady не публикует ни один из документов. Его well-known-маршруты отдают A2A-карточку, каталог API, индекс Agent Skills и MCP Server Card, а для OAuth — ничего. Публичный MCP-сервер задокументирован как Auth: none с теми же лимитами, что и REST API. Опциональные аккаунты, по умолчанию выключенные, — это собственный вход с короткоживущими токенами доступа, а не сервер авторизации, где могли бы регистрироваться сторонние агенты.

3 октября 2026 года все четыре OAuth well-known URL на www.ai-siteready.com отвечали 404, а главная страница не отправляла Bearer-challenge, поэтому ни одна из проверок не находит сигнала OAuth: в профиле по умолчанию обе показывают N/A.

Запустите бесплатное сканирование вашего API или MCP-URL, чтобы увидеть, какой исход получает каждый документ, и HTTP-доказательства к нему — на английском, украинском или русском. Этот гайд — часть про вход в теме доступности для вызова; гайд по каталогу API объясняет, как агенты сначала находят API, а аудит за 30 минут показывает, где это место в полном проходе. Для общей картины начните с материала о том, что значит готовность к ИИ-агентам.

Если коротко: если ваш API защищён, опубликуйте 401, указывающий на метаданные RFC 9728, и сервер авторизации, чьи метаданные RFC 8414 совпадают с его issuer и объявляют S256. Если не защищён — не публикуйте ничего и пусть за вас говорит 404.

У IMozz 20 лет в разработке ПО, а последний год он строит продукты с помощью LLM. Он развивает aiSiteReady, сканер только для чтения, который проверяет, может ли ИИ-агент прочитать и вызвать сайт. Сканер серверно рендерит собственный контент как рабочий пример.

Частые вопросы

Нужны ли метаданные OAuth discovery, если мой сайт публичный и только для чтения?
Нет. Эти документы описывают защищённый OAuth-ресурс и его сервер авторизации. У публичного сайта только для чтения нет ни того ни другого, поэтому публиковать нечего. Не добавляйте файлы-заглушки ради зелёной проверки: клиенты обязаны отбрасывать метаданные, которые не совпадают, а выдуманный сервер авторизации отправит агентов туда, где токены не выдают. Честный ответ — обычный 404.
Чем метаданные RFC 9728 отличаются от метаданных RFC 8414?
RFC 9728 описывает защищённый ресурс, то есть ваш API или MCP-сервер: его идентификатор, серверы авторизации, которым он доверяет, и scope, которые он поддерживает. RFC 8414 описывает сервер авторизации: issuer, эндпоинты авторизации и токена, возможности вроде PKCE. Агент сначала читает первый документ, чтобы понять, кому доверять, затем второй — чтобы узнать, куда отправить пользователя.
Требует ли MCP оба документа?
Для защищённых серверов фактически да. В ревизии MCP 2026-07-28 серверы обязаны реализовать RFC 9728, а серверы авторизации — предоставлять метаданные по RFC 8414 или OpenID Connect Discovery. Но сама авторизация в MCP необязательна, поэтому публичный MCP-сервер без входа не публикует ни тот ни другой. Требование действует, когда вы защищаете сервер через OAuth.
Где публиковать метаданные, если у issuer есть путь?
RFC 8414 вставляет суффикс well-known между хостом и путём: issuer https://auth.example.com/tenant1 описывается по адресу /.well-known/oauth-authorization-server/tenant1. OpenID Connect Discovery, наоборот, добавляет суффикс в конец. MCP-клиенты пробуют сначала OAuth-адрес со вставкой, затем OpenID-адрес со вставкой, затем OpenID-адрес с добавлением, поэтому, если сервер ваш, публикуйте по первому адресу.