openai-ads-mcp 0.1.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.
@@ -0,0 +1,227 @@
1
+ import { z } from "zod";
2
+ import { OpenAIAdsAPIError } from "./client.js";
3
+ import { badRequest, coerceList, coerceMapping, coerceStringList, extractId, getClientOrError, handleApiError, isRecord, ok, validateNonEmpty, } from "./core.js";
4
+ import { buildAdGroupBody } from "./tools/adgroups.js";
5
+ import { buildAdBody } from "./tools/ads.js";
6
+ import { buildCampaignBody } from "./tools/campaigns.js";
7
+ function parseToolError(errorText) {
8
+ try {
9
+ const parsed = JSON.parse(errorText);
10
+ return isRecord(parsed) ? parsed : { message: errorText };
11
+ }
12
+ catch {
13
+ return { message: errorText };
14
+ }
15
+ }
16
+ async function buildCampaign(args) {
17
+ const [groupPayload, groupParseError] = coerceMapping(args.ad_group, "ad_group");
18
+ if (groupParseError)
19
+ return groupParseError;
20
+ const [adPayloads, adsParseError] = coerceList(args.ads, "ads");
21
+ if (adsParseError)
22
+ return adsParseError;
23
+ if (!adPayloads?.length)
24
+ return badRequest("ads must include at least one ad.");
25
+ const [campaignBody, campaignError] = buildCampaignBody({
26
+ name: args.name,
27
+ budget_usd: args.budget_usd,
28
+ status: "paused",
29
+ confirm_budget: args.confirm_budget,
30
+ create: true,
31
+ });
32
+ if (campaignError)
33
+ return campaignError;
34
+ const { client, error } = getClientOrError();
35
+ if (error)
36
+ return error;
37
+ const created = {
38
+ campaign: null,
39
+ ad_group: null,
40
+ ads: [],
41
+ };
42
+ try {
43
+ const campaign = await client.post("/campaigns", campaignBody);
44
+ created.campaign = campaign;
45
+ const campaignId = extractId(campaign, "id", "campaign_id");
46
+ if (!campaignId) {
47
+ return ok({ created, error: { message: "Campaign was created but no id was returned." } });
48
+ }
49
+ const [adGroupBody, adGroupError] = buildAdGroupBody({
50
+ campaign_id: campaignId,
51
+ name: groupPayload?.name,
52
+ billing_event: groupPayload?.billing_event,
53
+ max_bid_usd: groupPayload?.max_bid_usd,
54
+ status: "paused",
55
+ context_hints: groupPayload?.context_hints,
56
+ create: true,
57
+ });
58
+ if (adGroupError) {
59
+ return ok({ created, error: parseToolError(adGroupError) });
60
+ }
61
+ const adGroup = await client.post("/ad_groups", adGroupBody);
62
+ created.ad_group = adGroup;
63
+ const adGroupId = extractId(adGroup, "id", "ad_group_id");
64
+ if (!adGroupId) {
65
+ return ok({ created, error: { message: "Ad group was created but no id was returned." } });
66
+ }
67
+ for (const [index, ad] of adPayloads.entries()) {
68
+ if (!isRecord(ad)) {
69
+ return ok({ created, error: { message: `ads[${index}] must be an object.` } });
70
+ }
71
+ const [adBody, adError] = buildAdBody({
72
+ ad_group_id: adGroupId,
73
+ name: ad.name ?? ad.title,
74
+ creative_type: ad.creative_type ?? "chat_card",
75
+ title: ad.title,
76
+ body: ad.body,
77
+ target_url: ad.target_url,
78
+ file_id: ad.file_id,
79
+ price: ad.price,
80
+ status: "paused",
81
+ create: true,
82
+ });
83
+ if (adError) {
84
+ return ok({ created, error: parseToolError(adError) });
85
+ }
86
+ created.ads.push(await client.post("/ads", adBody));
87
+ }
88
+ return ok({
89
+ created,
90
+ note: "Created paused. To go live, call set_campaign_state/set_ad_group_state/set_ad_state with state='activate'.",
91
+ });
92
+ }
93
+ catch (apiError) {
94
+ if (apiError instanceof OpenAIAdsAPIError && (created.campaign || created.ad_group || created.ads.length)) {
95
+ return ok({ created, error: { status_code: apiError.statusCode, message: apiError.detail } });
96
+ }
97
+ return handleApiError(apiError);
98
+ }
99
+ }
100
+ async function draftContextHints(args) {
101
+ const productError = validateNonEmpty("product", args.product, 2, 200);
102
+ if (productError)
103
+ return productError;
104
+ const [keywordValues, keywordsError] = coerceStringList(args.keywords, "keywords");
105
+ if (keywordsError)
106
+ return keywordsError;
107
+ const product = String(args.product).trim();
108
+ const audience = typeof args.audience === "string" && args.audience.trim() ? args.audience.trim() : null;
109
+ const intent = typeof args.intent === "string" && args.intent.trim() ? args.intent.trim() : null;
110
+ const bits = [`Product: ${product}`];
111
+ if (audience)
112
+ bits.push(`Audience: ${audience}`);
113
+ if (intent)
114
+ bits.push(`Intent: ${intent}`);
115
+ if (keywordValues?.length)
116
+ bits.push(`Keywords: ${keywordValues.slice(0, 12).join(", ")}`);
117
+ const base = bits.join(" | ");
118
+ const hints = [
119
+ {
120
+ context_hint: base,
121
+ rationale: "Broad enough to capture the category, narrow enough to avoid unrelated prompts.",
122
+ },
123
+ {
124
+ context_hint: `${base} | Moment: comparing options, reading recommendations, or asking what to buy`,
125
+ rationale: "Targets high-intent discovery moments where paid placement can shape a shortlist.",
126
+ },
127
+ ];
128
+ if (audience) {
129
+ hints.push({
130
+ context_hint: `Product: ${product} | Audience problem: ${audience} needs a credible solution`,
131
+ rationale: "Frames the ad around the buyer and use case rather than only the product name.",
132
+ });
133
+ }
134
+ return ok({ context_hints: hints.map((item) => item.context_hint), drafts: hints });
135
+ }
136
+ async function bulkAbTestHints(args) {
137
+ const adGroupError = validateNonEmpty("ad_group_id", args.ad_group_id);
138
+ if (adGroupError)
139
+ return adGroupError;
140
+ const [parsed, variantsError] = coerceList(args.variants, "variants");
141
+ if (variantsError)
142
+ return variantsError;
143
+ if (!parsed?.length)
144
+ return badRequest("variants must include at least one variant.");
145
+ if (parsed.length > 20)
146
+ return badRequest("Create at most 20 variants per A/B test batch.");
147
+ const { client, error } = getClientOrError();
148
+ if (error)
149
+ return error;
150
+ const created = [];
151
+ try {
152
+ for (const [index, variant] of parsed.entries()) {
153
+ if (!isRecord(variant)) {
154
+ return ok({ created, error: { message: `variants[${index}] must be an object.` } });
155
+ }
156
+ const [adBody, adError] = buildAdBody({
157
+ ad_group_id: args.ad_group_id,
158
+ name: variant.name ?? `AB test: ${String(variant.title ?? index + 1)}`,
159
+ creative_type: variant.creative_type ?? "chat_card",
160
+ title: variant.title,
161
+ body: variant.body,
162
+ target_url: variant.target_url,
163
+ file_id: variant.file_id,
164
+ price: variant.price,
165
+ status: "paused",
166
+ create: true,
167
+ });
168
+ if (adError) {
169
+ return ok({ created, error: parseToolError(adError) });
170
+ }
171
+ created.push(await client.post("/ads", adBody));
172
+ }
173
+ return ok({
174
+ created_ads: created,
175
+ ad_ids: created.map((ad) => extractId(ad, "id", "ad_id")),
176
+ note: "Created paused. Activate only the variants you are ready to test.",
177
+ });
178
+ }
179
+ catch (apiError) {
180
+ if (apiError instanceof OpenAIAdsAPIError) {
181
+ return ok({ created, error: { status_code: apiError.statusCode, message: apiError.detail } });
182
+ }
183
+ return handleApiError(apiError);
184
+ }
185
+ }
186
+ export const helperTools = [
187
+ {
188
+ name: "build_campaign",
189
+ description: "Build one paused campaign tree with one ad group and multiple paused ads, with guarded budget handling.",
190
+ inputSchema: {
191
+ name: z.string(),
192
+ budget_usd: z.number(),
193
+ ad_group: z.any(),
194
+ ads: z.any(),
195
+ confirm_budget: z.boolean().default(false),
196
+ },
197
+ argNames: ["name", "budget_usd", "ad_group", "ads", "confirm_budget"],
198
+ writes: true,
199
+ destructive: true,
200
+ openWorld: true,
201
+ handler: buildCampaign,
202
+ },
203
+ {
204
+ name: "draft_context_hints",
205
+ description: "Draft deterministic context_hints for an ad group from product, audience, intent, and keywords.",
206
+ inputSchema: {
207
+ product: z.string(),
208
+ audience: z.string().optional(),
209
+ intent: z.string().optional(),
210
+ keywords: z.any().optional(),
211
+ },
212
+ argNames: ["product", "audience", "intent", "keywords"],
213
+ handler: draftContextHints,
214
+ },
215
+ {
216
+ name: "bulk_ab_test_hints",
217
+ description: "Create multiple paused chat_card ad variants under one ad group for a clean A/B test.",
218
+ inputSchema: {
219
+ ad_group_id: z.string(),
220
+ variants: z.any(),
221
+ },
222
+ argNames: ["ad_group_id", "variants"],
223
+ writes: true,
224
+ handler: bulkAbTestHints,
225
+ },
226
+ ];
227
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { type AdsToolDefinition } from "./core.js";
4
+ export declare const allToolDefinitions: AdsToolDefinition[];
5
+ export declare function registeredToolDefinitions(): AdsToolDefinition[];
6
+ export declare function registeredToolMetadata(): Array<{
7
+ name: string;
8
+ args: string[];
9
+ }>;
10
+ export declare function createOpenAIAdsMcpServer(): McpServer;
11
+ export declare function main(): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import { pathToFileURL } from "node:url";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { INSTRUCTIONS, isReadonlyMode, registerAdsTool } from "./core.js";
6
+ import { helperTools } from "./helpers.js";
7
+ import { registerTrakkrVisibilityResource } from "./resource_trakkr.js";
8
+ import { adGroupTools } from "./tools/adgroups.js";
9
+ import { adTools } from "./tools/ads.js";
10
+ import { accountTools } from "./tools/account.js";
11
+ import { audienceTools } from "./tools/audiences.js";
12
+ import { campaignTools } from "./tools/campaigns.js";
13
+ import { conversionTools } from "./tools/conversions.js";
14
+ import { insightTools } from "./tools/insights.js";
15
+ export const allToolDefinitions = [
16
+ ...accountTools,
17
+ ...campaignTools,
18
+ ...adGroupTools,
19
+ ...adTools,
20
+ ...insightTools,
21
+ ...audienceTools,
22
+ ...conversionTools,
23
+ ...helperTools,
24
+ ];
25
+ export function registeredToolDefinitions() {
26
+ return allToolDefinitions.filter((tool) => !(tool.writes && isReadonlyMode()));
27
+ }
28
+ export function registeredToolMetadata() {
29
+ return registeredToolDefinitions().map((tool) => ({ name: tool.name, args: [...tool.argNames] }));
30
+ }
31
+ export function createOpenAIAdsMcpServer() {
32
+ const server = new McpServer({
33
+ name: "OpenAI Ads",
34
+ version: "0.1.0",
35
+ }, {
36
+ instructions: INSTRUCTIONS,
37
+ });
38
+ registerTrakkrVisibilityResource(server);
39
+ for (const tool of allToolDefinitions) {
40
+ registerAdsTool(server, tool);
41
+ }
42
+ return server;
43
+ }
44
+ export async function main() {
45
+ const server = createOpenAIAdsMcpServer();
46
+ await server.connect(new StdioServerTransport());
47
+ }
48
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
49
+ main().catch((error) => {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ console.error(`openai-ads-mcp failed to start: ${message}`);
52
+ process.exitCode = 1;
53
+ });
54
+ }
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAA0B,MAAM,WAAW,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAwB;IACrD,GAAG,YAAY;IACf,GAAG,aAAa;IAChB,GAAG,YAAY;IACf,GAAG,OAAO;IACV,GAAG,YAAY;IACf,GAAG,aAAa;IAChB,GAAG,eAAe;IAClB,GAAG,WAAW;CACf,CAAC;AAEF,MAAM,UAAU,yBAAyB;IACvC,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,yBAAyB,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE,YAAY;KAC3B,CACF,CAAC;IACF,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;QACtC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;IAC1C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/E,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare const TRAKKR_VISIBILITY_URI = "openai-ads://trakkr-visibility";
3
+ export declare const TRAKKR_VISIBILITY_BRIEFING: string;
4
+ export declare function registerTrakkrVisibilityResource(server: McpServer): void;
@@ -0,0 +1,28 @@
1
+ export const TRAKKR_VISIBILITY_URI = "openai-ads://trakkr-visibility";
2
+ export const TRAKKR_VISIBILITY_BRIEFING = "# Paid and organic AI visibility\n\n" +
3
+ "OpenAI Ads helps you buy visibility inside ChatGPT. That answers one " +
4
+ "question: where can you place paid messages?\n\n" +
5
+ "Trakkr answers the other half: where does your brand already appear " +
6
+ "organically across ChatGPT, Perplexity, Gemini, Claude, Google AI " +
7
+ "Overviews, Reddit, and citations?\n\n" +
8
+ "Use both views together:\n\n" +
9
+ "1. Pull Ads insights to see paid impressions, clicks, spend, and conversions.\n" +
10
+ "2. Track organic AI visibility to see which prompts, competitors, and citations already shape the market.\n" +
11
+ "3. Use the gap between the two to decide where paid coverage is worth buying.\n\n" +
12
+ "Learn more at https://trakkr.ai.";
13
+ export function registerTrakkrVisibilityResource(server) {
14
+ server.registerResource("Trakkr AI visibility briefing", TRAKKR_VISIBILITY_URI, {
15
+ title: "Paid and organic AI visibility",
16
+ description: "A short paste-ready briefing on connecting ChatGPT ad placements with organic AI visibility tracking.",
17
+ mimeType: "text/markdown",
18
+ }, async (uri) => ({
19
+ contents: [
20
+ {
21
+ uri: uri.href,
22
+ mimeType: "text/markdown",
23
+ text: TRAKKR_VISIBILITY_BRIEFING,
24
+ },
25
+ ],
26
+ }));
27
+ }
28
+ //# sourceMappingURL=resource_trakkr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource_trakkr.js","sourceRoot":"","sources":["../src/resource_trakkr.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAAG,gCAAgC,CAAC;AAEtE,MAAM,CAAC,MAAM,0BAA0B,GACrC,sCAAsC;IACtC,uEAAuE;IACvE,kDAAkD;IAClD,sEAAsE;IACtE,oEAAoE;IACpE,uCAAuC;IACvC,8BAA8B;IAC9B,iFAAiF;IACjF,6GAA6G;IAC7G,mFAAmF;IACnF,kCAAkC,CAAC;AAErC,MAAM,UAAU,gCAAgC,CAAC,MAAiB;IAChE,MAAM,CAAC,gBAAgB,CACrB,+BAA+B,EAC/B,qBAAqB,EACrB;QACE,KAAK,EAAE,gCAAgC;QACvC,WAAW,EAAE,uGAAuG;QACpH,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,GAAG,CAAC,IAAI;gBACb,QAAQ,EAAE,eAAe;gBACzB,IAAI,EAAE,0BAA0B;aACjC;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type AdsToolDefinition } from "../core.js";
2
+ export declare function getAccount(): Promise<string>;
3
+ export declare const accountTools: AdsToolDefinition[];
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import { getClientOrError, handleApiError, ok } from "../core.js";
3
+ export async function getAccount() {
4
+ const { client, error } = getClientOrError();
5
+ if (error)
6
+ return error;
7
+ try {
8
+ return ok(await client.get("/ad_account"));
9
+ }
10
+ catch (apiError) {
11
+ return handleApiError(apiError);
12
+ }
13
+ }
14
+ export const accountTools = [
15
+ {
16
+ name: "get_account",
17
+ description: "Get the authenticated OpenAI Ads account. Use this first to verify that OPENAI_ADS_API_KEY works and to read account id, name, timezone, currency, and settings.",
18
+ inputSchema: {},
19
+ argNames: [],
20
+ handler: () => getAccount(),
21
+ },
22
+ ];
23
+ void z;
24
+ //# sourceMappingURL=account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/tools/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,EAAE,EAA0B,MAAM,YAAY,CAAC;AAE1F,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC7C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,MAAM,MAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,QAAQ,EAAE,CAAC;QAClB,OAAO,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAwB;IAC/C;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,kKAAkK;QACpK,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;KAC5B;CACF,CAAC;AAEF,KAAK,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type AdsToolDefinition, type JsonRecord } from "../core.js";
2
+ export declare function buildAdGroupBody(input: {
3
+ campaign_id?: unknown;
4
+ name?: unknown;
5
+ status?: string;
6
+ billing_event?: string;
7
+ max_bid_usd?: unknown;
8
+ context_hints?: unknown;
9
+ create?: boolean;
10
+ }): [JsonRecord | null, string | null];
11
+ export declare const adGroupTools: AdsToolDefinition[];
@@ -0,0 +1,205 @@
1
+ import { z } from "zod";
2
+ import { badRequest, coerceStringList, getClientOrError, handleApiError, ok, optionalParams, usdToMicros, validateFloatRange, validateIntRange, validateNonEmpty, validateOption, } from "../core.js";
3
+ const AD_GROUP_STATES = new Set(["activate", "pause", "archive"]);
4
+ const AD_GROUP_STATUSES = new Set(["active", "paused", "archived"]);
5
+ const BILLING_EVENTS = new Set(["impression", "click"]);
6
+ export function buildAdGroupBody(input) {
7
+ const body = {};
8
+ const create = input.create === true;
9
+ if (create) {
10
+ const campaignError = validateNonEmpty("campaign_id", input.campaign_id);
11
+ if (campaignError)
12
+ return [null, campaignError];
13
+ body.campaign_id = input.campaign_id;
14
+ }
15
+ if (input.name !== undefined && input.name !== null) {
16
+ const nameError = validateNonEmpty("name", input.name, 3, 1000);
17
+ if (nameError)
18
+ return [null, nameError];
19
+ body.name = String(input.name).trim();
20
+ }
21
+ else if (create) {
22
+ return [null, badRequest("name is required.")];
23
+ }
24
+ const status = input.status ?? (create ? "paused" : undefined);
25
+ if (status !== undefined) {
26
+ if (!AD_GROUP_STATUSES.has(status))
27
+ return [null, badRequest("status must be active, paused, or archived.")];
28
+ if (create && status !== "paused") {
29
+ return [null, badRequest("Create tools only create paused ad groups. Use set_ad_group_state after review.")];
30
+ }
31
+ body.status = status;
32
+ }
33
+ if (input.billing_event !== undefined || input.max_bid_usd !== undefined) {
34
+ if (input.billing_event === undefined || input.max_bid_usd === undefined) {
35
+ return [null, badRequest("billing_event and max_bid_usd must be provided together.")];
36
+ }
37
+ if (!BILLING_EVENTS.has(input.billing_event))
38
+ return [null, badRequest("billing_event must be impression or click.")];
39
+ const bid = Number(input.max_bid_usd);
40
+ const bidError = validateFloatRange("max_bid_usd", bid, 0.000001, 100);
41
+ if (bidError)
42
+ return [null, bidError];
43
+ body.bidding_config = { billing_event_type: input.billing_event, max_bid_micros: usdToMicros(bid) };
44
+ }
45
+ else if (create) {
46
+ return [null, badRequest("billing_event and max_bid_usd are required.")];
47
+ }
48
+ if (input.context_hints !== undefined) {
49
+ const [hints, hintsError] = coerceStringList(input.context_hints, "context_hints");
50
+ if (hintsError)
51
+ return [null, hintsError];
52
+ body.context_hints = hints;
53
+ }
54
+ if (!Object.keys(body).length)
55
+ return [null, badRequest("Provide at least one field to update.")];
56
+ return [body, null];
57
+ }
58
+ async function listAdGroups(args) {
59
+ const limit = Number(args.limit ?? 20);
60
+ const limitError = validateIntRange("limit", limit, 1, 500);
61
+ if (limitError)
62
+ return limitError;
63
+ const { client, error } = getClientOrError();
64
+ if (error)
65
+ return error;
66
+ try {
67
+ return ok(await client.get("/ad_groups", optionalParams({
68
+ campaign_id: args.campaign_id,
69
+ limit,
70
+ after: args.after,
71
+ before: args.before,
72
+ order: args.order ?? "desc",
73
+ })));
74
+ }
75
+ catch (apiError) {
76
+ return handleApiError(apiError);
77
+ }
78
+ }
79
+ async function getAdGroup(args) {
80
+ const adGroupError = validateNonEmpty("ad_group_id", args.ad_group_id);
81
+ if (adGroupError)
82
+ return adGroupError;
83
+ const { client, error } = getClientOrError();
84
+ if (error)
85
+ return error;
86
+ try {
87
+ return ok(await client.get(`/ad_groups/${args.ad_group_id}`));
88
+ }
89
+ catch (apiError) {
90
+ return handleApiError(apiError);
91
+ }
92
+ }
93
+ async function createAdGroup(args) {
94
+ const [body, bodyError] = buildAdGroupBody({ ...args, status: String(args.status ?? "paused"), create: true });
95
+ if (bodyError)
96
+ return bodyError;
97
+ const { client, error } = getClientOrError();
98
+ if (error)
99
+ return error;
100
+ try {
101
+ return ok(await client.post("/ad_groups", body));
102
+ }
103
+ catch (apiError) {
104
+ return handleApiError(apiError);
105
+ }
106
+ }
107
+ async function updateAdGroup(args) {
108
+ const adGroupError = validateNonEmpty("ad_group_id", args.ad_group_id);
109
+ if (adGroupError)
110
+ return adGroupError;
111
+ const [body, bodyError] = buildAdGroupBody(args);
112
+ if (bodyError)
113
+ return bodyError;
114
+ const { client, error } = getClientOrError();
115
+ if (error)
116
+ return error;
117
+ try {
118
+ return ok(await client.post(`/ad_groups/${args.ad_group_id}`, body));
119
+ }
120
+ catch (apiError) {
121
+ return handleApiError(apiError);
122
+ }
123
+ }
124
+ async function setAdGroupState(args) {
125
+ const adGroupError = validateNonEmpty("ad_group_id", args.ad_group_id);
126
+ if (adGroupError)
127
+ return adGroupError;
128
+ const state = String(args.state);
129
+ const stateError = validateOption("state", state, AD_GROUP_STATES);
130
+ if (stateError)
131
+ return stateError;
132
+ const { client, error } = getClientOrError();
133
+ if (error)
134
+ return error;
135
+ try {
136
+ return ok(await client.post(`/ad_groups/${args.ad_group_id}/${state}`));
137
+ }
138
+ catch (apiError) {
139
+ return handleApiError(apiError);
140
+ }
141
+ }
142
+ const orderSchema = z.enum(["asc", "desc"]).default("desc");
143
+ export const adGroupTools = [
144
+ {
145
+ name: "list_ad_groups",
146
+ description: "List ad groups, optionally filtered to a campaign.",
147
+ inputSchema: {
148
+ campaign_id: z.string().optional(),
149
+ limit: z.number().int().default(20),
150
+ after: z.string().optional(),
151
+ before: z.string().optional(),
152
+ order: orderSchema,
153
+ },
154
+ argNames: ["campaign_id", "limit", "after", "before", "order"],
155
+ handler: listAdGroups,
156
+ },
157
+ {
158
+ name: "get_ad_group",
159
+ description: "Get one ad group by id.",
160
+ inputSchema: { ad_group_id: z.string() },
161
+ argNames: ["ad_group_id"],
162
+ handler: getAdGroup,
163
+ },
164
+ {
165
+ name: "create_ad_group",
166
+ description: "Create a paused ad group under a campaign with bid config and optional context hints.",
167
+ inputSchema: {
168
+ campaign_id: z.string(),
169
+ name: z.string(),
170
+ billing_event: z.enum(["impression", "click"]),
171
+ max_bid_usd: z.number(),
172
+ status: z.enum(["paused", "active"]).default("paused"),
173
+ context_hints: z.any().optional(),
174
+ },
175
+ argNames: ["campaign_id", "name", "billing_event", "max_bid_usd", "status", "context_hints"],
176
+ writes: true,
177
+ handler: createAdGroup,
178
+ },
179
+ {
180
+ name: "update_ad_group",
181
+ description: "Update ad group fields, including bid config and context hints.",
182
+ inputSchema: {
183
+ ad_group_id: z.string(),
184
+ name: z.string().optional(),
185
+ billing_event: z.enum(["impression", "click"]).optional(),
186
+ max_bid_usd: z.number().optional(),
187
+ status: z.enum(["active", "paused", "archived"]).optional(),
188
+ context_hints: z.any().optional(),
189
+ },
190
+ argNames: ["ad_group_id", "name", "billing_event", "max_bid_usd", "status", "context_hints"],
191
+ writes: true,
192
+ handler: updateAdGroup,
193
+ },
194
+ {
195
+ name: "set_ad_group_state",
196
+ description: "Activate, pause, or archive an ad group. Activation can start delivery when parent and child layers are active.",
197
+ inputSchema: { ad_group_id: z.string(), state: z.enum(["activate", "pause", "archive"]) },
198
+ argNames: ["ad_group_id", "state"],
199
+ writes: true,
200
+ destructive: true,
201
+ openWorld: true,
202
+ handler: setAdGroupState,
203
+ },
204
+ ];
205
+ //# sourceMappingURL=adgroups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adgroups.js","sourceRoot":"","sources":["../../src/tools/adgroups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type AdsToolDefinition, type JsonRecord } from "../core.js";
2
+ export declare function buildCreative(input: {
3
+ creative_type?: unknown;
4
+ title?: unknown;
5
+ body?: unknown;
6
+ target_url?: unknown;
7
+ file_id?: unknown;
8
+ price?: unknown;
9
+ create?: boolean;
10
+ }): [JsonRecord | null, string | null];
11
+ export declare function buildAdBody(input: {
12
+ ad_group_id?: unknown;
13
+ name?: unknown;
14
+ creative_type?: unknown;
15
+ title?: unknown;
16
+ body?: unknown;
17
+ target_url?: unknown;
18
+ file_id?: unknown;
19
+ price?: unknown;
20
+ status?: string;
21
+ create?: boolean;
22
+ }): [JsonRecord | null, string | null];
23
+ export declare const adTools: AdsToolDefinition[];