Debugg AI

officiel

Permettez à 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_page pour 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_crawl pour 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 executions pour 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.

Debugg AI MCP server

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ètreTypeDescription
descriptionchaîne requisQuoi tester (langage naturel)
urlchaîne requisURL cible — http://localhost:3000 est automatiquement tunnelisée
environmentIdchaîneUUID d'un environnement spécifique
credentialIdchaîneUUID d'un identifiant spécifique
credentialRolechaîneChoisir un identifiant par rôle (par exemple admin, guest)
usernamechaîneNom d'utilisateur pour la connexion (éphémère — non persisté)
passwordchaîneMot de passe pour la connexion (éphémère — non persisté)
loginCredentialstableauComptes pour les connexions que l'agent rencontre pendant la tâche — [{username, password, label?}]
useEnvironmentCredentialsbooléenDé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
freshSessionbooléenDéfaut false. true force une vraie connexion au lieu de réutiliser la session chaude conservée pour ce compte
authobjetPrécondition d'authentification — {precondition, entryUrl, deepUrl, environmentId, username, password}
repoNamechaîneRemplacer 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 (ou credentialId / credentialRole) — l'identité de l'exécution.
  • auth.username / auth.password — épingle la connexion de précondition lorsque vous utilisez aussi auth.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: true sur 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 avec username / 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ètreTypeDescription
targetstableau requis1 à 20 entrées : [{url, waitForSelector?, waitForLoadState?, timeoutMs?}]
targets[].urlchaîne requisURL 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[].waitForSelectorchaîneSélecteur CSS optionnel à attendre après la navigation
targets[].timeoutMsnombreDélai d'attente par URL, 1000-30000 (défaut 10000)
includeHtmlbooléenRenvoyer le HTML brut dans chaque résultat (défaut faux)
captureScreenshotsbooléenRenvoyer 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

ActionParamètresRé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

ActionParamètresRé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

ActionParamètresRé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

ActionParamètresRé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

ActionParamètresRé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 :

URIQuoi
debugg-ai://projectsTous les projets (première page)
debugg-ai://environmentsEnvironnements pour le projet auto-détecté
debugg-ai://executionsExé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.ai retiré 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: true avec {error: 'NotFound', ...}, jamais comme des exceptions levées.
  • Un DEBUGGAI_API_KEY manquant 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
successoutcome
failureCategoryoutcome + reason
stepsTaken / stepsBudget / stepsRemainingbudget: {maxSteps, usedSteps}
failedNodeerrorInfo
get → projects[0] / executions[0] / environments[0] + pageInfo + filter{project} / {execution} / {project, environment}
message / note sur les avertissements et résultatschamps 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_projectsproject {action:"get"} / project {action:"list"}
create_projectproject {action:"create"}
update_project, delete_projectAbandonnés — utilisez l'application web DebuggAI
search_environmentsenvironment {action:"get"} / {action:"list"}
create_environment / update_environment / delete_environmentenvironment {action:"create"|"update"|"delete"}
create_test_suite / search_test_suites / run_test_suite / get_test_suite_results / delete_test_suitetest_suite {action:"create"|"list"|"run"|"results"|"delete"}
create_test_case / update_test_case / delete_test_casetest_case {action:"create"|"update"|"delete"}
search_executionsexecutions {action:"get"|"list"}
trigger_crawl paramètre headlessAbandonné — 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_projectsearch_projects (mode uuid vs mode filtre)
list_environments, get_environmentsearch_environments
list_credentials, get_credentialsearch_environments — identifiants intégrés sur chaque environnement
create_credentialcreate_environment({credentials: [...]}) seed, ou update_environment({addCredentials: [...]})
update_credentialupdate_environment({updateCredentials: [{uuid, ...patch}]})
delete_credentialupdate_environment({removeCredentialIds: [uuid]})
list_teams, list_reposcreate_project({teamName, repoName}) — résolution de nom avec gestion d'ambiguïté
list_executions, get_executionsearch_executions
cancel_executionAbandonné — 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'environnementRequiseObjectif
DEBUGGAI_API_KEYouiClé API du backend. Alias : DEBUGGAI_API_TOKEN, DEBUGGAI_JWT_TOKEN.
DEBUGGAI_API_URLnonURL de base du backend. Par défaut https://api.debugg.ai.
DEBUGGAI_TOKEN_TYPEnontoken (défaut) ou bearer.
DEBUGGAI_EVAL_TEMPLATEnonRemplace 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_LEVELnonerror / warn / info (défaut) / debug.
POSTHOG_API_KEYnonRemplace la clé de projet de télémétrie intégrée (par ex. fork privé).
DEBUGGAI_TELEMETRY_DISABLEDnonDé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.

EndpointObjectif
POST /mcpMCP Streamable HTTP (protégé par porteur)
GET /.well-known/oauth-protected-resourceMétadonnées RFC 9728 (découverte du serveur d'autorisation)
GET /healthContrôle de santé du répartiteur de charge / ECS
Variable d'environnementDéfautObjectif
DEBUGGAI_MCP_TRANSPORTstdioDéfinir sur http pour le transport distant
PORT3000Port d'écoute HTTP
DEBUGGAI_MCP_PUBLIC_URLhttps://mcp.debugg.aiURL de ressource publique de ce serveur (RFC 9728 resource)
DEBUGGAI_OAUTH_ISSUERhttps://auth.debugg.aiServeur d'autorisation annoncé aux clients
DEBUGGAI_TOKEN_TYPEtokenDé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énementQuand
tool.executed / tool.failedPar appel d'outil
workflow.executedPar exécution d'agent navigateur (contient pollCount, durationMs, finalIntervalMs)
tunnel.provisioned / tunnel.provision_retry / tunnel.stoppedPar événement de cycle de vie du tunnel
template.lookup / project.lookupSuccè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=1 pour 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