Aller au contenu

Hermes : les 32 outils MCP

Un agent sans outils ne peut que parler. Ce qui rend Hermes utile, c’est le catalogue de 32 outils métier qu’il peut appeler pour lire et modifier l’état réel du système : projets Odoo, conteneurs Docker, métriques Prometheus, notes du vault Obsidian.

Ces outils ne vivent pas dans le conteneur de l’agent. Ils sont définis dans un workflow N8N (Hermes MCP Tools, 33 nodes, actif) qui les expose via un unique MCP Server Trigger protégé par Bearer. Le conteneur ne connaît qu’une URL et un token.

CanalCibleOutilsUsage
n8n-toolsn8n:5678/mcp/hermes-tools32 outils métier curésLe flow normal, 99 % des appels
n8n-adminn8n-mcp:3000/mcp4 outils, filtrés sur 24 exposésDiagnostic de workflows uniquement

Cibles

N8N · Hermes MCP Tools · 33 nodes

Bearer · flow normal

Bearer · debug seul

Hermes · gateway

MCP Server Trigger · Bearer

23 nodes odooTool natifs

4 sous-workflows gateway · entrées typées

Odoo · XML-RPC

Docker Actions · SSH

Prometheus · SSH + curl

vps-vault · SSH + git

Telegram Content Pipeline

n8n-mcp · 4 outils diagnostic


Pourquoi des outils curés plutôt qu’un accès direct ?

Section intitulée « Pourquoi des outils curés plutôt qu’un accès direct ? »

Il aurait été plus rapide de donner à l’agent un accès générique à l’API Odoo et de le laisser composer ses appels XML-RPC. Trois raisons de ne pas le faire.

EnjeuCe qu’apporte un outil dédié
SurfaceUn outil ne fait qu’une chose. odoo_update_task ne peut pas supprimer un projet, quelle que soit la créativité du modèle
SchémaChaque paramètre a un nom, un type et une description. Le modèle n’a pas à deviner la forme d’un domaine Odoo
Point de contrôleUn node N8N entre l’agent et la cible permet de valider, plafonner, échapper et journaliser avant exécution

Le coût est réel — chaque nouvel outil est un node à créer — mais il se paie une fois, et il rend le comportement de l’agent prévisible.

Les outils non-Odoo ne pointent jamais directement sur les workflows existants. Chaque domaine passe par un wrapper qui définit ses propres entrées, puis délègue.

Sans wrapper, l’agent devrait connaître le contrat interne de Docker Actions ou du Telegram Content Pipeline — des workflows conçus pour d’autres appelants, dont la forme peut changer. Le wrapper découple : il donne à l’agent un schéma MCP propre et stable, et absorbe les évolutions internes.


Odoo — projets et tâches (10)

OutilRôle
odoo_list_projectsListe id + nom des projets
odoo_create_projectCrée un projet (l’ORM crée le compte analytique associé)
odoo_update_projectMet à jour un champ (nom / description)
odoo_archive_projectArchive ou désarchive
odoo_list_task_stagesÉtapes kanban d’un projet (id, nom, séquence, repliée)
odoo_move_task_stageDéplace une tâche dans le kanban
odoo_list_tasksTâches d’un projet
odoo_get_taskDétail d’une tâche, description incluse
odoo_create_taskCrée une tâche
odoo_update_taskMet à jour un champ (nom / description / échéance)

Odoo — contacts (3) : odoo_search_contacts (recherche par nom, retourne coordonnées et adresse), odoo_create_contact, odoo_update_contact.

Odoo — CRM (6) : crm_list_stages (étapes du pipeline avec séquence et is_won), crm_list_leads, crm_create_lead (type=opportunity forcé pour que le lead atterrisse dans le pipeline), crm_update_lead, crm_move_stage, crm_delete_leadsensible.

Odoo — timesheets (4) : timesheet_report (lignes depuis une date), timesheet_log_hours, timesheet_update, timesheet_deletesensible.

Vault Obsidian (4) : vault_search (grep insensible à la casse, 3 correspondances par fichier, plafond 60 lignes), vault_list (fichiers suivis, plafond 300), vault_read (plafond 30 000 caractères, retourne un contentHash), vault_write (écriture confinée).

Infrastructure (5) : docker_read (status / logs / liste), docker_manage (start / stop / restart / update — sensible), monitoring_alerts, monitoring_query (PromQL instantané), content_generate (brouillon de note, article ou recherche).

