ftp-deploy-mcp 0.0.0-stage → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.fr.md +468 -0
  2. package/CHANGELOG.md +415 -0
  3. package/CONTRIBUTING.fr.md +120 -0
  4. package/CONTRIBUTING.md +111 -0
  5. package/LICENSE +21 -0
  6. package/LICENSE.fr.md +26 -0
  7. package/README.fr.md +518 -0
  8. package/README.md +501 -2
  9. package/SECURITY.fr.md +99 -0
  10. package/SECURITY.md +94 -0
  11. package/docs/AGENT-PERFORMANCE.fr.md +144 -0
  12. package/docs/AGENT-PERFORMANCE.md +133 -0
  13. package/docs/ERROR-CONTRACT.fr.md +141 -0
  14. package/docs/ERROR-CONTRACT.md +137 -0
  15. package/docs/LANGUAGES.fr.md +68 -0
  16. package/docs/LANGUAGES.md +62 -0
  17. package/docs/RELEASE.fr.md +462 -0
  18. package/docs/RELEASE.md +435 -0
  19. package/docs/RESOURCE-BOUNDS.fr.md +144 -0
  20. package/docs/RESOURCE-BOUNDS.md +132 -0
  21. package/docs/SCRIPTED-EVALUATIONS.fr.md +190 -0
  22. package/docs/SCRIPTED-EVALUATIONS.md +181 -0
  23. package/docs/SECURITY-MODEL.fr.md +262 -0
  24. package/docs/SECURITY-MODEL.md +236 -0
  25. package/docs/STATE-STORAGE.fr.md +236 -0
  26. package/docs/STATE-STORAGE.md +231 -0
  27. package/docs/TRANSFERS.fr.md +140 -0
  28. package/docs/TRANSFERS.md +123 -0
  29. package/docs/WORKFLOW-MODEL.fr.md +63 -0
  30. package/docs/WORKFLOW-MODEL.md +62 -0
  31. package/evaluations/README.fr.md +95 -0
  32. package/evaluations/README.md +92 -0
  33. package/evaluations/fixture/README.txt +3 -0
  34. package/evaluations/fixture/catalog/alpha.txt +4 -0
  35. package/evaluations/fixture/catalog/bravo.txt +4 -0
  36. package/evaluations/fixture/catalog/charlie.txt +4 -0
  37. package/evaluations/fixture/catalog/delta.txt +4 -0
  38. package/evaluations/fixture/catalog/echo.txt +4 -0
  39. package/evaluations/fixture/catalog/foxtrot.txt +4 -0
  40. package/evaluations/fixture/reports/checks.txt +4 -0
  41. package/evaluations/fixture/reports/release.txt +3 -0
  42. package/evaluations/read-only.fr.xml +42 -0
  43. package/evaluations/read-only.xml +42 -0
  44. package/ftp-servers.example.json +27 -0
  45. package/install.cmd +29 -0
  46. package/install.sh +18 -0
  47. package/package.json +88 -4
  48. package/server.json +35 -0
  49. package/src/adapters/ftp.js +392 -0
  50. package/src/adapters/sftp.js +647 -0
  51. package/src/admission.js +15 -0
  52. package/src/atomic-write.js +131 -0
  53. package/src/clients.js +212 -0
  54. package/src/config.js +629 -0
  55. package/src/durable/confirmation.js +88 -0
  56. package/src/durable/engine.js +696 -0
  57. package/src/durable/plan.js +238 -0
  58. package/src/durable/schemas.js +206 -0
  59. package/src/durable/state.js +317 -0
  60. package/src/durable/status.js +175 -0
  61. package/src/durable-tools.js +94 -0
  62. package/src/errors.js +88 -0
  63. package/src/filezilla.js +260 -0
  64. package/src/i18n.js +58 -0
  65. package/src/index.js +175 -0
  66. package/src/local-path.js +130 -0
  67. package/src/locales/en.js +152 -0
  68. package/src/locales/errors.en.js +22 -0
  69. package/src/locales/errors.fr.js +22 -0
  70. package/src/locales/fr.js +152 -0
  71. package/src/locales/runtime.en.js +259 -0
  72. package/src/locales/runtime.fr.js +259 -0
  73. package/src/operations.js +276 -0
  74. package/src/redact.js +105 -0
  75. package/src/remote-path.js +101 -0
  76. package/src/scanner.js +103 -0
  77. package/src/setup.js +888 -0
  78. package/src/state/codec.mjs +103 -0
  79. package/src/state/index.mjs +1 -0
  80. package/src/state/io.mjs +173 -0
  81. package/src/state/records.mjs +60 -0
  82. package/src/state/store.mjs +360 -0
  83. package/src/state/writer.mjs +250 -0
  84. package/src/tool-registry.js +464 -0
  85. package/src/tools.js +1226 -0
  86. package/src/transfers.js +425 -0
  87. package/src/workflow/budget.mjs +83 -0
  88. package/src/workflow/events.mjs +199 -0
  89. package/src/workflow/model.mjs +179 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) ftp-deploy-mcp contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/LICENSE.fr.md ADDED
