@kaminari-ad/mcp 0.4.0 → 0.5.2

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,8 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.2] - 2026-06-20
11
+
12
+ ### Security
13
+
14
+ - **Bump `undici` 8.3.0 to 8.5.0** to clear the npm-audit gate after the
15
+ upstream disclosure of seven high-severity advisories (TLS validation
16
+ bypass, shared-cache disclosure, Set-Cookie SameSite downgrade, header
17
+ injection, WebSocket DoS). `undici` is a direct dependency.
18
+
19
+ ### Added
20
+
21
+ - **Security response headers on the HTTP transport.** Every HTTP
22
+ response now carries `Strict-Transport-Security`,
23
+ `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`,
24
+ `Referrer-Policy: no-referrer`, and `Permissions-Policy`. These moved
25
+ off the upstream edge proxy so `mcp.kaminari.ad` is self-contained. No
26
+ CORS and no org-identifying headers are added (tenant-isolation rules).
27
+
28
+ > `0.5.1` was tagged prematurely (before the version bump) and is
29
+ > superseded by `0.5.2`; it was never published to npm.
30
+
31
+ ## [0.5.0] - 2026-06-17
32
+
10
33
  ### Added
11
34
 
35
+ - **Ready-made scan report links.** `get_scan`, `list_scans`, and
36
+ `list_run_scans` now surface `report_url` (authenticated dashboard
37
+ report) and `public_report_url` (shareable, no-login) for every scan,
38
+ and `screenshot_url` / `creative_screenshot_url` are absolute URLs.
39
+ The agent links to a scan using these fields verbatim instead of
40
+ hand-building URLs (it previously guessed the apex host instead of the
41
+ `app.kaminari.ad` SPA host). A new MCP server `instructions` string
42
+ (advertised on both transports during `initialize`) reinforces the
43
+ rule: never construct scan/app URLs — use the ones the API returns.
12
44
  - **OAuth 2.0 Protected Resource discovery.** The HTTP transport now
13
45
  serves `GET /.well-known/oauth-protected-resource` (RFC 9728) and
14
46
  returns `WWW-Authenticate: Bearer resource_metadata="…", scope="…"`
@@ -62,6 +94,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
62
94
  were no-ops; removing them is non-breaking (unknown keys were
63
95
  already stripped by input validation).
64
96
 
97
+ ### Security
98
+
99
+ - **Cleared the `audit:deps` gate (5 advisories).** `npm audit fix`
100
+ resolved form-data (high), vite (high), and `@babel/core`; `js-yaml`
101
+ is forced to `4.2.0` via `overrides` (transitive through the dev-only
102
+ `@redocly/openapi-core`). Runtime dependencies are unchanged.
103
+
65
104
  ## [0.3.0] - 2026-05-20
66
105
 
67
106
  Major-feature release — full parity with the API surface added in
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { NAME, VERSION, err, ok } from './chunk-RBCMUVI6.js';
2
+ import { NAME, VERSION, err, ok } from './chunk-SQVFFWOB.js';
3
3
  import process from 'process';
4
4
  import { z } from 'zod';
5
5
 
@@ -162,10 +162,10 @@ async function main() {
162
162
  }
163
163
  const config = configResult.value;
164
164
  if (config.transport === "stdio") {
165
- const { bootstrapStdio } = await import('./stdio-bootstrap-7GVABHZQ.js');
165
+ const { bootstrapStdio } = await import('./stdio-bootstrap-JBLNH46R.js');
166
166
  return bootstrapStdio(config);
167
167
  }
168
- const { bootstrapHttp } = await import('./http-bootstrap-TGX6STYD.js');
168
+ const { bootstrapHttp } = await import('./http-bootstrap-X2Y2VGBO.js');
169
169
  return bootstrapHttp(config);
170
170
  }
