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

  1. Dans Tocsin24, ouvrez l’instance, puis Réglages › Agents.
  2. 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.
  3. 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 »).

Contenu du fichier .mcp.json
  1. {
  2. "mcpServers": {
  3. "tocsin24": {
  4. "type": "http",
  5. "url": "https://app.tocsin24.com/api/agents/mcp",
  6. "headers": { "Authorization": "Bearer ${TOCSIN24_TOKEN}" }
  7. }
  8. }
  9. }

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.
Terminal, dans le projet de la boutique
Vérifie la connexion (Claude Code demande d'approuver le serveur du projet au premier lancement) claude mcp list

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

  1. Dans Réglages › Agents, sous le jeton, saisissez l’adresse HTTPS publique qui recevra les événements, puis « Enregistrer ».
  2. Copiez le secret de signature (il commence par t24whsec_) : il n’est montré qu’une fois.
  3. 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.

Contenu du fichier Exemple d'envoi (corps JSON)
  1. {
  2. "id": 4182,
  3. "type": "incident.opened",
  4. "created_at": "2026-11-02T10:15:04+00:00",
  5. "site": { "slug": "ab12cd34ef56", "name": "Boutique" },
  6. "environment": "production",
  7. "incident": {
  8. "id": 1203, "type": "exposed_file", "severity": "critical", "level": "critical", "status": "open",
  9. "title": "Fichier exposé sur le web : /.git/config",
  10. "first_detected_at": "2026-11-02T10:14:58+00:00", "last_detected_at": "2026-11-02T10:14:58+00:00",
  11. "url": "https://app.tocsin24.com/sites/ab12cd34ef56/incidents/1203"
  12. },
  13. "untrusted_fields": ["incident.title"]
  14. }

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).
Contenu du fichier webhook.php (PHP)
  1. <?php
  2. $secret = getenv('TOCSIN24_WEBHOOK_SECRET');
  3. $body = file_get_contents('php://input');
  4. $timestamp = $_SERVER['HTTP_X_TOCSIN24_TIMESTAMP'] ?? '';
  5. $delivery = $_SERVER['HTTP_X_TOCSIN24_DELIVERY'] ?? '';
  6. $signature = $_SERVER['HTTP_X_TOCSIN24_SIGNATURE'] ?? '';
  7. $expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $delivery . '.' . $body, $secret);
  8. if (! ctype_digit($timestamp) || ! ctype_digit($delivery) || abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $signature)) {
  9. http_response_code(401);
  10. exit;
  11. }
  12. $event = json_decode($body, true);
  13. // Ignorer un envoi déjà traité : X-Tocsin24-Delivery est le même pour chaque nouvel essai.
  14. http_response_code(204);
Contenu du fichier webhook.mjs (Node.js)
  1. import { createHmac, timingSafeEqual } from 'node:crypto';
  2. import { createServer } from 'node:http';
  3. const secret = process.env.TOCSIN24_WEBHOOK_SECRET;
  4. createServer((req, res) => {
  5. const chunks = [];
  6. req.on('data', (c) => chunks.push(c));
  7. req.on('end', () => {
  8. const body = Buffer.concat(chunks).toString('utf8');
  9. const timestamp = req.headers['x-tocsin24-timestamp'] ?? '';
  10. const delivery = req.headers['x-tocsin24-delivery'] ?? '';
  11. const signature = Buffer.from(req.headers['x-tocsin24-signature'] ?? '');
  12. const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(`${timestamp}.${delivery}.${body}`).digest('hex'));
  13. const fresh = /^\d+$/.test(timestamp) && /^\d+$/.test(delivery) && Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
  14. if (!fresh || signature.length !== expected.length || !timingSafeEqual(signature, expected)) {
  15. res.writeHead(401).end();
  16. return;
  17. }
  18. const event = JSON.parse(body);
  19. res.writeHead(204).end();
  20. });
  21. }).listen(8080);

5. La boucle détection, correction, vérification

  1. Détection : le webhook reçoit incident.opened (ou l’agent lit evenements_depuis avec son dernier curseur).
  2. Lecture : l’agent appelle lire_incident avec l’identifiant reçu, puis prendre_en_charge pour que l’équipe sache qu’il s’en occupe.
  3. 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.
  4. Compte rendu : commenter_incident dit ce qui a été changé, sans jamais recopier de secret.
  5. Vérification : demander_verification relance 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.
  6. 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