mcpField
Я
Яндекс Директ API v5

Яндекс Директ API v5

本地服务
github.com商业与营销17 周前更新

关于 Яндекс Директ API v5

Яндекс Директ API v5 是面向 Яндекс Директ 的 MCP 服务和命令行工具,覆盖由机器可读规范生成的 113 个方法。它默认仅开放读取工具,并通过精确处理长整数、金额单位和响应错误等机制减少数据误读。

主要功能

  1. 01覆盖 113 个 API 方法
  2. 02默认仅开放读取工具
  3. 03写入操作需显式启用
  4. 04保持长整数标识符精度
  5. 05换算金额微单位并标注字段
  6. 06提供目录、字段、模式和账户清单工具

适用场景

  1. 01查询广告系列、广告和关键词
  2. 02获取报告并等待报告生成
  3. 03核对账户库存及 API 返回情况
  4. 04按需启用广告数据写入操作

MCP 相关

可作为 MCP 服务连接 Claude Code、Cursor、Codex 等客户端,并按配置公开 API 工具。工具集支持按配置文件或显式列表筛选;写入工具默认不公开,需设置 DIRECT_ALLOW_WRITES=1。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"artgas1-yandex-direct-api": {
"command": "npx",
"args": [
"-y",
"yandex-direct-api-mcp"
],
"env": {
"YANDEX_DIRECT_TOKEN": "<YANDEX_DIRECT_TOKEN>",
"YANDEX_DIRECT_LOGIN": "<YANDEX_DIRECT_LOGIN>",
"DIRECT_PROFILE": "<DIRECT_PROFILE>",
"DIRECT_TOOLS": "<DIRECT_TOOLS>",
"DIRECT_ALLOW_WRITES": "<DIRECT_ALLOW_WRITES>",
"DIRECT_API_VERSION": "<DIRECT_API_VERSION>",
"DIRECT_SANDBOX": "<DIRECT_SANDBOX>",
"DIRECT_MAX_OUTPUT_CHARS": "<DIRECT_MAX_OUTPUT_CHARS>"
}
}
}
}
启动命令npx -y yandex-direct-api-mcp
需要配置的环境变量
YANDEX_DIRECT_TOKEN密钥OAuth-токен Яндекса со scope direct:api (https://oauth.yandex.ru/)
YANDEX_DIRECT_LOGINЛогин кабинета для заголовка Client-Login. Нужен агентствам и представителям; для собственного кабинета не задаётся
DIRECT_PROFILEНабор объявляемых инструментов: core — узкий набор по умолчанию, read — все читающие, all — вся поверхность
DIRECT_TOOLSЯвный список инструментов или служб через запятую. Побеждает DIRECT_PROFILE
DIRECT_ALLOW_WRITESРазрешить изменяющие методы (add/update/delete). Пока выключено, они не объявляются вовсе. Значения: 1, true, yes
DIRECT_API_VERSIONВерсия пути API. Разные версии отдают разные наборы полей одной и той же кампании
DIRECT_SANDBOXОтправлять запросы в песочницу Директа вместо боевого кабинета. Значения: 1, true, yes
DIRECT_MAX_OUTPUT_CHARSПотолок размера ответа инструмента в символах; сверх него ответ усекается с пометкой

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmyandex-direct-api-mcp1.1.1

工具

13

收录的工具列表 · 更新于 2 周前

参数类型必填说明
Pageobject否LimitOffset 对象:Limit、Offset(确切架构:type=LimitOffset 的 direct_schema)
FieldNamesarray是12 个值(Id、CampaignId、Status、Name、…)—完整列表:direct_fields
SelectionCriteriaobject是对象 AdGroupsSelectionCriteria:CampaignIds、Ids、Types、Statuses、TagIds、Tags、AppIconStatuses、ServingStatuses、NegativeKeywordSharedSetIds(准确架构:type=AdGroupsSelectionCriteria 的 direct_schema)
SmartAdGroupFieldNamesarray否以下之一:FeedId、AdTitleSource、AdBodySource
UnifiedAdGroupFieldNamesarray否以下之一:OfferRetargeting
MobileAppAdGroupFieldNamesarray否以下之一:StoreUrl、TargetDeviceType、TargetCarrier、TargetOperatingSystemVersion、AppIconModeration、AppAvailabilityStatus、AppOperatingSystemType
DynamicTextAdGroupFieldNamesarray否以下之一:AutotargetingCategories、AutotargetingSettings、DomainUrl、DomainUrlProcessingStatus
TextAdGroupFeedParamsFieldNamesarray否以下之一:FeedId、FeedCategoryIds
DynamicTextFeedAdGroupFieldNamesarray否以下之一:AutotargetingCategories、AutotargetingSettings、Source、FeedId、SourceType、SourceProcessingStatus
AutotargetingSettingsCategoriesFieldNamesarray否以下之一:Exact、Narrow、Alternative、Accessory、Broader
AutotargetingSettingsBrandOptionsFieldNamesarray否以下之一:WithoutBrands、WithAdvertiserBrand、WithCompetitorsBrand

详细介绍

yandex-direct-mcp

MCP 服务和命令行工具,适用于 Яндекс Директа v5 API。覆盖全部 113 个方法, 这些方法由机器可读的架构生成;默认声明其中九个,即用于读取数据的方法。其余方法可通过一个变量启用,修改功能默认关闭。

mcp-name: io.github.artgas1/yandex-direct-api-mcp

npm CI License: MIT

English

既可作为 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)。

npx -y yandex-direct-api-mcp

覆盖范围

覆盖内容服务数方法数其中属于 core工具示例
广告系列和广告9373direct_adgroups_get、direct_ads_get
定向9451direct_keywords_get
出价和策略4152direct_bidmodifiers_get、direct_keywordbids_get
报告和字典692direct_dictionaries_get、direct_reports_get
客户和代理商271direct_clients_get
总计301139另有四个辅助工具:direct_catalog、direct_fields、direct_schema、direct_inventory

此表根据规范自动生成(npm run coverage),而不是手动填写:文档中的数字可能会在不知不觉中与架构不一致,让错误看起来和事实一模一样。

快速开始

需要带有 direct:api scope 的 Яндекс OAuth 令牌——https://oauth.yandex.ru/ (应用必须已获批访问 Директа API)。

MCP:

{
  "mcpServers": {
    "yandex-direct": {
      "command": "npx",
      "args": ["-y", "yandex-direct-api-mcp"],
      "env": { "YANDEX_DIRECT_TOKEN": "ваш-токен" }
    }
  }
}

命令行:

export YANDEX_DIRECT_TOKEN="ваш-токен"

yandex-direct-mcp catalog --service campaigns
yandex-direct-mcp describe campaigns.get
yandex-direct-mcp call campaigns.get --FieldNames Id --FieldNames Name

此服务器会帮你处理的问题

这些并非便利功能。每一项都是直接请求 Директа 时可能悄无声息出错的地方:响应看起来正常,没有错误,但数值或结果却不正确。 以下内容均通过实际 API 运行验证,而非从文档中推测。

金额始终会被放大一百万倍
DailyBudget.Amount = 1000000000     ← это 1000 единиц валюты счёта
Cost               = 1234500000     ← это 1234,50 единицы валюты счёта

错误正好是一百万倍,而且看起来不像错误:数值合情合理,可以对它求和、相除,还可以据此绘制图表。用于关闭报表中微单位的 returnMoneyInMicros 标头,对普通服务不起作用——已在 campaigns 上验证,数值没有变化。

服务器会将金额转换为账户货币,并在响应中列出具体转换过的字段:

"_мета": { "суммы_переведены_из_микроединиц": ["Amount", "Refund", "Spend"] }
Идентификаторы объявлений не помещаются в число JavaScript

Типичный Id объявления: 1234567890123456789 — девятнадцать цифр. JSON.parse держит пятнадцать и превращает его в 1234567890123456800.

И это не единичный курьёз: девятнадцатизначные идентификаторы встретились в каждом проверенном кабинете, а не в одном экземпляре. Схема Яндекса объявляет 358 полей типом xsd:long — то есть диапазон до 19 цифр нормален по контракту.

Опасен не сдвиг, а то, как он выходит наружу: испорченный идентификатор Директ принимает и отвечает HTTP 200 с телом {"result":{}}. То есть отказа нет — есть сообщение «такого объявления нет». Пустота как доказательство отсутствия.

Сервер разбирает тело так, что длинные целые остаются точными. Отдельно проверено, что API принимает идентификатор строкой, поэтому точность держится на всём пути — и на чтении, и на записи.

Успех определяется телом, а не кодом ответа
что спросиликодчто в теле
неверный FieldNames200error_code: 8000
неизвестный метод202error_code: 55
ошибка в отчёте400error_code: "8000" — строкой, не числом
отчёт поставлен в очередь201пусто, retryIn: 1
отчёт считается202пусто, retryIn: 10

