@kaminari-ad/mcp 0.17.0 → 0.18.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 CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.17.1] - 2026-09-03
11
+
12
+ ### Fixed
13
+
14
+ - **The screenshot tools said PNG; the API has only ever sent WebP.**
15
+ `get_scan_screenshot` and `get_scan_creative_screenshot` advertised
16
+ "base64-encoded PNG", while every screenshot route on the API side
17
+ hardcodes `image/webp` — the crawler writes WebP and the legacy `.png`
18
+ keys were backfilled long ago. `get_scan_landing_screenshot` named no
19
+ format at all. All three now name WebP and say outright that the
20
+ client has to be able to decode it.
21
+
22
+ No transcoding was added, deliberately: this server does no image
23
+ processing at all — it base64-encodes the bytes it received and passes
24
+ the response's own content type through. A client that cannot read
25
+ WebP has to handle that on its own side, and an error such as
26
+ `webp codec not registered: registerWebpCodec() must be called by a
27
+ Node server` comes from the client, not from here and not from the
28
+ API.
29
+
10
30
  ## [0.17.0] - 2026-09-03
11
31
 
12
32
  ### Added
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { NAME, VERSION, err, ok } from './chunk-OX65SNEN.js';
2
+ import { NAME, VERSION, err, ok } from './chunk-KCQ55TRV.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-NVDBVJ7K.js');
163
+ const { bootstrapStdio } = await import('./stdio-bootstrap-ZWMO4KXK.js');
164
164
  return bootstrapStdio(config);
165
165
  }
166
- const { bootstrapHttp } = await import('./http-bootstrap-DKGGQURI.js');
166
+ const { bootstrapHttp } = await import('./http-bootstrap-WTWLW2LP.js');
167
167
  return bootstrapHttp(config);
168
168
  }
169
169
  main().then(
@@ -3,8 +3,8 @@ export { err, ok } from 'neverthrow';
3
3
 
4
4
  // src/shared/version.ts
5
5
  var NAME = "@kaminari-ad/mcp";
6
- var VERSION = "0.17.0";
6
+ var VERSION = "0.18.0";
7
7
 
8
8
  export { NAME, VERSION };
9
- //# sourceMappingURL=chunk-OX65SNEN.js.map
10
- //# sourceMappingURL=chunk-OX65SNEN.js.map
9
+ //# sourceMappingURL=chunk-KCQ55TRV.js.map
10
+ //# sourceMappingURL=chunk-KCQ55TRV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/version.ts"],"names":[],"mappings":";;;;AASO,IAAM,IAAA,GAAO;AACb,IAAM,OAAA,GAAU","file":"chunk-OX65SNEN.js","sourcesContent":["/**\n * Package version and name. Hard-coded as constants here, asserted to\n * match `package.json` by a unit test.\n *\n * Why not import `package.json`: it would force JSON-module support at\n * runtime and tsup-bundling would inline the entire manifest. Two\n * constants + one assertion test is simpler and gives the same safety.\n */\n\nexport const NAME = \"@kaminari-ad/mcp\";\nexport const VERSION = \"0.17.0\";\n"]}
1
+ {"version":3,"sources":["../src/shared/version.ts"],"names":[],"mappings":";;;;AASO,IAAM,IAAA,GAAO;AACb,IAAM,OAAA,GAAU","file":"chunk-KCQ55TRV.js","sourcesContent":["/**\n * Package version and name. Hard-coded as constants here, asserted to\n * match `package.json` by a unit test.\n *\n * Why not import `package.json`: it would force JSON-module support at\n * runtime and tsup-bundling would inline the entire manifest. Two\n * constants + one assertion test is simpler and gives the same safety.\n */\n\nexport const NAME = \"@kaminari-ad/mcp\";\nexport const VERSION = \"0.18.0\";\n"]}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { err, ok } from './chunk-OX65SNEN.js';
2
+ import { err, ok } from './chunk-KCQ55TRV.js';
3
3
  import { createHash, randomUUID } from 'crypto';
4
4
  import createClient from 'openapi-fetch';
5
5
  import { fetch } from 'undici';
@@ -1348,8 +1348,6 @@ var BillingSummarySchema = schemas.BillingSummaryResponse.pick({
1348
1348
  scheduled_effective_at: true
1349
1349
  }).strip();
1350
1350
  var parseBillingSummary = (raw) => parseWithSchema(BillingSummarySchema, raw, "billing-summary");
1351
-
1352
- // src/infrastructure/api/parsers/parse-campaign.ts
1353
1351
  var CampaignSchema = schemas.CampaignResponse.pick({
1354
1352
  id: true,
1355
1353
  name: true,
@@ -1378,7 +1376,7 @@ var CampaignSchema = schemas.CampaignResponse.pick({
1378
1376
  is_archived: true,
1379
1377
  created_at: true,
1380
1378
  last_run_at: true
1381
- }).extend({ repeat_mode: schemas.RepeatMode.default("isolated") }).strip();
1379
+ }).extend({ repeat_mode: schemas.RepeatMode.default("isolated") }).extend({ max_discovered_ads: z.number().int().nullable().optional() }).strip();
1382
1380
  var parseCampaign = (raw) => parseWithSchema(CampaignSchema, raw, "campaign");
1383
1381
  var parseCampaignPage = (raw) => parsePagedWithItemSchema(CampaignSchema, raw, "campaigns");
1384
1382
 
@@ -1840,7 +1838,7 @@ var ScanSchema = schemas.ScanResponse.pick({
1840
1838
  repeat_scan_ids: true,
1841
1839
  retry_attempt: true,
1842
1840
  retry_max_attempts: true
1843
- }).extend({ creative_kind: z.string().default("banner") }).strip();
1841
+ }).extend({ creative_kind: z.string().default("banner") }).extend({ max_discovered_ads: z.number().int().nullable().optional() }).strip();
1844
1842
  var ScanArraySchema = z.array(ScanSchema);
