@attrkit/mcp 0.4.1 → 0.4.3
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.
- package/dist/cli.js +69 -24
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -14059,7 +14059,12 @@ async function callApi(config, path, options = {}) {
|
|
|
14059
14059
|
return {
|
|
14060
14060
|
ok: false,
|
|
14061
14061
|
status: 0,
|
|
14062
|
-
json: {
|
|
14062
|
+
json: {
|
|
14063
|
+
error: error instanceof Error && error.name === "AbortError" ? {
|
|
14064
|
+
code: "timeout",
|
|
14065
|
+
message: `no response within ${REQUEST_TIMEOUT_MS / 1000}s. The request may still have been applied on the server; retry with the same idempotency_key rather than a new one.`
|
|
14066
|
+
} : { code: "network_error", message: error instanceof Error ? error.message : String(error) }
|
|
14067
|
+
}
|
|
14063
14068
|
};
|
|
14064
14069
|
} finally {
|
|
14065
14070
|
clearTimeout(timer);
|
|
@@ -14071,10 +14076,12 @@ function toToolResult(result) {
|
|
|
14071
14076
|
const code = envelope?.error?.code ?? `http_${result.status}`;
|
|
14072
14077
|
const message = envelope?.error?.message ? `: ${envelope.error.message}` : "";
|
|
14073
14078
|
const retryAfter = result.status === 429 && result.retryAfter ? ` (Retry-After: ${result.retryAfter})` : "";
|
|
14079
|
+
const excerpt = !envelope?.error?.message && result.rawBody ? ` — body: ${result.rawBody.replace(/\s+/g, " ").trim().slice(0, 300)}` : "";
|
|
14080
|
+
const hint = result.status === 401 ? " Check ATTRKIT_API_KEY: this is the same error for a missing, wrong, revoked or expired key." : "";
|
|
14074
14081
|
return {
|
|
14075
14082
|
content: [{
|
|
14076
14083
|
type: "text",
|
|
14077
|
-
text: `AttrKit API error (${result.status || "network"}): ${code}${message}${retryAfter}`
|
|
14084
|
+
text: `AttrKit API error (${result.status || "network"}): ${code}${message}${retryAfter}${excerpt}${hint}`
|
|
14078
14085
|
}],
|
|
14079
14086
|
isError: true
|
|
14080
14087
|
};
|
|
@@ -14103,16 +14110,16 @@ ${body}`
|
|
|
14103
14110
|
structuredContent: structured
|
|
14104
14111
|
};
|
|
14105
14112
|
}
|
|
14106
|
-
var SERVER_VERSION = "0.4.
|
|
14113
|
+
var SERVER_VERSION = "0.4.3";
|
|
14107
14114
|
var periodSchema = z4.enum(["7d", "30d", "90d", "all"]).describe("Reporting window. Defaults to 30d.").optional();
|
|
14108
14115
|
var appIdSchema = z4.string().describe("Optional app id to scope the result to one app.").optional();
|
|
14109
14116
|
var requiredAppIdSchema = z4.string().describe("The AttrKit app id.");
|
|
14110
14117
|
var idempotencyKeySchema = z4.string().max(255).describe("Stable retry key for this exact mutation.").optional();
|
|
14111
14118
|
var ownersSchema = z4.record(z4.string(), z4.enum(["attrkit", "revenuecat", "customer"]));
|
|
14112
14119
|
var spendRowSchema = z4.object({
|
|
14113
|
-
campaign_id: z4.string().optional().describe("
|
|
14120
|
+
campaign_id: z4.string().optional().describe("The AttrKit campaign UUID, NOT the ad network's own campaign id. It is the opposite of create_campaign_link.campaign_id and is the most common mistake here: read it from list_campaigns. The API rejects a network id by name. Preferred snake_case spelling."),
|
|
14114
14121
|
campaignId: z4.string().optional().describe("Accepted camelCase alias for campaign_id."),
|
|
14115
|
-
adset_id: z4.string().optional().nullable(),
|
|
14122
|
+
adset_id: z4.string().optional().nullable().describe("Ad set id. Must be sent together with ad_id; either one alone is rejected."),
|
|
14116
14123
|
adsetId: z4.string().optional().nullable(),
|
|
14117
14124
|
ad_id: z4.string().optional().nullable(),
|
|
14118
14125
|
adId: z4.string().optional().nullable(),
|
|
@@ -14158,16 +14165,19 @@ function createServer(config, fetchImpl) {
|
|
|
14158
14165
|
const server = new McpServer({ name: "attrkit", version: SERVER_VERSION });
|
|
14159
14166
|
const call = (path, options) => callApi(config, path, { fetchImpl, ...options });
|
|
14160
14167
|
server.registerTool("whoami", {
|
|
14168
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14161
14169
|
title: "Inspect management-key scope",
|
|
14162
14170
|
description: "Return the authenticated workspace, plan, app restriction and read/write scopes.",
|
|
14163
14171
|
inputSchema: {}
|
|
14164
14172
|
}, async () => toToolResult(await call("/api/v1/whoami")));
|
|
14165
14173
|
server.registerTool("get_usage_cap", {
|
|
14174
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14166
14175
|
title: "Get the workspace usage cap",
|
|
14167
14176
|
description: "Return the workspace's monthly qualified-install cap, alert email, current billing period and usage. Requires a workspace-scoped read key.",
|
|
14168
14177
|
inputSchema: {}
|
|
14169
14178
|
}, async () => toToolResult(await call("/api/v1/workspace/usage-cap")));
|
|
14170
14179
|
server.registerTool("set_usage_cap", {
|
|
14180
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14171
14181
|
title: "Set the workspace usage cap",
|
|
14172
14182
|
description: "Set a monthly qualified-install cap of at least 10,000 and its alert email. Pass null for both values to clear the cap. Requires a workspace-scoped write key.",
|
|
14173
14183
|
inputSchema: {
|
|
@@ -14199,11 +14209,13 @@ function createServer(config, fetchImpl) {
|
|
|
14199
14209
|
}));
|
|
14200
14210
|
});
|
|
14201
14211
|
server.registerTool("list_apps", {
|
|
14212
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14202
14213
|
title: "List apps",
|
|
14203
14214
|
description: "List the iOS and Android apps in your AttrKit workspace (id, name, platform, bundle id, store id, status).",
|
|
14204
14215
|
inputSchema: {}
|
|
14205
14216
|
}, async () => toToolResult(await call("/api/v1/apps")));
|
|
14206
14217
|
server.registerTool("create_app", {
|
|
14218
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14207
14219
|
title: "Create an app",
|
|
14208
14220
|
description: "Create an iOS or Android app without the web UI. Returns the publishable key and a one-time app-scoped management key.",
|
|
14209
14221
|
inputSchema: {
|
|
@@ -14236,11 +14248,13 @@ function createServer(config, fetchImpl) {
|
|
|
14236
14248
|
}
|
|
14237
14249
|
})));
|
|
14238
14250
|
server.registerTool("get_app", {
|
|
14251
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14239
14252
|
title: "Get an app",
|
|
14240
14253
|
description: "Return one app's configuration.",
|
|
14241
14254
|
inputSchema: { app_id: requiredAppIdSchema }
|
|
14242
14255
|
}, async ({ app_id }) => toToolResult(await call(`/api/v1/apps/${encodeURIComponent(app_id)}`)));
|
|
14243
14256
|
server.registerTool("update_app", {
|
|
14257
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14244
14258
|
title: "Update an app",
|
|
14245
14259
|
description: "Update app metadata, store destination, timezone or device-matching mode.",
|
|
14246
14260
|
inputSchema: {
|
|
@@ -14275,6 +14289,7 @@ function createServer(config, fetchImpl) {
|
|
|
14275
14289
|
}
|
|
14276
14290
|
})));
|
|
14277
14291
|
server.registerTool("archive_app", {
|
|
14292
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
14278
14293
|
title: "Archive an app",
|
|
14279
14294
|
description: "Archive an app and remove it from active customer operations.",
|
|
14280
14295
|
inputSchema: { app_id: requiredAppIdSchema }
|
|
@@ -14282,11 +14297,13 @@ function createServer(config, fetchImpl) {
|
|
|
14282
14297
|
method: "DELETE"
|
|
14283
14298
|
})));
|
|
14284
14299
|
server.registerTool("get_publishable_key", {
|
|
14300
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14285
14301
|
title: "Get an app publishable key",
|
|
14286
14302
|
description: "Reveal the recoverable SDK publishable key for an app.",
|
|
14287
14303
|
inputSchema: { app_id: requiredAppIdSchema }
|
|
14288
14304
|
}, async ({ app_id }) => toToolResult(await call(`/api/v1/apps/${encodeURIComponent(app_id)}/publishable-key`)));
|
|
14289
14305
|
server.registerTool("rotate_publishable_key", {
|
|
14306
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
14290
14307
|
title: "Rotate an app publishable key",
|
|
14291
14308
|
description: "Issue a new SDK publishable key and return the old-key grace deadline.",
|
|
14292
14309
|
inputSchema: {
|
|
@@ -14295,11 +14312,13 @@ function createServer(config, fetchImpl) {
|
|
|
14295
14312
|
}
|
|
14296
14313
|
}, async ({ app_id, idempotency_key }) => toToolResult(await call(`/api/v1/apps/${encodeURIComponent(app_id)}/publishable-key`, { method: "POST", idempotencyKey: idempotency_key })));
|
|
14297
14314
|
server.registerTool("list_api_keys", {
|
|
14315
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14298
14316
|
title: "List management keys",
|
|
14299
14317
|
description: "List masked workspace and app management keys. Secret plaintext is never returned.",
|
|
14300
14318
|
inputSchema: {}
|
|
14301
14319
|
}, async () => toToolResult(await call("/api/v1/api-keys")));
|
|
14302
14320
|
server.registerTool("create_api_key", {
|
|
14321
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14303
14322
|
title: "Create a management key",
|
|
14304
14323
|
description: "Create a read-only or read/write workspace or app key. The secret is returned once.",
|
|
14305
14324
|
inputSchema: {
|
|
@@ -14314,6 +14333,7 @@ function createServer(config, fetchImpl) {
|
|
|
14314
14333
|
body: { label, scopes, app_id: app_id ?? null }
|
|
14315
14334
|
})));
|
|
14316
14335
|
server.registerTool("revoke_api_key", {
|
|
14336
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
14317
14337
|
title: "Revoke a management key",
|
|
14318
14338
|
description: "Immediately revoke a management key by id.",
|
|
14319
14339
|
inputSchema: { key_id: z4.string().uuid() }
|
|
@@ -14321,6 +14341,7 @@ function createServer(config, fetchImpl) {
|
|
|
14321
14341
|
method: "DELETE"
|
|
14322
14342
|
})));
|
|
14323
14343
|
server.registerTool("list_links", {
|
|
14344
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14324
14345
|
title: "List campaign links",
|
|
14325
14346
|
description: "List tracking links, optionally for one app.",
|
|
14326
14347
|
inputSchema: {
|
|
@@ -14336,11 +14357,13 @@ function createServer(config, fetchImpl) {
|
|
|
14336
14357
|
}
|
|
14337
14358
|
})));
|
|
14338
14359
|
server.registerTool("list_campaigns", {
|
|
14360
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14339
14361
|
title: "List campaigns",
|
|
14340
14362
|
description: "List ad campaigns with their honest profit surface: the scale/cut/hold call, profit p05/p50/p95, spend, retention, and payback. Use this to see how campaigns are performing.",
|
|
14341
14363
|
inputSchema: { app_id: appIdSchema, period: periodSchema }
|
|
14342
14364
|
}, async ({ app_id, period }) => toToolResult(await call("/api/v1/reports/campaigns", { query: { appId: app_id, period } })));
|
|
14343
14365
|
server.registerTool("list_ads", {
|
|
14366
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14344
14367
|
title: "List creative-level ad performance",
|
|
14345
14368
|
description: "Return ad and ad-set performance, evidence tiers, ROAS, CPA, CPC and modeled remainders.",
|
|
14346
14369
|
inputSchema: {
|
|
@@ -14356,6 +14379,7 @@ function createServer(config, fetchImpl) {
|
|
|
14356
14379
|
}
|
|
14357
14380
|
})));
|
|
14358
14381
|
server.registerTool("list_recent_events", {
|
|
14382
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14359
14383
|
title: "List recent events and installs",
|
|
14360
14384
|
description: "Return the same recent attribution events and installs visible on the Live dashboard.",
|
|
14361
14385
|
inputSchema: {
|
|
@@ -14369,33 +14393,35 @@ function createServer(config, fetchImpl) {
|
|
|
14369
14393
|
}
|
|
14370
14394
|
})));
|
|
14371
14395
|
server.registerTool("get_campaign_decision", {
|
|
14396
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14372
14397
|
title: "Get campaign decisions (scale / cut / hold)",
|
|
14373
14398
|
description: "Return AttrKit's profit DECISIONS for your campaigns: the scale/cut/hold call and confidence, computed by the attribution engine. Report the `call` VERBATIM — do not recompute or override it; when it says not_enough_data, say so. This is the tool to drive budget automation.",
|
|
14374
14399
|
inputSchema: { app_id: appIdSchema }
|
|
14375
14400
|
}, async ({ app_id }) => toToolResult(await call("/api/v1/decisions", { query: { appId: app_id } })));
|
|
14376
14401
|
server.registerTool("record_campaign_decision", {
|
|
14402
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14377
14403
|
title: "Record a campaign decision",
|
|
14378
14404
|
description: "Freeze a scale/cut/hold decision and its exact model inputs for later maturity evaluation.",
|
|
14379
14405
|
inputSchema: {
|
|
14380
14406
|
app_id: requiredAppIdSchema,
|
|
14381
|
-
campaign_id: z4.string(),
|
|
14382
|
-
call: z4.enum(["scale", "cut", "hold"]),
|
|
14383
|
-
actor: z4.enum(["dashboard", "auto_suggested"]).optional(),
|
|
14384
|
-
p05: z4.number(),
|
|
14385
|
-
p50: z4.number(),
|
|
14386
|
-
p95: z4.number(),
|
|
14387
|
-
spend_minor_units: z4.number().nonnegative(),
|
|
14388
|
-
currency: z4.string().length(3),
|
|
14389
|
-
band_width_pct: z4.number().nonnegative(),
|
|
14390
|
-
threshold: z4.number(),
|
|
14391
|
-
model_version: z4.string(),
|
|
14392
|
-
cost_model_version: z4.number().int().positive().nullable(),
|
|
14393
|
-
revenue_per_install_minor_units: z4.number().nonnegative().nullable(),
|
|
14407
|
+
campaign_id: z4.string().describe("The AttrKit campaign uuid, as returned by list_campaigns or get_campaign_decision. Not the ad network's own campaign id."),
|
|
14408
|
+
call: z4.enum(["scale", "cut", "hold"]).describe("The decision being frozen. Report get_campaign_decision's own call verbatim rather than forming your own."),
|
|
14409
|
+
actor: z4.enum(["dashboard", "auto_suggested"]).optional().describe("Who made the call. Use auto_suggested when an agent proposed it without a human confirming."),
|
|
14410
|
+
p05: z4.number().describe("Low end of the profit range from get_campaign_decision, in minor units. Pass through unchanged."),
|
|
14411
|
+
p50: z4.number().describe("Central profit estimate from get_campaign_decision, in minor units. Pass through unchanged."),
|
|
14412
|
+
p95: z4.number().describe("High end of the profit range from get_campaign_decision, in minor units. Pass through unchanged."),
|
|
14413
|
+
spend_minor_units: z4.number().nonnegative().describe("Spend the decision was taken against, in minor units of `currency`."),
|
|
14414
|
+
currency: z4.string().length(3).describe("ISO 4217 code for spend and revenue on this decision, e.g. USD. Three letters."),
|
|
14415
|
+
band_width_pct: z4.number().nonnegative().describe("Width of the profit band as a percentage, from get_campaign_decision. It is how the maturity check later judges whether the range was tight enough to act on."),
|
|
14416
|
+
threshold: z4.number().describe("The profit threshold the call was made against, in minor units."),
|
|
14417
|
+
model_version: z4.string().describe("Model version string from get_campaign_decision. Recorded so a later evaluation knows which model produced the range."),
|
|
14418
|
+
cost_model_version: z4.number().int().positive().nullable().describe("Cost model version from get_campaign_decision, or null when no cost model applied."),
|
|
14419
|
+
revenue_per_install_minor_units: z4.number().nonnegative().nullable().describe("Revenue per install used in the estimate, in minor units, or null when revenue was unavailable."),
|
|
14394
14420
|
revenue_per_install_quality: z4.enum([
|
|
14395
14421
|
"campaign_verified_cohort",
|
|
14396
14422
|
"app_verified_cohort_fallback",
|
|
14397
14423
|
"unavailable"
|
|
14398
|
-
]),
|
|
14424
|
+
]).describe("How that revenue figure was derived: from this campaign's own verified cohort, from the app-wide fallback, or not at all. Pass through from get_campaign_decision."),
|
|
14399
14425
|
idempotency_key: idempotencyKeySchema
|
|
14400
14426
|
}
|
|
14401
14427
|
}, async ({
|
|
@@ -14439,11 +14465,13 @@ function createServer(config, fetchImpl) {
|
|
|
14439
14465
|
}
|
|
14440
14466
|
})));
|
|
14441
14467
|
server.registerTool("get_attribution_rollup", {
|
|
14468
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14442
14469
|
title: "Get attribution rollup",
|
|
14443
14470
|
description: "Return the account-level attribution overview: installs accounted-for by evidence class (verified / device-matched / modeled / organic), MER, revenue and data freshness.",
|
|
14444
14471
|
inputSchema: { app_id: appIdSchema, period: periodSchema }
|
|
14445
14472
|
}, async ({ app_id, period }) => toToolResult(await call("/api/v1/reports/overview", { query: { appId: app_id, period } })));
|
|
14446
14473
|
server.registerTool("create_campaign_link", {
|
|
14474
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14447
14475
|
title: "Create a campaign tracking link",
|
|
14448
14476
|
description: "Create a web-to-app tracking link for an ad campaign. Requires a write-scoped API key. Returns the link id and url.",
|
|
14449
14477
|
inputSchema: {
|
|
@@ -14451,10 +14479,11 @@ function createServer(config, fetchImpl) {
|
|
|
14451
14479
|
network: z4.enum(["meta", "google", "tiktok"]).describe("The ad network delivering the campaign."),
|
|
14452
14480
|
destination_url: z4.string().url().describe("The App Store URL to send users to."),
|
|
14453
14481
|
campaign_name: z4.string().max(120).optional().describe("Optional human-readable campaign name."),
|
|
14454
|
-
campaign_id: z4.string().optional().describe("Optional external campaign id."),
|
|
14482
|
+
campaign_id: z4.string().optional().describe("Optional external campaign id. This is the AD NETWORK's own campaign id, not an AttrKit uuid; it is the opposite of import_spend.campaign_id, which requires the AttrKit one."),
|
|
14483
|
+
serve_landing: z4.boolean().optional().describe("Serve the interstitial landing bridge on this link. Defaults to true at the API. The bridge is what captures browser-side context for device matching, so turning it off narrows what can be matched."),
|
|
14455
14484
|
idempotency_key: idempotencyKeySchema
|
|
14456
14485
|
}
|
|
14457
|
-
}, async ({ app_id, network, destination_url, campaign_name, campaign_id, idempotency_key }) => toToolResult(await call("/api/v1/links", {
|
|
14486
|
+
}, async ({ app_id, network, destination_url, campaign_name, campaign_id, serve_landing, idempotency_key }) => toToolResult(await call("/api/v1/links", {
|
|
14458
14487
|
method: "POST",
|
|
14459
14488
|
idempotencyKey: idempotency_key,
|
|
14460
14489
|
body: {
|
|
@@ -14462,10 +14491,12 @@ function createServer(config, fetchImpl) {
|
|
|
14462
14491
|
network,
|
|
14463
14492
|
destinationUrl: destination_url,
|
|
14464
14493
|
...campaign_name ? { campaignName: campaign_name } : {},
|
|
14465
|
-
...campaign_id ? { campaignId: campaign_id } : {}
|
|
14494
|
+
...campaign_id ? { campaignId: campaign_id } : {},
|
|
14495
|
+
...serve_landing === undefined ? {} : { serveLanding: serve_landing }
|
|
14466
14496
|
}
|
|
14467
14497
|
})));
|
|
14468
14498
|
server.registerTool("update_link_status", {
|
|
14499
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14469
14500
|
title: "Enable or disable a campaign link",
|
|
14470
14501
|
description: "Change a tracking link between active and disabled.",
|
|
14471
14502
|
inputSchema: {
|
|
@@ -14475,6 +14506,7 @@ function createServer(config, fetchImpl) {
|
|
|
14475
14506
|
}
|
|
14476
14507
|
}, async ({ link_id, status, idempotency_key }) => toToolResult(await call(`/api/v1/links/${encodeURIComponent(link_id)}`, { method: "PATCH", idempotencyKey: idempotency_key, body: { status } })));
|
|
14477
14508
|
server.registerTool("get_spend", {
|
|
14509
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14478
14510
|
title: "Get spend and cost models",
|
|
14479
14511
|
description: "Return imported ad spend, cost models, completeness and spend freshness.",
|
|
14480
14512
|
inputSchema: { app_id: appIdSchema }
|
|
@@ -14482,6 +14514,7 @@ function createServer(config, fetchImpl) {
|
|
|
14482
14514
|
query: { appId: app_id }
|
|
14483
14515
|
})));
|
|
14484
14516
|
server.registerTool("import_spend", {
|
|
14517
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14485
14518
|
title: "Import ad spend",
|
|
14486
14519
|
description: "Import campaign or creative-level spend rows.",
|
|
14487
14520
|
inputSchema: {
|
|
@@ -14530,6 +14563,7 @@ function createServer(config, fetchImpl) {
|
|
|
14530
14563
|
}
|
|
14531
14564
|
})));
|
|
14532
14565
|
server.registerTool("set_cost_model", {
|
|
14566
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14533
14567
|
title: "Set an app cost model",
|
|
14534
14568
|
description: "Version commission, payment fees and variable COGS used in profit decisions.",
|
|
14535
14569
|
inputSchema: {
|
|
@@ -14565,6 +14599,7 @@ function createServer(config, fetchImpl) {
|
|
|
14565
14599
|
}
|
|
14566
14600
|
})));
|
|
14567
14601
|
server.registerTool("pull_network_spend", {
|
|
14602
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14568
14603
|
title: "Pull spend from an ad network",
|
|
14569
14604
|
description: "Fetch and import creative-level spend from a configured Meta, Google or TikTok connection.",
|
|
14570
14605
|
inputSchema: {
|
|
@@ -14588,18 +14623,20 @@ function createServer(config, fetchImpl) {
|
|
|
14588
14623
|
}
|
|
14589
14624
|
})));
|
|
14590
14625
|
server.registerTool("list_integrations", {
|
|
14626
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14591
14627
|
title: "List ad-network integrations",
|
|
14592
14628
|
description: "List redacted ad-network connections and their readiness.",
|
|
14593
14629
|
inputSchema: {}
|
|
14594
14630
|
}, async () => toToolResult(await call("/api/v1/integrations")));
|
|
14595
14631
|
server.registerTool("create_integration", {
|
|
14632
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14596
14633
|
title: "Create an ad-network integration",
|
|
14597
14634
|
description: "Store encrypted network credentials and configure event ownership.",
|
|
14598
14635
|
inputSchema: {
|
|
14599
14636
|
network: z4.enum(["meta", "google", "tiktok"]),
|
|
14600
14637
|
account_ref: z4.string().min(1),
|
|
14601
14638
|
credential: z4.string().min(1),
|
|
14602
|
-
owners: ownersSchema,
|
|
14639
|
+
owners: ownersSchema.describe("Which destination owns each event family. Enabling a destination requires ALL eight families to be present, or the API rejects the call."),
|
|
14603
14640
|
enable: z4.boolean().optional(),
|
|
14604
14641
|
idempotency_key: idempotencyKeySchema
|
|
14605
14642
|
}
|
|
@@ -14609,6 +14646,7 @@ function createServer(config, fetchImpl) {
|
|
|
14609
14646
|
body: { network, account_ref, credential, owners, enable: enable ?? false }
|
|
14610
14647
|
})));
|
|
14611
14648
|
server.registerTool("update_integration", {
|
|
14649
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14612
14650
|
title: "Update an ad-network integration",
|
|
14613
14651
|
description: "Rotate credentials or enable/disable an integration.",
|
|
14614
14652
|
inputSchema: {
|
|
@@ -14628,21 +14666,24 @@ function createServer(config, fetchImpl) {
|
|
|
14628
14666
|
}
|
|
14629
14667
|
})));
|
|
14630
14668
|
server.registerTool("delete_integration", {
|
|
14669
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
14631
14670
|
title: "Delete an ad-network integration",
|
|
14632
14671
|
description: "Delete a disabled integration. Enabled integrations must be disabled first.",
|
|
14633
14672
|
inputSchema: { connection_id: z4.string() }
|
|
14634
14673
|
}, async ({ connection_id }) => toToolResult(await call(`/api/v1/integrations/${encodeURIComponent(connection_id)}`, { method: "DELETE" })));
|
|
14635
14674
|
server.registerTool("get_revenuecat", {
|
|
14675
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14636
14676
|
title: "Get RevenueCat configuration",
|
|
14637
14677
|
description: "Return redacted RevenueCat status and the AttrKit webhook URL.",
|
|
14638
14678
|
inputSchema: { app_id: requiredAppIdSchema }
|
|
14639
14679
|
}, async ({ app_id }) => toToolResult(await call(`/api/v1/apps/${encodeURIComponent(app_id)}/revenuecat`)));
|
|
14640
14680
|
server.registerTool("configure_revenuecat", {
|
|
14681
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14641
14682
|
title: "Configure RevenueCat",
|
|
14642
14683
|
description: "Store the RevenueCat provider app id and encrypted authorization secret for an app.",
|
|
14643
14684
|
inputSchema: {
|
|
14644
14685
|
app_id: requiredAppIdSchema,
|
|
14645
|
-
provider_app_id: revenueCatProviderAppIdSchema,
|
|
14686
|
+
provider_app_id: revenueCatProviderAppIdSchema.describe("RevenueCat's PROJECT app id from their dashboard app settings, not the SDK key."),
|
|
14646
14687
|
authorization_secret: z4.string().min(16).max(1024),
|
|
14647
14688
|
idempotency_key: idempotencyKeySchema
|
|
14648
14689
|
}
|
|
@@ -14652,11 +14693,13 @@ function createServer(config, fetchImpl) {
|
|
|
14652
14693
|
body: { provider_app_id, authorization_secret }
|
|
14653
14694
|
})));
|
|
14654
14695
|
server.registerTool("list_webhooks", {
|
|
14696
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14655
14697
|
title: "List outbound webhooks",
|
|
14656
14698
|
description: "List redacted outbound webhook subscriptions.",
|
|
14657
14699
|
inputSchema: {}
|
|
14658
14700
|
}, async () => toToolResult(await call("/api/v1/webhooks")));
|
|
14659
14701
|
server.registerTool("create_webhook", {
|
|
14702
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
14660
14703
|
title: "Create an outbound webhook",
|
|
14661
14704
|
description: "Create an SSRF-checked webhook subscription. Returns the signing secret once.",
|
|
14662
14705
|
inputSchema: {
|
|
@@ -14677,11 +14720,13 @@ function createServer(config, fetchImpl) {
|
|
|
14677
14720
|
}
|
|
14678
14721
|
})));
|
|
14679
14722
|
server.registerTool("delete_webhook", {
|
|
14723
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
14680
14724
|
title: "Delete an outbound webhook",
|
|
14681
14725
|
description: "Delete a webhook subscription.",
|
|
14682
14726
|
inputSchema: { subscription_id: z4.string().uuid() }
|
|
14683
14727
|
}, async ({ subscription_id }) => toToolResult(await call(`/api/v1/webhooks/${encodeURIComponent(subscription_id)}`, { method: "DELETE" })));
|
|
14684
14728
|
server.registerTool("export_events", {
|
|
14729
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
14685
14730
|
title: "Export events and installs",
|
|
14686
14731
|
description: "Export one app's events and installs as CSV for an inclusive date range.",
|
|
14687
14732
|
inputSchema: {
|