La ligne de commande, et le serveur MCP qu’elle contient

Un seul paquet npm fait trois choses : il envoie les source maps qui rendent une pile d’appels lisible, il soumet un diff à relecture, et il expose votre télémétrie à un agent de code via MCP. C’est la troisième qui mérite votre attention — elle met vos erreurs de production sous les yeux de l’agent qui modifie le code.

Installation

Il faut Node 20.19 ou plus récent. Rien à installer si vous voulez seulement essayer : npx le récupère et l’exécute en une seule étape, ce qui est la bonne forme pour un job de CI, qui a intérêt à figer une version plutôt qu’à suivre la dernière en date.

Chaque commande annonce ce qu’elle va faire avant de le faire, et --dry-run sur les deux commandes qui envoient quelque chose vous montre la charge utile sans rien transmettre.

Terminal
# une fois, sans installer
npx [email protected] whoami

# ou bien installez-le
npm install -g snagspy
snagspy --help

Donnez-lui un jeton, par l’environnement

L’authentification se fait avec une clé d’API créée dans les réglages de votre organisation. La CLI lit SNAGSPY_TOKEN, et il existe une option --token qu’il vaut mieux éviter : un argument est visible par tout ce qui peut lister les processus sur la machine, et il reste dans l’historique du shell. Cette option existe parce qu’il n’y a parfois pas d’autre moyen, pas parce que c’est le moyen normal.

SNAGSPY_API désigne l’API et ne sert que si vous n’êtes pas sur la plateforme hébergée. whoami est la commande à lancer quand quelque chose est refusé et que vous voulez savoir quelle organisation et quelles portées le jeton porte réellement : elle affiche ces deux choses et rien d’autre, donc elle se colle sans risque dans un rapport de bug.

Terminal
export SNAGSPY_TOKEN=slk_...
snagspy whoami

organisation: Example Ltd (cafb3c85-07d2-44a8-bab1-a7f04fffb0e6)
scopes:       events:read, issues:write

Chaque commande exige sa portée, et rien de plus

Les quatre commandes demandent quatre portées différentes : un jeton créé pour que la CI envoie des source maps ne peut lire aucun événement. C’est tout l’intérêt de les séparer — l’identifiant qui vit dans votre chaîne de build doit pouvoir faire la seule chose que fait votre chaîne de build.

Un jeton portant plusieurs portées est parfaitement normal : celui d’un développeur porte en général les deux qu’utilise le serveur MCP. La séparation compte surtout pour les jetons que vous ne regarderez plus jamais.

Portée par commande
snagspy upload    artifacts:write
snagspy review    code:review
snagspy mcp       events:read     (lecture)
snagspy mcp       issues:write    (changer le statut d’un incident)
snagspy whoami    n’importe laquelle

Envoyez vos source maps, pour qu’une pile d’appels nomme votre code

Une pile d’appels minifiée annonce t.js:1:4821, ce qui n’apprend rien à personne. Envoyer les source maps d’une version rétablit le fichier et la ligne que quelqu’un a écrits. Faites-le pendant le build, après le bundler et avant le déploiement.

--release est optionnel et vous devriez toujours le passer. Une source map envoyée sans version ne peut être rattachée au build qui a produit l’erreur : la résolution n’a alors silencieusement pas lieu — et une pile non résolue ressemble exactement à une pile issue d’une version dont vous n’avez jamais envoyé les source maps.

La commande indique ce qu’elle a envoyé et ce qu’elle a ignoré. Un fichier sans source map à côté de lui est ignoré plutôt que traité comme une erreur, parce qu’un répertoire dist contient normalement les deux.

Terminal
snagspy upload --project <id-du-projet> --release v1.4.2 ./dist

snagspy upload: 1 sent, 0 skipped, from ./dist

Soumettez une modification à relecture

snagspy review calcule le diff de votre branche et l’envoie pour commentaire. Sans option, il déduit une base de fusion à partir de origin/HEAD ; --base origin/main le dit explicitement, et --diff lit un diff unifié depuis un fichier si vous préférez lancer git vous-même.

