yadirect-mcp
# Yandex Direct MCP Server — отчёты и безопасное создание кампаний для AI-агентов
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](https://yandex.ru/dev/direct/doc/ru/)
[](https://github.com/Lermont/yamcp/actions/workflows/ci.yml)
[](LICENSE)
**yadirect-mcp** — локальный MCP-сервер для Яндекс Директа, который подключает рекламную отчётность и защищённую настройку кампаний к Claude Code, OpenAI Codex, Hermes Agent, ZCode и другим MCP-совместимым AI-агентам.
Вместо десятков низкоуровневых методов API агент получает семь понятных инструментов для аналитики и один опциональный инструмент для создания кампании. Инструмент здесь соответствует задаче, а не методу API: например, `direct_account_settings` за один вызов читает корректировки, ретаргетинг и общие минус-фразы — три сервиса, которые в разборе кампании нужны вместе. Большие отчёты сохраняются в TSV, а в контекст модели возвращаются только сводка и preview — это экономит токены и не обрезает данные.
> [!IMPORTANT]
> По умолчанию сервер работает в режиме `report`: все доступные инструменты только читают данные. Режим создания кампаний включается явно через `YD_MODE=campaign_setup`, требует preview и точного подтверждения и никогда автоматически не запускает показы.
## Для чего нужен yadirect-mcp
- Выгружать статистику Яндекс Директа естественным языком прямо из AI-агента.
- Получать список клиентов агентства и кампаний рекламодателя.
- Строить отчёты по показам, кликам, расходу, CTR, CPC, конверсиям и другим полям Reports API.
- Читать настройки, которых в отчётах нет: корректировки ставок, условия ретаргетинга, общие наборы минус-фраз.
- Видеть, куда ведёт реклама: посадочные страницы объявлений, их UTM-разметку и заполненность дополнений.
- Проверять коды регионов до того, как они уедут в кампанию или в запрос частотности.
- Сохранять полные выгрузки на диск и читать их постранично без повторного расхода баллов API.
- Подготавливать текстово-графическую кампанию с группами, объявлениями и ключевыми фразами.
- Проверять план кампании до записи и создавать объекты только после явного согласия пользователя.
- Ограничивать доступ AI-агента белым списком клиентских логинов.
Проект полезен агентствам, PPC-специалистам, performance-маркетологам, аналитикам и разработчикам AI-автоматизаций для Яндекс Директа.
## Ключевые возможности
| Возможность | Как реализовано |
|---|---|
| Безопасный режим по умолчанию | В `YD_MODE=report` write-инструмент даже не регистрируется в MCP |
| Агентский токен, много клиентов | `client_login` передаётся в каждый клиентский вызов |
| Большие отчёты без переполнения контекста | Полный TSV сохраняется на диск, модель получает totals и первые строки |
| Частотность Вордстата | `direct_wordstat` собирает спрос по фразам, пишет полный список на диск и отдаёт сводку |
| Настройки мимо отчётов | `direct_account_settings` читает корректировки, ретаргетинг и общие минус-фразы; секции независимы |
| Посадочные страницы и UTM | `direct_ads` отдаёт `Href`, которого нет ни в одном типе отчёта, и сводку по уникальным URL |
| Гео без угадывания | `direct_regions` ищет код по названию и проверяет готовые коды, которые Директ принимает молча |
| Корректные агрегаты | CTR, CPC и CR пересчитываются из суммарных метрик, а не складываются по строкам |
| Онлайн- и офлайн-отчёты | Поддержаны ответы `200`, очередь `201` и ожидание `202` с `retryIn` |
| Контроль очереди | Семафор на логин и лимит `YD_MAX_INFLIGHT` от 1 до 5 |
| Видимость баллов API | Заголовок `Units` добавляется к ответу инструмента |
| Защита от чужого кабинета | `YD_ALLOWED_LOGINS` ограничивает допустимые логины |
| Защищённая запись | Preview → точная confirmation-фраза → последовательное создание объектов |
| Без неожиданного запуска рекламы | Сервер не вызывает `resume`; созданная кампания остаётся неактивной |
## Как это работает
```mermaid
flowchart LR
U["Пользователь"] --> A["Claude Code / Codex / Hermes / ZCode"]
A <-->|"MCP over stdio"| M["yadirect-mcp"]
M <-->|"JSON API v5 / Reports API / Вордстат v4"| Y["Яндекс Директ"]
M -->|"полный TSV"| F["Локальная папка отчётов"]
M -->|"totals + preview + path"| A
```
Сервер использует локальный stdio-транспорт. MCP-клиент сам запускает Python-процесс, передаёт ему переменные окружения и завершает его вместе с сессией. Логи пишутся только в `stderr`, потому что `stdout` зарезервирован протоколом MCP.
## Инструменты MCP
### `direct_list_clients`
Возвращает логины клиентов агентства, `ClientId`, название и валюту. Метод использует `agencyclients.get` без заголовка `Client-Login`.
Параметр:
- `limit` — максимум клиентов, по умолчанию `1000`.
### `direct_campaigns`
Возвращает ID, имя, тип, состояние и статус кампаний клиента.
Параметры:
- `client_login` — логин рекламодателя;
- `include_archived` — включить архивные кампании, по умолчанию `false`.
### `direct_regions`
Справочник регионов Директа (`dictionaries.get`, словарь `GeoRegions`): поиск кода по названию и обратная проверка готовых кодов.
Параметры:
- `query` — часть названия, например `Москва`, `Ростов`, `Татарстан`; регистр и «ё» не важны;
- `ids` — коды для обратной проверки;
- `client_login` — нужен только агентскому токену: Директ требует заголовок `Client-Login` на клиентских методах;
- `limit` — сколько совпадений вернуть, от `1` до `200`.
Нужен хотя бы один из `query` / `ids`: справочник целиком инструмент не отдаёт — это тысячи записей в контекст модели. Сам справочник загружается один раз на процесс, повторные вызовы баллов не тратят.
Смысл инструмента в том, что **Директ коды регионов не проверяет**. `geo_ids: [999999]` не вызовет ошибку — Вордстат вернёт частотность не по тому региону, а неверный `RegionIds` так же молча сузит показы. Поэтому каждое совпадение приходит с путём до корня: «Москва» — это и город `213`, и «Москва и область» `1`, и без родителей их не различить. Коды, которых нет в справочнике, возвращаются отдельным списком `unknown_ids` с предупреждением.
```json
{
"query": "москва",
"matches": [
{"id": 213, "name": "Москва", "type": "City", "parent_id": 1,
"path": ["Весь мир", "Россия", "Москва и область"]},
{"id": 1, "name": "Москва и область", "type": "Region", "parent_id": 225,
"path": ["Весь мир", "Россия"]}
],
"total_matches": 2,
"truncated": false
}
```
### `direct_account_settings`
Настройки кабинета, которых нет в Reports API: корректировки ставок (`bidmodifiers.get`), условия ретаргетинга (`retargetinglists.get`) и общие наборы минус-фраз (`negativekeywordsharedsets.get`).
Параметры:
- `client_login` — логин рекламодателя;
- `sections` — какие секции читать: `bid_modifiers`, `retargeting_lists`, `negative_keyword_sets`; пусто — все три;
- `campaign_ids` — для каких кампаний смотреть корректировки; пусто — сервер сам возьмёт неархивные кампании клиента, но не более 50.
Инструмент закрывает разрыв в диагностике: отчёт покажет статистику в разрезе `Device`, `Gender`, `Age`, но не покажет выставленный коэффициент, а «нет мобильных конверсий» и «на мобильные стоит −100%» — это разные диагнозы. То же с общими минус-фразами: набор применён ко всем группам и не виден ни в одном отчёте.
Секции независимы: ошибка в одной приходит полем `error` внутри неё, остальные возвращаются как есть — нет доступа к ретаргетингу не должно означать потерю уже прочитанных корректировок. `bidmodifiers.get` принимает не более 10 кампаний за вызов, поэтому список режется на пачки автоматически. Если кампаний больше 50, ответ содержит `truncated` и `campaigns_total`, а не молча усечённую выборку. Длинные наборы минус-фраз приходят с полным `keywords_count` и первыми 50 фразами.
### `direct_ads`
Объявления вместе с посадочными страницами (`ads.get`): куда ведёт реклама, что в заголовках и текстах, размечены ли ссылки UTM.
Параметры:
- `client_login` — логин рекламодателя;
- `campaign_ids`, `ad_group_ids`, `ad_ids` — чем сузить выборку; пусто — все объявления клиента;
- `include_archived` — включить архивные, по умолчанию `false`;
- `limit` — сколько объявлений забрать за вызов, `1`–`10000`.
Ссылки объявления в Reports API нет ни в одном типе отчёта: поле `Href` существует только здесь, а запрос его в отчёте отваливается с `error_code=8000`. Без него разбор упирается в стену на самом частом вопросе — на какую страницу идёт группа и одна ли это главная на весь аккаунт.
Кроме списка объявлений инструмент возвращает `landing_pages` — сводку по уникальным URL с числом объявлений, кампаниями и разобранными UTM, — а также `domains` и счётчики `ads_without_href` и `ads_without_utm`. Динамические параметры Директа (`{campaign_id}` и прочие) остаются в сводке шаблонами: «метка есть» и «метка работает» должны различаться. Дополнения приходят фактом наличия (`sitelinks`, `vcard`, `image`), а не идентификаторами — за содержимым нужен отдельный вызов, и в каждом ответе оно не нужно.
Пустой `SelectionCriteria` метод не принимает, поэтому без явной выборки сервер сам читает кампании клиента и отправляет `CampaignIds` пачками по 10, как требует API; при более чем 50 кампаниях ответ содержит `truncated` и `campaigns_total`. Архивные отсеиваются по полю `State`, а не через критерий отбора. Запрашивается блок `TextAd`: у графических, видео и смарт-объявлений `href` придёт пустым, и это видно в `ads_without_href`, а не выглядит как «ссылок нет».
### `direct_report`
Формирует отчёт через Reports API, сохраняет TSV и возвращает путь, число строк, колонки, итоги и preview.
Основные параметры:
- `client_login` — логин рекламодателя;
- `date_from`, `date_to` — период в формате `YYYY-MM-DD`;
- `fields` — поля отчёта, например `Date`, `CampaignName`, `Impressions`, `Clicks`, `Cost`;
- `report_type` — тип отчёта, по умолчанию `CUSTOM_REPORT`;
- `goals` — ID целей Метрики;
- `attribution_models` — модели атрибуции;
- `filters` — фильтры Reports API;
- `order_by` — сортировка;
- `limit` — ограничение числа строк;
- `include_vat` — суммы с НДС или без него.
Поддерживаемые типы включают `CUSTOM_REPORT`, `ACCOUNT_PERFORMANCE_REPORT`, `CAMPAIGN_PERFORMANCE_REPORT`, `ADGROUP_PERFORMANCE_REPORT`, `AD_PERFORMANCE_REPORT`, `CRITERIA_PERFORMANCE_REPORT`, `SEARCH_QUERY_PERFORMANCE_REPORT` и `REACH_AND_FREQUENCY_PERFORMANCE_REPORT`.
Пример результата:
```json
{
"path": "D:/yadirect-reports/client1_2026-06-01_2026-06-30_r_8f3a1c9d.tsv",
"rows": 18234,
"columns": ["Date", "CampaignName", "Impressions", "Clicks", "Cost"],
"totals": {
"Impressions": 1204331,
"Clicks": 43012,
"Cost": 1250430.5,
"Ctr": 3.57,
"AvgCpc": 29.07
},
"preview": [{"Date": "2026-06-01", "CampaignName": "Поиск | Москва"}],
"preview_truncated": true,
"units": {"spent": 12, "rest": 23695, "daily": 64000}
}
```
### `direct_read_report`
Читает ранее сохранённый TSV без нового обращения к API. Доступ разрешён только внутри `YD_OUT_DIR` и только для файлов `.tsv`.
Параметры:
- `path` — абсолютный путь из ответа `direct_report`;
- `offset` — первая строка, начиная с `0`;
- `limit` — размер страницы от `1` до `1000`.
### `direct_wordstat`
Частотность Яндекс Вордстата: сколько раз за месяц искали фразу, какие запросы искали вместе с ней и какие похожие. Нужен на сборке семантики, при разборе статуса «Мало показов» и когда в отчёте надо отделить падение спроса от падения кампании.
Параметры:
- `phrases` — до 50 фраз за вызов; операторы Директа работают (`!`, кавычки, `+`);
- `geo_ids` — регионы Директа, например `[225]` — Россия, `[213]` — Москва; пусто — без ограничения по региону;
- `min_shows` — отбросить подсказки с частотностью ниже порога;
- `top` — сколько подсказок каждого вида показать в ответе, от `1` до `100`.
Полный список уходит в `YD_OUT_DIR` тем же TSV, что и отчёты, и читается через `direct_read_report`. В ответ приходит сводка по каждой фразе: частотность самой фразы, количество вложенных и похожих запросов, топ тех и других.
`client_login` не нужен — данные Вордстата общие для всех кабинетов. `Shows` означает спрос в поиске за месяц, а не прогноз показов кампании: `shows: 0` — спроса нет, `shows: null` вместе с полем `note` — Вордстат не ответил по этой фразе.
Метод живёт в устаревшем API v4, потому что аналога в v5 нет. Отсюда два следствия: в песочнице (`YD_SANDBOX`) инструмент недоступен, а баллы v4 считаются отдельно от v5 и в поле `units` не попадают. Отчёты Вордстата удаляются из очереди аккаунта сразу после выгрузки, в том числе когда вызов завершился ошибкой.
### `direct_campaign_setup`
Доступен только при `YD_MODE=campaign_setup`. Создаёт одну новую `TextCampaign`, группы, текстовые объявления и ключевые фразы.
Параметры:
- `client_login` — логин рекламодателя;
- `campaign` — объект `CampaignAddItem` без `Id`;
- `ad_groups` — группы без `CampaignId`, с локальными массивами `Ads` и `Keywords`;
- `confirmation` — точная строка из `confirmation_required` после одобрения preview.
Первый вызов всегда выполняется без `confirmation` и ничего не записывает. После проверки плана пользователь явно подтверждает операцию, и агент повторяет тот же вызов с полученной строкой.
## Ресурсы MCP: база знаний по Директу
Правил настройки кампании гораздо больше, чем помещается в инструкции сервера, а инструкции едут в каждый запрос. Поэтому сервер отдаёт базу знаний **ресурсами**, которые модель читает по требованию: в инструкциях остаётся только то, без чего ошибка происходит молча (микроединицы, обязательный автотаргетинг, порядок подтверждения).
- `direct://kb` — оглавление;
- `direct://kb/<имя>` — документ.
| Документ | О чём |
|---|---|
| `server-capabilities` | Что тулы сервера умеют и чего не делают, обход для автотаргетинга, порядок работы |
| `launch-checklist` | Чек-лист первичной настройки: вводные от клиента, структура аккаунта, кампания, группы, объявления, UTM |
| `tech-limits` | Лимиты символов и фраз, требования модерации |
| `api-contract` | Обязательные поля `Campaigns`/`AdGroups`/`Ads`/`Keywords`, микроединицы, баллы и лимиты вызовов |
| `campaign-types` | Единая перфоманс-кампания, режим совместимости API v5 |
| `strategies-budgets` | Стратегии, обучение, минимальные бюджеты, оплата за конверсии |
| `metrika-goals` | Счётчик и цели Метрики, ценность конверсии, модели атрибуции |
| `keywords-negatives` | Операторы фраз, правила минусовки, статус «Мало показов» |
| `targeting-adjustments` | Автотаргетинг, корректировки ставок, ретаргетинг |
| `optimization-playbook` | Донастройка: порядок разбора, пороги по CPA, частота проверок |
| `report-recipes` | Наборы полей `direct_report` под каждую задачу оптимизации |
Источники — официальная справка Яндекс Директа и документация API v5, материалы eLama, публичная практика агентств. Ресурсы доступны в обоих режимах, включая `report`.
## Требования
- Windows 10/11, Linux или другая ОС с Python.
- Python 3.11 или новее.
- OAuth-токен Яндекс Директа с разрешением `direct:api`.
- Доступ приложения к API Яндекс Директа.
- MCP-клиент с поддержкой локального `stdio`.
Для агентского сценария нужен токен представителя агентства. Официальные инструкции: [регистрация приложения](https://yandex.ru/dev/direct/doc/ru/register), [получение OAuth-токена](https://yandex.ru/dev/direct/doc/ru/token) и [авторизационные токены](https://yandex.ru/dev/direct/doc/ru/concepts/auth-token).
> [!CAUTION]
> OAuth-токен даёт доступ к реальным данным и действиям пользователя Яндекс Директа. Не добавляйте токен в Git, README, issue, логи или скриншоты.
## Установка на Windows
### 1. Получите исходный код
Скачайте архив из GitHub Releases или клонируйте репозиторий:
```powershell
git clone https://github.com/Lermont/yamcp.git
Set-Location yamcp
```
### 2. Создайте виртуальное окружение
```powershell
py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install .
```
Если команда `py -3.11` недоступна, проверьте установленные версии через `py -0p` или используйте `python -m venv .venv`.
### 3. Подготовьте каталоги и секрет
Для текущей PowerShell-сессии:
```powershell
$env:YD_TOKEN = "y0_your_token"
$env:YD_OUT_DIR = "D:/yadirect-reports"
$env:YD_MODE = "report"
New-Item -ItemType Directory -Force $env:YD_OUT_DIR
```
В `cmd.exe`:
```bat
set YD_TOKEN=y0_your_token
set YD_OUT_DIR=D:\yadirect-reports
set YD_MODE=report
```
Файл `.env.example` — только документированный шаблон. Приложение намеренно не загружает `.env` автоматически: переменные передаёт оболочка или MCP-клиент.
## Установка на Linux
Для Debian/Ubuntu при необходимости установите Python и модуль `venv`:
```bash
sudo apt-get update
sudo apt-get install -y python3 python3-venv git
```
Затем установите сервер в изолированное окружение:
```bash
git clone https://github.com/Lermont/yamcp.git
cd yamcp
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install .
mkdir -p "$HOME/yadirect-reports"
```
Для текущей shell-сессии:
```bash
export YD_TOKEN='y0_your_token'
export YD_OUT_DIR="$HOME/yadirect-reports"
export YD_MODE='report'
```
Для сервера или CI храните токен в секрет-хранилище, а не в репозитории. Не запускайте MCP-процесс как публичный сетевой сервис: текущая реализация рассчитана на локальный `stdio`.
## Настройка переменных окружения
| Переменная | Обязательна | По умолчанию | Назначение |
|---|---:|---|---|
| `YD_TOKEN` | Да | — | OAuth-токен с доступом к Яндекс Директ API |
| `YD_AGENCY_LOGIN` | Нет | — | Логин агентства; информационная настройка |
| `YD_ALLOWED_LOGINS` | Нет | пусто | Разрешённые клиентские логины через запятую; пусто — любые |
| `YD_OUT_DIR` | Нет | `./out` | Каталог полных TSV-отчётов |
| `YD_MAX_INFLIGHT` | Нет | `4` | Одновременные офлайн-отчёты на логин, от `1` до `5` |
| `YD_INLINE_ROWS` | Нет | `30` | Строки preview в MCP-ответе, от `0` до `1000` |
| `YD_REPORT_DEADLINE` | Нет | `600` | Максимальное ожидание отчёта в секундах |
| `YD_SANDBOX` | Нет | `false` | Использовать sandbox API Яндекс Директа |
| `YD_LANG` | Нет | `ru` | Язык ошибок API: `ru` или `en` |
| `YD_MODE` | Нет | `report` | `report` или `campaign_setup` |
| `YD_DEFAULT_WEEKLY_BUDGET` | Нет | пусто | Недельный бюджет кампании по умолчанию, в валюте кабинета; попадает в инструкции сервера |
Рекомендуемая production-конфигурация начинается с `YD_MODE=report` и непустого `YD_ALLOWED_LOGINS`.
## Подключение к Claude Code
Claude Code запускает локальные MCP-серверы по stdio. Все параметры Claude должны стоять до имени сервера, а команда запуска — после `--`.
### Windows PowerShell
```powershell
claude mcp add --scope user --transport stdio `
--env "YD_TOKEN=y0_your_token" `
--env "YD_AGENCY_LOGIN=my-agency" `
--env "YD_ALLOWED_LOGINS=client-1,client-2" `
--env "YD_OUT_DIR=D:/yadirect-reports" `
--env "YD_MODE=report" `
yandex-direct -- `
"D:/path/to/yamcp/.venv/Scripts/python.exe" -m yadirect_mcp
```
### Linux
```bash
claude mcp add --scope user --transport stdio \
--env "YD_TOKEN=$YD_TOKEN" \
--env "YD_AGENCY_LOGIN=my-agency" \
--env "YD_ALLOWED_LOGINS=client-1,client-2" \
--env "YD_OUT_DIR=$HOME/yadirect-reports" \
--env "YD_MODE=report" \
yandex-direct -- \
/absolute/path/to/yamcp/.venv/bin/python -m yadirect_mcp
```
Проверка:
```bash
claude mcp list
claude mcp get yandex-direct
```
В интерактивной сессии выполните `/mcp`. Для командных отчётов, которые могут ждать очередь API, при необходимости добавьте в `.mcp.json` поле `"timeout": 660000`.
Официальная документация: [Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp).
## Подключение к OpenAI Codex
Codex CLI, IDE extension и Codex desktop используют общую MCP-конфигурацию `config.toml`. Пользовательский файл находится в `~/.codex/config.toml`; конфигурацию одного доверенного проекта можно хранить в `.codex/config.toml`.
### Windows
```toml
[mcp_servers.yandex-direct]
command = "D:/path/to/yamcp/.venv/Scripts/python.exe"
args = ["-m", "yadirect_mcp"]
cwd = "D:/path/to/yamcp"
startup_timeout_sec = 20
tool_timeout_sec = 660
default_tools_approval_mode = "writes"
env_vars = ["YD_TOKEN"]
[mcp_servers.yandex-direct.env]
YD_AGENCY_LOGIN = "my-agency"
YD_ALLOWED_LOGINS = "client-1,client-2"
YD_OUT_DIR = "D:/yadirect-reports"
YD_MODE = "report"
YD_LANG = "ru"
```
Перед запуском Codex задайте секрет в PowerShell:
```powershell
$env:YD_TOKEN = "y0_your_token"
codex
```
### Linux
```toml
[mcp_servers.yandex-direct]
command = "/absolute/path/to/yamcp/.venv/bin/python"
args = ["-m", "yadirect_mcp"]
cwd = "/absolute/path/to/yamcp"
startup_timeout_sec = 20
tool_timeout_sec = 660
default_tools_approval_mode = "writes"
env_vars = ["YD_TOKEN"]
[mcp_servers.yandex-direct.env]
YD_AGENCY_LOGIN = "my-agency"
YD_ALLOWED_LOGINS = "client-1,client-2"
YD_OUT_DIR = "/home/user/yadirect-reports"
YD_MODE = "report"
YD_LANG = "ru"
```
Проверьте сервер командой `codex mcp list`, а активные инструменты — командой `/mcp` внутри Codex. В desktop/IDE можно также открыть **Settings → MCP servers**, добавить STDIO-сервер и перезапустить клиент.
Официальная документация: [Model Context Protocol in Codex](https://learn.chatgpt.com/docs/extend/mcp).
## Подключение к Hermes Agent
Hermes читает MCP-настройки из `~/.hermes/config.yaml`. Для stdio-серверов Hermes передаёт только явно перечисленные переменные окружения, поэтому укажите все настройки в блоке `env`.
### Linux
```yaml
mcp_servers:
yandex-direct:
command: "/absolute/path/to/yamcp/.venv/bin/python"
args: ["-m", "yadirect_mcp"]
env:
YD_TOKEN: "y0_your_token"
YD_AGENCY_LOGIN: "my-agency"
YD_ALLOWED_LOGINS: "client-1,client-2"
YD_OUT_DIR: "/home/user/yadirect-reports"
YD_MODE: "report"
YD_LANG: "ru"
timeout: 660
connect_timeout: 20
enabled: true
```
### Windows
```yaml
mcp_servers:
yandex-direct:
command: "D:/path/to/yamcp/.venv/Scripts/python.exe"
args: ["-m", "yadirect_mcp"]
env:
YD_TOKEN: "y0_your_token"
YD_OUT_DIR: "D:/yadirect-reports"
YD_MODE: "report"
timeout: 660
connect_timeout: 20
enabled: true
```
После изменения конфигурации запустите `hermes chat` или выполните `/reload-mcp` в активной сессии. Инструменты будут зарегистрированы с префиксом вида `mcp_yandex_direct_*`.
Ограничьте доступ к файлу конфигурации и не публикуйте его, если внутри находится токен. Официальная документация: [Hermes Agent — MCP](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/mcp.md).
## Подключение к ZCode
Откройте **Settings → MCP Servers → New MCP Server** и задайте:
1. Scope: `User` или `Workspace`.
2. Type: `stdio`.
3. Command: абсолютный путь к Python из `.venv`.
4. Arguments: `-m` и `yadirect_mcp` как два отдельных аргумента.
5. Environment variables: минимум `YD_TOKEN`, `YD_OUT_DIR` и `YD_MODE=report`.
В режиме **Full configuration** можно вставить JSON:
```json
{
"mcpServers": {
"yandex-direct": {
"type": "stdio",
"command": "D:/path/to/yamcp/.venv/Scripts/python.exe",
"args": ["-m", "yadirect_mcp"],
"env": {
"YD_TOKEN": "y0_your_token",
"YD_AGENCY_LOGIN": "my-agency",
"YD_ALLOWED_LOGINS": "client-1,client-2",
"YD_OUT_DIR": "D:/yadirect-reports",
"YD_MODE": "report",
"YD_LANG": "ru"
}
}
}
}
```
ZCode также умеет импортировать MCP-серверы из конфигураций Claude Code, Codex CLI, OpenCode и generic `.agents`. Официальная документация: [ZCode MCP Servers](https://zcode.z.ai/en/docs/mcp-services).
## Другие MCP-клиенты
Cursor, Windsurf, Cline, Continue, OpenCode, VS Code и другие клиенты обычно принимают JSON-конфигурацию формата `mcpServers`. Названия меню и расположение файла отличаются, но параметры процесса одинаковы:
```json
{
"mcpServers": {
"yandex-direct": {
"command": "/absolute/path/to/yamcp/.venv/bin/python",
"args": ["-m", "yadirect_mcp"],
"env": {
"YD_TOKEN": "y0_your_token",
"YD_OUT_DIR": "/absolute/path/to/yadirect-reports",
"YD_MODE": "report"
}
}
}
}
```
Универсальные правила:
- используйте абсолютный путь к Python из виртуального окружения;
- выбирайте транспорт `stdio`, не HTTP и не SSE;
- не добавляйте вывод в `stdout` между клиентом и сервером;
- передавайте токен через секреты или окружение;
- установите timeout вызова не меньше `YD_REPORT_DEADLINE + 60` секунд;
- после изменения режима перезапустите MCP-сервер, потому что набор инструментов определяется при старте.
## Первый запрос к агенту
После подключения начните с безопасной проверки:
```text
Используй yandex-direct. Покажи доступных клиентов агентства, ничего не изменяй.
```
Затем запросите отчёт:
```text
Выгрузи для client-login статистику кампаний за июнь 2026:
дата, кампания, показы, клики и расход. Суммы нужны с НДС.
Покажи итоги и 10 первых строк, полный файл не вставляй в чат.
```
Для дальнейшего чтения:
```text
Прочитай следующие 100 строк сохранённого отчёта через direct_read_report.
Не отправляй новый запрос в API.
```
Частотность для новой кампании:
```text
Собери спрос по фразам «пластиковые окна», «остекление балкона», «окна пвх»
по Москве через direct_wordstat, отсеки всё ниже 100 показов.
Покажи сводку и скажи, что стоит брать в семантику, а что нет.
```
## Создание кампании: безопасный сценарий
1. Остановите активный MCP-процесс.
2. Установите `YD_MODE=campaign_setup`.
3. Желательно задайте один или несколько логинов в `YD_ALLOWED_LOGINS`.
4. Перезапустите MCP-клиент и убедитесь, что появился `direct_campaign_setup`.
5. Попросите агента собрать недостающие данные и сформировать preview.
6. Проверьте бюджет, стратегию, регионы, даты, ссылки, тексты, ключевые фразы и минус-слова.
7. Явно подтвердите создание только после проверки.
8. После ответа проверьте `status`, созданные ID, warnings и errors.
9. Проверьте кампанию в интерфейсе Яндекс Директа. Сервер не запускает показы.
Пример безопасного запроса:
```text
Подготовь новую текстово-графическую кампанию для client-login.
Сначала задай вопросы о цели, географии, бюджете, сроках, стратегии,
счётчиках и целях Метрики, семантике, минус-словах и объявлениях.
Затем вызови direct_campaign_setup без confirmation и покажи полный preview.
Ничего не создавай без моего отдельного подтверждения.
```
Денежные поля JSON API при создании передаются в микроединицах: сумма в валюте × `1_000_000`. Входные поля используют официальный регистр API: `Name`, `StartDate`, `TextCampaign`, `RegionIds`, `TextAd`, `Keyword` и т. д.
Операция API не атомарна. Если дочерний этап завершился ошибкой, ответ сохраняет уже созданные ID. Не повторяйте весь запрос вслепую: это может создать дубликат кампании.
## Технические решения
### Стабильный `ReportName`
Имя отчёта — хеш спецификации. Оно остаётся одинаковым между попытками polling, иначе каждый повтор мог бы создать новый офлайн-отчёт. Разные поля и фильтры получают разные имена.
### Корректное ожидание Reports API
Сервер различает:
- `200` — отчёт готов;
- `201` — отчёт поставлен в очередь;
- `202` — отчёт ещё формируется;
- `400` — ошибка параметров или лимитов;
- `500` — ошибка сервера Яндекс Директа.
Для `201` и `202` сервер читает `retryIn`, повторяет идентичный запрос и контролирует общий deadline. Лимиты Reports API описаны в [официальной документации](https://yandex.ru/dev/direct/doc/ru/restrictions): одновременно в очереди может быть не больше пяти офлайн-отчётов на пользователя.
### Экономия контекста модели
Полный TSV не возвращается в MCP-ответе. `direct_report` отдаёт:
- абсолютный путь к файлу;
- количество строк и названия колонок;
- пересчитанные totals;
- ограниченный preview;
- информацию о баллах API.
Остальные строки читаются через `direct_read_report` без API-вызова.
## Ограничения
- Проект не является официальным продуктом Яндекса.
- Нет Яндекс Метрики: токен Директа к её API доступа не даёт, нужен отдельный с правом `metrika:read`. Конверсии по целям при этом доступны — их отдаёт `direct_report` по параметру `goals`.
- Вордстат работает через устаревший API v4 (в v5 аналога нет) и недоступен в песочнице.
- Нет пакетной выгрузки сразу по всем логинам.
- Не создаются ЕПК, медийные и мобильные кампании.
- Не редактируются и не удаляются существующие объекты: корректировки ставок и условия ретаргетинга читаются, но не задаются.
- Правила отбора условий ретаргетинга (`Rules`) не возвращаются — только состав списка, его тип и доступность.
- Не выполняются `resume`, автоматический запуск показов и rollback.
- Сервер предоставляет локальный stdio-транспорт, а не удалённый HTTP endpoint.
## Диагностика
### MCP-клиент не видит сервер
1. Убедитесь, что путь в `command` абсолютный и файл существует.
2. Выполните `"<python>" -c "import yadirect_mcp; print('ok')"` в той же среде.
3. Проверьте наличие `YD_TOKEN` именно в окружении MCP-процесса.
4. Проверьте, что аргументы переданы как `-m`, `yadirect_mcp`.
5. Перезапустите клиент после изменения конфигурации.
### `YD_TOKEN не задан`
Сервер не получил токен. `.env` автоматически не читается. Добавьте `YD_TOKEN` в `env` конфигурации MCP или экспортируйте переменную до запуска клиента.
### Отчёт завершается по timeout клиента
Увеличьте timeout инструмента. Рекомендуемое значение — `YD_REPORT_DEADLINE + 60` секунд. Для стандартного deadline `600` используйте `660` секунд или `660000` миллисекунд — в зависимости от формата клиента.
### Логин заблокирован
Если ответ содержит `Логин ... не разрешён`, добавьте точный логин в `YD_ALLOWED_LOGINS` через запятую или исправьте опечатку. Для production не рекомендуется отключать whitelist без необходимости.
### Ошибка Яндекс Директа
Ответ инструмента содержит `error`, а для `DirectError` также `error_code` и `request_id`. Сохраните `request_id` для обращения в поддержку и проверьте совместимость выбранных полей, типа отчёта и фильтров.
## Разработка
Установите dev-зависимости:
```bash
python -m venv .venv
python -m pip install -e ".[dev]"
```
Запустите проверки:
```bash
python -m ruff check .
python -m pytest -q
python -m build
python -m twine check dist/*
```
Тесты покрывают polling `201 → 202 → 200`, стабильность `ReportName`, заголовки API, обработку `400`, пересчёт итогов, whitelist, проверку конфигурации, регистрацию read/write-инструментов по режиму, безопасный preview, валидацию родительских ID, передачу созданных ID и частичные ошибки. Для Вордстата отдельно проверяются транспорт v4 (токен в теле, ошибка с `HTTP 200`), разбиение длинного списка фраз на отчёты, удаление отчётов из очереди даже после сбоя и различение нулевого спроса от отсутствующего ответа. Для справочника регионов — ранжирование совпадений, нормализация «ё», путь до корня при битой и зацикленной ссылке на родителя, явный список неизвестных кодов и однократная загрузка словаря. Для настроек кабинета — разбиение кампаний на пачки по 10, изоляция упавшей секции, сохранность значения при неизвестном типе корректировки и видимость усечения выборки.
Правила участия описаны в [CONTRIBUTING.md](CONTRIBUTING.md), выпуск версии — в [RELEASING.md](RELEASING.md), политика безопасности — в [SECURITY.md](SECURITY.md).
## Roadmap
- [ ] Яндекс Метрика: выгрузка на диск плюс компактная сводка.
- [ ] Переезд Вордстата с устаревшего API v4 на Yandex Cloud Search API.
- [ ] `direct_report_batch` для нескольких логинов с общим контролем очереди.
- [ ] Дисковый кеш закрытых периодов с TTL по дате.
- [ ] Экспорт Parquet для BI и аналитических пайплайнов.
- [ ] Опциональный удалённый Streamable HTTP transport с отдельной аутентификацией.
## Лицензия
Проект распространяется по лицензии [MIT](LICENSE).
Названия Яндекс, Яндекс Директ, Claude, Codex, Hermes и ZCode принадлежат соответствующим правообладателям. Этот независимый проект не аффилирован с Яндексом, Anthropic, OpenAI, Nous Research или Zhipu AI.
---
**Ключевые слова:** Яндекс Директ MCP, Yandex Direct MCP server, API Яндекс Директа, Claude Code MCP, OpenAI Codex MCP, Hermes Agent MCP, ZCode MCP, AI-агент для контекстной рекламы, автоматизация PPC, отчёты Яндекс Директ, управление рекламными кампаниями.
TDQS
Scored across 8 tools
Each tool targets a distinct resource or stage: clients, campaigns, wordstat, regions, account settings, ads, report export, and report reading. report and read_report are clearly separated as fetch vs read saved output, so there is no real overlap.
All tools share the direct_ prefix and use snake_case, making the family identifiable. Most are direct_<noun> (direct_campaigns, direct_ads), while direct_list_clients and direct_read_report use verb_noun, a minor but visible deviation.
Eight tools is a well-scoped count for a Yandex Direct analysis/read-only API surface. Each tool addresses a distinct need without redundancy or bloat.
The set covers the main read/analysis workflows: client selection, campaign/ads/settings inspection, wordstat and region lookups, plus report generation and paginated reading. Minor gaps exist—no goal-list retrieval or management operations—but the core analytical workflow is not dead-ended.