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.
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
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:
{"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: 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_overviewdie Lage lesen, mitwar3_toastTipps auf den Bildschirm geben; - Den Spieler mitten im Spiel fragen:
war3_ask_playerzeigt drei Karten, und es geht mit der Karte weiter, die der Spieler anklickt; - Kommentar:
war3_eventsliest, was passiert ist,war3_saylä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_screenshoteinen Screenshot machen und nachsehen, ob die selbst gezeichneten Buttons richtig sitzen.
So sieht ein Gespräch etwa aus
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(htow1,hpea5) →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 alsmcp__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.
- Logs gehen nach stderr, auf stdout steht nur das Protokoll.