@@ -0,0 +1,26 @@
1
+ # Licence MIT — traduction informative
2
+
3
+ [English — canonical license](./LICENSE) | **Français — traduction informative**
4
+
5
+ Cette traduction facilite la lecture. Le texte anglais du fichier
6
+ [LICENSE](./LICENSE) constitue la licence de référence.
7
+
8
+ Copyright (c) contributeurs de ftp-deploy-mcp
9
+
10
+ Il est accordé gratuitement à toute personne obtenant une copie de ce logiciel
11
+ et des fichiers de documentation associés (le « Logiciel ») l'autorisation
12
+ d'utiliser le Logiciel sans restriction, notamment les droits d'utiliser,
13
+ copier, modifier, fusionner, publier, distribuer, concéder en sous-licence
14
+ et/ou vendre des copies du Logiciel, et de permettre aux personnes auxquelles
15
+ le Logiciel est fourni d'en faire autant, sous réserve des conditions suivantes :
16
+
17
+ La mention de copyright ci-dessus et la présente autorisation doivent être
18
+ incluses dans toutes les copies ou parties substantielles du Logiciel.
19
+
20
+ LE LOGICIEL EST FOURNI « EN L'ÉTAT », SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU
21
+ IMPLICITE, NOTAMMENT SANS GARANTIE DE QUALITÉ MARCHANDE, D'ADÉQUATION À UN USAGE
22
+ PARTICULIER ET D'ABSENCE DE CONTREFAÇON. EN AUCUN CAS LES AUTEURS OU TITULAIRES
23
+ DU COPYRIGHT NE PEUVENT ÊTRE TENUS RESPONSABLES D'UNE RÉCLAMATION, DE DOMMAGES
24
+ OU DE TOUTE AUTRE RESPONSABILITÉ, QUE CE SOIT DANS LE CADRE D'UNE ACTION
25
+ CONTRACTUELLE, DÉLICTUELLE OU AUTRE, DÉCOULANT DU LOGICIEL, DE SON UTILISATION
26
+ OU DE TOUTE AUTRE OPÉRATION LIÉE AU LOGICIEL.
package/README.fr.md ADDED
@@ -0,0 +1,518 @@
1
+ <div align="center">
2
+
3
+ <img src="https://raw.githubusercontent.com/alebgl77/ftp-deploy-mcp/main/assets/logo.svg" width="96" alt="logo ftp-deploy-mcp">
4
+
5
+ # ftp-deploy-mcp
6
+
7
+ **Le bouton déployer pour les agents de codage IA.**
8
+
9
+ Donnez à Claude Code, Claude Desktop, Cursor, Windsurf, Trae, Antigravity ou
10
+ tout client MCP un moyen ciblé de lister, lire, téléverser, télécharger et
11
+ déployer des fichiers sur vos propres serveurs FTP, FTPS et SFTP.
12
+
13
+ Le serveur stdio implémente la révision MCP `2026-07-28` avec le SDK TypeScript
14
+ modulaire v2 stable et conserve la négociation historique du SDK pour les
15
+ anciens clients MCP.
16
+
17
+ *English version → [README.md](./README.md)*
18
+
19
+ Langue de la CLI et des outils MCP : anglais par défaut ; utilisez `--lang fr` ou `FTP_MCP_LANG=fr`.
20
+ [Périmètre et priorité des langues](./docs/LANGUAGES.fr.md).
21
+
22
+ [![CI](https://github.com/alebgl77/ftp-deploy-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/alebgl77/ftp-deploy-mcp/actions/workflows/ci.yml)
23
+ [![Licence : MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
24
+ [![Node >=22](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)](./package.json)
25
+ [![Compatible MCP](https://img.shields.io/badge/MCP-compatible-8A2BE2.svg)](https://modelcontextprotocol.io)
26
+
27
+ <img src="https://raw.githubusercontent.com/alebgl77/ftp-deploy-mcp/main/assets/banner-fr.png" width="100%" alt="ftp-deploy-mcp — Déploiement contrôlé pour vos agents IA ; FTP, FTPS, SFTP via MCP stdio">
28
+
29
+ </div>
30
+
31
+ Des contrôles conçus pour le déploiement gardent les identifiants hors des
32
+ réponses d'outils, proposent lecture seule et dry-run, et limitent l'accès aux
33
+ fichiers locaux avec `localRoot`. Le dépôt est couvert par une suite e2e
34
+ étendue utilisant des serveurs FTP et SFTP locaux. Aucune télémétrie.
35
+
36
+ > **Disponibilité :** l'installation depuis les sources fonctionne aujourd'hui.
37
+ > Le paquet npm n'est **pas encore publié** : `npx -y ftp-deploy-mcp` reste
38
+ > indisponible. Le projet indique toujours que la publication dans le registre
39
+ > MCP officiel est en attente ; l'installation depuis un registre n'est pas
40
+ > proposée ici. Les releases de sources GitHub sont distinctes des publications
41
+ > sur npm et le registre MCP officiel. Les pages Glama et MCP Index existantes
42
+ > sont des fiches de découverte, pas la preuve d'un paquet installable.
43
+ > Cette copie porte la version 0.3.1. Les versions sources publiées figurent sur
44
+ > [GitHub Releases](https://github.com/alebgl77/ftp-deploy-mcp/releases/latest) ;
45
+ > la release GitHub v0.3.0 publiée reste inchangée.
46
+
47
+ ## Documentation
48
+
49
+ | Document | English | Français |
50
+ |---|---|---|
51
+ | Présentation et installation | [README](./README.md) | [README](./README.fr.md) |
52
+ | Modifications | [Changelog](./CHANGELOG.md) | [Journal](./CHANGELOG.fr.md) |
53
+ | Contribution | [Guide](./CONTRIBUTING.md) | [Guide](./CONTRIBUTING.fr.md) |
54
+ | Politique de sécurité | [Policy](./SECURITY.md) | [Politique](./SECURITY.fr.md) |
55
+ | Modèle de sécurité | [Model](./docs/SECURITY-MODEL.md) | [Modèle](./docs/SECURITY-MODEL.fr.md) |
56
+ | Publication | [Guide](./docs/RELEASE.md) | [Guide](./docs/RELEASE.fr.md) |
57
+ | Évaluation d'agents | [Instructions](./evaluations/README.md) | [Instructions](./evaluations/README.fr.md) |
58
+ | Performances et intégration des agents | [Guide](./docs/AGENT-PERFORMANCE.md) | [Guide](./docs/AGENT-PERFORMANCE.fr.md) |
59
+ | Conformité MCP scriptée | [Guide](./docs/SCRIPTED-EVALUATIONS.md) | [Guide](./docs/SCRIPTED-EVALUATIONS.fr.md) |
60
+ | Langues de la CLI et des outils MCP | [Guide](./docs/LANGUAGES.md) | [Guide](./docs/LANGUAGES.fr.md) |
61
+ | Contrat d'erreur MCP | [Contract](./docs/ERROR-CONTRACT.md) | [Contrat](./docs/ERROR-CONTRACT.fr.md) |
62
+ | Transferts vérifiés par promotion | [Guide](./docs/TRANSFERS.md) | [Guide](./docs/TRANSFERS.fr.md) |
63
+ | Limites de parcours et d'admission | [Limits](./docs/RESOURCE-BOUNDS.md) | [Limites](./docs/RESOURCE-BOUNDS.fr.md) |
64
+ | Stockage d'état durable | [Library](./docs/STATE-STORAGE.md) | [Bibliothèque](./docs/STATE-STORAGE.fr.md) |
65
+ | Modèle du workflow durable | [Model](./docs/WORKFLOW-MODEL.md) | [Modèle](./docs/WORKFLOW-MODEL.fr.md) |
66
+ | Licence MIT | [Texte canonique](./LICENSE) | [Traduction informative](./LICENSE.fr.md) |
67
+
68
+ ## Architecture et scénarios
69
+
70
+ Explorez les schémas d'architecture actuelle et cible et les scénarios illustratifs
71
+ dans le [guide HTML interactif bilingue](https://github.com/alebgl77/ftp-deploy-mcp/blob/main/site/index.html).
72
+ Le guide et ses instructions
73
+ de reconstruction en [anglais](https://github.com/alebgl77/ftp-deploy-mcp/blob/main/site/README.md) et en
74
+ [français](https://github.com/alebgl77/ftp-deploy-mcp/blob/main/site/README.fr.md) se trouvent dans le dépôt, hors du paquet
75
+ npm. Après clonage, ouvrez `site/index.html` localement et utilisez son
76
+ sélecteur de langue.
77
+
78
+ Les bannières du README ont été générées avec ChatGPT Image. Leur
79
+ [provenance et leurs prompts exacts](https://github.com/alebgl77/ftp-deploy-mcp/blob/main/assets/provenance/README.fr.md)
80
+ documentent leur rôle illustratif ; elles ne constituent pas une certification.
81
+
82
+ ## Première installation depuis les sources
83
+
84
+ 1. Installez une version de Node.js prise en charge : 22, 24 ou 26 (minimum : 22).
85
+ 2. Lancez `git clone https://github.com/alebgl77/ftp-deploy-mcp.git`, puis
86
+ `cd ftp-deploy-mcp`.
87
+ 3. Lancez `npm ci --omit=dev --ignore-scripts`.
88
+ 4. Lancez `npm run setup`, puis modifiez la configuration générée : renseignez
89
+ un `localRoot` absolu, remplacez les identifiants et configurez le pin de clé
90
+ d'hôte SFTP ou les acceptations de risque FTP/FTPS décrites plus bas.
91
+ 5. Redémarrez le client MCP et essayez un dry-run :
92
+
93
+ ```text
94
+ Appelez ftp_deploy avec :
95
+ {"server":"prod","local_dir":"dist","remote_dir":"/","dry_run":true}
96
+ ```
97
+
98
+ Sous Windows, `install.cmd`, et sous macOS/Linux, `./install.sh`, peuvent
99
+ remplacer les étapes 3–4. Relisez chaque serveur généré avant la première
100
+ connexion.
101
+
102
+ Pour une version étiquetée, sélectionnez son tag exact avant l'installation.
103
+ `npm ci` utilise le seul fichier de référence `package-lock.json`, avec six
104
+ dépendances directes épinglées exactement et le graphe revu. Conservez-le avec
105
+ les sources. `--ignore-scripts` désactive les scripts automatiques de cycle de
106
+ vie des dépendances ; le setup est une action explicite distincte.
107
+
108
+ Le fichier d'installation source v0.3.1 porte le nom
109
+ `ftp-deploy-mcp-0.3.1-source.tar.gz` : 90 fichiers, dont ce verrouillage. Après
110
+ vérification de sa publication et de ses empreintes, extrayez-le dans un dossier
111
+ neuf :
112
+
113
+ ```bash
114
+ tar --ignore-zeros -xzf ftp-deploy-mcp-0.3.1-source.tar.gz
115
+ cd package
116
+ npm ci --omit=dev --ignore-scripts
117
+ node src/index.js setup
118
+ ```
119
+
120
+ Cette archive d'installation exclut les tests et scripts de maintenance du dépôt ;
121
+ le ZIP/tar automatique de GitHub contient le dépôt complet. Le `.tgz` npm distinct
122
+ contient 89 fichiers sans verrouillage et reste non qualifié : un vrai consommateur
123
+ npm a changé dix dépendances de production. Il ne garantit pas une installation
124
+ verrouillée. Le [guide de publication](./docs/RELEASE.fr.md) décrit les contrôles
125
+ et leurs limites.
126
+
127
+ ## Matrice protocoles et sécurité
128
+
129
+ | Protocole | Identité du transport | Comportement de la racine distante | Usage recommandé |
130
+ |---|---|---|---|
131
+ | **SFTP** | Chiffré. `hostKeySha256` est obligatoire sauf si `allowUnknownHostKey: true` accepte explicitement le risque d'usurpation. | Les contrôles `realpath`/`lstat` refusent les composants symboliques et maintiennent les opérations sous `root`. Un serveur malveillant ou changeant peut encore créer une course entre contrôle et usage. | À privilégier, avec empreinte vérifiée hors bande. |
132
+ | **FTPS** | Chiffré si le certificat est vérifié. `insecureTLS: true` exige aussi `allowInsecure: true` et supprime la protection MITM. | Une sous-racine côté client n'est pas un jail anti-symlink fiable. Un `root` autre que `/` est refusé sauf `allowUnsafeRemoteRoot: true`. | Utiliser un compte dédié, chrooté côté serveur, dont la racine visible est `/`. |
133
+ | **FTP** | En clair. Refusé sauf si `allowInsecure: true` accepte interception et exposition des identifiants. | Même limite que FTPS : la vraie frontière est le compte/chroot serveur, pas le contrôle lexical du client. | Héritage uniquement, réseau de confiance et compte dédié chrooté. |
134
+
135
+ Les trois protocoles appliquent aussi `localRoot` à `ftp_upload`,
136
+ `ftp_deploy` et `ftp_download` afin de limiter les fichiers locaux accessibles
137
+ au serveur MCP.
138
+
139
+ ## Ce que vous obtenez
140
+
141
+ - Dix outils MCP ciblés : découverte et test des serveurs, liste, lecture,
142
+ téléversement, déploiement récursif, téléchargement, création de dossier,
143
+ renommage et suppression.
144
+ - Plusieurs serveurs nommés dans une configuration locale.
145
+ - Exclusions façon gitignore, dry-run et mode `readOnly` par serveur.
146
+ - Import FileZilla, assistant de configuration et commande `doctor` en lecture
147
+ seule.
148
+ - Identifiants chargés localement depuis la configuration, l'environnement ou
149
+ des clés SSH, et jamais renvoyés intentionnellement au modèle.
150
+
151
+ ## Configuration des serveurs
152
+
153
+ Un chemin de configuration explicite fait autorité :
154
+
155
+ 1. `--config <chemin>`
156
+ 2. `FTP_MCP_CONFIG`, en l'absence de `--config`
157
+
158
+ Une configuration explicite vide, absente, illisible ou invalide produit une
159
+ erreur sans repli vers un autre fichier. Les outils MCP restent disponibles
160
+ pour signaler le problème. `--config` exige un argument de chemin.
161
+
162
+ Sans ces deux sélecteurs, la première configuration trouvée est utilisée :
163
+
164
+ 1. `./ftp-servers.json`
165
+ 2. `~/.ftp-mcp/servers.json`
166
+
167
+ L'exemple pédagogique ci-dessous contient des commentaires. Un vrai fichier de
168
+ configuration doit être du JSON strict ; partez de
169
+ [ftp-servers.example.json](./ftp-servers.example.json).
170
+
171
+ ```jsonc
172
+ {
173
+ "defaultServer": "prod",
174
+ "stateDir": "/home/alice/.local/state/ftp-deploy-mcp",
175
+ "requirePlan": true,
176
+ "servers": {
177
+ "prod": {
178
+ "protocol": "sftp",
179
+ "host": "ssh.example.com",
180
+ "port": 22,
181
+ "user": "deploy",
182
+ "password": "${ENV:PROD_PASSWORD}",
183
+ "privateKeyPath": "~/.ssh/id_ed25519",
184
+ "passphrase": "${ENV:PROD_KEY_PASSPHRASE}",
185
+ "localRoot": "/home/alice/projects/site",
186
+ "root": "/var/www/site",
187
+ "hostKeySha256": "SHA256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
188
+ "readOnly": false
189
+ }
190
+ }
191
+ }
192
+ ```
193
+
194
+ Remplacez l'empreinte composée de `A`, volontairement inutilisable pour un vrai
195
+ hôte. Pendant une rotation contrôlée, `hostKeySha256` accepte un tableau :
196
+
197
+ ```json
198
+ "hostKeySha256": [
199
+ "SHA256:old_verified_43_character_base64_value_here",
200
+ "SHA256:new_verified_43_character_base64_value_here"
201
+ ]
202
+ ```
203
+
204
+ Ces libellés montrent seulement la forme et ne sont pas des pins valides.
205
+ Chaque valeur réelle contient exactement `SHA256:` suivi de 43 caractères
206
+ base64 sans remplissage.
207
+
208
+ ### Référence des champs
209
+
210
+ | Champ | Protocoles | Signification |
211
+ |---|---|---|
212
+ | `stateDir` | niveau supérieur | Répertoire absolu et normalisé facultatif pour l'état durable, canoniquement disjoint de chaque `localRoot`. Son activation publie les quatre outils durables. |
213
+ | `requirePlan` | niveau supérieur | Avec `stateDir`, vaut `true` par défaut. Bloque les mutations distantes legacy sauf le dry-run de `ftp_deploy` ; `false` les conserve sous le même verrou persistant d'alias. |
214
+ | `stateLimits` | niveau supérieur | Quotas stricts facultatifs pour l'état, les sauvegardes, plans, opérations, fichiers/octets de plan, octets/événements de journal et fichiers de sauvegarde. |
215
+ | `protocol` | tous | Requis : `ftp`, `ftps` ou `sftp`. |
216
+ | `host` / `port` / `user` | tous | Hôte, port et compte. Ports par défaut : 21, 990 pour FTPS implicite et 22 pour SFTP. |
217
+ | `password` | tous | Mot de passe ou placeholder `${ENV:NOM}`. |
218
+ | `privateKeyPath` / `passphrase` | SFTP | Chemin de clé SSH et passphrase optionnelle. `~` est étendu. Ces champs authentifient l'utilisateur, pas le serveur. |
219
+ | `localRoot` | tous | Requis pour upload, deploy et download. Doit se résoudre en dossier local absolu existant ; `~` est accepté. Les chemins relatifs et les sorties par lien/jonction sont refusés. Un chemin d'outil absolu doit lui aussi rester à l'intérieur. |
220
+ | `root` | tous | Racine distante, `/` par défaut. SFTP utilise realpath/lstat. FTP/FTPS exigent un chroot serveur pour une frontière fiable. |
221
+ | `hostKeySha256` | SFTP | Empreinte obligatoire, chaîne ou tableau non vide. Format : `SHA256:<43 caractères base64 sans remplissage>`. Incompatible avec `allowUnknownHostKey`. |
222
+ | `allowUnknownHostKey` | SFTP | Dérogation de compatibilité urgente. `true` accepte une identité serveur non vérifiée et affiche un avertissement. |
223
+ | `readOnly` | tous | Bloque upload, deploy, mkdir, rename et delete. Le dry-run de deploy reste possible. |
224
+ | `operationTimeoutMs` | tous | Délai d'un appel, attente et connexion comprises : 120000 ms par défaut. Entier de 100 à 3600000. Les délais natifs du transport restent actifs. |
225
+ | `maxTransferBytes` | tous | Maximum d'octets réels par fichier : 268435456 (256 Mio) par défaut, maximum 1099511627776 (1 Tio). Entier positif représentable exactement. |
226
+ | `maxDeployFiles` | tous | Maximum de fichiers sélectionnés par déploiement : 10000 par défaut, maximum 100000. Entier positif ; ne borne pas le parcours complet des dossiers. |
227
+ | `maxScanEntries` | tous | Entrées locales visitées par déploiement, racine, exclusions et liens compris. Défaut 100000, maximum 1000000 ; entier positif sans perte. |
228
+ | `maxScanDepth` | tous | Profondeur inclusive des dossiers sous la racine (niveau 0). Défaut 64, maximum 256 ; entier positif sans perte. |
229
+ | `maxDeployBytes` | tous | Maximum cumulé d'octets sources par déploiement : 1073741824 (1 Gio) par défaut, maximum 1099511627776 (1 Tio). Les tentatives échouées conservent leur réservation. |
230
+ | `implicitTLS` | FTPS | Active TLS implicite, normalement sur le port 990. |
231
+ | `insecureTLS` | FTPS | Désactive la vérification du certificat. Exige `allowInsecure: true`. |
232
+ | `allowInsecure` | FTP/FTPS | Accepte explicitement FTP en clair ou FTPS non vérifié. Ne sécurise pas la connexion. |
233
+ | `allowUnsafeRemoteRoot` | FTP/FTPS | Autorise un `root` autre que `/` malgré le risque de sortie par symlink. À utiliser seulement si la frontière du compte serveur est comprise. |
234
+
235
+ Toute chaîne peut contenir `${ENV:NOM_DE_VARIABLE}`. Une variable absente
236
+ produit une erreur de configuration qui la nomme.
237
+
238
+ ### Vérifier une empreinte SFTP hors bande
239
+
240
+ Ne faites pas confiance à une empreinte obtenue uniquement via la connexion que
241
+ vous cherchez justement à vérifier.
242
+
243
+ 1. Obtenez l'empreinte SHA-256 depuis le panneau authentifié ou le support de
244
+ l'hébergeur, ou auprès d'un administrateur via un canal séparé et
245
+ authentifié.
246
+ 2. Si vous administrez l'hôte, utilisez sa console de confiance pour lancer par
247
+ exemple
248
+ `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256`.
249
+ 3. Comparez toute la valeur `SHA256:...` avant de la placer dans
250
+ `hostKeySha256`. `ssh-keyscan` peut collecter une clé candidate, mais ne
251
+ l'authentifie pas à lui seul.
252
+
253
+ Pour une rotation, vérifiez la nouvelle empreinte hors bande, configurez
254
+ temporairement les deux pins, changez la clé serveur, confirmez la connexion,
255
+ puis retirez l'ancien pin. N'utilisez pas `allowUnknownHostKey` comme raccourci.
256
+
257
+ ## Référence des outils
258
+
259
+ Tous les chemins distants sont relatifs au `root` distant. `server` est
260
+ optionnel lorsqu'un `defaultServer` est défini ou qu'un seul serveur existe.
261
+
262
+ | Outil | Paramètres principaux | Rôle |
263
+ |---|---|---|
264
+ | `ftp_list_servers` | aucun | Affiche les métadonnées et avertissements, jamais les mots de passe. |
265
+ | `ftp_test` | `server?` | Se connecte et liste la racine visible. |
266
+ | `ftp_list` | `server?`, `path?`, `limit?`, `offset?` | Liste un dossier distant. `limit` vaut 50 par défaut (1–200) ; `offset` vaut 0 par défaut. |
267
+ | `ftp_read` | `server?`, `path`, `max_bytes?` | Lit un fichier texte borné ; refuse les binaires. |
268
+ | `ftp_upload` | `server?`, `local_path`, `remote_path?` | Envoie un fichier depuis `localRoot`. |
269
+ | `ftp_deploy` | `server?`, `local_dir`, `remote_dir?`, `include?`, `exclude?`, `dry_run?` | Déploie récursivement un dossier de `localRoot`. |
270
+ | `ftp_download` | `server?`, `remote_path`, `local_path`, `overwrite?` | Télécharge dans `localRoot`. |
271
+ | `ftp_mkdir` | `server?`, `path` | Crée un dossier distant récursivement. |
272
+ | `ftp_rename` | `server?`, `from_path`, `to_path` | Renomme ou déplace. |
273
+ | `ftp_delete` | `server?`, `path`, `recursive?` | Supprime un fichier ou, avec récursion explicite, un dossier. |
274
+ | `ftp_plan_deploy` | `server?`, `local_dir`, `remote_dir?`, `include?`, `exclude?`, `ttl_seconds?` | Publie un plan durable immuable et expirant. Disponible seulement avec `stateDir`. |
275
+ | `ftp_apply_deploy` | `plan_id`, `idempotency_key`, `resume?` | Confirme, associe puis reprend explicitement une application durable. |
276
+ | `ftp_deploy_status` | exactement un de `plan_id` / `operation_id`, `offset?`, `limit?`, `if_journal_seq?` | Lit un instantané durable paginé, sans réseau ni écriture d'état. |
277
+ | `ftp_rollback_deploy` | `operation_id`, `resume?` | Confirme et reprend explicitement le retour arrière prudent des fichiers durablement acquittés. |
278
+
279
+ ### Garanties du workflow durable
280
+
281
+ Les outils durables exigent le flux officiel MCP `input_required`, sans repli
282
+ booléen. L'état signé lie session, méthode, digest du plan, opération, hash de
283
+ la clé d'idempotence, choix de reprise, séquence du journal et expiration. Un
284
+ refus, une preuve invalide ou expirée, ou un client incompatible n'a aucun effet
285
+ distant. L'association seule renvoie un statut ; toute mutation distante non
286
+ terminale exige `resume:true`.
287
+
288
+ Le niveau est `observable_state_reconciled` : le remplacement par fichier dépend
289
+ du serveur, l'atomicité multi-fichiers et l'exécution exactement une fois sont
290
+ fausses, et le retour arrière couvre seulement les fichiers durablement acquittés.
291
+ SFTP remplace et crée seulement sous un parent canonique existant ; FTP/FTPS
292
+ remplace seulement un fichier régulier existant. Aucun parent durable n'est créé,
293
+ aucun extra distant purgé, aucun retour automatique lancé et aucun
294
+ `SATISFIED_UNOWNED` restauré.
295
+
296
+ Les processus coopérants partageant le même `stateDir` canonique sérialisent
297
+ l'alias exact avant construction de l'adaptateur. Ce n'est pas un verrou distant
298
+ distribué et cela ne coordonne ni aliases ni répertoires d'état différents.
299
+ Aliases d'écriture qui se chevauchent, renommage d'alias, binaires mélangés et
300
+ processus tué avec verrou persistant exigent une intervention : mettez les
301
+ écrivains en pause pour les mises à niveau et récupérez les verrous hors ligne.
302
+ Les écrivains externes et courses ABA restent hors de la garantie observable.
303
+
304
+ ### Promotion vérifiée depuis un fichier temporaire
305
+
306
+ Les envois et déploiements écrivent dans un temporaire voisin imprévisible,
307
+ vérifient son nombre réel d'octets et son SHA256 contre la source locale, puis
308
+ le promeuvent par un unique renommage. Un échec de vérification ou de renommage
309
+ ne déclenche jamais la suppression de la cible finale ni un repli vers un
310
+ écrasement direct. Les téléchargements vérifient un temporaire local exclusif,
311
+ le synchronisent et le ferment avant de promouvoir le fichier complet. Par
312
+ défaut, `overwrite:false` utilise un lien physique pour préserver tout fichier
313
+ apparu entre-temps ; les systèmes sans liens physiques échouent sans écraser.
314
+
315
+ Les remplacements locaux et SFTP conservent les bits de droits (0777) d'une
316
+ cible régulière existante ; FTP/FTPS ne le garantit pas de façon portable.
317
+ Les droits de création du compte, l'umask et les ACL doivent donc convenir à
318
+ la destination. Le renommage dépend du serveur et du système de fichiers.
319
+ Le chemin legacy ne garantit ni remplacement atomique universel, ni transaction
320
+ du site, ni retour arrière. La relecture augmente le trafic réseau. Voir les
321
+ [garanties, limites et règles de nettoyage des transferts](./docs/TRANSFERS.fr.md).
322
+
323
+ ### Exécution, annulation et contention
324
+
325
+ Dans un même processus Node, upload, deploy, mkdir, rename et delete suivent
326
+ une file FIFO pour un protocole, nom d'hôte, port et utilisateur normalisés
327
+ identiques. Les alias de serveur et les racines partagent ce verrou. Les
328
+ téléchargements sont sérialisés par destination locale canonique, y compris
329
+ entre serveurs. Les lectures distantes peuvent se chevaucher.
330
+
331
+ Une annulation MCP ou l'expiration du délai ferme les transports actifs et
332
+ arrête les fichiers suivants du déploiement. Les erreurs portent `CANCELLED`
333
+ ou `TIMEOUT` ; `TARGET_BUSY` indique l'attente d'une autre opération. Une
334
+ réponse peut précéder le règlement réel d'une opération bloquée, mais son
335
+ verrou reste détenu jusqu'au règlement et au nettoyage. Aucune mutation
336
+ incertaine n'est réessayée automatiquement. Inspectez l'état distant et local
337
+ partiel avant de réessayer ; les mutations legacy ne sont pas transactionnelles
338
+ et ne fournissent aucun retour arrière.
339
+
340
+ La préparation interne est à usage unique et limitée à 10 secondes sans
341
+ prolonger l'échéance globale. L'admission reste détenue jusqu'à la fin réelle
342
+ du travail et du nettoyage. Un contexte préparé est libéré une fois, même s'il
343
+ arrive après annulation ; le handler n'est pas appelé après une préparation
344
+ annulée ou expirée. Les callbacks de préparation peuvent eux-mêmes agir. Les
345
+ outils durables appliquent la même discipline de terminaison. Voir les
346
+ [limites de ressources](./docs/RESOURCE-BOUNDS.fr.md).
347
+
348
+ La progression n'est envoyée qu'avec un token fourni par l'appelant, sous
349
+ forme de compteurs croissants, sans chemins ni texte d'identifiants. Les
350
+ verrous ne coordonnent pas les autres processus Node, alias DNS, comptes ou
351
+ clients externes présents sur le même hôte.
352
+
353
+ ### Compatibilité des réponses, pagination et annotations
354
+
355
+ `ftp_list` renvoie une page plutôt qu'une liste de dossier non bornée. Une
356
+ réponse réussie contient les champs de pagination `total`, `count`, `offset`,
357
+ `limit`, `has_more` et `next_offset`. Par exemple, la requête
358
+ `{"server":"prod","path":"/assets","limit":2,"offset":2}` peut produire
359
+ l'extrait volontairement non exhaustif ci-dessous. Il omet les champs requis
360
+ `server`, `path` et `security_warning` au premier niveau, ainsi que les champs
361
+ requis `size_bytes` et `modified_at` de chaque entrée :
362
+
363
+ ```json
364
+ {
365
+ "structuredContent": {
366
+ "entries": [
367
+ { "name": "app.css", "type": "file" },
368
+ { "name": "app.js", "type": "file" }
369
+ ],
370
+ "total": 6,
371
+ "count": 2,
372
+ "offset": 2,
373
+ "limit": 2,
374
+ "has_more": true,
375
+ "next_offset": 4
376
+ }
377
+ }
378
+ ```
379
+
380
+ Le texte historique, lisible par un humain dans `content`, est conservé pour
381
+ compatibilité. En cas de succès, tous les outils sauf `ftp_read` annoncent
382
+ aussi un `outputSchema` MCP et renvoient un `structuredContent` correspondant ;
383
+ `ftp_read` conserve un succès texte borné. Chacun des neuf schémas structurés
384
+ accepte soit sa forme stricte de succès, soit une enveloppe stricte `{error}`.
385
+ Les erreurs d’exécution renvoient `isError: true`, un texte traduit, un code,
386
+ un UUID de requête, les effets observés et une indication de reprise sûre.
387
+ Un outil inconnu reste une erreur de protocole. Voir le
388
+ [contrat d’erreur](./docs/ERROR-CONTRACT.fr.md).
389
+
390
+ Le processus admet au plus 64 appels d’outil, y compris ceux encore en nettoyage
391
+ après annulation. Les appels supplémentaires renvoient `CAPACITY_LIMIT`. Le parcours
392
+ local d’un déploiement est asynchrone et borné séparément ; les [limites de ressources](./docs/RESOURCE-BOUNDS.fr.md)
393
+ décrivent le comptage exact, `SCAN_LIMIT` et les exclusions personnalisées corrigées.
394
+
395
+ Tous les outils publient des annotations MCP sur leur caractère lecture seule,
396
+ destructif, idempotent et ouvert sur l'extérieur. Ces annotations guident les
397
+ clients mais ne constituent pas une frontière de sécurité : imposez les accès
398
+ avec les identifiants serveur, `readOnly`, `localRoot` et les contrôles de
399
+ protocole décrits plus haut. Le résultat structuré de `ftp_deploy` contient un
400
+ résumé et des échantillons bornés, pas des listes exhaustives de fichiers.
401
+
402
+ `ftp_deploy` n'est pas une transaction. Si un ou plusieurs transferts échouent,
403
+ l'outil renvoie une erreur MCP avec un résumé du déploiement partiel ; les
404
+ fichiers déjà promus ne sont pas annulés.
405
+
406
+ Les exclusions par défaut couvrent notamment `node_modules`, `.git`, les
407
+ fichiers d'environnement, journaux, métadonnées système, `ftp-servers.json` et
408
+ `.ftp-mcp` à toute profondeur.
409
+ Le nom réservé `.ftp-mcp-*.tmp` est toujours exclu, même si un motif `include`
410
+ explicite le sélectionne, pour ne pas déployer un temporaire de téléchargement partiel.
411
+
412
+ ## Configuration du client
413
+
414
+ `npm run setup` détecte les clients pris en charge, crée des sauvegardes
415
+ horodatées avant de modifier une configuration existante et affiche un bloc
416
+ pour les clients configurés par interface. Pour un branchement manuel,
417
+ remplacez le chemin par celui, absolu, de ce checkout :
418
+
419
+ ```json
420
+ {
421
+ "mcpServers": {
422
+ "ftp": {
423
+ "command": "node",
424
+ "args": ["/chemin/absolu/vers/ftp-deploy-mcp/src/index.js"]
425
+ }
426
+ }
427
+ }
428
+ ```
429
+
430
+ Les emplacements courants sont `.mcp.json` pour Claude Code,
431
+ `~/.cursor/mcp.json` pour Cursor et
432
+ `~/.codeium/windsurf/mcp_config.json` pour Windsurf. Claude Desktop et les
433
+ autres clients acceptent la même commande et les mêmes arguments dans leurs
434
+ réglages MCP.
435
+
436
+ Après vérification de la première publication npm, cette commande source pourra
437
+ être remplacée par `npx -y ftp-deploy-mcp`. Ce n'est volontairement pas présenté
438
+ comme une installation fonctionnelle aujourd'hui.
439
+
440
+ ## Import FileZilla et diagnostic
441
+
442
+ ```bash
443
+ node src/index.js import-filezilla --file /chemin/sitemanager.xml --out ./ftp-servers.json
444
+ npm run doctor
445
+ ```
446
+
447
+ L'import peut décoder des mots de passe en clair. Gardez la sortie hors du
448
+ contrôle de version, restreignez ses droits, ajoutez `localRoot` et examinez
449
+ chaque avertissement de transport ou de racine FTP/FTPS avant la connexion.
450
+ `doctor` reste en lecture seule et ne montre pas les mots de passe.
451
+
452
+ ## Migration de v0.1 vers v0.2
453
+
454
+ La release GitHub v0.3.0 est publiée. Cette copie source porte la version
455
+ 0.3.1. Le paquet npm reste non publié et le projet indique toujours que la
456
+ publication dans le registre MCP officiel est en attente. Les étapes ci-dessous
457
+ concernent l'installation depuis les sources et n'annoncent pas une release npm.
458
+
459
+ 1. Ajoutez un `localRoot` absolu à tout serveur utilisé pour upload, deploy ou
460
+ download.
461
+ 2. Pour chaque serveur SFTP, ajoutez un `hostKeySha256` vérifié hors bande.
462
+ `allowUnknownHostKey: true` doit rester une acceptation de risque temporaire
463
+ et explicite ; ne configurez pas les deux champs.
464
+ 3. Pour FTP/FTPS, préférez un chroot serveur dédié dont la racine visible est
465
+ `/` et posez `root` à `/`. Une sous-racine exige désormais
466
+ `allowUnsafeRemoteRoot: true` et reste vulnérable aux symlinks serveur.
467
+ 4. Traitez l'échec de `ftp_deploy` comme un déploiement partiel : examinez le
468
+ résumé et réconciliez l'arbre distant avant de relancer.
469
+ 5. Relancez `npm run setup` ou mettez à jour la commande MCP vers ce checkout,
470
+ puis lancez `npm run doctor` et un dry-run.
471
+
472
+ Le remplacement atomique des nouvelles configurations sensibles est une
473
+ condition vérifiée par les tests de publication ; un numéro de version seul
474
+ n'établit pas cette garantie. Consultez
475
+ [docs/RELEASE.fr.md](./docs/RELEASE.fr.md) pour la qualification et la publication.
476
+
477
+ ## Sécurité et limites
478
+
479
+ - La frontière FTP/FTPS la plus forte est l'isolation ou le chroot du compte
480
+ côté serveur. La normalisation client refuse les traversées évidentes, mais
481
+ FTP n'a pas de primitives `REALPATH`/`LSTAT` portables permettant de prouver
482
+ qu'un symlink serveur reste dans une sous-racine.
483
+ - SFTP vérifie le pin d'hôte et refuse les composants symboliques via
484
+ `realpath`/`lstat`. Un serveur contrôlé par un attaquant peut encore changer
485
+ son état entre vérification et opération.
486
+ - `readOnly` limite les écritures accidentelles via ce serveur MCP ; des droits
487
+ distants réellement en lecture seule restent plus forts.
488
+ - FTP, `insecureTLS`, `allowUnknownHostKey` et `allowUnsafeRemoteRoot` sont des
489
+ acceptations explicites de risque, pas des fonctions de sécurité.
490
+
491
+ Lisez le [modèle de sécurité complet](./docs/SECURITY-MODEL.fr.md) et la
492
+ [politique de signalement privé](./SECURITY.fr.md).
493
+
494
+ ## Développement
495
+
496
+ ```bash
497
+ npm test
498
+ npm run eval:scripted
499
+ node src/index.js --version
500
+ node src/index.js --help
501
+ ```
502
+
503
+ La suite de tests utilise des serveurs FTP et SFTP locaux, sans réseau externe.
504
+ Les contributions sont bienvenues ; voir
505
+ [CONTRIBUTING.fr.md](./CONTRIBUTING.fr.md). Les mainteneurs doivent suivre le
506
+ [guide de release](./docs/RELEASE.fr.md). Une évaluation agent reproductible, en
507
+ lecture seule et hébergée à l'extérieur, est décrite dans
508
+ [evaluations/README.fr.md](./evaluations/README.fr.md).
509
+
510
+ Depuis un checkout source, `npm run eval:scripted` exécute 43 cas dans les deux
511
+ langues avec un adaptateur mémoire et les vrais handlers MCP. Le
512
+ [guide de conformité scriptée](./docs/SCRIPTED-EVALUATIONS.fr.md) décrit rapports
513
+ et limites ; cette commande n’évalue pas un modèle.
514
+
515
+ ## Licence
516
+
517
+ MIT — voir le [texte anglais de référence](./LICENSE) et sa
518
+ [traduction française informative](./LICENSE.fr.md).