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

Source: https://war3ai.com/fr/docs/mcp/

`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

```bash
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 :

```json
{"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](https://war3ai.com/fr/docs/gateway/) : 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_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

```text
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](https://war3ai.com/fr/docs/gateway/) 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.
