refactor(infra): MCP n8n natif, retrait du conteneur dédié (v0.15.0)

n8n ≥ 2.18.4 sert son propre MCP : suppression du service mcp-n8n,
MCP_N8N_URL pointe vers l'endpoint natif de l'instance (auth MCP Access
Token Bearer). Portainer reste un sidecar officiel. Aucun changement de
code (registry HTTP+Bearer inchangé). Docs + .env alignés, compose
revalidé.

Palier de risque : n/a (infra + config).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kantin-Petit
2026-06-23 01:40:49 +02:00
parent 52980837a9
commit ceddb86198
6 changed files with 29 additions and 26 deletions
+6 -5
View File
@@ -9,11 +9,12 @@ OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_API_KEY= # SECRET — clé API Ollama cloud
OLLAMA_MODEL=qwen3:cloud # modèle cloud (suffixe :cloud), tool-calling
# ── MCP n8n (czlonkowski/n8n-mcp) ──────────────────────────────────────
N8N_API_URL=http://n8n:5678 # interne uniquement
N8N_API_KEY= # SECRET — token n8n à portée RESTREINTE
MCP_N8N_URL=http://mcp-n8n:3000 # endpoint du serveur MCP n8n (interne)
MCP_N8N_AUTH_TOKEN= # SECRET — auth du serveur MCP n8n
# ── MCP n8n : NATIF (instance n8n ≥ 2.18.4) ────────────────────────────
# Pas de conteneur dédié : n8n sert son propre MCP. Activer côté instance
# (env d'instance + activation par workflow), puis copier l'URL + le token
# depuis n8n → Connection details. URL = endpoint MCP de l'instance (interne).
MCP_N8N_URL=http://n8n:5678/mcp # à confirmer dans Connection details de n8n
MCP_N8N_AUTH_TOKEN= # SECRET — "MCP Access Token" n8n (Bearer)
# ── MCP Portainer (portainer/portainer-mcp) ────────────────────────────
PORTAINER_URL=https://portainer:9443 # interne uniquement
+9
View File
@@ -6,6 +6,15 @@ incompatibles. Chaque ligne renvoie à un commit dédié (un artefact = un commi
## [Unreleased]
## [0.15.0] — 2026-06-23
### Changed
- MCP n8n = **natif** (instance n8n ≥ 2.18.4) au lieu d'un conteneur dédié :
suppression du service `mcp-n8n` du compose ; `MCP_N8N_URL` pointe vers
l'endpoint MCP de l'instance n8n, auth par "MCP Access Token" (Bearer).
MCP Portainer reste un sidecar officiel. Aucun changement de code (le registry
parle déjà HTTP+Bearer). Docs (CLAUDE.md, architecture, networks) + `.env.example`
mis à jour. Compose revalidé (services : ollama, socket-proxy, mcp-portainer, backend).
## [0.14.0] — 2026-06-23 — fin Phase 2 (écriture + need-review)
### Added
- `docs/need-review.md` : documentation complète du cycle (états, sursis,
+3 -2
View File
@@ -37,8 +37,9 @@ existant. Le cerveau est un LLM en boucle tool-calling :
- Backend/API : **Fastify**.
- LLM : client Ollama `/api/chat` (tool-calling natif), modèles `:cloud`.
- Surface texte Phase 1 : **bot Telegram** (long-polling → zéro port ouvert).
- MCP : conteneurs `portainer/portainer-mcp` + `czlonkowski/n8n-mcp`, tags
épinglés, **read-only en Phase 1**.
- MCP : **n8n natif** (instance ≥ 2.18.4, pas de conteneur — endpoint MCP servi
par n8n, à activer) + **Portainer sidecar** `portainer/portainer-mcp` (tag
épinglé). **Read-only en Phase 1.**
- Tests : **Vitest** (gatekeeper + scoping read-only).
- État assets : **SQLite** (table posée dès P0/P1, câblée en P2+).
+4 -4
View File
@@ -21,8 +21,8 @@ d'un homelab Debian + Docker + Traefik existant.
│ - audit log │ └───────────┘
└─────────────────────────┘
│ MCP (stdio/http interne)
├───────────────► MCP n8n ──► n8n API (interne)
└───────────────► MCP Portainer ─► socket-proxy ─► Docker / Portainer
├───────────────► MCP n8n natif (endpoint sur l'instance n8n, interne)
└───────────────► MCP Portainer (sidecar) ─► socket-proxy ─► Docker / Portainer
```
## Invariants
@@ -54,6 +54,6 @@ sont exposés : aucun risque d'écriture.
|---|---|---|---|
| Backend CHLOVA | code maison (TS) | seule surface | — |
| Ollama (proxy cloud) | `ollama/ollama` épinglé | interne | — |
| MCP n8n | `czlonkowski/n8n-mcp` épinglé | interne | read-only (P1) |
| MCP Portainer | `portainer/portainer-mcp` épinglé | interne | read-only (P1) |
| MCP n8n | **natif** dans n8n ≥ 2.18.4 (pas de conteneur) | interne | read-only (P1) |
| MCP Portainer | `portainer/portainer-mcp` épinglé (sidecar) | interne | read-only (P1) |
| socket-proxy | `tecnativa/docker-socket-proxy` épinglé | interne | scoping Docker |
+6 -14
View File
@@ -53,18 +53,11 @@ services:
- chlova-internal
# AUCUN port publié.
# ── MCP n8n (czlonkowski/n8n-mcp) — read-only en Phase 1 ────────────────
mcp-n8n:
image: ghcr.io/czlonkowski/n8n-mcp:2.18.3 # TODO confirmer tag + épingler digest
restart: unless-stopped
environment:
MCP_MODE: http # transport HTTP (backend distant via réseau)
MCP_AUTH_TOKEN: ${MCP_N8N_AUTH_TOKEN:?requis}
N8N_API_URL: ${N8N_API_URL} # instance n8n existante (interne)
N8N_API_KEY: ${N8N_API_KEY:?requis} # token n8n à portée RESTREINTE (lecture P1)
networks:
- chlova-internal
# AUCUN port publié.
# ── MCP n8n : NATIF (instance n8n ≥ 2.18.4) — pas de conteneur dédié ─────
# n8n expose son propre serveur MCP. À activer côté instance n8n (variable
# d'env d'instance + activation par workflow), puis copier l'URL + le "MCP
# Access Token" depuis n8n → Connection details. Le backend s'y connecte via
# MCP_N8N_URL (réseau interne). n8n doit être attaché à chlova-internal.
# ── MCP Portainer (portainer/portainer-mcp) — read-only en Phase 1 ──────
mcp-portainer:
@@ -93,13 +86,12 @@ services:
CHLOVA_ENV: ${CHLOVA_ENV:-production}
CHLOVA_PHASE: ${CHLOVA_PHASE:-1} # 1 = lecture seule (défaut) ; 2 = écriture sous review
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://ollama:11434}
MCP_N8N_URL: ${MCP_N8N_URL:-http://mcp-n8n:3000}
MCP_N8N_URL: ${MCP_N8N_URL} # endpoint MCP natif de n8n
MCP_PORTAINER_URL: ${MCP_PORTAINER_URL:-http://mcp-portainer:3000}
volumes:
- chlova-data:/app/data # SQLite (table assets, P2+)
depends_on:
- ollama
- mcp-n8n
- mcp-portainer
networks:
- chlova-internal
+1 -1
View File
@@ -7,7 +7,7 @@
| Réseau | Type | Membres | But |
|---|---|---|---|
| `chlova-internal` | `internal: true` | backend, ollama, mcp-n8n, mcp-portainer, socket-proxy, (n8n, portainer existants) | bus interne ; **aucun accès externe** |
| `chlova-internal` | `internal: true` | backend, ollama, mcp-portainer, socket-proxy, (n8n + Portainer existants, à attacher) | bus interne ; **aucun accès externe** |
| `chlova-egress` | bridge | ollama uniquement | sortie contrôlée vers `ollama.com` |
- `chlova-internal` est déclaré `internal: true` : **pas de route vers l'extérieur**.