@cookiemunch/mcp 0.7.1 → 0.9.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
@@ -2,6 +2,15 @@
2
2
 
3
3
  Every published release, newest first. Dates are the day the version was cut. Each release tracks the same-numbered `@cookiemunch/sdk`.
4
4
 
5
+ ## 0.9.0 (2026-10-30)
6
+
7
+ - Added: `get_site_upcoming_regulations`. Built on `@cookiemunch/sdk` 0.9.0.
8
+
9
+ ## 0.8.0 (2026-10-30)
10
+
11
+ - Added: `connect_dsar_executor` takes `mintFrom` and `externalId`; `secretKey` is optional. Built on `@cookiemunch/sdk` 0.8.0.
12
+ - Added: `connect_identity_provider`: one-call connect for an identity provider's privacy orchestrator.
13
+
5
14
  ## 0.7.1 (2026-10-24)
6
15
 
7
16
  - Changed: tool descriptions name each vendor's own embed manifest (`/.well-known/<product>-embed.json`); built on `@cookiemunch/sdk` 0.7.1.
package/dist/bin.cjs CHANGED
@@ -17,7 +17,7 @@ function registerConfigTools(tool, client) {
17
17
  const blockingModeEnum = import_zod.z.enum(["auto", "manual"]);
18
18
  const bannerModeEnum = import_zod.z.enum(["opt-in", "opt-out", "off"]);
19
19
  const bannerTypeEnum = import_zod.z.enum(["multilevel", "inline", "accept-decline", "accept-only", "do-not-sell"]);
20
- const bannerLayoutEnum = import_zod.z.enum(["top", "bottom", "push-down", "popup", "overlay"]);
20
+ const bannerLayoutEnum = import_zod.z.enum(["top", "bottom", "push-down", "popup", "overlay", "sidebar"]);
21
21
  const consentModeModeEnum = import_zod.z.enum(["basic", "advanced"]);
22
22
  const geoRuleSchema = import_zod.z.object({
23
23
  match: import_zod.z.object({
@@ -193,9 +193,14 @@ function registerConfigTools(tool, client) {
193
193
  const setBannerBasicsSchema = import_zod.z.object({
194
194
  cbid: import_zod.z.string().describe("Site identifier (cbid)."),
195
195
  type: bannerTypeEnum.optional().describe("Banner type. multilevel | inline | accept-decline | accept-only | do-not-sell."),
196
- layout: bannerLayoutEnum.optional().describe("Banner layout. top | bottom | push-down | popup | overlay."),
196
+ layout: bannerLayoutEnum.optional().describe("Banner layout. top | bottom | push-down | popup | overlay | sidebar."),
197
197
  preset: import_zod.z.enum(["bar", "box", "full"]).optional().describe("Named shape that sets type/secondLayer (and layout for box): bar = slim one-row bar + categories in a modal; box = centred card + modal; full = every category in the first layer."),
198
- secondLayer: import_zod.z.enum(["expand", "popup", "modal"]).optional().describe("Where the categories open from an inline banner."),
198
+ secondLayer: import_zod.z.enum(["expand", "popup", "modal", "sidebar"]).optional().describe("Where the categories open from an inline banner."),
199
+ sidebar: import_zod.z.object({
200
+ side: import_zod.z.enum(["left", "right"]).optional(),
201
+ width: import_zod.z.number().min(280).max(640).optional(),
202
+ backdrop: import_zod.z.boolean().optional()
203
+ }).optional().describe("The drawer of a sidebar layout or second layer: side (default right, mirrored for RTL), width in px 280\u2013640 (default 400), backdrop (default true). Merged onto the stored value."),
199
204
  density: import_zod.z.enum(["comfortable", "compact"]).optional().describe("compact = one-row bar from 760px wide."),
200
205
  theme: import_zod.z.record(import_zod.z.unknown()).optional().describe("Partial ThemeTokens \u2014 deep-merged onto the existing banner theme. Includes `scrollbar`: { style: themed|thin|native|hidden, thumb?, thumbHover?, track?, width? 4\u201316, radius? 0\u2013999 }."),
201
206
  content: import_zod.z.record(import_zod.z.unknown()).optional().describe("Partial BannerContent \u2014 banner copy overrides (title, body, button labels, policyUrl, etc.).")
@@ -205,7 +210,7 @@ function registerConfigTools(tool, client) {
205
210
  "Configure v1 banner appearance for a site: preset, type, layout, second layer, density, theme tokens, and copy (content.preferencesTitle titles the preferences dialog). Fetches the current config, patches only those banner fields, and PUTs. Setting type or secondLayer (or layout under the box preset) without a preset removes the stored preset, which would otherwise re-derive them.",
206
211
  setBannerBasicsSchema.shape,
207
212
  async (a) => {
208
- const { cbid: siteId, type, layout, preset, secondLayer, density, theme, content } = setBannerBasicsSchema.parse(a);
213
+ const { cbid: siteId, type, layout, preset, secondLayer, sidebar, density, theme, content } = setBannerBasicsSchema.parse(a);
209
214
  const cfg = await client.sites.getConfig(siteId);
210
215
  const existingBanner = cfg["banner"] ?? {};
211
216
  const existingTheme = existingBanner["theme"] ?? {};
@@ -215,12 +220,14 @@ function registerConfigTools(tool, client) {
215
220
  ...type !== void 0 ? { type } : {},
216
221
  ...layout !== void 0 ? { layout } : {},
217
222
  ...secondLayer !== void 0 ? { secondLayer } : {},
223
+ ...sidebar !== void 0 ? { sidebar: { ...existingBanner["sidebar"], ...sidebar } } : {},
218
224
  ...density !== void 0 ? { density } : {},
219
225
  ...preset !== void 0 ? { preset } : {},
220
226
  ...theme !== void 0 ? { theme: { ...existingTheme, ...theme } } : {},
221
227
  ...content !== void 0 ? { content: { ...existingContent, ...content } } : {}
222
228
  };
223
- const owned = type !== void 0 || secondLayer !== void 0 || layout !== void 0 && banner["preset"] === "box";
229
+ const ownedLayout = layout !== void 0 && (banner["preset"] === "box" || banner["preset"] === "bar" && !["top", "bottom", "push-down"].includes(layout));
230
+ const owned = type !== void 0 || secondLayer !== void 0 || ownedLayout;
224
231
  if (preset === void 0 && owned) delete banner["preset"];
225
232
  return client.sites.putConfig(siteId, { ...cfg, banner });
226
233
  }
@@ -514,6 +521,19 @@ function registerPlatformTools(tool, client) {
514
521
  { days: import_zod2.z.number().int().positive().optional() },
515
522
  (a) => client.regulatory.upcoming(a.days)
516
523
  );
524
+ tool(
525
+ "get_site_upcoming_regulations",
526
+ "Privacy laws taking effect soon (default 90 days) where a site\u2019s visitors are: those whose jurisdiction holds at least minShare (default 0.01) of the site\u2019s last 30 days of consent decisions. Each has daysUntil, trafficShare and, for a US state law, what changes (GPC duty, sensitive-data opt-in, minors rule). A shipped dataset with a review date, not legal advice.",
527
+ {
528
+ cbid: import_zod2.z.string().describe("The site id."),
529
+ days: import_zod2.z.number().int().positive().optional(),
530
+ minShare: import_zod2.z.number().min(0).max(1).optional()
531
+ },
532
+ (a) => client.regulatory.upcomingForSite(a.cbid, {
533
+ ...a.days !== void 0 ? { days: a.days } : {},
534
+ ...a.minShare !== void 0 ? { minShare: a.minShare } : {}
535
+ })
536
+ );
517
537
  tool(
518
538
  "get_dsr_sla",
519
539
  "The rights queue at a glance: how many requests are overdue, due today, due soon or on track, plus the overdue ids.",
@@ -557,8 +577,10 @@ function registerPlatformTools(tool, client) {
557
577
  revokeAtlasIdGrant: import_zod2.z.boolean().optional().describe("A preset param, when the preset's params list it: default false. True adds an optional step that revokes the person's app grant on erasure; a credential without the scope reports skipped: insufficient_scope."),
558
578
  label: import_zod2.z.string().optional().describe("Your name for the credential, shown beside keyPrefix."),
559
579
  system: import_zod2.z.string().optional().describe("The name this connection answers to in a plan, e.g. identity or crm. Required unless the preset has a default."),
560
- baseUrl: import_zod2.z.string().optional().describe("The system's public https origin. Required unless the preset sets it."),
561
- secretKey: import_zod2.z.string().describe("Its API key, with whatever scope that system needs to export and erase a user."),
580
+ baseUrl: import_zod2.z.string().optional().describe("The system's public https origin, or a base with a path (cm-standard-v1 v4 on: the path replaces /api/privacy; cm-standard-v2: the contract paths hang off it). Required unless the preset sets it."),
581
+ secretKey: import_zod2.z.string().optional().describe("Its API key, with whatever scope that system needs to export and erase a user. Send this or mintFrom."),
582
+ mintFrom: import_zod2.z.string().optional().describe("In place of secretKey: a partner id (one that registered an executorKeyUrl, e.g. chatly, forumulate, referalli) that mints the key for the site under its partner link. The connection is scoped to that site. With dryRun, the answer's mint says who would mint it; nothing is minted."),
583
+ externalId: import_zod2.z.string().optional().describe("With mintFrom: the partner account the key is minted for. Default: the one the site's live link for that partner names."),
562
584
  webhookSecret: import_zod2.z.string().optional().describe("Signing secret of its webhook endpoint. Optional: polling closes tasks without it."),
563
585
  auto: import_zod2.z.boolean().optional().describe("Open a sub-task automatically when a request reaches fulfilment. Default true."),
564
586
  orchestrator: import_zod2.z.union([import_zod2.z.literal(1), import_zod2.z.literal(2)]).optional().describe("How it takes part in cases. Default 2 (v2 headers on every call); 1 is the v1 adapter. The answer carries a completionSecret, shown once, that signs its completions."),
@@ -927,12 +949,12 @@ function registerKeyAndTagTools(tool, client) {
927
949
  const tagsSchema = import_zod4.z.object({
928
950
  type: import_zod4.z.enum(TAGGED),
929
951
  id: import_zod4.z.string(),
930
- metadata: import_zod4.z.record(import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])).describe("Keys to set; null removes one. forgedeck_sandbox cannot be set here."),
952
+ metadata: import_zod4.z.record(import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])).describe("Keys to set; null removes one. stack_sandbox cannot be set here."),
931
953
  dryRun: import_zod4.z.boolean().optional().describe("Answer with the diff, storing nothing. Do this first.")
932
954
  });
933
955
  tool(
934
956
  "update_resource_tags",
935
- "Change a resource\u2019s tags (merge). For adopting resources created before tags existed, e.g. forgedeck_product and forgedeck_env. A resource can never be made a sandbox after it was created.",
957
+ "Change a resource\u2019s tags (merge). For adopting resources created before tags existed, e.g. stack_product and stack_env. A resource can never be made a sandbox after it was created.",
936
958
  tagsSchema.shape,
937
959
  (a) => {
938
960
  const { type, id, metadata, dryRun } = tagsSchema.parse(a);
@@ -967,7 +989,7 @@ function registerKeyAndTagTools(tool, client) {
967
989
  );
968
990
  tool(
969
991
  "get_provision_env",
970
- "What `forgedeck env` writes for a product provisioned with this forgedeck ref: variable names, non-secret values (cbid, script URL, API base) and references for secrets, never a secret. Read-only.",
992
+ "What `env` writes for a product provisioned with this stack ref: variable names, non-secret values (cbid, script URL, API base) and references for secrets, never a secret. Read-only.",
971
993
  { ref: import_zod4.z.string() },
972
994
  (a) => client.provisionEnv(a.ref)
973
995
  );
@@ -1413,13 +1435,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1413
1435
  type: import_zod6.z.string().describe("access | deletion | closure | restriction | rectification, or erasure / erase / export."),
1414
1436
  emails: import_zod6.z.array(import_zod6.z.string()).optional().describe("The person's addresses."),
1415
1437
  identity: import_zod6.z.object({ iss: import_zod6.z.string(), sub: import_zod6.z.string(), ext: import_zod6.z.string().optional(), principal: import_zod6.z.string().optional() }).optional().describe("A signed-in identity from the site's sign-in issuer. People are never linked on email when it is present."),
1416
- source: import_zod6.z.enum(["product", "atlas", "admin"]).optional(),
1438
+ source: import_zod6.z.enum(["product", "identity", "admin"]).optional().describe("identity: the site's sign-in provider, whichever it is."),
1417
1439
  reason: import_zod6.z.string().optional(),
1418
1440
  skipSystems: import_zod6.z.array(import_zod6.z.string()).optional().describe("System names, connection ids, or self."),
1419
1441
  fulfill: import_zod6.z.boolean().optional(),
1420
1442
  test: import_zod6.z.boolean().optional(),
1421
1443
  idempotencyKey: import_zod6.z.string().optional(),
1422
- trace: import_zod6.z.string().optional().describe("An X-ForgeDeck-Trace to keep, from the caller.")
1444
+ trace: import_zod6.z.string().optional().describe("An X-Trace-Id to keep, from the caller.")
1423
1445
  },
1424
1446
  (a) => client.dsar.openCase(
1425
1447
  {
@@ -1458,7 +1480,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1458
1480
  );
1459
1481
  tool(
1460
1482
  "find_dsar_by_trace",
1461
- "The rights request carrying one X-ForgeDeck-Trace id \u2014 to follow one event across products. Read-only.",
1483
+ "The rights request carrying one X-Trace-Id id \u2014 to follow one event across products. Read-only.",
1462
1484
  { trace: import_zod6.z.string() },
1463
1485
  (a) => client.dsar.listByTrace(a.trace)
1464
1486
  );
@@ -1488,6 +1510,22 @@ ${JSON.stringify(r, null, 2)}` : r;
1488
1510
  typeof a.iss === "string" && typeof a.sub === "string" ? { iss: a.iss, sub: a.sub } : { email: String(a.email ?? "") }
1489
1511
  )
1490
1512
  );
1513
+ tool(
1514
+ "connect_identity_provider",
1515
+ "Connect an identity provider's privacy orchestrator in one call, so it opens a rights case here when a person deletes their account there. Mints a key holding only dsar:write, locked to the site (no keys:write needed), and hands it to the provider, authorised with the provider instance key. The minted key is never returned, only its prefix; connecting again replaces it. Built in: atlas. Any other provider: pass connector. Run with dryRun first: it mints and sends nothing.",
1516
+ {
1517
+ provider: import_zod6.z.string().describe("The provider id, e.g. atlas."),
1518
+ cbid: import_zod6.z.string().describe("The site the provider opens cases on."),
1519
+ providerKey: import_zod6.z.string().describe("The provider instance's secret key (Atlas: the instance secret key). Used for this one call, never stored."),
1520
+ connector: import_zod6.z.object({ url: import_zod6.z.string(), method: import_zod6.z.enum(["PUT", "POST"]).optional(), body: import_zod6.z.record(import_zod6.z.unknown()) }).optional().describe('Only for a provider with no built-in connector: its https orchestrator URL and JSON body; a body value "{apiKey}" becomes the minted key.'),
1521
+ dryRun: import_zod6.z.boolean().optional().describe("Show the key and the request that would be made, minting and sending nothing.")
1522
+ },
1523
+ (a) => client.integrations.connect(
1524
+ a.provider,
1525
+ { cbid: a.cbid, providerKey: a.providerKey, ...a.connector ? { connector: a.connector } : {} },
1526
+ { dryRun: a.dryRun === true }
1527
+ )
1528
+ );
1491
1529
  tool(
1492
1530
  "advance_dsar",
1493
1531
  "Advance a DSAR to a new status (received \u2192 verifying \u2192 in_progress \u2192 completed, or rejected).",
@@ -1875,7 +1913,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1875
1913
  (a) => client.sites.applyImport(a.cbid, a.data, a.overwrite ? { overwrite: true } : void 0)
1876
1914
  );
1877
1915
  const declarationShape = {
1878
- category: import_zod6.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
1916
+ category: import_zod6.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.suite or categories.custom ids."),
1879
1917
  purpose: import_zod6.z.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
1880
1918
  purposes: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string().max(1e3)).nullable().optional().describe('The purpose in other languages, keyed by BCP-47 tag: {"es": "\u2026", "pt-BR": "\u2026"}. The banner, data-cc="declaration" and cookie-declaration.js draw the visitor\u2019s language. null clears.'),
1881
1919
  provider: import_zod6.z.string().optional(),
@@ -2425,7 +2463,7 @@ ${JSON.stringify(r, null, 2)}` : r;
2425
2463
  }
2426
2464
 
2427
2465
  // src/index.ts
2428
- var MCP_VERSION = "0.7.1";
2466
+ var MCP_VERSION = "0.9.0";
2429
2467
  function createCookieMunchMcp(opts) {
2430
2468
  const client = opts.client ?? (0, import_sdk.createCookieMunch)({ apiKey: opts.apiKey, baseUrl: opts.baseUrl, userAgent: opts.userAgent ?? `cookiemunch-mcp/${MCP_VERSION}` });
2431
2469
  const server = new import_mcp.McpServer({ name: "cookiemunch", version: "1.0.0" });