Debugg AI
официальныйПредоставьте вашим агентам генерации кода возможность создавать и запускать сквозные тесты без конфигурации для новых изменений кода в удаленных браузерах через платформу тестирования Debugg AI.
Что можно делать с Debugg AI MCP?
- Запуск AI-браузерных тестов — Попросите протестировать любой URL или локальное приложение с помощью инструкций на естественном языке через
check_app_in_browser, возвращая результат «пройдено/не пройдено» со скриншотами. - Быстрая проверка нескольких страниц — Используйте
probe_pageдля пакетной проверки 1–20 URL-адресов на наличие ошибок консоли, сетевых проблем и состояния рендеринга без затрат на LLM. - Управление тестовыми средами — Создавайте, обновляйте или просматривайте среды с учетными данными и авторизованными SSO-хостами с помощью инструмента
environment. - Запуск обхода сайтов — Вызывайте
trigger_crawl, чтобы заполнить граф знаний проекта данными от серверного браузерного агента. - Запуск и отслеживание тестовых наборов — Создавайте наборы, запускайте асинхронные прогоны и получайте результаты каждого теста через действия
test_suite. - Просмотр артефактов выполнения — Получайте полные детали запусков, HAR-сетевые трассировки и журналы консоли через
executionsдля отладки проблем во время выполнения.
Документация
Debugg AI — MCP Server
AI-управляемое тестирование браузера через Model Context Protocol. Укажите любой URL (или localhost) и опишите, что нужно протестировать — AI-агент просматривает ваше приложение и возвращает результат «пройдено/не пройдено» со скриншотами.
Настройка
Требуется Node.js 20.20.0 или новее (транзитивное требование от posthog-node@^5.26.0).
Тестирование http://localhost:... URL-адресов требует бинарный файл caddy — check_app_in_browser,
probe_page и trigger_crawl туннелируют локальные цели через локальный обратный прокси Caddy.
Это устанавливается автоматически: npm-зависимость @radically-straightforward/caddy загружает
закреплённый релиз Caddy для вашей платформы во время npm install/npx — в обычном случае вам ничего не нужно устанавливать самостоятельно. Теперь это единственный бинарный файл, который загружает этот пакет; сам туннельный клиент — это
чистый TypeScript — он заменил пакет ngrok, который загружал агент ngrok.
Если эта загрузка никогда не выполнялась (npm install --ignore-scripts, офлайн/изолированная установка), укажите CADDY_BIN на
вашу собственную установку (brew install caddy / apt install caddy / см.
caddyserver.com/docs/install) — её отсутствие проявится как
понятная ошибка при первом вызове localhost-URL, а не как тихое зависание. Вызовы публичных URL-адресов, все
инструменты, не связанные с браузером, и test_suite {action:"run"} (который использует собственный выделенный туннель и
полностью обходит Caddy) в любом случае не нуждаются в нём.
Получите API-ключ на debugg.ai, затем добавьте в конфигурацию вашего MCP-клиента:
{
"mcpServers": {
"debugg-ai": {
"command": "npx",
"args": ["-y", "@debugg-ai/debugg-ai-mcp"],
"env": {
"DEBUGGAI_API_KEY": "your_api_key_here"
}
}
}
}
Или с Docker:
docker run -i --rm --init -e DEBUGGAI_API_KEY=your_api_key quinnosha/debugg-ai-mcp
Шаг npm install у Dockerfile в принципе подхватил бы caddy тем же автоматическим способом, что и локальные установки — но на момент написания Dockerfile не COPY несколько каталогов, которые теперь нужны сборке (handlers, tools, types, config), и по-прежнему ссылается на каталог tunnels/, который больше не существует, поэтому свежая сборка, скорее всего, завершится ошибкой раньше, чем это станет актуально. Это существующий пробел, не связанный с Caddy. Текущий опубликованный образ quinnosha/debugg-ai-mcp
в любом случае предшествует зависимости от Caddy — вызовы localhost-URL к
check_app_in_browser/probe_page/trigger_crawl будут завершаться ошибкой с CaddyBinaryNotFoundError
внутри этого образа, пока он не будет пересобран (исправлен Dockerfile) и переопубликован, или CADDY_BIN не укажет на
отдельно встроенный. Вызовы публичных URL-адресов, инструменты, не связанные с браузером, и test_suite {action:"run"}
в любом случае не затрагиваются.
Инструменты
Сервер предоставляет 8 инструментов: три браузерных инструмента плюс один основанный на действиях инструмент для каждой управляемой сущности. Ключевые инструменты — check_app_in_browser (полноценный AI-агент) и probe_page (лёгкий зонд страницы без LLM). Остальные — project, environment, test_suite, test_case, executions — каждый принимает дискриминатор action (например, {"action":"list"}), который выбирает операцию. Деструктивные действия delete требуют подтверждения (запрос уточнения там, где это поддерживается, в противном случае confirm: true).
Браузер
check_app_in_browser
Запускает AI-браузерного агента против вашего приложения. Агент перемещается, взаимодействует и сообщает результаты со скриншотами. URL-адреса localhost автоматически туннелируются через сервер туннеля debugg.
| Параметр | Тип | Описание |
|---|---|---|
description | строка обязательно | Что тестировать (естественный язык) |
url | строка обязательно | Целевой URL — http://localhost:3000 автоматически туннелируется |
environmentId | строка | UUID конкретной среды |
credentialId | строка | UUID конкретных учётных данных |
credentialRole | строка | Выбор учётных данных по роли (например, admin, guest) |
username | строка | Имя пользователя для входа (эфимерное — не сохраняется) |
password | строка | Пароль для входа (эфимерный — не сохраняется) |
loginCredentials | массив | Учётные записи для входов, которые агент встречает во время задачи — [{username, password, label?}] |
useEnvironmentCredentials | логический | По умолчанию true. false запрещает автоматическое заполнение сохранённых учётных данных среды; без указанной учётной записи это означает не входить в систему вообще |
freshSession | логический | По умолчанию false. true принудительно выполняет реальный вход вместо повторного использования тёплой сессии, хранящейся для этой учётной записи |
auth | объект | Предусловие аутентификации — {precondition, entryUrl, deepUrl, environmentId, username, password} |
repoName | строка | Переопределение автоматически определённого имени git-репозитория (например, my-org/my-repo) |
Одна сфокусированная проверка за вызов. У агента есть внутренний бюджет примерно в 25 шагов; разбивайте более крупные наборы на несколько вызовов.
Учётные данные: передавайте их как параметры, а не в тексте
Упоминание учётной записи только в description не заставляет агента использовать её — он возвращается к сохранённым учётным данным среды, и отклонение приложением неправильной учётной записи выглядит как сбой приложения. Всё, что вы передаёте как параметр, имеет приоритет над значением среды по умолчанию для каждого входа в запуске, а не только первого:
username/password(илиcredentialId/credentialRole) — идентичность запуска.auth.username/auth.password— закрепляет вход по предусловию, когда вы также используетеauth.precondition: "login".loginCredentials— учётные записи для формы входа, которую агент достигает в середине задачи. Это то, что нужно для сценариев вроде установить пароль → вас перенаправляют на вход → войти как только что созданная учётная запись, где разделение на отдельные вызовы потеряло бы состояние браузера.
Установите useEnvironmentCredentials: false, когда тихий возврат к тестовому пользователю по умолчанию сделал бы проверку недействительной.
Междоменный SSO? Запуск вводит учётные данные только на собственном хосте приложения и его поддоменах; страница входа на другом домене отклоняется как offscope_host. Добавьте хост поставщика удостоверений в authorizedCredentialHosts среды (см. environment).
Проверяете страницу, которая вообще не требует входа? Передайте useEnvironmentCredentials: false и не указывайте учётную запись. Эта комбинация означает ровно то, что говорит — не входить в систему — и запуск полностью пропускает аутентификацию вместо поиска формы входа. Используйте её для публичных страниц, маркетинговых сайтов, документации и всего, что находится до аутентификации. Это также быстрее: по умолчанию (auto) агент перейдёт по ссылке «Войти» с вашей страницы и попробует сохранённую учётную запись среды, прежде чем что-либо оценивать.
Повторное использование сессии: почему проверка может сообщить «нет формы входа»
Запуски не входят в систему каждый раз. После подтверждённого входа бэкенд захватывает сессию этой учётной записи и восстанавливает её при следующем запуске для той же идентичности, что полностью пропускает вход — именно поэтому проверка может обоснованно вернуться с submitted: false и без формы входа: она уже была авторизована. Восстановленный запуск сообщает о себе в logins с reason: "restored_session", так что вы можете отличить его от запуска, который действительно не нашёл форму.
Сессии привязаны к каждой учётной записи, поэтому указание другой учётной записи никогда не повторно использует чужую. Два способа обойти повторное использование:
freshSession: trueв одном вызове — выполнить реальный вход на этот раз, затем повторно захватить. Используйте, когда проверяете именно процесс входа, когда подозреваете, что сохранённая сессия устарела, или когда единственный маршрут приложения между персонами — это выход.- Инструмент
environment,action: "clearSessions"— аннулировать сохранённые сессии, чтобы последующие запуски выполняли вход. Сузьте с помощьюusername/credentialId; несуженные очистки требуют подтверждения, потому что каждая учётная запись в среде затем повторно аутентифицируется.
Используйте action: "sessions", чтобы увидеть, что среда в настоящее время хранит и будет ли каждая сессия повторно использована.
Результаты сообщают фактически использованную идентичность, поэтому неправильная видна, а не маскируется под сломанное приложение:
"logins": [
{ "username": "qa+invitefix@example.com", "source": "task", "submitted": true, "authenticated": true },
{ "username": "qatest123@example.com", "source": "env_default", "submitted": false, "authenticated": false,
"reason": "offscope_host", "detail": "refused to enter credentials on auth.idp.example: not part of this run's scope …" }
],
"credentialWarning": {
"requested": "qa+invitefix@example.com",
"used": ["qatest123@example.com"]
}
source — это task | explicit | credential_id (учётная запись, которую вы указали) или env | env_default (сохранённая учётная запись среды). submitted истинно только когда учётные данные действительно были введены и отправлены; reason сообщает, что произошло (например, offscope_host, restored_session), а detail, когда присутствует, — это человекочитаемое объяснение этого — для отказа offscope_host он называет хост и способ авторизации. credentialWarning появляется только когда вы указали учётную запись, а значение среды по умолчанию для другой учётной записи действительно было отправлено — никогда для входа, который был отклонён или пропущен. loginError появляется, когда указанная учётная запись не может быть разрешена и запуск отказался подставлять другую.
Каждый успешный запуск возвращает блок browserSession вместе со скриншотом — предварительно подписанные URL-адреса S3 для захваченного HAR (полный сетевой трафик) и журнала консоли (каждое сообщение JS-консоли). Используйте их для обнаружения циклов повторной загрузки, ошибок гидратации и других проблем времени выполнения, которые проходят проверки типов и модульные тесты:
"browserSession": {
"harUrl": "https://...session_18139.har?X-Amz-...",
"consoleLogUrl": "https://...session_18139_console.json?X-Amz-...",
"recordingUrl": "https://...session_18139_recording.webm?X-Amz-...",
"harStatus": "downloaded",
"consoleLogStatus": "downloaded",
"harRedactionStatus": "redacted",
"consoleLogRedactionStatus": "redacted"
}
URL-адреса — это кратковременные предварительно подписанные S3 — повторно получите родительское выполнение через executions {action:"get", uuid}, чтобы обновить. harStatus / consoleLogStatus различают 'downloaded' (URL доступен для получения), 'not_available' (страница ничего не выдала), 'failed' (захват сломался). При новом запуске URL-адреса обычно null, потому что захват загружается асинхронно после завершения агента — опрашивайте executions {action:"get", uuid: executionId}, пока статус не достигнет 'downloaded'. Заголовки Authorization / Cookie / token/secret/api_key очищаются на стороне сервера перед сохранением артефактов.
trigger_crawl
Запускает серверный обход браузерного агента для заполнения графа знаний проекта. URL-адреса localhost туннелируются автоматически. Возвращает {executionId, status, targetUrl, durationMs, outcome?, crawlSummary?, knowledgeGraph?, browserSession?} с knowledgeGraph.skipped === false при успешной загрузке. crawlSummary и knowledgeGraph содержат только ключи, о которых сообщили узлы обхода/импорта бэкенда — отсутствующее количество отсутствует, а не заполнено 0. Блок browserSession (URL-адреса HAR + журнала консоли, той же формы, что и выше) также присутствует в завершённых обходах.
probe_page
Лёгкий пакетный зонд страницы без LLM. Передайте 1-20 URL-адресов; каждый переходит, дожидается стабилизации контента (DOM затихает, с ограничением — никогда не по сетевой тишине, которую живое приложение не достигает) и возвращает отрисованное состояние — скриншот + метаданные страницы + структурированные ошибки консоли + сводку сети. Нет цикла агента, нет затрат на LLM, нет проверок сценариев. Используйте для «не сломал ли я /settings?», много-маршрутных дымовых проверок после рефакторинга, CI-прогонов на каждый PR и быстрых проверок доступности, где цикл агента check_app_in_browser на 60-150 секунд — избыточен.
| Параметр | Тип | Описание |
|---|---|---|
targets | массив обязательно | 1-20 записей: [{url, waitForSelector?, waitForLoadState?, timeoutMs?}] |
targets[].url | строка обязательно | Публичный URL или localhost (автоматически туннелируется) |
targets[].waitForLoadState | перечисление | 'domcontentloaded' (по умолчанию, + ограниченное ожидание стабилизации контента) / 'load' (также блокируется на сторонних встраиваниях) / 'networkidle' (принято, никогда не выдаётся — сеть живого сайта не переходит в состояние простоя) |
targets[].waitForSelector | строка | Необязательный CSS-селектор для ожидания после перехода |
targets[].timeoutMs | число | Таймаут на URL, 1000-30000 (по умолчанию 10000) |
includeHtml | логический | Возвращать сырой HTML в каждом результате (по умолчанию false) |
captureScreenshots | логический | Возвращать один PNG на цель (по умолчанию true) |
Все цели в пакете используют один общий туннель сессии, но только пакеты с одним портом (или все публичные) используют одно выполнение бэкенда — 5 URL-адресов на одном порту в одном вызове значительно быстрее, чем 5 параллельных вызовов по одному URL. Пакет, смешивающий несколько локальных портов, разбивается на одно последовательное выполнение бэкенда на группу портов (всё ещё один вызов, всё ещё один объединённый results[] в вашем исходном порядке, но N обратных переходов бэкенда вместо одного — медленнее, не отклоняется). Поле error на каждый URL сохраняет устойчивость пакета: одна неудачная цель не приводит к сбою остальных.
Ключ агрегации networkSummary — это origin + pathname — циклы повторных запросов (?n=0..4 многократно обращается к одной и той же конечной точке) схлопываются в одну запись со счётчиком, поэтому /api/poll, появляющийся с count: 47, — это тот самый сигнал «бесконечного цикла повторных запросов», о котором просили пользователи.
Бюджет производительности: <10 с для 1 URL, <25 с для 20. Мёртвый порт localhost возвращает LocalServerUnreachable менее чем за 2 с, не сжигая выполнение рабочего процесса.
project
| Действие | Параметры | Результат |
|---|---|---|
get | {uuid} | Подробная информация о проекте |
list | {q?, page?, pageSize?} | Постраничные сводки |
create | {name, platform, (teamUuid|teamName), (repoUuid|repoName)} | Созданный проект |
Команда и репозиторий определяются либо по uuid, либо по имени (точное совпадение без учёта регистра; NotFound, если ничего не найдено, AmbiguousMatch, если найдено несколько). Нет update/delete — переименуйте или удалите проект в веб-приложении DebuggAI.
environment
| Действие | Параметры | Результат |
|---|---|---|
get | {uuid, projectUuid?} | Окружение с встроенными учётными данными (пароли никогда не возвращаются) |
list | {projectUuid?, q?, page?, pageSize?} | Постраничные окружения, каждое с массивом учётных данных |
create | {name, url, description?, projectUuid?, credentials?, authorizedCredentialHosts?} | Созданное окружение (опционально заполняет учётные данные) |
update | {uuid, name?, url?, description?, addCredentials?, updateCredentials?, removeCredentialIds?, authorizedCredentialHosts?} | Изменённое окружение; операции с учётными данными выполняются в порядке удалить → обновить → добавить |
delete | {uuid, projectUuid?, confirm?} | Удаляет окружение (каскадно удаляет учётные данные) — требуется подтверждение |
sessions | {uuid, username?, credentialId?} | Захваченные сеансы входа, которые хранит окружение, по каждой учётной записи, каждый со своим isUsable |
clearSessions | {uuid, username?, credentialId?, confirm?} | Делает их недействительными, чтобы следующий запуск выполнил реальный вход — очистка без области действия требует подтверждения |
projectUuid автоматически определяется из git-репозитория, если не указано. Сбои отдельных учётных данных отображаются в credentialWarnings[] без блокировки операции с окружением.
authorizedCredentialHosts перечисляет хосты, на которых запуск может использовать учётные данные этого окружения помимо собственного хоста приложения — для кросс-доменного SSO добавьте сюда хост IdP (например, ["auth.example.com"]). Только голые имена хостов: без схемы, пути, порта или подстановочных знаков (поддомены хоста приложения уже входят в область действия). При update он заменяет список; [] очищает его. get/list возвращают его, если сервер это поддерживает. Ответ возвращает сохранённый список; если сервер не сохранил его (старые серверы игнорируют поле), результат содержит authorizedCredentialHostsWarning: {requested, returned} вместо молчаливого успеха.
sessions / clearSessions управляют тёплыми аутентифицированными сеансами, которые бэкенд повторно использует, чтобы пропустить вход (см. Повторное использование сеансов). Содержимое сеансов никогда не возвращается — cookie сеанса является учётным данным типа bearer. clearSessions помечает сеансы как недействительные, а не удаляет строки, поэтому повторное использование прекращается немедленно, а история захвата остаётся читаемой.
test_suite
| Действие | Параметры | Результат |
|---|---|---|
list | {projectUuid|projectName, search?, page?, pageSize?} | Постраничные наборы тестов со статусом и процентом прохождения |
create | {name, description, projectUuid|projectName} | Созданный набор тестов |
run | {suiteUuid|(suiteName+project), targetUrl?} | Запускает все тесты асинхронно |
results | {suiteUuid|(suiteName+project)} | Набор тестов + результаты по каждому тесту |
delete | {suiteUuid|(suiteName+project), confirm?} | Мягкое удаление — требуется подтверждение |
test_case
| Действие | Параметры | Результат |
|---|---|---|
create | {name, description, agentTaskDescription, suiteUuid|(suiteName+project), relativeUrl?, maxSteps?} | Созданный тестовый сценарий (не запускается автоматически) |
update | {testUuid, name?, description?, agentTaskDescription?} | Изменённый тестовый сценарий |
delete | {testUuid, confirm?} | Мягкое удаление — требуется подтверждение |
executions
| Действие | Параметры | Результат |
|---|---|---|
get | {uuid} | Полная информация (nodeExecutions + состояние + errorInfo) + артефакты скриншотов/gif |
list | {status?, projectUuid?, page?, pageSize?} | Постраничные сводки |
404 от бэкенда отображается как isError: true с {error: 'NotFound', message, uuid}. Учётные данные всегда возвращаются без паролей.
Постраничная навигация
Каждый ответ list разбит на страницы. Форма ответа:
{
"pageInfo": { "page": 1, "pageSize": 20, "totalCount": 47, "totalPages": 3, "hasMore": true },
"<items>": [ ... ]
}
Передайте необязательные page (с 1, по умолчанию 1) и pageSize (по умолчанию 20, максимум 200; значения сверх лимита ограничиваются). Ни один ответ никогда не обрезается молча.
get возвращает один объект под его единственным именем — {project}, {execution}, {project, environment} — без pageInfo.
Ресурсы
Наряду с инструментами сервер предоставляет доступные только для чтения сущности как MCP ресурсы, чтобы клиенты могли просматривать их и упоминать через @ как контекст:
| URI | Что это |
|---|---|
debugg-ai://projects | Все проекты (первая страница) |
debugg-ai://environments | Окружения для автоматически определённого проекта |
debugg-ai://executions | Недавние выполнения (первая страница) |
debugg-ai://project/{uuid} | Один проект, полная информация |
debugg-ai://environment/{uuid} | Одно окружение (учётные данные встроены, пароли скрыты) |
debugg-ai://execution/{uuid} | Одно выполнение, полная информация об узлах + ссылки на артефакты |
Чтения направляются в те же обработчики, что и инструменты project / environment /
executions, поэтому данные и аутентификация идентичны. Ресурсы аддитивны —
клиенты без поддержки ресурсов продолжают использовать инструменты.
Инварианты безопасности
- Пароли доступны только для записи. Они никогда не появляются в теле ответа ни одного инструмента.
- URL туннелей (
*.tunnel.debugg.ai, а также устаревший*.ngrok.debugg.ai, на который исторические запуски всё ещё ссылаются) удаляются из всех ответов браузерного агента, включая текст, созданный агентом. - 404 от бэкенда отображаются как
isError: trueс{error: 'NotFound', ...}, никогда как выброшенные исключения. - Отсутствующий
DEBUGGAI_API_KEYотображается как структурированная ошибка инструмента при первом вызове — сервер по-прежнему регистрирует и перечисляет инструменты нормально.
Миграция на v6.0.0 (вердикты бэкенда, без текста от MCP)
Вердикт запуска — это pass | fail | error, при этом reason бэкенда передаётся дословно. Запуск, который
никогда не пытался выполнить тест, читается как outcome: null, skipped: true, skipReason.
| Удалено | Замена |
|---|---|
success | outcome |
failureCategory | outcome + reason |
stepsTaken / stepsBudget / stepsRemaining | budget: {maxSteps, usedSteps} |
failedNode | errorInfo |
get → projects[0] / executions[0] / environments[0] + pageInfo + filter | {project} / {execution} / {project, environment} |
message / note в предупреждениях и результатах | только структурированные поля |
Полный список: CHANGELOG.md 6.0.0.
Миграция на v3.0.0 (инструменты на основе действий)
v3 объединил 20 инструментов по глаголам в 8 инструментов на основе действий. Старый инструмент → новый tool {action}:
| Удалено | Замена |
|---|---|
search_projects | project {action:"get"} / project {action:"list"} |
create_project | project {action:"create"} |
update_project, delete_project | Удалено — используйте веб-приложение DebuggAI |
search_environments | environment {action:"get"} / {action:"list"} |
create_environment / update_environment / delete_environment | environment {action:"create"|"update"|"delete"} |
create_test_suite / search_test_suites / run_test_suite / get_test_suite_results / delete_test_suite | test_suite {action:"create"|"list"|"run"|"results"|"delete"} |
create_test_case / update_test_case / delete_test_case | test_case {action:"create"|"update"|"delete"} |
search_executions | executions {action:"get"|"list"} |
Параметр trigger_crawl headless | Удалено — всегда headless |
Действия delete теперь требуют подтверждения (запрос на уточнение или confirm: true). Клиенты подхватывают новый интерфейс при перезапуске MCP.
Миграция с v1.x (критическое изменение в v2.0.0)
v2 сократил поверхность с 22 инструментов до 11. Сопоставление старый инструмент → новый инструмент:
| Удалено | Замена |
|---|---|
list_projects, get_project | search_projects (режим uuid или режим фильтра) |
list_environments, get_environment | search_environments |
list_credentials, get_credential | search_environments — учётные данные встроены в каждое окружение |
create_credential | заполнение create_environment({credentials: [...]}) или update_environment({addCredentials: [...]}) |
update_credential | update_environment({updateCredentials: [{uuid, ...patch}]}) |
delete_credential | update_environment({removeCredentialIds: [uuid]}) |
list_teams, list_repos | create_project({teamName, repoName}) — разрешение имён с обработкой неоднозначности |
list_executions, get_execution | search_executions |
cancel_execution | Удалено — остановка бэкенда автоматическая |
Изменения формы ответа: голое поле count в ответах списков исчезло — используйте pageInfo.totalCount.
Конфигурация
| Переменная окружения | Обязательна | Назначение |
|---|---|---|
DEBUGGAI_API_KEY | да | Ключ API бэкенда. Псевдонимы: DEBUGGAI_API_TOKEN, DEBUGGAI_JWT_TOKEN. |
DEBUGGAI_API_URL | нет | Базовый URL бэкенда. По умолчанию https://api.debugg.ai. |
DEBUGGAI_TOKEN_TYPE | нет | token (по умолчанию) или bearer. |
DEBUGGAI_EVAL_TEMPLATE | нет | Переопределяет slug рабочего процесса App Evaluation, на который отправляет check_app_in_browser. По умолчанию flow/e2es/app-eval. Отправка привязана к этому slug, чтобы переименование шаблона бэкенда не сломало её. |
LOG_LEVEL | нет | error / warn / info (по умолчанию) / debug. |
POSTHOG_API_KEY | нет | Переопределяет встроенный ключ проекта телеметрии (например, для приватного форка). |
DEBUGGAI_TELEMETRY_DISABLED | нет | Установите в 1 / true / yes / on, чтобы полностью отключить телеметрию. |
DEBUGGAI_API_KEY=your_api_key
Удалённый / HTTP транспорт (опционально)
По умолчанию сервер использует stdio (локальный npx). Он также может работать как
размещённый многопользовательский удалённый MCP через stateless Streamable HTTP + OAuth:
DEBUGGAI_MCP_TRANSPORT=http PORT=3000 DEBUGGAI_TOKEN_TYPE=bearer npx -y @debugg-ai/debugg-ai-mcp@latest
Это OAuth Resource Server: каждый POST /mcp требует
Authorization: Bearer <token>; отсутствующие/недействительные токены получают 401 с
WWW-Authenticate, указывающим на метаданные RFC 9728, и клиенты выполняют поток OAuth
против объявленного сервера авторизации. Bearer-токен ограничен запросом —
api.debugg.ai проверяет его.
| Конечная точка | Назначение |
|---|---|
POST /mcp | MCP Streamable HTTP (защищено bearer-токеном) |
GET /.well-known/oauth-protected-resource | Метаданные RFC 9728 (обнаружение сервера авторизации) |
GET /health | Проверка работоспособности балансировщика / ECS |
| Переменная окружения | По умолчанию | Назначение |
|---|---|---|
DEBUGGAI_MCP_TRANSPORT | stdio | Установите в http для удалённого транспорта |
PORT | 3000 | HTTP порт прослушивания |
DEBUGGAI_MCP_PUBLIC_URL | https://mcp.debugg.ai | Публичный URL ресурса этого сервера (RFC 9728 resource) |
DEBUGGAI_OAUTH_ISSUER | https://auth.debugg.ai | Сервер авторизации, объявляемый клиентам |
DEBUGGAI_TOKEN_TYPE | token | Установите в bearer, чтобы токены OAuth передавались как Authorization: Bearer |
Установкам stdio ничего из этого не нужно.
Мультирепличные развёртывания (go/no-go перед раскаткой): состояние туннеля (сеансовый туннель,
его экземпляр Caddy и его блокировка портового маршрута) находится в процессе, привязано к каждому вызывающему
по хешу bearer-токена — нет межпроцессной координации. Запуск нескольких реплик за обычным
round-robin балансировщиком означает, что вызовы одного вызывающего могут попадать на разные реплики и создавать один
туннель на каждую реплику, которую они задевают, вместо одного на весь сеанс (ограничено
количеством реплик, самовосстанавливается через существующее автоматическое отключение по простою 55 минут — никогда не является
ошибкой корректности между сеансами, поскольку любой отдельный вызов инструмента остаётся на одной реплике на всё своё время). Чтобы получить
ожидаемое поведение «один туннель на сеанс» в мультирепличном HTTP-развёртывании, настройте
маршрутизацию, привязанную к сеансу, на балансировщике (sticky/consistent-hash по той же идентичности,
которую выводит getSessionKey() — на практике, bearer-токен Authorization вызывающего). См.
docs/local-tunnel-multiplexer-architecture-2026-07-31.md §2.1 для полного обоснования и
честного пути деградации, если это не настроено.
Телеметрия
Сервер MCP поставляется с включённой телеметрией по умолчанию — встроенным write-only ключом проекта PostHog (phc_*), чтобы команда могла наблюдать за частотой попаданий в кэш, частотой опросов, надёжностью туннелей и другими операционными метриками по всей установленной базе. Фиксируемые события:
| Событие | Когда |
|---|---|
tool.executed / tool.failed | При каждом вызове инструмента |
workflow.executed | При каждом выполнении браузерного агента (содержит pollCount, durationMs, finalIntervalMs) |
tunnel.provisioned / tunnel.provision_retry / tunnel.stopped | При каждом событии жизненного цикла туннеля |
template.lookup / project.lookup | Попадание/промах в кэше с durationMs при холодном вызове |
Политика конфиденциальности:
- Отдельный идентификатор — это
SHA-256(api_key).slice(0, 16)— никогда не сырой ключ, без PII. - Ключи
phc_*являются write-only по соглашению PostHog; безопасно встраивать в исходный код. - Установите
DEBUGGAI_TELEMETRY_DISABLED=1, чтобы полностью отказаться (разрешается в no-op провайдер; никакие события не покидают процесс).
Активный режим логируется при запуске:
Telemetry enabled (PostHog, DebuggAI default project). Set DEBUGGAI_TELEMETRY_DISABLED=1 to opt out.
Telemetry enabled (PostHog, custom POSTHOG_API_KEY)
Telemetry disabled (DEBUGGAI_TELEMETRY_DISABLED is set)
Локальная разработка
npm install
npm run build
npm run test:e2e # real end-to-end evals against the backend
Набор для оценки запускает собранный MCP-сервер как подпроцесс, проверяет каждый инструмент на реальном бэкенде и записывает артефакты каждого потока в scripts/evals/artifacts/<timestamp>/. См. scripts/evals/flows/ для отдельных сценариев.
Регистрация MCP: debugg-ai-local против debugg-ai
Этот репозиторий содержит .mcp.json, который регистрирует сервер в рамках проекта с именем debugg-ai-local, указывающий на node dist/index.js — только что собранный локальный код. Он активируется только тогда, когда рабочая директория Claude Code — этот репозиторий.
Ваши другие проекты должны использовать регистрацию в рамках пользователя debugg-ai, которая тянет из опубликованного npm-пакета:
npm run mcp:global # registers debugg-ai in ~/.claude.json to npx -y @debugg-ai/debugg-ai-mcp
После редактирования кода здесь запустите npm run mcp:local (который просто пересобирает), чтобы следующий вызов debugg-ai-local подхватил ваши изменения.
Ссылки
Dashboard · Docs · Issues · Discord
Лицензия Apache-2.0 © 2025 DebuggAI