Sur cette page
Docs Faire écrire un Bot par l’IA

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ôlePeut utiliser
dev (par défaut)Tous les outils, y compris war3_jass
player --player NNe commande que les unités du joueur N et ne voit que ce qui est dans sa vision (mode équitable) ; pas de JASS
observerLecture 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

OutilCe qu’il fait
war3_overviewLa 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_unitsListe des unités (owner vaut me / enemy / creep / all, filtre types) ; addr sert à donner des ordres
war3_eventsCe 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_callAppelle n’importe quelle interface publique (move, attack_move, train, build, cast, learn, ui.button, canvas.text…) ; une unité s’écrit {"unit": addr}
war3_apiRecherche dans les interfaces : par mot-clé, dans les noms et les descriptions
war3_toast / war3_sayUne ligne de texte en haut de l’écran / une phrase au-dessus d’une unité
war3_ask_playerPré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_screenshotCapture de l’écran du jeu (PNG ; fonctionne même si la fenêtre est masquée, sans lui voler le focus)
war3_jassExé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_overview pour lire la partie, war3_toast pour afficher des conseils à l’écran ;
  • Consulter le joueur en cours de partie : war3_ask_player affiche trois cartes, et on suit celle sur laquelle le joueur clique ;
  • Commentaire : war3_events pour lire ce qui s’est passé, war3_say pour 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_screenshot pour 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 (htow 1, hpea 5) → 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 forme mcp__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.