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

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-перевірки отримують статус N/A, якщо сигналів 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/застосунок (api_application), заголовок WWW-Authenticate: Bearer на сканованому URL, заголовок Link там само з oauth-authorization-server або openid-configuration, а також знайдені метадані захищеного ресурсу чи будь-який Bearer-challenge, помічений перевіркою ресурсу.

Один наслідок: профіль API/застосунок (api_application) сам є сигналом, тож із ним відсутній документ лишається 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-адресу з дописуванням, тож, якщо сервер ваш, публікуйте за першою адресою.