# 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).