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.
- package/CHANGELOG.fr.md +468 -0
- package/CHANGELOG.md +415 -0
- package/CONTRIBUTING.fr.md +120 -0
- package/CONTRIBUTING.md +111 -0
- package/LICENSE +21 -0
- package/LICENSE.fr.md +26 -0
- package/README.fr.md +518 -0
- package/README.md +501 -2
- package/SECURITY.fr.md +99 -0
- package/SECURITY.md +94 -0
- package/docs/AGENT-PERFORMANCE.fr.md +144 -0
- package/docs/AGENT-PERFORMANCE.md +133 -0
- package/docs/ERROR-CONTRACT.fr.md +141 -0
- package/docs/ERROR-CONTRACT.md +137 -0
- package/docs/LANGUAGES.fr.md +68 -0
- package/docs/LANGUAGES.md +62 -0
- package/docs/RELEASE.fr.md +462 -0
- package/docs/RELEASE.md +435 -0
- package/docs/RESOURCE-BOUNDS.fr.md +144 -0
- package/docs/RESOURCE-BOUNDS.md +132 -0
- package/docs/SCRIPTED-EVALUATIONS.fr.md +190 -0
- package/docs/SCRIPTED-EVALUATIONS.md +181 -0
- package/docs/SECURITY-MODEL.fr.md +262 -0
- package/docs/SECURITY-MODEL.md +236 -0
- package/docs/STATE-STORAGE.fr.md +236 -0
- package/docs/STATE-STORAGE.md +231 -0
- package/docs/TRANSFERS.fr.md +140 -0
- package/docs/TRANSFERS.md +123 -0
- package/docs/WORKFLOW-MODEL.fr.md +63 -0
- package/docs/WORKFLOW-MODEL.md +62 -0
- package/evaluations/README.fr.md +95 -0
- package/evaluations/README.md +92 -0
- package/evaluations/fixture/README.txt +3 -0
- package/evaluations/fixture/catalog/alpha.txt +4 -0
- package/evaluations/fixture/catalog/bravo.txt +4 -0
- package/evaluations/fixture/catalog/charlie.txt +4 -0
- package/evaluations/fixture/catalog/delta.txt +4 -0
- package/evaluations/fixture/catalog/echo.txt +4 -0
- package/evaluations/fixture/catalog/foxtrot.txt +4 -0
- package/evaluations/fixture/reports/checks.txt +4 -0
- package/evaluations/fixture/reports/release.txt +3 -0
- package/evaluations/read-only.fr.xml +42 -0
- package/evaluations/read-only.xml +42 -0
- package/ftp-servers.example.json +27 -0
- package/install.cmd +29 -0
- package/install.sh +18 -0
- package/package.json +88 -4
- package/server.json +35 -0
- package/src/adapters/ftp.js +392 -0
- package/src/adapters/sftp.js +647 -0
- package/src/admission.js +15 -0
- package/src/atomic-write.js +131 -0
- package/src/clients.js +212 -0
- package/src/config.js +629 -0
- package/src/durable/confirmation.js +88 -0
- package/src/durable/engine.js +696 -0
- package/src/durable/plan.js +238 -0
- package/src/durable/schemas.js +206 -0
- package/src/durable/state.js +317 -0
- package/src/durable/status.js +175 -0
- package/src/durable-tools.js +94 -0
- package/src/errors.js +88 -0
- package/src/filezilla.js +260 -0
- package/src/i18n.js +58 -0
- package/src/index.js +175 -0
- package/src/local-path.js +130 -0
- package/src/locales/en.js +152 -0
- package/src/locales/errors.en.js +22 -0
- package/src/locales/errors.fr.js +22 -0
- package/src/locales/fr.js +152 -0
- package/src/locales/runtime.en.js +259 -0
- package/src/locales/runtime.fr.js +259 -0
- package/src/operations.js +276 -0
- package/src/redact.js +105 -0
- package/src/remote-path.js +101 -0
- package/src/scanner.js +103 -0
- package/src/setup.js +888 -0
- package/src/state/codec.mjs +103 -0
- package/src/state/index.mjs +1 -0
- package/src/state/io.mjs +173 -0
- package/src/state/records.mjs +60 -0
- package/src/state/store.mjs +360 -0
- package/src/state/writer.mjs +250 -0
- package/src/tool-registry.js +464 -0
- package/src/tools.js +1226 -0
- package/src/transfers.js +425 -0
- package/src/workflow/budget.mjs +83 -0
- package/src/workflow/events.mjs +199 -0
- package/src/workflow/model.mjs +179 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
**English** | [Français](./CHANGELOG.fr.md)
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file.
|
|
6
|
+
|
|
7
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
8
|
+
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
9
|
+
|
|
10
|
+
## [0.3.1] - 2026-10-17
|
|
11
|
+
|
|
12
|
+
This patch release is limited to release qualification and a supply-chain lock
|
|
13
|
+
refresh. It preserves the immutable v0.3.0 tag and GitHub source release. npm
|
|
14
|
+
and Official MCP Registry publication remain pending.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Release qualification now locks the optional transitive `nan` dependency to
|
|
19
|
+
2.29.0, including its reviewed registry URL and integrity, matching the
|
|
20
|
+
version resolved by a fresh installation. No runtime behavior or public API
|
|
21
|
+
changes.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Package, lockfile, MCP server and bilingual release metadata now consistently
|
|
26
|
+
target v0.3.1. The complete v0.3.0 history remains below.
|
|
27
|
+
|
|
28
|
+
## [0.3.0] - 2026-10-17
|
|
29
|
+
|
|
30
|
+
This minor release uses the separate GitHub source release channel; the published v0.2.0 tag and
|
|
31
|
+
release remain unchanged. npm and Official MCP Registry publication remain
|
|
32
|
+
pending. Install from source; no npm, `npx` or registry availability is claimed.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Optional durable deployment with `stateDir`: `ftp_plan_deploy`,
|
|
37
|
+
`ftp_apply_deploy`, `ftp_deploy_status`, and `ftp_rollback_deploy`. The
|
|
38
|
+
workflow uses official MCP `input_required` confirmation, sealed journals,
|
|
39
|
+
bounded verified backups, explicit resume, and conservative reconciliation.
|
|
40
|
+
Its guarantee is `observable_state_reconciled`, not multi-file atomicity or
|
|
41
|
+
exactly-once execution.
|
|
42
|
+
- Privacy-safe state format v2 stores a domain-salted local-root hash and strict
|
|
43
|
+
relative source paths, never the absolute local root. Apply revalidates local
|
|
44
|
+
identity before connection; rollback remains usable after local-root drift.
|
|
45
|
+
State v1 requires offline reinitialization.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Internal preparation is single-use, capped at 10 seconds without extending
|
|
50
|
+
the overall deadline, and retains admission until actual work and cleanup
|
|
51
|
+
settle. Prepared contexts are released once, including late completion after
|
|
52
|
+
cancellation. A cancelled or expired preparation never invokes the handler;
|
|
53
|
+
the preparation callback itself may act. No public MCP tool is added.
|
|
54
|
+
- Release qualification compares the complete expected package manifest,
|
|
55
|
+
authoritative source lock and all shipped source bytes. Unapproved dependency
|
|
56
|
+
modifiers and installation hooks are refused before consumer installation.
|
|
57
|
+
- Archive inspection reads and hashes compressed bytes once, performs strict
|
|
58
|
+
gzip decoding with a 32 MiB aggregate output cap, rejects nonzero data after
|
|
59
|
+
the consumed gzip boundary, and supplies the same decoded TAR to every tar
|
|
60
|
+
invocation. Terminal NUL padding is allowed; gzip/TAR member boundaries
|
|
61
|
+
cannot hide extra files from validation.
|
|
62
|
+
- npm and MCP workflows separate qualification without OIDC or secrets from
|
|
63
|
+
publication in a fresh checkout pinned to `github.sha`. npm transfers the
|
|
64
|
+
exact uploaded artifact ID and original inventory/integrity values; the
|
|
65
|
+
publication job validates those bindings before creating its local proof.
|
|
66
|
+
Dependency installation, tests, smoke checks and `--runtime` execute only
|
|
67
|
+
outside privileged publication jobs.
|
|
68
|
+
- Release metadata parsing accepts the supported npm pack JSON array/object
|
|
69
|
+
forms consistently in CI. Changelog dates must be valid calendar dates.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- The MCP runtime now uses the stable modular TypeScript SDK v2.3.1:
|
|
74
|
+
`@modelcontextprotocol/server` is the exact production pin, while the exact
|
|
75
|
+
client and raw-wire core packages remain development-only. The stdio entry
|
|
76
|
+
uses the SDK's `serveStdio` factory, negotiates revision `2026-07-28`, and
|
|
77
|
+
retains the legacy client path, including revision `2024-11-05`.
|
|
78
|
+
- The five direct production dependencies are pinned exactly; the sole
|
|
79
|
+
`package-lock.json` retains 35 reviewed non-root records (22 production and
|
|
80
|
+
13 development). No shrinkwrap is shipped.
|
|
81
|
+
- The builder produces a 90-file source installation archive with its lockfile,
|
|
82
|
+
distinct from the 89-file npm package without a lockfile. Proofs explicitly
|
|
83
|
+
bind the distribution, sources and integrity.
|
|
84
|
+
- Source installation uses `npm ci --omit=dev --ignore-scripts`; contributor
|
|
85
|
+
setup uses `npm ci --ignore-scripts`. Archive bytes may vary across systems.
|
|
86
|
+
The actual installed graph, including transitive dependencies and peers, is
|
|
87
|
+
compared with the original authority before publication.
|
|
88
|
+
- npm remains unqualified after ten observed changes in a real installation.
|
|
89
|
+
MCP qualification checks the actual registry download, then the privileged
|
|
90
|
+
job requires its original integrity before authentication.
|
|
91
|
+
|
|
92
|
+
- English/French installation and release documentation distinguishes GitHub
|
|
93
|
+
source releases from npm and Official MCP Registry availability.
|
|
94
|
+
|
|
95
|
+
Scripted tests are not an LLM benchmark, and this minor release makes no
|
|
96
|
+
enterprise-certification claim.
|
|
97
|
+
|
|
98
|
+
## [0.2.0] - 2026-09-09
|
|
99
|
+
|
|
100
|
+
The GitHub tag and release are cut from this commit. Publication to npm and to
|
|
101
|
+
the MCP registry is still pending, so `npx -y ftp-deploy-mcp` and registry-based
|
|
102
|
+
installation do not work yet; install from source. Package and server metadata
|
|
103
|
+
are aligned at 0.2.0. All changes below are relative to 0.1.0, the only version
|
|
104
|
+
ever released.
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
|
|
108
|
+
- Bilingual command line. `--lang en` and `--lang fr` (also `--lang=fr`) select
|
|
109
|
+
the language of general and subcommand help, `setup` prompts and choices,
|
|
110
|
+
connection-test labels, `doctor` diagnostics, `import-filezilla` warnings and
|
|
111
|
+
server startup messages. The new `FTP_MCP_LANG` environment variable sets the
|
|
112
|
+
same default, and the option takes precedence over it, including over an
|
|
113
|
+
invalid environment value. The option is read before the subcommand parser and
|
|
114
|
+
may appear before or after the subcommand. Only `en` and `fr` are accepted; an
|
|
115
|
+
invalid or incomplete option exits unsuccessfully before `setup` or
|
|
116
|
+
`import-filezilla` writes anything. OS locale variables such as `LANG` are
|
|
117
|
+
never consulted. See [languages](./docs/LANGUAGES.md).
|
|
118
|
+
- Localized MCP contracts. Tool titles, descriptions, input field descriptions,
|
|
119
|
+
business success text and error messages follow the selected language. The ten
|
|
120
|
+
tool names, structured result field names and public error codes are stable and
|
|
121
|
+
are not translated, and no tool argument selects a language.
|
|
122
|
+
- `setup` writes `FTP_MCP_LANG` into the MCP client entries it generates,
|
|
123
|
+
including `en`, so a configured server keeps its setup language after a
|
|
124
|
+
restart. The paste-ready Trae snippet carries the same setting.
|
|
125
|
+
- Structured error envelope on every tool error. Alongside the `isError` text,
|
|
126
|
+
results now carry `structuredContent.error` with `schema_version`, `code`,
|
|
127
|
+
`message`, `retryable`, a per-call `request_id` UUID, `next_action` and
|
|
128
|
+
`effects`. Upload, download and deployment errors can add a strict `partial`
|
|
129
|
+
block (`completed_files`, `completed_bytes`, `failed_files`, optional
|
|
130
|
+
`total_files`, and `final`). `request_id` is not a durable operation
|
|
131
|
+
identifier; there is no journal, rollback or recovery command. This release
|
|
132
|
+
returns `retryable: false` for every error and never retries an uncertain
|
|
133
|
+
mutation. See the [error contract](./docs/ERROR-CONTRACT.md).
|
|
134
|
+
- Six per-server configuration keys, each with an enforced default and maximum.
|
|
135
|
+
Tool arguments cannot override them, and values must be positive safe integers:
|
|
136
|
+
`operationTimeoutMs` (default 120000 ms, accepted range 100–3600000),
|
|
137
|
+
`maxTransferBytes` (default 268435456, maximum 1099511627776),
|
|
138
|
+
`maxDeployFiles` (default 10000, maximum 100000),
|
|
139
|
+
`maxDeployBytes` (default 1073741824, maximum 1099511627776),
|
|
140
|
+
`maxScanEntries` (default 100000, maximum 1000000) and
|
|
141
|
+
`maxScanDepth` (default 64, maximum 256). These defaults apply to servers that
|
|
142
|
+
do not set them, so a deployment that succeeded on 0.1.0 can now be refused
|
|
143
|
+
with `TRANSFER_LIMIT` or `SCAN_LIMIT` before any connection is opened.
|
|
144
|
+
**BREAKING — `operationTimeoutMs` also introduces a deadline 0.1.0 never
|
|
145
|
+
had:** every tool call now aborts with `TIMEOUT` after 120000 ms by default,
|
|
146
|
+
and unlike the other limits it fires mid-flight rather than refusing up
|
|
147
|
+
front, so a large or slow `ftp_deploy` that ran to completion on 0.1.0 can
|
|
148
|
+
stop part-way with files already promoted and no rollback. Raise
|
|
149
|
+
`operationTimeoutMs` (up to 3600000) for slow links. See
|
|
150
|
+
[verified transfers](./docs/TRANSFERS.md) and
|
|
151
|
+
[resource limits](./docs/RESOURCE-BOUNDS.md).
|
|
152
|
+
- Process-wide admission control. One Node isolate admits at most 64 concurrent
|
|
153
|
+
tool calls; the 65th returns the new `CAPACITY_LIMIT` with `effects:none`,
|
|
154
|
+
`retryable:false` and `next_action:retry`. This is a concurrency cap, not a
|
|
155
|
+
lifetime quota: a slot is released when its worker and cleanup actually settle,
|
|
156
|
+
including after cancellation or timeout, and there is no queue or automatic
|
|
157
|
+
retry. Admission happens after schema validation and before preparation.
|
|
158
|
+
- MCP cancellation and per-call deadlines. A peer `notifications/cancelled`
|
|
159
|
+
aborts the operation and the SDK suppresses its result, so clients must not
|
|
160
|
+
expect a delivered `CANCELLED` envelope; the separate internal deadline
|
|
161
|
+
returns `TIMEOUT`. Cancellation and expiry stop later stages and close the
|
|
162
|
+
transport, but do not undo effects already accepted by the server. A public
|
|
163
|
+
transport decorator corrects the installed SDK's cancellation gap for the
|
|
164
|
+
numeric correlation ID `0` and the empty string `""`; other IDs, including the
|
|
165
|
+
string `"0"`, keep native SDK behaviour.
|
|
166
|
+
- Serialized mutations. Writing tools take a FIFO lock on the remote endpoint
|
|
167
|
+
(protocol, host, port, user) and `ftp_download` takes one on the canonical
|
|
168
|
+
local destination, so two calls cannot interleave writes on the same target.
|
|
169
|
+
Locks are held until the underlying worker actually settles, not until the
|
|
170
|
+
response is sent, and they coordinate only within one Node.js process.
|
|
171
|
+
- Per-server `localRoot` boundary for `ftp_upload`, `ftp_deploy`, and
|
|
172
|
+
`ftp_download`. The root must be absolute (with `~` expansion supported);
|
|
173
|
+
traversal and local symlink/junction escapes are refused.
|
|
174
|
+
- SFTP host-key pinning through `hostKeySha256`, accepting one SHA-256
|
|
175
|
+
fingerprint or a non-empty array for controlled key rotation.
|
|
176
|
+
- Explicit `allowUnknownHostKey` override for operators who temporarily accept
|
|
177
|
+
an unverified SFTP server identity.
|
|
178
|
+
- Explicit `allowUnsafeRemoteRoot` override for FTP/FTPS operators who accept
|
|
179
|
+
the unresolved symlink risk of a client-side sub-root.
|
|
180
|
+
- MCP output schemas and successful structured responses for every tool except
|
|
181
|
+
the intentionally text-only `ftp_read`, plus annotations for all ten tools.
|
|
182
|
+
- Bilingual documentation set, each page in English and French:
|
|
183
|
+
[security model](./docs/SECURITY-MODEL.md),
|
|
184
|
+
[release process](./docs/RELEASE.md),
|
|
185
|
+
[error contract](./docs/ERROR-CONTRACT.md),
|
|
186
|
+
[languages](./docs/LANGUAGES.md),
|
|
187
|
+
[verified transfers](./docs/TRANSFERS.md),
|
|
188
|
+
[resource limits](./docs/RESOURCE-BOUNDS.md),
|
|
189
|
+
[state storage](./docs/STATE-STORAGE.md),
|
|
190
|
+
[workflow model](./docs/WORKFLOW-MODEL.md) and
|
|
191
|
+
[scripted MCP conformance](./docs/SCRIPTED-EVALUATIONS.md). `CONTRIBUTING`,
|
|
192
|
+
`SECURITY`, `LICENSE` and this changelog gain French counterparts, joining the
|
|
193
|
+
`README` pair that already shipped in 0.1.0; both `README` languages were
|
|
194
|
+
rewritten for this release.
|
|
195
|
+
- A bilingual interactive HTML guide under `site/`, generated from
|
|
196
|
+
`site/project-data.json` and `site/i18n.json` and verified in CI by
|
|
197
|
+
`scripts/build-guide.mjs --check`. It lives in the repository only and is
|
|
198
|
+
excluded from the npm package.
|
|
199
|
+
- A reproducible, external read-only agent evaluation fixture and 10-question
|
|
200
|
+
MCP evaluation set, now in English (`evaluations/read-only.xml`) and French
|
|
201
|
+
(`evaluations/read-only.fr.xml`), plus a separate scripted conformance runner
|
|
202
|
+
of 43 scenarios executed in both languages against the real MCP SDK client and
|
|
203
|
+
in-memory transport (`npm run eval:scripted`). The runner is repository
|
|
204
|
+
tooling, is not an LLM benchmark, and is excluded from the npm package. See
|
|
205
|
+
[scripted MCP conformance](./docs/SCRIPTED-EVALUATIONS.md).
|
|
206
|
+
- Internal, inert libraries `src/state/` and `src/workflow/`. They ship inside
|
|
207
|
+
the package because it publishes `src`, but they expose no MCP tool, read no
|
|
208
|
+
configuration, create no state directory and are not imported by the running
|
|
209
|
+
server. They deliver no deployment workflow, rollback or recovery in this
|
|
210
|
+
release; both [state storage](./docs/STATE-STORAGE.md) and the
|
|
211
|
+
[workflow model](./docs/WORKFLOW-MODEL.md) state this explicitly.
|
|
212
|
+
- Contributor-facing npm scripts: `test:transports`, `test:contract`,
|
|
213
|
+
`test:bounds`, `test:state`, `test:workflow`, `test:eval-runner` and
|
|
214
|
+
`eval:scripted`. CI additionally runs `scripts/check-docs.mjs` for bilingual
|
|
215
|
+
documentation and `test/release-gates.js`.
|
|
216
|
+
- `server.json` MCP registry metadata, declaring the `FTP_MCP_CONFIG` and
|
|
217
|
+
`FTP_MCP_LANG` environment variables and a stdio transport.
|
|
218
|
+
- A repository `Dockerfile` and `.dockerignore` building a `node:24-alpine`
|
|
219
|
+
image whose entrypoint is the stdio server; mount a configuration file and
|
|
220
|
+
point `FTP_MCP_CONFIG` at it. No image is published, and neither file is
|
|
221
|
+
included in the npm package.
|
|
222
|
+
|
|
223
|
+
### Changed
|
|
224
|
+
|
|
225
|
+
- **BREAKING — Node.js 18, 19, 20 and 21 are no longer supported.**
|
|
226
|
+
`engines.node` moves from `>=18` to `>=22`. CI qualifies Node 22 and 24 on
|
|
227
|
+
Linux, Windows and macOS.
|
|
228
|
+
- **BREAKING — an explicit configuration selector now fails closed.** When
|
|
229
|
+
`--config <path>` or `FTP_MCP_CONFIG` is present, that single path is
|
|
230
|
+
authoritative: it must exist, be a regular file and load successfully, and no
|
|
231
|
+
other candidate is attempted. `--config` takes priority over
|
|
232
|
+
`FTP_MCP_CONFIG`, and an empty explicit value is rejected. Only when neither
|
|
233
|
+
is set does discovery still try `./ftp-servers.json` then
|
|
234
|
+
`~/.ftp-mcp/servers.json`. In 0.1.0 both selectors were merely the first
|
|
235
|
+
entries of a fallback list, so a missing or unreadable explicit path silently
|
|
236
|
+
fell through to another file. The server still starts; every tool that needs
|
|
237
|
+
the configuration now fails with `CONFIG_INVALID` instead of operating on an
|
|
238
|
+
unintended configuration, and `ftp_list_servers` returns `status: "invalid"`
|
|
239
|
+
with the loader diagnostic.
|
|
240
|
+
- One rejected server entry no longer disables the whole configuration. Entries
|
|
241
|
+
are validated individually: valid servers stay usable, and each invalid one is
|
|
242
|
+
reported by name with its reason through `ftp_list_servers` (`status`,
|
|
243
|
+
`valid_count`, `invalid_count` and a bounded `errors` list). Naming a rejected
|
|
244
|
+
entry returns that entry's `CONFIG_INVALID`, an unknown name
|
|
245
|
+
returns `SERVER_UNKNOWN`, and omitting `server` with several valid candidates
|
|
246
|
+
and no `defaultServer` returns `SERVER_REQUIRED`. In 0.1.0 the first invalid
|
|
247
|
+
entry made the entire file unusable and every tool call failed. Envelope
|
|
248
|
+
problems — no `servers` object, an empty one, an unknown `defaultServer`, an
|
|
249
|
+
unset `${ENV:VAR}` — still reject the whole file, as does a file in which
|
|
250
|
+
every entry is invalid.
|
|
251
|
+
- **BREAKING — `localRoot` is now required** by `ftp_upload`, `ftp_deploy` and
|
|
252
|
+
`ftp_download`, **and relative tool paths now resolve against it instead of
|
|
253
|
+
the server process's working directory.** A server entry without an absolute
|
|
254
|
+
`localRoot` refuses those three tools with `CONFIG_INVALID`. In 0.1.0
|
|
255
|
+
`local_path` and `local_dir` resolved against `process.cwd()`, so an unchanged
|
|
256
|
+
call such as `ftp_deploy {"local_dir":"dist"}` now reads `<localRoot>/dist`
|
|
257
|
+
instead of `<cwd>/dist` — it can silently select a different directory, or
|
|
258
|
+
fail with `NOT_FOUND` or `PATH_REJECTED` when the old target sits outside the
|
|
259
|
+
root. Absolute paths keep their meaning and must still resolve inside
|
|
260
|
+
`localRoot`. `ftp_list_servers` reports each server's `localRoot` status.
|
|
261
|
+
- Tool errors are no longer text-only. Every error result now carries the
|
|
262
|
+
structured `{error}` envelope described above, and the nine tools with an
|
|
263
|
+
output schema publish a JSON Schema draft-07 `oneOf` of their success object
|
|
264
|
+
and that envelope. `ftp_read` keeps text-only success and no output schema;
|
|
265
|
+
its errors still use the same internally validated envelope. Existing text
|
|
266
|
+
responses remain available alongside structured successful responses, and
|
|
267
|
+
`ftp_deploy` still reports bounded samples rather than exhaustive file lists.
|
|
268
|
+
- `ftp_upload`, `ftp_deploy` and `ftp_download` now verify every file before
|
|
269
|
+
promoting it. Uploads hash the local source with SHA256, write to an
|
|
270
|
+
unpredictable sibling named `.ftp-mcp-<random>.tmp`, read that temporary back,
|
|
271
|
+
compare byte count and digest, then promote with one rename. On failure the
|
|
272
|
+
server never deletes the final destination to make promotion succeed and never
|
|
273
|
+
falls back to a direct overwrite; it deletes only its own temporary, and a
|
|
274
|
+
cleanup failure adds a bounded warning that a temporary may remain. Downloads
|
|
275
|
+
read a bounded remote SHA256 expectation first, then promote by same-directory
|
|
276
|
+
hard link with `overwrite:false` (the default) or by rename with
|
|
277
|
+
`overwrite:true`. The basename pattern `.ftp-mcp-*.tmp` is reserved and always
|
|
278
|
+
excluded from `ftp_deploy`, even when an explicit `include` matches it. This
|
|
279
|
+
adds network traffic and latency, does not make a multi-file deployment
|
|
280
|
+
atomic, and does not promise universal atomic replacement: FTP and SFTP rename
|
|
281
|
+
behaviour depends on the server and filesystem. SFTP records the temporary's
|
|
282
|
+
server-assigned mode, restricts it to 0600 while writing, and before promotion
|
|
283
|
+
restores the existing destination's permission bits (0777 mask), or that
|
|
284
|
+
recorded creation mode for a new file; a required stat or chmod failure
|
|
285
|
+
prevents promotion. FTP/FTPS has no portable permission-preservation mechanism
|
|
286
|
+
here, so replacing an existing remote file can reset its permissions to the
|
|
287
|
+
server's creation defaults. Locally, `ftp_download` copies an existing
|
|
288
|
+
destination's 0777 bits onto its temporary, but a **new** local file is now
|
|
289
|
+
created with mode 0600 rather than 0.1.0's process-umask default, and
|
|
290
|
+
promotion with the default `overwrite:false` needs hard-link support in the
|
|
291
|
+
destination directory and fails closed without it. See
|
|
292
|
+
[verified transfers](./docs/TRANSFERS.md).
|
|
293
|
+
- Deployment selection is now bounded and asynchronous. `maxScanEntries` and
|
|
294
|
+
`maxScanDepth` cap visited entries and directory depth; exceeding either
|
|
295
|
+
refuses the complete selection with `SCAN_LIMIT` (`effects:none`,
|
|
296
|
+
`retryable:false`, `next_action:fix_input`) before any remote connection, for
|
|
297
|
+
dry runs as well as real deploys. See
|
|
298
|
+
[resource limits](./docs/RESOURCE-BOUNDS.md).
|
|
299
|
+
- **Deployment selection can now include files it previously skipped.** Only the
|
|
300
|
+
built-in `node_modules`, `.git` and `.ftp-mcp` directory names prune
|
|
301
|
+
traversal. Custom `exclude` patterns and `include` patterns no longer prune
|
|
302
|
+
directories; they keep their existing per-file matching rules. This removes a
|
|
303
|
+
former directory-probe false positive in which, for example,
|
|
304
|
+
`exclude: ["**/__ftp_deploy_probe__"]` also hid `docs/wanted.txt`. Review a
|
|
305
|
+
dry run after upgrading if you rely on exclusion patterns.
|
|
306
|
+
- **BREAKING — plain FTP, and FTPS with `insecureTLS: true`, are now refused.**
|
|
307
|
+
0.1.0 had no insecure-transport gate and connected to both without objection.
|
|
308
|
+
0.2.0 raises `TRANSPORT_POLICY` before any network I/O unless the server entry
|
|
309
|
+
sets `allowInsecure: true`, so every 0.1.0 `"protocol": "ftp"` entry — the
|
|
310
|
+
default, namesake protocol of this package — stops connecting until that flag
|
|
311
|
+
is added.
|
|
312
|
+
- **BREAKING — SFTP connections without `hostKeySha256` are refused** before
|
|
313
|
+
authentication, with `HOST_KEY_REJECTED`, unless `allowUnknownHostKey: true`
|
|
314
|
+
is explicitly configured. 0.1.0 performed no host-key verification and had no
|
|
315
|
+
such field, so every existing SFTP server entry stops connecting until one of
|
|
316
|
+
the two keys is added.
|
|
317
|
+
- **BREAKING — FTP/FTPS connections whose `root` is not `/` are refused**
|
|
318
|
+
unless `allowUnsafeRemoteRoot: true` is explicitly configured;
|
|
319
|
+
`REMOTE_ROOT_REJECTED` is raised before any network I/O. 0.1.0 accepted any
|
|
320
|
+
`root` and its own README recommended exactly this pattern
|
|
321
|
+
(`"root": "/var/www/site"`), so those entries stop connecting until the flag
|
|
322
|
+
is added. The recommended boundary is now a dedicated server-side chrooted
|
|
323
|
+
account with `root: "/"`.
|
|
324
|
+
- `ftp_deploy` returns an MCP error when any transfer fails and includes a
|
|
325
|
+
partial-deployment summary, now also as structured `partial` counters. Earlier
|
|
326
|
+
successful transfers are not rolled back.
|
|
327
|
+
- `ftp_list` no longer returns every directory entry by default. It returns the
|
|
328
|
+
first 50 entries and pagination metadata; callers can select an offset and a
|
|
329
|
+
page size from 1 through 200.
|
|
330
|
+
- Tool results are bounded to 25000 bytes of UTF-8 `JSON.stringify` covering
|
|
331
|
+
both text and structured data after redaction. Oversized results shrink their
|
|
332
|
+
bounded samples and rebuild pagination first, then truncate the largest text
|
|
333
|
+
body with a `… [output truncated]` marker, and fall back to `OUTPUT_LIMIT`
|
|
334
|
+
only when nothing can be shrunk — while preserving the request UUID, effects
|
|
335
|
+
and observed partial counters. This cap sits below `ftp_read`'s unchanged
|
|
336
|
+
`max_bytes` window (default 262144, hard max 1048576): a read that returned
|
|
337
|
+
256 KB of content on 0.1.0 now returns roughly 25 KB, marked as truncated, in
|
|
338
|
+
a successful result.
|
|
339
|
+
- Boolean safety flags and SFTP fingerprint formats are validated per server.
|
|
340
|
+
- `setup` surfaces active insecure-transport acknowledgments; `doctor` surfaces
|
|
341
|
+
active insecure-transport, unknown-host-key and unsafe-remote-root
|
|
342
|
+
acknowledgments.
|
|
343
|
+
- Documentation now distinguishes the working source install from future
|
|
344
|
+
`npx` and MCP registry installation.
|
|
345
|
+
- The published package now also ships `docs/`, `evaluations/`, `server.json`,
|
|
346
|
+
`CONTRIBUTING.md`, `CONTRIBUTING.fr.md`, `SECURITY.md`, `SECURITY.fr.md`,
|
|
347
|
+
`CHANGELOG.fr.md` and `LICENSE.fr.md`. The package and `server.json`
|
|
348
|
+
descriptions are now bilingual and describe local confinement and verified
|
|
349
|
+
staging.
|
|
350
|
+
- New runtime dependency `zod-to-json-schema`, used to publish the tool input
|
|
351
|
+
and output JSON Schemas.
|
|
352
|
+
- The local FTP test server now uses the `@electerm/ftp-srv` development
|
|
353
|
+
dependency.
|
|
354
|
+
|
|
355
|
+
### Removed
|
|
356
|
+
|
|
357
|
+
- `assets/banner.svg`, `assets/banner.png`, `assets/demo.svg` and
|
|
358
|
+
`assets/diagram.svg`. The README banners are now `assets/banner-en.png` and
|
|
359
|
+
`assets/banner-fr.png`, with their generation prompts and provenance recorded
|
|
360
|
+
under `assets/provenance/`.
|
|
361
|
+
- The `ftp-srv` development dependency, replaced as noted above.
|
|
362
|
+
|
|
363
|
+
### Fixed
|
|
364
|
+
|
|
365
|
+
- Interactive manual server entry in `setup` no longer writes the wizard result
|
|
366
|
+
through a missing property.
|
|
367
|
+
- Case variants of protocol names can no longer bypass insecure-transport
|
|
368
|
+
checks on setup and diagnostic paths.
|
|
369
|
+
- Tool errors retain applicable security warnings, including failures after an
|
|
370
|
+
insecure connection may already have exposed credentials.
|
|
371
|
+
|
|
372
|
+
### Security
|
|
373
|
+
|
|
374
|
+
- Insecure transports are refused by default; see the **BREAKING** entry under
|
|
375
|
+
*Changed* for the new `allowInsecure` gate and its upgrade impact. Warnings
|
|
376
|
+
are attached to discovery, diagnostics, successes, and failures involving
|
|
377
|
+
accepted insecure transports.
|
|
378
|
+
- SFTP resolves the configured remote root and uses realpath/lstat checks to
|
|
379
|
+
refuse symbolic-link components and resolved paths outside that root. A
|
|
380
|
+
malicious server can still race state between validation and operation. An
|
|
381
|
+
SFTP connection also pins its initial canonical root; a known root change
|
|
382
|
+
returns `TARGET_CHANGED` and refuses to rebase an owned temporary.
|
|
383
|
+
- FTP/FTPS no longer describe lexical path normalization as a trustworthy
|
|
384
|
+
anti-symlink jail; server-side account isolation is the real boundary.
|
|
385
|
+
- Local sources and download destinations are constrained under `localRoot`.
|
|
386
|
+
- Non-interactive setup fails closed: it reports insecure transports but never
|
|
387
|
+
grants an `allowInsecure` exception automatically.
|
|
388
|
+
- Error confidentiality is enforced at the result boundary. Error objects,
|
|
389
|
+
causes, stacks, credentials and raw arguments are never serialized; secrets
|
|
390
|
+
are masked in free text; configuration credentials are collected before
|
|
391
|
+
validation, including values from rejected entries and resolved `${ENV:VAR}`
|
|
392
|
+
placeholders, so loader diagnostics use the same mask. Malformed configuration
|
|
393
|
+
JSON yields a generic syntax diagnostic with no parser excerpt, and rejected
|
|
394
|
+
FileZilla blocks are identified by numeric index without echoing untrusted
|
|
395
|
+
names or protocol fields. Remote strings such as `Page:` and `SECURITY
|
|
396
|
+
WARNING` cannot impersonate the trusted notice rendering.
|
|
397
|
+
- The committed lockfile resolves the MCP SDK's transitive `hono` dependency to
|
|
398
|
+
the patched 4.13.5.
|
|
399
|
+
|
|
400
|
+
## [0.1.0] - 2026-07-20
|
|
401
|
+
|
|
402
|
+
### Added
|
|
403
|
+
|
|
404
|
+
- Ten MCP tools: `ftp_list_servers`, `ftp_test`, `ftp_list`, `ftp_read`,
|
|
405
|
+
`ftp_upload`, `ftp_deploy`, `ftp_download`, `ftp_mkdir`, `ftp_rename`, and
|
|
406
|
+
`ftp_delete`.
|
|
407
|
+
- Multi-server configuration across FTP, FTPS, and SFTP.
|
|
408
|
+
- Recursive directory deploy with gitignore-like excludes and dry-run.
|
|
409
|
+
- Per-server remote `root` path normalization and `readOnly` mode.
|
|
410
|
+
- `${ENV:VAR}` placeholders for configuration secrets.
|
|
411
|
+
- FileZilla import, including implicit FTPS sites.
|
|
412
|
+
- Setup wizard with MCP client configuration backups.
|
|
413
|
+
- Read-only `doctor` diagnostic and source installers.
|
|
414
|
+
- English and French documentation.
|
|
415
|
+
- End-to-end tests against local FTP and SFTP servers.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Contribuer à ftp-deploy-mcp
|
|
2
|
+
|
|
3
|
+
[English](./CONTRIBUTING.md) | **Français**
|
|
4
|
+
|
|
5
|
+
Merci d'envisager une contribution. Ce projet reste volontairement compact et
|
|
6
|
+
limite ses dépendances ; lisez les principes ci-dessous avant d'ouvrir une PR.
|
|
7
|
+
|
|
8
|
+
Le runtime MCP prend en charge Node.js >=22. L'outillage de publication exige **Node.js 24.20.0 exactement** : création et inspection des archives, inventaires source, contrôles du graphe installé, vérification du registre et `npm run test:release` refusent les autres versions avant ces opérations. Utilisez la distribution Node qualifiée, avec son npm fourni, et consignez les versions Node/libuv/npm/tar avec `node scripts/release-toolchain.mjs`. La qualification du consommateur peut toujours exécuter le serveur MCP avec Node 22 et appeler séparément les outils externes de publication avec Node 24.20.0.
|
|
9
|
+
|
|
10
|
+
La CI conserve les neuf jobs runtime (Node 22/24/26 sur Linux, macOS et Windows). La suite complète de publication s'exécute séparément sur les trois systèmes avec Node 24.20.0. macOS comporte trois passes complètes prédéfinies ; tout échec fait échouer le job. Ces passes de qualification sont fixes, sans relance après échec, cas ignoré ni augmentation des limites d'archive. Les workflows supply-chain et de publication npm/MCP utilisent la même version Node exacte.
|
|
11
|
+
|
|
12
|
+
## Environnement de développement
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git clone https://github.com/alebgl77/ftp-deploy-mcp.git
|
|
16
|
+
cd ftp-deploy-mcp
|
|
17
|
+
npm ci --ignore-scripts
|
|
18
|
+
npm test
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`npm test` est le principal contrôle du code. Il démarre de vrais serveurs FTP
|
|
22
|
+
et SFTP locaux sur des ports de boucle locale et exécute la suite de bout en
|
|
23
|
+
bout contre eux : aucun accès réseau externe n'est requis ni utilisé. Pour
|
|
24
|
+
les modifications de documentation seules, vérifiez aussi que les exemples
|
|
25
|
+
JSON modifiés s'analysent, que les liens Markdown relatifs existent, puis
|
|
26
|
+
exécutez `git diff --check`.
|
|
27
|
+
|
|
28
|
+
## Mettre à jour le graphe de dépendances
|
|
29
|
+
|
|
30
|
+
`package-lock.json` est l'unique fichier de verrouillage de référence ;
|
|
31
|
+
n'ajoutez pas de `npm-shrinkwrap.json` parallèle. Les six dépendances directes de
|
|
32
|
+
production sont épinglées à une version exacte. L'installation courante utilise
|
|
33
|
+
`npm ci --ignore-scripts` et ne doit pas réécrire le graphe.
|
|
34
|
+
|
|
35
|
+
Pour une mise à jour voulue, modifiez uniquement les versions exactes approuvées,
|
|
36
|
+
régénérez le verrouillage source avec les scripts de cycle de vie désactivés et la version
|
|
37
|
+
npm qualifiée, puis consignez cette version npm. Examinez toute entrée du graphe
|
|
38
|
+
ajoutée, supprimée ou modifiée, notamment `resolved`, `integrity`, les contraintes
|
|
39
|
+
facultatives/de plateforme et les hooks d'installation. N'acceptez pas de
|
|
40
|
+
modifications sans rapport issues d'une mise à jour ou d'une correction d'audit
|
|
41
|
+
automatique. Exécutez une installation propre, les tests concernés, l'audit des
|
|
42
|
+
dépendances et les contrôles de l'archive exacte et du consommateur isolé du
|
|
43
|
+
[guide de publication](./docs/RELEASE.fr.md). Présentez ensemble les modifications
|
|
44
|
+
des sources, du manifeste et du verrouillage source pour la revue.
|
|
45
|
+
|
|
46
|
+
La distribution d'installation source contient 90 fichiers, dont ce verrouillage. Le paquet npm distinct contient 89 fichiers sans verrouillage et reste non qualifié après dix dérives observées dans une installation réelle. Les contrôles du graphe installé comparent aussi les dépendances transitives et les peers à l'inventaire source original ; tout écart bloque la publication npm/MCP.
|
|
47
|
+
|
|
48
|
+
## Principes
|
|
49
|
+
|
|
50
|
+
- **JavaScript ESM simple.** Pas de TypeScript, d'outil de regroupement ni
|
|
51
|
+
d'étape de compilation. Le contenu de `src/` est exécuté tel quel.
|
|
52
|
+
- **Aucune nouvelle dépendance d'exécution sans discussion.** Ouvrez d'abord
|
|
53
|
+
une issue si vous en jugez une nécessaire : les `dependencies` de
|
|
54
|
+
`package.json` sont volontairement limitées.
|
|
55
|
+
- **Chaque fonctionnalité s'accompagne d'assertions de test.** Les nouveaux
|
|
56
|
+
outils, options ou comportements ne sont terminés qu'une fois couverts
|
|
57
|
+
dans `test/smoke.test.js`.
|
|
58
|
+
- **Les garanties de sécurité reflètent les limites des protocoles.** Les
|
|
59
|
+
sous-racines FTP/FTPS côté client ne sont pas présentées comme un confinement
|
|
60
|
+
sûr contre les liens symboliques ; le compte/chroot dédié côté serveur est
|
|
61
|
+
la frontière. Les protections SFTP doivent documenter la course résiduelle
|
|
62
|
+
côté serveur.
|
|
63
|
+
- **Disponibilité des sources et disponibilité d'une publication sont
|
|
64
|
+
distinctes.** N'annoncez pas l'installation par `npx` ou le registre MCP
|
|
65
|
+
avant que l'artefact correspondant soit public et vérifié indépendamment.
|
|
66
|
+
- **En mode serveur, `stdout` est réservé à JSON-RPC.** N'utilisez jamais
|
|
67
|
+
`console.log` dans le chemin d'exécution du serveur MCP : toute sortie
|
|
68
|
+
standard est un message du protocole. Les diagnostics et les messages
|
|
69
|
+
destinés aux humains vont sur `stderr` ou dans les commandes `doctor`/`setup`
|
|
70
|
+
(hors mode serveur).
|
|
71
|
+
|
|
72
|
+
## Exécuter une partie de la suite
|
|
73
|
+
|
|
74
|
+
Exécutez la suite principale :
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node test/smoke.test.js
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Exécutez séparément la qualification des transports et les contrôles de publication :
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
node --test test/transport-qualification.js
|
|
84
|
+
npm run test:release
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`npm test` exécute la suite principale et la qualification des transports.
|
|
88
|
+
Avant d'ouvrir une PR, lancez les deux ainsi que les contrôles de publication
|
|
89
|
+
concernés par le changement ; gardez les assertions existantes activées.
|
|
90
|
+
|
|
91
|
+
## Liste de contrôle d'une PR
|
|
92
|
+
|
|
93
|
+
- [ ] `npm test` passe (utilisez le total actuel ; ne le figez pas dans la documentation).
|
|
94
|
+
- [ ] Aucune nouvelle dépendance d'exécution, ou elle a d'abord été discutée dans une issue.
|
|
95
|
+
- [ ] Les comportements ajoutés ou modifiés ont des assertions de test correspondantes.
|
|
96
|
+
- [ ] `README.md` (anglais) et `README.fr.md` (français) sont mis à jour si le
|
|
97
|
+
comportement visible par l'utilisateur a changé.
|
|
98
|
+
- [ ] Les nouveaux exemples de configuration sont en JSON strict et les liens
|
|
99
|
+
Markdown relatifs pointent vers des cibles existantes.
|
|
100
|
+
- [ ] Les modifications sensibles pour la sécurité figurent dans
|
|
101
|
+
[docs/SECURITY-MODEL.fr.md](./docs/SECURITY-MODEL.fr.md).
|
|
102
|
+
|
|
103
|
+
## Publication (mainteneurs)
|
|
104
|
+
|
|
105
|
+
N'improvisez pas la première publication à partir de cette courte section.
|
|
106
|
+
Suivez le [guide de publication](./docs/RELEASE.fr.md), qui couvre :
|
|
107
|
+
|
|
108
|
+
- la concordance des versions du paquet, du verrouillage source, du serveur et du tag,
|
|
109
|
+
puis la vérification distincte des versions npm et du registre MCP officiel
|
|
110
|
+
après publication ;
|
|
111
|
+
- la validation d'une archive propre et les tests de bout en bout ;
|
|
112
|
+
- npm Trusted Publishing, la provenance et le recours à un `NPM_TOKEN` de
|
|
113
|
+
courte durée uniquement si l'amorçage de la première publication l'exige ;
|
|
114
|
+
- les opérations manuelles de propriété et de publication sur le registre MCP ;
|
|
115
|
+
- les vérifications après publication et le rétablissement par une nouvelle
|
|
116
|
+
version corrective.
|
|
117
|
+
|
|
118
|
+
Le paquet npm et l'entrée du registre MCP ne sont disponibles qu'une fois
|
|
119
|
+
tous les prérequis manuels applicables et toutes les vérifications de ce
|
|
120
|
+
guide satisfaits.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Contributing to ftp-deploy-mcp
|
|
2
|
+
|
|
3
|
+
**English** | [Français](./CONTRIBUTING.fr.md)
|
|
4
|
+
|
|
5
|
+
Thanks for considering a contribution. This project intentionally stays small and
|
|
6
|
+
dependency-light — please read the principles below before opening a PR.
|
|
7
|
+
|
|
8
|
+
The MCP runtime supports Node.js >=22. Release tooling requires **Node.js 24.20.0 exactly**: archive creation and inspection, source inventories, installed-graph checks, registry verification and `npm run test:release` reject other versions before performing those operations. Use the qualified Node distribution, including its bundled npm, and record Node/libuv/npm/tar versions with `node scripts/release-toolchain.mjs`. Consumer runtime qualification may still execute the MCP server with Node 22 while invoking the external release tools separately with Node 24.20.0.
|
|
9
|
+
|
|
10
|
+
CI retains all nine runtime jobs (Node 22/24/26 on Linux, macOS and Windows). The complete release suite runs separately on all three operating systems with Node 24.20.0. macOS has three predefined full passes; any failed pass fails the job. These are fixed qualification passes, with no failure retries, skipped cases or increased archive limits. Supply-chain and npm/MCP publication workflows use the same exact release Node version.
|
|
11
|
+
|
|
12
|
+
## Dev setup
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git clone https://github.com/alebgl77/ftp-deploy-mcp.git
|
|
16
|
+
cd ftp-deploy-mcp
|
|
17
|
+
npm ci --ignore-scripts
|
|
18
|
+
npm test
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`npm test` is the main code gate. It spins up real local FTP and SFTP servers
|
|
22
|
+
on loopback ports and runs the full e2e suite against them — no external
|
|
23
|
+
network access is required or used. Documentation-only changes should also
|
|
24
|
+
parse changed JSON examples, check relative Markdown links, and run
|
|
25
|
+
`git diff --check`.
|
|
26
|
+
|
|
27
|
+
## Updating the dependency graph
|
|
28
|
+
|
|
29
|
+
`package-lock.json` is the only authoritative lockfile; do not add a parallel
|
|
30
|
+
`npm-shrinkwrap.json`. The six direct production dependencies are exact pins.
|
|
31
|
+
Routine setup uses `npm ci --ignore-scripts` and must not rewrite the graph.
|
|
32
|
+
|
|
33
|
+
For an intentional update, change only the approved exact versions, regenerate
|
|
34
|
+
the source lockfile with lifecycle scripts disabled and the qualified npm version,
|
|
35
|
+
and record that npm version. Review every added, removed or changed graph entry,
|
|
36
|
+
including `resolved`, `integrity`, optional/platform constraints and install
|
|
37
|
+
hooks. Do not accept unrelated graph changes from an automatic update or audit
|
|
38
|
+
fix. Run a clean install, the affected tests, the dependency audit and exact
|
|
39
|
+
tarball/isolated-consumer checks in the [release guide](./docs/RELEASE.md).
|
|
40
|
+
Keep the source, manifest and lockfile changes together for review.
|
|
41
|
+
|
|
42
|
+
The source installation distribution contains 90 files, including this lockfile. The separate npm package contains 89 files without a lockfile and remains unqualified after ten observed changes in a real installation. Installed-graph checks compare transitive dependencies and peers against the original source inventory; any difference blocks npm/MCP publication.
|
|
43
|
+
|
|
44
|
+
## Principles
|
|
45
|
+
|
|
46
|
+
- **Plain ESM JavaScript.** No TypeScript, no bundler, no build step. What's in
|
|
47
|
+
`src/` is what runs.
|
|
48
|
+
- **No new runtime dependencies without discussion.** Open an issue first if you
|
|
49
|
+
think one is needed — `dependencies` in `package.json` are kept deliberately
|
|
50
|
+
minimal.
|
|
51
|
+
- **Every feature lands with smoke-test assertions.** New tools, options, or
|
|
52
|
+
behaviors are not considered done until they're covered in
|
|
53
|
+
`test/smoke.test.js`.
|
|
54
|
+
- **Security claims match protocol reality.** FTP/FTPS client-side sub-roots
|
|
55
|
+
are not described as a symlink-safe jail; a dedicated server-side
|
|
56
|
+
account/chroot is the boundary. SFTP protections must document the residual
|
|
57
|
+
server-side race.
|
|
58
|
+
- **Source and published availability are distinct.** Do not advertise `npx`
|
|
59
|
+
or MCP registry installation until the corresponding artifact is public and
|
|
60
|
+
independently verified.
|
|
61
|
+
- **`stdout` in server mode is JSON-RPC only.** Never `console.log` from the MCP
|
|
62
|
+
server path — anything written to stdout is a wire-protocol message.
|
|
63
|
+
Diagnostics and human-facing output belong on `stderr` or in `doctor`/`setup`
|
|
64
|
+
(non-server) commands.
|
|
65
|
+
|
|
66
|
+
## Running part of the suite
|
|
67
|
+
|
|
68
|
+
Run the main smoke suite:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
node test/smoke.test.js
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run the transport qualification and release gates separately:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node --test test/transport-qualification.js
|
|
78
|
+
npm run test:release
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`npm test` runs the main smoke suite and transport qualification. Before
|
|
82
|
+
opening a PR, run both and any release gates affected by the change; keep
|
|
83
|
+
existing assertions enabled.
|
|
84
|
+
|
|
85
|
+
## PR checklist
|
|
86
|
+
|
|
87
|
+
- [ ] `npm test` passes (use the current total; do not hard-code it in docs).
|
|
88
|
+
- [ ] No new runtime dependency, or it was discussed in an issue first.
|
|
89
|
+
- [ ] New/changed behavior has matching smoke-test assertions.
|
|
90
|
+
- [ ] Docs updated in both `README.md` (English) and `README.fr.md` (French) if
|
|
91
|
+
user-facing behavior changed.
|
|
92
|
+
- [ ] New configuration examples are strict JSON and relative Markdown links
|
|
93
|
+
resolve.
|
|
94
|
+
- [ ] Security-sensitive changes are reflected in
|
|
95
|
+
[docs/SECURITY-MODEL.md](./docs/SECURITY-MODEL.md).
|
|
96
|
+
|
|
97
|
+
## Releasing (maintainers)
|
|
98
|
+
|
|
99
|
+
Do not improvise the first publication from this short section. Follow the
|
|
100
|
+
[release guide](./docs/RELEASE.md), which covers:
|
|
101
|
+
|
|
102
|
+
- matching package, lockfile, server and tag versions, then separately
|
|
103
|
+
verifying npm and Official MCP Registry versions after publication;
|
|
104
|
+
- clean-tarball validation and end-to-end tests;
|
|
105
|
+
- npm Trusted Publishing/provenance and the short-lived `NPM_TOKEN` fallback
|
|
106
|
+
needed only when first-publication bootstrapping requires it;
|
|
107
|
+
- manual MCP registry ownership and publication;
|
|
108
|
+
- post-publish verification and fix-forward rollback.
|
|
109
|
+
|
|
110
|
+
The npm package and MCP registry entry are not available until every applicable
|
|
111
|
+
manual prerequisite and verification step in that guide has passed.
|