Hermes Agent comme gateway : Executor et MCP self-hosted
/ 6 min de lecture
Table des matières
Un agent IA ne se résume pas à un modèle qui reçoit un prompt et renvoie du texte. Dès qu’il doit rester disponible, répondre depuis une messagerie, accéder à des outils et conserver un environnement d’exécution, il devient un système distribué.
Dans mon infrastructure, Hermes Agent joue le rôle de gateway et d’orchestrateur. Il reçoit les messages Discord, construit les conversations et appelle un modèle compatible OpenAI. Les capacités externes ne sont pas ajoutées directement à Hermes : elles passent par Executor, une couche d’intégration auto-hébergée qui expose un endpoint MCP.
Cette séparation est le point important de l’architecture. Hermes raisonne et dialogue ; Executor centralise l’accès aux outils ; les serveurs MCP fournissent des capacités spécialisées. Le tout tourne dans une stack Docker, avec des services isolés des accès extérieurs directs.
Les trois couches du système
flowchart LR
User["Utilisateur Discord"] -->|message| Hermes["Hermes Agent\ngateway run"]
Hermes -->|appel du modèle| Models["Modèle IA"]
Hermes -->|MCP HTTP + OAuth| Executor["Executor\nMCP toolkit Hermes"]
Executor --> GTFS["GTFS-MCP"]
Executor --> Moodle["Moodle-MCP"]
Executor --> Storage["Executor /data\nvolume persistant"]
Hermes : la couche agent
Hermes est déployé avec l’image nousresearch/hermes-agent:latest. Le conteneur démarre avec gateway run, et non comme une simple session interactive. Cette différence est fondamentale : le processus reste actif, écoute les événements Discord et maintient les sessions de conversation.
Sa configuration est montée depuis config/hermes/config.yaml dans /opt/data/config.yaml. Elle décrit notamment :
- le fournisseur de modèle ;
- le répertoire de travail
/workspace; - l’interface Discord et ses règles d’autorisation ;
- le serveur MCP distant auquel Hermes doit se connecter.
Le gateway Discord est volontairement restreint. La configuration autorise un utilisateur et un canal précis, désactive les mentions générales et n’exige pas de mentionner le bot dans ce canal. Ce sont des choix de routage et de confiance, pas des propriétés intrinsèques du modèle.
Le modèle : une dépendance séparée
Hermes n’héberge pas le modèle. La configuration pointe vers :
model: provider: custom default: gemini-pro-agent base_url: https://<cliproxyapi host>/v1 api_key: not-needed api_mode: chat_completionsLe service cli-proxy-api tourne lui aussi dans Docker, avec une configuration versionnée séparée. Il sert de façade compatible avec plusieurs fournisseurs et évite de coupler Hermes à une implémentation particulière de modèle.
Executor : le plan d’intégration
Executor est déployé avec ghcr.io/rhyssullivan/executor-selfhost:latest. Il centralise les intégrations et expose une surface MCP consommable par Hermes.
Son état est conservé dans le volume Docker executor, monté sur /data. La persistance est importante : les intégrations, la configuration et l’état du service ne doivent pas disparaître à chaque recréation du conteneur.
Hermes ne référence pas l’interface générale d’Executor, mais un toolkit MCP dédié :
mcp_servers: executor: url: https://<executor-host>/mcp/toolkits/hermes auth: oauthLe nom executor devient donc une frontière de capacités dans Hermes. L’agent ne connaît pas nécessairement l’implémentation de chaque outil en aval ; il découvre une surface MCP publiée par Executor.
MCP comme frontière de capacités
Le Model Context Protocol standardise la façon dont un client découvre et appelle des outils externes. Dans ce setup, Hermes est le client MCP et Executor est le serveur MCP visible par Hermes.
Hermes distingue les serveurs locaux et les serveurs MCP distants. Mon intégration Executor utilise un endpoint distant authentifié avec auth: oauth.
Cette organisation apporte une séparation utile :
- Hermes conserve la logique de conversation et de décision.
- Executor présente une surface d’outils cohérente à l’agent.
- Les serveurs spécialisés peuvent rester des services indépendants.
- Les identifiants et politiques d’intégration peuvent être centralisés dans Executor.
La configuration Hermes ne déclare explicitement qu’Executor. C’est donc Executor qui présente à Hermes la liste unifiée des intégrations et des outils disponibles.
Les MCP exposés à Hermes
Voici les intégrations actuellement exposées par le toolkit Hermes d’Executor :
| Intégration | Identifiant Executor | Rôle dans le setup |
|---|---|---|
| GTFS | gtfs |
Itinéraires et horaires de transports en commun. |
| Moodle | moodle |
Accès à l’espace d’apprentissage Moodle. |
| Dockhand | dockhand_api |
Gestion et orchestration de la stack Docker du VPS. |
| Cloudflare | cloudflare_mcp |
Gestion des services réseau et des règles de sécurité Cloudflare. |
| Pocket ID | pocket_id_api |
Interaction avec le fournisseur d’identité OIDC/SSO. |
| GitHub | github_graphql |
Consultation et gestion des dépôts, issues et pull requests. |
| Pelican Application / Admin | pelican_api_application |
Administration du panel Pelican et de ses nodes. |
| Pelican Client | pelican_api_client |
Contrôle des serveurs hébergés par Pelican. |
| Spotify | spotify |
Lecture en cours, recherche et gestion des playlists. |
| Firecrawl | firecrawl_mcp |
Scraping, extraction de contenu et crawl de sites. |
| GrepApp | grep_mcp |
Recherche de code dans les dépôts publics. |
| Excalidraw | excalidraw_app_demo |
Création de schémas, maquettes et tableaux blancs. |
| Context7 | context7_mcp |
Recherche de contexte et de documentation pour les outils utilisés. |
Cette liste donne une image plus juste de ce que signifie « donner des outils à Hermes ». L’agent ne reçoit pas seulement un accès à un outil unique : il dispose d’un catalogue transversal couvrant la vie quotidienne, l’infrastructure, le développement, la documentation et la création de schémas.
La séparation reste nette : Hermes choisit quand utiliser un outil et présente le résultat dans la conversation ; Executor porte les intégrations et les autorisations nécessaires ; chaque service conserve sa logique métier.
Isolation et sécurité
Les composants sont isolés des accès extérieurs directs. Les services internes ne sont pas exposés comme des ports publics ; lorsqu’un accès externe est nécessaire, il passe par les mécanismes de contrôle et d’authentification prévus par l’infrastructure.
Cette séparation limite la surface d’attaque et évite que chaque serveur MCP doive devenir lui-même une application publique. Hermes ne voit que les outils qu’Executor lui expose, tandis que les services spécialisés restent derrière cette frontière.
Le chemin d’une requête
Une interaction typique suit cette chaîne conceptuelle :
- Un message arrive dans le canal Discord autorisé.
- Le gateway Hermes vérifie l’utilisateur et le canal.
- Hermes restaure la session correspondante et prépare le contexte.
- Le modèle analyse la demande et peut choisir un outil.
- Hermes envoie alors l’appel à la surface MCP Executor.
- Executor applique sa logique d’intégration et transmet éventuellement l’appel à un serveur spécialisé.
- Le résultat revient dans la boucle Hermes, qui peut poursuivre son raisonnement.
- La réponse finale est envoyée à Discord.
Le modèle ne devient donc pas directement un administrateur du VPS. Il opère dans un ensemble de surfaces d’outils exposées par Hermes et Executor. La qualité du système dépend autant de cette sélection de capacités que du modèle lui-même.
Ce que cette architecture rend possible
Le bénéfice principal est le découplage. Un nouvel outil peut être ajouté en aval sans transformer Hermes en monolithe. Un autre client MCP pourrait également consommer Executor, tandis que Hermes reste le point d’accès conversationnel orienté Discord.
La centralisation crée aussi un endroit naturel pour traiter les intégrations, leurs secrets et leur politique d’exposition. À l’inverse, elle ajoute une dépendance supplémentaire : si Executor est indisponible, les outils qu’il publie le sont également, même si Hermes et le modèle fonctionnent encore.
Enfin, l’usage d’images latest rend le déploiement simple mais moins reproductible. Pour documenter ou reproduire exactement cette installation, il faudrait conserver les versions ou digests des images utilisées, ainsi que la version d’Hermes et les versions des serveurs MCP. Le fichier actuel décrit donc une architecture opérationnelle, pas un lockfile complet de l’infrastructure.
En résumé
Hermes Agent est ici la couche d’interaction et d’orchestration : il reçoit les messages Discord, gère les sessions et pilote le modèle. Executor est la passerelle MCP qui expose à Hermes une surface d’outils centralisée. GTFS-MCP et Moodle-MCP sont les serveurs MCP spécialisés déployés en complément.
La valeur du setup ne vient pas d’un composant unique, mais des frontières entre eux. L’agent peut raisonner sans connaître chaque intégration ; les outils peuvent évoluer sans réécrire le gateway ; et l’infrastructure conserve le contrôle de la persistance et de l’exposition.