# LLM вызывает инструменты (MCP)

> tools/war3_mcp.py — это MCP-сервер. Подключите его к Claude Code, Claude Desktop или любому клиенту с поддержкой MCP, и LLM сможет сама смотреть на обстановку, отдавать команды, писать игроку на экране, задавать ему вопросы карточками и делать скриншоты — без заранее написанного кода.

Источник: https://war3ai.com/ru/docs/mcp/

`tools/war3_mcp.py` — это **MCP-сервер** (stdio). Подключите его к Claude Code, Claude Desktop, агентному фреймворку для локальных моделей — к любому клиенту с поддержкой MCP, — и LLM сможет **напрямую** смотреть на обстановку, отдавать команды, писать игроку на игровом экране, задавать ему вопросы и делать скриншоты, не написав заранее ни строчки кода.

Помимо написания ботов, роли советника и озвучки юнитов, это ещё один способ подключения: **LLM сама пользуется инструментами**.

## Подключение

```bash
claude mcp add war3 -- python <репозиторий>\tools\war3_mcp.py --inst 9      # Claude Code; <репозиторий> замените на свою папку openwar3
```

Для других клиентов конфигурация пишется в том же формате:

```json
{"mcpServers": {"war3": {"command": "python", "args": ["<репозиторий>\\tools\\war3_mcp.py", "--inst", "9"]}}}
```

К игре сервер подключается только при первом вызове инструмента, так что игру можно запустить и позже; если игру закрыть и запустить снова, следующий вызов переподключится автоматически. Через `--role` можно ограничить, что разрешено LLM:

| Роль | Что доступно |
|---|---|
| `dev` (по умолчанию) | Все инструменты, включая `war3_jass` |
| `player --player N` | Командовать только юнитами игрока N и видеть только его обзор (честный режим); без JASS |
| `observer` | Только чтение, рисовать на экране и заставлять юнитов говорить нельзя; рантайм сразу отклоняет его команды |

У роли `player` те же ограничения, что и в [шлюзе](https://war3ai.com/ru/docs/gateway/): нельзя завершить игру, сменить скорость или поставить паузу, недоступны методы, раскрывающие чужие карты, а запросы с номером игрока работают только для своего игрока.

Несколько лимитов: результат инструмента — не больше 200 000 символов, лишнее обрезается с подсказкой, как сузить запрос; `war3_ask_player` ждёт не дольше 120 секунд; `scale` у скриншота — от 0.1 до 1.

## Инструменты

| Инструмент | Что делает |
|---|---|
| `war3_overview` | Обстановка на одной странице: время, ресурсы, пища, число наших юнитов по типам, герои (здоровье, мана, уровень, перезарядка), видимые типы вражеских юнитов, производство. **Вызывайте первым** |
| `war3_units` | Список юнитов (`owner`: me / enemy / creep / all, фильтр `types`); `addr` нужен для команд |
| `war3_events` | Что произошло с прошлого вызова: гибель, повышение уровня, применение способностей, завершение производства, чат, нажатия игрока на кнопки… (по умолчанию без нескольких самых шумных видов) |
| `war3_call` | Вызвать любой публичный метод (`move`, `attack_move`, `train`, `build`, `cast`, `learn`, `ui.button`, `canvas.text`…); юнит задаётся как `{"unit": addr}` |
| `war3_api` | Поиск по API: по ключевому слову в именах и описаниях |
| `war3_toast` / `war3_say` | Строка текста вверху экрана / реплика над головой юнита |
| `war3_ask_player` | Показать игроку посреди экрана несколько карточек, дождаться клика и вернуть выбранный вариант (игру можно поставить на паузу) |
| `war3_screenshot` | Скриншот игры (PNG; снимается, даже если окно перекрыто, фокус не перехватывается) |
| `war3_jass` | Выполнить фрагмент JASS (только dev; менять мир — только в одиночной игре) |

Что с этим можно сделать:

- **Напарник / тренер**: `war3_overview` — посмотреть обстановку, `war3_toast` — дать совет на экране;
- **Спрашивать игрока по ходу игры**: `war3_ask_player` показывает три карточки, и LLM действует по той, которую выбрал игрок;
- **Комментирование**: `war3_events` — узнать, что произошло, `war3_say` — пусть юниты сами об этом расскажут;
- **Командовать отрядом напрямую**: роль `player` + `war3_call`, двигать можно только свои юниты;
- **Отлаживать интерфейс по картинке**: `war3_screenshot` — сделать снимок и проверить, правильно ли стоят нарисованные кнопки.

## Как примерно выглядит диалог

```text
Вы: Посмотри, что сейчас на карте, и спроси меня на экране: что дальше — экспансия, армия или улучшение ратуши?

→ war3_overview      {}
← Обстановка: игровое время, золото 500, пища 10/12, наши htow 1 · hpea 5 · Hpal 1, врагов не видно, производства нет
→ war3_ask_player    {"question": "Что дальше?", "options": ["Армия", "Экспансия", "Улучшение ратуши"], "pause": true}
← {"picked": 1, "option": "Экспансия"}

Модель: Вы выбрали экспансию. Сначала через war3_units найду свободного крестьянина, потом посмотрю, где ближайший золотой рудник…
```

## Замеры

2026-09-25:

- Собственный MCP-клиент на живом матче, 7/7: рукопожатие → список инструментов (10) → `war3_overview` (`htow` 1, `hpea` 5) → `war3_units` → `war3_toast` → `war3_screenshot` (PNG около 200 000 байт) → `war3_ask_player` (три карточки, имитация клика по второй → `{"picked": 1, "option": "开矿"}`, то есть «экспансия»).
- Реальное подключение к Claude Code 2.1: он сам запускает сервер и проходит рукопожатие, статус `connected`, все 10 инструментов появляются в его списке инструментов как `mcp__war3__*`.

## Реализация

- JSON-RPC 2.0 с разделением по строкам (`initialize` / `tools/list` / `tools/call` / `ping`), версия протокола 2025-06-18, совместимость с 2025-03-26 и 2024-11-05.
- Ошибки инструментов по правилам MCP возвращаются в результате (`isError: true`), соединение не рвётся.
- Со [шлюзом](https://war3ai.com/ru/docs/gateway/) общие белые списки ролей, формат аргумента-юнита и «обстановка на одной странице».
- Логи идут в stderr, в stdout — только протокол.