GatewayEntréesDélègue à
DockerdockerStack, dockerActionDocker Actions
Monitoringmode (alerts / query), promqlSSH local → curl Prometheus 127.0.0.1:9090
ContentcontentType, text, urlTelegram Content Pipeline
VaultvaultAction, vaultQuery, vaultContent, vaultBaseHashSSH local → git + grep sur ~/vaults/vps-vault

Prometheus n’écoute que sur le loopback du host : le gateway monitoring passe donc par SSH puis curl, comme le health check Docker. Le PromQL est échappé avant insertion dans la commande.

vault_write est le seul outil qui modifie durablement quelque chose hors d’Odoo. Sa validation se fait en JavaScript avant construction de la commande shell : liste blanche de préfixes (research/, inbox/), extension .md obligatoire, anti-traversal, contrôle des caractères, plafond de 150 000 octets — comptés en octets, pas en caractères.

Le point intéressant est le read-before-overwrite, sans état partagé : vault_read renvoie un contentHash (sha256 tronqué à 12 hexadécimaux), et écraser un fichier existant exige de repasser ce hash en Base_Hash. Sans hash, la réponse est __EXISTS__ ; si le fichier a changé depuis la lecture, __STALE_READ__.

Les gateways ne lèvent pas d’exception sur une entrée invalide : ils renvoient un marqueur que le formateur traduit en {success: false, error, hint}. __NOT_FOUND__, __BAD_PATH__, __BAD_ACTION__, __EMPTY_QUERY__, __EXISTS__, __STALE_READ__.

L’effet de bord est important : ces réponses ne déclenchent pas le Global Error Handler. Une faute de frappe de l’agent est une réponse métier, pas un incident d’infrastructure — elle repart directement dans la conversation avec un indice sur la correction à apporter.

SurfaceProtection
Endpoint MCPBearer obligatoire — 403 sans token, vérifié en E2E
Depuis Internet/mcp/* et /mcp-test/* renvoient 404 côté Caddy ; seul n8n:5678 en interne fonctionne
docker_manageWhitelist d’actions dans Docker Actions ; security-stack non actionnable
Actions destructricesdocker_manage, crm_delete_lead, timesheet_delete exigent une confirmation explicite, imposée par le system prompt
Écriture vaultPréfixes en liste blanche, anti-traversal, read-before-overwrite

LimiteImpactMitigation
employee_id figé à 1timesheet_log_hours écrit toujours sur le même employéSans objet aujourd’hui, à paramétrer si l’équipe grandit
Redémarrage après chaque évolutionToute modification de schéma impose un restartRegrouper les changements d’outils
Pas d’approbation en avalLes actions sensibles ne sont protégées que par le promptWhitelist côté Docker Actions ; chaîne d’approbation à câbler
Aucun sous-node désactivableDésactiver un outil casse le routage de tous les suivantsSupprimer le node plutôt que le désactiver (voir le quatrième piège)

Si les actions sensibles doivent être vraiment bloquantes :

  • Réutiliser le MCP Confirmation Handler déjà en place pour CLI Ollama plutôt que d’en écrire un second.
  • Le gateway posterait un webhook et attendrait le callback Telegram, comme le fait déjà cli-ollama.

Si le catalogue continue de grossir :

  • 32 outils tiennent encore dans un prompt, mais chaque outil coûte des tokens à chaque tour.
  • Piste : des toolsets activables par contexte, sur le modèle du /mcp par conversation du système conversationnel.

Si un outil doit écrire ailleurs que dans le vault :

  • Le patron vault_write est réutilisable tel quel : liste blanche de préfixes, validation avant construction de commande, read-before-overwrite par hash.
  • La partie coûteuse — le transfert chunké et la vérification d’intégrité — est déjà écrite.
Fenêtre de terminal
# Le catalogue vu par l'agent
docker exec hermes hermes mcp test n8n-tools
# Tester l'endpoint directement (403 attendu sans token)
docker exec n8n sh -c 'curl -s -o /dev/null -w "%{http_code}\n" -X POST \
http://n8n:5678/mcp/hermes-tools'
# Vérifier que l'endpoint reste fermé depuis l'extérieur (404 attendu)
curl -so /dev/null -w '%{http_code}\n' https://n8n.guigpap.com/mcp/hermes-tools

  • Hermes Agent — Le déploiement et son modèle de sécurité
  • Skills — Les procédures qui exploitent ces outils
  • Mémoire Mnemosyne — Les outils de mémoire, côté conteneur