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/SECURITY.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
**English** | [Français](./SECURITY.fr.md)
|
|
4
|
+
|
|
5
|
+
## Supported versions
|
|
6
|
+
|
|
7
|
+
The project has not yet completed its first npm or MCP registry publication.
|
|
8
|
+
Security fixes target the current source branch and the latest tagged 0.x
|
|
9
|
+
release. Older 0.x tags may be asked to upgrade rather than receive a backport.
|
|
10
|
+
|
|
11
|
+
| Version | Support |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Current source / latest 0.x tag | Supported |
|
|
14
|
+
| Older 0.x tags | Best effort |
|
|
15
|
+
|
|
16
|
+
## Report a vulnerability privately
|
|
17
|
+
|
|
18
|
+
**Do not open a public GitHub issue, discussion, or pull request for a suspected
|
|
19
|
+
vulnerability.**
|
|
20
|
+
|
|
21
|
+
Use GitHub's private vulnerability reporting: open the
|
|
22
|
+
[repository Security page](https://github.com/alebgl77/ftp-deploy-mcp/security),
|
|
23
|
+
choose **Report a vulnerability**, and include:
|
|
24
|
+
|
|
25
|
+
- affected commit or version and protocol;
|
|
26
|
+
- minimal reproduction steps and required server configuration;
|
|
27
|
+
- expected versus observed access or disclosure;
|
|
28
|
+
- impact, including which local or remote files/credentials are exposed;
|
|
29
|
+
- any suggested remediation or disclosure deadline.
|
|
30
|
+
|
|
31
|
+
Avoid including live credentials or private keys. Use disposable test accounts
|
|
32
|
+
and redact logs. If private reporting is unavailable, open a public issue that
|
|
33
|
+
contains no vulnerability details and asks the maintainer to establish a
|
|
34
|
+
private channel.
|
|
35
|
+
|
|
36
|
+
The target is to acknowledge a complete report within 72 hours, then confirm
|
|
37
|
+
scope, coordinate a fix and tests, and agree on a disclosure date. This is a
|
|
38
|
+
response target, not a bug-bounty or resolution-time promise.
|
|
39
|
+
|
|
40
|
+
## In scope
|
|
41
|
+
|
|
42
|
+
- Access outside `localRoot` through traversal, symlink, junction, or download
|
|
43
|
+
destination handling.
|
|
44
|
+
- SFTP access outside `root`, host-key verification bypass, or unsafe handling
|
|
45
|
+
of a verified host-key rotation.
|
|
46
|
+
- FTP/FTPS connection to a non-root client jail without the explicit
|
|
47
|
+
`allowUnsafeRemoteRoot` acknowledgment.
|
|
48
|
+
- Plain FTP or unverified FTPS without the explicit `allowInsecure`
|
|
49
|
+
acknowledgment.
|
|
50
|
+
- Credential or key material exposed in tool results, diagnostics, logs, or
|
|
51
|
+
errors.
|
|
52
|
+
- `readOnly` bypass, destructive-operation guard bypass, or incorrect success
|
|
53
|
+
reporting after a partial deployment.
|
|
54
|
+
- Corruption or unsafe replacement of server or MCP client configuration.
|
|
55
|
+
- A release archive accepted with changed shipped source, a changed dependency
|
|
56
|
+
manifest or source lockfile, or an unapproved dependency modifier or install hook.
|
|
57
|
+
|
|
58
|
+
Issues that depend on a malicious FTP server using symlinks outside a
|
|
59
|
+
client-configured sub-root are important but are **not claimed to be prevented**:
|
|
60
|
+
FTP/FTPS require a server-side account/chroot boundary. Likewise, SFTP
|
|
61
|
+
realpath/lstat checks reduce symlink escapes but cannot remove every race on a
|
|
62
|
+
malicious server. These limits are documented in the
|
|
63
|
+
[security model](./docs/SECURITY-MODEL.md).
|
|
64
|
+
|
|
65
|
+
## Dependency and release integrity
|
|
66
|
+
|
|
67
|
+
The six direct production dependencies use exact versions.
|
|
68
|
+
`package-lock.json` is the sole source graph authority, shipped in the 90-file
|
|
69
|
+
source installation archive. Use `npm ci --omit=dev --ignore-scripts` after
|
|
70
|
+
extraction and retain this file. Changes require review of the complete graph,
|
|
71
|
+
its URLs and integrity values, then the checks in the
|
|
72
|
+
[release guide](./docs/RELEASE.md).
|
|
73
|
+
|
|
74
|
+
The 89-file npm package contains no lockfile and remains unqualified. A real
|
|
75
|
+
installation changed ten production dependencies. Workflows reject installed
|
|
76
|
+
graph drift before npm or MCP publication; a source proof cannot authorize npm.
|
|
77
|
+
A future matching npm graph is evidence only for the tested environment and date,
|
|
78
|
+
with no guarantee about future installations.
|
|
79
|
+
|
|
80
|
+
A passing dependency audit is evidence for that graph on that date, not a
|
|
81
|
+
guarantee against future advisories or a certification of production use.
|
|
82
|
+
Report archive-validation bypasses privately using the same process above.
|
|
83
|
+
GitHub releases do not establish npm or Official MCP Registry availability.
|
|
84
|
+
|
|
85
|
+
## Research guidelines
|
|
86
|
+
|
|
87
|
+
- Test only systems and accounts you own or are authorized to assess.
|
|
88
|
+
- Do not access other users' data, degrade service, persist access, or use
|
|
89
|
+
social engineering.
|
|
90
|
+
- Stop once the issue is demonstrated and share details privately.
|
|
91
|
+
- Give the project a reasonable opportunity to remediate before disclosure.
|
|
92
|
+
|
|
93
|
+
Good-faith research following these guidelines is welcome, but this document
|
|
94
|
+
does not grant authorization against third-party FTP/SFTP services.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Performances et intégration des agents
|
|
2
|
+
|
|
3
|
+
[English](./AGENT-PERFORMANCE.md)
|
|
4
|
+
|
|
5
|
+
Les optimisations réduisent les calculs locaux répétés dans le serveur MCP.
|
|
6
|
+
Elles s'appliquent à tout client utilisant ses outils stdio, quel que soit le
|
|
7
|
+
fournisseur du modèle. L'architecture, les noms des outils, les arguments, les
|
|
8
|
+
schémas de réponse, la vérification des transferts, l'annulation et les limites
|
|
9
|
+
d'admission sont conservés.
|
|
10
|
+
|
|
11
|
+
- L'adaptateur FTP/SFTP sélectionné est chargé au premier usage. Le coût de
|
|
12
|
+
l'import est reporté à la première connexion ; les suivants utilisent le
|
|
13
|
+
cache de modules de Node.
|
|
14
|
+
- Chaque redactor garde en cache les secrets littéraux triés et les motifs
|
|
15
|
+
compilés des secrets courts, puis les reconstruit à l'ajout d'un nouveau
|
|
16
|
+
secret distinct. La mémoire supplémentaire croît avec le nombre de secrets ;
|
|
17
|
+
l'ordre des remplacements et le comportement normal/strict sont préservés.
|
|
18
|
+
- Un comptage incrémental exact des octets JSON évite de sérialiser à répétition
|
|
19
|
+
les échantillons qui grandissent. La troncature du texte évite aussi une
|
|
20
|
+
sérialisation complète en double. Le contenu et les plafonds des réponses
|
|
21
|
+
sont préservés.
|
|
22
|
+
|
|
23
|
+
## Connecter un agent
|
|
24
|
+
|
|
25
|
+
Installez les sources comme indiqué dans le [README](../README.fr.md). Utilisez
|
|
26
|
+
Node.js 22 ou plus récent et des chemins absolus explicites. Cette définition
|
|
27
|
+
générique utilise le checkout comme répertoire de travail du processus et
|
|
28
|
+
sélectionne directement la configuration des serveurs :
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"command": "node",
|
|
33
|
+
"args": [
|
|
34
|
+
"/chemin/absolu/vers/ftp-deploy-mcp/src/index.js",
|
|
35
|
+
"--config",
|
|
36
|
+
"/chemin/absolu/vers/ftp-servers.json"
|
|
37
|
+
],
|
|
38
|
+
"cwd": "/chemin/absolu/vers/ftp-deploy-mcp"
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Adaptez la configuration englobante au client. S'il n'accepte pas `cwd`, fixez
|
|
43
|
+
explicitement le répertoire de travail du lanceur ; conservez les deux chemins
|
|
44
|
+
absolus dans les arguments. `localRoot`, dans la configuration des serveurs,
|
|
45
|
+
détermine l'arborescence locale autorisée. `FTP_MCP_CONFIG` est une alternative
|
|
46
|
+
à `--config`, qui reste prioritaire. Voir la
|
|
47
|
+
[configuration](../README.fr.md#configuration-des-serveurs).
|
|
48
|
+
|
|
49
|
+
| Client agent | Mode d'intégration |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| Claude Code / Claude Desktop | Ajoutez la commande et les arguments sous `mcpServers` ; voir la [configuration du client](../README.fr.md#configuration-du-client). |
|
|
52
|
+
| OpenAI Agents SDK pour JavaScript | Créez `MCPServerStdio` avec les options de lancement, connectez-le et ajoutez-le aux `mcpServers` de l'agent. Fermez-le à la fin. Voir le [guide MCP du SDK](https://openai.github.io/openai-agents-js/guides/mcp/). |
|
|
53
|
+
| Gemini CLI | Ajoutez les options de lancement sous `mcpServers` dans `settings.json` ; voir le [guide MCP de Gemini CLI](https://geminicli.com/docs/tools/mcp-server/). |
|
|
54
|
+
| Qwen-Agent | Fournissez une configuration d'outil contenant `mcpServers` avec la commande et les arguments ; voir l'[exemple MCP de Qwen-Agent](https://github.com/QwenLM/Qwen-Agent#how-to-use-mcp). |
|
|
55
|
+
|
|
56
|
+
Ces modes décrivent la compatibilité stdio ; ils ne constituent pas des
|
|
57
|
+
résultats de tests de bout en bout propres à chaque fournisseur. Une
|
|
58
|
+
intégration MCP distante hébergée nécessite un serveur MCP HTTP accessible ou
|
|
59
|
+
un pont distinct. Ce dépôt expose stdio et n'ajoute ni serveur HTTP ni pont.
|
|
60
|
+
|
|
61
|
+
Pour un catalogue stable, OpenAI Agents SDK accepte l'option
|
|
62
|
+
`cacheToolsList: true` dans `MCPServerStdio`. Elle évite de répéter la découverte
|
|
63
|
+
des outils côté client. Invalidez ce cache avec `invalidateToolsCache()` si le
|
|
64
|
+
catalogue change ; voir les [conseils de cache du SDK](https://openai.github.io/openai-agents-js/guides/mcp/#other-things-to-know).
|
|
65
|
+
|
|
66
|
+
## Cibler les appels
|
|
67
|
+
|
|
68
|
+
- Appelez `ftp_list` avec un `limit` adapté (50 par défaut, 200 au maximum).
|
|
69
|
+
Suivez le `next_offset` renvoyé seulement si d'autres entrées sont utiles.
|
|
70
|
+
La pagination borne la réponse MCP ; l'adaptateur récupère toujours la liste
|
|
71
|
+
du dossier distant.
|
|
72
|
+
- Appelez `ftp_read` avec un `max_bytes` explicite, par exemple 8192 pour un
|
|
73
|
+
petit fichier de configuration. Le défaut est de 256 Kio et le plafond de 1 Mio.
|
|
74
|
+
- Attendez chaque mutation dont dépend la suivante. Terminez par exemple un
|
|
75
|
+
envoi avant de renommer sa destination. Les lectures indépendantes peuvent
|
|
76
|
+
se chevaucher ; les verrous FIFO et les [limites d'admission](./RESOURCE-BOUNDS.fr.md)
|
|
77
|
+
restent actifs.
|
|
78
|
+
- Examinez un appel `ftp_deploy` avec `dry_run: true` avant le déploiement réel.
|
|
79
|
+
Cette simulation n'effectue aucune entrée-sortie réseau et ne vérifie pas
|
|
80
|
+
la cible distante.
|
|
81
|
+
|
|
82
|
+
Des réponses bornées et pertinentes, ainsi que la mesure du nombre d'appels,
|
|
83
|
+
du temps d'exécution et des erreurs suivent les
|
|
84
|
+
[conseils de conception d'outils d'Anthropic](https://www.anthropic.com/engineering/writing-tools-for-agents).
|
|
85
|
+
|
|
86
|
+
## Reproduire les contrôles
|
|
87
|
+
|
|
88
|
+
Depuis un checkout complet avec les dépendances de développement :
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm ci --ignore-scripts
|
|
92
|
+
npm run test:performance
|
|
93
|
+
npm test
|
|
94
|
+
npm run test:eval-runner
|
|
95
|
+
npm run eval:scripted
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`test:performance` exécute `test/redaction-performance.test.mjs` et
|
|
99
|
+
`test/agent-performance.test.mjs` ; ces régressions font aussi partie de
|
|
100
|
+
`npm test`.
|
|
101
|
+
|
|
102
|
+
Le benchmark d'exécution exige un checkout intact comme premier argument.
|
|
103
|
+
Créez et installez cette référence une fois, ou utilisez un checkout existant
|
|
104
|
+
du même commit :
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
git worktree add --detach ../ftp-deploy-mcp-baseline a068aa5c3b1e53caaffc2c7907966ff5a2e9cb0f
|
|
108
|
+
npm --prefix ../ftp-deploy-mcp-baseline ci --ignore-scripts
|
|
109
|
+
npm run benchmark:agents -- ../ftp-deploy-mcp-baseline 200
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Le dernier argument optionnel est le nombre positif d'itérations (200 par
|
|
113
|
+
défaut). `benchmark:agents` exécute `scripts/benchmark-agent-performance.mjs`
|
|
114
|
+
avec des fixtures locales, vérifie l'équivalence des sorties et rapporte le
|
|
115
|
+
travail de sérialisation et la durée. Sa mesure de découverte couvre l'import
|
|
116
|
+
des modules, l'enregistrement et la liste des outils, sans le handshake stdio
|
|
117
|
+
complet. Consignez le commit, la version de Node.js, le système d'exploitation
|
|
118
|
+
et la charge avec les mesures ; répétez les comparaisons sur la même machine.
|
|
119
|
+
Sur les premières versions de Node.js 22 sans instrumentation des imports,
|
|
120
|
+
les contrôles utilisant ces hooks sont ignorés et les nombres de modules sont
|
|
121
|
+
indisponibles ; les mesures de durée du benchmark restent exécutées.
|
|
122
|
+
|
|
123
|
+
Le microbenchmark de masquage est optionnel et compare des sorties de fixtures
|
|
124
|
+
identiques à celles de l'implémentation précédente. Il affiche des médianes
|
|
125
|
+
indicatives sans assertion sur la durée. Dans un shell POSIX :
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
REDACTION_BENCHMARK=1 node --test test/redaction-performance.test.mjs
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Dans PowerShell :
|
|
132
|
+
|
|
133
|
+
```powershell
|
|
134
|
+
$env:REDACTION_BENCHMARK = '1'
|
|
135
|
+
node --test test/redaction-performance.test.mjs
|
|
136
|
+
Remove-Item Env:REDACTION_BENCHMARK
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Les tests et benchmarks mesurent le comportement de l'implémentation et son
|
|
140
|
+
exécution locale. Les [évaluations scriptées](./SCRIPTED-EVALUATIONS.fr.md)
|
|
141
|
+
exercent les handlers MCP sans modèle. Ils ne démontrent ni qualité du modèle,
|
|
142
|
+
ni économie de tokens, ni latence d'un fournisseur, ni débit FTP/SFTP en
|
|
143
|
+
production. Les [instructions d'évaluation d'agents](../evaluations/README.fr.md)
|
|
144
|
+
couvrent séparément les essais avec un modèle.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Agent performance and client integration
|
|
2
|
+
|
|
3
|
+
[Français](./AGENT-PERFORMANCE.fr.md)
|
|
4
|
+
|
|
5
|
+
The performance work reduces repeated local computation in the MCP server.
|
|
6
|
+
It applies to any client using its stdio tools, independently of the model
|
|
7
|
+
provider. The server architecture, tool names, arguments, response schemas,
|
|
8
|
+
transfer verification, cancellation and admission limits remain in place.
|
|
9
|
+
|
|
10
|
+
- The selected FTP/SFTP adapter loads on first use. Its import cost moves to
|
|
11
|
+
the first connection; subsequent imports use Node's module cache.
|
|
12
|
+
- Each redactor caches sorted secret literals and compiled short-secret
|
|
13
|
+
patterns, rebuilding them when a new distinct secret is collected. Extra
|
|
14
|
+
storage grows with the number of secrets; replacement order and normal/strict
|
|
15
|
+
behavior are preserved.
|
|
16
|
+
- Exact incremental JSON byte accounting avoids repeatedly serializing growing
|
|
17
|
+
samples. Text truncation also avoids a duplicate full-result serialization.
|
|
18
|
+
Response content and size limits are preserved.
|
|
19
|
+
|
|
20
|
+
## Connect an agent
|
|
21
|
+
|
|
22
|
+
Install from source as described in the [README](../README.md). Use Node.js 22
|
|
23
|
+
or newer and explicit absolute paths. This generic launch specification uses
|
|
24
|
+
the checkout as the process working directory and selects the server
|
|
25
|
+
configuration directly:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"command": "node",
|
|
30
|
+
"args": [
|
|
31
|
+
"/absolute/path/to/ftp-deploy-mcp/src/index.js",
|
|
32
|
+
"--config",
|
|
33
|
+
"/absolute/path/to/ftp-servers.json"
|
|
34
|
+
],
|
|
35
|
+
"cwd": "/absolute/path/to/ftp-deploy-mcp"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Adapt the surrounding configuration to the client. If it has no `cwd` setting,
|
|
40
|
+
set the launcher's working directory explicitly; keep both argument paths
|
|
41
|
+
absolute. `localRoot` in the server configuration determines the allowed local
|
|
42
|
+
file tree. `FTP_MCP_CONFIG` is an alternative to `--config`; the command-line
|
|
43
|
+
selector takes precedence. See [configuration](../README.md#server-configuration).
|
|
44
|
+
|
|
45
|
+
| Agent client | Integration route |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| Claude Code / Claude Desktop | Add the command and arguments under `mcpServers`; see [client setup](../README.md#client-setup). |
|
|
48
|
+
| OpenAI Agents SDK for JavaScript | Create `MCPServerStdio` with the launch options, connect it and attach it to the agent's `mcpServers`. Close it when finished. See the [SDK MCP guide](https://openai.github.io/openai-agents-js/guides/mcp/). |
|
|
49
|
+
| Gemini CLI | Add the launch options under `mcpServers` in `settings.json`; see the [Gemini CLI MCP guide](https://geminicli.com/docs/tools/mcp-server/). |
|
|
50
|
+
| Qwen-Agent | Supply a tool configuration containing `mcpServers` with the command and arguments; see the [Qwen-Agent MCP example](https://github.com/QwenLM/Qwen-Agent#how-to-use-mcp). |
|
|
51
|
+
|
|
52
|
+
These routes describe stdio compatibility; they are not provider-specific
|
|
53
|
+
end-to-end test results. Remote hosted MCP integrations require an accessible
|
|
54
|
+
HTTP MCP server or a separate bridge. This repository exposes stdio and adds
|
|
55
|
+
no HTTP server or bridge.
|
|
56
|
+
|
|
57
|
+
For a stable tool catalog, the OpenAI Agents SDK optionally accepts
|
|
58
|
+
`cacheToolsList: true` in `MCPServerStdio`. This avoids repeated client-side
|
|
59
|
+
tool discovery. Invalidate the cache with `invalidateToolsCache()` when the
|
|
60
|
+
catalog changes; see the [SDK caching guidance](https://openai.github.io/openai-agents-js/guides/mcp/#other-things-to-know).
|
|
61
|
+
|
|
62
|
+
## Keep calls focused
|
|
63
|
+
|
|
64
|
+
- Use `ftp_list` with an appropriate `limit` (default 50, maximum 200). Follow
|
|
65
|
+
the returned `next_offset` only when more entries are needed. Pagination
|
|
66
|
+
bounds the MCP response; the adapter still obtains the remote directory list.
|
|
67
|
+
- Use `ftp_read` with an explicit `max_bytes`, for example 8192 for a small
|
|
68
|
+
configuration file. The default is 256 KiB and the hard maximum is 1 MiB.
|
|
69
|
+
- Await dependent mutations in sequence. For example, finish an upload before
|
|
70
|
+
renaming its destination. Independent reads may overlap; the server's FIFO
|
|
71
|
+
locks and [admission limits](./RESOURCE-BOUNDS.md) still apply.
|
|
72
|
+
- Review an `ftp_deploy` call with `dry_run: true` before executing the deploy.
|
|
73
|
+
The dry run performs no network I/O and does not verify the remote endpoint.
|
|
74
|
+
|
|
75
|
+
Bounded, relevant responses and measurement of tool-call counts, runtime and
|
|
76
|
+
errors follow [Anthropic's tool design guidance](https://www.anthropic.com/engineering/writing-tools-for-agents).
|
|
77
|
+
|
|
78
|
+
## Reproduce the checks
|
|
79
|
+
|
|
80
|
+
Run from a full repository checkout with development dependencies installed:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm ci --ignore-scripts
|
|
84
|
+
npm run test:performance
|
|
85
|
+
npm test
|
|
86
|
+
npm run test:eval-runner
|
|
87
|
+
npm run eval:scripted
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`test:performance` runs `test/redaction-performance.test.mjs` and
|
|
91
|
+
`test/agent-performance.test.mjs`; these regressions also run in `npm test`.
|
|
92
|
+
|
|
93
|
+
The runtime benchmark requires a pristine checkout as its first argument.
|
|
94
|
+
Create and install this baseline once, or use an existing checkout of the same
|
|
95
|
+
commit:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
git worktree add --detach ../ftp-deploy-mcp-baseline a068aa5c3b1e53caaffc2c7907966ff5a2e9cb0f
|
|
99
|
+
npm --prefix ../ftp-deploy-mcp-baseline ci --ignore-scripts
|
|
100
|
+
npm run benchmark:agents -- ../ftp-deploy-mcp-baseline 200
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The optional final argument is the positive iteration count (default 200).
|
|
104
|
+
`benchmark:agents` runs `scripts/benchmark-agent-performance.mjs` with local
|
|
105
|
+
fixtures, checks output equivalence, and reports serialization work and elapsed
|
|
106
|
+
time. Its discovery measurement covers module import, registration and tool
|
|
107
|
+
listing, not the complete stdio handshake. Record the commit, Node.js version,
|
|
108
|
+
operating system and workload alongside timings; repeat comparisons on the
|
|
109
|
+
same machine. On early Node.js 22 releases without module-load instrumentation,
|
|
110
|
+
hook-based checks are skipped and module counts are unavailable; benchmark
|
|
111
|
+
timings still run.
|
|
112
|
+
|
|
113
|
+
The redaction microbenchmark is opt-in and compares identical fixture outputs
|
|
114
|
+
with the previous implementation. It reports diagnostic medians without timing
|
|
115
|
+
assertions. On POSIX shells:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
REDACTION_BENCHMARK=1 node --test test/redaction-performance.test.mjs
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
On PowerShell:
|
|
122
|
+
|
|
123
|
+
```powershell
|
|
124
|
+
$env:REDACTION_BENCHMARK = '1'
|
|
125
|
+
node --test test/redaction-performance.test.mjs
|
|
126
|
+
Remove-Item Env:REDACTION_BENCHMARK
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The tests and benchmarks measure implementation behavior and local execution.
|
|
130
|
+
The [scripted evaluations](./SCRIPTED-EVALUATIONS.md) exercise MCP handlers
|
|
131
|
+
without a model. They do not establish model quality, token savings, provider
|
|
132
|
+
latency or production FTP/SFTP throughput. Use the separate
|
|
133
|
+
[agent evaluation instructions](../evaluations/README.md) for model-based work.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Contrat d’erreur MCP
|
|
2
|
+
|
|
3
|
+
[English](./ERROR-CONTRACT.md)
|
|
4
|
+
|
|
5
|
+
Les dix outils legacy et leurs champs de succès restent stables. Lorsque
|
|
6
|
+
`stateDir` est activé, quatre outils durables supplémentaires sont publiés. Neuf outils legacy
|
|
7
|
+
publient un `oneOf` JSON Schema draft-07 avec deux possibilités strictes :
|
|
8
|
+
l’objet de succès existant et `{error}`. `ftp_read` conserve un succès texte
|
|
9
|
+
sans schéma de sortie ; ses erreurs utilisent néanmoins l’enveloppe validée
|
|
10
|
+
en interne. Les clients doivent lire `isError` et les champs stables ci-dessous
|
|
11
|
+
plutôt qu’analyser le texte traduit.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"isError": true,
|
|
16
|
+
"content": [{ "type": "text", "text": "Erreur : READ_ONLY : …" }],
|
|
17
|
+
"structuredContent": {
|
|
18
|
+
"error": {
|
|
19
|
+
"schema_version": 1,
|
|
20
|
+
"code": "READ_ONLY",
|
|
21
|
+
"message": "…",
|
|
22
|
+
"retryable": false,
|
|
23
|
+
"request_id": "46d0223a-de77-4f28-bf77-f8b9706a4ecb",
|
|
24
|
+
"next_action": "fix_config",
|
|
25
|
+
"effects": "none"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`request_id` est un nouvel UUID créé par le serveur pour un appel. Il est
|
|
32
|
+
distinct de l’identifiant de corrélation JSON-RPC et n’identifie pas une
|
|
33
|
+
opération durable. Les erreurs durables ajoutent `plan_id` et `operation_id`
|
|
34
|
+
facultatifs, une phase et des compteurs partiels durables. Ces identifiants
|
|
35
|
+
réfèrent uniquement au workflow journalisé et jamais à la corrélation JSON-RPC.
|
|
36
|
+
|
|
37
|
+
## Décisions stables et effets observés
|
|
38
|
+
|
|
39
|
+
Les valeurs acceptées pour `code` sont :
|
|
40
|
+
|
|
41
|
+
`CONFIG_REQUIRED`, `CONFIG_INVALID`, `SERVER_REQUIRED`, `SERVER_UNKNOWN`,
|
|
42
|
+
`INVALID_ARGUMENT`, `READ_ONLY`, `TRANSPORT_POLICY`, `HOST_KEY_REJECTED`,
|
|
43
|
+
`REMOTE_ROOT_REJECTED`, `PATH_REJECTED`, `NOT_FOUND`, `ALREADY_EXISTS`,
|
|
44
|
+
`TRANSFER_LIMIT`, `TRANSFER_VERIFY`, `TARGET_CHANGED`, `CANCELLED`, `TIMEOUT`,
|
|
45
|
+
`DEPLOY_PARTIAL`, `TRANSPORT_ERROR`, `OUTPUT_LIMIT`, `INTERNAL_ERROR`,
|
|
46
|
+
`SCAN_LIMIT`, `CAPACITY_LIMIT`.
|
|
47
|
+
|
|
48
|
+
Les outils durables utilisent aussi `DURABLE_STATE_DISABLED`,
|
|
49
|
+
`DURABLE_STATE_BUSY`, `DURABLE_STATE_LIMIT`, `DURABLE_STATE_CORRUPT`,
|
|
50
|
+
`DURABLE_STATE_IO`, `DURABLE_STATE_UNSUPPORTED`, `PLAN_NOT_FOUND`,
|
|
51
|
+
`PLAN_EXPIRED`, `PLAN_STALE`, `PLAN_CONSUMED`, `IDEMPOTENCY_CONFLICT`,
|
|
52
|
+
`CONFIRMATION_DECLINED`, `CONFIRMATION_INVALID`,
|
|
53
|
+
`CLIENT_INTERACTION_UNSUPPORTED`, `STATUS_CHANGED`,
|
|
54
|
+
`RECONCILIATION_REQUIRED`, `ROLLBACK_CONFLICT` et `WORKFLOW_UNSUPPORTED`.
|
|
55
|
+
L’état v1 est refusé avant décodage des plans et exige une réinitialisation hors ligne.
|
|
56
|
+
|
|
57
|
+
`SCAN_LIMIT` refuse toute la sélection locale avant connexion, avec `effects:none`
|
|
58
|
+
et `next_action:fix_input`. `CAPACITY_LIMIT` refuse l’admission avant préparation,
|
|
59
|
+
avec `effects:none` et `next_action:retry`. Les deux conservent `retryable:false` ;
|
|
60
|
+
voir les [limites de ressources](./RESOURCE-BOUNDS.fr.md).
|
|
61
|
+
|
|
62
|
+
Les valeurs legacy de `next_action` sont `fix_input`, `fix_config`,
|
|
63
|
+
`select_server`, `inspect_target`, `retry`, `contact_operator` et `none`.
|
|
64
|
+
Les erreurs durables peuvent aussi indiquer `status`, `resume_apply`,
|
|
65
|
+
`resume_rollback`, `offline_recovery` ou `upgrade_client`.
|
|
66
|
+
Les erreurs des outils historiques renvoient prudemment `retryable:false`. Les
|
|
67
|
+
erreurs durables ne renvoient `retryable:true` que pour
|
|
68
|
+
`DURABLE_STATE_BUSY`, `DURABLE_STATE_IO`, `STATUS_CHANGED` et les échecs
|
|
69
|
+
`TIMEOUT` ou `TRANSPORT_ERROR` projetés ; toutes les autres renvoient `false`.
|
|
70
|
+
Ce drapeau guide le client sans jamais autoriser une reprise automatique : il
|
|
71
|
+
faut suivre `next_action`, surtout après un effet `possible` ou `confirmed`.
|
|
72
|
+
|
|
73
|
+
| `effects` | Signification |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `none` | Aucune opération mutatrice n’a été lancée par cet appel. |
|
|
76
|
+
| `possible` | Une mutation a été lancée, sans effet encore confirmé. |
|
|
77
|
+
| `confirmed` | Au moins un effet a été acquitté ; d’autres effets peuvent rester incertains. |
|
|
78
|
+
|
|
79
|
+
Les effets comprennent les temporaires, leur nettoyage et les écritures
|
|
80
|
+
locales des téléchargements. Une politique distante de lecture seule
|
|
81
|
+
n’interdit pas ces écritures locales. `confirmed` ne signifie pas que toute
|
|
82
|
+
l’opération a réussi ; zéro fichier terminé ne prouve pas l’absence de
|
|
83
|
+
modification. Un échec de fermeture après promotion conserve les effets confirmés.
|
|
84
|
+
|
|
85
|
+
Les erreurs d’envoi, de téléchargement et de déploiement peuvent inclure les
|
|
86
|
+
champs stricts `partial` : `completed_files`, `completed_bytes`, `failed_files`,
|
|
87
|
+
`total_files` facultatif et `final`. Ce sont des entiers sûrs non négatifs,
|
|
88
|
+
issus des promotions observées et des tentatives de fichier en échec, sans
|
|
89
|
+
analyse du texte. Les octets comptent les fichiers terminés, pas tout le
|
|
90
|
+
trafic réseau ni les temporaires partiellement écrits. `final: false` indique
|
|
91
|
+
un instantané anticipé pendant que le traitement sous-jacent se termine.
|
|
92
|
+
Cet instantané n’est pas révisé ultérieurement dans la réponse.
|
|
93
|
+
|
|
94
|
+
## Protocole, annulation et limites de sortie
|
|
95
|
+
|
|
96
|
+
Les arguments rejetés par le schéma d’entrée déclaré d’un outil connu donnent
|
|
97
|
+
`INVALID_ARGUMENT` avant son traitement, sa connexion ou une écriture locale.
|
|
98
|
+
Un refus métier ultérieur peut survenir après connexion. Un outil inconnu renvoie
|
|
99
|
+
une erreur de protocole JSON-RPC `-32602` bornée sans reprendre son nom.
|
|
100
|
+
Les trames mal formées conservent le traitement des erreurs de protocole du SDK.
|
|
101
|
+
|
|
102
|
+
L’annulation MCP du client interrompt l’opération et le SDK supprime sa réponse :
|
|
103
|
+
le client ne doit pas attendre une enveloppe `CANCELLED`. Les échéances internes
|
|
104
|
+
sont distinctes et peuvent renvoyer `TIMEOUT`. L’annulation native du SDK v2
|
|
105
|
+
traite chaque identifiant de requête valide, dont le nombre `0` et la chaîne vide
|
|
106
|
+
`""`. Une garde du canal, possédée par le point d’entrée, réserve chaque
|
|
107
|
+
identifiant de requête JSON-RPC entrant, toutes méthodes confondues, avant sa
|
|
108
|
+
remise au SDK. Tout doublon actif ferme la connexion avant l’exécution d’un
|
|
109
|
+
second handler, même si sa méthode diffère. L’identifiant d’un appel d’outil
|
|
110
|
+
n’est libéré qu’après le règlement ou l’échec de l’envoi de sa réponse terminale
|
|
111
|
+
et le règlement réel de tous les tours de handler enregistrés, de sa préparation
|
|
112
|
+
et de sa libération, y compris tous les tours legacy d’entrée requise.
|
|
113
|
+
Si l’annulation supprime la réponse, il reste réservé jusqu’à la fermeture de la
|
|
114
|
+
connexion. Des identifiants concurrents distincts, dont `0`, `""`, `1` et `"0"`,
|
|
115
|
+
restent indépendants. Une réponse dont l’envoi a déjà commencé ne peut pas être
|
|
116
|
+
rappelée. L’annulation n’efface pas les effets.
|
|
117
|
+
|
|
118
|
+
Les résultats d’outils connus sont masqués, bornés puis validés à une seule
|
|
119
|
+
frontière. La limite de 25 000 octets porte sur le `JSON.stringify` UTF-8 du
|
|
120
|
+
résultat complet, texte et données structurées compris, après expansion du
|
|
121
|
+
masquage. Les avertissements de sécurité ont un rôle de rendu interne distinct.
|
|
122
|
+
Des chaînes distantes telles que `Page:` ou `SECURITY WARNING` ne peuvent pas
|
|
123
|
+
acquérir ce rôle. La pagination est reconstruite après réduction des exemples.
|
|
124
|
+
Un repli `OUTPUT_LIMIT` conserve l’UUID, les effets et les compteurs observés.
|
|
125
|
+
|
|
126
|
+
Les décisions typées précèdent la traduction. Les détails natifs restent des
|
|
127
|
+
données de leur source sous un libellé traduit ; une réponse FTP ambiguë,
|
|
128
|
+
dont le code 550, ne devient pas `NOT_FOUND` d’après son texte. Les secrets
|
|
129
|
+
sont masqués dans le texte libre. Seules les constantes publiques propres au
|
|
130
|
+
schéma et l’UUID créé pour ce résultat sont préservés à leurs chemins
|
|
131
|
+
structurés exacts. Les objets Error, causes, piles, identifiants secrets et
|
|
132
|
+
arguments bruts ne sont pas sérialisés. Les secrets de configuration sont
|
|
133
|
+
collectés en privé avant validation, y compris ceux des entrées rejetées et
|
|
134
|
+
les valeurs ENV résolues. Les diagnostics publics du chargeur utilisent le
|
|
135
|
+
même masque. Un JSON mal formé reçoit un diagnostic générique sans extrait
|
|
136
|
+
du parseur ; aucune extraction fiable de secrets depuis ce contenu n’est
|
|
137
|
+
revendiquée. Les blocs FileZilla rejetés sont identifiés par leur index
|
|
138
|
+
numérique, sans reprise des noms ou champs de protocole non fiables.
|
|
139
|
+
|
|
140
|
+
Voir les [langues](./LANGUAGES.fr.md), le [modèle de sécurité](./SECURITY-MODEL.fr.md)
|
|
141
|
+
et les [transferts vérifiés](./TRANSFERS.fr.md) pour les autres limites.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# MCP error contract
|
|
2
|
+
|
|
3
|
+
[Français](./ERROR-CONTRACT.fr.md)
|
|
4
|
+
|
|
5
|
+
The ten legacy tool names and success field shapes remain stable. When
|
|
6
|
+
`stateDir` is enabled, four durable tools are additionally advertised. Nine legacy tools publish
|
|
7
|
+
a JSON Schema draft-07 `oneOf` with two strict alternatives: the existing
|
|
8
|
+
success object and `{error}`. `ftp_read` retains text-only success and no
|
|
9
|
+
output schema; its errors still use the internally validated envelope.
|
|
10
|
+
Clients should use `isError` and the stable fields below, rather than parse
|
|
11
|
+
the localized human text.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"isError": true,
|
|
16
|
+
"content": [{ "type": "text", "text": "Error: READ_ONLY: …" }],
|
|
17
|
+
"structuredContent": {
|
|
18
|
+
"error": {
|
|
19
|
+
"schema_version": 1,
|
|
20
|
+
"code": "READ_ONLY",
|
|
21
|
+
"message": "…",
|
|
22
|
+
"retryable": false,
|
|
23
|
+
"request_id": "46d0223a-de77-4f28-bf77-f8b9706a4ecb",
|
|
24
|
+
"next_action": "fix_config",
|
|
25
|
+
"effects": "none"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`request_id` is a fresh server-generated UUID for one call. It is unrelated to
|
|
32
|
+
the JSON-RPC correlation ID and is not a durable operation identifier. No
|
|
33
|
+
`operation_id`. Durable errors additionally carry nullable `plan_id` and
|
|
34
|
+
`operation_id`, a phase, and durable partial counters. Those identifiers refer
|
|
35
|
+
only to the sealed journal workflow and are never JSON-RPC correlation IDs.
|
|
36
|
+
|
|
37
|
+
## Stable decisions and effect observations
|
|
38
|
+
|
|
39
|
+
The accepted `code` values are:
|
|
40
|
+
|
|
41
|
+
`CONFIG_REQUIRED`, `CONFIG_INVALID`, `SERVER_REQUIRED`, `SERVER_UNKNOWN`,
|
|
42
|
+
`INVALID_ARGUMENT`, `READ_ONLY`, `TRANSPORT_POLICY`, `HOST_KEY_REJECTED`,
|
|
43
|
+
`REMOTE_ROOT_REJECTED`, `PATH_REJECTED`, `NOT_FOUND`, `ALREADY_EXISTS`,
|
|
44
|
+
`TRANSFER_LIMIT`, `TRANSFER_VERIFY`, `TARGET_CHANGED`, `CANCELLED`, `TIMEOUT`,
|
|
45
|
+
`DEPLOY_PARTIAL`, `TRANSPORT_ERROR`, `OUTPUT_LIMIT`, `INTERNAL_ERROR`,
|
|
46
|
+
`SCAN_LIMIT`, `CAPACITY_LIMIT`.
|
|
47
|
+
|
|
48
|
+
Durable tools also use `DURABLE_STATE_DISABLED`, `DURABLE_STATE_BUSY`,
|
|
49
|
+
`DURABLE_STATE_LIMIT`, `DURABLE_STATE_CORRUPT`, `DURABLE_STATE_IO`,
|
|
50
|
+
`DURABLE_STATE_UNSUPPORTED`, `PLAN_NOT_FOUND`, `PLAN_EXPIRED`, `PLAN_STALE`,
|
|
51
|
+
`PLAN_CONSUMED`, `IDEMPOTENCY_CONFLICT`, `CONFIRMATION_DECLINED`,
|
|
52
|
+
`CONFIRMATION_INVALID`, `CLIENT_INTERACTION_UNSUPPORTED`, `STATUS_CHANGED`,
|
|
53
|
+
`RECONCILIATION_REQUIRED`, `ROLLBACK_CONFLICT`, and `WORKFLOW_UNSUPPORTED`.
|
|
54
|
+
State v1 is rejected before plan decoding and requires offline reinitialization.
|
|
55
|
+
|
|
56
|
+
`SCAN_LIMIT` refuses the complete local selection before connecting, with
|
|
57
|
+
`effects:none` and `next_action:fix_input`. `CAPACITY_LIMIT` refuses admission
|
|
58
|
+
before preparation, with `effects:none` and `next_action:retry`. Both keep
|
|
59
|
+
`retryable:false`; see [resource limits](./RESOURCE-BOUNDS.md).
|
|
60
|
+
|
|
61
|
+
The accepted legacy `next_action` values are `fix_input`, `fix_config`,
|
|
62
|
+
`select_server`, `inspect_target`, `retry`, `contact_operator`, and `none`.
|
|
63
|
+
Durable errors can additionally direct `status`, `resume_apply`,
|
|
64
|
+
`resume_rollback`, `offline_recovery`, or `upgrade_client`.
|
|
65
|
+
Legacy-tool errors conservatively return `retryable:false`. Durable errors set
|
|
66
|
+
`retryable:true` only for `DURABLE_STATE_BUSY`, `DURABLE_STATE_IO`,
|
|
67
|
+
`STATUS_CHANGED`, and mapped `TIMEOUT` or `TRANSPORT_ERROR` failures; all other
|
|
68
|
+
durable errors return `false`. The flag is guidance for the caller and never
|
|
69
|
+
authorizes an automatic retry: follow `next_action`, especially after any
|
|
70
|
+
`possible` or `confirmed` effect.
|
|
71
|
+
|
|
72
|
+
| `effects` | Meaning |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `none` | No mutating operation was dispatched by this call. |
|
|
75
|
+
| `possible` | Mutation was dispatched, without a confirmed effect yet. |
|
|
76
|
+
| `confirmed` | At least one effect was acknowledged; further uncertain effects may exist. |
|
|
77
|
+
|
|
78
|
+
Effects include temporary files, cleanup and local download writes. A remote
|
|
79
|
+
read-only policy does not prohibit local download writes. `confirmed` does
|
|
80
|
+
not mean that the entire operation succeeded, and zero completed files does
|
|
81
|
+
not prove that nothing changed. A transport close failure after promotion
|
|
82
|
+
retains confirmed effects.
|
|
83
|
+
|
|
84
|
+
Upload, download and deployment errors can include strict `partial` fields:
|
|
85
|
+
`completed_files`, `completed_bytes`, `failed_files`, optional `total_files`,
|
|
86
|
+
and `final`. Counts are safe nonnegative integers from observed promotions
|
|
87
|
+
and failed file attempts, not text parsing. Bytes count completed files;
|
|
88
|
+
they do not represent all network traffic or partially written temporaries.
|
|
89
|
+
`final: false` marks an early snapshot while the underlying worker still
|
|
90
|
+
settles. An early snapshot is not later revised on the wire.
|
|
91
|
+
|
|
92
|
+
## Protocol, cancellation and output boundaries
|
|
93
|
+
|
|
94
|
+
Arguments rejected by a known tool's declared input schema produce
|
|
95
|
+
`INVALID_ARGUMENT` before its handler, connection or filesystem write. Later
|
|
96
|
+
business-policy refusals can occur after connection. An unknown tool returns a
|
|
97
|
+
bounded JSON-RPC `-32602` protocol error without echoing its name. Malformed
|
|
98
|
+
protocol frames retain the SDK's protocol-error handling.
|
|
99
|
+
|
|
100
|
+
MCP peer cancellation aborts the operation, and the SDK suppresses its result;
|
|
101
|
+
clients must not expect a delivered `CANCELLED` envelope. Internal deadlines
|
|
102
|
+
are distinct and may return `TIMEOUT`. SDK v2 cancellation handles every valid
|
|
103
|
+
request ID natively, including numeric `0` and the empty string `""`. An
|
|
104
|
+
entry-owned wire guard reserves every inbound JSON-RPC request ID, across all
|
|
105
|
+
methods, before SDK dispatch. A duplicate active ID closes the connection before
|
|
106
|
+
a second handler runs, including a cross-method duplicate. A tool-call ID is
|
|
107
|
+
released only after both its terminal response send settles or fails and its
|
|
108
|
+
all registered handler-turn workers, preparation and disposal settle, including
|
|
109
|
+
all legacy input-required rounds. If peer cancellation suppresses
|
|
110
|
+
the response, the ID remains reserved until the connection closes. Concurrent
|
|
111
|
+
different IDs, including `0`, `""`, `1` and `"0"`, remain independent. A
|
|
112
|
+
response whose send already started cannot be recalled. Cancellation does not
|
|
113
|
+
undo effects.
|
|
114
|
+
|
|
115
|
+
Known tool results are redacted, bounded and validated once at the boundary.
|
|
116
|
+
The 25,000-byte limit covers UTF-8 `JSON.stringify` of the complete result,
|
|
117
|
+
including both text and structured data, after redaction expansion. Required
|
|
118
|
+
security notices have a separate trusted rendering role. Remote strings such
|
|
119
|
+
as `Page:` and `SECURITY WARNING` cannot acquire that role. Pagination is
|
|
120
|
+
rebuilt after sample shrinking. An `OUTPUT_LIMIT` fallback preserves request
|
|
121
|
+
UUID, effects and observed partial counters.
|
|
122
|
+
|
|
123
|
+
Typed decisions precede translation. Native diagnostic details remain source
|
|
124
|
+
data under a localized wrapper; ambiguous FTP responses, including code 550,
|
|
125
|
+
do not become `NOT_FOUND` based on prose. Secrets are masked in free text.
|
|
126
|
+
Only schema-specific public constants and the UUID minted for this result
|
|
127
|
+
are preserved at their exact structured paths. Error objects, causes, stacks,
|
|
128
|
+
credentials and raw arguments are not serialized. Configuration credentials
|
|
129
|
+
are collected privately before validation, including values from rejected
|
|
130
|
+
entries and resolved environment placeholders. Public loader diagnostics use
|
|
131
|
+
the same mask. Malformed JSON receives a generic syntax diagnostic with no
|
|
132
|
+
parser excerpt; no reliable secret extraction from malformed input is claimed.
|
|
133
|
+
Rejected FileZilla blocks are identified by their numeric block index without
|
|
134
|
+
echoing untrusted names or protocol fields.
|
|
135
|
+
|
|
136
|
+
See [languages](./LANGUAGES.md), the [security model](./SECURITY-MODEL.md)
|
|
137
|
+
and [verified transfers](./TRANSFERS.md) for the remaining operational limits.
|