OAuth на MCP-сервере: Claude и ChatGPT подключаются без токена

OAuth

Пару недель назад я писал о том, зачем ИИ-агентам личные токены. Настройка в конце того поста хорошо работает в Claude Code: создаёте токен, запускаете одну команду — и агент читает баг-репорты.

Потом люди попробовали добавить BugDump в Claude в браузере, и ничего не вышло.

В пользовательском коннекторе Claude некуда вставить токен. В ChatGPT тоже. VS Code примет заголовок, если отредактировать его конфиг, но его сценарий «Add Server» заголовок не спрашивает. MCP-клиенты, которыми пользуется большинство, ждут URL, а когда сервер отвечает 401, ждут, что пользователь войдёт в аккаунт.

Поэтому я добавил в MCP-сервер вход через аккаунт BugDump. Код оказался меньшей частью работы. Ниже — как это выглядит для того, кто подключается, и четыре решения, на которые ушла большая часть времени.

Как MCP-клиент входит в аккаунт

Вы копируете https://api.bugdump.com/api/mcp и добавляете его в Claude как пользовательский коннектор — или нажимаете Добавить в Claude на MCP-странице проекта, и кнопка сделает это за вас. Claude открывает в браузере страницу BugDump. Вы входите, выбираете, может ли приложение что-то менять или только читать, и нажимаете «Разрешить».

Страница согласия BugDump с вопросом «Разрешить Claude использовать ваш аккаунт BugDump?»: выбрано «Чтение и запись», второй вариант — «Только чтение», кнопки «Разрешить» и «Отмена»

Под капотом это сценарий, который описывает спецификация MCP. Первый запрос возвращается с 401 и заголовком WWW-Authenticate, который указывает на небольшой JSON-документ. Этот документ называет сервер, который отвечает за вход. Claude получает метаданные этого сервера, отправляет вас на страницу входа и обменивает результат на токен. Ничего здесь не завязано на Claude. Клиенту, который следует спецификации, чтобы найти страницу входа, нужен только URL.

Одно подключение на все проекты

Личные токены в BugDump привязаны к одному проекту. Это аккуратная модель. Токен для Acme Store не видит Acme Admin, и никому не приходится гадать, в каком проекте работает агент.

Я собирался сохранить её и для входа: одно подключение на проект, возможно, с отдельным URL на каждый проект. Потом попробовал добавить второе. Claude не добавляет один и тот же URL коннектора дважды, а отдельный URL на каждый проект означает отдельный коннектор, который надо настроить и за которым надо следить. У человека с тремя проектами оказалось бы три коннектора, а большинство остановилось бы на первом.

Поэтому подключение через вход принадлежит вам, а не проекту. Оно видит все проекты, в которых вы состоите, а каждый из остальных инструментов принимает один дополнительный аргумент, project, — слаг проекта, который можно не передавать, если вы состоите только в одном проекте. Новый инструмент, list_projects, сообщает ассистенту, до чего он может дотянуться, включая ключ каждого проекта, так что ассистент знает, что AS-1 живёт в Acme Store.

Больше всего мне нравится, что происходит, когда ассистент забывает указать, какой проект он имеет в виду. Сервер не выбирает проект за него. Если вы состоите больше чем в одном проекте, вызов возвращает вот это:

JSON
{
  "error": "MCP_PROJECT_REQUIRED",
  "message": "This account belongs to several projects. Pass `project` with the slug of the one the user means.",
  "projects": [
    { "slug": "acme-admin", "key": "AA", "name": "Acme Admin", "role": "OWNER" },
    { "slug": "acme-store", "key": "AS", "name": "Acme Store", "role": "OWNER" }
  ]
}

Это приходит как обычный результат инструмента, а не как ошибка протокола, поэтому модель его читает и пробует ещё раз с правильным слагом. Часто до этого доходить не должно: инструкции сервера велят ассистенту первым делом вызывать list_projects.

Членство в проекте проверяется при каждом вызове. Если человек уходит из проекта, его ассистент теряет к нему доступ на следующем же запросе, и ничего не нужно подчищать.

Только известные клиенты: Client ID Metadata Documents