Один и тот же код 202 означает отказ у campaigns и «ещё считается» у reports. Проверка res.ok пропускает первые три строки таблицы: отказ уходит модели как удачный ответ.

Отчёт приходит не сразу

201 → 202 → 200. Замер: до готовности потребовалось три запроса. Повтор идёт с тем же ReportName — имя и есть ключ поставленной задачи. Сервер ждёт сам.

Версия пути меняет данные

Один и тот же запрос:

/json/v5/campaigns    → N кампаний, у всех Type = TEXT_CAMPAIGN
/json/v501/campaigns  → те же N,     у всех Type = UNIFIED_CAMPAIGN

Это разные представления с разными наборами глубоких полей, и несовпадение отнимает их без всякого признака:

путьнабор полейглубокие поля
v5TextCampaignFieldNamesприходят
v5UnifiedCampaignFieldNamesпусто, ошибки нет
v501TextCampaignFieldNamesпусто, ошибки нет
v501UnifiedCampaignFieldNamesприходят

Стратегия, настройки, счётчики просто отсутствуют — читается как «у кампании ничего не настроено». Умолчание v501 (документация называет адресом только его), переключается DIRECT_API_VERSION=v5, выбранная версия печатается в каждом ответе, а несовпадающий набор полей вызывает предупреждение.

Список кампаний неполон

Кампании Мастера кампаний не отдаются методом campaigns.get вовсе — ни списком, ни по явному Ids; ответ пустой и без ошибки. Ни v5, ни v501 этого не меняют.

Поэтому состав кабинета собирает отдельный инструмент direct_inventory: он склеивает список кампаний и отчёт и помечает каждую строку источником. Предупреждения в описании тут мало — оно требует, чтобы читатель помнил про него в момент вывода, а вывод делается по данным, которые выглядят нормально.

Прогон на живом кабинете: объединение оказалось на кампанию длиннее списка, и эта строка была видна только отчёту. Невидимая для campaigns.get кампания при этом откручивается и может нести основную долю показов — по списку кампаний этого не заметить.

ВНИМАНИЕ: 1 кампаний откручивались, но методом campaigns.get НЕ отдаются
          (10000017). Управлять ими через API нельзя — только в интерфейсе.
Предупреждение — это применено, а не отклонено

В ответе на add/update каждому входному элементу отвечает выходной. Различать надо по Errors; Warnings означает «применено с замечанием». Счёт по наличию любого содержимого даёт «отклонено всё» там, где применилось всё. Сервер приводит итог отдельной строкой:

UpdateResults: применено 2, отклонено 1, с предупреждениями 1
Форму списка задаёт тип, а не направление
RegionIds            (maxOccurs=unbounded) → [225, 977]
RestrictedRegionIds  (тип ArrayOfLong)     → {"Items": [225]}

Обе формы одинаковы и на чтении, и на записи. Сервер снимает и ставит обёртку по графу типов, а не по виду значения, поэтому круг «прочитал → поправил → записал» не рвётся. Вам обе формы видны как обычные массивы.

Кабинет называется в каждом ответе

Client-Login переключает кабинет по-настоящему, и ошибиться в нём можно молча. Несуществующий логин отбивается кодом 8800 — это видно сразу. А существующий, но не тот, отдаёт полные и правильные данные, просто из другого кабинета: по виду ответа это неотличимо.

Поэтому сервер спрашивает у API, кто отвечает, и пишет ответ в каждый конверт:

"_мета": { "кабинет": "example-login (ClientId 1234567)", "версия_api": "v501" }

Спрашивается один раз за запуск и кешируется — clients.get стоит 10 баллов.

Поверхность

Описания всех объявленных инструментов лежат в контексте модели на каждом ходу, вызываете вы их или нет. Поэтому по умолчанию объявляется не всё, что умеет API, а то, чем пользуются.

Список всех 113 методов API Директа: девять оставлены и выделены, 104 вычеркнуты. Манифест по умолчанию — 27 028 байт против 143 706 у полного каталога.

Замер tools/list на собранном сервере (npm run surface):

профильинструментовбайт≈ токенов
core (умолчание)1327 02812 455
read3761 15828 183
all + DIRECT_ALLOW_WRITES=1117143 70666 224

