Un LLM appelle directement des outils (MCP)
tools/war3_mcp.py est un serveur MCP. Branchez-le sur Claude Code, Claude Desktop ou n’importe quel client compatible MCP : le LLM peut alors observer directement la partie, donner des ordres, parler au joueur à l’écran, lui poser des questions avec des cartes et prendre des captures d’écran, sans écrire de code au préalable.
tools/war3_mcp.py est un serveur MCP (stdio). Claude Code, Claude Desktop, un framework d’agents pour modèles locaux — branchez-le sur n’importe quel client compatible MCP, et le LLM peut directement observer la partie, donner des ordres, parler au joueur sur l’écran du jeu, lui poser des questions et prendre des captures d’écran, sans écrire de code au préalable.
Après l’écriture de Bots, le rôle de conseiller et les unités qui parlent, c’est une autre façon de se brancher : le LLM utilise lui-même les outils.
Brancher le serveur
claude mcp add war3 -- python <dépôt>\tools\war3_mcp.py --inst 9 # Claude Code ; remplacez <dépôt> par votre dossier openwar3
Pour les autres clients, écrivez la configuration sur ce modèle :
{"mcpServers": {"war3": {"command": "python", "args": ["<dépôt>\\tools\\war3_mcp.py", "--inst", "9"]}}}
La connexion au jeu n’a lieu qu’au premier appel d’outil : le jeu peut donc être lancé après ; s’il est fermé puis relancé, l’appel suivant se reconnecte automatiquement. Ajoutez --role pour limiter ce que le LLM peut faire :
| Rôle | Peut utiliser |
|---|---|
dev (par défaut) | Tous les outils, y compris war3_jass |
player --player N | Ne commande que les unités du joueur N et ne voit que ce qui est dans sa vision (mode équitable) ; pas de JASS |
observer | Lecture seule, ne peut rien dessiner à l’écran ni faire parler les unités ; le runtime rejette directement ses commandes |
Le rôle player a les mêmes limites que dans la passerelle : pas de fin de partie, de changement de vitesse ni de pause, pas d’accès aux interfaces qui dévoilent le jeu caché des autres, et les requêtes avec un numéro de joueur ne portent que sur lui-même.
Quelques plafonds : un résultat d’outil fait au plus 200 000 caractères, et au-delà il est tronqué avec une indication pour réduire la portée de la requête ; war3_ask_player attend au plus 120 secondes ; le scale des captures d’écran est compris entre 0.1 et 1.
Outils
| Outil | Ce qu’il fait |
|---|---|
war3_overview | La partie en une page : temps, ressources, nourriture, effectifs de chacun de nos types d’unités, héros (PV, mana, niveau, recharges), types d’unités ennemies visibles, production. À appeler en premier |
war3_units | Liste des unités (owner vaut me / enemy / creep / all, filtre types) ; addr sert à donner des ordres |
war3_events | Ce qui s’est passé depuis l’appel précédent : morts, montées de niveau, sorts lancés, productions terminées, chat, clics du joueur sur les boutons… (par défaut sans les quelques types qui inondent le flux) |
war3_call | Appelle n’importe quelle interface publique (move, attack_move, train, build, cast, learn, ui.button, canvas.text…) ; une unité s’écrit {"unit": addr} |
war3_api | Recherche dans les interfaces : par mot-clé, dans les noms et les descriptions |
war3_toast / war3_say | Une ligne de texte en haut de l’écran / une phrase au-dessus d’une unité |
war3_ask_player | Présente quelques cartes de choix au centre de l’écran, attend le clic du joueur et renvoie son choix (peut mettre le jeu en pause) |
war3_screenshot | Capture de l’écran du jeu (PNG ; fonctionne même si la fenêtre est masquée, sans lui voler le focus) |
war3_jass | Exécute un bout de JASS (réservé à dev ; modification du monde en solo uniquement) |
Ce qu’on peut en faire :
- Partenaire de jeu / coach :
war3_overviewpour lire la partie,war3_toastpour afficher des conseils à l’écran ; - Consulter le joueur en cours de partie :
war3_ask_playeraffiche trois cartes, et on suit celle sur laquelle le joueur clique ; - Commentaire :
war3_eventspour lire ce qui s’est passé,war3_saypour que les unités le racontent elles-mêmes ; - Commander directement une armée : rôle
player+war3_call, qui ne peut déplacer que ses propres unités ; - Ajuster l’interface en regardant l’image : une capture avec
war3_screenshotpour vérifier que les boutons dessinés sont bien placés.
À quoi ressemble une conversation
Vous : regarde où en est la partie, puis demande-moi à l'écran : prochaine étape, expansion, masser des troupes ou monter de tier ?
→ war3_overview {}
← La partie en une page : temps de jeu, or 500, nourriture 10/12, chez nous htow 1 · hpea 5 · Hpal 1, aucun ennemi en vue, aucune production en cours
→ war3_ask_player {"question": "Prochaine étape ?", "options": ["Masser des troupes", "Expansion", "Monter de tier"], "pause": true}
← {"picked": 1, "option": "Expansion"}
Modèle : vous avez choisi l'expansion. Je cherche d'abord un paysan inactif avec war3_units, puis la mine d'or la plus proche…
Mesures
2026-09-25 :
- Notre propre client MCP connecté à une vraie partie, 7/7 : poignée de main → liste des outils (10) →
war3_overview(htow1,hpea5) →war3_units→war3_toast→war3_screenshot(PNG d’environ 200 Ko) →war3_ask_player(trois cartes, clic simulé sur la deuxième →{"picked": 1, "option": "Expansion"}). - Claude Code 2.1 réellement branché : il lance lui-même le serveur et fait la poignée de main, l’état est
connected, et les 10 outils apparaissent dans sa liste d’outils sous la formemcp__war3__*.
Implémentation
- JSON-RPC 2.0 délimité par des retours à la ligne (
initialize/tools/list/tools/call/ping), version de protocole 2025-06-18, compatible avec 2025-03-26 et 2024-11-05. - Les erreurs d’outil sont placées dans le résultat, conformément aux règles de MCP (
isError: true), sans couper la connexion. - Partage avec la passerelle la même liste blanche de rôles, le même format de paramètres d’unité et la même « partie en une page ».
- Les journaux vont sur stderr ; stdout ne contient que le protocole.