# El LLM usa herramientas directamente (MCP)

> tools/war3_mcp.py es un servidor MCP. Conéctalo a Claude Code, Claude Desktop o cualquier cliente compatible con MCP y el LLM podrá ver la partida, dar órdenes, hablar con el jugador en pantalla, preguntarle con tarjetas y hacer capturas de la imagen, sin escribir código antes.

Fuente: https://war3ai.com/es/docs/mcp/

`tools/war3_mcp.py` es un **servidor MCP** (stdio). Claude Code, Claude Desktop, frameworks de agentes con modelos locales: cualquier cliente compatible con MCP puede conectarlo, y el LLM podrá **directamente** ver la partida, dar órdenes, hablar con el jugador en la pantalla del juego, hacerle preguntas y hacer capturas de la imagen, sin escribir código antes.

Además de escribir Bots, hacer de asesor o poner voz a las unidades, esta es otra forma de conectarlo: **el propio LLM es quien usa las herramientas**.

## Conectarlo

```bash
claude mcp add war3 -- python <repositorio>\tools\war3_mcp.py --inst 9      # Claude Code; cambia <repositorio> por tu carpeta de openwar3
```

En otros clientes, escribe la configuración con este formato:

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

Solo se conecta al juego la primera vez que se llama a una herramienta, así que el juego se puede abrir después; si el juego se cierra y se vuelve a abrir, la siguiente llamada se reconecta sola. Añade `--role` para limitar lo que puede hacer el LLM:

| Rol | Qué puede usar |
|---|---|
| `dev` (por defecto) | Todas las herramientas, incluida `war3_jass` |
| `player --player N` | Solo puede mandar las unidades del jugador N y solo ve lo que está en su visión (modo justo); sin JASS |
| `observer` | Solo lectura; no puede dibujar en pantalla ni hacer hablar a las unidades; el runtime rechaza directamente los comandos que envíe |

El rol `player` tiene las mismas limitaciones que en la [pasarela](https://war3ai.com/es/docs/gateway/): no puede terminar la partida, cambiar la velocidad ni pausar, no tiene acceso a las interfaces que dejan ver las cartas de los demás, y las consultas que llevan número de jugador solo pueden consultar el propio.

Algunos límites: el resultado de una herramienta tiene como máximo 200 000 caracteres; si se pasa, se recorta y se indica cómo acotar la consulta; `war3_ask_player` espera como máximo 120 segundos; el `scale` de las capturas va de 0.1 a 1.

## Herramientas

| Herramienta | Qué hace |
|---|---|
| `war3_overview` | La partida en una página: tiempo, recursos, comida, número de unidades propias por tipo, héroes (vida, maná, nivel, enfriamientos), tipos de unidades enemigas visibles, producción. **Llámala primero** |
| `war3_units` | Lista de unidades (`owner` puede ser me / enemy / creep / all; `types` filtra); el `addr` sirve para dar órdenes |
| `war3_events` | Lo que ha pasado desde la última llamada: muertes, subidas de nivel, hechizos, producción terminada, chat, botones que pulsó el jugador… (por defecto quita los tipos más ruidosos) |
| `war3_call` | Llama a cualquier interfaz pública (`move`, `attack_move`, `train`, `build`, `cast`, `learn`, `ui.button`, `canvas.text`…); las unidades se escriben `{"unit": addr}` |
| `war3_api` | Busca interfaces por palabra clave en el nombre y la descripción |
| `war3_toast` / `war3_say` | Una línea de texto en la parte de arriba de la pantalla / una frase sobre la cabeza de una unidad |
| `war3_ask_player` | Muestra al jugador unas tarjetas de elección en el centro de la pantalla, espera a que pulse una y devuelve cuál eligió (puede pausar el juego) |
| `war3_screenshot` | Captura de la imagen del juego (PNG; funciona aunque la ventana esté tapada y no roba el foco) |
| `war3_jass` | Ejecuta un fragmento de JASS (solo dev; cambiar el mundo, solo en partidas de un jugador) |

Lo que se puede hacer con esto:

- **Acompañante / entrenador**: `war3_overview` para ver la partida y `war3_toast` para dar consejos en pantalla;
- **Preguntar al jugador mientras juega**: `war3_ask_player` muestra tres tarjetas y se sigue la que pulse el jugador;
- **Comentarista**: `war3_events` para leer lo que ha pasado y `war3_say` para que lo cuenten las propias unidades;
- **Mandar directamente un ejército**: rol `player` + `war3_call`; solo puede mover sus propias unidades;
- **Ajustar la interfaz mirando la imagen**: `war3_screenshot` hace una captura para comprobar si los botones que dibujó están bien colocados.

## Así es, más o menos, una conversación

```text
Tú: Mira cómo va la partida y luego pregúntame en pantalla: ¿ahora expando, saco tropas o mejoro el ayuntamiento?

→ war3_overview      {}
← La partida en una página: tiempo de juego, oro 500, comida 10/12, propias htow 1 · hpea 5 · Hpal 1, ningún enemigo a la vista, nada en producción
→ war3_ask_player    {"question": "¿Siguiente paso?", "options": ["Sacar tropas", "Expandir", "Mejorar ayuntamiento"], "pause": true}
← {"picked": 1, "option": "Expandir"}

Modelo: Has elegido expandir. Primero busco un campesino libre con war3_units y luego miro dónde está la mina de oro más cercana…
```

## Medido

2026-09-25:

- Con un cliente MCP propio conectado a una partida real, 7/7: handshake → listar herramientas (10) → `war3_overview` (`htow` 1, `hpea` 5) → `war3_units` → `war3_toast` → `war3_screenshot` (PNG de unos 200 000 bytes) → `war3_ask_player` (tres tarjetas; clic simulado en la segunda → `{"picked": 1, "option": "Expandir"}`).
- Conectado de verdad a Claude Code 2.1: arranca el servidor por su cuenta, hace el handshake, el estado es `connected` y las 10 herramientas aparecen en su lista de herramientas como `mcp__war3__*`.

## Implementación

- JSON-RPC 2.0 delimitado por saltos de línea (`initialize` / `tools/list` / `tools/call` / `ping`), versión del protocolo 2025-06-18, compatible con 2025-03-26 y 2024-11-05.
- Los errores de las herramientas van dentro del resultado, como marca MCP (`isError: true`), sin cortar la conexión.
- Comparte con la [pasarela](https://war3ai.com/es/docs/gateway/) la misma lista blanca de roles, el mismo formato de parámetros de unidad y la misma «partida en una página».
- Los logs van a stderr; stdout solo lleva el protocolo.