Умолчание в 5,3 раза легче полного набора. Главный рычаг — вложенные типы не разворачиваются в схему: транзитивно campaigns.add это 1083 поля и 54 КБ на один инструмент. Вместо разворачивания состав типа назван словами в описании, а точная схема выдаётся инструментом direct_schema по запросу.

Чего не видно — расскажет сам сервер: инструмент direct_catalog перечисляет все 113 методов и говорит, какие скрыты и как их включить.

Изменение выключено по умолчанию

Из 113 методов 80 меняют данные, 16 удаляют. У Директа нет подтверждающего шага: suspend останавливает показы в момент вызова, archive убирает кампанию из работы, delete необратим, а на другом конце — деньги.

Меняющие инструменты не объявляются вовсе, пока не задан DIRECT_ALLOW_WRITES=1. Объявлять их и отказывать на вызове — худший вариант: контекст за них платится полностью, а позвать всё равно нельзя.

Неизвестное имя профиля — отказ на старте, а не откат к полной поверхности: неверная настройка ограничения не должна превращаться в отсутствие ограничения.

Есть песочница: DIRECT_SANDBOX=1 (нужны отдельная регистрация и отдельный токен). Факт включения печатается при старте и в каждом ответе.

Настройки

переменнаяпо умолчаниючто делает
YANDEX_DIRECT_TOKEN—OAuth-токен, scope direct:api. Обязательна
YANDEX_DIRECT_LOGIN—логин кабинета (не почта). Переключает кабинет по-настоящему: под одним токеном отдаёт другой аккаунт со своей квотой. Фактический кабинет сервер называет в каждом ответе
DIRECT_PROFILEcorecore, read, all
DIRECT_TOOLS—явный список служб или инструментов, побеждает профиль
DIRECT_ALLOW_WRITESвыкл.объявить меняющие данные инструменты
DIRECT_API_VERSIONv501v501 или v5 — меняет представление кампаний
DIRECT_SANDBOXвыкл.песочница вместо боевого кабинета
DIRECT_MAX_OUTPUT_CHARS60000потолок ответа; усечение называется вслух

Откуда берутся инструменты

Ни один метод не описан руками.

источникчто даётпочему нужен
WSDL 29 служб + 3 общие XSDсостав, типы, обязательность, массивность, перечисленияединственный полный: в индексе документации нет vcards, smartadtargets, dynamictextadtargets, dynamicfeedadtargets
страницы документациичеловекочитаемые описанияв WSDL нет ни одного xs:documentation
описано явнослужба reportsWSDL для неё Директ не отдаёт (404)

Итог: 30 служб, 113 методов, 609 типов, 240 перечислений.

npm run spec:fetch    # скачать WSDL и документацию в .cache/
npm run spec:build    # собрать spec/direct-api.json

⚠️ Перечисления из схемы отстают от живого API и поэтому не становятся жёстким фильтром, а идут подсказкой в описание. Сверка с живым API: campaigns принимает CreateTime, keywords — AutotargetingBrief, AutotargetingBriefSuggests, AutotargetingMode, которых в схеме нет. Фильтр по отстающему списку запретил бы то, что API умеет, и отказ выглядел бы как отсутствие возможности. Право решать остаётся за API.

Проверки

npm test         # 70 тестов, включая отрицательные контроли
npm run surface  # замер поверхности по профилям
npm run coverage # таблица покрытия для README
npm run graphic  # пересобрать графику поверхности (SVG и GIF)
npm run smoke    # прогон собранного сервера против живого API (нужен токен)

Тесты содержат отрицательные контроли на каждый инвариант — то есть могут упасть на том дефекте, ради которого написаны: на порче идентификатора, на ошибке с кодом 202, на пустой схеме get, на пропаже службы и на чтении предупреждений как отказов.

Скилл — работа без MCP

Для агентов, которым MCP не нужен или недоступен:

npx skills add artgas1/yandex-direct-mcp

Ставит один канонический экземпляр в .agents/skills/yandex-direct/ и связывает его с каталогами агентов. Скилл — тонкая надстройка над той же командой: своей логики у него нет, поэтому расходиться с сервером ему нечем.

Если выбираете между серверами

Серверов к Директу написано много. Полезные вопросы к любому из них — те же, что перечислены выше: приводит ли суммы из микро-единиц; переживают ли девятнадцатизначные идентификаторы разбор; считается ли HTTP 200 с телом error успехом; ждёт ли он отчёт после 201; отличает ли Warnings от Errors; что делает при опечатке в имени профиля. Ответы стоят одного вызова.

Лицензия

MIT.

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。