Files
mcp-wms-api/ROADMAP.md
T
Arthur Ria 1a1b9ebe03 Roadmap : lots de correction issus du diagnostic du 24/08
Ajoute ROADMAP.md et le relie depuis README.md et CLAUDE.md.

Origine : un rapport d'usage d'une session Cowork sur le profil LIMAGRAIN a
signalé 8 anomalies. Vérification faite contre le WMS réel, 4 bugs sont
confirmés et reproduits, dont un non signalé par le rapport.

Cause racine commune : entity_type est interpolé dans Context.{entity_type}
sans aucune validation, alors que le nom attendu est le TableName de l'API
Metadata et non le nom d'entité de l'AD. Container -> Containers, mais
Alias -> Alias : c'est un mapping, pas une règle de pluralisation. L'API
Metadata connaît 232 entités là où le MCP en expose 12 en dur, et la liste
documentée était fausse (Aliases n'existe pas).

Lot 1 (déblocage) : corps des erreurs HTTP remonté, routage des outils par
table explicite, projections de champs des workflows.
Lot 2 (fond) : résolution des entités via l'API Metadata, rejet des
paramètres inconnus.
Lot 3 : bornage des sorties volumineuses, documentation.

Trois propositions du rapport sont explicitement écartées, avec leur raison :
uniformisation des noms de paramètres, indexStatus sur generic_search, outil
dédié d'aide à la syntaxe.

CLAUDE.md : la section « Points ouverts » renvoie désormais vers la roadmap et
avertit des deux pièges non encore corrigés.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:39:08 +02:00

172 lines
6.9 KiB
Markdown

# Roadmap
Travaux planifiés, par lot. Chaque lot est livrable indépendamment.
Constats issus de la session de diagnostic du **24/08/2026** (profil `LIMAGRAIN`,
host `10.255.255.2`, tenant `LIMAGRAI2512`), déclenchée par un rapport d'usage
d'une session Cowork. Toutes les anomalies ci-dessous ont été **reproduites**
contre le WMS réel — ce ne sont pas des hypothèses.
Les décisions actées vivent dans [DECISIONS.md](DECISIONS.md) ; ce fichier ne
contient que ce qui reste à faire.
---
## Cause racine commune
Le MCP interpole `entity_type` dans `Context.{entity_type}` **sans aucune
validation** (vérifié : aucune liste blanche dans le code). Or le nom attendu
par le contexte de lecture n'est pas le nom d'entité de l'Application
Dictionary.
L'API Metadata (`GET /Metadata/Entities`, **232 entités**) donne la
correspondance exacte :
| `Name` (renvoyé par `search_ad_elements`) | `TableName` (attendu par `Context.`) |
|---|---|
| `Container` | `Containers` |
| `Product` | `Products` |
| `ContainerType` | `ContainerTypes` |
| `Alias` | `Alias`**invariant, pas de pluriel** |
| `Item` | *n'existe pas dans le modèle Reading* |
Ce n'est donc pas une règle de pluralisation : c'est un mapping, et seul
`TableName` fait foi. `TableName` est unique sur les 232 entités.
Conséquences déjà constatées :
- une session utilisant les noms de l'AD (singuliers) déclenche un **HTTP 500**
sur chaque requête ;
- la liste d'entités documentée était fausse (`Aliases` n'existe pas, c'est
`Alias`) ;
- le MCP n'expose que 12 entités figées là où l'API en connaît 232.
---
## Lot 1 — Déblocage
Objectif : rendre le MCP auto-diagnosticable et réparer ce qui est cassé. Ce lot
seul aurait suffi à ce qu'une session se débrouille sans intervention.
### L1.1 — Remonter le détail des erreurs HTTP
Aujourd'hui toute erreur d'API se résume à `Request failed with status code 500`.
Or le WMS renvoie déjà le diagnostic complet dans le corps de la réponse :
```json
{"ClassName":"System.AggregateException","Message":"Compile Error: ...
'ApplicationReadingContext' ne contient pas de définition pour 'Container' ..."}
```
Enrichir l'erreur au point de passage unique (`api-service.post` / `.get`) avec :
statut, URL, verbe, payload envoyé, corps de réponse tronqué à ~2000 caractères.
**Fichier :** `src/services/api-service.js` (catch de `post` et `get`).
### L1.2 — Fiabiliser le routage des outils
Deux outils sont listés dans `tools/list` mais ne sont routés vers aucun module,
à cause du routage par préfixe :
| Outil | Cause | Erreur observée |
|---|---|---|
| `get_entity_metadata` | capté par `startsWith('get_entity_')` avant sa propre branche | `Unknown WMS query tool` |
| `list_log_files` | ne contient pas `_logs` mais `_log_files` | `Unknown tool` |
Remplacer le routage par préfixe par une **table explicite nom → module**,
construite depuis les `listTools()` de chaque module. Un outil listé mais non
routé devient alors impossible par construction, au lieu d'être rattrapé au cas
par cas.
**Fichier :** `src/index.js` (handler `tools/call`).
### L1.3 — Corriger les projections de champs des workflows
L'API AD renvoie les champs en minuscules (`id`, `name`, `version`,
`applicationName`). Deux endroits supposent une autre forme :
- `search_workflows` projette `w.Id`, `w.Code`, `w.Name`, `w.Category` → tous
`undefined`, supprimés par `JSON.stringify`**50 objets vides** pour un
`count` pourtant correct ;
- `workflow-service` lit `w.category || w.Category`, deux clés inexistantes →
`list_workflow_categories` renvoie **0 catégorie** et classe les 4012
workflows en `Uncategorized`.
Le champ le plus proche d'une catégorie est `applicationName`, mais il vaut
`EasyWMS` pour tous les workflows : la notion de catégorie n'a **aucun support**
dans les données. Décider en connaissance de cause plutôt que d'inventer une
taxonomie.
**Fichiers :** `src/tools/workflow-tools.js`, `src/services/workflow-service.js`.
---
## Lot 2 — Correctif de fond
### L2.1 — Résolution des entités via l'API Metadata
Accepter `entity_type` au nom d'entité (`Container`) ou au nom de jeu
(`Containers`), insensible à la casse, et émettre `Context.{TableName}`. Cache
identique aux autres (TTL partagé, invalidation au changement de profil).
Sur nom inconnu, échouer **avant tout appel réseau**, avec un message
actionnable :
> « Item » n'existe pas dans le modèle Reading. Proches : ItemGroup, StockItem.
> 232 entités disponibles — utilisez `get_entity_metadata` pour la liste.
Supprime la cause des 500 et débloque 232 entités au lieu de 12.
### L2.2 — Rejeter les paramètres inconnus
Le SDK MCP ignore silencieusement les paramètres non déclarés : un appel
`read_recent_logs(lines: 60)` retombe sur le défaut `count = 100` sans le
moindre signal, et l'appelant conclut à un paramètre ignoré.
Ajouter `additionalProperties: false` aux 23 schémas d'outils.
C'est le correctif retenu **à la place** d'une uniformisation des noms de
paramètres : renommer casse les usages existants pour un gain cosmétique, alors
que la cause réelle est l'absence de signal.
---
## Lot 3 — Ergonomie et documentation
### L3.1 — Bornage des sorties volumineuses
- `get_system_parameters` : ajouter `limit` / `offset`, aujourd'hui absents
(sortie constatée : 70 000 caractères, rejetée par le client).
- `search_logs` : garde-fou de taille. `max_results` existe déjà, mais les
`context_lines` multiplient le volume (88 000 caractères pour 50 résultats).
- Renvoyer `truncated: true` explicitement plutôt que de laisser le client se
faire rejeter.
### L3.2 — Documentation
- DECISIONS.md : **D21** la règle `TableName`, **D22** le routage par table
explicite.
- CLAUDE.md : corriger la liste d'entités (`Aliases``Alias`) et renvoyer vers
`get_entity_metadata` comme source de vérité.
- `wms://query-examples` : un exemple singulier/pluriel commenté.
---
## Écarté
| Proposition | Raison |
|---|---|
| Uniformiser les noms de paramètres (`entity_type` / `query` partout) | Casse les usages existants ; les alias de transition doublent la surface à maintenir. La cause réelle est traitée par L2.2. |
| Exposer un `indexStatus` sur `generic_search` | `TotalDocuments: 0` est déjà le signal. Le MCP n'a aucun moyen d'interroger l'état de l'index de recherche. |
| Outil dédié `get_query_syntax_help` | L'information doit se trouver dans le message d'erreur, là où elle est lue (L2.1), pas dans un outil qu'il faut penser à appeler. |
---
## Points ouverts (hors lots)
- **`select_expression`** : les projections via le paramètre `Select` provoquent
des erreurs de compilation côté serveur (D13). Irritant principal restant.
- **Déploiement SSH sur la VM** : l'exécutable est validé, la configuration SSH
reste à faire.
- **Historique des shipment templates** : hors de portée, les logs concernés
n'existent pas sur l'hôte joignable (D16).