1845
1843
  var parseScan = (raw) => parseWithSchema(ScanSchema, raw, "scan");
1846
1844
  var parseScanArray = (raw) => parseWithSchema(ScanArraySchema, raw, "scans");
@@ -3892,6 +3890,15 @@ var cancelCampaignTool = {
3892
3890
  return ok(result.value);
3893
3891
  }
3894
3892
  };
3893
+ var MAX_DISCOVERED_ADS_DESCRIPTION = 'How many ad blocks to look for on each publisher page before stopping (1-25). Every ad found becomes its own scan with its own report and is BILLED AS A SEPARATE CHECK, so this multiplies the cost: a page scanned at 25 can cost 26 checks \u2014 one parent plus its children. Only valid on an ad-discovery target \u2014 `ad_discovery: true` on a scan, or `campaign_type: "ad_discovery"` on a campaign \u2014 and rejected with 422 anywhere else.';
3894
+ var PLATFORM_DEFAULT_NOTE = "The platform default is 12 unless an operator retuned it.";
3895
+ var maxDiscoveredAds = z.number().int().min(1).max(25);
3896
+ var maxDiscoveredAdsField = maxDiscoveredAds.optional().describe(
3897
+ `${MAX_DISCOVERED_ADS_DESCRIPTION} Omit it to use the platform default. ` + PLATFORM_DEFAULT_NOTE
3898
+ );
3899
+ var maxDiscoveredAdsUpdateField = maxDiscoveredAds.nullable().optional().describe(
3900
+ `${MAX_DISCOVERED_ADS_DESCRIPTION} Omitting the field leaves the campaign's current setting unchanged; pass null to drop its own number and go back to the platform default. ${PLATFORM_DEFAULT_NOTE}`
3901
+ );
3895
3902
  var repeatRetryFields = {
3896
3903
  repeat_count: z.number().int().min(1).max(20).optional().describe(
3897
3904
  "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."
@@ -3986,6 +3993,7 @@ var CreateCampaignInputShape = {
3986
3993
  "VAST video ad tag: an http(s) URL of a VAST endpoint OR raw VAST XML (required if campaign_type=vast)."
3987
3994
  ),
3988
3995
  referrer: campaignReferrerField,
3996
+ max_discovered_ads: maxDiscoveredAdsField,
3989
3997
  country_codes: z.array(z.string().length(2)).min(1).describe("ISO 3166-1 alpha-2 codes \u2014 one scan per country per run."),
3990
3998
  group_id: z.string().uuid().optional().describe("Parent group UUID; defaults to the org's default group."),
3991
3999
  ...campaignConfigFields,
@@ -4013,6 +4021,7 @@ var createCampaignTool = {
4013
4021
  ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
4014
4022
  ...input.vast_tag !== void 0 ? { vast_tag: input.vast_tag } : {},
4015
4023
  ...input.referrer !== void 0 ? { referrer: input.referrer } : {},
4024
+ ...input.max_discovered_ads !== void 0 ? { max_discovered_ads: input.max_discovered_ads } : {},
4016
4025
  ...input.group_id !== void 0 ? { group_id: input.group_id } : {},
4017
4026
  ...input.labels !== void 0 ? { labels: input.labels } : {},
4018
4027
  ...input.policy_set_id !== void 0 ? { policy_set_id: input.policy_set_id } : {},
@@ -4186,6 +4195,7 @@ var UpdateCampaignInputShape = {
4186
4195
  "New VAST video ad tag: an http(s) URL of a VAST endpoint OR raw VAST XML (vast-type campaigns)."
4187
4196
  ),
4188
4197
  referrer: campaignReferrerUpdateField,
4198
+ max_discovered_ads: maxDiscoveredAdsUpdateField,
4189
4199
  country_codes: z.array(z.string().length(2)).optional().describe("Replace the country list."),
4190
4200
  group_id: z.string().uuid().optional().describe("Move the campaign to another group."),
4191
4201
  ...campaignConfigFields,
@@ -4195,7 +4205,7 @@ var UpdateCampaignInputShape = {
4195
4205
  };
4196
4206
  var updateCampaignTool = {
4197
4207
  name: "update_campaign",
4198
- description: "Update one or more fields of a campaign. Fields not supplied are left unchanged. `policy_set_id` accepts null to clear the binding, and `referrer` accepts null to clear the publisher page scans are checked from.",
4208
+ description: "Update one or more fields of a campaign. Fields not supplied are left unchanged. `policy_set_id` accepts null to clear the binding, `referrer` accepts null to clear the publisher page scans are checked from, and `max_discovered_ads` accepts null to go back to the platform ad cap.",
4199
4209
  annotations: {
4200
4210
  title: "Update Campaign",
4201
4211
  readOnlyHint: false,
@@ -4211,6 +4221,7 @@ var updateCampaignTool = {
4211
4221
  ...input.ad_tag !== void 0 ? { ad_tag: input.ad_tag } : {},
4212
4222
  ...input.vast_tag !== void 0 ? { vast_tag: input.vast_tag } : {},
4213
4223
  ...input.referrer !== void 0 ? { referrer: input.referrer } : {},
4224
+ ...input.max_discovered_ads !== void 0 ? { max_discovered_ads: input.max_discovered_ads } : {},
4214
4225
  ...input.country_codes !== void 0 ? { country_codes: input.country_codes } : {},
4215
4226
  ...input.group_id !== void 0 ? { group_id: input.group_id } : {},
4216
4227
  ...input.labels !== void 0 ? { labels: input.labels } : {},
@@ -5314,6 +5325,7 @@ var CreateScanInputShape = {
5314
5325
  ad_discovery: z.boolean().optional().describe(
5315
5326
  "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`."
5316
5327
  ),
5328
+ max_discovered_ads: maxDiscoveredAdsField,
5317
5329
  ...repeatRetryFields
5318
5330
  };
5319
5331
  var createScanTool = {
@@ -5340,6 +5352,7 @@ var createScanTool = {
5340
5352
  ...input.campaign_id !== void 0 ? { campaign_id: input.campaign_id } : {},
5341
5353
  ...input.run_id !== void 0 ? { run_id: input.run_id } : {},
5342
5354
  ...input.ad_discovery !== void 0 ? { ad_discovery: input.ad_discovery } : {},
5355
+ ...input.max_discovered_ads !== void 0 ? { max_discovered_ads: input.max_discovered_ads } : {},
5343
5356
  ...pickRepeatRetryBody(input)
5344
5357
  };
5345
5358
  const result = await ctx.api.createScan(body);
@@ -5399,7 +5412,7 @@ var GetScanCreativeScreenshotInputShape = {
5399
5412
  };
5400
5413
  var getScanCreativeScreenshotTool = {
5401
5414
  name: "get_scan_creative_screenshot",
5402
- description: "Fetch the creative screenshot for an ad-tag scan as an inline image (base64-encoded PNG). Returns 404 if the scan is not an ad-tag scan or has no creative captured yet.",
5415
+ description: "Fetch the creative screenshot for an ad-tag scan as an inline image (base64-encoded WebP \u2014 the API stores and serves every screenshot as WebP, so the client must be able to decode it). Returns 404 if the scan is not an ad-tag scan or has no creative captured yet.",
5403
5416
  annotations: {
5404
5417
  title: "Get Scan Creative Screenshot",
5405
5418
  readOnlyHint: true,
@@ -5444,7 +5457,7 @@ var GetScanLandingScreenshotInputShape = {
5444
5457
  };
5445
5458
  var getScanLandingScreenshotTool = {
5446
5459
  name: "get_scan_landing_screenshot",
5447
- description: "Fetch the screenshot of one landing tab on an ad-tag scan as an inline image. Use `get_scan` first to discover available `landings[*].ord` values.",
5460
+ description: "Fetch the screenshot of one landing tab on an ad-tag scan as an inline image (base64-encoded WebP \u2014 the API stores and serves every screenshot as WebP, so the client must be able to decode it). Use `get_scan` first to discover available `landings[*].ord` values.",
5448
5461
  annotations: {
5449
5462
  title: "Get Scan Landing Screenshot",
5450
5463
  readOnlyHint: true,
@@ -5471,7 +5484,7 @@ var GetScanScreenshotInputShape = {
5471
5484
  };
5472
5485
  var getScanScreenshotTool = {
5473
5486
  name: "get_scan_screenshot",
5474
- description: "Fetch the primary screenshot for a scan as an inline image (base64-encoded PNG). Pass `width` to request a resized version (50-2000 px). Returns one MCP image content block.",
5487
+ description: "Fetch the primary screenshot for a scan as an inline image (base64-encoded WebP \u2014 the API stores and serves every screenshot as WebP, so the client must be able to decode it). Pass `width` to request a resized version (50-2000 px). Returns one MCP image content block.",
5475
5488
  annotations: {
5476
5489
  title: "Get Scan Screenshot",
5477
5490
  readOnlyHint: true,
@@ -6227,5 +6240,5 @@ function formatToolError(error) {
6227
6240
  }
6228
6241
 
6229
6242
  export { BearerToken, SERVER_INSTRUCTIONS, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
6230
- //# sourceMappingURL=chunk-FA5A6Y4H.js.map
6231
- //# sourceMappingURL=chunk-FA5A6Y4H.js.map
6243
+ //# sourceMappingURL=chunk-MYBWPFWG.js.map
6244
+ //# sourceMappingURL=chunk-MYBWPFWG.js.map