--fail-on décide si une remarque fait échouer votre build, et vaut never par défaut. Ce choix est délibéré : adopter cet outil un vendredi ne doit pas faire échouer dès le même après-midi tous les pipelines de l’organisation. Passez à high une fois que vous aurez vu ce qu’il remonte sur votre propre code.

--format github produit des annotations en ligne, ce que vous voulez dans Actions. --fix applique à votre copie de travail les modifications proposées : rien n’est committé, rien n’est poussé, et git diff reste donc la façon dont vous décidez de les garder ou non.

Terminal
snagspy review --base origin/main
snagspy review --format github --fail-on high
snagspy review --dry-run          # affiche ce qui serait envoyé, n’envoie rien

Le serveur MCP : votre télémétrie, dans l’agent

snagspy mcp expose la télémétrie de votre organisation via MCP sur stdio, le transport que parlent Claude Code, Cursor et les autres clients d’agent. L’agent qui modifie un fichier peut alors demander ce qui échoue réellement en production, au lieu que vous recopiiez une pile d’appels dans une fenêtre de conversation.

C’est le même binaire et le même jeton. Indiquez la commande à votre client et donnez-lui l’environnement ; il n’y a pas de démon séparé et rien n’écoute sur un port.

Configuration du client d’agent
{
  "mcpServers": {
    "snagspy": {
      "command": "npx",
      "args": ["-y", "[email protected]", "mcp"],
      "env": { "SNAGSPY_TOKEN": "slk_..." }
    }
  }
}

Ce que l’agent peut demander

Dix outils, et le serveur n’enregistre que ceux que votre jeton peut appeler. Neuf lisent ; update_issue_status est le seul qui écrit, et il n’apparaît que pour un jeton portant issues:write. Un jeton ne portant aucune des deux portées est refusé au démarrage du serveur, plutôt que de se connecter en offrant une liste d’outils vide — un serveur qui démarre correctement et ne peut rien faire est le pire des deux échecs, parce que l’agent le rapporte comme « aucun résultat ».

L’assignation n’est délibérément pas proposée. L’API assigne un incident par revendication personnelle, et une clé d’API n’est pas une personne : il n’y a donc rien de cohérent qu’un agent puisse revendiquer.

Rien ici ne sort de l’organisation à laquelle appartient le jeton. Un outil qui prend un project_id restreint une recherche, il ne l’élargit pas.

Outils
list_issues          incidents groupés, activité la plus récente d’abord
get_issue            un incident et son événement le plus récent
search_logs          les logs d’un projet
list_traces          résumés de traces, une ligne chacun
get_trace            tous les spans d’une trace
service_map          quels services ont appelé lesquels
list_anomalies       écarts de taux par rapport à la ligne de base récente
list_releases        versions déduites des déploiements
deployment_health    la télémétrie de part et d’autre d’un déploiement
update_issue_status  résoudre, ignorer ou rouvrir   (issues:write)

Deux réponses à lire attentivement

Une pile d’appels n’est résolue que si les source maps ont été envoyées pour cette version. get_issue renvoie stack_is_resolved exactement pour cette raison : vérifiez-le avant de vous fier à un fichier et à un numéro de ligne, car une frame non résolue n’est pas fausse — elle parle du bundle plutôt que de la source.

deployment_health peut répondre insufficient_data, et ce n’est pas un satisfecit. Cela signifie qu’il y avait trop peu de télémétrie autour de ce déploiement pour comparer de part et d’autre. Lisez-le comme « inconnu » : vu d’ici, un service silencieux et un service en bonne santé sont identiques.

La service map trace une arête à partir d’un span dont le parent appartient à un autre service. Un projet dont tous les spans nomment un seul service n’a donc aucune arête, et une map vide traduit le plus souvent une instrumentation mono-service plutôt qu’une instrumentation cassée.

← Documentation