Debugg AI
officielPermettez à vos agents de génération de code de créer et d'exécuter des tests de bout en bout sans configuration sur les nouvelles modifications de code dans des navigateurs distants via la plateforme de test Debugg AI.
Que pouvez-vous faire avec Debugg AI MCP ?
- Exécuter des tests de navigateur IA — Demandez de tester n'importe quelle URL ou application localhost avec des instructions en langage naturel via
check_app_in_browser, renvoyant succès/échec avec captures d'écran. - Sonder plusieurs pages rapidement — Utilisez
probe_pagepour vérifier par lots 1 à 20 URL pour les erreurs de console, les problèmes réseau et l'état rendu sans coûts LLM. - Gérer les environnements de test — Créez, mettez à jour ou listez des environnements avec des identifiants et des hôtes SSO autorisés à l'aide de l'outil
environment. - Déclencher des explorations de sites — Lancez
trigger_crawlpour peupler le graphe de connaissances du projet avec l'exploration par agent navigateur côté serveur. - Exécuter et suivre les suites de tests — Créez des suites, déclenchez des exécutions asynchrones et récupérez les résultats par test via les actions
test_suite. - Inspecter les artefacts d'exécution — Récupérez les détails complets d'exécution, les traces réseau HAR et les journaux de console via
executionspour déboguer les problèmes d'exécution.
Documentation
Debugg AI — Serveur MCP
Tests de navigateur propulsés par l'IA via le Protocole de contexte de modèle. Pointez-le vers n'importe quelle URL (ou localhost) et décrivez ce qu'il faut tester — un agent IA parcourt votre application et renvoie réussite/échec avec des captures d'écran.
Configuration
Nécessite Node.js 20.20.0 ou ultérieur (exigence transitive de posthog-node@^5.26.0).
Tester les URL http://localhost:... nécessite le binaire caddy — check_app_in_browser,
probe_page et trigger_crawl tunnelisent les cibles localhost via un proxy inverse Caddy local.
Cela s'installe automatiquement : la dépendance npm @radically-straightforward/caddy télécharge une
version épinglée de Caddy pour votre plateforme lors de npm install/npx — rien à installer vous-même dans
le cas normal. C'est désormais le seul binaire que ce package télécharge ; le client tunnel lui-même est
du TypeScript pur — il a remplacé le package ngrok, qui récupérait l'agent ngrok.
Si ce téléchargement n'a jamais eu lieu (npm install --ignore-scripts, une installation hors ligne/isolée), pointez CADDY_BIN vers
votre propre installation (brew install caddy / apt install caddy / voir
caddyserver.com/docs/install) — son absence se manifeste par une
erreur claire lors du premier appel d'URL localhost, pas par un blocage silencieux. Les appels d'URL publiques, chaque
outil non-navigateur et test_suite {action:"run"} (qui utilise son propre tunnel dédié et
contourne entièrement Caddy) n'en ont pas besoin de toute façon.
Obtenez une clé API sur debugg.ai, puis ajoutez à votre configuration client MCP :
{
"mcpServers": {
"debugg-ai": {
"command": "npx",
"args": ["-y", "@debugg-ai/debugg-ai-mcp"],
"env": {
"DEBUGGAI_API_KEY": "your_api_key_here"
}
}
}
}
Ou avec Docker :
docker run -i --rm --init -e DEBUGGAI_API_KEY=your_api_key quinnosha/debugg-ai-mcp
L'étape npm install du Dockerfile récupérerait caddy de la même manière automatique que les installations
locales, en principe — mais au moment où j'écris ceci, le Dockerfile ne COPY pas plusieurs répertoires dont
la construction a maintenant besoin (handlers, tools, types, config) et référence toujours un répertoire tunnels/
qui n'existe plus, donc une nouvelle construction échouera probablement avant que cela n'ait d'importance. C'est une
lacune préexistante, sans rapport avec Caddy. L'image quinnosha/debugg-ai-mcp actuellement publiée
précède la dépendance Caddy de toute façon — les appels d'URL localhost vers
check_app_in_browser/probe_page/trigger_crawl échoueront avec CaddyBinaryNotFoundError
dans cette image jusqu'à ce qu'elle soit reconstruite (Dockerfile corrigé) et republiée, ou que CADDY_BIN pointe vers
une intégrée séparément. Les appels d'URL publiques, les outils non-navigateur et test_suite {action:"run"}
ne sont pas affectés de toute façon.
Outils
Le serveur expose 8 outils : trois outils Navigateur plus un outil basé sur des actions par entité gérée. Les outils phares sont check_app_in_browser (agent IA complet) et probe_page (sonde de page légère sans LLM). Les autres — project, environment, test_suite, test_case, executions — prennent chacun un discriminateur action (par exemple {"action":"list"}) qui sélectionne l'opération. Les actions destructives delete nécessitent une confirmation (une invite d'élicitation lorsque prise en charge, sinon confirm: true).
Navigateur
check_app_in_browser
Exécute un agent navigateur IA contre votre application. L'agent navigue, interagit et fait un rapport avec des captures d'écran. Les URL localhost sont automatiquement tunnelisées via le serveur tunnel debugg.
| Paramètre | Type | Description |
|---|---|---|
description | chaîne requis | Quoi tester (langage naturel) |
url | chaîne requis | URL cible — http://localhost:3000 est automatiquement tunnelisée |
environmentId | chaîne | UUID d'un environnement spécifique |
credentialId | chaîne | UUID d'un identifiant spécifique |
credentialRole | chaîne | Choisir un identifiant par rôle (par exemple admin, guest) |
username | chaîne | Nom d'utilisateur pour la connexion (éphémère — non persisté) |
password | chaîne | Mot de passe pour la connexion (éphémère — non persisté) |
loginCredentials | tableau | Comptes pour les connexions que l'agent rencontre pendant la tâche — [{username, password, label?}] |
useEnvironmentCredentials | booléen | Défaut true. false interdit le remplissage automatique des identifiants stockés de l'environnement ; sans compte nommé, cela signifie ne pas se connecter du tout |
freshSession | booléen | Défaut false. true force une vraie connexion au lieu de réutiliser la session chaude conservée pour ce compte |
auth | objet | Précondition d'authentification — {precondition, entryUrl, deepUrl, environmentId, username, password} |
repoName | chaîne | Remplacer le nom de dépôt git auto-détecté (par exemple my-org/my-repo) |
Un contrôle ciblé par appel. L'agent a un budget interne d'environ 25 étapes ; divisez les suites plus larges en plusieurs appels.
Identifiants : passez-les comme paramètres, pas en prose
Nommer un compte uniquement dans description ne fait pas que l'agent l'utilise — il retombe sur l'identifiant stocké de l'environnement, et le rejet du mauvais compte par l'application ressemble à une défaillance de l'application. Tout ce que vous passez comme paramètre l'emporte sur le défaut de l'environnement pour chaque connexion de l'exécution, pas seulement la première :
username/password(oucredentialId/credentialRole) — l'identité de l'exécution.auth.username/auth.password— épingle la connexion de précondition lorsque vous utilisez aussiauth.precondition: "login".loginCredentials— comptes pour un formulaire de connexion que l'agent atteint en cours de tâche. C'est celui pour les flux comme définir un mot de passe → être redirigé vers la connexion → se connecter en tant que compte que vous venez de créer, où diviser en appels séparés perdrait l'état du navigateur.
Définissez useEnvironmentCredentials: false lorsqu'un repli silencieux vers l'utilisateur de test par défaut invaliderait le contrôle.
SSO inter-domaines ? Une exécution ne saisit des identifiants que sur l'hôte propre de l'application et ses sous-domaines ; une page de connexion sur un autre domaine est refusée comme offscope_host. Ajoutez l'hôte du fournisseur d'identité au authorizedCredentialHosts de l'environnement (voir environment).
Vérifier une page qui ne nécessite aucune connexion ? Passez useEnvironmentCredentials: false et ne nommez aucun compte. Cette combinaison signifie exactement ce qu'elle dit — ne pas se connecter — et l'exécution saute entièrement l'authentification au lieu de chercher un formulaire de connexion. Utilisez-la pour les pages publiques, les sites marketing, la documentation et tout ce qui est pré-authentification. C'est aussi plus rapide : sur le défaut (auto), l'agent suivra un lien « Se connecter » hors de votre page et essaiera le compte stocké de l'environnement avant d'évaluer quoi que ce soit.
Réutilisation de session : pourquoi un contrôle peut signaler « pas de formulaire de connexion »
Les exécutions ne se connectent pas à chaque fois. Après une connexion vérifiée, le backend capture la session de ce compte et la restaure lors de la prochaine exécution pour la même identité, ce qui saute entièrement la connexion — c'est pourquoi un contrôle peut légitimement revenir avec submitted: false et aucun formulaire de connexion : il était déjà connecté. Une exécution restaurée se signale dans logins avec reason: "restored_session", pour que vous puissiez la distinguer d'une exécution qui n'a vraiment trouvé aucun formulaire.
Les sessions sont clés par compte, donc nommer un compte différent ne réutilise jamais celle de quelqu'un d'autre. Deux façons de contourner la réutilisation :
freshSession: truesur un seul appel — se connecter pour de vrai cette fois, puis recapturer. Utilisez-le lorsque le flux de connexion est ce que vous vérifiez, lorsque vous soupçonnez que la session stockée est obsolète, ou lorsque la seule route de l'application entre les personas est une déconnexion.- Outil
environment,action: "clearSessions"— invalider les sessions stockées pour que les exécutions suivantes se connectent. Affinez avecusername/credentialId; les effacements sans portée nécessitent une confirmation car chaque compte de l'environnement se réauthentifie alors.
Utilisez action: "sessions" pour voir ce qu'un environnement détient actuellement et si chacun serait réutilisé.
Les résultats signalent l'identité réellement utilisée, donc une mauvaise est visible plutôt que de se faire passer pour une application cassée :
"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 est task | explicit | credential_id (un compte que vous avez nommé) ou env | env_default (le compte stocké de l'environnement). submitted est vrai uniquement lorsque des identifiants ont été réellement saisis et soumis ; reason dit ce qui s'est passé (par exemple offscope_host, restored_session), et detail, lorsqu'il est présent, est une explication lisible par un humain — pour un refus offscope_host, il nomme l'hôte et comment l'autoriser. credentialWarning apparaît uniquement lorsque vous avez nommé un compte et qu'un défaut d'environnement pour un compte différent a été réellement soumis — jamais pour une connexion refusée ou sautée. loginError apparaît lorsqu'un compte nommé n'a pas pu être résolu et que l'exécution a refusé d'en substituer un différent.
Chaque exécution réussie renvoie un bloc browserSession à côté de la capture d'écran — des URL S3 pré-signées pour le HAR capturé (trace réseau complète) et le journal de console (chaque message de console JS). Utilisez-les pour détecter les boucles de re-récupération, les erreurs d'hydratation et d'autres problèmes d'exécution qui passent les vérifications de type et les tests unitaires :
"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"
}
Les URL sont des S3 pré-signées à courte durée de vie — récupérez l'exécution parente via executions {action:"get", uuid} pour les renouveler. harStatus / consoleLogStatus distinguent 'downloaded' (URL récupérable), 'not_available' (la page n'a rien émis), 'failed' (la capture a échoué). Sur une nouvelle exécution, les URL sont couramment null car la capture est téléchargée de manière asynchrone après la fin de l'agent — interrogez executions {action:"get", uuid: executionId} jusqu'à ce que le statut atteigne 'downloaded'. Les en-têtes Authorization / Cookie / token/secret/api_key sont nettoyés côté serveur avant que les artefacts ne soient persistés.
trigger_crawl
Déclenche un crawl d'agent navigateur côté serveur pour peupler le graphe de connaissances du projet. Les URL localhost se tunnelisent automatiquement. Renvoie {executionId, status, targetUrl, durationMs, outcome?, crawlSummary?, knowledgeGraph?, browserSession?} avec knowledgeGraph.skipped === false lors d'une ingestion réussie. crawlSummary et knowledgeGraph ne portent que les clés que les nœuds de crawl / import du backend ont signalées — un compte manquant est absent, jamais un 0 rempli. Le bloc browserSession (URL HAR + journal de console, même forme que ci-dessus) est également présent sur les crawls terminés.
probe_page
Sonde de page par lots légère sans LLM. Passez 1 à 20 URL ; chacune navigue, se stabilise sur le contenu (le DOM se taisant, borné — jamais sur le silence réseau, qu'une application en direct n'atteint jamais), et renvoie l'état rendu — capture d'écran + métadonnées de page + erreurs de console structurées + résumé réseau. Pas de boucle d'agent, pas de coût LLM, pas d'assertions de scénario. Utilisez-la pour « ai-je cassé /settings ? », des fumigènes multi-routes après un refactor, des balayages CI par PR, et des vérifications rapides de disponibilité où la boucle d'agent de 60 à 150 s de check_app_in_browser est excessive.
| Paramètre | Type | Description |
|---|---|---|
targets | tableau requis | 1 à 20 entrées : [{url, waitForSelector?, waitForLoadState?, timeoutMs?}] |
targets[].url | chaîne requis | URL publique ou localhost (tunnelisé automatiquement) |
targets[].waitForLoadState | énumération | 'domcontentloaded' (défaut, + une stabilisation de contenu bornée) / 'load' (bloque aussi sur les embeds tiers) / 'networkidle' (accepté, jamais émis — le réseau d'un site en direct ne passe pas à l'inactivité) |
targets[].waitForSelector | chaîne | Sélecteur CSS optionnel à attendre après la navigation |
targets[].timeoutMs | nombre | Délai d'attente par URL, 1000-30000 (défaut 10000) |
includeHtml | booléen | Renvoyer le HTML brut dans chaque résultat (défaut faux) |
captureScreenshots | booléen | Renvoyer un PNG par cible (défaut vrai) |
Toutes les cibles d'un lot partagent un tunnel de session, mais seuls les lots de même port (ou entièrement publics) partagent une seule exécution backend — 5 URL sur un port en un appel est nettement plus rapide que 5 appels parallèles à URL unique. Un lot qui mélange plusieurs ports locaux se décompose en une exécution backend séquentielle par groupe de ports (toujours un appel, toujours un results[] fusionné dans votre ordre d'origine, mais N allers-retours backend au lieu d'un — plus lent, pas rejeté). Le champ error par URL préserve la résilience du lot : une seule cible en échec ne fait pas échouer les autres.
networkSummary la clé d'agrégation est origin + pathname — les boucles de re-récupération (?n=0..4 frappant à plusieurs reprises le même endpoint) se réduisent en une seule entrée avec le compte, donc /api/poll apparaissant avec count: 47 est le signal actionnable de « boucle de re-récupération infinie » que les utilisateurs demandaient à l'origine.
Budget de performance : <10s pour 1 URL, <25s pour 20. Le port mort de localhost renvoie LocalServerUnreachable en <2s sans consommer une exécution de workflow.
project
| Action | Paramètres | Résultat |
|---|---|---|
get | {uuid} | Détail de projet organisé |
list | {q?, page?, pageSize?} | Résumés paginés |
create | {name, platform, (teamUuid|teamName), (repoUuid|repoName)} | Projet créé |
L'équipe et le dépôt se résolvent par soit uuid soit nom (correspondance exacte insensible à la casse ; NotFound si aucun, AmbiguousMatch si plusieurs). Il n'y a pas de update/delete — renommez ou supprimez un projet depuis l'application web DebuggAI.
environment
| Action | Paramètres | Résultat |
|---|---|---|
get | {uuid, projectUuid?} | Environnement avec identifiants intégrés (les mots de passe ne sont jamais renvoyés) |
list | {projectUuid?, q?, page?, pageSize?} | Environnements paginés, chacun avec un tableau d'identifiants |
create | {name, url, description?, projectUuid?, credentials?, authorizedCredentialHosts?} | Environnement créé (peut initialiser les identifiants) |
update | {uuid, name?, url?, description?, addCredentials?, updateCredentials?, removeCredentialIds?, authorizedCredentialHosts?} | Environnement corrigé ; les opérations d'identifiants s'exécutent supprimer → mettre à jour → ajouter |
delete | {uuid, projectUuid?, confirm?} | Supprime l'environnement (supprime en cascade les identifiants) — nécessite une confirmation |
sessions | {uuid, username?, credentialId?} | Sessions de connexion capturées que l'environnement détient, par compte, chacune avec son propre isUsable |
clearSessions | {uuid, username?, credentialId?, confirm?} | Les invalide pour que la prochaine exécution se connecte réellement — les effacements sans portée nécessitent une confirmation |
projectUuid se résout automatiquement depuis le dépôt git lorsqu'il est omis. Les échecs par identifiant apparaissent dans credentialWarnings[] sans bloquer l'opération d'environnement.
authorizedCredentialHosts liste les hôtes où une exécution peut entrer les identifiants de cet environnement en plus de l'hôte propre de l'application — pour le SSO inter-domaines, ajoutez l'hôte IdP ici (par ex. ["auth.example.com"]). Uniquement des noms d'hôtes nus : pas de schéma, chemin, port ou caractère générique (les sous-domaines de l'hôte de l'application sont déjà dans le périmètre). Sur update, il remplace la liste ; [] l'efface. get/list la renvoient lorsque le serveur la prend en charge. La réponse renvoie la liste enregistrée ; si le serveur ne l'a pas persistée (les serveurs plus anciens ignorent le champ), le résultat porte authorizedCredentialHostsWarning: {requested, returned} au lieu d'un succès silencieux.
sessions / clearSessions gèrent les sessions authentifiées chaudes que le backend réutilise pour sauter la connexion (voir Réutilisation de session). Le contenu des sessions n'est jamais renvoyé — un cookie de session est un identifiant porteur. clearSessions marque les sessions comme invalides plutôt que de supprimer les lignes, afin que la réutilisation s'arrête immédiatement tout en gardant l'historique de capture lisible.
test_suite
| Action | Paramètres | Résultat |
|---|---|---|
list | {projectUuid|projectName, search?, page?, pageSize?} | Suites paginées avec statut + taux de réussite |
create | {name, description, projectUuid|projectName} | Suite créée |
run | {suiteUuid|(suiteName+project), targetUrl?} | Déclenche tous les tests en asynchrone |
results | {suiteUuid|(suiteName+project)} | Suite + résultats par test |
delete | {suiteUuid|(suiteName+project), confirm?} | Suppression douce — nécessite une confirmation |
test_case
| Action | Paramètres | Résultat |
|---|---|---|
create | {name, description, agentTaskDescription, suiteUuid|(suiteName+project), relativeUrl?, maxSteps?} | Cas de test créé (non exécuté automatiquement) |
update | {testUuid, name?, description?, agentTaskDescription?} | Cas de test corrigé |
delete | {testUuid, confirm?} | Suppression douce — nécessite une confirmation |
executions
| Action | Paramètres | Résultat |
|---|---|---|
get | {uuid} | Détail complet (nodeExecutions + état + errorInfo) + artefacts de capture d'écran/gif |
list | {status?, projectUuid?, page?, pageSize?} | Résumés paginés |
Le 404 du backend apparaît comme isError: true avec {error: 'NotFound', message, uuid}. Les identifiants sont toujours renvoyés sans mots de passe.
Pagination
Chaque réponse list est paginée. Forme de la réponse :
{
"pageInfo": { "page": 1, "pageSize": 20, "totalCount": 47, "totalPages": 3, "hasMore": true },
"<items>": [ ... ]
}
Passez les paramètres optionnels page (indexé à partir de 1, défaut 1) et pageSize (défaut 20, max 200 ; les valeurs trop grandes sont plafonnées). Aucune réponse n'est jamais tronquée silencieusement.
Un get renvoie l'objet unique sous son nom singulier — {project}, {execution}, {project, environment} — sans pageInfo.
Ressources
En plus des outils, le serveur expose les entités en lecture seule comme ressources MCP afin que les clients puissent les parcourir et les mentionner avec @ comme contexte :
| URI | Quoi |
|---|---|
debugg-ai://projects | Tous les projets (première page) |
debugg-ai://environments | Environnements pour le projet auto-détecté |
debugg-ai://executions | Exécutions récentes (première page) |
debugg-ai://project/{uuid} | Un projet, détail complet |
debugg-ai://environment/{uuid} | Un environnement (identifiants intégrés, mots de passe masqués) |
debugg-ai://execution/{uuid} | Une exécution, détail complet des nœuds + liens d'artefacts |
Les lectures sont distribuées aux mêmes gestionnaires que les outils project / environment / executions, donc les données et l'authentification sont identiques. Les ressources sont additives — les clients sans support des ressources continuent d'utiliser les outils.
Invariants de sécurité
- Les mots de passe sont en écriture seule. Ils n'apparaissent jamais dans le corps d'aucune réponse d'aucun outil.
- Les URL de tunnel (
*.tunnel.debugg.ai, et le*.ngrok.debugg.airetiré auquel les exécutions historiques font encore référence) sont supprimées de toutes les réponses de l'agent navigateur, y compris le texte rédigé par l'agent. - Les 404 du backend apparaissent comme
isError: trueavec{error: 'NotFound', ...}, jamais comme des exceptions levées. - Un
DEBUGGAI_API_KEYmanquant apparaît comme une erreur d'outil structurée lors de la première invocation — le serveur enregistre et liste toujours les outils normalement.
Migration vers v6.0.0 (verdicts du backend, aucun texte rédigé par MCP)
Un verdict d'exécution est pass | fail | error, avec le reason du backend relayé textuellement. Une exécution qui n'a jamais tenté un test lit outcome: null, skipped: true, skipReason.
| Supprimé | Remplacement |
|---|---|
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 sur les avertissements et résultats | champs structurés uniquement |
Liste complète : CHANGELOG.md 6.0.0.
Migration vers v3.0.0 (outils basés sur les actions)
v3 a consolidé les 20 outils par verbe en 8 outils basés sur les actions. Ancien outil → nouveau tool {action} :
| Supprimé | Remplacement |
|---|---|
search_projects | project {action:"get"} / project {action:"list"} |
create_project | project {action:"create"} |
update_project, delete_project | Abandonnés — utilisez l'application web 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 paramètre headless | Abandonné — toujours sans tête |
Les actions delete nécessitent désormais une confirmation (invite d'élicitation, ou confirm: true). Les clients récupèrent la nouvelle surface au redémarrage de MCP.
Migration depuis v1.x (changement cassant dans v2.0.0)
v2 a réduit une surface de 22 outils à 11. Correspondance ancien outil → nouvel outil :
| Supprimé | Remplacement |
|---|---|
list_projects, get_project | search_projects (mode uuid vs mode filtre) |
list_environments, get_environment | search_environments |
list_credentials, get_credential | search_environments — identifiants intégrés sur chaque environnement |
create_credential | create_environment({credentials: [...]}) seed, ou update_environment({addCredentials: [...]}) |
update_credential | update_environment({updateCredentials: [{uuid, ...patch}]}) |
delete_credential | update_environment({removeCredentialIds: [uuid]}) |
list_teams, list_repos | create_project({teamName, repoName}) — résolution de nom avec gestion d'ambiguïté |
list_executions, get_execution | search_executions |
cancel_execution | Abandonné — l'arrêt du backend est automatique |
Changements de forme des réponses : le champ nu count sur les réponses de liste a disparu — utilisez pageInfo.totalCount.
Configuration
| Variable d'environnement | Requise | Objectif |
|---|---|---|
DEBUGGAI_API_KEY | oui | Clé API du backend. Alias : DEBUGGAI_API_TOKEN, DEBUGGAI_JWT_TOKEN. |
DEBUGGAI_API_URL | non | URL de base du backend. Par défaut https://api.debugg.ai. |
DEBUGGAI_TOKEN_TYPE | non | token (défaut) ou bearer. |
DEBUGGAI_EVAL_TEMPLATE | non | Remplace le slug du workflow d'évaluation d'application vers lequel check_app_in_browser distribue. Par défaut flow/e2es/app-eval. La distribution est épinglée à ce slug afin qu'un renommage de modèle backend ne puisse pas le casser. |
LOG_LEVEL | non | error / warn / info (défaut) / debug. |
POSTHOG_API_KEY | non | Remplace la clé de projet de télémétrie intégrée (par ex. fork privé). |
DEBUGGAI_TELEMETRY_DISABLED | non | Définir sur 1 / true / yes / on pour désactiver entièrement la télémétrie. |
DEBUGGAI_API_KEY=your_api_key
Transport distant / HTTP (optionnel)
Par défaut, le serveur parle stdio (npx local). Il peut à la place s'exécuter comme un MCP distant hébergé multi-utilisateurs sur Streamable HTTP sans état + OAuth :
DEBUGGAI_MCP_TRANSPORT=http PORT=3000 DEBUGGAI_TOKEN_TYPE=bearer npx -y @debugg-ai/debugg-ai-mcp@latest
C'est un serveur de ressources OAuth : chaque POST /mcp nécessite Authorization: Bearer <token> ; les jetons manquants/invalides obtiennent un 401 avec un WWW-Authenticate pointant vers les métadonnées RFC 9728, et les clients exécutent le flux OAuth contre le serveur d'autorisation annoncé. Le porteur est limité à la requête — api.debugg.ai le valide.
| Endpoint | Objectif |
|---|---|
POST /mcp | MCP Streamable HTTP (protégé par porteur) |
GET /.well-known/oauth-protected-resource | Métadonnées RFC 9728 (découverte du serveur d'autorisation) |
GET /health | Contrôle de santé du répartiteur de charge / ECS |
| Variable d'environnement | Défaut | Objectif |
|---|---|---|
DEBUGGAI_MCP_TRANSPORT | stdio | Définir sur http pour le transport distant |
PORT | 3000 | Port d'écoute HTTP |
DEBUGGAI_MCP_PUBLIC_URL | https://mcp.debugg.ai | URL de ressource publique de ce serveur (RFC 9728 resource) |
DEBUGGAI_OAUTH_ISSUER | https://auth.debugg.ai | Serveur d'autorisation annoncé aux clients |
DEBUGGAI_TOKEN_TYPE | token | Définir sur bearer pour que les jetons OAuth soient transmis comme Authorization: Bearer |
Les installations stdio n'ont besoin d'aucune de ces variables.
Déploiements multi-réplicas (go/no-go avant déploiement) : l'état du tunnel (le tunnel de session, son instance Caddy et son verrou de route de port) est en processus, indexé par appelant via un hachage du jeton porteur — il n'y a aucune coordination inter-processus. Exécuter plusieurs réplicas derrière un répartiteur de charge en round-robin simple signifie que les appels d'un même appelant peuvent atterrir sur différents réplicas et créer un tunnel par réplica touché au lieu d'un seul pour toute la session (borné par le nombre de réplicas, auto-réparateur via l'arrêt automatique existant après 55 minutes d'inactivité — jamais un bug de correction inter-sessions, puisque tout appel d'outil unique reste sur un réplica pendant toute sa durée). Pour obtenir le comportement voulu « un tunnel par session » sur un déploiement HTTP multi-réplicas, configurez un routage affine à la session au niveau du répartiteur de charge (collant/hachage cohérent basé sur la même identité dont getSessionKey() dérive — en pratique, le jeton porteur Authorization de l'appelant). Voir docs/local-tunnel-multiplexer-architecture-2026-07-31.md §2.1 pour le raisonnement complet et le chemin de dégradation honnête si cela n'est pas configuré.
Télémétrie
Le serveur MCP est livré avec la télémétrie activée par défaut — une clé de projet PostHog intégrée en écriture seule (phc_*) afin que l'équipe puisse observer les taux de succès du cache, la cadence de sondage, la fiabilité du tunnel et d'autres métriques opérationnelles sur l'ensemble des installations. Événements capturés :
| Événement | Quand |
|---|---|
tool.executed / tool.failed | Par appel d'outil |
workflow.executed | Par exécution d'agent navigateur (contient pollCount, durationMs, finalIntervalMs) |
tunnel.provisioned / tunnel.provision_retry / tunnel.stopped | Par événement de cycle de vie du tunnel |
template.lookup / project.lookup | Succès/échec du cache avec durationMs sur appel à froid |
Posture de confidentialité :
- L'ID distinct est
SHA-256(api_key).slice(0, 16)— jamais la clé brute, aucune donnée personnelle. - Les clés
phc_*sont en écriture seule par convention PostHog ; sûres à intégrer dans le code source. - Définissez
DEBUGGAI_TELEMETRY_DISABLED=1pour vous désinscrire entièrement (se résout en un fournisseur sans opération ; aucun événement ne quitte le processus).
Le mode actif est journalisé au démarrage :
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)
Développement local
npm install
npm run build
npm run test:e2e # real end-to-end evals against the backend
La suite d'évaluation lance le serveur MCP compilé comme sous-processus, exerce chaque outil contre un backend réel et écrit les artefacts par flux dans scripts/evals/artifacts/<timestamp>/. Voir scripts/evals/flows/ pour les scénarios individuels.
Enregistrement MCP : debugg-ai-local vs debugg-ai
Ce dépôt contient un .mcp.json qui enregistre un serveur limité au projet nommé debugg-ai-local pointant vers node dist/index.js — le code local fraîchement compilé. Il ne s'active que lorsque le répertoire de travail de Claude Code est ce dépôt.
Vos autres projets doivent utiliser l'enregistrement limité à l'utilisateur debugg-ai qui tire depuis le package npm publié :
npm run mcp:global # registers debugg-ai in ~/.claude.json to npx -y @debugg-ai/debugg-ai-mcp
Après avoir modifié le code ici, exécutez npm run mcp:local (qui ne fait que recompiler) afin que la prochaine invocation de debugg-ai-local prenne en compte vos modifications.
Liens
Dashboard · Docs · Issues · Discord
Licence Apache-2.0 © 2025 DebuggAI