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

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

ローカル
github.comビジネス・マーケティング17 週間前に更新

Яндекс Директ API v5 について

Яндекс Директ API v5は、Яндекс Директ向けのMCPサーバー兼CLIで、機械可読スキーマから生成した113のメソッドを扱います。読み取りツールのみを標準で公開し、大きな整数の精度や金額単位、APIエラーの処理に対応しています。

主な機能

  1. 01113のAPIメソッドをカバー
  2. 02読み取りツールを標準で公開
  3. 03書き込みには明示的な有効化が必要
  4. 04大きな整数IDの精度を保持
  5. 05金額のマイクロ単位を換算し対象フィールドを明示
  6. 06カタログ、フィールド、スキーマ、インベントリのツール

活用シーン

  1. 01キャンペーン、広告、キーワードの照会
  2. 02レポートの取得と生成完了までの待機
  3. 03アカウントの掲載状況とAPI結果の照合
  4. 04必要に応じた広告データ書き込みの有効化

MCP 対応

Claude Code、Cursor、Codexなどのクライアント向けにMCPサーバーとして動作し、設定に応じた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

Yandex Direct v5 API 用 MCP サーバーおよびコマンドラインです。機械可読スキーマから生成された113 のメソッドすべてを網羅しています。デフォルトで公開されるのは、読み取りに使う 9 つのメソッドです。残りは 1 つの変数で有効にでき、変更操作は無効になっています。

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

npm CI License: MIT

English

Claude Code、Cursor、Codex などのクライアント向け MCP サーバーとしても、MCP が不要な場合は通常のコマンドとしても動作します。

5 秒でわかること

ターミナルでの実行記録:direct_campaigns_get の呼び出しと 2 つの列。左側は通常の JSON.parse で解析したレスポンス本文、右側はサーバーを経由した同じデータです。予算は 1000000000 に対して 1000、解析で壊れた広告 ID に対して正確な ID、Items ラッパーに対して通常のリスト、HTTP 202 の拒否応答に対して拒否として認識された応答が表示されています。

どちらの列も実際のデータです。左側は通常の JSON.parse で解析したレスポンス本文、つまり、どのクライアントでも受け取るデータです。右側はサーバーが JSON-RPC 経由で返したデータです。ID の行がそれを明確に示しています。左側の ID は表示上そうなっているのではなく、実際に解析によって壊れています。トークンもネットワークも不要です。リクエストはローカルのスタブに送られるため、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さらに 4 つのユーティリティ:direct_catalog、direct_fields、direct_schema、direct_inventory

この表は手書きではなく、仕様から算出されます(npm run coverage)。文章中の数値はスキーマと食い違っていても気づかれず、誤った内容が正しいように見えてしまいます。

クイックスタート

direct:api スコープを持つ Yandex の OAuth トークンが必要です:https://oauth.yandex.ru/ (アプリケーションには、Direct 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

このサーバーが代わりに処理すること

利便性の話ではありません。それぞれ、Direct に直接リクエストすると気づかないまま誤る箇所です。レスポンスは正常に見え、エラーも出ませんが、数値や結果が間違っています。以下に挙げる内容はすべて、ドキュメントを読んだものではなく、実際の API を実行して確認しています。

金額は常に 100 万倍で返されます
DailyBudget.Amount = 1000000000     ← это 1000 единиц валюты счёта
Cost               = 1234500000     ← это 1234,50 единицы валюты счёта

誤差はちょうど 100 万倍ですが、誤りには見えません。数値はもっともらしく、合計したり、割ったり、グラフにしたりできます。レポートでマイクロ単位を無効にする 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.

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。