# LLM ruft Tools direkt auf (MCP)

> tools/war3_mcp.py ist ein MCP-Server. Hängst du ihn in Claude Code, Claude Desktop oder einen anderen MCP-fähigen Client, kann das LLM direkt die Lage sehen, Befehle erteilen, auf dem Bildschirm mit dem Spieler sprechen, ihm Karten zur Auswahl zeigen und Screenshots ansehen – ohne vorher Code zu schreiben.

Quelle: https://war3ai.com/de/docs/mcp/

`tools/war3_mcp.py` ist ein **MCP-Server** (stdio). Claude Code, Claude Desktop, Agent-Frameworks für lokale Modelle – hängst du ihn in einen beliebigen MCP-fähigen Client, kann das LLM **direkt** die Lage sehen, Befehle erteilen, auf dem Spielbildschirm mit dem Spieler sprechen, dem Spieler Fragen stellen und Screenshots ansehen, ohne vorher Code zu schreiben.

Neben Bot schreiben, Coach spielen und Einheiten sprechen lassen ist das ein weiterer Weg: **Das LLM benutzt die Tools selbst.**

## Einbinden

```bash
claude mcp add war3 -- python <Repo>\tools\war3_mcp.py --inst 9      # Claude Code; <Repo> durch deinen openwar3-Ordner ersetzen
```

Andere Clients konfigurierst du nach diesem Schema:

```json
{"mcpServers": {"war3": {"command": "python", "args": ["<Repo>\\tools\\war3_mcp.py", "--inst", "9"]}}}
```

Mit dem Spiel verbunden wird erst beim ersten Tool-Aufruf – das Spiel kann also später gestartet werden; wird es geschlossen und neu gestartet, verbindet sich der nächste Aufruf automatisch neu. Mit `--role` legst du fest, was das LLM darf:

| Rolle | Darf |
|---|---|
| `dev` (Standard) | alle Tools, einschließlich `war3_jass` |
| `player --player N` | nur Einheiten von Spieler N befehligen und nur dessen Sicht sehen (Fair-Modus); kein JASS |
| `observer` | nur lesen, nichts auf den Bildschirm zeichnen, keine Einheiten sprechen lassen; die Runtime lehnt seine Befehle direkt ab |

Für die Rolle `player` gelten dieselben Grenzen wie im [Gateway](https://war3ai.com/de/docs/gateway/): kein Spiel beenden, kein Tempo ändern, kein Pausieren, keine APIs, die die verdeckten Karten der anderen zeigen, und Abfragen mit Spielernummer gehen nur für den eigenen Spieler.

Ein paar Obergrenzen: Ein Tool-Ergebnis hat höchstens 200.000 Zeichen – was darüber hinausgeht, wird abgeschnitten, mit einem Hinweis, wie man den Umfang eingrenzt; `war3_ask_player` wartet höchstens 120 Sekunden; `scale` beim Screenshot liegt zwischen 0.1 und 1.

## Tools

| Tool | Was es tut |
|---|---|
| `war3_overview` | Lage auf einer Seite: Zeit, Ressourcen, Nahrung, Anzahl eigener Einheiten pro Typ, Helden (HP, Mana, Stufe, Abklingzeiten), sichtbare gegnerische Einheitentypen, Produktion. **Zuerst aufrufen** |
| `war3_units` | Einheitenliste (`owner` = me / enemy / creep / all, Filter per `types`); mit `addr` erteilst du Befehle |
| `war3_events` | Was seit dem letzten Aufruf passiert ist: Tode, Stufenaufstiege, Zauber, fertige Produktion, Chat, angeklickte Buttons … (standardmäßig ohne die Arten, die das Log fluten) |
| `war3_call` | Beliebige öffentliche API aufrufen (`move`, `attack_move`, `train`, `build`, `cast`, `learn`, `ui.button`, `canvas.text` …); Einheiten als `{"unit": addr}` |
| `war3_api` | APIs nachschlagen: Namen und Beschreibungen nach Stichwort durchsuchen |
| `war3_toast` / `war3_say` | eine Textzeile oben auf dem Bildschirm / ein Satz über dem Kopf einer Einheit |
| `war3_ask_player` | zeigt dem Spieler in der Bildschirmmitte ein paar Auswahlkarten, wartet auf den Klick und gibt die Wahl zurück (kann das Spiel pausieren) |
| `war3_screenshot` | Screenshot des Spielbilds (PNG; funktioniert auch, wenn das Fenster verdeckt ist, ohne den Fokus zu stehlen) |
| `war3_jass` | ein Stück JASS ausführen (nur dev; die Welt ändern nur im Einzelspieler) |

Was sich damit machen lässt:

- **Mitspieler / Trainer**: Mit `war3_overview` die Lage lesen, mit `war3_toast` Tipps auf den Bildschirm geben;
- **Den Spieler mitten im Spiel fragen**: `war3_ask_player` zeigt drei Karten, und es geht mit der Karte weiter, die der Spieler anklickt;
- **Kommentar**: `war3_events` liest, was passiert ist, `war3_say` lässt die Einheiten es selbst aussprechen;
- **Direkt eine Truppe befehligen**: Rolle `player` + `war3_call`, nur die eigenen Einheiten lassen sich bewegen;
- **Oberfläche per Bild prüfen**: Mit `war3_screenshot` einen Screenshot machen und nachsehen, ob die selbst gezeichneten Buttons richtig sitzen.

## So sieht ein Gespräch etwa aus

```text
Du: Schau dir die aktuelle Lage an und frag mich dann auf dem Bildschirm: als Nächstes expandieren, Armee aufbauen oder Hauptgebäude aufwerten?

→ war3_overview      {}
← Lage auf einer Seite: Spielzeit, Gold 500, Nahrung 10/12, eigene htow 1 · hpea 5 · Hpal 1, keine Gegner in Sicht, keine laufende Produktion
→ war3_ask_player    {"question": "Wie geht's weiter?", "options": ["Armee aufbauen", "Expandieren", "Aufwerten"], "pause": true}
← {"picked": 1, "option": "Expandieren"}

Modell: Du hast „Expandieren“ gewählt. Ich suche zuerst mit war3_units einen untätigen Bauern und schaue dann, wo die nächste Goldmine ist …
```

## Gemessen

2026-09-25:

- Eigener MCP-Client an einer echten Partie, 7/7: Handshake → Tools auflisten (10) → `war3_overview` (`htow` 1, `hpea` 5) → `war3_units` → `war3_toast` → `war3_screenshot` (PNG, ca. 200.000 Bytes) → `war3_ask_player` (drei Karten, simulierter Klick auf die zweite → `{"picked": 1, "option": "开矿"}`, also „Expandieren“).
- Live in Claude Code 2.1 eingebunden: Es startet den Server selbst, führt den Handshake durch, Status `connected`, und alle 10 Tools erscheinen als `mcp__war3__*` in seiner Tool-Liste.

## Implementierung

- Zeilengetrenntes JSON-RPC 2.0 (`initialize` / `tools/list` / `tools/call` / `ping`), Protokollversion 2025-06-18, kompatibel mit 2025-03-26 und 2024-11-05.
- Tool-Fehler landen nach MCP-Konvention im Ergebnis (`isError: true`), die Verbindung bleibt bestehen.
- Nutzt dieselbe Rollen-Whitelist, dasselbe Format für Einheitenparameter und dieselbe „Lage auf einer Seite“ wie das [Gateway](https://war3ai.com/de/docs/gateway/).
- Logs gehen nach stderr, auf stdout steht nur das Protokoll.
