From 4e30ea19478b12d2ab0d954521165d8829368a90 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Sat, 4 Jul 2026 18:56:02 +0100 Subject: [PATCH] =?UTF-8?q?common:=20runbook=20run=5Fcommand=20v2=20(P0=20?= =?UTF-8?q?mcp-nas)=20+=20obsolescence=20r=C3=A8gles=201-3=20MCP-NAS-SCRIP?= =?UTF-8?q?TING?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- _INDEX.md | 3 +- common/MCP-NAS-SCRIPTING.md | 5 +++ common/mcp-nas-run-command-v2.md | 71 ++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 common/mcp-nas-run-command-v2.md diff --git a/_INDEX.md b/_INDEX.md index 7e10b86..43022c5 100644 --- a/_INDEX.md +++ b/_INDEX.md @@ -25,7 +25,8 @@ | [Bifrost VK OpenCode fix (403/no route)](common/BIFROST-VK-OPENCODE-FIX.md) | 2026-06-23 | infra, bifrost, opencode, vk | | [Hebergement sites statiques Hermes (container nginx dedie)](common/HEBERGEMENT-SITES-STATIQUES.md) | 2026-06-22 | infra, nginx, static, hermes | -| [MCP NAS scripting reference (sessions, limites, services internes)](common/MCP-NAS-SCRIPTING.md) | 2026-06-23 | infra, mcp-nas, scripting | +| [MCP NAS scripting reference (sessions, limites, services internes)](common/MCP-NAS-SCRIPTING.md) — règles 1-3 obsolètes, voir v2 | 2026-06-23 | infra, mcp-nas, scripting | +| [MCP NAS run_command v2 (P0) : heredocs, commandes longues, busy-check, reset_session](common/mcp-nas-run-command-v2.md) | 2026-07-04 | infra, mcp-nas, run-command, tmux, reset-session | | [Migration OpenRouter vers OpenCode Go (endpoint zen/go/v1)](common/OPENCODE-GO-MIGRATION.md) | 2026-06-16 | infra, opencode, migration, llm | | [Cleanup stack documentaire (Pandoc/Gotenberg/Carbone retires)](common/cleanup-stack-documentaire.md) | 2026-06 | infra, cleanup, doc-stack | | [Git push depuis mcp-nas (172.17.0.1 vs 192.168.100.33)](common/git-push-depuis-mcp-nas.md) | 2026-06-15 | infra, git, mcp-nas | diff --git a/common/MCP-NAS-SCRIPTING.md b/common/MCP-NAS-SCRIPTING.md index f146e96..7370bb0 100644 --- a/common/MCP-NAS-SCRIPTING.md +++ b/common/MCP-NAS-SCRIPTING.md @@ -2,6 +2,11 @@ **Date** : 2026-06-23 | Session debug Veille/Bifrost (40+ tool calls observés) +> ⚠️ **OBSOLÈTE EN PARTIE depuis le patch P0 du 2026-07-04** — voir [mcp-nas-run-command-v2.md](mcp-nas-run-command-v2.md). +> Les RÈGLES 1, 2 et 3 ci-dessous (poisoning, heredoc interdit, limite 350 chars/base64) **ne s'appliquent plus** : +> heredocs, quotes et commandes longues fonctionnent nativement, et `reset_session` récupère une session bloquée. +> La section « RÈGLE 4 — Services internes (172.17.0.1) » reste valide. + --- ## Environnement du container diff --git a/common/mcp-nas-run-command-v2.md b/common/mcp-nas-run-command-v2.md new file mode 100644 index 0000000..dd6cbce --- /dev/null +++ b/common/mcp-nas-run-command-v2.md @@ -0,0 +1,71 @@ +# MCP NAS — run_command v2 (P0) : heredocs, commandes longues, reset_session + +**Date** : 2026-07-04 | Commit `30560984fa` sur `bolbol/linux-mcp-nas@main` | Testé et validé le jour même. + +> **Ce runbook remplace les RÈGLES 1–3 de [MCP-NAS-SCRIPTING.md](MCP-NAS-SCRIPTING.md).** +> Le chunking base64, la limite ~350 chars et l'interdiction de heredoc n'existent plus. +> La section « Services internes (172.17.0.1) » de l'ancien runbook reste valide. + +--- + +## Ce qui a changé + +Avant, `run_command` envoyait la commande brute à tmux via `send-keys` : le parsing shell +cassait sur les quotes, les heredocs déclenchaient un timeout tueur de session, et au-delà +de ~350 caractères la commande était tronquée — d'où le workaround base64 en 2 appels. + +Depuis le patch P0, le serveur **écrit la commande dans un fichier script depuis Python** +(`open(f"/tmp/mcp_{uid}.sh","w").write(command)` — zéro parsing shell) et n'envoie au pane que : + +``` +. /tmp/mcp_XXX.sh > /tmp/mcp_XXX.out 2>&1; echo $? > /tmp/mcp_XXX.rc +``` + +via `send-keys -l` (mode littéral). Conséquences : + +| Avant (v1) | Maintenant (v2) | +|------------|-----------------| +| Heredoc → timeout 120 s, session morte | Heredocs natifs, y compris `<<'EOF'` avec quotes/`$VAR`/backticks | +| Limite ~350 chars, base64 obligatoire | Testé 5 250 chars en un appel, intégrité parfaite | +| Quote simple `'` → troncature silencieuse | Quotes arbitraires OK (aucun parsing shell) | +| Prompt de continuation `>` empoisonnait la session | Mécaniquement impossible | +| Empilement sur pane occupé (vim/ssh/pager) | **Busy-check** : refus propre avec message d'options | +| Sessions poisonnées → new_session en chaîne | **reset_session** : reprise sans destruction | + +## Nouveaux comportements + +- **Busy-check** : si le pane exécute déjà quelque chose, `run_command` renvoie + `[SESSION OCCUPÉE] 'x' exécute actuellement 'sleep'…` au lieu d'empiler. Options proposées : + `capture_pane`, `send_keys`, `reset_session`, ou une autre session. +- **Timeout intelligent** : à expiration, le serveur tente un Ctrl-C puis sonde le shell. + S'il répond → session préservée (cwd/env conservés). Sinon → session recréée dans le même cwd. +- **`reset_session(session)`** : envoie Ctrl-C, `q` (pager), Ctrl-U, vérifie que le shell répond. + Reprend la main sur une session bloquée SANS la détruire. Pour vim : `send_keys ':q!'` d'abord. +- **Cleanup au démarrage** : sessions tmux orphelines et fichiers `/tmp/mcp_*` purgés au boot + du container (les 24 sessions zombies accumulées ont disparu au premier rebuild). + +## Tests de validation (2026-07-04) + +1. **Heredoc** avec quotes simples/doubles, `$VAR`, backticks, `$(subshell)`, `!#&*(){}[]|;<>` + → contenu intact, zéro expansion, exit code correct. +2. **Commande de 5 250 caractères** (heredoc 50 lignes × 100 chars + vérifications) + → 5 050 octets écrits, 50/50 lignes conformes au motif. +3. **Busy-check + reset_session** : `sleep 300` lancé via send_keys → `run_command` refusé + proprement → `reset_session` → « shell réactif, cwd/env conservés (cwd: /tmp) ». + +## Bonnes pratiques v2 + +- Écrire les scripts Python directement en heredoc : `cat <<'EOF' > /tmp/s.py … EOF` puis `python3 /tmp/s.py`. +- Ne plus jamais utiliser le workaround base64 (2 appels) ni le découpage printf-append. +- Session par défaut `claude` fiable ; `reset_session` avant de créer une session neuve. +- Le rebuild du container se fait **depuis le Mac** (`ssh nas`), jamais depuis mcp-nas lui-même : + ``` + ssh -p 22222 Best0f@192.168.100.33 + cd /volume1/docker/linux-mcp-nas + sudo docker compose build && sudo docker compose up -d --force-recreate + curl -s http://127.0.0.1:3042/health + ``` + +## À venir + +- **P1** : denylist ancrée (regex ancrées sur le début de commande) + résolution `nas.internal`.