@kaminari-ad/mcp 0.9.0 → 0.10.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.
- package/CHANGELOG.md +50 -0
- package/dist/bin.js +3 -3
- package/dist/{chunk-E66U4JXR.js → chunk-5UVZYMC3.js} +124 -46
- package/dist/chunk-5UVZYMC3.js.map +1 -0
- package/dist/{chunk-SWFPWJ74.js → chunk-KFVVS55N.js} +3 -3
- package/dist/{chunk-SWFPWJ74.js.map → chunk-KFVVS55N.js.map} +1 -1
- package/dist/{http-bootstrap-ZXECSCYN.js → http-bootstrap-3MGAQHND.js} +4 -4
- package/dist/{http-bootstrap-ZXECSCYN.js.map → http-bootstrap-3MGAQHND.js.map} +1 -1
- package/dist/{stdio-bootstrap-6DXIUJTV.js → stdio-bootstrap-7EXISZ66.js} +4 -4
- package/dist/{stdio-bootstrap-6DXIUJTV.js.map → stdio-bootstrap-7EXISZ66.js.map} +1 -1
- package/package.json +20 -14
- package/dist/chunk-E66U4JXR.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.10.0] - 2026-07-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Repeats and retries.** `create_scan`, `create_bulk_scans`,
|
|
15
|
+
`create_campaign`, and `update_campaign` accept `repeat_count` (1-20),
|
|
16
|
+
`repeat_mode` (`isolated` | `shared`), and `retry_max_attempts` (0-5).
|
|
17
|
+
`repeat_count` multiplies the scans created — and billed — per
|
|
18
|
+
`url x country x device` combination; `shared` runs a combination's repeats
|
|
19
|
+
in one browser behind one IP with cookies carried over (rejected with 422
|
|
20
|
+
together with ad discovery); `retry_max_attempts` re-crawls the same scan
|
|
21
|
+
after a transient failure without billing twice.
|
|
22
|
+
- **Repeat / retry fields on the read side.** Scan detail surfaces
|
|
23
|
+
`repeat_index`, `repeat_total`, `repeat_session_id`, `repeat_scan_ids`,
|
|
24
|
+
`retry_attempt`, and `retry_max_attempts`; the scan-list brief carries all of
|
|
25
|
+
those except `repeat_scan_ids`; campaign responses echo `repeat_count`,
|
|
26
|
+
`repeat_mode`, and `retry_max_attempts`.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **`list_balance_history` can filter on `card_top_up`.** The API has emitted
|
|
31
|
+
that transaction type for a while — an unfiltered call already returned the
|
|
32
|
+
rows — but the tool's own enum stopped at `crypto_top_up`, so
|
|
33
|
+
`type: ["card_top_up"]` was rejected locally and never reached the API. The
|
|
34
|
+
filter's length cap was one short for the same reason.
|
|
35
|
+
`BalanceTransactionType` is now aliased off the generated schema instead of
|
|
36
|
+
hand-mirrored, so the next regen turns a new value into a compile error.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Regenerated the OpenAPI type + zod-schema snapshots against `/api/v1`
|
|
41
|
+
v1.27.0. Besides the repeat / retry fields this picks up the
|
|
42
|
+
`creative-html` / `creative-video` / `vast-xml` artifact endpoints,
|
|
43
|
+
`video.click_through`, `creative_kind` as an enum, `tag_visibility` on custom
|
|
44
|
+
rules, the `card_top_up` balance-transaction type, and the `tag_match` scan
|
|
45
|
+
filter.
|
|
46
|
+
- `creative_kind` is surfaced as an open string rather than the regenerated
|
|
47
|
+
`banner | video` enum, following the same forward-compat policy as
|
|
48
|
+
`block_reason`. A creative kind added on the API side now degrades that one
|
|
49
|
+
field instead of failing the entire `get_scan` / `create_scan` /
|
|
50
|
+
`create_bulk_scans` response until an MCP release ships.
|
|
51
|
+
- `get_scan_screenshot` and `get_scan_landing_screenshot` warn that a resized
|
|
52
|
+
capture is top-cropped past 2.5x its width, and to omit `width` when the
|
|
53
|
+
whole page matters. `get_scan_creative_screenshot` never crops and is
|
|
54
|
+
unchanged.
|
|
55
|
+
- `get_campaign` and `list_campaigns` describe the repeat / retry settings they
|
|
56
|
+
echo, `list_scan_children` explains why those fields are always neutral on a
|
|
57
|
+
discovered-ad child, and `get_scan` documents the creative's `click_through`
|
|
58
|
+
destination.
|
|
59
|
+
|
|
10
60
|
## [0.8.0] - 2026-07-10
|
|
11
61
|
|
|
12
62
|
### Added
|
package/dist/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { NAME, VERSION, err, ok } from './chunk-
|
|
2
|
+
import { NAME, VERSION, err, ok } from './chunk-KFVVS55N.js';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
@@ -160,10 +160,10 @@ async function main() {
|
|
|
160
160
|
}
|
|
161
161
|
const config = configResult.value;
|
|
162
162
|
if (config.transport === "stdio") {
|
|
163
|
-
const { bootstrapStdio } = await import('./stdio-bootstrap-
|
|
163
|
+
const { bootstrapStdio } = await import('./stdio-bootstrap-7EXISZ66.js');
|
|
164
164
|
return bootstrapStdio(config);
|
|
165
165
|
}
|
|
166
|
-
const { bootstrapHttp } = await import('./http-bootstrap-
|
|
166
|
+
const { bootstrapHttp } = await import('./http-bootstrap-3MGAQHND.js');
|
|
167
167
|
return bootstrapHttp(config);
|
|
168
168
|
}
|
|
169
169
|
main().then(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { err, ok } from './chunk-
|
|
2
|
+
import { err, ok } from './chunk-KFVVS55N.js';
|
|
3
3
|
import { createHash, randomUUID } from 'crypto';
|
|
4
4
|
import createClient from 'openapi-fetch';
|
|
5
5
|
import { fetch } from 'undici';
|
|
@@ -240,6 +240,7 @@ var ProxyTargetRequest = z.object({
|
|
|
240
240
|
city: z.string().default(""),
|
|
241
241
|
isp: z.string().default("")
|
|
242
242
|
}).partial().passthrough();
|
|
243
|
+
var RepeatModeType = z.enum(["isolated", "shared"]);
|
|
243
244
|
z.object({
|
|
244
245
|
url: z.union([z.string(), z.null()]).optional(),
|
|
245
246
|
ad_tag: z.union([z.string(), z.null()]).optional(),
|
|
@@ -250,7 +251,10 @@ z.object({
|
|
|
250
251
|
labels: z.record(z.string()).optional(),
|
|
251
252
|
campaign_id: z.union([z.string(), z.null()]).optional(),
|
|
252
253
|
run_id: z.union([z.string(), z.null()]).optional(),
|
|
253
|
-
ad_discovery: z.boolean().optional().default(false)
|
|
254
|
+
ad_discovery: z.boolean().optional().default(false),
|
|
255
|
+
repeat_count: z.number().int().gte(1).optional().default(1),
|
|
256
|
+
repeat_mode: RepeatModeType.optional(),
|
|
257
|
+
retry_max_attempts: z.number().int().gte(0).optional().default(0)
|
|
254
258
|
}).passthrough();
|
|
255
259
|
var ScanStatus = z.enum([
|
|
256
260
|
"pending",
|
|
@@ -290,7 +294,8 @@ var VideoMetaResponse = z.object({
|
|
|
290
294
|
vast_version: z.string().default(""),
|
|
291
295
|
ad_system: z.string().default(""),
|
|
292
296
|
is_vpaid: z.boolean().default(false),
|
|
293
|
-
wrapper_depth: z.number().int().default(0)
|
|
297
|
+
wrapper_depth: z.number().int().default(0),
|
|
298
|
+
click_through: z.string().default("")
|
|
294
299
|
}).partial().passthrough();
|
|
295
300
|
var ProxyTargetResponse = z.object({
|
|
296
301
|
proxy_type: z.string(),
|
|
@@ -357,8 +362,11 @@ var ScanResponse = z.object({
|
|
|
357
362
|
public_report_url: z.string().optional().default(""),
|
|
358
363
|
ad_tag: z.union([z.string(), z.null()]).optional(),
|
|
359
364
|
vast_tag: z.union([z.string(), z.null()]).optional(),
|
|
360
|
-
creative_kind: z.
|
|
365
|
+
creative_kind: z.enum(["banner", "video"]).optional().default("banner"),
|
|
361
366
|
creative_screenshot_url: z.string().optional().default(""),
|
|
367
|
+
creative_video_url: z.string().optional().default(""),
|
|
368
|
+
vast_xml_url: z.string().optional().default(""),
|
|
369
|
+
creative_html_url: z.string().optional().default(""),
|
|
362
370
|
creative_width: z.number().int().optional().default(0),
|
|
363
371
|
creative_height: z.number().int().optional().default(0),
|
|
364
372
|
video: z.union([VideoMetaResponse, z.null()]).optional(),
|
|
@@ -374,7 +382,13 @@ var ScanResponse = z.object({
|
|
|
374
382
|
campaign_group_name: z.union([z.string(), z.null()]).optional(),
|
|
375
383
|
created_at: z.string().datetime({ offset: true }),
|
|
376
384
|
completed_at: z.union([z.string(), z.null()]),
|
|
377
|
-
landings: z.array(LandingResponse).optional()
|
|
385
|
+
landings: z.array(LandingResponse).optional(),
|
|
386
|
+
repeat_index: z.number().int().optional().default(0),
|
|
387
|
+
repeat_total: z.number().int().optional().default(1),
|
|
388
|
+
repeat_session_id: z.union([z.string(), z.null()]).optional(),
|
|
389
|
+
repeat_scan_ids: z.array(z.string().uuid()).optional(),
|
|
390
|
+
retry_attempt: z.number().int().optional().default(0),
|
|
391
|
+
retry_max_attempts: z.number().int().optional().default(0)
|
|
378
392
|
}).passthrough();
|
|
379
393
|
z.union([z.string(), z.null()]).optional();
|
|
380
394
|
var ScanBriefResponse = z.object({
|
|
@@ -401,7 +415,12 @@ var ScanBriefResponse = z.object({
|
|
|
401
415
|
ad_kind: z.union([z.string(), z.null()]).optional(),
|
|
402
416
|
network: z.string().optional().default(""),
|
|
403
417
|
emulator_display_name: z.string().optional().default(""),
|
|
404
|
-
emulator_category: z.string().optional().default("")
|
|
418
|
+
emulator_category: z.string().optional().default(""),
|
|
419
|
+
repeat_index: z.number().int().optional().default(0),
|
|
420
|
+
repeat_total: z.number().int().optional().default(1),
|
|
421
|
+
repeat_session_id: z.union([z.string(), z.null()]).optional(),
|
|
422
|
+
retry_attempt: z.number().int().optional().default(0),
|
|
423
|
+
retry_max_attempts: z.number().int().optional().default(0)
|
|
405
424
|
}).passthrough();
|
|
406
425
|
z.object({
|
|
407
426
|
items: z.array(ScanBriefResponse),
|
|
@@ -417,7 +436,10 @@ z.object({
|
|
|
417
436
|
country_codes: z.array(z.string()).min(1),
|
|
418
437
|
emulator_id: z.string().min(1).max(100),
|
|
419
438
|
proxy: ProxyTargetRequest.optional(),
|
|
420
|
-
labels: z.record(z.string()).optional()
|
|
439
|
+
labels: z.record(z.string()).optional(),
|
|
440
|
+
repeat_count: z.number().int().gte(1).optional().default(1),
|
|
441
|
+
repeat_mode: RepeatModeType.optional(),
|
|
442
|
+
retry_max_attempts: z.number().int().gte(0).optional().default(0)
|
|
421
443
|
}).passthrough();
|
|
422
444
|
z.object({
|
|
423
445
|
scope_type: z.enum(["last_n", "hours"]),
|
|
@@ -461,6 +483,7 @@ var GroupActionResponse = z.object({
|
|
|
461
483
|
run_ids: z.array(z.string().uuid()).optional(),
|
|
462
484
|
failures: z.array(BulkCampaignFailure).optional()
|
|
463
485
|
}).passthrough();
|
|
486
|
+
var RepeatMode = z.enum(["isolated", "shared"]);
|
|
464
487
|
z.object({
|
|
465
488
|
name: z.string().min(1).max(200),
|
|
466
489
|
campaign_type: z.string().optional().default("url"),
|
|
@@ -476,6 +499,9 @@ z.object({
|
|
|
476
499
|
proxy_region: z.string().optional().default(""),
|
|
477
500
|
proxy_city: z.string().optional().default(""),
|
|
478
501
|
proxy_isp: z.string().optional().default(""),
|
|
502
|
+
repeat_count: z.number().int().gte(1).optional().default(1),
|
|
503
|
+
repeat_mode: RepeatMode.optional(),
|
|
504
|
+
retry_max_attempts: z.number().int().gte(0).optional().default(0),
|
|
479
505
|
labels: z.record(z.string()).optional(),
|
|
480
506
|
policy_set_id: z.union([z.string(), z.null()]).optional(),
|
|
481
507
|
schedule_type: z.union([z.string(), z.null()]).optional(),
|
|
@@ -503,6 +529,9 @@ var CampaignResponse = z.object({
|
|
|
503
529
|
proxy_region: z.string().optional().default(""),
|
|
504
530
|
proxy_city: z.string().optional().default(""),
|
|
505
531
|
proxy_isp: z.string().optional().default(""),
|
|
532
|
+
repeat_count: z.number().int().optional().default(1),
|
|
533
|
+
repeat_mode: RepeatMode.optional(),
|
|
534
|
+
retry_max_attempts: z.number().int().optional().default(0),
|
|
506
535
|
schedule_type: z.union([z.string(), z.null()]).optional(),
|
|
507
536
|
schedule_weekly: z.union([z.record(z.array(z.number().int())), z.null()]).optional(),
|
|
508
537
|
schedule_interval_seconds: z.union([z.number(), z.null()]).optional(),
|
|
@@ -542,6 +571,9 @@ z.object({
|
|
|
542
571
|
proxy_region: z.union([z.string(), z.null()]),
|
|
543
572
|
proxy_city: z.union([z.string(), z.null()]),
|
|
544
573
|
proxy_isp: z.union([z.string(), z.null()]),
|
|
574
|
+
repeat_count: z.union([z.number(), z.null()]),
|
|
575
|
+
repeat_mode: z.union([RepeatMode, z.null()]),
|
|
576
|
+
retry_max_attempts: z.union([z.number(), z.null()]),
|
|
545
577
|
labels: z.union([z.record(z.string()), z.null()]),
|
|
546
578
|
policy_set_id: z.union([z.string(), z.null()]),
|
|
547
579
|
schedule_type: z.union([z.string(), z.null()]),
|
|
@@ -649,7 +681,8 @@ z.object({
|
|
|
649
681
|
tag_slug: z.string().max(100).optional().default(""),
|
|
650
682
|
rule_type: z.string().max(50),
|
|
651
683
|
config: z.object({}).partial().passthrough(),
|
|
652
|
-
target: z.string().max(30).optional().default("page")
|
|
684
|
+
target: z.string().max(30).optional().default("page"),
|
|
685
|
+
tag_visibility: z.union([z.record(TagVisibility), z.null()]).optional()
|
|
653
686
|
}).passthrough();
|
|
654
687
|
var CustomRuleResponse = z.object({
|
|
655
688
|
id: z.string().uuid(),
|
|
@@ -661,7 +694,8 @@ var CustomRuleResponse = z.object({
|
|
|
661
694
|
target: z.string(),
|
|
662
695
|
is_active: z.boolean(),
|
|
663
696
|
created_at: z.string().datetime({ offset: true }),
|
|
664
|
-
scope: z.string().optional().default("personal")
|
|
697
|
+
scope: z.string().optional().default("personal"),
|
|
698
|
+
tag_visibility: z.record(z.string()).optional()
|
|
665
699
|
}).passthrough();
|
|
666
700
|
z.object({
|
|
667
701
|
items: z.array(CustomRuleResponse),
|
|
@@ -675,7 +709,8 @@ z.object({
|
|
|
675
709
|
tag_slug: z.union([z.string(), z.null()]),
|
|
676
710
|
config: z.union([z.object({}).partial().passthrough(), z.null()]),
|
|
677
711
|
target: z.union([z.string(), z.null()]),
|
|
678
|
-
is_active: z.union([z.boolean(), z.null()])
|
|
712
|
+
is_active: z.union([z.boolean(), z.null()]),
|
|
713
|
+
tag_visibility: z.union([z.record(TagVisibility), z.null()])
|
|
679
714
|
}).partial().passthrough();
|
|
680
715
|
z.object({
|
|
681
716
|
scan_id: z.string().uuid(),
|
|
@@ -906,7 +941,8 @@ var BalanceTransactionType = z.enum([
|
|
|
906
941
|
"admin_adjustment",
|
|
907
942
|
"refund",
|
|
908
943
|
"invoice_settlement",
|
|
909
|
-
"crypto_top_up"
|
|
944
|
+
"crypto_top_up",
|
|
945
|
+
"card_top_up"
|
|
910
946
|
]);
|
|
911
947
|
z.union([z.array(BalanceTransactionType), z.null()]).optional();
|
|
912
948
|
var BalanceTransactionResponse = z.object({
|
|
@@ -1153,6 +1189,7 @@ z.object({
|
|
|
1153
1189
|
description: z.string().max(500).optional().default(""),
|
|
1154
1190
|
nodes: z.array(TaxonomyNodeRequest).optional().default([])
|
|
1155
1191
|
});
|
|
1192
|
+
z.enum(["any", "all"]);
|
|
1156
1193
|
var schemas = {
|
|
1157
1194
|
OrgResponse,
|
|
1158
1195
|
LabelDefinitionResponse,
|
|
@@ -1166,6 +1203,7 @@ var schemas = {
|
|
|
1166
1203
|
EmulatorResponse,
|
|
1167
1204
|
CampaignGroupResponse,
|
|
1168
1205
|
GroupActionResponse,
|
|
1206
|
+
RepeatMode,
|
|
1169
1207
|
CampaignResponse,
|
|
1170
1208
|
CampaignPickerItem,
|
|
1171
1209
|
RunResponse,
|
|
@@ -1308,6 +1346,9 @@ var CampaignSchema = schemas.CampaignResponse.pick({
|
|
|
1308
1346
|
proxy_region: true,
|
|
1309
1347
|
proxy_city: true,
|
|
1310
1348
|
proxy_isp: true,
|
|
1349
|
+
repeat_count: true,
|
|
1350
|
+
repeat_mode: true,
|
|
1351
|
+
retry_max_attempts: true,
|
|
1311
1352
|
labels: true,
|
|
1312
1353
|
policy_set_id: true,
|
|
1313
1354
|
schedule_enabled: true,
|
|
@@ -1318,7 +1359,7 @@ var CampaignSchema = schemas.CampaignResponse.pick({
|
|
|
1318
1359
|
is_archived: true,
|
|
1319
1360
|
created_at: true,
|
|
1320
1361
|
last_run_at: true
|
|
1321
|
-
}).strip();
|
|
1362
|
+
}).extend({ repeat_mode: schemas.RepeatMode.default("isolated") }).strip();
|
|
1322
1363
|
var parseCampaign = (raw) => parseWithSchema(CampaignSchema, raw, "campaign");
|
|
1323
1364
|
var parseCampaignPage = (raw) => parsePagedWithItemSchema(CampaignSchema, raw, "campaigns");
|
|
1324
1365
|
|
|
@@ -1746,8 +1787,14 @@ var ScanSchema = schemas.ScanResponse.pick({
|
|
|
1746
1787
|
ad_kind: true,
|
|
1747
1788
|
network: true,
|
|
1748
1789
|
created_at: true,
|
|
1749
|
-
completed_at: true
|
|
1750
|
-
|
|
1790
|
+
completed_at: true,
|
|
1791
|
+
repeat_index: true,
|
|
1792
|
+
repeat_total: true,
|
|
1793
|
+
repeat_session_id: true,
|
|
1794
|
+
repeat_scan_ids: true,
|
|
1795
|
+
retry_attempt: true,
|
|
1796
|
+
retry_max_attempts: true
|
|
1797
|
+
}).extend({ creative_kind: z.string().default("banner") }).strip();
|
|
1751
1798
|
var ScanArraySchema = z.array(ScanSchema);
|
|
1752
1799
|
var parseScan = (raw) => parseWithSchema(ScanSchema, raw, "scan");
|
|
1753
1800
|
var parseScanArray = (raw) => parseWithSchema(ScanArraySchema, raw, "scans");
|
|
@@ -1773,7 +1820,12 @@ var ScanBriefSchema = schemas.ScanBriefResponse.pick({
|
|
|
1773
1820
|
slot_index: true,
|
|
1774
1821
|
ad_kind: true,
|
|
1775
1822
|
network: true,
|
|
1776
|
-
created_at: true
|
|
1823
|
+
created_at: true,
|
|
1824
|
+
repeat_index: true,
|
|
1825
|
+
repeat_total: true,
|
|
1826
|
+
repeat_session_id: true,
|
|
1827
|
+
retry_attempt: true,
|
|
1828
|
+
retry_max_attempts: true
|
|
1777
1829
|
}).strip();
|
|
1778
1830
|
var parseScanPage = (raw) => parsePagedWithItemSchema(ScanBriefSchema, raw, "scans");
|
|
1779
1831
|
var TagDefinitionSchema = schemas.TagDefinitionWithStatsResponse.pick({
|
|
@@ -1865,10 +1917,7 @@ function createHttpApiGateway(config) {
|
|
|
1865
1917
|
if (dispatcher !== void 0) {
|
|
1866
1918
|
baseInit["dispatcher"] = dispatcher;
|
|
1867
1919
|
}
|
|
1868
|
-
return fetch(
|
|
1869
|
-
input.url,
|
|
1870
|
-
baseInit
|
|
1871
|
-
);
|
|
1920
|
+
return fetch(input.url, baseInit);
|
|
1872
1921
|
};
|
|
1873
1922
|
const client = createClient({
|
|
1874
1923
|
baseUrl,
|
|
@@ -1933,10 +1982,7 @@ function createHttpApiGateway(config) {
|
|
|
1933
1982
|
}
|
|
1934
1983
|
};
|
|
1935
1984
|
if (dispatcher !== void 0) init["dispatcher"] = dispatcher;
|
|
1936
|
-
response = await fetch(
|
|
1937
|
-
url,
|
|
1938
|
-
init
|
|
1939
|
-
);
|
|
1985
|
+
response = await fetch(url, init);
|
|
1940
1986
|
} catch (cause) {
|
|
1941
1987
|
logger.warn({ api_path: path, elapsed_ms: Date.now() - startedAtMs }, "api.network_error");
|
|
1942
1988
|
const inner = cause instanceof Error && cause.cause instanceof Error ? cause.cause : cause instanceof Error ? cause : null;
|
|
@@ -3245,13 +3291,14 @@ var TransactionTypeEnum = z.enum([
|
|
|
3245
3291
|
"admin_adjustment",
|
|
3246
3292
|
"refund",
|
|
3247
3293
|
"invoice_settlement",
|
|
3248
|
-
"crypto_top_up"
|
|
3294
|
+
"crypto_top_up",
|
|
3295
|
+
"card_top_up"
|
|
3249
3296
|
]);
|
|
3250
3297
|
var ListBalanceHistoryInputShape = {
|
|
3251
3298
|
date_from: z.string().date().optional().describe("ISO date, inclusive."),
|
|
3252
3299
|
date_to: z.string().date().optional().describe("ISO date, inclusive."),
|
|
3253
|
-
type: z.array(TransactionTypeEnum).max(
|
|
3254
|
-
"Filter by transaction kind. Pass several values to OR them (e.g. ['top_up_manual','crypto_top_up'] for credits-only)."
|
|
3300
|
+
type: z.array(TransactionTypeEnum).max(TransactionTypeEnum.options.length).optional().describe(
|
|
3301
|
+
"Filter by transaction kind. Pass several values to OR them (e.g. ['top_up_manual','crypto_top_up','card_top_up'] for credits-only)."
|
|
3255
3302
|
),
|
|
3256
3303
|
page: z.number().int().min(1).max(500).default(1).describe("1-indexed page."),
|
|
3257
3304
|
limit: z.number().int().min(1).max(200).default(50).describe("Page size.")
|
|
@@ -3558,6 +3605,28 @@ var cancelCampaignTool = {
|
|
|
3558
3605
|
return ok(result.value);
|
|
3559
3606
|
}
|
|
3560
3607
|
};
|
|
3608
|
+
var repeatRetryFields = {
|
|
3609
|
+
repeat_count: z.number().int().min(1).max(20).optional().describe(
|
|
3610
|
+
"How many times to repeat every scan this call already produces (1-20). It is a multiplier on top of the tool's own fan-out \u2014 see that tool's description for the exact formula \u2014 and each resulting repeat is a full scan with its own report and its own billing. 1-20 is the API's default ceiling; an operator can lower it during an incident, and then a value accepted here still comes back as a 422 from the API. Default: 1."
|
|
3611
|
+
),
|
|
3612
|
+
repeat_mode: z.enum(["isolated", "shared"]).optional().describe(
|
|
3613
|
+
"How the repeats of one combination relate to each other. 'isolated' gives every repeat a fresh browser and a new IP, so the repeats are statistically independent. 'shared' runs all repeats of one combination in a single browser behind one IP, carrying cookies and localStorage from one repeat to the next \u2014 use it to reproduce a cloaker or a frequency cap that only misbehaves on the second or third visit. 'shared' is rejected with 422 on an ad-discovery target: when creating, that is `ad_discovery: true` on a scan or `campaign_type: \"ad_discovery\"` on a campaign; when updating a campaign, it is a campaign whose existing type is already ad_discovery, since campaign_type itself cannot be changed. Default: isolated."
|
|
3614
|
+
),
|
|
3615
|
+
retry_max_attempts: z.number().int().min(0).max(5).optional().describe(
|
|
3616
|
+
"Extra crawl attempts when a scan fails for a technical reason \u2014 dead proxy, navigation timeout, browser crash (0-5). Permanent failures are never retried. The same scan is reused and only a completed scan is billed, so a retry never double-charges. 0-5 is the API's default ceiling; an operator can lower it, and then a value accepted here still comes back as a 422 from the API. Default: 0."
|
|
3617
|
+
)
|
|
3618
|
+
};
|
|
3619
|
+
function pickRepeatRetryBody(input) {
|
|
3620
|
+
const body = {};
|
|
3621
|
+
if (input.repeat_count !== void 0) body.repeat_count = input.repeat_count;
|
|
3622
|
+
if (input.repeat_mode !== void 0) body.repeat_mode = input.repeat_mode;
|
|
3623
|
+
if (input.retry_max_attempts !== void 0) {
|
|
3624
|
+
body.retry_max_attempts = input.retry_max_attempts;
|
|
3625
|
+
}
|
|
3626
|
+
return body;
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
// src/application/tools/campaigns/_campaign-config-fields.ts
|
|
3561
3630
|
var campaignConfigFields = {
|
|
3562
3631
|
emulator_categories: z.array(z.string()).optional().describe(
|
|
3563
3632
|
"Device categories to rotate through, e.g. ['android_phone']. Valid: android_phone, android_tablet, iphone, ipad, windows_desktop, macos_desktop. On create, omitting this defaults to ['android_phone']; pass [] together with emulator_specific_ids to target ONLY specific devices."
|
|
@@ -3572,6 +3641,7 @@ var campaignConfigFields = {
|
|
|
3572
3641
|
proxy_region: z.string().optional().describe("Proxy region/state targeting (free-text; only honoured for a single country)."),
|
|
3573
3642
|
proxy_city: z.string().optional().describe("Proxy city targeting."),
|
|
3574
3643
|
proxy_isp: z.string().optional().describe("Proxy ISP targeting."),
|
|
3644
|
+
...repeatRetryFields,
|
|
3575
3645
|
schedule_type: z.enum(["weekly", "interval"]).optional().describe(
|
|
3576
3646
|
"Scheduling mode: 'weekly' (run on a weekday/hour grid via schedule_weekly) or 'interval' (run every schedule_interval_seconds). Omit for a manual (run-on-demand) campaign."
|
|
3577
3647
|
),
|
|
@@ -3584,7 +3654,7 @@ var campaignConfigFields = {
|
|
|
3584
3654
|
schedule_timezone: z.string().optional().describe("IANA timezone for the weekly grid, e.g. 'Europe/Berlin'. Default: UTC.")
|
|
3585
3655
|
};
|
|
3586
3656
|
function pickCampaignConfigBody(input) {
|
|
3587
|
-
const body = {};
|
|
3657
|
+
const body = { ...pickRepeatRetryBody(input) };
|
|
3588
3658
|
if (input.emulator_categories !== void 0) body.emulator_categories = input.emulator_categories;
|
|
3589
3659
|
if (input.emulator_specific_ids !== void 0) {
|
|
3590
3660
|
body.emulator_specific_ids = input.emulator_specific_ids;
|
|
@@ -3606,8 +3676,10 @@ function pickCampaignConfigBody(input) {
|
|
|
3606
3676
|
// src/application/tools/campaigns/create-campaign.tool.ts
|
|
3607
3677
|
var CreateCampaignInputShape = {
|
|
3608
3678
|
name: z.string().min(1).max(200).describe("Display name (1-200 chars)."),
|
|
3609
|
-
campaign_type: z.enum(["url", "ad_tag", "vast"]).describe(
|
|
3610
|
-
|
|
3679
|
+
campaign_type: z.enum(["url", "ad_tag", "vast", "ad_discovery"]).describe(
|
|
3680
|
+
"`url`, `ad_tag`, `vast`, or `ad_discovery` \u2014 must match the target field below. `ad_discovery` is a publisher-page scan: set `url`; each run detects the page's ad blocks and opens a child scan per detected ad."
|
|
3681
|
+
),
|
|
3682
|
+
url: z.string().url().optional().describe("Target URL (required if campaign_type=url or ad_discovery)."),
|
|
3611
3683
|
ad_tag: z.string().optional().describe(
|
|
3612
3684
|
"Ad-tag HTML/JS or an http(s) URL of a page with the rendered creative (required if campaign_type=ad_tag)."
|
|
3613
3685
|
),
|
|
@@ -3623,7 +3695,7 @@ var CreateCampaignInputShape = {
|
|
|
3623
3695
|
};
|
|
3624
3696
|
var createCampaignTool = {
|
|
3625
3697
|
name: "create_campaign",
|
|
3626
|
-
description: "Create a recurring scan campaign (template). The schedule produces N scans per run where N = number of countries times number of device profiles
|
|
3698
|
+
description: "Create a recurring scan campaign (template). The schedule produces N scans per run where N = number of countries times number of device profiles times `repeat_count`. Scans cost credits when they run, not when the campaign is created, so a high `repeat_count` multiplies the bill on every run. The returned campaign echoes `repeat_count`, `repeat_mode`, and `retry_max_attempts`, so read it back to confirm what the campaign will do.",
|
|
3627
3699
|
annotations: {
|
|
3628
3700
|
title: "Create Campaign",
|
|
3629
3701
|
readOnlyHint: false,
|
|
@@ -3656,7 +3728,7 @@ var GetCampaignInputShape = {
|
|
|
3656
3728
|
};
|
|
3657
3729
|
var getCampaignTool = {
|
|
3658
3730
|
name: "get_campaign",
|
|
3659
|
-
description: "Get one campaign by UUID: name, type (url|ad_tag|vast), target URL / ad-tag / VAST tag (vast_tag), countries, schedule status, archive status, parent group.",
|
|
3731
|
+
description: "Get one campaign by UUID: name, type (url|ad_tag|vast|ad_discovery), target URL / ad-tag / VAST tag (vast_tag), countries, emulator selection, proxy targeting, schedule status, archive status, parent group. Also echoes the repeat / retry settings \u2014 `repeat_count`, `repeat_mode`, `retry_max_attempts` \u2014 so this is how you confirm what `create_campaign` or `update_campaign` actually saved, and how many scans a run will produce (countries x device profiles x `repeat_count`). `ad_discovery` campaigns store the publisher page in the URL field.",
|
|
3660
3732
|
annotations: {
|
|
3661
3733
|
title: "Get Campaign",
|
|
3662
3734
|
readOnlyHint: true,
|
|
@@ -3707,7 +3779,7 @@ var ListCampaignsInputShape = {
|
|
|
3707
3779
|
};
|
|
3708
3780
|
var listCampaignsTool = {
|
|
3709
3781
|
name: "list_campaigns",
|
|
3710
|
-
description: "List campaigns for the caller's organization, optionally filtered by group, archived flag, or name substring. Paginated.",
|
|
3782
|
+
description: "List campaigns for the caller's organization, optionally filtered by group, archived flag, or name substring. Paginated. Each row carries the same fields as `get_campaign`, including the repeat / retry settings (`repeat_count`, `repeat_mode`, `retry_max_attempts`) \u2014 use them to spot the campaigns that multiply their per-run scan count.",
|
|
3711
3783
|
annotations: {
|
|
3712
3784
|
title: "List Campaigns",
|
|
3713
3785
|
readOnlyHint: true,
|
|
@@ -3803,7 +3875,7 @@ var unarchiveCampaignTool = {
|
|
|
3803
3875
|
var UpdateCampaignInputShape = {
|
|
3804
3876
|
campaign_id: z.string().uuid().describe("Campaign UUID to update."),
|
|
3805
3877
|
name: z.string().min(1).max(200).optional().describe("New display name."),
|
|
3806
|
-
url: z.string().url().optional().describe("New target URL (url-type campaigns)."),
|
|
3878
|
+
url: z.string().url().optional().describe("New target URL (url-type and ad_discovery campaigns)."),
|
|
3807
3879
|
ad_tag: z.string().optional().describe(
|
|
3808
3880
|
"New ad-tag HTML/JS or an http(s) URL of a page with the rendered creative (ad_tag-type campaigns)."
|
|
3809
3881
|
),
|
|
@@ -4674,11 +4746,12 @@ var CreateBulkScansInputShape = {
|
|
|
4674
4746
|
country_codes: z.array(z.string().length(2)).min(1).max(50).describe("List of ISO 3166-1 alpha-2 country codes; one scan per country is created."),
|
|
4675
4747
|
emulator_id: z.string().min(1).max(100).describe("Device/OS profile slug; same for every country in the batch."),
|
|
4676
4748
|
proxy: scanProxyField,
|
|
4677
|
-
labels: z.record(z.string()).optional().describe("Arbitrary metadata copied onto every created scan.")
|
|
4749
|
+
labels: z.record(z.string()).optional().describe("Arbitrary metadata copied onto every created scan."),
|
|
4750
|
+
...repeatRetryFields
|
|
4678
4751
|
};
|
|
4679
4752
|
var createBulkScansTool = {
|
|
4680
4753
|
name: "create_bulk_scans",
|
|
4681
|
-
description: "Queue one new scan per country in a single call (e.g. test the same URL, ad-tag, or VAST video tag from US + DE + JP). COSTS N CREDITS where N = number of countries
|
|
4754
|
+
description: "Queue one new scan per country in a single call (e.g. test the same URL, ad-tag, or VAST video tag from US + DE + JP). COSTS N CREDITS where N = number of countries times `repeat_count`. Returns one entry per country; each entry's `repeat_scan_ids` lists that country's extra repeats.",
|
|
4682
4755
|
annotations: {
|
|
4683
4756
|
title: "Create Bulk Scans",
|
|
4684
4757
|
readOnlyHint: false,
|
|
@@ -4695,7 +4768,8 @@ var createBulkScansTool = {
|
|
|
4695
4768
|
...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
|
|
4696
4769
|
...input.vast_tag !== void 0 ? { vast_tag: input.vast_tag } : {},
|
|
4697
4770
|
...input.proxy !== void 0 ? { proxy: input.proxy } : {},
|
|
4698
|
-
...input.labels !== void 0 ? { labels: input.labels } : {}
|
|
4771
|
+
...input.labels !== void 0 ? { labels: input.labels } : {},
|
|
4772
|
+
...pickRepeatRetryBody(input)
|
|
4699
4773
|
};
|
|
4700
4774
|
const result = await ctx.api.createBulkScans(body);
|
|
4701
4775
|
if (result.isErr()) return err(mapApiError(result.error));
|
|
@@ -4720,11 +4794,12 @@ var CreateScanInputShape = {
|
|
|
4720
4794
|
run_id: z.string().uuid().optional().describe("Optional run UUID inside the campaign."),
|
|
4721
4795
|
ad_discovery: z.boolean().optional().describe(
|
|
4722
4796
|
"Publisher ad discovery: detect ad blocks on the page and spawn one child scan per detected ad (banner/pop). Only valid with `url`. Each child is a separate billed scan; list them with `list_scan_children`."
|
|
4723
|
-
)
|
|
4797
|
+
),
|
|
4798
|
+
...repeatRetryFields
|
|
4724
4799
|
};
|
|
4725
4800
|
var createScanTool = {
|
|
4726
4801
|
name: "create_scan",
|
|
4727
|
-
description: "Queue a single new scan for a URL, ad-tag, or VAST video tag against one country. COSTS CREDITS and bills the caller's organization. Returns the newly-created scan record.",
|
|
4802
|
+
description: "Queue a single new scan for a URL, ad-tag, or VAST video tag against one country. Takes one target and one country \u2014 there is no multi-URL form; call it once per URL. COSTS CREDITS and bills the caller's organization: this call creates exactly `repeat_count` scans (default 1) and bills every one of them. Returns the newly-created scan record; when `repeat_count` > 1 the response's `repeat_scan_ids` lists the sibling scans this call also created.",
|
|
4728
4803
|
annotations: {
|
|
4729
4804
|
title: "Create Scan",
|
|
4730
4805
|
readOnlyHint: false,
|
|
@@ -4744,7 +4819,8 @@ var createScanTool = {
|
|
|
4744
4819
|
...input.labels !== void 0 ? { labels: input.labels } : {},
|
|
4745
4820
|
...input.campaign_id !== void 0 ? { campaign_id: input.campaign_id } : {},
|
|
4746
4821
|
...input.run_id !== void 0 ? { run_id: input.run_id } : {},
|
|
4747
|
-
...input.ad_discovery !== void 0 ? { ad_discovery: input.ad_discovery } : {}
|
|
4822
|
+
...input.ad_discovery !== void 0 ? { ad_discovery: input.ad_discovery } : {},
|
|
4823
|
+
...pickRepeatRetryBody(input)
|
|
4748
4824
|
};
|
|
4749
4825
|
const result = await ctx.api.createScan(body);
|
|
4750
4826
|
if (result.isErr()) return err(mapApiError(result.error));
|
|
@@ -4756,7 +4832,7 @@ var GetScanInputShape = {
|
|
|
4756
4832
|
};
|
|
4757
4833
|
var getScanTool = {
|
|
4758
4834
|
name: "get_scan",
|
|
4759
|
-
description: "Get full detail for one scan by UUID: status, offer URL, absolute screenshot URL, report_url + public_report_url deep-links, timing, labels, and the parent campaign if any. VAST video scans also carry `vast_tag`, `creative_kind` (banner
|
|
4835
|
+
description: "Get full detail for one scan by UUID: status, offer URL, absolute screenshot URL, report_url + public_report_url deep-links, timing, labels, and the parent campaign if any. VAST video scans also carry `vast_tag`, `creative_kind` (`banner` or `video` today; treat it as an open string), and a `video` block (duration, media-file URL, the creative's `click_through` destination, VAST version, ad system, VPAID flag, wrapper depth). Repeats and retries: `repeat_index` / `repeat_total` place this scan inside its repeat group (0-based, so 2 of 5 reads as repeat_index 1), a non-null `repeat_session_id` means the group ran in `shared` mode (same browser, same IP, cookies carried over) and is the key to correlate its members \u2014 a shared group of one has nothing to carry over, so it stays null \u2014 `repeat_scan_ids` is filled only on the create response, and `retry_attempt` / `retry_max_attempts` show how many technical re-crawls this scan already consumed. Link users with the returned `report_url` / `public_report_url` \u2014 never construct URLs yourself.",
|
|
4760
4836
|
annotations: {
|
|
4761
4837
|
title: "Get Scan",
|
|
4762
4838
|
readOnlyHint: true,
|
|
@@ -4795,7 +4871,9 @@ var getScanCreativeScreenshotTool = {
|
|
|
4795
4871
|
var GetScanLandingScreenshotInputShape = {
|
|
4796
4872
|
scan_id: z.string().uuid().describe("Scan UUID (ad-tag scan)."),
|
|
4797
4873
|
landing_ord: z.number().int().min(0).max(50).describe("0-indexed landing slot (see `get_scan(...).landings[*].ord`)."),
|
|
4798
|
-
width: z.number().int().min(50).max(2e3).optional().describe(
|
|
4874
|
+
width: z.number().int().min(50).max(2e3).optional().describe(
|
|
4875
|
+
"Optional resize width in pixels. The API top-crops a resized landing screenshot whose height exceeds 2.5x its width, so a long landing page comes back as its top region only \u2014 never conclude that something is absent from the page from a resized capture. Fetch without `width` when you need the whole page."
|
|
4876
|
+
)
|
|
4799
4877
|
};
|
|
4800
4878
|
var getScanLandingScreenshotTool = {
|
|
4801
4879
|
name: "get_scan_landing_screenshot",
|
|
@@ -4821,7 +4899,7 @@ var getScanLandingScreenshotTool = {
|
|
|
4821
4899
|
var GetScanScreenshotInputShape = {
|
|
4822
4900
|
scan_id: z.string().uuid().describe("Scan UUID."),
|
|
4823
4901
|
width: z.number().int().min(50).max(2e3).optional().describe(
|
|
4824
|
-
"Optional resize width in pixels. The API resizes server-side to keep the image small for the agent's context window."
|
|
4902
|
+
"Optional resize width in pixels. The API resizes server-side to keep the image small for the agent's context window. It also top-crops a resized page screenshot whose height exceeds 2.5x its width, so a long page comes back as its top region only \u2014 never conclude that something is absent from the page from a resized capture. Fetch without `width` when you need the whole page."
|
|
4825
4903
|
)
|
|
4826
4904
|
};
|
|
4827
4905
|
var getScanScreenshotTool = {
|
|
@@ -4848,7 +4926,7 @@ var ListScanChildrenInputShape = {
|
|
|
4848
4926
|
};
|
|
4849
4927
|
var listScanChildrenTool = {
|
|
4850
4928
|
name: "list_scan_children",
|
|
4851
|
-
description: "List the discovered-ad child scans of a publisher ad-discovery scan \u2014 one per detected ad block on the page. Each child brief carries ad_kind (banner|pop), the attributed ad network, and slot_index. Returns a paginated envelope with screenshot + report deep-links; link users with those, never hand-build URLs.",
|
|
4929
|
+
description: "List the discovered-ad child scans of a publisher ad-discovery scan \u2014 one per detected ad block on the page. Each child brief carries ad_kind (banner|pop), the attributed ad network, and slot_index. The repeat / retry fields are present but never meaningful here: a child is always its own group of one (`repeat_index` 0, `repeat_total` 1, `repeat_session_id` null) and is never re-crawled, because repeats and retries apply to the publisher scan \u2014 repeating an ad-discovery scan gives you several parents, each with its own children. Returns a paginated envelope with screenshot + report deep-links; link users with those, never hand-build URLs.",
|
|
4852
4930
|
annotations: {
|
|
4853
4931
|
title: "List Scan Children",
|
|
4854
4932
|
readOnlyHint: true,
|
|
@@ -4899,7 +4977,7 @@ var ListScansInputShape = {
|
|
|
4899
4977
|
};
|
|
4900
4978
|
var listScansTool = {
|
|
4901
4979
|
name: "list_scans",
|
|
4902
|
-
description: "List scans for the caller's organization with optional filters (status, country, URL substring, date range, run/campaign/group, tag, AI/IAB/brand category, dynamic labels). Returns a paginated envelope; each brief carries `is_ad_tag` and `is_vast` flags, an absolute screenshot URL plus report_url (auth dashboard) and public_report_url (shareable) deep-links \u2014 link users with those, never hand-build URLs.",
|
|
4980
|
+
description: "List scans for the caller's organization with optional filters (status, country, URL substring, date range, run/campaign/group, tag, AI/IAB/brand category, dynamic labels). Returns a paginated envelope; each brief carries `is_ad_tag` and `is_vast` flags, an absolute screenshot URL plus report_url (auth dashboard) and public_report_url (shareable) deep-links \u2014 link users with those, never hand-build URLs. Repeated scans look like near-duplicate rows: `repeat_index` / `repeat_total` place each one inside its repeat group (0-based) and a non-null `repeat_session_id` means the group ran in `shared` mode (one browser, one IP, cookies carried across repeats) \u2014 group by it to compare the repeats of one combination. `retry_attempt` / `retry_max_attempts` count technical re-crawls of that same scan, not extra scans. `repeat_scan_ids` is not part of this response; use `get_scan` for a single scan's full detail.",
|
|
4903
4981
|
annotations: {
|
|
4904
4982
|
title: "List Scans",
|
|
4905
4983
|
readOnlyHint: true,
|
|
@@ -5533,5 +5611,5 @@ function formatToolError(error) {
|
|
|
5533
5611
|
}
|
|
5534
5612
|
|
|
5535
5613
|
export { BearerToken, SERVER_INSTRUCTIONS, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
|
|
5536
|
-
//# sourceMappingURL=chunk-
|
|
5537
|
-
//# sourceMappingURL=chunk-
|
|
5614
|
+
//# sourceMappingURL=chunk-5UVZYMC3.js.map
|
|
5615
|
+
//# sourceMappingURL=chunk-5UVZYMC3.js.map
|