Connect a remediation agent to Tocsin24
- MCP protocol, HTTP transport (streamable)
- Claude Code 2 or later
- Updated on 2 November 2026
- 15 minutes
A remediation agent is told about every detection, reads the incident and its fix steps, fixes the shop with its own access, then asks Tocsin24 to check again. The incident closes when Tocsin24 sees compliance restored: never on the agent's word.
On this page
Tocsin24 gives an agent three things: a token that only sees one instance, an MCP server to read what needs fixing and report back, and signed webhooks to be told in real time. This guide connects them in order, then shows the complete loop.
1. Create a token
- In Tocsin24, open the instance, then Settings › Agents.
- In the “New token” block, give a name (“Remediation agent”), a duration (90 days at most) and tick only the permissions needed:
- Read: incidents, hardening, vulnerabilities, probes, inventory, flagged files and pending baseline items;
- Comment: add to an incident’s log what the agent did;
- Take charge: show the team that an agent is handling the incident;
- Request a check: run an incident’s check again after a fix.
- Click “Create the token”, then copy it straight away: it starts with
t24_and will not be shown again. Keep it in the agent’s secret manager, never in a code repository.
2. Connect Claude Code
Give the token to the agent through the TOCSIN24_TOKEN environment variable (secret manager, untracked environment file). Then save this .mcp.json file at the root of the shop’s project; the server address is shown in Settings › Agents (“MCP server address”).
{"mcpServers": {"tocsin24": {"type": "http","url": "https://app.tocsin24.com/api/agents/mcp","headers": { "Authorization": "Bearer ${TOCSIN24_TOKEN}" }}}}
What each line means:
- ${TOCSIN24_TOKEN} Replaced by Claude Code at launch, from the environment variable: the token is never written in clear text in this file (which you can commit), in
~/.claude.jsonor in the terminal history.
In Claude Code, ask for example: “List the open Tocsin24 incidents and suggest a fix for the most serious one”. The agent uses the tools below (their names are in French).
| Tool | Permission | What it does |
|---|---|---|
lister_incidents |
Read | The instance’s incidents, filters: status, level, type, since |
lire_incident |
Read | Full incident: explanation, fix steps, affected items, files, log lines, history |
evenements_depuis |
Read | Events after a cursor (fallback without a webhook) |
etat_durcissement |
Read | Hardening checks and their step-by-step fix |
failles_exposees |
Read | Known vulnerabilities, installed version, expected patch |
etat_sondes |
Read | HTTP probes: availability, response time |
inventaire |
Read | Version, modules or plugins, applied patches |
fichiers_suspects |
Read | Code files flagged by the integrity check |
referentiel |
Read | Accounts, integrations, blocks and files still to approve |
erreurs_magento |
Read | Magento errors (system.log, exception.log) grouped by kind, and latest occurrences with their trace (Magento 2) |
commenter_incident |
Comment | Adds a comment to the incident’s log |
prendre_en_charge |
Take charge | Marks the incident as taken in charge |
demander_verification |
Request a check | Runs the incident’s check again |
Another MCP agent
Any MCP client that speaks the HTTP transport works: the server address above, and an Authorization: Bearer header followed by the token (read from an environment variable) on every request. The server answers in JSON, without a session or cookie, and only knows the token’s instance.
3. Receive events in real time
- In Settings › Agents, under the token, enter the public HTTPS address that will receive events, then “Save”.
- Copy the signing secret (it starts with
t24whsec_): it is shown only once. - Click “Send a test”: the delivery appears in the delivery log with the HTTP code received.
Tocsin24 sends a JSON POST for every incident opened, reopened, escalated or closed, only one per related group (the findings attached to the same change do not each send a delivery). Staging is sent too: the environment field is staging.
{"id": 4182,"type": "incident.opened","created_at": "2026-11-02T10:15:04+00:00","site": { "slug": "ab12cd34ef56", "name": "Shop" },"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"]}
The payload contains no sensitive detail: the agent reads the incident with lire_incident. A 2xx response counts as delivered; otherwise Tocsin24 retries after 30 s, 2 min, 10 min, 30 min then 2 h, and disables the webhook after several abandoned deliveries in a row. Too many events at once pause deliveries for a few minutes: a single storm.started event warns the agent, which then reads evenements_depuis.
4. Check the signature
Each delivery carries four headers: X-Tocsin24-Event (type), X-Tocsin24-Delivery (delivery ID, the same for its retries), X-Tocsin24-Timestamp (Unix timestamp) and X-Tocsin24-Signature, in the form sha256=<hex>: the HMAC-SHA256 of the string <timestamp>.<delivery ID>.<raw body> with the webhook’s secret. As the ID is signed, it cannot be changed to slip a duplicate through. Reject:
- a signature that does not match (constant-time comparison);
- a timestamp more than 5 minutes away from the current time (replay);
- a delivery ID already processed (duplicate retry).
<?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);// Skip a delivery already processed: X-Tocsin24-Delivery is the same for every retry.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. The detect, fix, verify loop
- Detect: the webhook receives
incident.opened(or the agent readsevenements_depuiswith its last cursor). - Read: the agent calls
lire_incidentwith the ID received, thenprendre_en_chargeso the team knows it is on it. - Fix: it follows the fix steps (for example, block
/.git/in the web server configuration) with its own access to the shop, and checks for itself with the command given in the incident. - Report:
commenter_incidentsays what was changed, without ever copying a secret. - Verify:
demander_verificationruns the check again (the hardening “Check now”, or an on-demand reading of the inventory, the code or the application state), with the same limits as a person. - Close: a few minutes later, Tocsin24 sees compliance restored and sends
incident.closed. If the incident stays open, the agent reads it again and starts over, or hands over to the team.
Frequently asked questions
Can the agent mark an incident "Legitimate" or "Ignored"?
No. These are human decisions: a compromised agent could otherwise silence an attack. The agent comments, takes charge and requests a check; the incident closes when Tocsin24 sees compliance restored, or by a decision of your team.
The server returns 401
The token is missing, mistyped, revoked or expired. Create a new one in Settings › Agents: a token is shown only once.
The server returns 403 "subscription_required" or "creator_access_revoked"
The instance is no longer subscribed (or is in its trial period), or the person who created the token no longer administers the instance. In the second case, a current administrator creates a new token.
The server returns 429
The token's request limit is reached: the Retry-After header gives the delay in seconds. Prefer webhooks to repeatedly polling evenements_depuis.
My webhook no longer receives anything
After several failed deliveries in a row, Tocsin24 disables it. Fix the service, then save the address again in Settings › Agents: the webhook is re-enabled. The delivery log shows the HTTP code of each attempt.
Why is my webhook address refused?
It must start with https://, without a user name or password, and its name must resolve to a public address: private, internal or local networks are refused, when saving and on every delivery.
Need help?
Write to us