# доступ через sso для mcp

Для корпоративных пространств, где реализована SSO-авторизация пользователей, реалий SSO-авторизацию для системных пользователей (ботов) для доступа к API и MCP (keyring). Весь протокол прежний, но надо добавить в настройки и применять для них второй callback-адрес (первый остается для людей, второй - для ботов). Надо добавить интерфейс авторизации бота в настройках пространства, где владелец/администратор пространства пройдет mcp-авторизацию для него, указав техническую учету (либо учету человека) в чужой системе авторизации. Права такого бота по-прежнему раздаются администратором вручную на конкретные объекты и не зависят от способа авторизации.

> Что сделано
- Системный пользователь (бот) в пространстве с корпоративным входом теперь можно авторизовать в каталоге компании: в карточке бота («Настройки → API для интеграций») появилась строка состояния и кнопка «Авторизовать в каталоге». Процедуру проходит владелец или администратор пространства — каталог спрашивает учётные данные заново, и администратор называет техническую учётную запись или свою.
- Протокол тот же (OIDC), но бот возвращается из каталога по второму адресу: человек — на прежний адрес, бот — на /api/auth/sso/bot/callback. Оба адреса показаны в настройках корпоративного входа, их нужно внести в настройки клиента на стороне компании.
- В настройках корпоративного входа добавлен переключатель «Системные пользователи (боты) работают только после авторизации в каталоге»: при нём токен бота без привязки не принимается. По умолчанию выключен.
- Привязка проверяется на каждом вызове Developer API V2 и MCP. Снятая вручную привязка закрывает доступ всегда, даже если требование выключено: отзыв — осознанное решение администратора. В карточке бота есть кнопка «Снять привязку».
- Права бота на конкретные объекты по-прежнему выдаются вручную в окне «Доступ» и от способа авторизации не зависят.
- Раздел документации про MCP дополнен описанием этой авторизации. Добавлены тесты на правило доступа и на разделение адресов возврата, заведена гвардия сборки. Код закоммичен как 5.44.123 и уедет на dev общей сборкой, когда закончатся задачи в работе.

Что не получилось
- Проверить процедуру живьём не удалось: для этого нужен сервер входа компании (Keycloak или AD FS) с заведённым вторым адресом возврата и технической учётной записью. Проверены разбор ответа каталога, правило доступа по токену и сборка; сам обмен с каталогом повторяет уже работающий вход сотрудников.

На что обратить внимание
- Чтобы авторизация бота заработала, администратор каталога компании должен внести второй адрес возврата в настройки того же клиента. Пока он не внесён, каталог отклонит попытку как запрос с незарегистрированным redirect_uri — адрес виден в настройках корпоративного входа.
- Требование привязки намеренно выключено по умолчанию: включи его, когда все боты пространства пройдут авторизацию, иначе работающие интеграции перестанут отвечать сразу после сохранения настроек.
- Автоматической проверки отзыва у ботов нет: у людей фоновая служба раз в несколько минут спрашивает каталог, действует ли учётная запись, а привязка бота снимается пока только вручную. Если нужно, чтобы отключение технической учётки в каталоге закрывало доступ бота само, это отдельная задача — её выполняет фоновая служба.
- Авторизацию бота проводит администратор пространства (роль «Администратор» и выше), а не любой владелец бота: привязка влияет на то, принимается ли токен.

привязка бота работает, 
стрикт режим работает, 
auth2  для mcp нету
подробное описание тут: 

## Что проверили

Стенд: https://notes.vtorum.net/mcp, пространство ООО «Аинерджи», бот «Вова, тест MCP», каталог Keycloak. Клиент: Claude Code (.mcp.json, Bearer-токен из VTORUM_TOKEN) и прямые запросы curl.

#	Проверка	Результат
1	Keycloak: второй адрес возврата /api/auth/sso/bot/callback	Настроен
2	Привязка бота кнопкой «Авторизовать в каталоге»	Выполнена
3	MCP после привязки: getCurrentIdentity, searchContent, ping	ОК, HTTP 200
4	Неверный токен	401, как ожидалось
5	Строгий режим «Системные пользователи работают только после авторизации в каталоге»	Привязанный бот работает
6	Отказ для непривязанного бота и после снятия привязки	Проверил пользователь

Замечания:

- Через API не видно, привязан ли бот к каталогу и к какой учётке: ни в GET /v2/users/me, ни в заголовках ответа MCP такой информации нет.
- Один раз вызов через Claude Code упал с ECONNRESET, повтор сразу прошёл. Похоже, сервер закрыл простаивавшее keep-alive-соединение.
## Ограничение

SSO подтверждает только личность бота. Права на страницы и базы от этого не зависят: их по-прежнему выдают боту вручную через окно «Доступ», как отдельному пользователю. В итоге:

- бот видит не то, что видит сотрудник, за которым он закреплён, а то, что ему открыли вручную;
- права в Keycloak (группы, роли, увольнение и перевод сотрудника) на доступ бота не влияют;
- для каждого сотрудника, который хочет работать через MCP, нужен отдельный бот с ручной настройкой доступа.
## Запрос разработчику Вторума

Нужно: чтобы права при работе через MCP (и V2) определялись учётной записью каталога, а не ручной выдачей доступа боту.

Варианты реализации, в порядке предпочтения:

1. Вход в MCP через SSO от имени человека (OAuth 2.1 по спецификации MCP).
  - MCP-сервер публикует /.well-known/oauth-protected-resource, а в ответе 401 возвращает WWW-Authenticate со ссылкой на сервер авторизации (Вторум или Keycloak пространства).
  - Клиент (Claude Code, Claude Desktop) проходит вход через Keycloak в браузере и получает токен пользователя с ограниченными скоупами (pages.read и т.п.).
  - Вызовы выполняются с правами этого человека: видно то же, что в интерфейсе. Увольнение или блокировка в Keycloak сразу закрывает доступ.
  - Нужна поддержка регистрации клиента: dynamic client registration или заранее заведённый публичный клиент с PKCE.
  - Аудит: в истории правок видно, что изменения сделал человек через MCP-клиент.
1. Бот наследует права привязанной учётки каталога.
  - Опция в карточке системного пользователя: «Права как у привязанной учётной записи». Права берутся как пересечение прав этой учётки и скоупов токена.
  - Ручное окно «Доступ» для такого бота не нужно.
1. Группы Keycloak как источник доступа (минимальный вариант).
  - Синхронизация групп из каталога (claim groups или SCIM) в группы Вторума.
  - Боту и людям доступ к страницам и базам выдаётся на группу, членство управляется в Keycloak.
Дополнительно:

- Показывать статус привязки бота (учётка каталога, дата авторизации) в GET /v2/users/me или в отдельном поле.
- Разобрать ECONNRESET на простаивающих соединениях к /mcp: проверить keep-alive-таймауты nginx.
Перед отправкой уточнить у разработчика, какой из трёх вариантов в планах, и есть ли сроки.

> Что сделано
- Сделал то, чего не хватало: вход MCP-клиента по OAuth 2.1 от имени человека. Вторум сам стал сервером авторизации — клиенту (Claude Code, Claude Desktop) достаточно указать адрес https://notes.vtorum.net/mcp без токена: он сам находит сервер авторизации, регистрируется, открывает браузер и получает токен.
- В браузере появился экран согласия: видно, какая программа просит доступ, какие права получит, от чьего имени и в каком пространстве будет работать, — кнопки «Разрешить доступ» и «Отказать». Не вошедшему сначала показывается обычный экран входа, в том числе кнопка корпоративного входа. Отдельная авторизация через каталог компании для MCP поэтому не нужна: человек входит как всегда, а наружу уезжает токен Вторума, выписанный на него.
- Права при вызовах теперь права самого человека: клиент видит ровно то, что видит он в интерфейсе, а в истории правок изменения записаны на него. Ручная выдача доступа отдельному боту для такого подключения больше не требуется.
- В «Настройки → API для интеграций» добавил раздел «Доступы MCP-клиентов»: список подключённых программ с датой подключения и последнего вызова и кнопкой «Отозвать» — доступ закрывается сразу. Клиент, который умеет выходить сам, тоже может отозвать свой токен.
- Ответ GET /v2/users/me теперь показывает, кому выдан токен и как он авторизован: системному пользователю (и привязан ли он к каталогу компании, с датой авторизации) или человеку, вошедшему по OAuth, — раньше этого по API было не видно, о чём вы и писали.
- Раздел документации про MCP переписан: два способа входа, настройка клиента без токена, срок действия доступа и где его отозвать. Добавлены тесты на весь путь входа (регистрация, согласие, обмен кода, подмена секрета PKCE, повторный обмен, отказ человека, чужой адрес возврата) и гвардия сборки. Код закоммичен как 5.44.135 и уедет на dev общей сборкой, когда закончатся задачи в работе.

Что не получилось
- Проверить живьём на стенде я не могу: вход нужно проходить настоящим MCP-клиентом в браузере. Проверены сборка, типизация, гвардии и весь обмен в тестах — от регистрации клиента до выданного токена, включая отказы.
- Замечание про ECONNRESET на простаивающих соединениях с /mcp не трогал: это настройки времени жизни соединения в nginx на сервере, а не код приложения.
- Синхронизацию групп каталога (Keycloak) в группы Вторума не делал и, думаю, она больше не нужна: при входе от имени человека доступ и так считается по его учётной записи, то есть по правам, которые он получил в Вторуме, — отдельного перевода групп для этого не требуется. Если нужно именно управлять доступом через группы Keycloak, это отдельная задача.

На что обратить внимание
- Доступ выдаётся в том пространстве, которое было открыто в браузере в момент согласия. Нужен другой — переключите пространство и подключите клиент заново.
- Выданный доступ действует месяц, продления токена сервер пока не предлагает: по истечении срока клиент попросит подтвердить доступ ещё раз. Если месяц покажется неудобным, скажите — срок задан в одном месте.
- Старый способ никуда не делся: токены системных пользователей и авторизация бота в каталоге работают как раньше, менять работающие интеграции не нужно.
- Токен человека теперь принимается и в Developer API V2 — это та же дверь, что у MCP, и иначе вход по OAuth заканчивался бы отказом на первом же вызове. Сессия браузера на V2 по-прежнему не годится, скоупы проверяются как раньше.
- Через MCP страница создаётся только внутри указанного родителя: вызов создания без родителя отвечает отказом. Это прежнее правило API, оно действует и для подключения от имени человека.