171
171
  main().then(
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { err, ok } from './chunk-RBCMUVI6.js';
2
+ import { err, ok } from './chunk-SQVFFWOB.js';
3
3
  import { createHash, randomUUID } from 'crypto';
4
4
  import createClient from 'openapi-fetch';
5
5
  import { fetch } from 'undici';
@@ -332,6 +332,8 @@ var ScanResponse = z.object({
332
332
  offer_url: z.string(),
333
333
  redirect_chain: z.array(RedirectHopResponse),
334
334
  screenshot_url: z.string().optional().default(""),
335
+ report_url: z.string().optional().default(""),
336
+ public_report_url: z.string().optional().default(""),
335
337
  ad_tag: z.union([z.string(), z.null()]).optional(),
336
338
  creative_screenshot_url: z.string().optional().default(""),
337
339
  creative_width: z.number().int().optional().default(0),
@@ -357,6 +359,8 @@ var ScanBriefResponse = z.object({
357
359
  status: ScanStatus,
358
360
  offer_url: z.string(),
359
361
  screenshot_url: z.string().optional().default(""),
362
+ report_url: z.string().optional().default(""),
363
+ public_report_url: z.string().optional().default(""),
360
364
  labels: z.record(z.string()).optional(),
361
365
  classification: z.union([ScanClassificationResponse, z.null()]).optional(),
362
366
  elapsed_ms: z.number().int(),
@@ -533,6 +537,8 @@ var ScanTileResponse = z.object({
533
537
  status: z.string(),
534
538
  offer_url: z.string().optional().default(""),
535
539
  screenshot_url: z.string().optional().default(""),
540
+ report_url: z.string().optional().default(""),
541
+ public_report_url: z.string().optional().default(""),
536
542
  elapsed_ms: z.number().int().optional().default(0),
537
543
  error: z.string().optional().default("")
538
544
  }).passthrough();
@@ -1630,6 +1636,8 @@ var ScanTileSchema = schemas.ScanTileResponse.pick({
1630
1636
  status: true,
1631
1637
  offer_url: true,
1632
1638
  screenshot_url: true,
1639
+ report_url: true,
1640
+ public_report_url: true,
1633
1641
  elapsed_ms: true,
1634
1642
  error: true
1635
1643
  }).strip();
@@ -1642,6 +1650,8 @@ var ScanSchema = schemas.ScanResponse.pick({
1642
1650
  status: true,
1643
1651
  offer_url: true,
1644
1652
  screenshot_url: true,
1653
+ report_url: true,
1654
+ public_report_url: true,
1645
1655
  ad_tag: true,
1646
1656
  creative_screenshot_url: true,
1647
1657
  page_title: true,
@@ -1665,6 +1675,8 @@ var ScanBriefSchema = schemas.ScanBriefResponse.pick({
1665
1675
  status: true,
1666
1676
  offer_url: true,
1667
1677
  screenshot_url: true,
1678
+ report_url: true,
1679
+ public_report_url: true,
1668
1680
  labels: true,
1669
1681
  elapsed_ms: true,
1670
1682
  campaign_id: true,
@@ -2534,6 +2546,18 @@ function wrap(impl) {
2534
2546
  }
2535
2547
  };
2536
2548
  }
2549
+
2550
+ // src/shared/server-instructions.ts
2551
+ var SERVER_INSTRUCTIONS = [
2552
+ "Kaminari Ad \u2014 ad-verification API (malvertising, scams, policy violations).",
2553
+ "",
2554
+ "Linking to a scan: use the URL fields the tools return \u2014 never build or guess them.",
2555
+ "- `report_url`: authenticated dashboard report (requires login).",
2556
+ "- `public_report_url`: shareable report (no login).",
2557
+ "- `screenshot_url` / `creative_screenshot_url`: absolute, directly followable.",
2558
+ "These come from `get_scan`, `list_scans`, and `list_run_scans`. Do NOT assemble",
2559
+ "scan/app URLs from a base host yourself \u2014 the apex domain does not serve scan pages."
2560
+ ].join("\n");
2537
2561
  function declareEmptyResourcesAndPrompts(server) {
2538
2562
  server.server.registerCapabilities({ resources: {}, prompts: {} });
2539
2563
  server.server.setRequestHandler(ListResourcesRequestSchema, async () => {
@@ -4480,7 +4504,7 @@ var ListRunScansInputShape = {
4480
4504
  };
4481
4505
  var listRunScansTool = {
4482
4506
  name: "list_run_scans",
4483
- description: "List the tile-scan items produced by one run (status, country, offer URL, screenshot, elapsed ms, error). For full scan details (input URL, labels, classification, redirect chain) fetch a specific scan via `get_scan`.",
4507
+ description: "List the tile-scan items produced by one run (status, country, offer URL, absolute screenshot URL, report_url + public_report_url deep-links, elapsed ms, error). Link users to a scan with the returned `report_url` (auth dashboard) or `public_report_url` (shareable) \u2014 never hand-build URLs. For full scan details (input URL, labels, classification, redirect chain) fetch a specific scan via `get_scan`.",
4484
4508
  annotations: {
4485
4509
  title: "List Run Scans",
4486
4510
  readOnlyHint: true,
@@ -4601,7 +4625,7 @@ var GetScanInputShape = {
4601
4625
  };
4602
4626
  var getScanTool = {
4603
4627
  name: "get_scan",
4604
- description: "Get full detail for one scan by UUID: status, offer URL, screenshot URL, timing, labels, and the parent campaign if any.",
4628
+ 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. Link users with the returned `report_url` / `public_report_url` \u2014 never construct URLs yourself.",
4605
4629
  annotations: {
4606
4630
  title: "Get Scan",
4607
4631
  readOnlyHint: true,
@@ -4719,7 +4743,7 @@ var ListScansInputShape = {
4719
4743
  };
4720
4744
  var listScansTool = {
4721
4745
  name: "list_scans",
4722
- 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.",
4746
+ 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 scan carries 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.",
4723
4747
  annotations: {
4724
4748
  title: "List Scans",
4725
4749
  readOnlyHint: true,
@@ -5351,6 +5375,6 @@ function formatToolError(error) {
5351
5375
  }
5352
5376
  }
5353
5377
 
5354
- export { BearerToken, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
5355
- //# sourceMappingURL=chunk-7DSLLKEK.js.map
5356
- //# sourceMappingURL=chunk-7DSLLKEK.js.map
5378
+ export { BearerToken, SERVER_INSTRUCTIONS, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
5379
+ //# sourceMappingURL=chunk-3CY2WEZF.js.map
5380
+ //# sourceMappingURL=chunk-3CY2WEZF.js.map