@kaminari-ad/mcp 0.3.0 → 0.4.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { err, ok } from './chunk-KTQBHJUB.js';
2
+ import { err, ok } from './chunk-RBCMUVI6.js';
3
3
  import { createHash, randomUUID } from 'crypto';
4
4
  import createClient from 'openapi-fetch';
5
5
  import { fetch } from 'undici';
@@ -1201,7 +1201,13 @@ var BillingSummarySchema = schemas.BillingSummaryResponse.pick({
1201
1201
  is_suspended: true,
1202
1202
  can_create_scan: true,
1203
1203
  billing_mode: true,
1204
- block_reason: true
1204
+ block_reason: true,
1205
+ current_plan_is_custom: true,
1206
+ credit_limit_micros: true,
1207
+ effective_minimum_balance_micros: true,
1208
+ scheduled_next_plan_id: true,
1209
+ scheduled_next_plan_name: true,
1210
+ scheduled_effective_at: true
1205
1211
  }).strip();
1206
1212
  var parseBillingSummary = (raw) => parseWithSchema(BillingSummarySchema, raw, "billing-summary");
1207
1213
 
@@ -1214,10 +1220,18 @@ var CampaignSchema = schemas.CampaignResponse.pick({
1214
1220
  ad_tag: true,
1215
1221
  country_codes: true,
1216
1222
  group_id: true,
1223
+ emulator_selection: true,
1224
+ proxy_type: true,
1225
+ proxy_region: true,
1226
+ proxy_city: true,
1227
+ proxy_isp: true,
1217
1228
  labels: true,
1218
1229
  policy_set_id: true,
1219
1230
  schedule_enabled: true,
1220
1231
  schedule_type: true,
1232
+ schedule_weekly: true,
1233
+ schedule_interval_seconds: true,
1234
+ schedule_timezone: true,
1221
1235
  is_archived: true,
1222
1236
  created_at: true,
1223
1237
  last_run_at: true
@@ -1390,6 +1404,7 @@ var UserSchema = schemas.UserResponse.pick({
1390
1404
  id: true,
1391
1405
  email: true,
1392
1406
  name: true,
1407
+ role_id: true,
1393
1408
  role_name: true,
1394
1409
  is_active: true,
1395
1410
  created_at: true
@@ -2637,7 +2652,8 @@ var getAccountTool = {
2637
2652
  var InviteUserInputShape = {
2638
2653
  email: z.string().email().describe("Email of the person to invite. They get a signup link."),
2639
2654
  role_id: z.string().uuid().describe("UUID of the role to assign on accept. Get UUIDs from `list_org_roles`."),
2640
- name: z.string().min(1).optional().describe("Optional display name for the invitee.")
2655
+ name: z.string().min(1).optional().describe("Optional display name for the invitee."),
2656
+ timezone: z.string().optional().describe("Optional IANA timezone for the invitee, e.g. 'Europe/Berlin'. Default: UTC.")
2641
2657
  };
2642
2658
  var inviteUserTool = {
2643
2659
  name: "invite_user",
@@ -2656,6 +2672,7 @@ var inviteUserTool = {
2656
2672
  role_id: input.role_id
2657
2673
  };
2658
2674
  if (input.name !== void 0) body.name = input.name;
2675
+ if (input.timezone !== void 0) body.timezone = input.timezone;
2659
2676
  const result = await ctx.api.inviteUser(body);
2660
2677
  if (result.isErr()) return err(mapApiError(result.error));
2661
2678
  return ok(result.value);
@@ -2833,12 +2850,11 @@ var updateAccountLabelsTool = {
2833
2850
  }
2834
2851
  };
2835
2852
  var UpdateOrgInputShape = {
2836
- name: z.string().min(1).max(200).optional().describe("New organization display name."),
2837
- settings: z.record(z.unknown()).optional().describe("Replacement settings object. Fields not supplied are left unchanged.")
2853
+ name: z.string().min(1).max(200).optional().describe("New organization display name.")
2838
2854
  };
2839
2855
  var updateOrgTool = {
2840
2856
  name: "update_org",
2841
- description: "Update the caller's organization \u2014 display name and/or settings object. Only supplied fields are touched.",
2857
+ description: "Update the caller's organization display name.",
2842
2858
  annotations: {
2843
2859
  title: "Update Organization",
2844
2860
  readOnlyHint: false,
@@ -2849,8 +2865,7 @@ var updateOrgTool = {
2849
2865
  inputSchema: z.object(UpdateOrgInputShape),
2850
2866
  handler: async (input, ctx) => {
2851
2867
  const body = {
2852
- ...input.name !== void 0 ? { name: input.name } : {},
2853
- ...input.settings !== void 0 ? { settings: input.settings } : {}
2868
+ ...input.name !== void 0 ? { name: input.name } : {}
2854
2869
  };
2855
2870
  const result = await ctx.api.updateOrg(body);
2856
2871
  if (result.isErr()) return err(mapApiError(result.error));
@@ -3356,12 +3371,11 @@ var unarchiveCampaignGroupTool = {
3356
3371
  };
3357
3372
  var UpdateCampaignGroupInputShape = {
3358
3373
  group_id: z.string().uuid().describe("Group UUID to update."),
3359
- name: z.string().min(1).max(200).optional().describe("New display name."),
3360
- schedule_paused: z.boolean().optional().describe("Pause/resume the scheduler for every campaign in this group.")
3374
+ name: z.string().min(1).max(200).optional().describe("New display name.")
3361
3375
  };
3362
3376
  var updateCampaignGroupTool = {
3363
3377
  name: "update_campaign_group",
3364
- description: "Update a campaign group: rename, or pause/resume the scheduler (the pause cascades to every campaign in the group).",
3378
+ description: "Rename a campaign group. To pause/resume its scheduler, use `pause_campaign_group_schedule` / `resume_campaign_group_schedule` instead.",
3365
3379
  annotations: {
3366
3380
  title: "Update Campaign Group",
3367
3381
  readOnlyHint: false,
@@ -3372,8 +3386,7 @@ var updateCampaignGroupTool = {
3372
3386
  inputSchema: z.object(UpdateCampaignGroupInputShape),
3373
3387
  handler: async (input, ctx) => {
3374
3388
  const body = {
3375
- ...input.name !== void 0 ? { name: input.name } : {},
3376
- ...input.schedule_paused !== void 0 ? { schedule_paused: input.schedule_paused } : {}
3389
+ ...input.name !== void 0 ? { name: input.name } : {}
3377
3390
  };
3378
3391
  const result = await ctx.api.updateCampaignGroup(input.group_id, body);
3379
3392
  if (result.isErr()) return err(mapApiError(result.error));
@@ -3420,6 +3433,52 @@ var cancelCampaignTool = {
3420
3433
  return ok(result.value);
3421
3434
  }
3422
3435
  };
3436
+ var campaignConfigFields = {
3437
+ emulator_categories: z.array(z.string()).optional().describe(
3438
+ "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."
3439
+ ),
3440
+ emulator_specific_ids: z.array(z.string()).optional().describe(
3441
+ "Pin exact device profile slugs from `list_emulators` (the `id` field), e.g. ['samsung_galaxy_s23_ultra_android16']. Always scanned regardless of emulator_mode."
3442
+ ),
3443
+ emulator_mode: z.enum(["random", "all"]).optional().describe(
3444
+ "How selected categories expand per run: 'random' = one random device per category (the UI's 'Random (1 per group)'), 'all' = every device in each category ('All checked'). Does not affect emulator_specific_ids. Default: random."
3445
+ ),
3446
+ proxy_type: z.enum(["residential", "mobile"]).optional().describe("Proxy network type. Default: residential."),
3447
+ proxy_region: z.string().optional().describe("Proxy region/state targeting (free-text; only honoured for a single country)."),
3448
+ proxy_city: z.string().optional().describe("Proxy city targeting."),
3449
+ proxy_isp: z.string().optional().describe("Proxy ISP targeting."),
3450
+ schedule_type: z.enum(["weekly", "interval"]).optional().describe(
3451
+ "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."
3452
+ ),
3453
+ schedule_weekly: z.record(z.array(z.number().int().min(0).max(23))).optional().describe(
3454
+ "Weekly run grid for schedule_type='weekly'. Keys are weekdays '0'-'6' (Mon-Sun); values are hours 0-23 in schedule_timezone, e.g. { '0': [9, 17], '4': [12] }."
3455
+ ),
3456
+ schedule_interval_seconds: z.number().int().optional().describe(
3457
+ "Run interval for schedule_type='interval'. Allowed presets (seconds): 60, 120, 300, 600, 900, 1800, 2700, 3600, 7200, 14400, 28800, 86400."
3458
+ ),
3459
+ schedule_timezone: z.string().optional().describe("IANA timezone for the weekly grid, e.g. 'Europe/Berlin'. Default: UTC.")
3460
+ };
3461
+ function pickCampaignConfigBody(input) {
3462
+ const body = {};
3463
+ if (input.emulator_categories !== void 0) body.emulator_categories = input.emulator_categories;
3464
+ if (input.emulator_specific_ids !== void 0) {
3465
+ body.emulator_specific_ids = input.emulator_specific_ids;
3466
+ }
3467
+ if (input.emulator_mode !== void 0) body.emulator_mode = input.emulator_mode;
3468
+ if (input.proxy_type !== void 0) body.proxy_type = input.proxy_type;
3469
+ if (input.proxy_region !== void 0) body.proxy_region = input.proxy_region;
3470
+ if (input.proxy_city !== void 0) body.proxy_city = input.proxy_city;
3471
+ if (input.proxy_isp !== void 0) body.proxy_isp = input.proxy_isp;
3472
+ if (input.schedule_type !== void 0) body.schedule_type = input.schedule_type;
3473
+ if (input.schedule_weekly !== void 0) body.schedule_weekly = input.schedule_weekly;
3474
+ if (input.schedule_interval_seconds !== void 0) {
3475
+ body.schedule_interval_seconds = input.schedule_interval_seconds;
3476
+ }
3477
+ if (input.schedule_timezone !== void 0) body.schedule_timezone = input.schedule_timezone;
3478
+ return body;
3479
+ }
3480
+
3481
+ // src/application/tools/campaigns/create-campaign.tool.ts
3423
3482
  var CreateCampaignInputShape = {
3424
3483
  name: z.string().min(1).max(200).describe("Display name (1-200 chars)."),
3425
3484
  campaign_type: z.enum(["url", "ad_tag"]).describe("`url` or `ad_tag` \u2014 must match the target field below."),
@@ -3427,7 +3486,7 @@ var CreateCampaignInputShape = {
3427
3486
  ad_tag: z.string().optional().describe("Ad-tag HTML/JS (required if campaign_type=ad_tag)."),
3428
3487
  country_codes: z.array(z.string().length(2)).min(1).describe("ISO 3166-1 alpha-2 codes \u2014 one scan per country per run."),
3429
3488
  group_id: z.string().uuid().optional().describe("Parent group UUID; defaults to the org's default group."),
3430
- emulator_categories: z.array(z.string()).optional().describe("Categories of device profiles to rotate through. Default: all available."),
3489
+ ...campaignConfigFields,
3431
3490
  labels: z.record(z.string()).optional().describe("Arbitrary metadata applied to every queued scan."),
3432
3491
  policy_set_id: z.string().uuid().optional().describe("Policy set to evaluate every scan against."),
3433
3492
  schedule_enabled: z.boolean().optional().describe("If true, the scheduler runs immediately. Default: false (manual run).")
@@ -3451,10 +3510,10 @@ var createCampaignTool = {
3451
3510
  ...input.url !== void 0 ? { url: input.url } : {},
3452
3511
  ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
3453
3512
  ...input.group_id !== void 0 ? { group_id: input.group_id } : {},
3454
- ...input.emulator_categories !== void 0 ? { emulator_categories: input.emulator_categories } : {},
3455
3513
  ...input.labels !== void 0 ? { labels: input.labels } : {},
3456
3514
  ...input.policy_set_id !== void 0 ? { policy_set_id: input.policy_set_id } : {},
3457
- ...input.schedule_enabled !== void 0 ? { schedule_enabled: input.schedule_enabled } : {}
3515
+ ...input.schedule_enabled !== void 0 ? { schedule_enabled: input.schedule_enabled } : {},
3516
+ ...pickCampaignConfigBody(input)
3458
3517
  };
3459
3518
  const result = await ctx.api.createCampaign(body);
3460
3519
  if (result.isErr()) return err(mapApiError(result.error));
@@ -3613,7 +3672,11 @@ var unarchiveCampaignTool = {
3613
3672
  var UpdateCampaignInputShape = {
3614
3673
  campaign_id: z.string().uuid().describe("Campaign UUID to update."),
3615
3674
  name: z.string().min(1).max(200).optional().describe("New display name."),
3675
+ url: z.string().url().optional().describe("New target URL (url-type campaigns)."),
3676
+ ad_tag: z.string().optional().describe("New ad-tag HTML/JS (ad_tag-type campaigns)."),
3616
3677
  country_codes: z.array(z.string().length(2)).optional().describe("Replace the country list."),
3678
+ group_id: z.string().uuid().optional().describe("Move the campaign to another group."),
3679
+ ...campaignConfigFields,
3617
3680
  labels: z.record(z.string()).optional().describe("Replace the label map."),
3618
3681
  policy_set_id: z.string().uuid().nullable().optional().describe("New policy set UUID; pass null to clear."),
3619
3682
  schedule_enabled: z.boolean().optional().describe("Pause / resume the scheduler.")
@@ -3632,10 +3695,14 @@ var updateCampaignTool = {
3632
3695
  handler: async (input, ctx) => {
3633
3696
  const body = {
3634
3697
  ...input.name !== void 0 ? { name: input.name } : {},
3698
+ ...input.url !== void 0 ? { url: input.url } : {},
3699
+ ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
3635
3700
  ...input.country_codes !== void 0 ? { country_codes: input.country_codes } : {},
3701
+ ...input.group_id !== void 0 ? { group_id: input.group_id } : {},
3636
3702
  ...input.labels !== void 0 ? { labels: input.labels } : {},
3637
3703
  ...input.policy_set_id !== void 0 ? { policy_set_id: input.policy_set_id } : {},
3638
- ...input.schedule_enabled !== void 0 ? { schedule_enabled: input.schedule_enabled } : {}
3704
+ ...input.schedule_enabled !== void 0 ? { schedule_enabled: input.schedule_enabled } : {},
3705
+ ...pickCampaignConfigBody(input)
3639
3706
  };
3640
3707
  const result = await ctx.api.updateCampaign(input.campaign_id, body);
3641
3708
  if (result.isErr()) return err(mapApiError(result.error));
@@ -3643,17 +3710,25 @@ var updateCampaignTool = {
3643
3710
  }
3644
3711
  };
3645
3712
  var CreateCustomRuleInputShape = {
3646
- name: z.string().min(1).max(200).describe("Display name."),
3647
- tag_slug: z.string().max(100).optional().describe("Tag slug to assign on match. Empty = create-only (advanced)."),
3648
- rule_type: z.string().max(50).describe("Rule engine: regex | substring | iab_category | etc. (API validates)."),
3649
- config: z.record(z.unknown()).describe("Rule-type-specific configuration object. Shape depends on rule_type."),
3713
+ name: z.string().min(1).max(200).describe(
3714
+ "Display name. For non-LLM rules this also becomes the `display_name` of the auto-registered tag definition (see `tag_slug`)."
3715
+ ),
3716
+ tag_slug: z.string().max(100).optional().describe(
3717
+ "Tag slug to assign on match. Empty = create-only (advanced). The API auto-registers a custom tag definition for this slug with `display_name = name`. **MUST NOT collide with a built-in system tag slug** (see `list_tags` where `is_system=true`); colliding requests return 422 with code `checking.system_slug_reserved`. For `rule_type='llm'` use `config.tags` keys instead and leave `tag_slug` empty."
3718
+ ),
3719
+ rule_type: z.string().max(50).describe(
3720
+ "Rule engine. One of: `stopword_content`, `stopword_url`, `regexp_content`, `regexp_url`, `blacklist_domain`, `combo`, `llm`. The API validates."
3721
+ ),
3722
+ config: z.record(z.unknown()).describe(
3723
+ "Rule-type-specific configuration object. Shape depends on `rule_type`. For `rule_type='llm'` the shape is `{ prompt: string, tags: { <tag_slug>: <description>, ... } }`; each key in `config.tags` is auto-registered as a custom tag definition AND must not collide with a system slug (same 422 contract as `tag_slug`)."
3724
+ ),
3650
3725
  target: z.string().max(30).optional().describe(
3651
3726
  "Where to apply the rule (e.g. 'page' for landing HTML). Default: page. See API docs for the full set of valid values."
3652
3727
  )
3653
3728
  };
3654
3729
  var createCustomRuleTool = {
3655
3730
  name: "create_custom_rule",
3656
- description: "Define a custom tag-detection rule (regex / substring / category). Matches will tag every future scan; existing scans are untouched until you call `recheck_scans`.",
3731
+ description: "Define a custom tag-detection rule. The API auto-registers a tag definition for each slug the rule emits (`tag_slug` for non-LLM rules; `config.tags` keys for `rule_type='llm'`); slugs that collide with a built-in system tag are rejected with HTTP 422 / code `checking.system_slug_reserved`. Matches tag every future scan; existing scans are untouched until you call `recheck_scans`.",
3657
3732
  annotations: {
3658
3733
  title: "Create Custom Rule",
3659
3734
  readOnlyHint: false,
@@ -3735,8 +3810,12 @@ var listCustomRulesTool = {
3735
3810
  }
3736
3811
  };
3737
3812
  var TestCustomRuleInputShape = {
3738
- rule_type: z.string().max(50).describe("Rule engine type (regex, substring, ...)."),
3739
- config: z.record(z.unknown()).describe("Rule-type-specific config to test."),
3813
+ rule_type: z.string().max(50).describe(
3814
+ "Rule engine type. One of: `stopword_content`, `stopword_url`, `regexp_content`, `regexp_url`, `blacklist_domain`, `combo`, `llm`."
3815
+ ),
3816
+ config: z.record(z.unknown()).describe(
3817
+ "Rule-type-specific config to test. Same shape as `create_custom_rule`'s `config`. NOTE: `test_custom_rule` evaluates the rule against a scan WITHOUT persisting it, so slug-collision validation does NOT run here \u2014 verify slugs against `list_tags` (`is_system=true`) before promoting to `create_custom_rule`."
3818
+ ),
3740
3819
  target: z.string().max(30).describe(
3741
3820
  "Where to apply the rule (e.g. 'page' for landing HTML). See API docs for the full set of valid values."
3742
3821
  ),
@@ -3744,7 +3823,7 @@ var TestCustomRuleInputShape = {
3744
3823
  };
3745
3824
  var testCustomRuleTool = {
3746
3825
  name: "test_custom_rule",
3747
- description: "Preview-test a rule definition against an existing scan WITHOUT persisting the rule. Returns `matched: bool`, evaluation time, and per-tag-slug details. Use to validate config before `create_custom_rule`.",
3826
+ description: "Preview-test a rule definition against an existing scan WITHOUT persisting the rule. Returns `matched: bool`, evaluation time, and per-tag-slug details. Use to validate config before `create_custom_rule`. NOTE: slug-collision validation does NOT run in preview mode \u2014 verify any `tag_slug` (or LLM `config.tags` keys) against `list_tags` (`is_system=true`) before promoting to `create_custom_rule`, which would otherwise reject the same payload with HTTP 422 / code `checking.system_slug_reserved`.",
3748
3827
  annotations: {
3749
3828
  title: "Test Custom Rule",
3750
3829
  readOnlyHint: true,
@@ -3766,9 +3845,15 @@ var testCustomRuleTool = {
3766
3845
  };
3767
3846
  var UpdateCustomRuleInputShape = {
3768
3847
  rule_id: z.string().uuid().describe("Rule UUID to update."),
3769
- name: z.string().min(1).max(200).optional().describe("New display name."),
3770
- tag_slug: z.string().max(100).optional().describe("New tag slug to assign on match."),
3771
- config: z.record(z.unknown()).optional().describe("New rule-type-specific config object."),
3848
+ name: z.string().min(1).max(200).optional().describe(
3849
+ "New display name. For non-LLM rules this also becomes the new `display_name` of the auto-registered tag definition."
3850
+ ),
3851
+ tag_slug: z.string().max(100).optional().describe(
3852
+ "New tag slug to assign on match. **MUST NOT collide with a built-in system tag slug** (see `list_tags` where `is_system=true`); colliding requests return 422 with code `checking.system_slug_reserved`. Re-registering an existing custom slug refreshes its tag definition's `display_name` / `description`."
3853
+ ),
3854
+ config: z.record(z.unknown()).optional().describe(
3855
+ "New rule-type-specific config object. For `rule_type='llm'` the keys of `config.tags` are auto-registered as tag definitions; any key that collides with a system slug returns the same 422 contract."
3856
+ ),
3772
3857
  target: z.string().max(30).optional().describe(
3773
3858
  "Where to apply the rule (e.g. 'page' for landing HTML). See API docs for the full set of valid values."
3774
3859
  ),
@@ -3776,7 +3861,7 @@ var UpdateCustomRuleInputShape = {
3776
3861
  };
3777
3862
  var updateCustomRuleTool = {
3778
3863
  name: "update_custom_rule",
3779
- description: "Update a custom tag-detection rule. Only supplied fields are sent. To toggle activation, pass `is_active`. Existing tagged scans are NOT re-evaluated \u2014 call `recheck_scans` for that. (Rule engine `rule_type` cannot be changed after creation; create a new rule instead.)",
3864
+ description: "Update a custom tag-detection rule. Only supplied fields are sent. Changing `tag_slug` (or `config.tags` keys for `rule_type='llm'`) onto a built-in system slug returns HTTP 422 / code `checking.system_slug_reserved`. To toggle activation, pass `is_active`. Existing tagged scans are NOT re-evaluated \u2014 call `recheck_scans` for that. (Rule engine `rule_type` cannot be changed after creation; create a new rule instead.)",
3780
3865
  annotations: {
3781
3866
  title: "Update Custom Rule",
3782
3867
  readOnlyHint: false,
@@ -3990,7 +4075,7 @@ var updateCustomTaxonomyTool = {
3990
4075
  var ListEmulatorsInputShape = {};
3991
4076
  var listEmulatorsTool = {
3992
4077
  name: "list_emulators",
3993
- description: "List every device/OS emulator profile available for scans (id, display name, category, browser). Use the `id` as `emulator_id` in `create_scan` / `create_campaign`.",
4078
+ description: "List every device/OS emulator profile available for scans (id, display name, category, browser). For `create_scan`, use the `id` as `emulator_id`. For `create_campaign` / `update_campaign`, use the `category` in `emulator_categories` or the `id` in `emulator_specific_ids`.",
3994
4079
  annotations: {
3995
4080
  title: "List Emulators",
3996
4081
  readOnlyHint: true,
@@ -4433,11 +4518,20 @@ var cancelScanTool = {
4433
4518
  return ok(result.value);
4434
4519
  }
4435
4520
  };
4521
+ var scanProxyField = z.object({
4522
+ proxy_type: z.enum(["residential", "mobile"]).optional().describe("Proxy network type. Default: residential."),
4523
+ region: z.string().optional().describe("Proxy region/state targeting."),
4524
+ city: z.string().optional().describe("Proxy city targeting."),
4525
+ isp: z.string().optional().describe("Proxy ISP targeting.")
4526
+ }).optional().describe("Optional proxy geo targeting for the crawl. Omit to use the org default.");
4527
+
4528
+ // src/application/tools/scans/create-bulk-scans.tool.ts
4436
4529
  var CreateBulkScansInputShape = {
4437
4530
  url: z.string().url().optional().describe("Direct URL. EITHER `url` OR `ad_tag` is required."),
4438
4531
  ad_tag: z.string().optional().describe("Raw ad-tag HTML/JS. EITHER `url` OR `ad_tag` is required."),
4439
4532
  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."),
4440
4533
  emulator_id: z.string().min(1).max(100).describe("Device/OS profile slug; same for every country in the batch."),
4534
+ proxy: scanProxyField,
4441
4535
  labels: z.record(z.string()).optional().describe("Arbitrary metadata copied onto every created scan.")
4442
4536
  };
4443
4537
  var createBulkScansTool = {
@@ -4457,6 +4551,7 @@ var createBulkScansTool = {
4457
4551
  emulator_id: input.emulator_id,
4458
4552
  ...input.url !== void 0 ? { url: input.url } : {},
4459
4553
  ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
4554
+ ...input.proxy !== void 0 ? { proxy: input.proxy } : {},
4460
4555
  ...input.labels !== void 0 ? { labels: input.labels } : {}
4461
4556
  };
4462
4557
  const result = await ctx.api.createBulkScans(body);
@@ -4469,6 +4564,7 @@ var CreateScanInputShape = {
4469
4564
  ad_tag: z.string().optional().describe("Raw HTML/JS ad tag (script, iframe, image). EITHER `url` OR `ad_tag` is required."),
4470
4565
  country_code: z.string().length(2).describe("ISO 3166-1 alpha-2 country code, e.g. US, DE, JP. Determines proxy geo."),
4471
4566
  emulator_id: z.string().min(1).max(100).describe("Device/OS profile slug; use `list_emulators` to discover valid values."),
4567
+ proxy: scanProxyField,
4472
4568
  labels: z.record(z.string()).optional().describe("Arbitrary string -> string metadata attached to the scan."),
4473
4569
  campaign_id: z.string().uuid().optional().describe("Optional campaign UUID to attribute the scan to."),
4474
4570
  run_id: z.string().uuid().optional().describe("Optional run UUID inside the campaign.")
@@ -4490,6 +4586,7 @@ var createScanTool = {
4490
4586
  emulator_id: input.emulator_id,
4491
4587
  ...input.url !== void 0 ? { url: input.url } : {},
4492
4588
  ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
4589
+ ...input.proxy !== void 0 ? { proxy: input.proxy } : {},
4493
4590
  ...input.labels !== void 0 ? { labels: input.labels } : {},
4494
4591
  ...input.campaign_id !== void 0 ? { campaign_id: input.campaign_id } : {},
4495
4592
  ...input.run_id !== void 0 ? { run_id: input.run_id } : {}
@@ -5042,7 +5139,12 @@ var testWebhookTool = {
5042
5139
  var UpdateWebhookInputShape = {
5043
5140
  webhook_id: z.string().uuid().describe("Webhook UUID."),
5044
5141
  url: z.string().url().optional().describe("New endpoint URL."),
5142
+ description: z.string().max(256).optional().describe("New human-readable label."),
5045
5143
  event_types: z.array(z.string()).max(50).optional().describe("Replace the subscribed-event-types list."),
5144
+ campaign_ids: z.array(z.string().uuid()).optional().describe("Restrict deliveries to these campaign UUIDs (replaces the current set)."),
5145
+ clear_campaign_ids: z.boolean().optional().describe(
5146
+ "Set true to remove the campaign restriction so the webhook fires for all campaigns."
5147
+ ),
5046
5148
  is_active: z.boolean().optional().describe("Enable / disable delivery.")
5047
5149
  };
5048
5150
  var updateWebhookTool = {
@@ -5059,7 +5161,10 @@ var updateWebhookTool = {
5059
5161
  handler: async (input, ctx) => {
5060
5162
  const body = {
5061
5163
  ...input.url !== void 0 ? { url: input.url } : {},
5164
+ ...input.description !== void 0 ? { description: input.description } : {},
5062
5165
  ...input.event_types !== void 0 ? { event_types: input.event_types } : {},
5166
+ ...input.campaign_ids !== void 0 ? { campaign_ids: input.campaign_ids } : {},
5167
+ ...input.clear_campaign_ids !== void 0 ? { clear_campaign_ids: input.clear_campaign_ids } : {},
5063
5168
  ...input.is_active !== void 0 ? { is_active: input.is_active } : {}
5064
5169
  };
5065
5170
  const result = await ctx.api.updateWebhook(input.webhook_id, body);
@@ -5247,5 +5352,5 @@ function formatToolError(error) {
5247
5352
  }
5248
5353
 
5249
5354
  export { BearerToken, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
5250
- //# sourceMappingURL=chunk-W7TPFRJB.js.map
5251
- //# sourceMappingURL=chunk-W7TPFRJB.js.map
5355
+ //# sourceMappingURL=chunk-7DSLLKEK.js.map
5356
+ //# sourceMappingURL=chunk-7DSLLKEK.js.map