yandex-direct-mcp-plus 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +186 -0
  3. package/dist/app/index.d.ts +2 -0
  4. package/dist/app/index.js +15 -0
  5. package/dist/app/registry.d.ts +2 -0
  6. package/dist/app/registry.js +83 -0
  7. package/dist/app/server.d.ts +4 -0
  8. package/dist/app/server.js +30 -0
  9. package/dist/shared/api/client.d.ts +1 -0
  10. package/dist/shared/api/client.js +16 -0
  11. package/dist/shared/api/errors.d.ts +2 -0
  12. package/dist/shared/api/errors.js +21 -0
  13. package/dist/shared/api/fetch.d.ts +5 -0
  14. package/dist/shared/api/fetch.js +62 -0
  15. package/dist/shared/api/json.d.ts +2 -0
  16. package/dist/shared/api/json.js +13 -0
  17. package/dist/shared/api/parse.d.ts +2 -0
  18. package/dist/shared/api/parse.js +10 -0
  19. package/dist/shared/api/reports.d.ts +6 -0
  20. package/dist/shared/api/reports.js +45 -0
  21. package/dist/shared/api/v4.d.ts +1 -0
  22. package/dist/shared/api/v4.js +18 -0
  23. package/dist/shared/config/endpoints.d.ts +3 -0
  24. package/dist/shared/config/endpoints.js +8 -0
  25. package/dist/shared/config/enums.d.ts +30 -0
  26. package/dist/shared/config/enums.js +137 -0
  27. package/dist/shared/config/env.d.ts +2 -0
  28. package/dist/shared/config/env.js +14 -0
  29. package/dist/shared/config/limits.d.ts +58 -0
  30. package/dist/shared/config/limits.js +54 -0
  31. package/dist/shared/lib/campaign-type.d.ts +12 -0
  32. package/dist/shared/lib/campaign-type.js +20 -0
  33. package/dist/shared/lib/date.d.ts +3 -0
  34. package/dist/shared/lib/date.js +17 -0
  35. package/dist/shared/lib/format.d.ts +3 -0
  36. package/dist/shared/lib/format.js +51 -0
  37. package/dist/shared/lib/id.d.ts +4 -0
  38. package/dist/shared/lib/id.js +21 -0
  39. package/dist/shared/lib/money.d.ts +6 -0
  40. package/dist/shared/lib/money.js +21 -0
  41. package/dist/shared/lib/pagination.d.ts +9 -0
  42. package/dist/shared/lib/pagination.js +26 -0
  43. package/dist/shared/lib/report.d.ts +1 -0
  44. package/dist/shared/lib/report.js +5 -0
  45. package/dist/shared/lib/tool.d.ts +24 -0
  46. package/dist/shared/lib/tool.js +20 -0
  47. package/dist/tools/account/handler.d.ts +3 -0
  48. package/dist/tools/account/handler.js +12 -0
  49. package/dist/tools/account/schema.d.ts +4 -0
  50. package/dist/tools/account/schema.js +7 -0
  51. package/dist/tools/account/tool.d.ts +1 -0
  52. package/dist/tools/account/tool.js +11 -0
  53. package/dist/tools/ad-extensions/handler.d.ts +5 -0
  54. package/dist/tools/ad-extensions/handler.js +35 -0
  55. package/dist/tools/ad-extensions/schema.d.ts +14 -0
  56. package/dist/tools/ad-extensions/schema.js +37 -0
  57. package/dist/tools/ad-extensions/tool.d.ts +3 -0
  58. package/dist/tools/ad-extensions/tool.js +27 -0
  59. package/dist/tools/ad-groups/handler.d.ts +5 -0
  60. package/dist/tools/ad-groups/handler.js +33 -0
  61. package/dist/tools/ad-groups/schema.d.ts +14 -0
  62. package/dist/tools/ad-groups/schema.js +27 -0
  63. package/dist/tools/ad-groups/tool.d.ts +3 -0
  64. package/dist/tools/ad-groups/tool.js +27 -0
  65. package/dist/tools/ad-images/handler.d.ts +5 -0
  66. package/dist/tools/ad-images/handler.js +47 -0
  67. package/dist/tools/ad-images/schema.d.ts +13 -0
  68. package/dist/tools/ad-images/schema.js +37 -0
  69. package/dist/tools/ad-images/tool.d.ts +1 -0
  70. package/dist/tools/ad-images/tool.js +11 -0
  71. package/dist/tools/ads/handler.d.ts +7 -0
  72. package/dist/tools/ads/handler.js +54 -0
  73. package/dist/tools/ads/schema.d.ts +27 -0
  74. package/dist/tools/ads/schema.js +68 -0
  75. package/dist/tools/ads/tool.d.ts +5 -0
  76. package/dist/tools/ads/tool.js +43 -0
  77. package/dist/tools/audience-targets/handler.d.ts +6 -0
  78. package/dist/tools/audience-targets/handler.js +96 -0
  79. package/dist/tools/audience-targets/schema.d.ts +29 -0
  80. package/dist/tools/audience-targets/schema.js +84 -0
  81. package/dist/tools/audience-targets/tool.d.ts +2 -0
  82. package/dist/tools/audience-targets/tool.js +19 -0
  83. package/dist/tools/bid-adjustments/handler.d.ts +4 -0
  84. package/dist/tools/bid-adjustments/handler.js +43 -0
  85. package/dist/tools/bid-adjustments/schema.d.ts +16 -0
  86. package/dist/tools/bid-adjustments/schema.js +50 -0
  87. package/dist/tools/bid-adjustments/tool.d.ts +2 -0
  88. package/dist/tools/bid-adjustments/tool.js +19 -0
  89. package/dist/tools/businesses/handler.d.ts +3 -0
  90. package/dist/tools/businesses/handler.js +26 -0
  91. package/dist/tools/businesses/schema.d.ts +6 -0
  92. package/dist/tools/businesses/schema.js +12 -0
  93. package/dist/tools/businesses/tool.d.ts +1 -0
  94. package/dist/tools/businesses/tool.js +11 -0
  95. package/dist/tools/campaigns/handler.d.ts +11 -0
  96. package/dist/tools/campaigns/handler.js +200 -0
  97. package/dist/tools/campaigns/schema.d.ts +46 -0
  98. package/dist/tools/campaigns/schema.js +109 -0
  99. package/dist/tools/campaigns/tool.d.ts +7 -0
  100. package/dist/tools/campaigns/tool.js +61 -0
  101. package/dist/tools/changes/handler.d.ts +5 -0
  102. package/dist/tools/changes/handler.js +33 -0
  103. package/dist/tools/changes/schema.d.ts +9 -0
  104. package/dist/tools/changes/schema.js +35 -0
  105. package/dist/tools/changes/tool.d.ts +1 -0
  106. package/dist/tools/changes/tool.js +11 -0
  107. package/dist/tools/dictionaries/handler.d.ts +5 -0
  108. package/dist/tools/dictionaries/handler.js +66 -0
  109. package/dist/tools/dictionaries/schema.d.ts +9 -0
  110. package/dist/tools/dictionaries/schema.js +23 -0
  111. package/dist/tools/dictionaries/tool.d.ts +2 -0
  112. package/dist/tools/dictionaries/tool.js +19 -0
  113. package/dist/tools/dynamic-targets/handler.d.ts +6 -0
  114. package/dist/tools/dynamic-targets/handler.js +96 -0
  115. package/dist/tools/dynamic-targets/schema.d.ts +33 -0
  116. package/dist/tools/dynamic-targets/schema.js +91 -0
  117. package/dist/tools/dynamic-targets/tool.d.ts +2 -0
  118. package/dist/tools/dynamic-targets/tool.js +19 -0
  119. package/dist/tools/feeds/handler.d.ts +3 -0
  120. package/dist/tools/feeds/handler.js +29 -0
  121. package/dist/tools/feeds/schema.d.ts +6 -0
  122. package/dist/tools/feeds/schema.js +12 -0
  123. package/dist/tools/feeds/tool.d.ts +1 -0
  124. package/dist/tools/feeds/tool.js +11 -0
  125. package/dist/tools/keywords/handler.d.ts +6 -0
  126. package/dist/tools/keywords/handler.js +53 -0
  127. package/dist/tools/keywords/schema.d.ts +21 -0
  128. package/dist/tools/keywords/schema.js +41 -0
  129. package/dist/tools/keywords/tool.d.ts +4 -0
  130. package/dist/tools/keywords/tool.js +35 -0
  131. package/dist/tools/negative-keywords/handler.d.ts +8 -0
  132. package/dist/tools/negative-keywords/handler.js +135 -0
  133. package/dist/tools/negative-keywords/merge.d.ts +2 -0
  134. package/dist/tools/negative-keywords/merge.js +36 -0
  135. package/dist/tools/negative-keywords/schema.d.ts +37 -0
  136. package/dist/tools/negative-keywords/schema.js +139 -0
  137. package/dist/tools/negative-keywords/shared-set-link.d.ts +3 -0
  138. package/dist/tools/negative-keywords/shared-set-link.js +21 -0
  139. package/dist/tools/negative-keywords/tool.d.ts +6 -0
  140. package/dist/tools/negative-keywords/tool.js +51 -0
  141. package/dist/tools/retargeting/handler.d.ts +4 -0
  142. package/dist/tools/retargeting/handler.js +47 -0
  143. package/dist/tools/retargeting/schema.d.ts +19 -0
  144. package/dist/tools/retargeting/schema.js +57 -0
  145. package/dist/tools/retargeting/tool.d.ts +2 -0
  146. package/dist/tools/retargeting/tool.js +19 -0
  147. package/dist/tools/search-queries/handler.d.ts +3 -0
  148. package/dist/tools/search-queries/handler.js +28 -0
  149. package/dist/tools/search-queries/schema.d.ts +7 -0
  150. package/dist/tools/search-queries/schema.js +17 -0
  151. package/dist/tools/search-queries/tool.d.ts +1 -0
  152. package/dist/tools/search-queries/tool.js +11 -0
  153. package/dist/tools/sitelinks/handler.d.ts +4 -0
  154. package/dist/tools/sitelinks/handler.js +28 -0
  155. package/dist/tools/sitelinks/schema.d.ts +13 -0
  156. package/dist/tools/sitelinks/schema.js +35 -0
  157. package/dist/tools/sitelinks/tool.d.ts +2 -0
  158. package/dist/tools/sitelinks/tool.js +19 -0
  159. package/dist/tools/statistics/handler.d.ts +3 -0
  160. package/dist/tools/statistics/handler.js +20 -0
  161. package/dist/tools/statistics/schema.d.ts +7 -0
  162. package/dist/tools/statistics/schema.js +17 -0
  163. package/dist/tools/statistics/tool.d.ts +1 -0
  164. package/dist/tools/statistics/tool.js +11 -0
  165. package/dist/tools/time-targeting/handler.d.ts +6 -0
  166. package/dist/tools/time-targeting/handler.js +124 -0
  167. package/dist/tools/time-targeting/schema.d.ts +19 -0
  168. package/dist/tools/time-targeting/schema.js +73 -0
  169. package/dist/tools/time-targeting/tool.d.ts +2 -0
  170. package/dist/tools/time-targeting/tool.js +20 -0
  171. package/dist/tools/vcards/handler.d.ts +4 -0
  172. package/dist/tools/vcards/handler.js +105 -0
  173. package/dist/tools/vcards/schema.d.ts +27 -0
  174. package/dist/tools/vcards/schema.js +43 -0
  175. package/dist/tools/vcards/tool.d.ts +2 -0
  176. package/dist/tools/vcards/tool.js +19 -0
  177. package/package.json +121 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 theYahia
