Nouveaux documents :
- README.md : porte d'entrée humaine, absente jusqu'ici. Objet du projet,
installation, npm test, branchement Claude Desktop, ajout d'un profil WMS,
compilation de l'exécutable.
- DECISIONS.md : 20 décisions et pièges vérifiés sur un WMS réel (D1..D20),
chacun avec son pourquoi. Extrait ce qui était noyé dans CLAUDE.md :
100 % API, tenant_code OAuth, réponses {entities}, casse des propriétés,
dotenv sur stderr, dates relatives LINQ non traduisibles, absence de
CommandParameterData, etc.
- MONITORING.md : supervision du serveur MCP. Préfixes de logs, séquence
d'un démarrage sain, cycle de vie du token OAuth et ses trois filets,
état des caches, table symptôme -> cause. Une section dit explicitement
ce qui n'est pas instrumenté (ni healthcheck, ni métriques, ni alerte).
- docs/logs.md : accès aux logs du WMS. Chemins, placeholder {host},
blocage volontaire sur les profils SaaS, les trois outils, format des
lignes, limites connues.
Mises à jour :
- CLAUDE.md réécrit et aligné sur le code. Correction de l'écart le plus
gênant : le code utilise QueryType 0 (Reading), la doc annonçait 1, soit
l'inverse de ce qui fonctionne pour les comparaisons de statut par
chaîne. Corrigés également : 6 resources et non 7 (workflows://categories
n'existe pas), section .env mono-profil obsolète, références à des
fichiers de test absents, README annoncé mais inexistant. Le suivi de
projet et les checklists de phases sont retirés.
- docs/README.md : index réel du dossier. L'ancien promettait une resource
docs:// qui n'a jamais existé.
- docs/getting_started.md : avertissement en tête, c'est une capture
partielle du portail Mecalux dont les liens internes ne résolvent pas.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.9 KiB
Supervision du serveur MCP
Comment savoir si le serveur tourne, ce qu'il fait, et pourquoi il ne répond
pas. Ce document décrit l'existant — il n'y a ni endpoint de santé, ni
métriques exportées : toute l'observabilité passe par stderr et par le
smoke test npm test.
Pour lire les logs du WMS (et non ceux du serveur MCP), voir docs/logs.md.
1. Où regarder
| Quoi | Où |
|---|---|
| Logs du serveur MCP | %APPDATA%\Claude\logs\ (fichier mcp-server-wms.log) |
| Logs applicatifs du WMS | partages \\<host>\... — voir docs/logs.md |
| État de la connexion WMS | npm test (voir §5) |
| Profil actif / caches | outils get_current_wms_profile, get_application_summary |
Tout passe par stderr. stdout est réservé au JSON du protocole MCP : la moindre écriture sur stdout casse la session Claude Desktop (voir D6 dans DECISIONS.md). En pratique, cela veut dire que les logs sont la seule sortie observable, et qu'ils sont complets.
Suivre les logs en direct :
Get-Content -Wait -Tail 50 "$env:APPDATA\Claude\logs\mcp-server-wms.log"
2. Lire les préfixes
Chaque ligne est préfixée par son composant. Le préfixe suffit à localiser le problème.
| Préfixe | Composant | Ce qu'il signale |
|---|---|---|
[Server] |
src/index.js |
démarrage, routage des outils, erreurs non rattrapées |
[Profile] |
config/profile-manager.js |
chargement des profils, bascule de profil |
[API] |
services/api-service.js |
OAuth, chaque requête HTTP, retries 401 |
[Workflow] |
services/workflow-service.js |
cache workflows, pagination |
[AD] |
services/ad-service.js |
cache par type d'élément, pagination |
[Logs] |
services/log-service.js |
chemins de logs illisibles ou absents |
[WMSQuery], [Metadata] |
services | construction des requêtes |
[*Tools] |
src/tools/ |
exécution d'un outil précis |
3. Démarrage : à quoi ressemble un boot sain
[dotenv@17.2.4] injecting env (30) from .env
[Profile] Loaded 3 profile(s). Active: LIMAGRAIN
[Server] Starting WMS MCP Server...
[Server] Architecture: 100% API-based (no direct database access)
[Server] Profiles available: AD, EUROTRAFIC, LIMAGRAIN
[Server] Active profile: LIMAGRAIN
[Server] WMS MCP Server running on stdio
[Server] Ready to accept requests from Claude Desktop
Trois points à contrôler dans cet ordre :
injecting env (N)— siNvaut 0, le.envn'a pas été trouvé. En mode packagé il est attendu à côté de l'exe (D7).Loaded N profile(s)— si 0,WMS_PROFILESest vide ou les variables<NOM>_HOST/USERNAME/PASSWORD/TENANTmanquent.Active profile: …— si le message estNo active profile, ce n'est pas une panne : Claude doit appelerswitch_wms_profileavant la première requête, et l'erreur renvoyée le lui indique explicitement (D8).
Aucune connexion au WMS n'est tentée au démarrage : un boot propre ne prouve donc pas que le WMS est joignable. Pour cela, voir §5.
4. Cycle de vie du token OAuth
Le token est obtenu paresseusement, à la première requête, puis rafraîchi
automatiquement. Réglages dans .env :
| Variable | Défaut | Rôle |
|---|---|---|
TOKEN_REFRESH_THRESHOLD |
1000 s |
âge au-delà duquel un refresh est déclenché avant la requête |
TOKEN_MAX_AGE |
1190 s |
âge au-delà duquel on ne tente plus le refresh_token mais une ré-authentification complète |
QUERY_TIMEOUT |
30000 ms |
timeout HTTP de toute requête WMS |
Séquence observable :
[API] Authenticating profile="LIMAGRAIN" tenant="LIMAGRAI2512" ...
[API] Authentication successful. Token expires in ~1190s
[API] POST /QueryExecute
... (~17 min plus tard)
[API] Refreshing token with refresh_token grant...
[API] Token refreshed successfully
Trois filets de sécurité, dans cet ordre :
- Avant la requête — si
âge > TOKEN_REFRESH_THRESHOLD, refresh préventif. - Refresh en échec — bascule automatique sur le grant
password([API] Token refresh failed, re-authenticating). - Réponse 401 — un refresh est déclenché et la requête est rejouée une
fois (
[API] Unauthorized, refreshing token and retrying...).
Ce qui est normal. Une ligne Token refresh failed isolée suivie d'une
authentification réussie : le filet a joué son rôle.
Ce qui ne l'est pas. Ces trois lignes en boucle rapprochée signalent des credentials invalides ou un tenant erroné — le serveur n'abandonne jamais de lui-même, il retentera à chaque requête.
5. Test de bout en bout
npm test
Teste le profil actif ; npm test -- AD cible un profil, npm test -- --all
les teste tous. Quatre vérifications en lecture seule, aucune écriture WMS :
| Test | Ce qu'il prouve |
|---|---|
| OAuth | host joignable, credentials et tenant corrects |
QueryExecute |
API ApplicationService opérationnelle |
QueryScalarExecute |
requêtes scalaires (Count) opérationnelles |
AD API (Validator) |
API Application Dictionary opérationnelle |
Sortie attendue :
=== Profil LIMAGRAIN ===
host=10.255.255.2 tenant=LIMAGRAI2512 saas=false
OK OAuth - token obtenu (age max ~1190s)
OK QueryExecute - 1 ligne(s)
OK QueryScalarExecute - 51160 produit(s)
OK AD API (Validator) - 10 element(s)
-> 4/4 tests reussis
Code de sortie 0 si tout passe, 1 sinon — utilisable tel quel dans une
tâche planifiée.
C'est le premier réflexe quand Claude signale une erreur WMS : il isole en quelques secondes une panne de connectivité d'un problème de requête.
6. État des caches
Deux caches, TTL commun WORKFLOW_CACHE_TTL (1 h par défaut), tous deux vidés
à chaque switch_wms_profile (D8).
| Cache | Contenu | Purge |
|---|---|---|
| workflows | ~3 700 workflows | TTL, ou bascule de profil |
| AD | un cache par type (20 types, ~38 800 éléments) | TTL par type, ou bascule de profil |
Les inspecter sans redémarrer : l'outil get_application_summary liste les
types chargés et leur nombre d'éléments — un type absent signifie simplement
qu'il n'a jamais été demandé dans cette session (D10).
Signature d'un chargement dans les logs :
[AD] Cache expired or empty, fetching Resource...
[AD] Fetching Resource: offset=0, pageSize=15000
[AD] Fetched 15000 Resource (total: 15000)
[AD] Fetching Resource: offset=15000, pageSize=15000
...
[AD] Successfully cached 29374 Resource
[AD] Cache hit: Resource (29374 elements) <- appels suivants
Une première requête sur Resource prend plusieurs dizaines de secondes : ce
n'est pas un blocage, c'est la pagination. Les suivantes sont instantanées.
7. Symptômes → causes
| Symptôme | Cause probable | Vérification |
|---|---|---|
| Le serveur n'apparaît pas dans Claude Desktop | chemin invalide dans claude_desktop_config.json, ou Claude pas redémarré |
ouvrir %APPDATA%\Claude\logs\ |
Unexpected token … is not valid JSON |
quelque chose a écrit sur stdout | chercher un console.log() ajouté (D6) |
injecting env (0) |
.env introuvable |
en packagé : le placer à côté de l'exe (D7) |
No WMS profile selected |
DEFAULT_WMS_PROFILE absent ou invalide |
c'est un état normal — appeler switch_wms_profile |
Authentication failed: … 400 |
tenant_code ou credentials erronés |
npm test -- <PROFIL> (D2) |
Boucle refresh failed / Authenticating |
credentials invalides | npm test |
ETIMEDOUT / ECONNREFUSED |
host injoignable (VPN, pare-feu) | Test-NetConnection <host> -Port 443 |
timeout of 30000ms exceeded |
requête trop lourde | ajouter un Where, réduire take, ou augmenter QUERY_TIMEOUT |
Successfully cached 0 workflows |
réponse non enveloppée par entities |
D4 |
| Recherche vide sur un élément existant | casse des propriétés (name vs Name) |
D5 |
Log access is disabled for SaaS profile |
profil SAAS=true |
comportement voulu (D9), utiliser les outils API |
| Erreur de compilation LINQ sur une date | DateTime.Now employé |
date littérale (D12) |
8. Ce qui n'est pas instrumenté
À connaître avant de promettre une supervision qui n'existe pas :
- Pas de healthcheck exposé, ni HTTP ni MCP.
npm testest le seul contrôle automatisable, et il faut le lancer soi-même. - Pas de métriques : ni compteur d'appels, ni latence, ni taux d'erreur.
- Pas de fichier de log propre au serveur : tout est capté par Claude Desktop, avec sa rotation à lui.
- Pas d'alerte : une panne d'authentification n'est visible qu'au prochain appel d'un outil.
uncaughtExceptionetunhandledRejectionsont journalisés mais n'arrêtent pas le processus (src/index.js). Le serveur peut donc survivre dans un état dégradé — d'où l'intérêt de relire les logs jusqu'au début en cas de comportement erratique, et non seulement la dernière erreur.