# LLM usando ferramentas (MCP)

> tools/war3_mcp.py é um servidor MCP. Conecte-o ao Claude Code, ao Claude Desktop ou a qualquer cliente com suporte a MCP, e o LLM passa a ver a partida, dar comandos, falar com o jogador na tela, perguntar ao jogador com cartões e tirar capturas de tela diretamente, sem escrever código antes.

Fonte: https://war3ai.com/pt/docs/mcp/

`tools/war3_mcp.py` é um **servidor MCP** (stdio). Claude Code, Claude Desktop, frameworks de agentes para modelos locais — conecte-o a qualquer cliente com suporte a MCP, e o LLM passa a **diretamente** ver a partida, dar comandos, falar com o jogador na tela do jogo, fazer perguntas ao jogador e tirar capturas de tela, sem escrever código antes.

Além de escrever Bots, aconselhar e dar voz às unidades, esta é mais uma forma de conexão: **o próprio LLM é quem usa as ferramentas**.

## Conectando

```bash
claude mcp add war3 -- python <repositório>\tools\war3_mcp.py --inst 9      # Claude Code; troque <repositório> pela sua pasta do openwar3
```

Em outros clientes, escreva a configuração neste formato:

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

A conexão com o jogo só acontece na primeira chamada de ferramenta, então o jogo pode ser aberto depois; se o jogo for fechado e aberto de novo, a próxima chamada reconecta sozinha. Acrescente `--role` para limitar o que o LLM pode fazer:

| Papel | O que pode usar |
|---|---|
| `dev` (padrão) | Todas as ferramentas, inclusive `war3_jass` |
| `player --player N` | Só comanda as unidades do jogador N e só enxerga a visão dele (modo justo); sem JASS |
| `observer` | Só leitura; não pode desenhar na tela nem fazer unidades falarem; o runtime rejeita direto os comandos que ele enviar |

O papel `player` tem as mesmas limitações do [gateway](https://war3ai.com/pt/docs/gateway/): não pode encerrar a partida, mudar a velocidade nem pausar, não tem acesso às APIs que mostram as cartas dos outros, e consultas que levam número de jogador só podem consultar o próprio jogador.

Alguns limites: o resultado de uma ferramenta tem no máximo 200 mil caracteres; o que passar disso é cortado, com uma dica de como restringir a consulta; `war3_ask_player` espera no máximo 120 segundos; o `scale` da captura de tela fica entre 0.1 e 1.

## Ferramentas

| Ferramenta | O que faz |
|---|---|
| `war3_overview` | Resumo da partida numa página: tempo, recursos, comida, contagem de cada tipo de unidade nossa, heróis (vida, mana, nível, recargas), tipos de unidades inimigas visíveis, produção. **Chame esta primeiro** |
| `war3_units` | Lista de unidades (`owner` aceita me / enemy / creep / all, `types` filtra); o `addr` serve para dar comandos |
| `war3_events` | O que aconteceu desde a última chamada: mortes, subidas de nível, feitiços, produção concluída, chat, o jogador clicou num botão… (por padrão, remove alguns tipos que inundam o log) |
| `war3_call` | Chama qualquer API pública (`move`, `attack_move`, `train`, `build`, `cast`, `learn`, `ui.button`, `canvas.text`…); unidades são escritas como `{"unit": addr}` |
| `war3_api` | Consulta a API: busca nomes e descrições por palavra-chave |
| `war3_toast` / `war3_say` | Uma linha de texto no alto da tela / uma frase sobre a cabeça de uma unidade |
| `war3_ask_player` | Mostra alguns cartões de escolha no meio da tela, espera o jogador clicar e retorna qual foi escolhido (pode pausar o jogo) |
| `war3_screenshot` | Captura da tela do jogo (PNG; funciona mesmo com a janela coberta, sem roubar o foco) |
| `war3_jass` | Executa um trecho de JASS (só para dev; alterações no mundo só em partida solo) |

O que dá para fazer:

- **Parceiro de jogo / coach**: `war3_overview` para ver a partida, `war3_toast` para dar conselhos na tela;
- **Perguntar ao jogador durante a partida**: `war3_ask_player` mostra três cartões, e o que o jogador clicar é o que vale;
- **Narração**: `war3_events` para ler o que aconteceu, `war3_say` para as próprias unidades contarem;
- **Comandar uma tropa diretamente**: papel `player` + `war3_call`, só com as próprias unidades;
- **Ajustar a interface olhando a imagem**: `war3_screenshot` tira uma captura, e o modelo confere se os botões que desenhou estão no lugar certo.

## Uma conversa típica

```text
Você: Veja como está a partida e depois me pergunte na tela: próximo passo é expandir, fazer mais tropas ou subir de tier?

→ war3_overview      {}
← Resumo da partida: tempo de jogo, ouro 500, comida 10/12, nossas htow 1 · hpea 5 · Hpal 1, nenhum inimigo visível, nada em produção
→ war3_ask_player    {"question": "Próximo passo?", "options": ["Mais tropas", "Expandir", "Subir de tier"], "pause": true}
← {"picked": 1, "option": "Expandir"}

Modelo: Você escolheu expandir. Primeiro vou usar war3_units para achar um camponês ocioso e depois ver onde fica a mina de ouro mais próxima…
```

## Medições

2026-09-25:

- Nosso próprio cliente MCP conectado a uma partida real, 7/7: handshake → listar ferramentas (10) → `war3_overview` (`htow` 1, `hpea` 5) → `war3_units` → `war3_toast` → `war3_screenshot` (PNG de cerca de 200 mil bytes) → `war3_ask_player` (três cartões, clique simulado no segundo → `{"picked": 1, "option": "开矿"}`, ou seja, “expandir”).
- Conectado de verdade no Claude Code 2.1: ele mesmo iniciou o servidor e fez o handshake, com status `connected`, e as 10 ferramentas apareceram na lista de ferramentas dele como `mcp__war3__*`.

## Implementação

- JSON-RPC 2.0 separado por quebras de linha (`initialize` / `tools/list` / `tools/call` / `ping`), versão do protocolo 2025-06-18, compatível com 2025-03-26 e 2024-11-05.
- Erros de ferramenta vão no resultado, como manda o MCP (`isError: true`), sem desconectar.
- Usa a mesma lista de permissões por papel, o mesmo formato de parâmetros de unidade e o mesmo “resumo da partida” do [gateway](https://war3ai.com/pt/docs/gateway/).
- Os logs vão para stderr; stdout só tem o protocolo.
