Les services lisaient `response?.entities || []` sur les reponses de l'API AD
(enveloppe { entities: [...] }, D4). Toute reponse d'une AUTRE forme — corps
vide, objet d'erreur, champ absent — devenait donc un tableau vide,
indistinguable d'une page finale legitime, et etait mise en cache avec un
timestamp valide : un cache vide empoisonne pour tout le TTL, sans le moindre
message. C'est la cause probable du `count: 0` mesure sous rafale, et le mode
d'echec le plus couteux du lot, parce qu'il se lit comme une reponse.
Le contrat est porte par src/services/ad-envelope.js pour les trois sites
(Workflow/GetByApplication, Application/GetAll, <Type>/GetByApplication) :
`{ entities: [...] }`, `[]` reel compris, est rendu tel quel ; toute autre
forme leve. entity-resolver etait deja conforme — il leve deja si
/configuration/applications ou le Metadata ne rendent aucune entite.
Volontairement sans retry ni logique de resilience : le but est de rendre
l'anomalie visible et non persistante. La rattraper la rendrait invisible,
c'est-a-dire exactement le defaut corrige.
--- Verifications (LIMAGRAIN) ---
Vide LEGITIME — search_workflows sur SmartUI (0 workflow, D26) :
search_workflows(SmartUI) : success=true application=SmartUI count=0
isError=false
error : (aucune)
hint : Aucun workflow trouve dans l'application "SmartUI" — c'est la
SEULE interrogee, les autres ne le sont jamais implicitement.
Le specifique client (prefixe CST_) vit dans "CustomApp" : [...]
cache pose ? workflowCachesByApplication =
{"SmartUI":{"cached":true,"count":0,"timestamp":1787665868988,
"age":0,"valid":true}}
stderr : No more workflows to fetch / Successfully cached 0 workflows
Forme SANS `entities` — non declenchable a la demande contre le vrai WMS,
couverte par un test direct (apiService.post substitue, renvoie {}) :
--- workflow-service fetchAllWorkflows("EasyWMS") avec une reponse {} ---
erreur levee : Failed to fetch workflows for application "EasyWMS":
Reponse inattendue de l'API AD sur Workflow/GetByApplication
(application "EasyWMS", offset 0) : un objet vide, au lieu de
l'enveloppe attendue { entities: [...] }. Rien n'a ete mis en cache —
relancez l'appel. Si l'erreur persiste, l'API AD est en defaut [...]
cache : {} (attendu {})
--- workflow-service fetchApplications() avec une reponse {} ---
erreur levee : Reponse inattendue de l'API AD sur Application/GetAll : [...]
cache : {} (attendu {})
--- ad-service getElements("Command") avec une reponse {} ---
erreur levee : Failed to fetch Command for application "EasyWMS": [...]
cache : {} (attendu {})
--- puis une reponse normale : le refetch repart (rien de coince) ---
1 workflow(s), cache : {"EasyWMS":{"cached":true,"count":1,...}}
Cas nominaux du helper (unitaire) : { entities: [] } et { entities: [1,2] }
passent ; {}, null, undefined, [], { error }, "texte" levent tous.
--- Non-regression, rafales rejouees 3 fois ---
L6.1 rafale workflow RUN 1/2/3 : 6/6 a count=44 | fetch=1 joins=5
L6.1 rafale resolver RUN 1/2/3 : 6/6 succes | chargements=1 joins=5 GET=5
L6.1 rafale mixte RUN 1/2/3 : CustomApp@44=3 EasyWMS@50=3 |
fetch=2 joins=4
L6.2 bascule RUN 1/2/3 : caches peuples : 0 (attendu 0)
sequentiel nominal count=50 puis count=50 | fetch=1 cached=1 joins=0
Baseline finale : tools/list 23, resources/list 6 ; npm test 4/4, exit 0.
ROADMAP : lot 6 retire. Le point ouvert « bascule de profil concurrente aux
appels en vol » reste — D27 borne les chargements paresseux, pas le routage
d'une requete deja partie.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WMS MCP Server
Serveur MCP qui donne à Claude un accès en lecture à un WMS EasyWMS (Mecalux), pour le diagnostic et l'analyse.
Concrètement, dans Claude Desktop :
« Combien de commandes sont bloquées en statut Release sur LIMAGRAIN ? » « Trouve les workflows qui touchent au réapprovisionnement. » « Cherche
Order 4711dans les logs. » « Quels paramètres sont surchargés sur l'entrepôt 2 ? »
Architecture : 100 % API REST. Aucun accès direct à Oracle — voir D1 dans DECISIONS.md.
Ce que le serveur expose
23 outils répartis en 8 familles :
| Famille | Outils |
|---|---|
| Requêtes WMS | query_wms_entities, count_wms_entities, get_entity_schema, search_wms_data |
| API brutes | call_query_api, execute_command |
| Workflows | search_workflows, get_workflow_details, list_workflow_categories |
| Application Dictionary | get_application_summary, get_ad_elements, search_ad_elements, get_ad_element_details, list_ad_types |
| Métadonnées | get_entity_metadata, generic_search |
| Configuration | get_system_parameters |
| Profils | list_wms_profiles, get_current_wms_profile, switch_wms_profile |
| Logs | read_recent_logs, list_log_files, search_logs |
6 resources de contexte : wms://entities, wms://entity-schemas,
wms://query-examples, workflows://overview, api://catalog, logs://guide.
Multi-WMS. Plusieurs backends (clients, tenants) coexistent dans un seul
serveur ; Claude bascule à la demande avec switch_wms_profile.
Installation
Prérequis : Node.js 18+ et un accès réseau au WMS (VPN si nécessaire).
npm install
Copiez .env.example en .env et renseignez au moins un profil :
WMS_API_AUTH=Basic R05BOklFNGU3aXFoZHQ=
WMS_APPLICATION=EasyWMS
WMS_API_PATH=/ApplicationService/api
WMS_TOKEN_PATH=/EasySTS/OAuth/Token
WORKFLOW_API_PATH=/AD/api
WMS_PROFILES=AD
DEFAULT_WMS_PROFILE=AD
AD_HOST=10.255.255.2
AD_USERNAME=...
AD_PASSWORD=...
AD_TENANT=AD
AD_SAAS=false
Vérifiez la connectivité — le test est en lecture seule :
npm test
Sortie attendue : 4/4 tests reussis. En cas d'échec, voir
MONITORING.md §7.
Brancher Claude Desktop
Éditez %APPDATA%\Claude\claude_desktop_config.json :
{
"mcpServers": {
"wms": {
"command": "node",
"args": ["D:\\chemin\\vers\\mcp-wms-api\\src\\index.js"]
}
}
}
Puis fermez et rouvrez complètement Claude Desktop. Les logs du serveur
apparaissent dans %APPDATA%\Claude\logs\.
Ajouter un WMS
- Ajoutez son nom à
WMS_PROFILES(séparateur : virgule). - Définissez
<NOM>_HOST,<NOM>_USERNAME,<NOM>_PASSWORD,<NOM>_TENANT. - Mettez
<NOM>_SAAS=truesi le WMS est hébergé dans le cloud Mecalux — les outils de log seront alors désactivés pour ce profil, à dessein.
Les URL se construisent à partir du host : rien d'autre à dupliquer. Testez
avec npm test -- <NOM>.
Compiler un exécutable Windows
npm run build
Produit dist/wms-mcp-server.exe (~76 Mo, autonome, cible node22-win-x64).
Placez le .env à côté de l'exe : en mode packagé, c'est là qu'il est lu,
et aucun credential n'est embarqué dans le binaire (D7). Les avertissements
Cannot find module '@modelcontextprotocol/sdk/…' pendant le build sont
normaux et sans effet (D18).
Déploiement type sur la VM :
C:\WMS\mcp\wms-mcp-server.exe
C:\WMS\mcp\.env
Documentation
| Fichier | Contenu |
|---|---|
| CLAUDE.md | Architecture, inventaire des outils, conventions de code |
| DECISIONS.md | Pourquoi le code est ainsi + pièges vérifiés en production |
| MONITORING.md | Superviser le serveur MCP : logs, token, caches, symptômes |
| ROADMAP.md | Travaux planifiés par lot, et ce qui a été écarté |
| docs/logs.md | Accès aux logs du WMS |
| docs/ | Références EasyWMS (API, entités) |
Sécurité
.envetdist/sont ignorés par git — ne les committez jamais.- La validation TLS est désactivée pour accepter les certificats auto-signés des WMS on-premise (D15).
- ⚠️ L'historique git contient un ancien fichier de configuration avec des mots
de passe en clair (commit
b59cbb3). Ces credentials sont à considérer comme compromis — voir D20.