Авторизация и токены
Всё, что не является публичным каталогом поселков, требует токена. Токен передаётся заголовком:
Authorization: Bearer <токен>
Токенов два вида, и выбор между ними — это выбор, чей это доступ.
Личный токен: ваш собственный скрипт
Заводится в Настройки → Доступ к MCP, показывается один раз при создании и больше никогда: хранится только его хэш. Потеряли — заведите новый.
Подходит, когда программа ваша и работает от вашего имени: скрипт, который раз в неделю выгружает работы по участку, домашняя автоматизация, ваш собственный ассистент.
Срок жизни задаётся при создании, по умолчанию год. Варианта «бессрочно» нет, и это честность, а не строгость: Passport ставит срок каждому токену, поэтому интерфейс, обещающий вечность, обещал бы то, чего хранилище не делает.
OAuth: приложение для других людей
Если вы делаете приложение, которым будут пользоваться другие жители, токен должен выдавать не человек копипастом, а сервер после явного согласия.
Стандартный authorization_code с обязательным PKCE:
| Метаданные сервера | GET /.well-known/oauth-authorization-server |
| Метаданные ресурса | GET /.well-known/oauth-protected-resource/mcp/{аудитория} |
| Экран согласия | GET /oauth/authorize |
| Обмен кода на токен | POST /oauth/token |
PKCE обязателен, а не желателен: клиент, который нельзя научить хранить секрет — а браузерное приложение и десктопный ассистент именно такие, — без PKCE отдаёт аккаунт любому, кто перехватил код авторизации.
Метаданные ресурса спрашивайте про конкретный сервер. Серверов несколько,
по одному на аудиторию, поэтому документ у каждого свой:
/.well-known/oauth-protected-resource/mcp/resident. Без пути отдаётся
резидентский сервер — тот, до которого дотягивается любой аккаунт.
Читайте метаданные, а не хардкодьте адреса: они строятся от того хоста, на который пришёл запрос, а у поселка может быть свой поддомен.
Откуда взять client_id
Два способа, и выбирать вам.
Client ID Metadata Documents — предпочтительный. Вы размещаете у себя
JSON-документ и присылаете его адрес как client_id:
{
"client_id": "https://ваш-домен/oauth/client.json",
"client_name": "Название, которое увидит человек",
"redirect_uris": ["http://127.0.0.1:3000/callback"]
}
Обязательны три поля: client_id, client_name, redirect_uris. client_id
внутри документа должен точно совпадать с адресом, по которому он лежит — это
то, что связывает документ с идентификатором, и несовпадение мы отвергаем.
Адрес обязан быть https и иметь путь.
Регистрироваться не нужно вовсе, и идентификатор переносим: у поселка свой
поддомен, то есть свой сервер авторизации, — с CIMD один и тот же client_id
работает во всех.
Мы забираем документ при первой авторизации и кэшируем, уважая ваши
заголовки кэширования. Поменяли список адресов — поставьте короткий max-age
или no-store, и изменение подхватится.
Динамическая регистрация — запасной. Если CIMD вы не умеете:
POST /oauth/register
{"client_name": "Название", "redirect_uris": ["http://127.0.0.1:3000/callback"],
"application_type": "native"}
В ответ придёт client_id. Секрет не выдаётся: клиент MCP не умеет его
хранить, и вместо него работает PKCE. Спецификация называет этот способ
устаревшим, поэтому он здесь для совместимости, а не как рекомендация.
Куда мы согласны вас вернуть. И тот и другой способ проверяют
redirect_uris по белому списку. Локальные адреса разрешены — 127.0.0.1,
localhost, [::1] с любым портом, — потому что настольный клиент принимает
код именно там. Своя схема (ваш-клиент://) добавляется по запросу: напишите
нам, какая.
Человек видит ваше приложение в списке разрешённых и может отозвать доступ целиком, одним действием, не разбираясь с отдельными токенами.
Время жизни
Access-токен живёт сутки, refresh-токен — 30 дней. Это и есть смысл OAuth: утёкший access-токен протухает сам, без вашего участия.