@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 +39 -0
- package/dist/bin.js +3 -3
- package/dist/{chunk-7DSLLKEK.js → chunk-3CY2WEZF.js} +31 -7
- package/dist/chunk-3CY2WEZF.js.map +1 -0
- package/dist/{chunk-RBCMUVI6.js → chunk-SQVFFWOB.js} +3 -3
- package/dist/{chunk-RBCMUVI6.js.map → chunk-SQVFFWOB.js.map} +1 -1
- package/dist/{http-bootstrap-TGX6STYD.js → http-bootstrap-X2Y2VGBO.js} +13 -5
- package/dist/http-bootstrap-X2Y2VGBO.js.map +1 -0
- package/dist/{stdio-bootstrap-7GVABHZQ.js → stdio-bootstrap-JBLNH46R.js} +8 -5
- package/dist/stdio-bootstrap-JBLNH46R.js.map +1 -0
- package/package.json +6 -2
- package/dist/chunk-7DSLLKEK.js.map +0 -1
- package/dist/http-bootstrap-TGX6STYD.js.map +0 -1
- package/dist/stdio-bootstrap-7GVABHZQ.js.map +0 -1
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-
|
|
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-
|
|
165
|
+
const { bootstrapStdio } = await import('./stdio-bootstrap-JBLNH46R.js');
|
|
166
166
|
return bootstrapStdio(config);
|
|
167
167
|
}
|
|
168
|
-
const { bootstrapHttp } = await import('./http-bootstrap-
|
|
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-
|
|
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-
|
|
5356
|
-
//# sourceMappingURL=chunk-
|
|
5378
|
+
export { BearerToken, SERVER_INSTRUCTIONS, createHttpApiGateway, createPinoLogger, declareEmptyResourcesAndPrompts, newRequestId, wireToolsIntoMcpServer };
|
|
5379
|
+
//# sourceMappingURL=chunk-3CY2WEZF.js.map
|
|
5380
|
+
//# sourceMappingURL=chunk-3CY2WEZF.js.map
|