4
+ Copyright (c) 2026 Pavelsiba
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # yandex-direct-mcp-plus
2
+
3
+ MCP-сервер для API Яндекс.Директ — управление контекстной рекламой из любого MCP-клиента (Claude, Cursor и др.): кампании, объявления, аудитории, изображения, фиды, уточнения, ставки, минус-фразы, стратегии, расписание показов, статистика и баланс. **51 инструмент.**
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node](https://img.shields.io/badge/node-%3E%3D22-green.svg)](https://nodejs.org)
7
+
8
+ > Деньги — **в рублях** (бюджеты, ставки на вводе и выводе); сервер сам конвертирует в микроединицы API. Поддержан **агентский режим** (Client-Login).
9
+ >
10
+ > Все ID передаются строками (`"1915016273214320641"`). Это сохраняет 64-битные идентификаторы Яндекс.Директа без потери точности в JavaScript.
11
+
12
+ > [!NOTE]
13
+ > В npm пакет пока не опубликован — ставится сборкой из исходников. Публикация будет отдельным релизом.
14
+
15
+ ## Установка
16
+
17
+ ```bash
18
+ git clone git@github.com:Pavelsiba/yandex-direct-mcp-plus.git
19
+ cd yandex-direct-mcp-plus
20
+ npm ci && npm run build
21
+ ```
22
+
23
+ ### Claude Desktop
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "yandex-direct": {
29
+ "command": "node",
30
+ "args": ["/путь/к/yandex-direct-mcp-plus/dist/app/index.js"],
31
+ "env": {
32
+ "YANDEX_DIRECT_TOKEN": "ваш_токен"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Claude Code
40
+
41
+ ```bash
42
+ claude mcp add yandex-direct -e YANDEX_DIRECT_TOKEN=ваш_токен -- node /путь/к/yandex-direct-mcp-plus/dist/app/index.js
43
+ ```
44
+ ## Конфигурация (переменные окружения)
45
+
46
+ | Переменная | Обязательна | Назначение |
47
+ |------------|:-----------:|------------|
48
+ | `YANDEX_DIRECT_TOKEN` | да | OAuth-токен Яндекс.Директ |
49
+ | `YANDEX_DIRECT_LOGIN` | нет | Логин клиента для агентских токенов (заголовок `Client-Login`). Обязателен, если токен агентский |
50
+ | `YANDEX_DIRECT_POLYGON_CAMPAIGN_ID` | нет | Только для `npm run test:int`: ID кампании-полигона, оставленной черновиком. Сетевые тесты пишут в неё и ни во что другое; без переменной они пропускаются |
51
+
52
+ ### Как получить токен
53
+
54
+ OAuth-токен выпускается для приложения, зарегистрированного в [Яндекс OAuth](https://oauth.yandex.ru/), с доступом к API Директа. Подробности — [регистрация приложения и получение токена](https://yandex.ru/dev/direct/doc/ru/token). Доступ к API нужно [запросить в интерфейсе Директа](https://yandex.ru/dev/direct/doc/ru/access-request).
55
+
56
+ ## ⚠️ Внимание: реальные траты
57
+
58
+ Инструменты `create_campaign`, `create_text_ad`, `add_keywords`, `set_keyword_bids` и др. меняют боевой рекламный аккаунт и могут **расходовать деньги**.
59
+
60
+ Тестовой среды у Яндекс.Директа больше нет: песочница отключена с июля 2026, и любой вызов идёт по боевому аккаунту. Отлаживать сценарии приходится на отдельной кампании, оставленной черновиком, — показов она не даёт и потому не тратит бюджет, пока не пройдёт модерацию и не будет включена.
61
+
62
+ ## Инструменты (51)
63
+
64
+ **Кампании**
65
+
66
+ | Инструмент | Описание |
67
+ |------------|----------|
68
+ | `list_campaigns` | Список кампаний (фильтр по статусу/типу, пагинация) |
69
+ | `get_campaign` | Детальная информация о кампании по ID |
70
+ | `create_campaign` | Создать кампанию (бюджет в рублях, выбор стратегии, часовой пояс, UTM-разметка) |
71
+ | `update_campaign` | Обновить название/бюджет/UTM-разметку и/или статус (SUSPEND/RESUME/ARCHIVE/UNARCHIVE) |
72
+ | `manage_campaigns` | suspend/resume/archive/unarchive для списка кампаний |
73
+ | `get_strategy` | Получить стратегию текстово-графической кампании |
74
+ | `set_strategy` | Сменить стратегию: ручная, максимум кликов, средняя цена клика/конверсии, оплата за конверсию |
75
+ | `get_time_targeting` | Расписание показов: часовой пояс, часы по дням недели, праздники |
76
+ | `set_time_targeting` | Задать расписание показов и почасовые коэффициенты (заменяет целиком) |
77
+
78
+ **Группы объявлений**
79
+
80
+ | Инструмент | Описание |
81
+ |------------|----------|
82
+ | `list_ad_groups` | Группы объявлений выбранных кампаний |
83
+ | `create_ad_group` | Создать группу с таргетингом по регионам |
84
+ | `delete_ad_groups` | Удалить группы по ID |
85
+ | `set_ad_group_negative_keywords` | Минус-фразы группы: `mode` обязателен — `replace`, `add` или `remove` |
86
+
87
+ **Объявления**
88
+
89
+ | Инструмент | Описание |
90
+ |------------|----------|
91
+ | `list_ads` | Объявления в группах |
92
+ | `create_text_ad` | Создать текстовое объявление (≤56/≤30/≤81) |
93
+ | `update_text_ad` | Обновить заголовок/текст/ссылку |
94
+ | `manage_ads` | suspend/resume/archive/unarchive/moderate/delete |
95
+ | `moderate_ads` | Отправить объявления на модерацию |
96
+
97
+ **Ключевые слова и ставки**
98
+
99
+ | Инструмент | Описание |
100
+ |------------|----------|
101
+ | `list_keywords` | Ключевые фразы в группах (ставки в рублях) |
102
+ | `add_keywords` | Добавить ключевые фразы |
103
+ | `set_keyword_bids` | Установить ставки (поиск/сети, рубли) на фразах/группах/кампаниях |
104
+ | `manage_keywords` | suspend/resume/delete |
105
+ | `set_campaign_negative_keywords` | Минус-фразы кампании: `mode` обязателен — `replace`, `add` или `remove` |
106
+ | `get_campaign_negative_keywords` | Получить минус-фразы кампаний |
107
+
108
+ **Быстрые ссылки, уточнения и корректировки**
109
+
110
+ | Инструмент | Описание |
111
+ |------------|----------|
112
+ | `list_sitelinks` | Получить наборы быстрых ссылок |
113
+ | `set_sitelinks` | Создать новый набор быстрых ссылок |
114
+ | `list_ad_extensions` | Получить уточнения (callouts) |
115
+ | `add_ad_extensions` | Создать уточнения |
116
+ | `delete_ad_extensions` | Удалить уточнения |
117
+ | `manage_ad_images` | Загрузить, получить или удалить изображения |
118
+ | `get_bid_adjustments` | Получить корректировки по устройствам, полу и возрасту |
119
+ | `set_bid_adjustments` | Изменить коэффициенты существующих корректировок |
120
+
121
+ **Аудитории, цели и фиды**
122
+
123
+ | Инструмент | Описание |
124
+ |------------|----------|
125
+ | `list_retargeting_lists` | Получить условия ретаргетинга и подбора аудитории |
126
+ | `add_retargeting_list` | Создать условие ретаргетинга |
127
+ | `list_audience_targets` | Получить аудиторные цели |
128
+ | `set_audience_targets` | add/set_bids/suspend/resume/delete аудиторных целей |
129
+ | `list_dynamic_targets` | Получить динамические цели |
130
+ | `manage_dynamic_targets` | add/set_bids/suspend/resume/delete динамических целей |
131
+ | `list_feeds` | Получить товарные фиды |
132
+ | `list_negative_keyword_shared_sets` | Получить общие наборы минус-фраз |
133
+ | `manage_negative_keyword_shared_sets` | add/update/delete общих наборов |
134
+ | `link_negative_keyword_sets` | Привязать общие наборы к кампаниям и группам объявлений |
135
+
136
+ **Статистика, аккаунт, справочники**
137
+
138
+ | Инструмент | Описание |
139
+ |------------|----------|
140
+ | `get_statistics` | Статистика за период (показы, клики, расход, CTR, CPC) |
141
+ | `get_search_queries` | Фактические поисковые запросы для подбора минус-фраз |
142
+ | `get_changes` | Проверить изменения кампаний, групп и объявлений |
143
+ | `list_vcards` | Получить виртуальные визитки |
144
+ | `add_vcard` | Создать виртуальную визитку |
145
+ | `list_businesses` | Получить профили организаций Яндекс Бизнеса |
146
+ | `get_account_balance` | Баланс аккаунта (Live API v4) |
147
+ | `get_regions` | Справочник кодов регионов (225 = Россия) |
148
+ | `list_time_zones` | Справочник часовых поясов для расписания показов |
149
+
150
+ ## Примеры запросов
151
+
152
+ ```
153
+ Покажи все активные рекламные кампании
154
+ Создай кампанию "Летняя распродажа" с бюджетом 5000 ₽/день, старт 2026-05-01
155
+ Установи ставку 25 ₽ на ключевые фразы 111 и 222
156
+ Добавь минус-фразы "бесплатно", "скачать" в кампанию 12345
157
+ Какая статистика у кампаний 12345 и 67890 за последнюю неделю?
158
+ Найди код региона для Новосибирска
159
+ Покажи баланс аккаунта
160
+ ```
161
+
162
+ ## Разработка
163
+
164
+ ```bash
165
+ npm install
166
+ npm run build # tsc → dist/
167
+ npm test # vitest (моки fetch)
168
+ npm run dev # tsx --conditions=development src/app/index.ts
169
+ npm run lint # biome
170
+ npm run typecheck # tsc --noEmit
171
+ npm run lint:dead # knip
172
+ ```
173
+
174
+ Код разложен по слоям `app → tools → shared`; инструмент — это каталог
175
+ `src/tools/<домен>/` с `schema.ts`, `handler.ts` и `tool.ts`. Подробности —
176
+ в [docs/architecture.md](docs/architecture.md).
177
+
178
+ ## Происхождение и благодарности
179
+
180
+ Проект начат на коде [`theYahia/yandex-direct-mcp`](https://github.com/theYahia/yandex-direct-mcp) под лицензией MIT. Расширение с 20 до 48 инструментов и перевод ID на строки — работа [**Maxim (DrSeedon)**](https://github.com/DrSeedon), [PR #7](https://github.com/theYahia/yandex-direct-mcp/pull/7); в npm эта версия не публиковалась. Дальше проект развивается самостоятельно и апстрим не отслеживает.
181
+
182
+ История до отделения от апстрима (версии 3.0.0–5.0.0, включая вклад DrSeedon) — в [docs/CHANGELOG-upstream.md](docs/CHANGELOG-upstream.md); дальнейшие изменения — в [CHANGELOG.md](CHANGELOG.md). План — в [docs/roadmap.md](docs/roadmap.md), архитектура — в [docs/architecture.md](docs/architecture.md).
183
+
184
+ ## Лицензия
185
+
186
+ MIT — см. [LICENSE](LICENSE). Уведомление об авторских правах исходного проекта сохранено.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ // Точка входа: поднимает сервер на stdio-транспорте и больше ничего не делает.
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { tools } from "#app/registry";
5
+ import { createServer, readVersion } from "#app/server";
6
+ async function main() {
7
+ const server = createServer(tools);
8
+ await server.connect(new StdioServerTransport());
9
+ // stdout занят транспортом MCP — любые сообщения только в stderr.
10
+ console.error(`[yd-mcp] v${readVersion()} запущен. ${tools.length} инструментов. Требуется YANDEX_DIRECT_TOKEN.`);
11
+ }
12
+ main().catch((error) => {
13
+ console.error("[yd-mcp] Ошибка запуска:", error);
14
+ process.exit(1);
15
+ });
@@ -0,0 +1,2 @@
1
+ import type { ToolDescriptor } from "#shared/lib/tool";
2
+ export declare const tools: readonly ToolDescriptor[];
@@ -0,0 +1,83 @@
1
+ import { getAccountBalanceTool } from "#tools/account/tool";
2
+ import { addAdExtensionsTool, deleteAdExtensionsTool, listAdExtensionsTool } from "#tools/ad-extensions/tool";
3
+ import { createAdGroupTool, deleteAdGroupsTool, listAdGroupsTool } from "#tools/ad-groups/tool";
4
+ import { manageAdImagesTool } from "#tools/ad-images/tool";
5
+ import { createTextAdTool, listAdsTool, manageAdsTool, moderateAdsTool, updateTextAdTool } from "#tools/ads/tool";
6
+ import { listAudienceTargetsTool, setAudienceTargetsTool } from "#tools/audience-targets/tool";
7
+ import { getBidAdjustmentsTool, setBidAdjustmentsTool } from "#tools/bid-adjustments/tool";
8
+ import { listBusinessesTool } from "#tools/businesses/tool";
9
+ import { createCampaignTool, getCampaignTool, getStrategyTool, listCampaignsTool, manageCampaignsTool, setStrategyTool, updateCampaignTool } from "#tools/campaigns/tool";
10
+ import { getChangesTool } from "#tools/changes/tool";
11
+ import { getRegionsTool, listTimeZonesTool } from "#tools/dictionaries/tool";
12
+ import { listDynamicTargetsTool, manageDynamicTargetsTool } from "#tools/dynamic-targets/tool";
13
+ import { listFeedsTool } from "#tools/feeds/tool";
14
+ import { addKeywordsTool, listKeywordsTool, manageKeywordsTool, setKeywordBidsTool } from "#tools/keywords/tool";
15
+ import { getCampaignNegativeKeywordsTool, linkNegativeKeywordSetsTool, listNegativeKeywordSharedSetsTool, manageNegativeKeywordSharedSetsTool, setAdGroupNegativeKeywordsTool, setCampaignNegativeKeywordsTool } from "#tools/negative-keywords/tool";
16
+ import { addRetargetingListTool, listRetargetingListsTool } from "#tools/retargeting/tool";
17
+ import { getSearchQueriesTool } from "#tools/search-queries/tool";
18
+ import { listSitelinksTool, setSitelinksTool } from "#tools/sitelinks/tool";
19
+ import { getStatisticsTool } from "#tools/statistics/tool";
20
+ import { getTimeTargetingTool, setTimeTargetingTool } from "#tools/time-targeting/tool";
21
+ import { addVcardTool, listVcardsTool } from "#tools/vcards/tool";
22
+ export const tools = [
23
+ // Кампании и стратегии
24
+ listCampaignsTool,
25
+ getCampaignTool,
26
+ createCampaignTool,
27
+ updateCampaignTool,
28
+ manageCampaignsTool,
29
+ getStrategyTool,
30
+ setStrategyTool,
31
+ getTimeTargetingTool,
32
+ setTimeTargetingTool,
33
+ // Группы объявлений
34
+ listAdGroupsTool,
35
+ createAdGroupTool,
36
+ deleteAdGroupsTool,
37
+ // Объявления
38
+ listAdsTool,
39
+ createTextAdTool,
40
+ updateTextAdTool,
41
+ manageAdsTool,
42
+ moderateAdsTool,
43
+ // Ключевые фразы и ставки
44
+ listKeywordsTool,
45
+ addKeywordsTool,
46
+ manageKeywordsTool,
47
+ setKeywordBidsTool,
48
+ // Минус-фразы
49
+ getCampaignNegativeKeywordsTool,
50
+ setCampaignNegativeKeywordsTool,
51
+ setAdGroupNegativeKeywordsTool,
52
+ listNegativeKeywordSharedSetsTool,
53
+ manageNegativeKeywordSharedSetsTool,
54
+ linkNegativeKeywordSetsTool,
55
+ // Ассеты объявления
56
+ listSitelinksTool,
57
+ setSitelinksTool,
58
+ listAdExtensionsTool,
59
+ addAdExtensionsTool,
60
+ deleteAdExtensionsTool,
61
+ manageAdImagesTool,
62
+ listVcardsTool,
63
+ addVcardTool,
64
+ // Таргетинг и корректировки
65
+ listAudienceTargetsTool,
66
+ setAudienceTargetsTool,
67
+ listDynamicTargetsTool,
68
+ manageDynamicTargetsTool,
69
+ listRetargetingListsTool,
70
+ addRetargetingListTool,
71
+ getBidAdjustmentsTool,
72
+ setBidAdjustmentsTool,
73
+ // Отчёты
74
+ getStatisticsTool,
75
+ getSearchQueriesTool,
76
+ // Аккаунт и справочники
77
+ getAccountBalanceTool,
78
+ listBusinessesTool,
79
+ getChangesTool,
80
+ listFeedsTool,
81
+ getRegionsTool,
82
+ listTimeZonesTool
83
+ ];
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ToolDescriptor } from "#shared/lib/tool";
3
+ export declare function readVersion(): string;
4
+ export declare function createServer(tools: readonly ToolDescriptor[]): McpServer;
@@ -0,0 +1,30 @@
1
+ // Композиция сервера: единственное место, знающее про McpServer и транспорт.
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ const packageRoot = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
7
+ export function readVersion() {
8
+ try {
9
+ // biome-ignore lint/plugin: package.json, идентификаторов Директа здесь нет
10
+ const pkg = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
11
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
12
+ }
13
+ catch {
14
+ return "0.0.0";
15
+ }
16
+ }
17
+ export function createServer(tools) {
18
+ const server = new McpServer({ name: "yd-mcp", version: readVersion() });
19
+ for (const tool of tools) {
20
+ server.registerTool(tool.name, {
21
+ title: tool.title,
22
+ description: tool.description,
23
+ inputSchema: tool.schema.shape,
24
+ annotations: tool.annotations
25
+ }, async (params) => ({
26
+ content: [{ type: "text", text: await tool.run(params) }]
27
+ }));
28
+ }
29
+ return server;
30
+ }
@@ -0,0 +1 @@
1
+ export declare function apiPost(service: string, method: string, params?: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,16 @@
1
+ // JSON API v5 — основной клиент: один POST на сервис с телом { method, params }.
2
+ import { assertNoApiError } from "#shared/api/errors";
3
+ import { commonHeaders, fetchWithRetry, logUnits } from "#shared/api/fetch";
4
+ import { parseJson, stringifyJson } from "#shared/api/json";
5
+ import { BASE_URL } from "#shared/config/endpoints";
6
+ export async function apiPost(service, method, params = {}) {
7
+ const response = await fetchWithRetry(`${BASE_URL}${service}`, {
8
+ method: "POST",
9
+ headers: commonHeaders(),
10
+ body: stringifyJson({ method, params })
11
+ });
12
+ logUnits(response);
13
+ const data = parseJson(await response.text());
14
+ assertNoApiError(data);
15
+ return data;
16
+ }
@@ -0,0 +1,2 @@
1
+ export declare function assertNoApiError(data: unknown): void;
2
+ export declare function assertNoApiErrorV4(data: Record<string, unknown> | null): void;
@@ -0,0 +1,21 @@
1
+ // Разбор ошибок Директа. Хендлеры сюда не заглядывают: их дело — сценарий.
2
+ // v5 возвращает ошибку уровня запроса телом с HTTP 200 — статус проверять бесполезно,
3
+ // признак ошибки один: ключ `error`. Док: https://yandex.ru/dev/direct/doc/en/concepts/errors-list
4
+ export function assertNoApiError(data) {
5
+ const error = data?.error;
6
+ if (!error || typeof error !== "object")
7
+ return;
8
+ const parts = [`Ошибка API Яндекс.Директ [${error.error_code ?? "?"}]: ${error.error_string ?? "неизвестная ошибка"}`];
9
+ if (error.error_detail)
10
+ parts.push(`— ${error.error_detail}`);
11
+ if (error.request_id)
12
+ parts.push(`(request_id: ${error.request_id})`);
13
+ throw new Error(parts.join(" "));
14
+ }
15
+ // v4 отвечает по-своему: error_str вместо error_string, признак — любой из двух ключей.
16
+ export function assertNoApiErrorV4(data) {
17
+ if (!data || (data.error_code === undefined && data.error_str === undefined))
18
+ return;
19
+ const detail = data.error_detail ? ` — ${data.error_detail}` : "";
20
+ throw new Error(`Ошибка API v4 [${data.error_code ?? "?"}]: ${data.error_str ?? "неизвестная ошибка"}${detail}`);
21
+ }
@@ -0,0 +1,5 @@
1
+ export declare function commonHeaders(): Record<string, string>;
2
+ export declare function logUnits(response: Response): void;
3
+ export type Transport = (url: string, options: RequestInit) => Promise<Response>;
4
+ export declare function setTransport(next: Transport): void;
5
+ export declare function fetchWithRetry(url: string, options?: RequestInit, retries?: number): Promise<Response>;
@@ -0,0 +1,62 @@
1
+ // Транспорт: заголовки, повторы, таймаут. Знает про HTTP и токен, не знает про домен.
2
+ import { getClientLogin, getToken } from "#shared/config/env";
3
+ import { MAX_RETRIES, MAX_RETRY_DELAY_MS, REQUEST_TIMEOUT_MS } from "#shared/config/limits";
4
+ export function commonHeaders() {
5
+ const headers = {
6
+ Authorization: `Bearer ${getToken()}`,
7
+ "Content-Type": "application/json",
8
+ "Accept-Language": "ru"
9
+ };
10
+ const clientLogin = getClientLogin();
11
+ if (clientLogin)
12
+ headers["Client-Login"] = clientLogin;
13
+ return headers;
14
+ }
15
+ // Units = «израсходовано/остаток/суточный лимит» баллов API. В stdout писать нельзя —
16
+ // там транспорт MCP, поэтому stderr.
17
+ export function logUnits(response) {
18
+ const units = response.headers?.get?.("Units");
19
+ if (units)
20
+ console.error(`[yd-mcp] Баллы API (потрачено/остаток/лимит): ${units}`);
21
+ }
22
+ function delay(ms) {
23
+ return new Promise((resolve) => setTimeout(resolve, ms));
24
+ }
25
+ // Шов для тестов. Раньше они подменяли globalThis.fetch — глобал один на процесс, и
26
+ // подмена задевала всё, что в нём живёт, включая SDK. Здесь шов свой, объявлен типом
27
+ // и виден в коде; сеть трогает единственная строка ниже.
28
+ let transport = (url, options) => fetch(url, options);
29
+ export function setTransport(next) {
30
+ transport = next;
31
+ }
32
+ export async function fetchWithRetry(url, options = {}, retries = MAX_RETRIES) {
33
+ for (let attempt = 1; attempt <= retries; attempt++) {
34
+ const controller = new AbortController();
35
+ const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
36
+ try {
37
+ const response = await transport(url, { ...options, signal: controller.signal });
38
+ clearTimeout(timer);
39
+ if (response.ok)
40
+ return response;
41
+ if (response.status >= 500 && attempt < retries) {
42
+ const backoff = Math.min(1000 * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
43
+ console.error(`[yd-mcp] ${response.status} от ${url}, повтор через ${backoff}мс (${attempt}/${retries})`);
44
+ await delay(backoff);
45
+ continue;
46
+ }
47
+ const body = await response.text().catch(() => "");
48
+ throw new Error(`HTTP ${response.status}: ${response.statusText}. ${body}`);
49
+ }
50
+ catch (error) {
51
+ clearTimeout(timer);
52
+ if (attempt === retries)
53
+ throw error;
54
+ if (error instanceof DOMException && error.name === "AbortError") {
55
+ console.error(`[yd-mcp] Таймаут ${url}, повтор (${attempt}/${retries})`);
56
+ continue;
57
+ }
58
+ throw error;
59
+ }
60
+ }
61
+ throw new Error("Все попытки исчерпаны");
62
+ }
@@ -0,0 +1,2 @@
1
+ export declare function parseJson(text: string): unknown;
2
+ export declare function stringifyJson(value: unknown): string;
@@ -0,0 +1,13 @@
1
+ // biome-ignore-all lint/plugin: единственное место в проекте, где вызывается разбор JSON
2
+ // ID Директа — 64-битные целые, в живых аккаунтах 19-значные. Родной JSON.parse молча
3
+ // округляет их до 2^53−1, превращая ID в валидное число, указывающее на другой объект.
4
+ // storeAsString отдаёт большие числа строками; сериализация принимает BigInt.
5
+ // Разбор и сериализация JSON живут только здесь — держит GritQL-плагин Biome.
6
+ import JSONbigFactory from "json-bigint";
7
+ const JSONbig = JSONbigFactory({ storeAsString: true });
8
+ export function parseJson(text) {
9
+ return JSONbig.parse(text);
10
+ }
11
+ export function stringifyJson(value) {
12
+ return JSONbig.stringify(value);
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { z } from "zod";
2
+ export declare function parseApiResult<Schema extends z.ZodType>(schema: Schema, value: unknown, what: string): z.infer<Schema>;
@@ -0,0 +1,10 @@
1
+ import { prettifyError } from "zod";
2
+ // Схемы ответов пишутся нестрогими (`z.looseObject`): Директ добавляет поля без
3
+ // предупреждения, и строгая схема превратила бы такое добавление в отказ инструмента.
4
+ // Обязательными объявляются только поля, на которые опирается сам инструмент.
5
+ export function parseApiResult(schema, value, what) {
6
+ const parsed = schema.safeParse(value);
7
+ if (parsed.success)
8
+ return parsed.data;
9
+ throw new Error(`Директ вернул ${what} в неожиданной форме: ${prettifyError(parsed.error)}`);
10
+ }
@@ -0,0 +1,6 @@
1
+ export type ReportOptions = {
2
+ skipReportHeader?: boolean;
3
+ skipReportSummary?: boolean;
4
+ skipColumnHeader?: boolean;
5
+ };
6
+ export declare function apiReport(params: Record<string, unknown>, opts?: ReportOptions): Promise<string>;
@@ -0,0 +1,45 @@
1
+ // ReportService отдаёт TSV и работает офлайн: 200 — отчёт готов, 201 — поставлен
2
+ // в очередь, 202 — ещё формируется, повторить через retryIn секунд.
3
+ // Док: https://yandex.ru/dev/direct/doc/en/codes
4
+ import { commonHeaders, fetchWithRetry, logUnits } from "#shared/api/fetch";
5
+ import { stringifyJson } from "#shared/api/json";
6
+ import { REPORT_URL } from "#shared/config/endpoints";
7
+ import { REPORT_DEFAULT_RETRY_IN_SEC, REPORT_MAX_POLLS, REPORT_MAX_RETRY_IN_SEC } from "#shared/config/limits";
8
+ function reportHeaders(opts) {
9
+ return {
10
+ ...commonHeaders(),
11
+ processingMode: "auto",
12
+ returnMoneyInMicros: "false",
13
+ skipReportHeader: opts.skipReportHeader === false ? "false" : "true",
14
+ skipReportSummary: opts.skipReportSummary ? "true" : "false",
15
+ skipColumnHeader: opts.skipColumnHeader ? "true" : "false"
16
+ };
17
+ }
18
+ // Сервер называет паузу в заголовке retryIn; на мусор и его отсутствие — свой дефолт.
19
+ function retryInSeconds(response) {
20
+ const raw = response.headers?.get?.("retryIn");
21
+ const parsed = raw == null ? Number.NaN : Number(raw);
22
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : REPORT_DEFAULT_RETRY_IN_SEC;
23
+ }
24
+ export async function apiReport(params, opts = {}) {
25
+ const headers = reportHeaders(opts);
26
+ const body = stringifyJson({ params });
27
+ for (let poll = 0; poll <= REPORT_MAX_POLLS; poll++) {
28
+ const response = await fetchWithRetry(REPORT_URL, { method: "POST", headers, body });
29
+ logUnits(response);
30
+ if (response.status === 200)
31
+ return response.text();
32
+ if (response.status === 201 || response.status === 202) {
33
+ if (poll === REPORT_MAX_POLLS) {
34
+ throw new Error(`Отчёт всё ещё формируется после ${REPORT_MAX_POLLS} попыток опроса. Повторите запрос позже.`);
35
+ }
36
+ const retryIn = retryInSeconds(response);
37
+ console.error(`[yd-mcp] Отчёт формируется (HTTP ${response.status}), повтор через ${retryIn}с (${poll + 1}/${REPORT_MAX_POLLS})`);
38
+ await new Promise((resolve) => setTimeout(resolve, Math.min(retryIn, REPORT_MAX_RETRY_IN_SEC) * 1000));
39
+ continue;
40
+ }
41
+ // Прочие коды сюда не доходят: fetchWithRetry бросает на всём, что не ok.
42
+ return response.text();
43
+ }
44
+ throw new Error("Не удалось получить отчёт");
45
+ }
@@ -0,0 +1 @@
1
+ export declare function apiV4(method: string, param?: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,18 @@
1
+ // Live API v4 — только ради баланса аккаунта, в v5 финансовой информации нет.
2
+ // Формат тела свой: { method, token, param }, токен внутри, а не в заголовке.
3
+ import { assertNoApiErrorV4 } from "#shared/api/errors";
4
+ import { fetchWithRetry, logUnits } from "#shared/api/fetch";
5
+ import { parseJson, stringifyJson } from "#shared/api/json";
6
+ import { V4_URL } from "#shared/config/endpoints";
7
+ import { getToken } from "#shared/config/env";
8
+ export async function apiV4(method, param = {}) {
9
+ const response = await fetchWithRetry(V4_URL, {
10
+ method: "POST",
11
+ headers: { "Content-Type": "application/json", "Accept-Language": "ru" },
12
+ body: stringifyJson({ method, token: getToken(), param })
13
+ });
14
+ logUnits(response);
15
+ const data = parseJson(await response.text());
16
+ assertNoApiErrorV4(data);
17
+ return data;
18
+ }
@@ -0,0 +1,3 @@
1
+ export declare const BASE_URL = "https://api.direct.yandex.com/json/v5/";
2
+ export declare const REPORT_URL = "https://api.direct.yandex.com/json/v5/reports";
3
+ export declare const V4_URL = "https://api.direct.yandex.ru/live/v4/json/";
@@ -0,0 +1,8 @@
1
+ // Эндпоинты Директа. Выбирать не из чего: песочница отключена Яндексом с июля 2026
2
+ // (ответ поддержки 05.09.2026), контур один — боевой. Отсюда константы, а не функции.
3
+ export const BASE_URL = "https://api.direct.yandex.com/json/v5/";
4
+ export const REPORT_URL = `${BASE_URL}reports`;
5
+ // Баланс общего счёта есть только в Live API v4 (AccountManagement.Get). Финансы в v5
6
+ // не отсутствуют вовсе — у кампании это поле Funds, у клиента Bonuses и
7
+ // OverdraftSumAvailable, — но суммы на счёте среди них нет. Сверено с WSDL 05.09.2026.
8
+ export const V4_URL = "https://api.direct.yandex.ru/live/v4/json/";
@@ -0,0 +1,30 @@
1
+ export declare const CAMPAIGN_STATUSES: readonly ["ACCEPTED", "DRAFT", "MODERATION", "REJECTED"];
2
+ export declare const KEYWORD_ACTIONS: readonly ["suspend", "resume", "delete"];
3
+ export declare const AD_ACTIONS: readonly ["suspend", "resume", "archive", "unarchive", "moderate", "delete"];
4
+ export declare const CAMPAIGN_ACTIONS: readonly ["suspend", "resume", "archive", "unarchive"];
5
+ export declare const CAMPAIGN_STATUS_ACTIONS: readonly ["SUSPEND", "RESUME", "ARCHIVE", "UNARCHIVE"];
6
+ export declare const CAMPAIGN_TYPES_CREATABLE: readonly ["TEXT_CAMPAIGN", "DYNAMIC_TEXT_CAMPAIGN"];
7
+ export declare const CAMPAIGN_TYPES: readonly ["TEXT_CAMPAIGN", "MOBILE_APP_CAMPAIGN", "DYNAMIC_TEXT_CAMPAIGN", "CPM_BANNER_CAMPAIGN", "SMART_CAMPAIGN", "UNIFIED_CAMPAIGN"];
8
+ export declare const SEARCH_STRATEGIES: readonly ["HIGHEST_POSITION", "IMPRESSIONS_BELOW_SEARCH", "WB_MAXIMUM_CLICKS", "WB_MAXIMUM_CONVERSION_RATE", "WEEKLY_CLICK_PACKAGE", "AVERAGE_CPC", "AVERAGE_CPA", "AVERAGE_CPA_MULTIPLE_GOALS", "AVERAGE_ROI", "AVERAGE_CRR", "PAY_FOR_CONVERSION", "PAY_FOR_CONVERSION_CRR", "PAY_FOR_CONVERSION_MULTIPLE_GOALS", "MAX_PROFIT", "SERVING_OFF"];
9
+ export declare const NETWORK_STRATEGIES: readonly ["NETWORK_DEFAULT", "MAXIMUM_COVERAGE", "WB_MAXIMUM_CLICKS", "WB_MAXIMUM_CONVERSION_RATE", "WEEKLY_CLICK_PACKAGE", "AVERAGE_CPC", "AVERAGE_CPA", "AVERAGE_CPA_MULTIPLE_GOALS", "AVERAGE_ROI", "AVERAGE_CRR", "PAY_FOR_CONVERSION", "PAY_FOR_CONVERSION_CRR", "PAY_FOR_CONVERSION_MULTIPLE_GOALS", "MAX_PROFIT", "SERVING_OFF"];
10
+ export declare const NEGATIVE_KEYWORD_SET_ACTIONS: readonly ["add", "update", "delete"];
11
+ export declare const AD_EXTENSION_STATES: readonly ["ON", "DELETED"];
12
+ export declare const AD_EXTENSION_STATUSES: readonly ["ACCEPTED", "DRAFT", "MODERATION", "REJECTED"];
13
+ export declare const AD_IMAGE_TYPES: readonly ["REGULAR", "WIDE", "FIXED_IMAGE", "AUTO"];
14
+ export declare const AD_IMAGE_ACTIONS: readonly ["add", "get", "delete"];
15
+ export declare const ASSOCIATED_FLAGS: readonly ["YES", "NO"];
16
+ export declare const RETARGETING_TYPES: readonly ["RETARGETING", "AUDIENCE"];
17
+ export declare const RETARGETING_RULE_OPERATORS: readonly ["ALL", "ANY", "NONE"];
18
+ export declare const BID_ADJUSTMENT_TYPES: readonly ["MOBILE_ADJUSTMENT", "TABLET_ADJUSTMENT", "DESKTOP_ADJUSTMENT", "DESKTOP_ONLY_ADJUSTMENT", "DEMOGRAPHICS_ADJUSTMENT"];
19
+ export declare const BID_ADJUSTMENT_LEVELS: readonly ["CAMPAIGN", "AD_GROUP"];
20
+ export declare const AUDIENCE_TARGET_STATES: readonly ["ON", "SUSPENDED"];
21
+ export declare const AUDIENCE_TARGET_ACTIONS: readonly ["add", "set_bids", "suspend", "resume", "delete"];
22
+ export declare const STRATEGY_PRIORITIES: readonly ["LOW", "NORMAL", "HIGH"];
23
+ export declare const DYNAMIC_TARGET_ACTIONS: readonly ["add", "set_bids", "suspend", "resume", "delete"];
24
+ export declare const WEBPAGE_CONDITION_OPERANDS: readonly ["URL", "DOMAIN", "PAGE_TITLE", "PAGE_CONTENT", "OFFERS_LIST_URL"];
25
+ export declare const WEBPAGE_CONDITION_OPERATORS: readonly ["EQUALS_ANY", "NOT_EQUALS_ALL", "CONTAINS_ANY", "NOT_CONTAINS_ALL"];
26
+ export declare const CHANGES_MODES: readonly ["campaigns", "objects"];
27
+ export declare const CHANGES_FIELD_NAMES: readonly ["CampaignIds", "AdGroupIds", "AdIds", "CampaignsStat"];
28
+ export declare const SETTABLE_SEARCH_STRATEGIES: readonly ["HIGHEST_POSITION", "WB_MAXIMUM_CLICKS", "AVERAGE_CPC", "AVERAGE_CPA", "PAY_FOR_CONVERSION", "SERVING_OFF"];
29
+ export declare const SETTABLE_NETWORK_STRATEGIES: readonly ["NETWORK_DEFAULT", "MAXIMUM_COVERAGE", "WB_MAXIMUM_CLICKS", "AVERAGE_CPC", "AVERAGE_CPA", "PAY_FOR_CONVERSION", "SERVING_OFF"];
30
+ export declare const WEEKDAYS: readonly ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];