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
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ export declare const listAdExtensionsSchema: z.ZodObject<{
3
+ limit: z.ZodOptional<z.ZodInt>;
4
+ offset: z.ZodOptional<z.ZodInt>;
5
+ ad_extension_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ states: z.ZodOptional<z.ZodArray<z.ZodLiteral<"DELETED" | "ON">>>;
7
+ statuses: z.ZodOptional<z.ZodArray<z.ZodLiteral<"ACCEPTED" | "DRAFT" | "MODERATION" | "REJECTED">>>;
8
+ }, z.core.$strip>;
9
+ export declare const addAdExtensionsSchema: z.ZodObject<{
10
+ callouts: z.ZodArray<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ export declare const deleteAdExtensionsSchema: z.ZodObject<{
13
+ ad_extension_ids: z.ZodArray<z.ZodString>;
14
+ }, z.core.$strip>;
@@ -0,0 +1,37 @@
1
+ // Уточнения (Callout) — единственный тип расширений, который покрывает сервер.
2
+ import { z } from "zod";
3
+ import { AD_EXTENSION_STATES, AD_EXTENSION_STATUSES } from "#shared/config/enums";
4
+ import { CALLOUT_TEXT_MAX, MAX_CALLOUTS_PER_CALL, MAX_IDS_PER_CALL } from "#shared/config/limits";
5
+ import { idField } from "#shared/lib/id";
6
+ import { pageFields } from "#shared/lib/pagination";
7
+ export const listAdExtensionsSchema = z.object({
8
+ ad_extension_ids: z
9
+ .array(idField("ID уточнения"))
10
+ .check(z.maxLength(MAX_IDS_PER_CALL, { error: `За один вызов допустимо не больше ${MAX_IDS_PER_CALL} уточнений` }))
11
+ .optional()
12
+ .meta({ description: "Конкретные уточнения; без них возвращаются все" }),
13
+ states: z.array(z.literal(AD_EXTENSION_STATES)).optional().meta({ description: "Фильтр по состоянию уточнения" }),
14
+ statuses: z
15
+ .array(z.literal(AD_EXTENSION_STATUSES))
16
+ .optional()
17
+ .meta({ description: "Фильтр по статусу модерации уточнения" }),
18
+ ...pageFields
19
+ });
20
+ export const addAdExtensionsSchema = z.object({
21
+ callouts: z
22
+ .array(z
23
+ .string()
24
+ .check(z.minLength(1, { error: "Текст уточнения не может быть пустым" }), z.maxLength(CALLOUT_TEXT_MAX, { error: `Текст уточнения длиннее ${CALLOUT_TEXT_MAX} символов` })))
25
+ .check(z.minLength(1, { error: "Список уточнений пуст" }), z.maxLength(MAX_CALLOUTS_PER_CALL, {
26
+ error: `За один вызов допустимо не больше ${MAX_CALLOUTS_PER_CALL} уточнений`
27
+ }))
28
+ .meta({ description: `Тексты уточнений, каждый до ${CALLOUT_TEXT_MAX} символов` })
29
+ });
30
+ export const deleteAdExtensionsSchema = z.object({
31
+ ad_extension_ids: z
32
+ .array(idField("ID уточнения"))
33
+ .check(z.minLength(1, { error: "Список уточнений пуст" }), z.maxLength(MAX_CALLOUTS_PER_CALL, {
34
+ error: `За один вызов допустимо не больше ${MAX_CALLOUTS_PER_CALL} уточнений`
35
+ }))
36
+ .meta({ description: "Уточнения, которые будут удалены безвозвратно" })
37
+ });
@@ -0,0 +1,3 @@
1
+ export declare const listAdExtensionsTool: import("#shared/lib/tool").ToolDescriptor;
2
+ export declare const addAdExtensionsTool: import("#shared/lib/tool").ToolDescriptor;
3
+ export declare const deleteAdExtensionsTool: import("#shared/lib/tool").ToolDescriptor;
@@ -0,0 +1,27 @@
1
+ import { DESTRUCTIVE, defineTool, READ, WRITE } from "#shared/lib/tool";
2
+ import { handleAddAdExtensions, handleDeleteAdExtensions, handleListAdExtensions } from "./handler.js";
3
+ import { addAdExtensionsSchema, deleteAdExtensionsSchema, listAdExtensionsSchema } from "./schema.js";
4
+ export const listAdExtensionsTool = defineTool({
5
+ name: "list_ad_extensions",
6
+ title: "Список уточнений",
7
+ description: "Получить уточнения (callouts) с их статусами и текстом.",
8
+ annotations: READ,
9
+ schema: listAdExtensionsSchema,
10
+ handler: handleListAdExtensions
11
+ });
12
+ export const addAdExtensionsTool = defineTool({
13
+ name: "add_ad_extensions",
14
+ title: "Создать уточнения",
15
+ description: "Создать уточнения (callouts), каждый текст до 25 символов.",
16
+ annotations: WRITE,
17
+ schema: addAdExtensionsSchema,
18
+ handler: handleAddAdExtensions
19
+ });
20
+ export const deleteAdExtensionsTool = defineTool({
21
+ name: "delete_ad_extensions",
22
+ title: "Удалить уточнения",
23
+ description: "Удалить уточнения по ID. ⚠️ Необратимо.",
24
+ annotations: DESTRUCTIVE,
25
+ schema: deleteAdExtensionsSchema,
26
+ handler: handleDeleteAdExtensions
27
+ });
@@ -0,0 +1,5 @@
1
+ import type { z } from "zod";
2
+ import type { createAdGroupSchema, deleteAdGroupsSchema, listAdGroupsSchema } from "./schema.js";
3
+ export declare function handleListAdGroups(params: z.infer<typeof listAdGroupsSchema>): Promise<string>;
4
+ export declare function handleCreateAdGroup(params: z.infer<typeof createAdGroupSchema>): Promise<string>;
5
+ export declare function handleDeleteAdGroups(params: z.infer<typeof deleteAdGroupsSchema>): Promise<string>;
@@ -0,0 +1,33 @@
1
+ import { apiPost } from "#shared/api/client";
2
+ import { formatResult } from "#shared/lib/format";
3
+ import { apiId, apiIds } from "#shared/lib/id";
4
+ import { buildPage } from "#shared/lib/pagination";
5
+ const LIST_FIELDS = ["Id", "Name", "CampaignId", "RegionIds", "Status", "Type"];
6
+ export async function handleListAdGroups(params) {
7
+ const requestParams = {
8
+ SelectionCriteria: { CampaignIds: apiIds(params.campaign_ids) },
9
+ FieldNames: LIST_FIELDS
10
+ };
11
+ const page = buildPage(params);
12
+ if (page)
13
+ requestParams.Page = page;
14
+ return formatResult(await apiPost("adgroups", "get", requestParams));
15
+ }
16
+ export async function handleCreateAdGroup(params) {
17
+ const data = await apiPost("adgroups", "add", {
18
+ AdGroups: [
19
+ {
20
+ Name: params.name,
21
+ CampaignId: apiId(params.campaign_id),
22
+ RegionIds: apiIds(params.region_ids)
23
+ }
24
+ ]
25
+ });
26
+ return formatResult(data);
27
+ }
28
+ export async function handleDeleteAdGroups(params) {
29
+ const data = await apiPost("adgroups", "delete", {
30
+ SelectionCriteria: { Ids: apiIds(params.ad_group_ids) }
31
+ });
32
+ return formatResult(data);
33
+ }
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ export declare const listAdGroupsSchema: z.ZodObject<{
3
+ limit: z.ZodOptional<z.ZodInt>;
4
+ offset: z.ZodOptional<z.ZodInt>;
5
+ campaign_ids: z.ZodArray<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ export declare const createAdGroupSchema: z.ZodObject<{
8
+ campaign_id: z.ZodString;
9
+ name: z.ZodString;
10
+ region_ids: z.ZodArray<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ export declare const deleteAdGroupsSchema: z.ZodObject<{
13
+ ad_group_ids: z.ZodArray<z.ZodString>;
14
+ }, z.core.$strip>;
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ import { idField } from "#shared/lib/id";
3
+ import { pageFields } from "#shared/lib/pagination";
4
+ export const listAdGroupsSchema = z.object({
5
+ campaign_ids: z
6
+ .array(idField("ID кампании, десятичная строка"))
7
+ .check(z.minLength(1, { error: "Укажите хотя бы одну кампанию" }))
8
+ .meta({ description: "Кампании, группы которых нужно выбрать" }),
9
+ ...pageFields
10
+ });
11
+ export const createAdGroupSchema = z.object({
12
+ campaign_id: idField("ID кампании, в которой создаётся группа"),
13
+ name: z
14
+ .string()
15
+ .check(z.minLength(1, { error: "Название не может быть пустым" }))
16
+ .meta({ description: "Название группы" }),
17
+ region_ids: z
18
+ .array(idField("ID региона показа"))
19
+ .check(z.minLength(1, { error: "Укажите хотя бы один регион" }))
20
+ .meta({ description: 'Регионы показа, например ["225"] — Россия. Коды берутся из get_regions' })
21
+ });
22
+ export const deleteAdGroupsSchema = z.object({
23
+ ad_group_ids: z
24
+ .array(idField("ID группы объявлений"))
25
+ .check(z.minLength(1, { error: "Список групп пуст" }))
26
+ .meta({ description: "Группы, которые будут удалены безвозвратно" })
27
+ });
@@ -0,0 +1,3 @@
1
+ export declare const listAdGroupsTool: import("#shared/lib/tool").ToolDescriptor;
2
+ export declare const createAdGroupTool: import("#shared/lib/tool").ToolDescriptor;
3
+ export declare const deleteAdGroupsTool: import("#shared/lib/tool").ToolDescriptor;
@@ -0,0 +1,27 @@
1
+ import { DESTRUCTIVE, defineTool, READ, WRITE } from "#shared/lib/tool";
2
+ import { handleCreateAdGroup, handleDeleteAdGroups, handleListAdGroups } from "./handler.js";
3
+ import { createAdGroupSchema, deleteAdGroupsSchema, listAdGroupsSchema } from "./schema.js";
4
+ export const listAdGroupsTool = defineTool({
5
+ name: "list_ad_groups",
6
+ title: "Список групп",
7
+ description: "Группы объявлений выбранных кампаний: названия, регионы, статусы.",
8
+ annotations: READ,
9
+ schema: listAdGroupsSchema,
10
+ handler: handleListAdGroups
11
+ });
12
+ export const createAdGroupTool = defineTool({
13
+ name: "create_ad_group",
14
+ title: "Создать группу",
15
+ description: "Создать группу объявлений в кампании с таргетингом по регионам (см. get_regions).",
16
+ annotations: WRITE,
17
+ schema: createAdGroupSchema,
18
+ handler: handleCreateAdGroup
19
+ });
20
+ export const deleteAdGroupsTool = defineTool({
21
+ name: "delete_ad_groups",
22
+ title: "Удалить группы",
23
+ description: "Удалить группы объявлений по их ID. ⚠️ Необратимо.",
24
+ annotations: DESTRUCTIVE,
25
+ schema: deleteAdGroupsSchema,
26
+ handler: handleDeleteAdGroups
27
+ });
@@ -0,0 +1,5 @@
1
+ import type { z } from "zod";
2
+ import type { manageAdImagesSchema } from "./schema.js";
3
+ type Params = z.infer<typeof manageAdImagesSchema>;
4
+ export declare function handleManageAdImages(params: Params): Promise<string>;
5
+ export {};
@@ -0,0 +1,47 @@
1
+ import { apiPost } from "#shared/api/client";
2
+ import { formatResult } from "#shared/lib/format";
3
+ import { buildPage } from "#shared/lib/pagination";
4
+ const NO_MONEY = { money: false };
5
+ const GET_FIELDS = ["AdImageHash", "OriginalUrl", "PreviewUrl", "Name", "Type", "Subtype", "Associated"];
6
+ async function addImages(params) {
7
+ if (!params.images?.length)
8
+ throw new Error("Для action=add передайте images.");
9
+ const data = await apiPost("adimages", "add", {
10
+ AdImages: params.images.map((image) => {
11
+ const item = { ImageData: image.image_data, Name: image.name };
12
+ if (image.type)
13
+ item.Type = image.type;
14
+ return item;
15
+ })
16
+ });
17
+ return formatResult(data, NO_MONEY);
18
+ }
19
+ async function deleteImages(params) {
20
+ if (!params.ad_image_hashes?.length)
21
+ throw new Error("Для action=delete передайте ad_image_hashes.");
22
+ const data = await apiPost("adimages", "delete", {
23
+ SelectionCriteria: { AdImageHashes: params.ad_image_hashes }
24
+ });
25
+ return formatResult(data, NO_MONEY);
26
+ }
27
+ async function getImages(params) {
28
+ const selection = {};
29
+ if (params.ad_image_hashes?.length)
30
+ selection.AdImageHashes = params.ad_image_hashes;
31
+ if (params.associated)
32
+ selection.Associated = params.associated;
33
+ const request = { FieldNames: GET_FIELDS };
34
+ if (Object.keys(selection).length > 0)
35
+ request.SelectionCriteria = selection;
36
+ const page = buildPage(params);
37
+ if (page)
38
+ request.Page = page;
39
+ return formatResult(await apiPost("adimages", "get", request), NO_MONEY);
40
+ }
41
+ export async function handleManageAdImages(params) {
42
+ if (params.action === "add")
43
+ return addImages(params);
44
+ if (params.action === "delete")
45
+ return deleteImages(params);
46
+ return getImages(params);
47
+ }
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+ export declare const manageAdImagesSchema: z.ZodObject<{
3
+ limit: z.ZodOptional<z.ZodInt>;
4
+ offset: z.ZodOptional<z.ZodInt>;
5
+ action: z.ZodLiteral<"add" | "delete" | "get">;
6
+ images: z.ZodOptional<z.ZodArray<z.ZodObject<{
7
+ image_data: z.ZodString;
8
+ name: z.ZodString;
9
+ type: z.ZodOptional<z.ZodLiteral<"AUTO" | "FIXED_IMAGE" | "REGULAR" | "WIDE">>;
10
+ }, z.core.$strip>>>;
11
+ ad_image_hashes: z.ZodOptional<z.ZodArray<z.ZodString>>;
12
+ associated: z.ZodOptional<z.ZodLiteral<"NO" | "YES">>;
13
+ }, z.core.$strip>;
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ import { AD_IMAGE_ACTIONS, AD_IMAGE_TYPES, ASSOCIATED_FLAGS } from "#shared/config/enums";
3
+ import { AD_IMAGE_NAME_MAX, MAX_IDS_PER_CALL, MAX_IMAGES_PER_CALL } from "#shared/config/limits";
4
+ import { pageFields } from "#shared/lib/pagination";
5
+ // Изображение адресуется хешем, а не числовым ID: idField здесь неприменим.
6
+ const adImageHash = z.string().check(z.minLength(1, { error: "Хеш изображения не может быть пустым" }));
7
+ const adImage = z.object({
8
+ image_data: z
9
+ .string()
10
+ .check(z.minLength(1, { error: "Данные изображения не могут быть пустыми" }))
11
+ .meta({ description: "Содержимое файла изображения в base64" }),
12
+ name: z
13
+ .string()
14
+ .check(z.minLength(1, { error: "Название не может быть пустым" }), z.maxLength(AD_IMAGE_NAME_MAX, { error: `Название длиннее ${AD_IMAGE_NAME_MAX} символов` }))
15
+ .meta({ description: "Название изображения в интерфейсе" }),
16
+ type: z.literal(AD_IMAGE_TYPES).optional().meta({ description: "Тип изображения; AUTO определяет его по размеру" })
17
+ });
18
+ export const manageAdImagesSchema = z.object({
19
+ action: z.literal(AD_IMAGE_ACTIONS).meta({ description: "Что сделать: add, get или delete (необратимо)" }),
20
+ images: z
21
+ .array(adImage)
22
+ .check(z.minLength(1, { error: "Список изображений пуст" }), z.maxLength(MAX_IMAGES_PER_CALL, {
23
+ error: `За один вызов допустимо не больше ${MAX_IMAGES_PER_CALL} изображений`
24
+ }))
25
+ .optional()
26
+ .meta({ description: "Изображения для загрузки; обязателен при action=add" }),
27
+ ad_image_hashes: z
28
+ .array(adImageHash)
29
+ .check(z.minLength(1, { error: "Список хешей пуст" }), z.maxLength(MAX_IDS_PER_CALL, { error: `За один вызов допустимо не больше ${MAX_IDS_PER_CALL} хешей` }))
30
+ .optional()
31
+ .meta({ description: "Хеши изображений: фильтр при action=get, обязателен при action=delete" }),
32
+ associated: z
33
+ .literal(ASSOCIATED_FLAGS)
34
+ .optional()
35
+ .meta({ description: "Фильтр при action=get: YES — только привязанные к объявлениям, NO — только свободные" }),
36
+ ...pageFields
37
+ });
@@ -0,0 +1 @@
1
+ export declare const manageAdImagesTool: import("#shared/lib/tool").ToolDescriptor;
@@ -0,0 +1,11 @@
1
+ import { DESTRUCTIVE, defineTool } from "#shared/lib/tool";
2
+ import { handleManageAdImages } from "./handler.js";
3
+ import { manageAdImagesSchema } from "./schema.js";
4
+ export const manageAdImagesTool = defineTool({
5
+ name: "manage_ad_images",
6
+ title: "Управление изображениями",
7
+ description: "Загрузить, получить или удалить изображения объявлений (AdImages). Для add данные передаются в base64.",
8
+ annotations: DESTRUCTIVE,
9
+ schema: manageAdImagesSchema,
10
+ handler: handleManageAdImages
11
+ });
@@ -0,0 +1,7 @@
1
+ import type { z } from "zod";
2
+ import type { createTextAdSchema, listAdsSchema, manageAdsSchema, moderateAdsSchema, updateTextAdSchema } from "./schema.js";
3
+ export declare function handleListAds(params: z.infer<typeof listAdsSchema>): Promise<string>;
4
+ export declare function handleCreateTextAd(params: z.infer<typeof createTextAdSchema>): Promise<string>;
5
+ export declare function handleUpdateTextAd(params: z.infer<typeof updateTextAdSchema>): Promise<string>;
6
+ export declare function handleManageAds(params: z.infer<typeof manageAdsSchema>): Promise<string>;
7
+ export declare function handleModerateAds(params: z.infer<typeof moderateAdsSchema>): Promise<string>;
@@ -0,0 +1,54 @@
1
+ import { apiPost } from "#shared/api/client";
2
+ import { formatResult } from "#shared/lib/format";
3
+ import { apiId, apiIds } from "#shared/lib/id";
4
+ import { buildPage } from "#shared/lib/pagination";
5
+ const LIST_FIELDS = ["Id", "CampaignId", "AdGroupId", "State", "Status"];
6
+ const TEXT_AD_FIELDS = ["Title", "Title2", "Text", "Href", "DisplayDomain"];
7
+ export async function handleListAds(params) {
8
+ const requestParams = {
9
+ SelectionCriteria: { AdGroupIds: apiIds(params.ad_group_ids) },
10
+ FieldNames: LIST_FIELDS,
11
+ TextAdFieldNames: TEXT_AD_FIELDS
12
+ };
13
+ const page = buildPage(params);
14
+ if (page)
15
+ requestParams.Page = page;
16
+ return formatResult(await apiPost("ads", "get", requestParams));
17
+ }
18
+ export async function handleCreateTextAd(params) {
19
+ const textAd = { Title: params.title, Text: params.text, Href: params.href };
20
+ if (params.title2)
21
+ textAd.Title2 = params.title2;
22
+ const data = await apiPost("ads", "add", {
23
+ Ads: [{ AdGroupId: apiId(params.ad_group_id), TextAd: textAd }]
24
+ });
25
+ return formatResult(data);
26
+ }
27
+ export async function handleUpdateTextAd(params) {
28
+ const textAd = {};
29
+ if (params.title !== undefined)
30
+ textAd.Title = params.title;
31
+ if (params.title2 !== undefined)
32
+ textAd.Title2 = params.title2;
33
+ if (params.text !== undefined)
34
+ textAd.Text = params.text;
35
+ if (params.href !== undefined)
36
+ textAd.Href = params.href;
37
+ if (Object.keys(textAd).length === 0) {
38
+ throw new Error("Нечего обновлять: укажите хотя бы одно из title/title2/text/href.");
39
+ }
40
+ const data = await apiPost("ads", "update", { Ads: [{ Id: apiId(params.ad_id), TextAd: textAd }] });
41
+ return formatResult(data);
42
+ }
43
+ export async function handleManageAds(params) {
44
+ const data = await apiPost("ads", params.action, {
45
+ SelectionCriteria: { Ids: apiIds(params.ad_ids) }
46
+ });
47
+ return formatResult(data);
48
+ }
49
+ export async function handleModerateAds(params) {
50
+ const data = await apiPost("ads", "moderate", {
51
+ SelectionCriteria: { Ids: apiIds(params.ad_ids) }
52
+ });
53
+ return formatResult(data);
54
+ }
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ export declare const listAdsSchema: z.ZodObject<{
3
+ limit: z.ZodOptional<z.ZodInt>;
4
+ offset: z.ZodOptional<z.ZodInt>;
5
+ ad_group_ids: z.ZodArray<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ export declare const createTextAdSchema: z.ZodObject<{
8
+ ad_group_id: z.ZodString;
9
+ title: z.ZodString;
10
+ title2: z.ZodOptional<z.ZodString>;
11
+ text: z.ZodString;
12
+ href: z.ZodString;
13
+ }, z.core.$strip>;
14
+ export declare const updateTextAdSchema: z.ZodObject<{
15
+ ad_id: z.ZodString;
16
+ title: z.ZodOptional<z.ZodString>;
17
+ title2: z.ZodOptional<z.ZodString>;
18
+ text: z.ZodOptional<z.ZodString>;
19
+ href: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ export declare const manageAdsSchema: z.ZodObject<{
22
+ ad_ids: z.ZodArray<z.ZodString>;
23
+ action: z.ZodLiteral<"archive" | "delete" | "moderate" | "resume" | "suspend" | "unarchive">;
24
+ }, z.core.$strip>;
25
+ export declare const moderateAdsSchema: z.ZodObject<{
26
+ ad_ids: z.ZodArray<z.ZodString>;
27
+ }, z.core.$strip>;
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+ import { AD_ACTIONS } from "#shared/config/enums";
3
+ import { AD_TEXT_LIMITS, MAX_ADS_PER_MODERATION } from "#shared/config/limits";
4
+ import { idField } from "#shared/lib/id";
5
+ import { pageFields } from "#shared/lib/pagination";
6
+ export const listAdsSchema = z.object({
7
+ ad_group_ids: z
8
+ .array(idField("ID группы объявлений"))
9
+ .check(z.minLength(1, { error: "Укажите хотя бы одну группу" }))
10
+ .meta({ description: "Группы, объявления которых нужно выбрать" }),
11
+ ...pageFields
12
+ });
13
+ export const createTextAdSchema = z.object({
14
+ ad_group_id: idField("ID группы, в которой создаётся объявление"),
15
+ title: z
16
+ .string()
17
+ .check(z.minLength(1, { error: "Заголовок не может быть пустым" }), z.maxLength(AD_TEXT_LIMITS.title, { error: `Заголовок длиннее ${AD_TEXT_LIMITS.title} символов` }))
18
+ .meta({ description: `Заголовок объявления, до ${AD_TEXT_LIMITS.title} символов` }),
19
+ title2: z
20
+ .string()
21
+ .check(z.maxLength(AD_TEXT_LIMITS.title2, { error: `Второй заголовок длиннее ${AD_TEXT_LIMITS.title2} символов` }))
22
+ .optional()
23
+ .meta({ description: `Второй заголовок, до ${AD_TEXT_LIMITS.title2} символов` }),
24
+ text: z
25
+ .string()
26
+ .check(z.minLength(1, { error: "Текст не может быть пустым" }), z.maxLength(AD_TEXT_LIMITS.text, { error: `Текст длиннее ${AD_TEXT_LIMITS.text} символов` }))
27
+ .meta({ description: `Текст объявления, до ${AD_TEXT_LIMITS.text} символов` }),
28
+ href: z
29
+ .string()
30
+ .check(z.minLength(1, { error: "Ссылка не может быть пустой" }))
31
+ .meta({ description: "Ссылка на сайт" })
32
+ });
33
+ export const updateTextAdSchema = z.object({
34
+ ad_id: idField("ID обновляемого объявления"),
35
+ title: z
36
+ .string()
37
+ .check(z.maxLength(AD_TEXT_LIMITS.title, { error: `Заголовок длиннее ${AD_TEXT_LIMITS.title} символов` }))
38
+ .optional()
39
+ .meta({ description: "Новый заголовок" }),
40
+ title2: z
41
+ .string()
42
+ .check(z.maxLength(AD_TEXT_LIMITS.title2, { error: `Второй заголовок длиннее ${AD_TEXT_LIMITS.title2} символов` }))
43
+ .optional()
44
+ .meta({ description: "Новый второй заголовок" }),
45
+ text: z
46
+ .string()
47
+ .check(z.maxLength(AD_TEXT_LIMITS.text, { error: `Текст длиннее ${AD_TEXT_LIMITS.text} символов` }))
48
+ .optional()
49
+ .meta({ description: "Новый текст объявления" }),
50
+ href: z.string().optional().meta({ description: "Новая ссылка на сайт" })
51
+ });
52
+ export const manageAdsSchema = z.object({
53
+ ad_ids: z
54
+ .array(idField("ID объявления"))
55
+ .check(z.minLength(1, { error: "Список объявлений пуст" }))
56
+ .meta({ description: "Объявления, над которыми выполняется действие" }),
57
+ action: z.literal(AD_ACTIONS).meta({
58
+ description: "Действие: suspend, resume, archive, unarchive, moderate или delete (необратимо)"
59
+ })
60
+ });
61
+ export const moderateAdsSchema = z.object({
62
+ ad_ids: z
63
+ .array(idField("ID объявления"))
64
+ .check(z.minLength(1, { error: "Список объявлений пуст" }), z.maxLength(MAX_ADS_PER_MODERATION, {
65
+ error: `За один вызов допустимо не больше ${MAX_ADS_PER_MODERATION} объявлений`
66
+ }))
67
+ .meta({ description: "Объявления, отправляемые на модерацию" })
68
+ });
@@ -0,0 +1,5 @@
1
+ export declare const listAdsTool: import("#shared/lib/tool").ToolDescriptor;
2
+ export declare const createTextAdTool: import("#shared/lib/tool").ToolDescriptor;
3
+ export declare const updateTextAdTool: import("#shared/lib/tool").ToolDescriptor;
4
+ export declare const manageAdsTool: import("#shared/lib/tool").ToolDescriptor;
5
+ export declare const moderateAdsTool: import("#shared/lib/tool").ToolDescriptor;
@@ -0,0 +1,43 @@
1
+ import { DESTRUCTIVE, defineTool, IDEMPOTENT, READ, WRITE } from "#shared/lib/tool";
2
+ import { handleCreateTextAd, handleListAds, handleManageAds, handleModerateAds, handleUpdateTextAd } from "./handler.js";
3
+ import { createTextAdSchema, listAdsSchema, manageAdsSchema, moderateAdsSchema, updateTextAdSchema } from "./schema.js";
4
+ export const listAdsTool = defineTool({
5
+ name: "list_ads",
6
+ title: "Список объявлений",
7
+ description: "Объявления в группах: заголовки, тексты, ссылки, статусы.",
8
+ annotations: READ,
9
+ schema: listAdsSchema,
10
+ handler: handleListAds
11
+ });
12
+ export const createTextAdTool = defineTool({
13
+ name: "create_text_ad",
14
+ title: "Создать объявление",
15
+ description: "Создать текстовое объявление: заголовок (≤56), второй заголовок (≤30), текст (≤81), ссылка.",
16
+ annotations: WRITE,
17
+ schema: createTextAdSchema,
18
+ handler: handleCreateTextAd
19
+ });
20
+ export const updateTextAdTool = defineTool({
21
+ name: "update_text_ad",
22
+ title: "Обновить объявление",
23
+ description: "Обновить текстовое объявление: заголовок, текст, ссылка. Изменённое объявление уходит на модерацию.",
24
+ annotations: IDEMPOTENT,
25
+ schema: updateTextAdSchema,
26
+ handler: handleUpdateTextAd
27
+ });
28
+ export const manageAdsTool = defineTool({
29
+ name: "manage_ads",
30
+ title: "Управление объявлениями",
31
+ description: "Действие над объявлениями: suspend/resume/archive/unarchive/moderate/delete. ⚠️ delete необратимо.",
32
+ annotations: DESTRUCTIVE,
33
+ schema: manageAdsSchema,
34
+ handler: handleManageAds
35
+ });
36
+ export const moderateAdsTool = defineTool({
37
+ name: "moderate_ads",
38
+ title: "Отправить объявления на модерацию",
39
+ description: "Отправить выбранные объявления на модерацию.",
40
+ annotations: IDEMPOTENT,
41
+ schema: moderateAdsSchema,
42
+ handler: handleModerateAds
43
+ });
@@ -0,0 +1,6 @@
1
+ import type { z } from "zod";
2
+ import type { listAudienceTargetsSchema, setAudienceTargetsSchema } from "./schema.js";
3
+ type Params = z.infer<typeof setAudienceTargetsSchema>;
4
+ export declare function handleListAudienceTargets(params: z.infer<typeof listAudienceTargetsSchema>): Promise<string>;
5
+ export declare function handleSetAudienceTargets(params: Params): Promise<string>;
6
+ export {};
@@ -0,0 +1,96 @@
1
+ import { apiPost } from "#shared/api/client";
2
+ import { formatResult } from "#shared/lib/format";
3
+ import { apiId, apiIds } from "#shared/lib/id";
4
+ import { buildPage } from "#shared/lib/pagination";
5
+ const LIST_FIELDS = [
6
+ "Id",
7
+ "AdGroupId",
8
+ "CampaignId",
9
+ "RetargetingListId",
10
+ "InterestId",
11
+ "ContextBid",
12
+ "StrategyPriority",
13
+ "State"
14
+ ];
15
+ export async function handleListAudienceTargets(params) {
16
+ const selection = {};
17
+ if (params.audience_target_ids?.length)
18
+ selection.Ids = apiIds(params.audience_target_ids);
19
+ if (params.ad_group_ids?.length)
20
+ selection.AdGroupIds = apiIds(params.ad_group_ids);
21
+ if (params.campaign_ids?.length)
22
+ selection.CampaignIds = apiIds(params.campaign_ids);
23
+ if (params.retargeting_list_ids?.length)
24
+ selection.RetargetingListIds = apiIds(params.retargeting_list_ids);
25
+ if (params.interest_ids?.length)
26
+ selection.InterestIds = apiIds(params.interest_ids);
27
+ if (params.states?.length)
28
+ selection.States = params.states;
29
+ // States сам по себе выборку не задаёт: Директ требует хотя бы один фильтр по ID.
30
+ if (!Object.keys(selection).some((key) => key !== "States")) {
31
+ throw new Error("Укажите хотя бы один фильтр ID для list_audience_targets.");
32
+ }
33
+ const request = { SelectionCriteria: selection, FieldNames: LIST_FIELDS };
34
+ const page = buildPage(params);
35
+ if (page)
36
+ request.Page = page;
37
+ return formatResult(await apiPost("audiencetargets", "get", request));
38
+ }
39
+ function buildTarget(target) {
40
+ const sources = [target.retargeting_list_id, target.interest_id].filter(Boolean);
41
+ if (sources.length !== 1) {
42
+ throw new Error("Каждая цель должна содержать ровно одно из retargeting_list_id/interest_id.");
43
+ }
44
+ const item = { AdGroupId: apiId(target.ad_group_id) };
45
+ if (target.retargeting_list_id)
46
+ item.RetargetingListId = apiId(target.retargeting_list_id);
47
+ if (target.interest_id)
48
+ item.InterestId = apiId(target.interest_id);
49
+ if (target.context_bid !== undefined)
50
+ item.ContextBid = target.context_bid;
51
+ if (target.strategy_priority)
52
+ item.StrategyPriority = target.strategy_priority;
53
+ return item;
54
+ }
55
+ function buildBid(bid) {
56
+ const selectors = [bid.audience_target_id, bid.ad_group_id, bid.campaign_id].filter(Boolean);
57
+ if (selectors.length !== 1) {
58
+ throw new Error("Каждая ставка должна содержать ровно один ID цели, группы или кампании.");
59
+ }
60
+ if (bid.context_bid === undefined && bid.strategy_priority === undefined) {
61
+ throw new Error("Для каждой ставки укажите context_bid и/или strategy_priority.");
62
+ }
63
+ const item = {};
64
+ if (bid.audience_target_id)
65
+ item.Id = apiId(bid.audience_target_id);
66
+ if (bid.ad_group_id)
67
+ item.AdGroupId = apiId(bid.ad_group_id);
68
+ if (bid.campaign_id)
69
+ item.CampaignId = apiId(bid.campaign_id);
70
+ if (bid.context_bid !== undefined)
71
+ item.ContextBid = bid.context_bid;
72
+ if (bid.strategy_priority)
73
+ item.StrategyPriority = bid.strategy_priority;
74
+ return item;
75
+ }
76
+ export async function handleSetAudienceTargets(params) {
77
+ if (params.action === "add") {
78
+ if (!params.targets?.length)
79
+ throw new Error("Для action=add передайте targets.");
80
+ const targets = params.targets.map(buildTarget);
81
+ return formatResult(await apiPost("audiencetargets", "add", { AudienceTargets: targets }));
82
+ }
83
+ if (params.action === "set_bids") {
84
+ if (!params.bids?.length)
85
+ throw new Error("Для action=set_bids передайте bids.");
86
+ const bids = params.bids.map(buildBid);
87
+ return formatResult(await apiPost("audiencetargets", "setBids", { Bids: bids }));
88
+ }
89
+ if (!params.audience_target_ids?.length) {
90
+ throw new Error(`Для action=${params.action} передайте audience_target_ids.`);
91
+ }
92
+ const data = await apiPost("audiencetargets", params.action, {
93
+ SelectionCriteria: { Ids: apiIds(params.audience_target_ids) }
94
+ });
95
+ return formatResult(data);
96
+ }