В классическом OAuth приложение регистрируют на сервере до того, как оно сможет у кого-то запросить доступ, — вручную или через Dynamic Client Registration. Более новый подход, который рекомендует спецификация MCP, — Client ID Metadata Documents: приложение представляется URL-адресом, который оно контролирует. У Claude это JSON-файл на claude.ai, где среди прочего перечислены адреса, на которые Claude разрешено получать результат входа.

Схема хорошая. Но сама по себе она значит, что любой, кто может разместить JSON-файл, может появиться на вашей странице согласия под любым именем.

Поэтому BugDump принимает четыре приложения: Claude, Claude Code и VS Code — по точному URL их документа, и ChatGPT — по одному фиксированному шаблону на chatgpt.com, потому что он публикует отдельный документ на каждое подключение. Страница согласия показывает название приложения и хост, где лежит его документ («Запрос от claude.ai»), а хост приложение подделать не может. Dynamic Client Registration выключена. Cursor использует именно её, поэтому Cursor по-прежнему работает с личным токеном, как скрипты и CI-задачи. Токены для этого и созданы.

Токен, согласие и аккаунт проверяются при каждом запросе

Access-токен живёт час. Потом приложение незаметно меняет refresh-токен на новый, и так подключение работает неделями, не прося вас войти заново. Подвох в том, что шаг обновления не останавливается, чтобы спросить, хотите ли вы, чтобы приложение по-прежнему было подключено, и активен ли ещё ваш аккаунт.

Поэтому MCP-эндпоинт BugDump спрашивает каждый раз. При каждом запросе он проверяет, что access-токен существует и не истёк, что ваше согласие для этого приложения всё ещё действует и что ваш аккаунт активен и не гостевой. Отключение приложения разом удаляет его согласие и все его токены, и его следующий же вызов падает с 401, который отправляет его обратно на страницу входа. Смена или сброс пароля отключает сразу все приложения — ровно то, что нужно, если пароль вы меняете из-за утечки.

«Подключённые приложения» в настройках безопасности аккаунта BugDump: VS Code с правом «Только чтение», Claude Code и Claude с правом «Чтение и запись», у каждого кнопка «Отключить»

Сами токены — случайные строки, которые хранятся в виде хешей, как и личные токены. Ключей подписи, которые нужно ротировать, нет, а отозвать токен — значит удалить одну строку.

Ассистент по-прежнему действует от вашего имени

Всё остальное я намеренно оставил как было. Приложение, подключённое через вход, действует от вашего имени и видит то же, что и вы. Каждое его изменение появляется в истории задачи и в комментариях под вашим именем с пометкой через MCP, а журнал аудита записывает, какое приложение его сделало. Выберите «Только чтение» — и инструменты записи вообще не регистрируются: модель никогда не видит move_task, поэтому не может даже попытаться его вызвать.

Задача BugDump «Checkout button does nothing on Safari» с комментарием, который Claude оставил от имени Alex Rivera, с пометкой «через MCP»

Это Claude разбирает баг с оформлением заказа в Safari. Он прочитал задачу, оставил заметку о том, куда смотреть в первую очередь, перенёс её в «В работе» и назначил исполнителя. Любому, кто потом читает задачу, понятно, какая часть пришла от ассистента.

Что пока шероховато

  • ChatGPT нужен режим разработчика, чтобы добавить свой MCP-сервер, а режим разработчика есть только на платном тарифе ChatGPT.

  • Чтобы изменить доступ, нужно переподключиться. Чтобы дать приложению с доступом только на чтение право на запись, вы отключаете его и подключаете заново. Я предпочитаю, чтобы вы делали этот выбор осознанно, а не переключателем, о котором потом забудете, но это лишний шаг.

  • Пометка пока не называет приложение. В комментарии написано «через MCP», а не «через Claude». Каждый комментарий и каждая запись истории уже хранят, какое приложение их сделало, просто страница задачи пока этого не показывает.

Как подключить BugDump к Claude, ChatGPT или VS Code

Откройте страницу MCP-сервер любого проекта и нажмите Добавить в Claude или скопируйте URL в ChatGPT или VS Code. Шаги для каждого приложения — в статье Как подключить Claude, ChatGPT или VS Code к BugDump. Если вы работаете в Cursor или подключаете скрипт, личные токены работают точно так же, как раньше: см. Как подключить BugDump к Claude Code (MCP).

Читайте также