
Яндекс Директ API v5
io.github.artgas1Published by GitHub account artgas1v1.1.1Updated Oct 24, 2026
MCP server for Yandex Direct API v5: 113 methods from the machine-readable schema
Overview
MCP server and CLI for Yandex Direct API v5, exposing 113 schema-generated methods so an assistant can read and, if enabled, change ad campaigns.
- What you can do
- Read campaigns, ad groups, ads, keywords and targeting settings
- Read bids, bid modifiers and strategies
- Run reports and fetch dictionaries and reference data
- List clients and agency accounts, plus catalog, field and schema helpers
- Build a full account inventory by combining campaign lists with reports
- Optionally add, update, suspend, archive or delete objects when writes are enabled
- When to use it
- Useful when an assistant needs to inspect or manage Yandex Direct advertising accounts: campaign structure, targeting, bids, reports and agency clients. It is aimed at people who want the API's silent pitfalls (micro-unit amounts, long IDs, error bodies with HTTP 200, delayed reports) handled rather than raw responses.
- Requirements
- Runs locally via npx (Node.js). Requires a Yandex OAuth token with the direct:api scope in YANDEX_DIRECT_TOKEN, and an approved application for Direct API access. Optional settings: YANDEX_DIRECT_LOGIN for agency accounts, DIRECT_PROFILE, DIRECT_TOOLS, DIRECT_API_VERSION, DIRECT_SANDBOX, DIRECT_ALLOW_WRITES, DIRECT_MAX_OUTPUT_CHARS. Network access to the Yandex Direct API.
Installation
In SourceWeft
- Open Яндекс Директ API v5 in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
yandex-direct-mcp
MCP-сервер и командная строка к API Яндекс Директа v5. Покрыты все 113 методов, порождённые из машиночитаемой схемы; по умолчанию объявляются девять — те, которыми читают. Остальное включается одной переменной, изменение выключено.
mcp-name: io.github.artgas1/yandex-direct-api-mcp
Работает и как MCP-сервер для Claude Code, Cursor, Codex и других клиентов, и как обычная команда — если MCP не нужен.
Что это даёт — за пять секунд
[Запись прогона в терминале: вызов direct_campaigns_get и две колонки — слева тело ответа, разобранное обычным JSON.parse, справа то же самое после сервера. Бюджет 1000000000 против 1000, идентификатор объявления, испорченный разбором, против точного, обёртка Items против обычного списка и отказ с кодом HTTP 202, распознанный как отказ.]Обе колонки настоящие: левая — тело ответа, разобранное обычным JSON.parse,
то есть так, как его получил бы любой клиент; правая — то, что вернул сервер по JSON-RPC.
Строка с идентификатором самодоказательна: слева он испорчен не потому, что так нарисовано,
а потому что его действительно портит разбор. Ни токена, ни сети: запросы уводятся на локальную
заглушку, поэтому прогон повторяется где угодно, включая CI. Повторить у себя — npm run demo, переснять — npm run demo:record
(нужен vhs).
Покрытие
Таблица считается из спеки (npm run coverage), а не пишется руками: числа в
прозе расходятся со схемой молча, и неправда выглядит ровно как правда.
Быстрый старт
Нужен OAuth-токен Яндекса со scope direct:api — https://oauth.yandex.ru/
(приложению требуется одобренная заявка на доступ к API Директа).
MCP:
Командная строка:
Что этот сервер делает за вас
Не удобства. Каждый пункт — место, где прямой запрос к Директу ошибается молча: ответ выглядит нормальным, ошибки нет, а число или вывод неверны. Всё перечисленное снято прогоном живого API, а не прочитано в документации.
Суммы приходят умноженными на миллион — всегда
Ошибка ровно в миллион раз, и она не выглядит ошибкой: число правдоподобное,
его можно сложить, поделить и построить по нему график. Заголовок
returnMoneyInMicros, который выключает микро-единицы в отчётах, на обычные
службы не действует — проверено на campaigns, значение не изменилось.
Сервер приводит суммы к валюте счёта и перечисляет в ответе, какие именно поля пересчитал:
Идентификаторы объявлений не помещаются в число JavaScript
Типичный Id объявления: 1234567890123456789 — девятнадцать цифр.
JSON.parse держит пятнадцать и превращает его в 1234567890123456800.
И это не единичный курьёз: девятнадцатизначные идентификаторы встретились в
каждом проверенном кабинете, а не в одном экземпляре. Схема Яндекса объявляет
358 полей типом xsd:long — то есть диапазон до 19 цифр нормален по контракту.
Опасен не сдвиг, а то, как он выходит наружу: испорченный идентификатор Директ
принимает и отвечает HTTP 200 с телом {"result":{}}. То есть отказа нет —
есть сообщение «такого объявления нет». Пустота как доказательство отсутствия.
Сервер разбирает тело так, что длинные целые остаются точными. Отдельно проверено, что API принимает идентификатор строкой, поэтому точность держится на всём пути — и на чтении, и на записи.
Успех определяется телом, а не кодом ответа
Один и тот же код 202 означает отказ у campaigns и «ещё считается» у
reports. Проверка res.ok пропускает первые три строки таблицы: отказ уходит
модели как удачный ответ.
Отчёт приходит не сразу
201 → 202 → 200. Замер: до готовности потребовалось три запроса. Повтор идёт с тем же
ReportName — имя и есть ключ поставленной задачи. Сервер ждёт сам.
Версия пути меняет данные
Один и тот же запрос:
Это разные представления с разными наборами глубоких полей, и несовпадение отнимает их без всякого признака:
Стратегия, настройки, счётчики просто отсутствуют — читается как «у кампании
ничего не настроено». Умолчание v501 (документация называет адресом только
его), переключается DIRECT_API_VERSION=v5, выбранная версия печатается в
каждом ответе, а несовпадающий набор полей вызывает предупреждение.
Список кампаний неполон
Кампании Мастера кампаний не отдаются методом campaigns.get вовсе — ни
списком, ни по явному Ids; ответ пустой и без ошибки. Ни v5, ни v501 этого
не меняют.
Поэтому состав кабинета собирает отдельный инструмент direct_inventory:
он склеивает список кампаний и отчёт и помечает каждую строку источником.
Предупреждения в описании тут мало — оно требует, чтобы читатель помнил про него
в момент вывода, а вывод делается по данным, которые выглядят нормально.
Прогон на живом кабинете: объединение оказалось на кампанию длиннее списка, и
эта строка была видна только отчёту. Невидимая для campaigns.get кампания при
этом откручивается и может нести основную долю показов — по списку кампаний
этого не заметить.
Предупреждение — это применено, а не отклонено
В ответе на add/update каждому входному элементу отвечает выходной.
Различать надо по Errors; Warnings означает «применено с замечанием».
Счёт по наличию любого содержимого даёт «отклонено всё» там, где применилось
всё. Сервер приводит итог отдельной строкой:
Форму списка задаёт тип, а не направление
Обе формы одинаковы и на чтении, и на записи. Сервер снимает и ставит обёртку по графу типов, а не по виду значения, поэтому круг «прочитал → поправил → записал» не рвётся. Вам обе формы видны как обычные массивы.
Кабинет называется в каждом ответе
Client-Login переключает кабинет по-настоящему, и ошибиться в нём можно молча.
Несуществующий логин отбивается кодом 8800 — это видно сразу. А существующий,
но не тот, отдаёт полные и правильные данные, просто из другого кабинета:
по виду ответа это неотличимо.
Поэтому сервер спрашивает у API, кто отвечает, и пишет ответ в каждый конверт:
Спрашивается один раз за запуск и кешируется — clients.get стоит 10 баллов.
Поверхность
Описания всех объявленных инструментов лежат в контексте модели на каждом ходу, вызываете вы их или нет. Поэтому по умолчанию объявляется не всё, что умеет API, а то, чем пользуются.
[Список всех 113 методов API Директа: девять оставлены и выделены, 104 вычеркнуты. Манифест по умолчанию — 27 028 байт против 143 706 у полного каталога.]Замер tools/list на собранном сервере (npm run surface):
Умолчание в 5,3 раза легче полного набора. Главный рычаг — вложенные типы не
разворачиваются в схему: транзитивно campaigns.add это 1083 поля и 54 КБ на
один инструмент. Вместо разворачивания состав типа назван словами в описании,
а точная схема выдаётся инструментом direct_schema по запросу.
Чего не видно — расскажет сам сервер: инструмент direct_catalog перечисляет
все 113 методов и говорит, какие скрыты и как их включить.
Изменение выключено по умолчанию
Из 113 методов 80 меняют данные, 16 удаляют. У Директа нет подтверждающего
шага: suspend останавливает показы в момент вызова, archive убирает кампанию
из работы, delete необратим, а на другом конце — деньги.
Меняющие инструменты не объявляются вовсе, пока не задан
DIRECT_ALLOW_WRITES=1. Объявлять их и отказывать на вызове — худший вариант:
контекст за них платится полностью, а позвать всё равно нельзя.
Неизвестное имя профиля — отказ на старте, а не откат к полной поверхности: неверная настройка ограничения не должна превращаться в отсутствие ограничения.
Есть песочница: DIRECT_SANDBOX=1 (нужны отдельная регистрация и отдельный
токен). Факт включения печатается при старте и в каждом ответе.
Настройки
Откуда берутся инструменты
Ни один метод не описан руками.
Итог: 30 служб, 113 методов, 609 типов, 240 перечислений.
⚠️ Перечисления из схемы отстают от живого API и поэтому не становятся
жёстким фильтром, а идут подсказкой в описание. Сверка с живым API: campaigns
принимает CreateTime, keywords — AutotargetingBrief,
AutotargetingBriefSuggests, AutotargetingMode, которых в схеме нет. Фильтр
по отстающему списку запретил бы то, что API умеет, и отказ выглядел бы как
отсутствие возможности. Право решать остаётся за API.
Проверки
Тесты содержат отрицательные контроли на каждый инвариант — то есть могут
упасть на том дефекте, ради которого написаны: на порче идентификатора, на
ошибке с кодом 202, на пустой схеме get, на пропаже службы и на чтении
предупреждений как отказов.
Скилл — работа без MCP
Для агентов, которым MCP не нужен или недоступен:
Ставит один канонический экземпляр в .agents/skills/yandex-direct/ и
связывает его с каталогами агентов. Скилл — тонкая надстройка над той же
командой: своей логики у него нет, поэтому расходиться с сервером ему нечем.
Если выбираете между серверами
Серверов к Директу написано много. Полезные вопросы к любому из них — те же,
что перечислены выше: приводит ли суммы из микро-единиц; переживают ли
девятнадцатизначные идентификаторы разбор; считается ли HTTP 200 с телом
error успехом; ждёт ли он отчёт после 201; отличает ли Warnings от
Errors; что делает при опечатке в имени профиля. Ответы стоят одного вызова.
Лицензия
MIT.
Source: README.md at commit 086ec45
Tools
0Version history
1- v1.1.1LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts