DirectAI MCP
# DirectAI MCP — личный сервер статистики и управления Яндекс Директом
> ИИ-агент? Следуй [AGENTS.md](AGENTS.md).
DirectAI MCP is a local MCP server for Yandex Direct stats and management.
Runs on your Windows 11 PC for a single user. Tested on Windows 11 only;
macOS/Linux not supported. Start install at §1 below.
Локальный MCP-сервер: ИИ-ассистенты (OpenCode, Codex и др.) через него читают
статистику и управляют вашими аккаунтами Яндекс Директа.
Только для одного пользователя, работает на вашем компьютере, в интернет
ничего не выставляет.
## Прежде чем устанавливать
Обязательно:
- Windows 11 (инструкции — только для PowerShell; macOS/Linux
не тестировались и не поддерживаются);
- аккаунт Яндекс Директа с хотя бы одной кампанией (можно черновик);
для агентств — главный логин агентства;
- своё приложение на oauth.yandex.ru (анкета на 5 минут, права Директ
и Метрика) — запомните ID приложения;
- одобренный доступ к API Директа (Инструменты → API → заявка с ID
приложения); одобрение занимает до нескольких дней;
- ИИ-помощник с поддержкой MCP (OpenCode, Codex, Claude Code,
Claude Desktop, Hermes); сам DirectAI бесплатный, работает локально
на вашем компьютере, для одного пользователя.
По ходу установки: токен получаете по ссылке, вводите сами в своём
терминале, никогда не в чат.
Желательно: доступ к счётчику Метрики (иначе CRM-выручка не отличается
от условной ценности целей).
Не нужно: программировать, покупать сервер, заранее ставить git или Python.
### С чего начать
1. Создайте приложение и подайте заявку на API — это самое долгое,
начните с этого (подробности — §1.1, шаг 5).
2. Пока ждёте одобрения — установите DirectAI (§1 или §1.1).
3. Когда заявку одобрят — получите токен и выполните проверку
(`set-token`, затем `check`).
## 1. Установка с нуля
Нужно: Windows 11, `uv`, `git` (оба ставятся через `winget`, см. §1.1),
токен Яндекс Директа (как получить — см. §1.1, нужен доступ к API).
```powershell
cd $env:USERPROFILE
git clone https://github.com/perejaslav/directai-mcp.git directai-mcp
cd $env:USERPROFILE\directai-mcp
uv tool install --editable .
uv tool update-shell
directai-mcp init
directai-mcp set-token --login ВАШ_ЛОГИН
directai-mcp check
```
Впишите свой логин в `%USERPROFILE%\.directai\accounts.toml` (`[auth] login`,
замените демо-алиасы) между `init` и `set-token`; в `set-token` передайте
тот же логин флагом `--login`.
Что происходит: `init` создаёт `%USERPROFILE%\.directai\` и копирует примеры
конфигов (существующие не трогает); `set-token` маскированно спрашивает токен
и кладёт его в Credential Manager Windows (в файлах токена нет никогда);
`check` проверяет доступ. Ожидание — строки `OK` по каждому аккаунту с числом
кампаний и остатком баллов.
## 1.1. Установка через ИИ-агента — промпт для новичка
Новичок (свой аккаунт Директа, ничего общего с автором) копирует блок ниже
в любого агента (OpenCode, Codex, Claude Code) — агент ставит всё с нуля.
```
Ты помогаешь новичку установить DirectAI MCP с нуля на Windows 11.
Человек не знает git, uv и PowerShell. Объясняй простыми словами,
одно действие за раз. Каждую команду давай отдельно, жди результата.
Правила: бюджеты и стратегию без «да» владельца не менять; guard не выключать никогда;
запись только через план с подтверждением; токен только в Credential Manager.
0. Сначала спроси, одобрен ли уже доступ к API Директа. Нет — начни
с шага 5 (создать приложение и подать заявку: это самое долгое),
затем ставь DirectAI (шаги 1–4), а токен и check — после одобрения.
Доступ уже одобрен — иди по шагам 1–4, затем токен и проверка.
1. Спроси разрешение и поставь git и uv (флаги снимают лишние вопросы):
winget install --id Git.Git -e --accept-package-agreements --accept-source-agreements
winget install --id astral-sh.uv -e --accept-package-agreements --accept-source-agreements
Проверь: git --version и uv --version. Нет команды — обнови PATH в этой сессии
(давай строку одним блоком, проверь, что вставилась одной строкой):
$env:Path = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User")
Нет winget — поставь App Installer из Microsoft Store.
2. Склонируй репозиторий (три команды, по одной). Папка directai-mcp уже есть —
не клонируй, а выполни git pull внутри неё:
cd $env:USERPROFILE
git clone https://github.com/perejaslav/directai-mcp.git directai-mcp
cd $env:USERPROFILE\directai-mcp
3. Установи и инициализируй (по одной команде):
uv tool install --editable .
uv tool update-shell
$env:Path = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User")
directai-mcp --version
directai-mcp init
Первая установка качает Python несколько минут — это не зависание.
4. Спроси логины кабинетов (это не секрет): главный — владелец будущего токена.
Если кабинетов несколько (агентство: главный логин видит клиентские) —
попроси все. ПОЛНОСТЬЮ замени демо-алиасы в %USERPROFILE%\.directai\accounts.toml:
[auth] login — реальный главный логин, под каждый логин свой [aliases.*].
goals.toml необязателен: названия целей Метрики, можно заполнить позже.
5. Токен. Объясни: создай приложение типа «Для доступа к API или отладки»
на https://oauth.yandex.ru/client/new с правами direct:api и metrika:read.
Redirect URI настраивать не нужно — он фиксирован. Затем открой в браузере ссылку
https://oauth.yandex.ru/authorize?response_type=token&client_id=ID_ПРИЛОЖЕНИЯ&redirect_uri=https://oauth.yandex.ru/verification_code
(подставь ID со страницы приложения) и нажми «Разрешить» — токен появится
в адресной строке. Скопируй ТОЛЬКО значение после access_token= и до &,
не весь URL (вид: access_token=y0_AgA...&token_type=...). Спроси «что видишь?»:
ошибка OAuth — проверить ID приложения и пробелы. Это штатный способ из доки:
https://yandex.ru/dev/direct/doc/ru/concepts/auth-token. Затем подай заявку
на доступ к API в интерфейсе Директа (Инструменты → API → Мои заявки),
инструкция: https://yandex.ru/dev/direct/doc/ru/concepts/register.
В описании заявки укажи «личный учёт статистики и управление своими кампаниями».
Одобрение занимает до нескольких дней — ошибка 58 до этого норма, просто ждём.
Без metrika:read типы ценностей берутся из goals.toml (по умолчанию условные).
6. Токен в чат писать ЗАПРЕЩЕНО. Пусть человек САМ выполнит в своём терминале:
directai-mcp set-token — и введёт токен в скрытое поле. Символы не отображаются —
это нормально: вставить и Enter. Если вставил в чат — останови, попроси
отозвать токен в Яндекс ID и выпустить новый.
7. Проверь: directai-mcp check. Расшифруй итог: OK — работает; 53 — неверный
токен, повторить шаг 6; 58 — нет доступа к API, вернуться к шагу 5; 513 —
у логина нет аккаунта в Директе (создай кампанию в интерфейсе); 152 —
кончились баллы API, подождать до завтра. Коды:
https://yandex.ru/dev/direct/doc/ref-v5/concepts/errors-list.html
8. Самопроверка сервера: directai-mcp probe. Ожидание — две строки OK
(версия сервера, число инструментов, stats_summary найден). Баллы API
не тратятся. Сырые stdio-пробы вручную не делать — только probe.
9. Подключи харнес: сначала спроси, какой — OpenCode, Codex или Claude Code.
Сделай копию его конфига (*.bak), потом ДОПИШИ блок directai-mcp, чужие MCP
не трогай. Готовые блоки — examples/harness-configs.md.
9. Попроси человека САМОГО перезапустить харнес (закрыть все его окна
и открыть заново). В новой сессии пусть спросит:
«Используй только directai-mcp: покажи расходы по всем аккаунтам за вчера» —
и сверит цифры с веб-интерфейсом Директа. Сошлось — готово.
10. Удали свои бэкапы (*.bak-*, *-tool-backup-*), чужие файлы не трогай.
```
## 2. Подключение к харнесам
Команда запуска везде одна — `directai-mcp` (без аргументов: STDIO-сервер).
После настройки перезапустите харнес.
**OpenCode** — файл `%USERPROFILE%\.config\opencode\opencode.json`:
```json
{
"mcp": {
"directai-mcp": {
"type": "local",
"command": ["directai-mcp"],
"enabled": true
}
}
}
```
**Codex** — файл `%USERPROFILE%\.codex\config.toml`:
```toml
[mcp_servers.directai-mcp]
command = "directai-mcp"
args = []
```
Остальные (Claude Desktop, Claude Code) — готовые фрагменты в
`examples/harness-configs.md`. Если харнес не видит команду, укажите полный
путь к `directai-mcp.exe` (покажет `(Get-Command directai-mcp).Source`).
Проверка (задать ИИ): «Покажи расходы по всем аккаунтам за последние 7 дней» —
итоги должны совпасть с веб-интерфейсом Директа.
## 3. Файлы в `%USERPROFILE%\.directai\`
| Файл | Что внутри и как править |
|---|---|
| `accounts.toml` | Ваши кабинеты: `[auth] login` — владелец токена, под каждый логин свой `[aliases.*]` (короткое имя и роль). Плюс `defaults` (`include_vat`, `max_rows`, `attribution`), секция `[guard]` и секция `[audience]` (`write_enabled`, дефолт `false` — запись в Аудитории выключена), секция `[retargeting]` (`write_enabled`, дефолт `false` — запись ретаргетинга выключена). Секретов здесь нет. Править любым текстовым редактором, применяется со следующего запроса. |
| `rules.toml` | Правила: обязательный DisplayUrlPath, слова для заголовков, пороги `max_budget_ratio` / `max_bid_ratio` (предупреждения при резких изменениях). |
| `goals.toml` | `id цели → Название` (цели Метрики). В отчётах цель видна как «Название (id)», без названия — голый id. Названия вписываете вы. |
| `journal.sqlite` | Журнал всех записей (не удаляйте). |
| `plans\` | Планы записи: один файл на план (общее хранилище для всех процессов сервера, TTL 15 минут, применение ровно один раз; просроченные чистятся автоматически). |
| `exports\` | CSV/MD-выгрузки из отчётов. |
| `logs\` | Логи сервера. |
Переопределить каталог: переменная `DIRECTAI_HOME`. Токен Директа: только
Credential Manager (`directai-mcp`) или переменная `DIRECTAI_TOKEN`. Для
Метрики (v1.17.1) — отдельный токен: `directai-mcp set-metrika-token
--login <логин>` (Credential Manager `directai-mcp-metrika` или переменная
`DIRECTAI_METRIKA_TOKEN`), подробности — §7.1; без него чтение идёт токеном
Директа с примечанием, а запись целей недоступна. Для
Яндекс.Вебмастера можно хранить отдельный токен: `directai-mcp set-token
--webmaster` (Credential Manager `directai-mcp-webmaster` или переменная
`DIRECTAI_WEBMASTER_TOKEN`); без него используется основной токен.
Для Wordstat API Yandex Cloud используется отдельный API-ключ: выполните
`directai-mcp set-token --wordstat`, введите `folderId` каталога AI Studio,
затем ключ в скрытом поле. Ключ хранится в Credential Manager
(`directai-mcp-wordstat` или `DIRECTAI_WORDSTAT_API_KEY`), а `folderId` — в
`[wordstat] folder_id` в `accounts.toml`. Секретный ключ в этот файл не
записывается. Действия Wordstat — только чтение и не используют OAuth-токен
Директа.
Запись в Яндекс Аудитории выключена по умолчанию
(`[audience] write_enabled=false`); включается только явным
`write_enabled = true`, путь тот же: `plan_write` → ваше согласие →
`apply_write`, guard требует имя сегмента `[TEST DirectAI]*`.
## 4. Что умеет сервер
Порядок работы ИИ: `search_actions` → `describe_action` → `run_read`
(чтение) или `plan_write` → показать вам → `apply_write` (запись).
`describe_action` без имени (или с пустой строкой) — статус сервера, вызов
бесплатный (API не тратится): `server_version` (что декларирует установка
пакета, `importlib.metadata`), `code_version` (код, реально запущенный в
процессе), `disk_version` (исходники на диске) и строка «Метрика: …» —
какой токен используется для Метрики (отдельный или токен Директа), §7.1.
Если `code_version` ≠ `disk_version` — блок предупреждения «перезапустите
MCP-сервер»; если `server_version` ≠ `code_version` — «переустановите пакет»
(`uv tool install --force --editable .`, README §7): у editable-установки
метаданные обновляются только переустановкой, перезапуск сервера не поможет.
Чтение (57):
| Действие | Что делает |
|---|---|
| `stats_summary` | Итоги по аккаунтам: показы, клики, расход, конверсии |
| `stats_campaigns` | Статистика по кампаниям |
| `stats_adgroups` | Статистика по группам объявлений |
| `stats_ads` | Статистика по объявлениям |
| `stats_keywords` | Статистика по фразам и автотаргетингу |
| `stats_search_queries` | Поисковые запросы пользователей |
| `stats_regions` | Статистика по регионам местонахождения |
| `stats_placements` | Статистика по площадкам РСЯ |
| `stats_devices` | Статистика по устройствам |
| `stats_audiences` | Статистика по аудиториям и ретаргетингу |
| `stats_compare` | Сравнение двух периодов (только так, не вручную) |
| `stats_custom` | Произвольный отчёт: свои поля и фильтры |
| `campaigns_list`, `campaigns_get` | Список и полные настройки кампаний |
| `adgroups_list` | Группы кампании |
| `ads_list` | Объявления (ссылки, уточнения, DisplayUrlPath; фильтр States, вкл. архивные) |
| `keywords_list` | Фразы группы или кампании |
| `negatives_audit` | Все минус-фразы кампании одним ответом |
| `extensions_list` | Быстрые ссылки, уточнения, изображения |
| `audiences_list` | Аудиторные условия и списки ретаргетинга |
| `bids_get` | Ставки фраз (поиск и сети) |
| `bid_modifiers_get` | Корректировки ставок |
| `dictionaries_get` | Справочники (регионы по названию) |
| `changes_check` | Что менялось с даты |
| `accounts_discover`, `accounts_check`, `accounts_balance` | Кабинеты: поиск, проверка доступа, баллы |
| `counter_check` | Проверка счётчиков Метрики кампании |
| `metrika_goals_list` | Цели счётчиков Метрики: id, название, тип (без статистики) |
| `metrika_traffic` | Метрика: визиты по источникам (source/utm/direct/landing/device/region) |
| `metrika_goals_report` | Метрика: достижения целей и CR, в разрезе group_by — опционально |
| `metrika_bytime` | Метрика: динамика по дням/неделям (визиты, отказы, цель) |
| `metrika_direct_cpa` | Цена заявки по кампаниям: расход Директа + визиты/цели Метрики, CPA |
| `moderation_check` | Статусы модерации объявлений |
| `webmaster_hosts`, `webmaster_summary`, `webmaster_query` | Вебмастер: сайты и подтверждение прав, ИКС и проблемы, произвольный read-ресурс API v4 |
| `audience_segments_list`, `audience_segment_get` | Аудитории: сегменты пользователя (тип, статус, размер) |
| `strategies_get` | Пакетные стратегии: настройки, бюджеты и цели |
| `feeds_get` | Фиды: источник, статус обработки, кампании |
| `dynamic_targets_get`, `dynamic_feed_targets_get`, `smart_targets_get` | Условия динамических объявлений и фильтры смарт-баннеров |
| `businesses_get` | Профили организаций (только по ID) |
| `turbopages_get` | Турбо-страницы: метаданные без содержимого блоков |
| `keyword_bids_forecast` | Прогноз ставок по существующим фразам: объём трафика → ставка → цена (только чтение) |
| `phrases_forecast` | Прогноз показов/кликов/цен для новых фраз до добавления (Live v4, только чтение) |
| `wordstat_top` | Wordstat: популярные и связанные запросы за последние 30 дней |
| `wordstat_dynamics` | Wordstat: динамика частотности по дням, неделям или месяцам |
| `wordstat_regions` | Wordstat: распределение частотности по регионам за последние 30 дней |
| `wordstat_regions_tree` | Wordstat: справочник регионов и иерархия кодов |
| `retargeting_lists_list` | Условия ретаргетинга кабинета: правила человеческим языком, где используются |
| `audience_targets_list` | Привязки аудиторий к группам: условие, состояние, ставка/приоритет |
| `campaign_journal` | Журнал кампании: история правок, результаты по периодам, заметки (пишет md-файл) |
| `campaign_journal_snapshot` | Снимок результатов кампании за период (Директ + Метрика, локально) |
| `campaign_journal_note` | Заметка к кампании: гипотеза, решение, наблюдение, задача (локально) |
### Метрика: отчёты (v1.12.0, только чтение)
- `metrika_traffic` — визиты, пользователи, отказы, глубина, время,
достижения цели и CR по источникам: `group_by` — `source` (тип источника),
`utm` / `utm_full`, `direct` (кампании Директа), `landing` (страница входа),
`device`, `region`. Фильтры `filter_utm_source` / `filter_utm_campaign`
(точное совпадение).
- `metrika_goals_report` — строки = цели (достижения, CR); в разрезе
`group_by` — опционально (те же значения).
- `metrika_bytime` — динамика по дням/неделям (`group: day|week`):
визиты, отказы, выбранная цель.
- `metrika_direct_cpa` — связка с Директом по кампаниям одного логина:
расход/клики из Директа + визиты/отказы/цели из Метрики; колонки —
кампания, расход, клики, визиты, клики→визиты %, отказы %, цели, CR %,
CPA = расход / цели. Расхождение кликов и визитов > 30% —
флаг «проверить разметку/счётчик».
- Общее: счётчик — `counter_id`, иначе `[metrika] counter_id`, иначе счётчики
кампаний; период по умолчанию — последние 14 полных дней; цели по
умолчанию — основная (`primary_conversion_goal_id`), иначе все цели счётчика;
атрибуция по умолчанию `lastsign` (в шапке); `accuracy=full`, семплирование
помечается; 403 по счётчику — «нет доступа», без падения.
- Отчёты остаются только на чтение; запись целей счётчика — отдельные
действия записи, см. §5.3.
- Порядок сопоставления кампаний в `metrika_direct_cpa` (способ — в колонке
«Связь»): ID → ID+1e8 (у старых кампаний OrderID в Метрике больше
CampaignId на сто миллионов; «Связь» = ID+сдвиг) → точное имя при единственном
кандидате («Связь» = имя). Несопоставленные — отдельными блоками
(кампании логина без расхода / визиты кампаний других логинов /
«Чужие кампании»).
### Режим выгрузки (dump)
Любое действие чтения принимает параметры `dump_dir` (папка сессии) и
`dump_tag` (суффикс имени). В этом режиме ответ дополнительно сохраняется
в файлы как есть, без преобразований:
- `<NN>_<action>[_<tag>].json` — конверт ответа: `raw_items` (объекты API:
деньги в micros, enum, null, вложенность; единственное преобразование —
ID-ключи `*Id(s)` числом → строкой), `requested_field_names`
(по каким полям читали), `pagination_complete` (все ли страницы
прочитаны — честно из пагинации, не дефолт), `truncated` (неполон ли
именно raw), `display_truncated` (обрезан ли только показ для чата),
`warnings`. Пример: `03_keywords_list.json`, `07_ads_list_morning.json`;
- `manifest.json` — порядок файлов и их sha256 (сборка только по манифесту,
не по glob);
- `describe_<action>.json` — схема ответа (один раз на действие).
Пример вызова: `run_read({"name": "keywords_list", "params":
{"account": "client-a", "campaign_ids": [900000036],
"dump_dir": "C:/work/dump-session", "dump_tag": "morning"}})`.
Основной потребитель — скилл `yandex-direct-campaign-dump-directai`:
он вызывает чтения, собирает `dump.json`, проверяет полноту валидатором
и строит Markdown/Excel. Вручную данные не пересказываются.
Связанные правила чтения:
- `ads_list`, параметр `states`: по умолчанию архивные не возвращаются;
`states: ["ARCHIVED"]` (или вместе с `ON`/`OFF`/`SUSPENDED`) включает их.
- Фразы — целиком по умолчанию (включая внутрифразные минус-слова);
укороченный показ — только явным `short_phrases: true` и только
для отображения, raw не трогает.
### Прогноз ставок и спроса (v1.9.0, только чтение)
- `keyword_bids_forecast` — по уже добавленным фразам (`KeywordBids.get`:
`AuctionBids` → объём трафика/ставка/цена, `Coverage` для сетей):
ровно один scope (`campaign_id` | `adgroup_ids` | `keyword_ids`),
ровно один кабинет; таблица «объём → ставка → цена» + медианы цены
для объёмов 100 и 15. Пример: `run_read({"name":
"keyword_bids_forecast", "params": {"account": "client-a",
"keyword_ids": [900000011], "include_network": false}})`.
- `phrases_forecast` — по новым фразам до добавления (Live v4
`CreateNewForecast` → ожидание → `GetForecast` → `DeleteForecastReport`):
не более 100 фраз за отчёт, `region_ids[]` обязателен, `currency`
(по умолчанию RUB). Пример: `run_read({"name": "phrases_forecast",
"params": {"account": "client-a", "phrases": ["окна пвх"],
"region_ids": [213]}})`.
- Ограничения: ставки не меняются; на автостратегиях/ЕПК данные
показываются с пометкой «ставками управляет стратегия, прогноз
справочный», при отсутствии — «нет данных аукциона» (не ошибка);
`AuctionBids=null` при RARELY_SERVED, только графических объявлениях
в группе и всегда для автотаргетинга (показывается отдельно);
прогноз для новых фраз: не более 5 отчётов одновременно (ошибка 31),
хранение 5 часов, готовность до ~60 с (таймаут — `forecast_id`
для повтора); период API прогноза не поддерживает.
- Проверено живьём (10.2026): при поиске SERVING_OFF API всё равно отдаёт
`AuctionBids` — показываются справочно с пометкой про отключение поиска;
позиции прогноза — P11..P24, CTR — числом (знак % добавляет рендер).
### Ретаргетинг и аудитории (v1.10.0)
- Чтение всегда доступно: `retargeting_lists_list` — условия кабинета
(`«выполнили всё ... И НЕ выполнили ничего ...»`, Scope, где используются);
`audience_targets_list` — привязки к группам (условие, состояние,
ставка/приоритет). Пример: `run_read({"name": "retargeting_lists_list",
"params": {"account": "client-a"}})`.
- Правила (A8): в ЕПК/текстово-графических группах — условия `RETARGETING`
(цели/сегменты Метрики, сегменты Аудиторий); `AUDIENCE` — для медийных
групп (краткосрочные интересы допустимы и в ТГО); совместимость привязки
проверяется живьём по `AvailableForTargetsInAdGroupTypes` условия
(ЕПК-группы API v5 видит как `TEXT_AD_GROUP`).
На поиске условие сужает аудиторию (AND с фразами), в сетях — расширяет
(OR). Исключить аудиторию (например, купивших) — только корректировкой
ставки −100% (`bid_modifiers_set`, вид RETARGETING): «показы этой аудитории
будут полностью отключены»; в конверсионных стратегиях это меняет целевую
CPA/ДРР. Условие только из NONE-правил — только для корректировок
(привязать к группе нельзя).
- Запись выключена по умолчанию: `[retargeting] write_enabled = true`
в `accounts.toml` (аналог `[audience]`). Примеры:
посетители сайта за 30 дней без заказа — `retargeting_list_create`
(ALL-правило «цель визита», NONE-правило «цель заказа»);
исключить купивших — `bid_modifiers_set` с `kind: RETARGETING`,
`bid_modifier: 0` на условие купивших.
- Лимиты API: 2000 условий на пользователя, 1000 за вызов; 1–50 правил,
1–250 аргументов; срок членства 1–540 дней (для целей Метрики);
не более 50 привязок в ТГО-группе; ставка привязки — ручная стратегия
(при авто — только приоритет, ставка игнорируется с предупреждением).
- Баллы: `KeywordBids.get` — 15 + 3 за каждые 2000 фраз (оценка в ответе,
факт — в строке `API:`; при 152 — понятная ошибка с остатком);
Live-прогноз — без Units (баллы не расходуются). Учёт баллов уже есть
(`Units` из заголовков, `net_summary`) — переиспользован.
- Каждый ответ помечен «прогноз Яндекса, не гарантия» с датой, регионами
и валютой (НДС — как отдаёт API, без пересчёта). В dump поля аукциона
не добавляются. Подсказка также в описании `keywords_add`.
Запись (25, все — только через план, см. §5):
| Действие | Что делает |
|---|---|
| `campaigns_create`, `campaigns_update`, `campaigns_state` | Создание (по умолчанию ЕПК), изменение (в т. ч. ключевые цели), остановка/архив кампаний |
| `adgroups_create`, `adgroups_update` | Создание и изменение групп (тип группы — из типа кампании) |
| `ads_create`, `ads_update`, `ads_state` | Создание (для ЕПК — RESPONSIVE_AD), изменение, состояние объявлений |
| `keywords_add`, `keywords_update`, `keywords_state` | Фразы: пакетное добавление, тексты, состояние |
| `negatives_set` | Минус-фразы кампании/групп и общие наборы |
| `extensions_create` | Ссылки, уточнения, изображения |
| `bids_set` | Ставки фраз (поиск и сети) |
| `bid_modifiers_set` | Корректировки: добавить, изменить, удалить (включая RETARGETING для аудиторий) |
| `metrika_goal_create`, `metrika_goal_update`, `metrika_goal_delete` | Цели счётчика Метрики: создать, изменить, удалить (нужен токен с правом `metrika:write`, см. §5.3) |
| `retargeting_list_create`, `retargeting_list_update`, `retargeting_list_delete` | Условия ретаргетинга: создание, изменение, удаление неиспользуемых (только при `[retargeting] write_enabled=true`) |
| `audience_target_add`, `audience_target_state` | Привязка условий к группам, пауза/возобновление/удаление привязок (только при `[retargeting] write_enabled=true`) |
Запись в Аудитории (экспериментально, выключена по умолчанию
`[audience] write_enabled=false`): `audience_segment_from_file` — создание
сегмента uploading из локального CSV/TXT (phone/email, в API только SHA256-хеши;
имя только `[TEST DirectAI]*`, файл с несколькими колонками без `id_column`
отклоняется) и `audience_segment_delete` — удаление сегмента только
`[TEST DirectAI]*` по живому имени из API. Путь тот же: `plan_write` → ваше
согласие → `apply_write`; без включённого `write_enabled` оба действия
отклоняются до API.
Запись ретаргетинга (v1.10.0, выключена по умолчанию
`[retargeting] write_enabled=false`): `retargeting_list_create` /
`retargeting_list_update` / `retargeting_list_delete` — условия
(цели Метрики, сегменты; удаление — только неиспользуемых, без префикса
`[TEST DirectAI]` нужно явное согласие) и `audience_target_add` /
`audience_target_state` — привязка к группам и её состояние.
Исключение аудитории — только корректировкой −100% (`bid_modifiers_set`,
вид RETARGETING), не условием. Путь тот же: `plan_write` → ваше
согласие → `apply_write`; без включённого `write_enabled` все пять
действий отклоняются до API. Подробности — раздел «Ретаргетинг и аудитории» ниже.
## 5. Как работает запись
1. ИИ вызывает `plan_write` — сервер показывает предпросмотр «было → станет»
и предупреждения (например, ставка меняется больше чем в 2 раза).
2. Вы читаете предпросмотр и явно разрешаете.
3. ИИ вызывает `apply_write` (с `acknowledge_warnings=true`, если были
предупреждения) — сервер выполняет, затем **повторно читает объект
(read-back)** и пишет всё в журнал.
4. Итог: `applied` (подтверждено), `partial` (часть строк отклонена API),
`failed`, `unverified` (результат неясен — проверить вручную).
Журнал: инструмент `get_operation_log` (последние операции) и файл
`journal.sqlite`. Планы живут в каталоге `plans\` — общем для всех процессов
сервера: план, созданный в одном процессе, применяется из любого другого
ровно один раз (повтор — «уже применён», истёкший — «просрочен»,
неизвестный id — «не найден»). Прямых записей в обход плана не бывает. Что можно где:
бюджеты и смена стратегии запрещены везде (к ключевым целям относится
изменение их набора и ценностей); в боевых кампаниях разрешены
фразы (добавление, пауза/запуск), объявления (создание, тексты, ссылки),
ссылки/уточнения, регионы групп, минусы и площадки (добавление), ставки
и корректировки; замена целиком (replace), пауза кампаний и объявлений,
удаления — только в тестовых кампаниях `[TEST DirectAI]*`.
## 5.1. Создание кампаний: ЕПК по умолчанию
- `campaigns_create` создаёт `UNIFIED_CAMPAIGN` (ЕПК, запрос на `json/v501`).
Legacy `TEXT_CAMPAIGN` — только явным `campaign_type="TEXT_CAMPAIGN"`
с предупреждением «устаревший тип».
- `campaigns_update`: блок стратегии и версия запроса — по типу кампании
(`UnifiedCampaign`/`v501` для ЕПК).
- `adgroups_create`: тип группы API выводит из кампании; неизвестная
кампания или тип — отказ до API.
- `ads_create`: для ЕПК используйте `responsive_ads` (`RESPONSIVE_AD`,
запрос на `v501`); `TEXT_AD` допустим, но API конвертирует его
(10251) — предупреждение требует подтверждения. Совместимость типа
группы/кампании проверяется до API. DisplayUrlPath обязателен
для обоих типов и сверяется в read-back.
- Цепочка создания: кампания → группа → фразы → объявление отдельными
планами; модерация (`ads_state moderate`) в цепочку не входит и
заблокирована guard по умолчанию — только отдельным шагом
с явного решения пользователя.
## 5.2. Ключевые цели (`campaigns_update`: `priority_goals`)
Цели и их ценности (`PriorityGoals`) — вход оптимизации, поэтому меняются
тем же планом, что и стратегия: только в тестовой кампании, а в режиме
`confirm` — после явного «да» на конкретный план.
- Формат: список `[{goal_id, value_rub, is_metrika_source_of_value=false}]`.
`value_rub` — ценность конверсии в рублях (для «Максимум прибыли» —
маржа); внутрь уходит в микро-единицах (₽ × 1 000 000). Список целей —
`metrika_goals_list`; `is_metrika_source_of_value=true` API принимает
только для стратегий с долей расходов (`AVERAGE_CRR`,
`PAY_FOR_CONVERSION_CRR`).
- Режим один — **замена набора целиком** (`Operation=SET`): не перечислили
цель — она пропала. Пустой список без явного `priority_goals_reset=true`
отклоняется до API; `priority_goals_reset=true` — это `PriorityGoals=null`
(оптимизация на вовлечённые сессии). Оба параметра вместе нельзя.
- Повторяющийся `goal_id`, `goal_id ≤ 0` и `value_rub ≤ 0` — отказ до API.
- Как в API, ключевые цели нельзя передавать кампании в пакетной стратегии
(и нельзя одновременно с ключом пакетной стратегии в параметрах): такую
кампанию сначала отвязывают (`PackageBiddingStrategy=null` + новая
`BiddingStrategy`) — DirectAI этого пока не делает.
- Предпросмотр плана показывает цели и ценности «было → станет», read-back
после записи перечитывает `PriorityGoals` и сверяет их с запрошенными.
## 5.3. Цели счётчика Метрики (`metrika_goal_create/update/delete`)
Запись целей — через Management API `POST|PUT|DELETE
/management/v1/counter/{counterId}/goal(s)`. Нужен **отдельный токен
приложения Метрики** с правом `metrika:write` (§7.1): без него запись
отклоняется до обращения к API. Если права нет, API отвечает 403, и сервер
объясняет, как перевыпустить токен — токен в сообщениях, логах и чате не
появляется.
`counter_id` — точный id счётчика, без разбора кампаний.
Типы целей и параметры:
| Тип (`type`) | Условия | Особое |
|---|---|---|
| `action` | `conditions=[{operator, value}]`, `operator` = `exact`/`contain`/`start`/`regexp` | JS-событие; `value` — идентификатор события (`ym(...)`) |
| `url` | `conditions=[…]` (те же операторы + `action`/`regexp_action`/`contain_action` для составных целей) | посещение страниц; несколько условий — «ИЛИ» |
| `email`, `messenger`, `search` | `conditions=[…]` | длина значения до 1024 (`email`) / 16384 |
| `phone` | `conditions=[…]` | `hide_phone_number`; значение до 25 символов |
| `file` | `file_all=true` **или** `file_url=…` | ровно одно из двух |
| `social` | `social_all=true` **или** `social_url=…` | ровно одно из двух |
| `step` | `steps=[{type: action|url, conditions:[…]}]`, 2–5 шагов | составная цель, порядок шагов важен |
| `number` | `depth` (≥ 2) | глубина просмотров |
| `visit_duration` | `duration` (секунды, ≥ 1) | длительность визита |
Общее для всех: `name` (1–255), `default_price` (цена по умолчанию,
не отрицательная), `is_favorite`.
- **Мультицели в Management API нет** — типа `multi` в GoalE не существует
(мультицель есть только в интерфейсе Метрики). Эквивалент «несколько
условий через ИЛИ» — несколько `conditions` в одной цели, так и работает
`type=url`/`action`; отдельная попытка создать `multi` отклоняется с этим
текстом. Типы `chat` и `payment_system` в DirectAI не заведены.
- **Проверки до записи** (живое чтение, до обращения к API): право на
счётчик (`GET counter/{id}` → `permission`: `own`/`edit`; `view` — только
просмотр, запись отклоняется), лимит счётчика — до 200 целей, и **точный
дубль**: тот же тип + те же условия → отказ с id и именем существующей
цели (порядок условий и краевые пробелы не считаются различием; порядок
шагов составной цели — считается).
- `metrika_goal_update` — частичное изменение (имя, условия, цена по
умолчанию, `is_favorite`, `depth`, `duration`). В API `PUT` заменяет цель
целиком, поэтому сервер читает живую цель и собирает полное тело: поля,
которые вы не меняли, сохраняются. Ничего не меняется — отказ до API.
Тип цели и её шаги не меняются; автоцели (`e_purchase`, `call`, `form`,
`conditional_call` и др. — их нет в GoalE) не обновляются и удаляются
только вручную в интерфейсе.
- `metrika_goal_delete` — необратимо: собранная по цели статистика пропадёт
из отчётов. План всегда помечается «⚠ ОПАСНАЯ ОПЕРАЦИЯ» и применяется
только с `owner_confirmed=true` (в любом режиме guard) и
`acknowledge_warnings=true`.
- Read-back после каждой записи: сервер заново читает цели счётчика и
сверяет тип, условия и имя (id новой цели — из ответа POST). При таймауте
или обрыве связи статус `unverified`, запись **не повторяется вслепую** —
решение принимает перечитанный список целей.
## 6. Guard (защита)
Опасные операции — строго внутри кампаний `[TEST DirectAI]*`.
Guard это контролирует: перед каждой записью сверяет
**живое имя кампании** через API.
Как завести тестовую кампанию: создайте в интерфейсе Директа кампанию
с именем, начинающимся на `[TEST DirectAI]` (можно черновик); только в ней
доступны replace, пауза кампаний/объявлений, удаления.
Коротко о правилах:
- бюджеты и смена стратегии — запрещены везде, даже в тестовых; к стратегии
отнесены и ключевые цели с ценностями (см. §5.2);
- в боевых кампаниях можно: фразы, объявления, ссылки/уточнения, регионы,
минусы и ставки (см. §5);
- только в тестовых: замены целиком, пауза кампаний/объявлений, удаления.
Блокируется: запись вне разрешённого, переименование кампаний,
модерация, чужие общие объекты, неизвестные действия.
Включён по умолчанию (`[guard] guard=true` в `accounts.toml` плюс дефолт
в коде). Выключение — **только вашим решением**: поставьте `guard = false`
(и убедитесь, что нет переменной `DIRECTAI_TEST_GUARD=1`), после тестов
верните `true`.
#### Режим `confirm` (v1.15.0): не запрет, а подтверждение владельца
```toml
[guard]
guard = true
mode = "confirm" # по умолчанию "block"
```
В режиме `confirm` политические запреты не блокируют, а превращают план
в **«⚠ ОПАСНАЯ ОПЕРАЦИЯ»** со списком причин:
бюджет (`daily_budget`, `strategy` с `WeeklySpendLimit`), смена стратегии,
изменение ключевых целей и их ценностей (§5.2),
модерация, переименование кампании, создание кампании без префикса,
пауза/запуск/архив кампаний и объявлений, правки вне `[TEST DirectAI]*`,
замены целиком, удаление корректировок, чужие общие объекты.
Такой план применяется только `apply_write(..., owner_confirmed=true)` —
агент ставит флаг **лишь после явного «да» владельца в чате на этот
конкретный план**. Предупреждения по-прежнему требуют отдельно
`acknowledge_warnings=true`. В журнал операция пишется с пометкой
`[ОПАСНАЯ, подтверждено владельцем]`.
Жёсткими остаются и в `confirm`: объект не найден/ошибка API, поля
`read_only` (A1), выключенные Аудитории/ретаргетинг (`write_enabled=false`),
неизвестные действия.
Цели Метрики (§5.3) живут вне Директа, поэтому префикс `[TEST DirectAI]*` к
ним не относится: запись проверяет право на счётчик, отсутствие дубля и
лимит 200 целей (это отказ до API), а удаление цели в любом режиме guard
требует `owner_confirmed=true`.
`campaigns_update` снова принимает `name` (одна кампания за план)
и `daily_budget` (₽, `daily_budget_mode` STANDARD|DISTRIBUTED) — в `block`
они отклоняются до API, в `confirm` — опасная операция.
То же и для ключевых целей (`priority_goals`, `priority_goals_reset`): класс
«стратегии» (§5.2), свойств плана (`plan_id`, TTL 15 минут,
`acknowledge_warnings`, `owner_confirmed`) сервер не ослаблял.
### 6.1 Правило для агентов-клиентов MCP
Текст блокировки guard — это **защита, а не ошибка**.
При блокировке агент:
1. останавливается и сообщает вам: какая операция, какой объект, почему
заблокирована (режим `confirm`: план «⚠ ОПАСНАЯ ОПЕРАЦИЯ» — показывает
причины дословно и применяет с `owner_confirmed=true` только после
вашего явного «да» на этот план);
2. **не ищет и не меняет** конфиг guard (`accounts.toml`, секция `[guard]`,
переменная `DIRECTAI_TEST_GUARD`) и вообще ничего в `safety/`;
3. **не предлагает обход** защиты;
4. **не переносит** операцию на другую кампанию (в т.ч. тестовую) без вашего
явного указания.
Снятие ограничения — только ваше ручное решение (см. §6). Ни один инструмент
сервера конфиг guard не пишет и не читает наружу: единственный источник —
`accounts.toml` и переменная окружения.
### 6.2 Сравнение периодов и выбор инструмента
1. Сравнение периодов агент выполняет **только через `stats_compare`**
(A, B, Δ абс., Δ% одним вызовом). Два вызова `stats_*` с ручной
арифметикой запрещены — они дают разную точность Δ%.
2. Если вы указали конкретный MCP-сервер или инструмент — агент использует
**только его** и не подменяет другим.
## 7. Обновление
Перед обновлением: закройте все окна харнесов и остановите фоновый
шлюз Hermes (он держит `directai-mcp.exe` даже при закрытых окнах) —
команды выполняет человек в обычном PowerShell:
```powershell
Get-Process directai-mcp -ErrorAction SilentlyContinue | Stop-Process -Force
hermes -p default gateway stop 2>$null
Get-CimInstance Win32_Process |
Where-Object { $_.CommandLine -match 'hermes|openchamber|opencode' -and $_.ProcessId -ne $PID } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
Start-Sleep -Seconds 2
Get-CimInstance Win32_Process |
Where-Object { $_.Name -eq 'directai-mcp.exe' -or $_.CommandLine -match 'hermes|openchamber|opencode' } |
Select-Object ProcessId, Name
```
Фильтр по `python.exe … hermes_cli.main … gateway run` не использовать:
Hermes запущен отдельным процессом (direct spawn) и таким фильтром не ловится.
Чужие процессы агент не убивает — команды выполняет человек.
Проверка перед переустановкой (c и d должны быть OK):
```powershell
directai-mcp doctor --preinstall
```
Обновление с бэкапом вне uv tool dir и откатом при ошибке
(без `exit` — он закрывает окно PowerShell):
```powershell
cd $env:USERPROFILE\directai-mcp
git pull
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$tooldir = uv tool dir
Copy-Item "$tooldir\directai-mcp" "$env:USERPROFILE\directai-mcp-tool-backup-$stamp" -Recurse
uv tool install --force --editable .
uv tool update-shell
if ($LASTEXITCODE -ne 0) {
Remove-Item "$tooldir\directai-mcp" -Recurse -Force
Copy-Item "$env:USERPROFILE\directai-mcp-tool-backup-$stamp" "$tooldir\directai-mcp" -Recurse
Write-Output "ОТКАТ: инструмент восстановлен из бэкапа"
} else {
directai-mcp check
directai-mcp probe
Remove-Item "$env:USERPROFILE\directai-mcp-tool-backup-$stamp" -Recurse -Force
}
```
`init` после обновления можно повторить: существующие конфиги не затрутся,
недостающие (например, новые примеры) докопируются. После обновления
откройте харнесы заново и запустите Hermes (сервер подхватывается при
старте). Никогда не делайте `cd` внутрь каталога установки (`uv tool dir`):
бэкап перед установкой — только вне tool dir (копии внутри tool dir `uv`
считает инструментами и выдаёт `malformed`); бэкап удаляется только при
успехе, при ошибке — откат из бэкапа.
## 7.1. Отдельный токен Метрики (v1.17.1)
Метрика больше не работает на токене Директа: у приложений «для авторизации
пользователей» лимит 3 группы разрешений, поэтому права `metrika:read` и
`metrika:write` живут в отдельном приложении Яндекс OAuth и хранятся в своём
ключе Credential Manager (`directai-mcp-metrika`).
Поведение по умолчанию:
- **чтение** Метрики (`metrika_traffic`, `metrika_goals_list`,
`metrika_goals_report`, `metrika_bytime`, `metrika_direct_cpa`,
`counter_check`, снимки журнала) идёт отдельным токеном, если он есть;
- **без отдельного токена** чтение продолжает работать на токене Директа, а в
ответе появляется примечание «Метрика читается токеном Директа…»;
- **запись целей** (`metrika_goal_create/update/delete`) без отдельного токена
не начинается: `Ошибка подготовки: запись целей Метрики требует отдельный
токен Метрики (metrika:write)…` — до обращения к API.
Выпуск токена (шаги выполняет владелец, токен в чат не передаётся):
1. В приложении Метрики включены права **«Яндекс Метрика» → чтение и
изменение** (`metrika:read` + `metrika:write`), Redirect URI
`https://oauth.yandex.ru/verification_code` — как у приложения Директа.
2. Откройте в браузере под своим логином (команда сама напечатает ссылку с
`client_id` приложения Метрики):
```powershell
directai-mcp set-metrika-token --login ВАШ_ЛОГИН
```
3. Разрешите доступ, скопируйте токен из адресной строки и вставьте его в
скрытое поле, которое задаёт команда. Client secret приложения DirectAI
не знает и не хранит — OAuth-поток проходит в браузере, как для Директа.
4. Проверка: `directai-mcp check` (строка «Метрика: …») и
`directai-mcp doctor` (проверка `l. Метрика`). В `describe_action` без
аргументов тоже есть строка «Метрика: отдельный токен / токен Директа».
Что показывают проверки (значение токена не печатается нигде):
- источник токена и его длина;
- `client_id` приложения, выпустившего токен (`login.yandex.ru/info`) —
так видно, что Метрике достался именно токен приложения Метрики; если
приложение чужое, `check` и `doctor` об этом предупреждают;
- читается ли список счётчиков;
- право `metrika:write` **не проверяется**: Яндекс не отдаёт scopes токена, а
выяснить его можно только записью цели. Поэтому в выводе честно сказано,
что право подтвердит первая запись (при 403 сервер объяснит, как
перевыпустить токен).
Отозвать токен — на стороне Яндекс ID (правки приложения → «Отозвать
токены»); новый токен выпускается той же командой.
### 7.2. Секреты в логах (v1.17.2)
- Логи HTTP-клиентов (`httpx`, `httpcore`) всегда на уровне **WARNING**:
на INFO логгер пишет URL запроса целиком, а значит и query-параметры.
Поднимать их уровень нельзя.
- Дополнительно все обработчики логов чистят значения параметров
`oauth_token`, `token`, `apikey`, `api_key`, `access_token`,
`refresh_token` → `***`. Тексты сетевых ошибок Метрики чистятся тоже.
- Токены передаются только заголовками (`Authorization: OAuth` / `Bearer` /
`Api-Key`) и никогда не попадают в URL, ответы инструментов, журнал
операций и предпросмотр плана.
- Файл лога: `%USERPROFILE%\.directai\logs\directai.log`. Если секрет туда
попал (например, старая версия): перевыпустите токен и удалите файл —
он пересоздаётся при следующем запуске.
```powershell
Remove-Item "$env:USERPROFILE\.directai\logs\directai.log"
```
## 8. Типичные ошибки
| Симптом | Что делать |
|---|---|
| Ошибка 53 (авторизация) | Токен недействителен: `directai-mcp set-token`, затем `check` |
| Ошибка 58 (регистрация приложения) | Завершите заявку на доступ к API в интерфейсе Директа |
| Ошибка 513 (логин не подключён) | Логин не привязан к Директу — проверьте `Client-Login`/аккаунт |
| Не хватает баллов API | Подождите сброса лимита; остаток виден в `check` |
| Харнес не видит сервер | Стабильный путь к exe — `(Get-Command directai-mcp).Source` (обычно `%USERPROFILE%\.local\bin\directai-mcp.exe`); перезапуск харнеса, логи в `.directai\logs` |
| План с предупреждениями не применяется | Это защита: повторите `apply_write` с `acknowledge_warnings=true` только после вашего согласия |
| `token missing for login 'X'` | Токен сохранён под другим логином: выполните `directai-mcp set-token --login <[auth] login>` с логином из `accounts.toml` |
| Вебмастер: «нет права» / «токен не принят» | Нужен отдельный токен: `directai-mcp set-token --webmaster` (приложение «для доступа к API» с правом `webmaster:hostinfo`) |
| Метрика: 403 при записи целей | Не хватает отдельного токена Метрики или в нём нет права `metrika:write`: выпустите токен приложения Метрики — `directai-mcp set-metrika-token --login <ваш логин>` (§7.1). Токен в чат не пишите |
| Метрика: «запись целей Метрики требует отдельный токен» | Тот же текст без обращения к API: запись не начинается, пока не выпущен отдельный токен Метрики (§7.1) |
| Метрика: «у вас доступ только просмотр» | Счётчик открыт гостю с уровнем `view`: запись целей на нём невозможна, нужен уровень `edit` |
| Wordstat: «API key missing» или «folderId не настроен» | Выполните `directai-mcp set-token --wordstat`; API-ключ вводится скрыто, `folderId` хранится в `[wordstat]` |
| `Ignoring malformed tool` | Битая копия/рецепт, не повод сносить рабочий инструмент: закройте все окна харнесов и переустановите с `--force` (бэкап — вне tool dir). `uninstall` — только для заведомо мусорных записей |
| `os error 32` при переустановке | exe занят MCP-клиентами: покажите владельцев (`Get-CimInstance Win32_Process -Filter 'Name="directai-mcp.exe"'`, поле `ParentProcessId`), чужие процессы не убивайте. Шлюз Hermes (`python.exe … hermes_cli.main … gateway run`) работает в фоне и держит exe даже при закрытых окнах — человек останавливает его сам (см. §7: остановка сервера и шлюза), после установки запускает Hermes заново. Висящие `opencode serve` — тоже владельцы: их закрывают штатно, не `kill` |
| Как быстро проверить сервер | `directai-mcp --version` → `check` → `probe` (две строки OK, `stats_summary` найден; баллы не тратятся). Сырые stdio-пробы вручную не делать |
## 8.1. Диагностика (doctor)
При проблеме подключения — сначала doctor (агент — см. AGENTS.md §4.1):
```powershell
directai-mcp doctor
directai-mcp doctor --skip-api # без сети
directai-mcp doctor --json # машинный вывод для скилла
directai-mcp doctor --preinstall # строгая проверка перед переустановкой
```
Одиннадцать проверок по порядку (версия, exe, процессы, блокировка файла,
конфиг, токены, API, Hermes, Аудитории, ретаргетинг, каталог планов) — каждая OK / WARN / FAIL
с причиной и рекомендуемым действием. Код возврата: 0 — всё OK,
1 — есть WARN, 2 — есть FAIL. Токены не печатаются (только есть/нет/длина).
Занятый exe и работающие сессии по умолчанию — INFO, а не тревога;
строго (WARN/FAIL) — только с `--preinstall` перед переустановкой.
Диагностика read-only: ничего не останавливает и не правит, чинит человек
готовым блоком из `skills/directai-connection-doctor/references/playbooks.md`.
Скилл `directai-connection-doctor` (триггеры: «MCP не работает»,
«os error 32», «hermes не видит», коды 513/58/53) лежит в репозитории
(`skills/directai-connection-doctor/`); установка локально — скопировать
папку в `%USERPROFILE%\.agents\skills\directai-connection-doctor`.
## 8.2. Скиллы сценариев (v1.11.0)
- `directai-campaign-audit` (`skills/directai-campaign-audit/`): разбор кампании —
настройки, `stats_compare` 14 vs 14 (Δ = A−B, Δ% от базы B), срезы, гигиена,
план улучшений. Только чтение. Триггеры: «разбери кампанию», «почему просела»,
«что улучшить», ID кампании.
- `directai-campaign-create` (`skills/directai-campaign-create/`): кампания
из описания или YAML (`references/campaign-template.yaml`) — бриф,
`phrases_forecast`, структура таблицей → «да», запись через планы, кампания
остаётся остановленной. Триггеры: «создай кампанию», описание товара/услуги.
- Установка локально — скопировать папку скилла
в `%USERPROFILE%\.agents\skills\<имя>`. Общие правила обоих скиллов: бюджеты
не менять без явного «да» владельца (план «ОПАСНАЯ ОПЕРАЦИЯ»), запись только prepare → подтверждение → apply → read-back,
DisplayUrlPath всегда заполнять.
## 9. Что отложено
Актуальный список — в `BACKLOG.md` (пункты 4–10: правила бизнеса, Вордстат,
упущенный спрос, напоминания, лиды, позиции SERP, VK Ads) и в «Замеченные
хвосты» там же. Устаревший список «что отложено» здесь больше не ведётся.
## 10. Знания Директа (пакет A1–A11 + B2)
Авторство части знаний: см. NOTICE.md (awaik/direct-mcp-ai-project, MIT).
- A1: `ENABLE_AREA_OF_INTEREST_TARGETING` отменено 31.08.2026 — только чтение
(`campaigns_get` + `campaign_setting_notices`); запись отклоняется.
Поля из `notices` не писать никогда.
- A2: Директ сам добавляет минус-слова в пересекающиеся фразы группы
(`keywords_list`); автоминус не считать ошибкой.
- A3: операторы минус-фраз — см. раздел «Минус-фразы» ниже.
- A4: корректировки — разные категории перемножаются, внутри категории
наибольшая, −100% низший приоритет, групповая перекрывает кампанию;
в конверсионных — влияет на CPA/ДРР (`bid_modifiers_set`).
- A5: GoalId 12 = вовлечённые сессии, 13 = все приоритетные цели (служебные).
- A6: атрибуция — Метрика с 25.06.2026 cross-device, у Директа свои enum;
каждый `stats_*` показывает `attribution {requested, effective, source}`.
- A7: `WB_MAXIMUM_CLICKS` требует `WeeklySpendLimit`; `AVERAGE_CPC` отдельная
стратегия с `AverageCpc` (`strategies_get`).
- A8: ЕПК/текстово-графические — `RETARGETING` с goal_id; `AUDIENCE` только
медийные; поиск AND, сети OR (`audiences_list`).
- A9: макросы трекинга (`campaigns_update`/`adgroups_update`, TrackingParams).
- A10: Турбо-блоки, `clients.site`, CPM-видео — только интерфейс.
- A11: интенты — 5 классов; цену/отзывы/гео не минусовать автоматически.
### Минус-фразы
- `"..."` — запрос только из этих слов; `[]` — порядок; `!` — словоформа;
`+` — обязательность; полное пересечение минуса с ключом отменяет минус.
- Проверка конфликтов — в `dump_to_xlsx.py` (функция `neg_match`), тесты
на вымышленных фразах.
### Атрибуция
| Система | Модели |
|---|---|
| Директ | FCCD, LC, LSCCD, AUTO (прямого соответствия Метрике нет) |
| Метрика (legacy → cross-device с 25.06.2026) | lastsign → cross_device_last_significant и др. |
Фактическая модель Reports API отдельно не возвращает: в `effective`
подставляется запрошенная модель (`effective_attribution`), `source` —
откуда взялась (`api` — явно в параметрах, `config` — дефолт accounts.toml).
`effective=null`, `source="not_reported"` — только если модели действительно
нет. Без целей Reports игнорирует AttributionModels (фактически LC) —
это помечается в ответе отдельно.
## 11. Статусы поиска (B1, v1.6.0)
Каждый ответ `campaigns_get`/`campaigns_list` несёт строку
`Статус поиска: <lookup_status>, presence=..., proves_account_empty=...`
и то же в dump-конверте/manifest (`lookup_status`).
| lookup_status | Когда | presence |
|---|---|---|
| `resolved` | объект найден в Campaigns API | `configured` |
| `resolved` | в Campaigns API нет, в Reports есть данные (архив/удалена/чужой доступ) | `statistics_only` |
| `not_observed` | нет ни в API, ни в Reports за проверенный период (период указан в message). Не утверждается, что кампании не существует | `null` |
| `ambiguous` | поиск по имени/подстроке дал >1 совпадения; возвращаются кандидаты (id, name, state) | `null` |
| `incomplete` | ответ частичный (пагинация/лимит/ошибка части запросов); указано, что не проверено | `null` |
| `failed` | ошибка API/сети; код ошибки Директа, без трактовки как «пусто» | `null` |
Проверка Reports для `statistics_only` — только когда Campaigns API вернул
пусто по явному ID; один лёгкий отчёт (`CAMPAIGN_PERFORMANCE_REPORT`,
`CampaignId`, `Impressions`/`Clicks`, период по умолчанию 90 дней,
параметр `lookup_days` переопределяет). Пустой `campaigns_list` —
`proves_account_empty=false` + причины (фильтр, права, логин):
пусто ≠ объекта нет. Запись разрешена только при `resolved+configured`
(guard отклоняет остальное до API).
## 12. Основная цель (B3, v1.6.0)
`accounts.toml`: необязательное поле кабинета `primary_conversion_goal_id`
(вымышленный пример: `900000123`) и переопределение по кампании
`[aliases.<имя>.campaigns.<campaign_id>] primary_conversion_goal_id`
(также `[accounts.<имя>.campaigns.<id>]`, пример: `900000456`).
Приоритет: явный параметр запроса `primary_goal` > кампания > кабинет > нет.
Валидация: целое > 0; служебные `12`/`13` допустимы, но `check` предупреждает
с расшифровкой (вовлечённые сессии / все приоритетные цели); сверка с целями
Метрики — best-effort, отсутствие доступа — предупреждение, не ошибка.
`stats_*`/`stats_compare`: блок `Цель: id=..., label=..., source=param|campaign|account|none`
рядом с атрибуцией; CPA/CR — по этой цели; при `source=none` — как в v1.5.0
+ warning «основная цель не задана, CPA по всем целям».
Правило для агентов: перед оптимизацией читать журнал кампании
(`campaign_journal`) и считать CPA по основной цели.
## 13. Журнал кампании (v1.13.0)
Один Markdown-файл на кампанию: что меняли, почему и что стало с результатами
(`<reports_dir>/journals/<login>/<campaign_id>.md`, перезаписывается при каждом
`campaign_journal`; источник правды — `journal.sqlite`). Привязка операций —
таблица `operation_campaigns` (схему `operations` не меняли; старые записи
привязаны backfill при первом `connect`). Снимки результатов —
`campaign_snapshots` (`direct`: показы/клики/расход/CTR/CPC/конверсии из
`stats_compare`-логики; `metrika`: визиты/отказы/цели/CPA из
`metrika_direct_cpa`-логики; цель по умолчанию — основная; будущие даты
отклоняются до API, как в v1.12.1). Заметки — `campaign_notes`
(`hypothesis|decision|observation|todo`).
Инструменты (все read; заметки и снимки пишут только локально, без write API
Директа и без планов): `campaign_journal` (сборка + файл),
`campaign_journal_snapshot`, `campaign_journal_note`, фильтр
`get_operation_log(campaign_id=...)`. Δ в таблице снимков: Δ = A−B, Δ% от B.
TDQS
Scored across 7 tools
Each tool maps to a distinct stage or resource: account listing, catalog search, action introspection, read execution, write planning, write application, and logging. The plan/apply pair is complementary rather than ambiguous, and read/execute vs. catalog search are clearly separated.
All tool names follow a consistent lowercase snake_case verb-first pattern: list_, search_, describe_, run_, plan_, apply_, get_. The naming style is uniform and predictable across the entire set.
Seven tools is well within the ideal range and each tool earns its place in the workflow. The count matches the server's apparent scope: account discovery, action inspection, read execution, and a two-phase write flow.
The toolset covers the main lifecycle well: discover accounts, search and describe actions, run reads, plan writes, apply them, and review the operation log. Minor gaps exist, such as no explicit cancel-plan operation or fetching a single log entry by ID, but agents can work around these.