Brancher un agent de correction sur Tocsin24
- Protocole MCP, transport HTTP (streamable)
- Claude Code 2 et plus récent
- Mis à jour le 2 novembre 2026
- 15 minutes
Un agent de correction est prévenu de chaque détection, lit la fiche de l’incident et sa marche à suivre, corrige la boutique avec ses propres accès, puis demande à Tocsin24 de revérifier. L’incident se ferme quand Tocsin24 constate le retour à la conformité : jamais sur la parole de l’agent.
Sur cette page
Tocsin24 donne à un agent trois choses : un jeton qui ne voit qu’une instance, un serveur MCP pour lire ce qu’il faut corriger et rendre compte, et des webhooks signés pour être prévenu en temps réel. Ce guide les branche dans l’ordre, puis montre la boucle complète.
1. Créer un jeton
- Dans Tocsin24, ouvrez l’instance, puis Réglages › Agents.
- Bloc « Nouveau jeton » : donnez un nom (« Agent de correction »), une durée (90 jours au plus) et cochez seulement les droits utiles :
- Lecture : incidents, durcissement, failles, sondes, inventaire, fichiers signalés et référentiel en attente ;
- Commenter : ajouter au journal d’un incident ce que l’agent a fait ;
- Prendre en charge : montrer à l’équipe qu’un agent s’occupe de l’incident ;
- Demander une vérification : relancer le contrôle d’un incident après une correction.
- Cliquez sur « Créer le jeton », puis copiez-le aussitôt : il commence par
t24_et ne sera plus affiché. Rangez-le dans le gestionnaire de secrets de l’agent, jamais dans un dépôt de code.
2. Brancher Claude Code
Donnez le jeton à l’agent par la variable d’environnement TOCSIN24_TOKEN (gestionnaire de secrets, fichier d’environnement non versionné). Enregistrez ensuite ce fichier .mcp.json à la racine du projet de la boutique ; l’adresse du serveur est affichée dans Réglages › Agents (« Adresse du serveur MCP »).
{"mcpServers": {"tocsin24": {"type": "http","url": "https://app.tocsin24.com/api/agents/mcp","headers": { "Authorization": "Bearer ${TOCSIN24_TOKEN}" }}}}
Ce que veut dire chaque ligne :
- ${TOCSIN24_TOKEN} Remplacé par Claude Code au lancement, à partir de la variable d’environnement : le jeton n’est écrit en clair ni dans ce fichier (que vous pouvez versionner), ni dans
~/.claude.json, ni dans l’historique du terminal.
Dans Claude Code, demandez par exemple : « Liste les incidents ouverts de Tocsin24 et propose une correction pour le plus grave ». L’agent utilise les outils ci-dessous.
| Outil | Droit | Ce qu’il fait |
|---|---|---|
lister_incidents |
Lecture | Incidents de l’instance, filtres : statut, niveau, type, depuis |
lire_incident |
Lecture | Fiche complète : explication, marche à suivre, éléments concernés, fichiers, lignes de log, journal |
evenements_depuis |
Lecture | Événements après un curseur (repli sans webhook) |
etat_durcissement |
Lecture | Contrôles de durcissement et leur marche à suivre pas à pas |
failles_exposees |
Lecture | Failles connues, version installée, correctif attendu |
etat_sondes |
Lecture | Sondes HTTP : disponibilité, temps de réponse |
inventaire |
Lecture | Version, modules ou extensions, correctifs appliqués |
fichiers_suspects |
Lecture | Fichiers de code signalés par le contrôle d’intégrité |
referentiel |
Lecture | Comptes, intégrations, blocs et fichiers encore à valider |
erreurs_magento |
Lecture | Erreurs Magento (system.log, exception.log) par famille, et dernières occurrences avec leur trace (Magento 2) |
commenter_incident |
Commenter | Ajoute un commentaire au journal de l’incident |
prendre_en_charge |
Prendre en charge | Marque l’incident comme pris en charge |
demander_verification |
Demander une vérification | Relance le contrôle de l’incident |
Un autre agent MCP
Tout client MCP qui parle le transport HTTP convient : adresse du serveur ci-dessus, en-tête Authorization: Bearer suivi du jeton (lu dans une variable d’environnement) sur chaque requête. Le serveur répond en JSON, sans session ni cookie, et ne connaît que l’instance du jeton.
3. Recevoir les événements en temps réel
- Dans Réglages › Agents, sous le jeton, saisissez l’adresse HTTPS publique qui recevra les événements, puis « Enregistrer ».
- Copiez le secret de signature (il commence par
t24whsec_) : il n’est montré qu’une fois. - Cliquez sur « Envoyer un test » : l’envoi apparaît dans le journal des envois avec le code HTTP reçu.
Tocsin24 envoie un POST JSON pour chaque incident ouvert, rouvert, plus grave ou clos, un seul par affaire (les constats rattachés à une même modification ne produisent pas d’envoi chacun). La préproduction est envoyée aussi : le champ environment vaut staging.
{"id": 4182,"type": "incident.opened","created_at": "2026-11-02T10:15:04+00:00","site": { "slug": "ab12cd34ef56", "name": "Boutique" },"environment": "production","incident": {"id": 1203, "type": "exposed_file", "severity": "critical", "level": "critical", "status": "open","title": "Fichier exposé sur le web : /.git/config","first_detected_at": "2026-11-02T10:14:58+00:00", "last_detected_at": "2026-11-02T10:14:58+00:00","url": "https://app.tocsin24.com/sites/ab12cd34ef56/incidents/1203"},"untrusted_fields": ["incident.title"]}
La charge utile ne contient aucun détail sensible : l’agent lit la fiche par lire_incident. Une réponse 2xx vaut livraison ; sinon Tocsin24 réessaie après 30 s, 2 min, 10 min, 30 min puis 2 h, et désactive le webhook après plusieurs envois abandonnés de suite. Trop d’événements d’un coup suspendent les envois quelques minutes : un seul événement storm.started prévient l’agent, qui lit alors evenements_depuis.
4. Vérifier la signature
Chaque envoi porte quatre en-têtes : X-Tocsin24-Event (type), X-Tocsin24-Delivery (identifiant de l’envoi, le même pour ses nouveaux essais), X-Tocsin24-Timestamp (horodatage Unix) et X-Tocsin24-Signature, de la forme sha256=<hex> : le HMAC-SHA256 de la chaîne <horodatage>.<identifiant de l'envoi>.<corps brut> avec le secret du webhook. L’identifiant étant signé, il ne peut pas être changé pour faire passer un doublon. Refusez :
- une signature qui ne correspond pas (comparaison à temps constant) ;
- un horodatage à plus de 5 minutes de l’heure courante (rejeu) ;
- un identifiant d’envoi déjà traité (doublon d’un nouvel essai).
<?php$secret = getenv('TOCSIN24_WEBHOOK_SECRET');$body = file_get_contents('php://input');$timestamp = $_SERVER['HTTP_X_TOCSIN24_TIMESTAMP'] ?? '';$delivery = $_SERVER['HTTP_X_TOCSIN24_DELIVERY'] ?? '';$signature = $_SERVER['HTTP_X_TOCSIN24_SIGNATURE'] ?? '';$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $delivery . '.' . $body, $secret);if (! ctype_digit($timestamp) || ! ctype_digit($delivery) || abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $signature)) {http_response_code(401);exit;}$event = json_decode($body, true);// Ignorer un envoi déjà traité : X-Tocsin24-Delivery est le même pour chaque nouvel essai.http_response_code(204);
import { createHmac, timingSafeEqual } from 'node:crypto';import { createServer } from 'node:http';const secret = process.env.TOCSIN24_WEBHOOK_SECRET;createServer((req, res) => {const chunks = [];req.on('data', (c) => chunks.push(c));req.on('end', () => {const body = Buffer.concat(chunks).toString('utf8');const timestamp = req.headers['x-tocsin24-timestamp'] ?? '';const delivery = req.headers['x-tocsin24-delivery'] ?? '';const signature = Buffer.from(req.headers['x-tocsin24-signature'] ?? '');const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(`${timestamp}.${delivery}.${body}`).digest('hex'));const fresh = /^\d+$/.test(timestamp) && /^\d+$/.test(delivery) && Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;if (!fresh || signature.length !== expected.length || !timingSafeEqual(signature, expected)) {res.writeHead(401).end();return;}const event = JSON.parse(body);res.writeHead(204).end();});}).listen(8080);
5. La boucle détection, correction, vérification
- Détection : le webhook reçoit
incident.opened(ou l’agent litevenements_depuisavec son dernier curseur). - Lecture : l’agent appelle
lire_incidentavec l’identifiant reçu, puisprendre_en_chargepour que l’équipe sache qu’il s’en occupe. - Correction : il suit la marche à suivre (par exemple bloquer
/.git/dans la configuration du serveur web) avec ses propres accès à la boutique, et vérifie lui-même avec la commande donnée dans la fiche. - Compte rendu :
commenter_incidentdit ce qui a été changé, sans jamais recopier de secret. - Vérification :
demander_verificationrelance le contrôle (« Vérifier » du durcissement, ou relevé à la demande de l’inventaire, du code ou de l’état de l’application), avec les mêmes limites qu’une personne. - Fermeture : quelques minutes plus tard, Tocsin24 constate le retour à la conformité et envoie
incident.closed. Si l’incident reste ouvert, l’agent relit la fiche et recommence, ou passe la main à l’équipe.
Questions fréquentes
L’agent peut-il classer un incident « Légitime » ou « Ignoré » ?
Non. Ce sont des décisions humaines : un agent compromis pourrait sinon faire taire une attaque. L’agent commente, prend en charge et demande une vérification ; l’incident se ferme quand Tocsin24 constate le retour à la conformité, ou par une décision de votre équipe.
Le serveur répond 401
Le jeton est absent, mal recopié, retiré ou expiré. Créez-en un nouveau dans Réglages › Agents : un jeton n’est montré qu’une fois.
Le serveur répond 403 « subscription_required » ou « creator_access_revoked »
L’instance n’est plus abonnée (ou est en période d’essai), ou la personne qui a créé le jeton n’administre plus l’instance. Dans le second cas, un administrateur actuel crée un nouveau jeton.
Le serveur répond 429
La limite de requêtes du jeton est atteinte : l’en-tête Retry-After donne le délai en secondes. Préférez les webhooks au sondage répété de evenements_depuis.
Mon webhook ne reçoit plus rien
Après plusieurs envois en échec de suite, Tocsin24 le désactive. Corrigez le service, puis enregistrez de nouveau l’adresse dans Réglages › Agents : le webhook est réactivé. Le journal des envois montre le code HTTP de chaque essai.
Pourquoi mon adresse de webhook est-elle refusée ?
Elle doit commencer par https://, sans identifiant ni mot de passe, et son nom doit se résoudre vers une adresse publique : les réseaux privés, internes ou locaux sont refusés, à l’enregistrement comme à chaque envoi.
Besoin d’aide ?
Nous écrire