@cookiemunch/mcp 0.2.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.
package/dist/bin.cjs CHANGED
@@ -9,7 +9,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
9
9
  var import_sdk = require("@cookiemunch/sdk");
10
10
 
11
11
  // src/tools.ts
12
- var import_zod4 = require("zod");
12
+ var import_zod5 = require("zod");
13
13
 
14
14
  // src/tools-config.ts
15
15
  var import_zod = require("zod");
@@ -96,7 +96,7 @@ function registerConfigTools(tool, client) {
96
96
  const setLanguagesSchema = import_zod.z.object({
97
97
  cbid: import_zod.z.string().describe("Site identifier (cbid)."),
98
98
  defaultCulture: import_zod.z.string().optional().describe('Default locale/culture code, e.g. "en", "fr". Stored in i18n.defaultCulture.'),
99
- autoDetect: import_zod.z.boolean().optional().describe("Auto-detect visitor language from browser locale. Stored in i18n.autoDetect."),
99
+ autoDetect: import_zod.z.union([import_zod.z.boolean(), import_zod.z.literal("page")]).optional().describe(`true: follow the visitor's browser language; false: defaultCulture for everyone; "page": follow the page's <html lang>, then the browser. Stored in i18n.autoDetect.`),
100
100
  translations: import_zod.z.record(import_zod.z.record(import_zod.z.unknown())).optional().describe("Per-locale banner copy overrides. Merged onto banner.i18n (locale keys preserved)."),
101
101
  overrides: import_zod.z.record(import_zod.z.object({ banner: import_zod.z.record(import_zod.z.string()).optional(), categories: import_zod.z.record(import_zod.z.object({ label: import_zod.z.string().optional(), description: import_zod.z.string().optional() })).optional() })).optional().describe("The site's own copy per language, keyed by tag (de, pt-BR): { banner: { title, body, \u2026 }, categories: { <id>: { label, description } } }. Each language given replaces its entry in i18n.overrides; other languages are kept. Strings the site wrote are shown as written in any language without an override \u2014 stock translations never replace them.")
102
102
  });
@@ -197,7 +197,7 @@ function registerConfigTools(tool, client) {
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
198
  secondLayer: import_zod.z.enum(["expand", "popup", "modal"]).optional().describe("Where the categories open from an inline banner."),
199
199
  density: import_zod.z.enum(["comfortable", "compact"]).optional().describe("compact = one-row bar from 760px wide."),
200
- theme: import_zod.z.record(import_zod.z.unknown()).optional().describe("Partial ThemeTokens \u2014 deep-merged onto the existing banner theme."),
200
+ 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
201
  content: import_zod.z.record(import_zod.z.unknown()).optional().describe("Partial BannerContent \u2014 banner copy overrides (title, body, button labels, policyUrl, etc.).")
202
202
  });
203
203
  tool(
@@ -544,12 +544,16 @@ function registerPlatformTools(tool, client) {
544
544
  "connect_dsar_executor",
545
545
  "Connect a system that runs part of a rights request \u2014 an identity platform, a CRM, anything with a rights API. Cookie Munch is not specific to any platform: the `profile` describes that system's API (paths, the words it uses for export/erase, its status vocabulary, how it signs webhooks), so connecting a new one needs no code. The secret key is stored encrypted and never returned; the response carries the webhook URL to configure in that system. Sub-tasks open automatically once a request reaches fulfilment (after identity verification), and completions are picked up by webhook or by polling.",
546
546
  {
547
- system: import_zod2.z.string().describe("The name this connection answers to in a plan, e.g. identity or crm."),
548
- baseUrl: import_zod2.z.string().describe("The system's public https origin."),
547
+ preset: import_zod2.z.string().optional().describe("Build profile (and, unless the preset takes baseUrl as a param, baseUrl) from a versioned preset instead of sending profile. list_dsar_executor_presets names them, what each needs, and which wait on another platform."),
548
+ presetVersion: import_zod2.z.number().int().optional().describe("With preset: the version to build. Default the latest."),
549
+ orgId: import_zod2.z.string().optional().describe("A preset param, when the preset's params list it."),
550
+ atlasIdAppId: import_zod2.z.string().optional().describe("A preset param, when the preset's params list it: the identity platform's app id, so an erasure also revokes the app's grant."),
551
+ 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."),
552
+ baseUrl: import_zod2.z.string().optional().describe("The system's public https origin. Required unless the preset sets it."),
549
553
  secretKey: import_zod2.z.string().describe("Its API key, with whatever scope that system needs to export and erase a user."),
550
554
  webhookSecret: import_zod2.z.string().optional().describe("Signing secret of its webhook endpoint. Optional: polling closes tasks without it."),
551
555
  auto: import_zod2.z.boolean().optional().describe("Open a sub-task automatically when a request reaches fulfilment. Default true."),
552
- profile: import_zod2.z.record(import_zod2.z.unknown()).describe("How to drive that system: { open, poll, statuses } required, plus optional subjectLookup, auth, idempotencyHeader and webhook. See the connected-systems docs for the shape."),
556
+ profile: import_zod2.z.record(import_zod2.z.unknown()).optional().describe("How to drive that system: { open, poll, statuses } required, plus optional subjectLookup, auth, idempotencyHeader, grantRevoke and webhook. Omit it when using preset."),
553
557
  dryRun: import_zod2.z.boolean().optional().describe("Validate everything and answer the connection that would be created, storing nothing.")
554
558
  },
555
559
  (a) => {
@@ -557,6 +561,28 @@ function registerPlatformTools(tool, client) {
557
561
  return dryRun === true ? client.fulfillment.dryRunConnectExecutor(input) : client.fulfillment.connectExecutor(input);
558
562
  }
559
563
  );
564
+ tool(
565
+ "list_dsar_executor_presets",
566
+ "The versioned executor presets: each one's name, params, latest version, and whether it is usable now or waits on another platform's API (waitingOn names the platform and its spec items). Also this org's canary address for connection tests. Read-only.",
567
+ {},
568
+ () => client.fulfillment.executorPresets()
569
+ );
570
+ tool(
571
+ "upgrade_dsar_executor_preset",
572
+ "Rebuild a connection's profile and address from its preset's latest version (or presetVersion), keeping its id, credentials, system and scope \u2014 or adopt a preset on a hand-written connection by naming it. Answers with a diff. Use dryRun first: the answer shows exactly what would change and nothing is stored.",
573
+ {
574
+ id: import_zod2.z.string().describe("The connection id."),
575
+ preset: import_zod2.z.string().optional().describe("Only to adopt a preset on a connection that has none."),
576
+ presetVersion: import_zod2.z.number().int().optional(),
577
+ orgId: import_zod2.z.string().optional(),
578
+ atlasIdAppId: import_zod2.z.string().optional(),
579
+ dryRun: import_zod2.z.boolean().optional().describe("Answer the diff and change nothing.")
580
+ },
581
+ (a) => {
582
+ const { id, dryRun, ...input } = a;
583
+ return dryRun === true ? client.fulfillment.dryRunUpgradeExecutorPreset(id, input) : client.fulfillment.upgradeExecutorPreset(id, input);
584
+ }
585
+ );
560
586
  tool(
561
587
  "test_dsar_executor_webhook",
562
588
  "Would this webhook delivery from a connected system verify? Runs the receiver's exact check (headers, timestamp tolerance, prefix, HMAC) on headers and a raw body you supply, acts on nothing, and returns { verified, stage, reason } naming the stage that failed. `body` must be the raw request body string, byte for byte. Read-only.",
@@ -590,15 +616,17 @@ function registerPlatformTools(tool, client) {
590
616
  );
591
617
  tool(
592
618
  "test_dsar_executor",
593
- "Try a connected system against one email WITHOUT filing a rights request. Runs its subject lookup and returns the raw upstream answers (credentials removed) and a one-line verdict. The open step is rendered but not sent, unless open is true on an export, which opens and polls a real export once. An erasure is never sent by a test.",
619
+ "Try a connected system against one email (or the org canary, canary: true) WITHOUT filing a rights request. Runs its subject lookup and returns the raw upstream answers (credentials removed) and a one-line verdict; code base_url_redirects means its baseUrl redirects and the verdict names where. The open step is rendered but not sent, unless open is true on an export, which opens and polls a real export once. An erasure is never sent by a test.",
594
620
  {
595
621
  id: import_zod2.z.string().describe("The connection id."),
596
- email: import_zod2.z.string().describe("The address to look up."),
622
+ email: import_zod2.z.string().optional().describe("The address to look up. Omit it with canary."),
623
+ canary: import_zod2.z.boolean().optional().describe("Use this org's canary address \u2014 no real person involved. A canary locate also updates the connection's health."),
597
624
  operation: import_zod2.z.enum(["locate", "export", "erase"]).optional().describe("Default locate."),
598
625
  open: import_zod2.z.boolean().optional().describe("For export only: open a real export and poll it once.")
599
626
  },
600
627
  (a) => client.fulfillment.testExecutor(a.id, {
601
- email: a.email,
628
+ ...typeof a.email === "string" ? { email: a.email } : {},
629
+ ...a.canary === true ? { canary: true } : {},
602
630
  ...a.operation ? { operation: a.operation } : {},
603
631
  ...typeof a.open === "boolean" ? { open: a.open } : {}
604
632
  })
@@ -684,31 +712,107 @@ function registerPlatformTools(tool, client) {
684
712
  );
685
713
  }
686
714
 
687
- // src/tools-rights-page.ts
715
+ // src/tools-integrations.ts
688
716
  var import_zod3 = require("zod");
717
+ function registerIntegrationTools(tool, client) {
718
+ const updateSiteSchema = import_zod3.z.object({
719
+ cbid: import_zod3.z.string().describe("Site identifier (cbid)."),
720
+ domain: import_zod3.z.string().optional().describe("New domain, a bare hostname. A move clears verification: verify the new domain afterwards."),
721
+ name: import_zod3.z.string().nullable().optional().describe("Display name data subjects see on the rights page and in notices; null clears it."),
722
+ aliases: import_zod3.z.array(import_zod3.z.string()).optional().describe("Other hosts serving the site (replaces the list; [] clears it). Accepted consent origins, never verified claims."),
723
+ dryRun: import_zod3.z.boolean().optional().describe("Answer with the diff and its effects, storing nothing.")
724
+ });
725
+ tool(
726
+ "update_site",
727
+ "Rename or move a site: its domain, display name and aliases. The cbid and the consent ledger stay. Moving the domain clears verification; the scanner and preview links follow the new domain. Use dryRun first to see the diff and every effect.",
728
+ updateSiteSchema.shape,
729
+ (a) => {
730
+ const { cbid, dryRun, ...patch } = updateSiteSchema.parse(a);
731
+ return client.sites.update(cbid, patch, { dryRun });
732
+ }
733
+ );
734
+ tool(
735
+ "integration_health",
736
+ "Check every link a site\u2019s privacy wiring depends on: the domain, the snippet and CSP on the live page, connected systems (base URL redirects, a test lookup), webhooks, partner links, Atlas cookie_consent, cookies needing review, the rights page, the mail provider and the request SLA. Each row has ok (null = could not check) and a fix hint. Read-only.",
737
+ { cbid: import_zod3.z.string().optional().describe("Site identifier; optional when the org has one site.") },
738
+ (a) => client.integrationHealth(a.cbid)
739
+ );
740
+ const provisionSchema = import_zod3.z.object({
741
+ product: import_zod3.z.string().describe("A slug naming the product."),
742
+ domain: import_zod3.z.string().describe("The product\u2019s domain (bare hostname)."),
743
+ name: import_zod3.z.string().optional(),
744
+ aliases: import_zod3.z.array(import_zod3.z.string()).optional(),
745
+ cbid: import_zod3.z.string().optional().describe("Update this site instead of matching by domain."),
746
+ atlas: import_zod3.z.object({ secretKey: import_zod3.z.string(), cookieConsent: import_zod3.z.boolean().optional(), dsrWebhook: import_zod3.z.boolean().optional(), frontendApiHost: import_zod3.z.string().optional().describe("Your Atlas frontend API host (auth.example.com): declares the Atlas sign-in cookies on the site.") }).optional().describe("Atlas secret key (sk_\u2026) \u2014 used for this call only, never stored or returned."),
747
+ forumulate: import_zod3.z.object({ token: import_zod3.z.string(), orgId: import_zod3.z.string(), consent: import_zod3.z.boolean().optional(), executorKey: import_zod3.z.boolean().optional(), label: import_zod3.z.string().optional() }).optional().describe("Forumulate org token \u2014 used for this call only, never stored or returned."),
748
+ rightsApi: import_zod3.z.object({ baseUrl: import_zod3.z.string(), secretKey: import_zod3.z.string(), profilePreset: import_zod3.z.string().optional() }).optional(),
749
+ dryRun: import_zod3.z.boolean().optional().describe("Report what each step would do; write nothing on any platform. Run this first.")
750
+ });
751
+ tool(
752
+ "provision_product",
753
+ "Wire a product\u2019s privacy in one call: create or update the site, connected systems, the Atlas request-completion webhook and hosted-page consent banner, and Forumulate consent and executor key. Writes across three platforms; run with dryRun first. Idempotent: a re-run answers every step unchanged. No secret appears in the result.",
754
+ provisionSchema.shape,
755
+ (a) => {
756
+ const { dryRun, ...input } = provisionSchema.parse(a);
757
+ return client.provision(input, { dryRun });
758
+ }
759
+ );
760
+ tool(
761
+ "list_site_partners",
762
+ "Which partner platforms (Forumulate, Atlas) receive this site\u2019s consent events, each with its status, and which partners are on offer. Read-only.",
763
+ { cbid: import_zod3.z.string() },
764
+ (a) => client.sites.listPartners(a.cbid)
765
+ );
766
+ const linkSchema = import_zod3.z.object({
767
+ cbid: import_zod3.z.string(),
768
+ partner: import_zod3.z.enum(["forumulate", "atlas"]),
769
+ externalId: import_zod3.z.string().describe("The partner\u2019s id for the receiving account, e.g. a Forumulate organisation id."),
770
+ label: import_zod3.z.string().optional().describe('Shown with the partner name, e.g. "docs".'),
771
+ events: import_zod3.z.array(import_zod3.z.enum(["consent.recorded", "consent.withdrawn"])).optional(),
772
+ dryRun: import_zod3.z.boolean().optional()
773
+ });
774
+ tool(
775
+ "link_site_partner",
776
+ "Grant a partner platform this site\u2019s consent events (they start flowing out to it). No secret is created: deliveries are signed with Cookie Munch\u2019s own key. Idempotent.",
777
+ linkSchema.shape,
778
+ (a) => {
779
+ const { cbid, dryRun, ...input } = linkSchema.parse(a);
780
+ return client.sites.linkPartner(cbid, input, { dryRun });
781
+ }
782
+ );
783
+ tool(
784
+ "unlink_site_partner",
785
+ "Revoke a partner link: no further consent events go to that partner.",
786
+ { cbid: import_zod3.z.string(), linkId: import_zod3.z.string() },
787
+ (a) => client.sites.unlinkPartner(a.cbid, a.linkId)
788
+ );
789
+ }
790
+
791
+ // src/tools-rights-page.ts
792
+ var import_zod4 = require("zod");
689
793
  function registerRightsTools(tool, client) {
690
- const cbid = { cbid: import_zod3.z.string().describe("Site identifier (cbid). Must belong to your org.") };
794
+ const cbid = { cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org.") };
691
795
  const base = {
692
- baseUpdatedAt: import_zod3.z.union([import_zod3.z.number().int(), import_zod3.z.string(), import_zod3.z.null()]).optional().describe("The draft\u2019s updatedAt from your last read (null if it had none). If someone saved since, the write is refused with 409 draft_conflict and the current draft; omit to overwrite regardless.")
796
+ baseUpdatedAt: import_zod4.z.union([import_zod4.z.number().int(), import_zod4.z.string(), import_zod4.z.null()]).optional().describe("The draft\u2019s updatedAt from your last read (null if it had none). If someone saved since, the write is refused with 409 draft_conflict and the current draft; omit to overwrite regardless.")
693
797
  };
694
798
  const baseOpt = (a) => a.baseUpdatedAt !== void 0 ? { baseUpdatedAt: a.baseUpdatedAt } : {};
695
799
  tool("get_rights_page", "Read the site\u2019s rights page DRAFT (the default page until first saved), with warnings that would block publishing.", cbid, (a) => client.rightsPage.get(a.cbid));
696
800
  tool(
697
801
  "update_rights_page",
698
802
  "Replace the rights page draft with a full document (theme, sections, form, i18n, seo, customCss). Nothing goes live until publish_rights_page. Prefer patch_rights_page for small changes and preview_rights_page when unsure. Pass baseUpdatedAt (from get_rights_page) to avoid overwriting someone else\u2019s save: a mismatch is 409 draft_conflict with the current draft.",
699
- { ...cbid, page: import_zod3.z.record(import_zod3.z.unknown()).describe("The whole RightsPage document (v: 1)."), ...base },
803
+ { ...cbid, page: import_zod4.z.record(import_zod4.z.unknown()).describe("The whole RightsPage document (v: 1)."), ...base },
700
804
  (a) => client.rightsPage.put(a.cbid, a.page, baseOpt(a))
701
805
  );
702
806
  tool(
703
807
  "patch_rights_page",
704
808
  "Change part of the rights page draft: objects merge, arrays (sections, request types, fields) replace whole, null removes a field. baseUpdatedAt works as on update_rights_page (409 draft_conflict).",
705
- { ...cbid, patch: import_zod3.z.record(import_zod3.z.unknown()), ...base },
809
+ { ...cbid, patch: import_zod4.z.record(import_zod4.z.unknown()), ...base },
706
810
  (a) => client.rightsPage.patch(a.cbid, a.patch, baseOpt(a))
707
811
  );
708
812
  tool(
709
813
  "preview_rights_page",
710
814
  'Validate a rights-page write WITHOUT saving: returns the document as it would be stored and any publish warnings. mode "patch" (default) or "put".',
711
- { ...cbid, page: import_zod3.z.record(import_zod3.z.unknown()), mode: import_zod3.z.enum(["patch", "put"]).optional() },
815
+ { ...cbid, page: import_zod4.z.record(import_zod4.z.unknown()), mode: import_zod4.z.enum(["patch", "put"]).optional() },
712
816
  (a) => client.rightsPage.dryRun(a.cbid, a.page, { mode: a.mode ?? "patch" })
713
817
  );
714
818
  tool("get_published_rights_page", "Read the LIVE rights page document (404 not_published while the site shows the default page).", cbid, (a) => client.rightsPage.getPublished(a.cbid));
@@ -722,14 +826,14 @@ function registerRightsTools(tool, client) {
722
826
  tool(
723
827
  "rollback_rights_page",
724
828
  "Publish an earlier version of the rights page again (as a new version): it goes live at once and REPLACES the current draft, so unpublished edits are lost and cannot be recovered (versions hold only published documents). Pass baseUpdatedAt (from get_rights_page) to refuse with 409 draft_conflict if anyone saved the draft since you read it.",
725
- { ...cbid, version: import_zod3.z.number().int().min(1), ...base },
829
+ { ...cbid, version: import_zod4.z.number().int().min(1), ...base },
726
830
  (a) => client.rightsPage.rollback(a.cbid, a.version, baseOpt(a))
727
831
  );
728
832
  }
729
833
  function registerRightsPageTools(tool, client) {
730
- const site = import_zod3.z.object({ cbid: import_zod3.z.string().describe("Site identifier (cbid). Must belong to your org.") });
834
+ const site = import_zod4.z.object({ cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org.") });
731
835
  const host = site.extend({
732
- hostname: import_zod3.z.string().describe("The custom hostname, e.g. privacy.example.com (unicode or punycode).")
836
+ hostname: import_zod4.z.string().describe("The custom hostname, e.g. privacy.example.com (unicode or punycode).")
733
837
  });
734
838
  tool(
735
839
  "list_rights_page_domains",
@@ -869,10 +973,10 @@ function registerTools(server, client) {
869
973
  }
870
974
  });
871
975
  };
872
- const cbid = { cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org.") };
976
+ const cbid = { cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org.") };
873
977
  const range = {
874
- from: import_zod4.z.number().optional().describe("Epoch-ms lower bound."),
875
- to: import_zod4.z.number().optional().describe("Epoch-ms upper bound.")
978
+ from: import_zod5.z.number().optional().describe("Epoch-ms lower bound."),
979
+ to: import_zod5.z.number().optional().describe("Epoch-ms upper bound.")
876
980
  };
877
981
  tool(
878
982
  "whoami",
@@ -890,19 +994,19 @@ function registerTools(server, client) {
890
994
  tool(
891
995
  "get_site",
892
996
  "One site: its domain, cbid and verification status. Read-only.",
893
- { cbid: import_zod4.z.string() },
997
+ { cbid: import_zod5.z.string() },
894
998
  (a) => client.sites.get(a.cbid)
895
999
  );
896
1000
  tool(
897
1001
  "get_site_banner",
898
1002
  "Which banner design a site uses, or bannerId null when none is assigned. Read-only.",
899
- { cbid: import_zod4.z.string() },
1003
+ { cbid: import_zod5.z.string() },
900
1004
  (a) => client.sites.banner(a.cbid)
901
1005
  );
902
1006
  tool(
903
1007
  "get_privacy_policy",
904
1008
  "Generate the site's privacy and cookie policy as Markdown, naming the org's data controller. Needs a contact email: the one given, else the org controller's, else the owner's. Read-only \u2014 nothing is published.",
905
- { cbid: import_zod4.z.string(), contactEmail: import_zod4.z.string().optional(), effectiveDate: import_zod4.z.string().optional().describe("YYYY-MM-DD; defaults to today."), jurisdictions: import_zod4.z.array(import_zod4.z.string()).optional() },
1009
+ { cbid: import_zod5.z.string(), contactEmail: import_zod5.z.string().optional(), effectiveDate: import_zod5.z.string().optional().describe("YYYY-MM-DD; defaults to today."), jurisdictions: import_zod5.z.array(import_zod5.z.string()).optional() },
906
1010
  (a) => client.sites.policy(a.cbid, {
907
1011
  ...a.contactEmail ? { contactEmail: a.contactEmail } : {},
908
1012
  ...a.effectiveDate ? { effectiveDate: a.effectiveDate } : {},
@@ -912,7 +1016,7 @@ function registerTools(server, client) {
912
1016
  tool(
913
1017
  "set_ad_personalization",
914
1018
  "Add or remove the separate 'personalised ads' choice on the site's live banner. With it on, accepting marketing no longer implies personalised ads unless `default` is true.",
915
- { cbid: import_zod4.z.string(), enabled: import_zod4.z.boolean(), default: import_zod4.z.boolean().optional(), label: import_zod4.z.string().optional() },
1019
+ { cbid: import_zod5.z.string(), enabled: import_zod5.z.boolean(), default: import_zod5.z.boolean().optional(), label: import_zod5.z.string().optional() },
916
1020
  (a) => client.sites.setAdPersonalization(a.cbid, {
917
1021
  enabled: a.enabled,
918
1022
  ...a.default !== void 0 ? { default: a.default } : {},
@@ -923,11 +1027,11 @@ function registerTools(server, client) {
923
1027
  "analyze_session",
924
1028
  "Analyse a captured browsing session against the consent it ran under: which trackers fired after the visitor opted out, and what personal data left the page. Read-only.",
925
1029
  {
926
- cbid: import_zod4.z.string(),
927
- har: import_zod4.z.unknown().optional().describe("A HAR export of the session."),
928
- requests: import_zod4.z.array(import_zod4.z.unknown()).optional().describe("Or the requests directly."),
929
- consent: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.boolean()).optional(),
930
- gpc: import_zod4.z.boolean().optional()
1030
+ cbid: import_zod5.z.string(),
1031
+ har: import_zod5.z.unknown().optional().describe("A HAR export of the session."),
1032
+ requests: import_zod5.z.array(import_zod5.z.unknown()).optional().describe("Or the requests directly."),
1033
+ consent: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.boolean()).optional(),
1034
+ gpc: import_zod5.z.boolean().optional()
931
1035
  },
932
1036
  (a) => client.sites.analyzeSession(a.cbid, {
933
1037
  ...a.har !== void 0 ? { har: a.har } : {},
@@ -939,14 +1043,14 @@ function registerTools(server, client) {
939
1043
  tool(
940
1044
  "create_site",
941
1045
  "Create a new site. The cbid is auto-generated if you omit it.",
942
- { domain: import_zod4.z.string().describe("The site domain, e.g. example.com."), cbid: import_zod4.z.string().optional().describe("Optional explicit cbid.") },
1046
+ { domain: import_zod5.z.string().describe("The site domain, e.g. example.com."), cbid: import_zod5.z.string().optional().describe("Optional explicit cbid.") },
943
1047
  (a) => client.sites.create({ domain: a.domain, ...typeof a.cbid === "string" ? { cbid: a.cbid } : {} })
944
1048
  );
945
1049
  tool(
946
1050
  "create_sites_bulk",
947
1051
  "Create up to 100 sites in one call. Partial success: each item reports ok or its own error, and a bad or duplicate item fails only itself.",
948
1052
  {
949
- sites: import_zod4.z.array(import_zod4.z.object({ domain: import_zod4.z.string(), cbid: import_zod4.z.string().optional(), platform: import_zod4.z.string().optional() })).min(1).max(100)
1053
+ sites: import_zod5.z.array(import_zod5.z.object({ domain: import_zod5.z.string(), cbid: import_zod5.z.string().optional(), platform: import_zod5.z.string().optional() })).min(1).max(100)
950
1054
  },
951
1055
  (a) => client.sites.createBulk(a.sites)
952
1056
  );
@@ -956,15 +1060,15 @@ function registerTools(server, client) {
956
1060
  "Replace (overwrite) the banner/consent configuration for a site via PUT. This is destructive, not a merge: any top-level SiteConfig field you omit from `config` reverts to its default rather than keeping its current value \u2014 unless keepUnspecified is true, in which case omitted top-level fields keep their stored value and only the fields you send are replaced (each whole). A top-level field sent as null reverts to its default. To change one setting, use patch_site_config instead \u2014 it merges server-side. Prefer the narrower set_* tools (set_blocking, set_banner_basics, etc.) when they cover your change.",
957
1061
  {
958
1062
  ...cbid,
959
- config: import_zod4.z.record(import_zod4.z.unknown()).describe("The full SiteConfig to write, not a patch. Without keepUnspecified, omitted top-level fields are NOT preserved from the current config."),
960
- keepUnspecified: import_zod4.z.boolean().optional().describe("PUT ?keep=unspecified: keep the stored value of every top-level field `config` omits, instead of reverting it to its default.")
1063
+ config: import_zod5.z.record(import_zod5.z.unknown()).describe("The full SiteConfig to write, not a patch. Without keepUnspecified, omitted top-level fields are NOT preserved from the current config."),
1064
+ keepUnspecified: import_zod5.z.boolean().optional().describe("PUT ?keep=unspecified: keep the stored value of every top-level field `config` omits, instead of reverting it to its default.")
961
1065
  },
962
1066
  (a) => a.keepUnspecified === true ? client.sites.putConfig(a.cbid, a.config, { keep: "unspecified" }) : client.sites.putConfig(a.cbid, a.config)
963
1067
  );
964
1068
  tool(
965
1069
  "patch_site_config",
966
1070
  `Change part of a site's banner/consent configuration. The patch is a JSON Merge Patch (RFC 7386) over the stored config server-side: any field you omit keeps its current value, and a field set to null is REMOVED (it falls back to its default) \u2014 e.g. { "banner": { "i18n": { "es": null } } } drops the Spanish override. This is the safe way to flip one setting, and it needs no read-modify-write. Use update_site_config only when you genuinely mean to replace the whole document.`,
967
- { ...cbid, config: import_zod4.z.record(import_zod4.z.unknown()).describe('The subset of SiteConfig to change, e.g. { "banner": { "showRightsLink": true } }. Everything else is preserved; null removes a field.') },
1071
+ { ...cbid, config: import_zod5.z.record(import_zod5.z.unknown()).describe('The subset of SiteConfig to change, e.g. { "banner": { "showRightsLink": true } }. Everything else is preserved; null removes a field.') },
968
1072
  (a) => client.sites.patchConfig(a.cbid, a.config)
969
1073
  );
970
1074
  tool(
@@ -972,9 +1076,9 @@ function registerTools(server, client) {
972
1076
  'Preview a config change WITHOUT saving it: returns the config as it would be saved, a diff of every field that would change, and any warnings (plan-gated or unrecognised fields). mode "patch" (default) previews patch_site_config; mode "put" previews update_site_config, and its diff lists everything a replace would revert to its default (unless keepUnspecified is true). Use it before any write you are not sure of.',
973
1077
  {
974
1078
  ...cbid,
975
- config: import_zod4.z.record(import_zod4.z.unknown()).describe('The patch (or, with mode "put", the full config) to preview.'),
976
- mode: import_zod4.z.enum(["patch", "put"]).optional().describe("patch (default) merges; put replaces."),
977
- keepUnspecified: import_zod4.z.boolean().optional().describe('With mode "put": preview update_site_config with keepUnspecified (omitted top-level fields keep their stored value).')
1079
+ config: import_zod5.z.record(import_zod5.z.unknown()).describe('The patch (or, with mode "put", the full config) to preview.'),
1080
+ mode: import_zod5.z.enum(["patch", "put"]).optional().describe("patch (default) merges; put replaces."),
1081
+ keepUnspecified: import_zod5.z.boolean().optional().describe('With mode "put": preview update_site_config with keepUnspecified (omitted top-level fields keep their stored value).')
978
1082
  },
979
1083
  (a) => client.sites.dryRunConfig(a.cbid, a.config, {
980
1084
  mode: a.mode ?? "patch",
@@ -986,8 +1090,8 @@ function registerTools(server, client) {
986
1090
  'Check a banner config for consent-button parity WITHOUT saving it: is "Accept all" more prominent than "Reject all" anywhere \u2014 a brighter or more saturated colour, a bigger or bolder button, Reject styled as a link, hidden, below the fold, set apart, missing from the first layer, or worded to guilt-trip? Regulators (EDPB, CNIL) treat that as a dark pattern. Returns findings, a 0\u2013100 score and the reject style that would match Accept. It checks exactly what the write would store: merged over the stored config as patch_site_config would, or with replace: true replaced as update_site_config would. Run it before writing any banner design.',
987
1091
  {
988
1092
  ...cbid,
989
- config: import_zod4.z.record(import_zod4.z.unknown()).describe("The proposed SiteConfig (or a partial one, or a v2 flow design)."),
990
- replace: import_zod4.z.boolean().optional().describe("Check what update_site_config (a full replace) would store, instead of what patch_site_config (a merge) would.")
1093
+ config: import_zod5.z.record(import_zod5.z.unknown()).describe("The proposed SiteConfig (or a partial one, or a v2 flow design)."),
1094
+ replace: import_zod5.z.boolean().optional().describe("Check what update_site_config (a full replace) would store, instead of what patch_site_config (a merge) would.")
991
1095
  },
992
1096
  async (a) => {
993
1097
  const r = await client.sites.lintConfig(a.cbid, a.config, a.replace === true ? { replace: true } : {});
@@ -1011,7 +1115,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1011
1115
  tool(
1012
1116
  "get_consent_log",
1013
1117
  "Get recent anonymised consent records for a site.",
1014
- { ...cbid, ...range, limit: import_zod4.z.number().optional().describe("Max records to return (default 200).") },
1118
+ { ...cbid, ...range, limit: import_zod5.z.number().optional().describe("Max records to return (default 200).") },
1015
1119
  (a) => client.consent.log(a.cbid, {
1016
1120
  from: a.from,
1017
1121
  to: a.to,
@@ -1021,7 +1125,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1021
1125
  tool(
1022
1126
  "get_subject_consent",
1023
1127
  "One person's consent records across every site in the org \u2014 web, mobile and desktop \u2014 by the subjectId your apps attach. Consent data: needs the consent:read scope. Read-only.",
1024
- { subjectId: import_zod4.z.string() },
1128
+ { subjectId: import_zod5.z.string() },
1025
1129
  (a) => client.subjects.consent(a.subjectId)
1026
1130
  );
1027
1131
  tool("list_dsar", "List all Data Subject Access Requests for your organization.", {}, () => client.dsar.list());
@@ -1029,51 +1133,53 @@ ${JSON.stringify(r, null, 2)}` : r;
1029
1133
  "update_dsar_executor",
1030
1134
  "Change a connected system in place \u2014 its profile, address, credential or auto flag. Only what you pass changes; the stored credential is kept unless you give a new one. With dryRun, answers the connection as it would be and a diff, and changes nothing.",
1031
1135
  {
1032
- id: import_zod4.z.string(),
1033
- patch: import_zod4.z.record(import_zod4.z.unknown()),
1034
- dryRun: import_zod4.z.boolean().optional().describe("Validate and diff without saving.")
1136
+ id: import_zod5.z.string(),
1137
+ patch: import_zod5.z.record(import_zod5.z.unknown()),
1138
+ dryRun: import_zod5.z.boolean().optional().describe("Validate and diff without saving.")
1035
1139
  },
1036
1140
  (a) => a.dryRun === true ? client.fulfillment.dryRunUpdateExecutor(a.id, a.patch) : client.fulfillment.updateExecutor(a.id, a.patch)
1037
1141
  );
1038
1142
  tool(
1039
1143
  "get_dsar",
1040
1144
  "One rights request by id, including its status and the deadline it must be answered by.",
1041
- { id: import_zod4.z.string() },
1145
+ { id: import_zod5.z.string() },
1042
1146
  (a) => client.dsar.get(a.id)
1043
1147
  );
1044
1148
  tool(
1045
1149
  "erase_dsar_subject",
1046
1150
  "For a deletion request that is past identity verification: erase the person\u2019s consent records on one site, identified by their consent stamp. Irreversible. The erasure is noted on the request. If the response carries a warning, nothing was cryptographically erased \u2014 tell the user.",
1047
- { id: import_zod4.z.string(), cbid: import_zod4.z.string(), stamp: import_zod4.z.string() },
1151
+ { id: import_zod5.z.string(), cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1048
1152
  (a) => client.dsar.erase(a.id, a.cbid, a.stamp)
1049
1153
  );
1050
1154
  tool(
1051
1155
  "export_dsar_subject",
1052
1156
  "For an access or portability request that is past identity verification: the person\u2019s consent records on one site, identified by their consent stamp. The export is noted on the request.",
1053
- { id: import_zod4.z.string(), cbid: import_zod4.z.string(), stamp: import_zod4.z.string() },
1157
+ { id: import_zod5.z.string(), cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1054
1158
  (a) => client.dsar.export(a.id, a.cbid, a.stamp)
1055
1159
  );
1056
1160
  tool(
1057
1161
  "get_dsar_response_notice",
1058
1162
  "The subject-facing response notice for a request, as plain text \u2014 what to send the person. Read-only; nothing is sent.",
1059
- { id: import_zod4.z.string() },
1163
+ { id: import_zod5.z.string() },
1060
1164
  (a) => client.dsar.response(a.id)
1061
1165
  );
1062
1166
  tool(
1063
1167
  "create_dsar",
1064
1168
  "Open a new Data Subject Access Request.",
1065
1169
  {
1066
- type: import_zod4.z.enum(["access", "deletion", "rectification", "portability", "opt-out"]).describe("DSAR right being exercised."),
1067
- subjectEmail: import_zod4.z.string().describe("The data subject\u2019s email."),
1068
- regulation: import_zod4.z.enum(["gdpr", "ccpa"]).describe("Governing regulation."),
1069
- note: import_zod4.z.string().optional().describe("Optional free-text note."),
1070
- test: import_zod4.z.boolean().optional().describe("Mark it as a test request: kept off the SLA board and deletable afterwards with delete_test_dsar.")
1170
+ type: import_zod5.z.enum(["access", "deletion", "rectification", "portability", "opt-out"]).describe("DSAR right being exercised."),
1171
+ subjectEmail: import_zod5.z.string().describe("The data subject\u2019s email."),
1172
+ regulation: import_zod5.z.enum(["gdpr", "ccpa"]).describe("Governing regulation."),
1173
+ note: import_zod5.z.string().optional().describe("Optional INTERNAL note; never shown to the data subject."),
1174
+ messageToSubject: import_zod5.z.string().max(2e3).optional().describe("The line the data subject reads in the response notice. Never an API key."),
1175
+ test: import_zod5.z.boolean().optional().describe("Mark it as a test request: kept off the SLA board and deletable afterwards with delete_test_dsar.")
1071
1176
  },
1072
1177
  (a) => client.dsar.create({
1073
1178
  type: a.type,
1074
1179
  subjectEmail: a.subjectEmail,
1075
1180
  regulation: a.regulation,
1076
1181
  ...typeof a.note === "string" ? { note: a.note } : {},
1182
+ ...typeof a.messageToSubject === "string" ? { messageToSubject: a.messageToSubject } : {},
1077
1183
  ...a.test === true ? { test: true } : {}
1078
1184
  })
1079
1185
  );
@@ -1081,11 +1187,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1081
1187
  "create_rights_link",
1082
1188
  "Mint a signed, single-use link to a site\u2019s hosted rights page for a person you know is signed in to that site. On the page their email is filled in and locked and the email-code step is skipped; the filed request is recorded as verified by their account. Give the link only to that person. Expires in 15 minutes by default (max 1 hour). Needs dsar:write.",
1083
1189
  {
1084
- cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org."),
1085
- email: import_zod4.z.string().describe("The signed-in person\u2019s verified email address."),
1086
- userId: import_zod4.z.string().optional().describe("Your own account id for them; recorded on the request."),
1087
- rights: import_zod4.z.array(import_zod4.z.enum(["access", "erasure", "rectification", "portability", "restriction", "objection", "opt_out_sale", "opt_out_targeted", "limit_sensitive"])).min(1).optional().describe("Limit the link to these rights. Default: every right the page offers."),
1088
- ttlSeconds: import_zod4.z.number().int().min(60).max(3600).optional().describe("How long the link works, in seconds (default 900).")
1190
+ cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org."),
1191
+ email: import_zod5.z.string().describe("The signed-in person\u2019s verified email address."),
1192
+ userId: import_zod5.z.string().optional().describe("Your own account id for them; recorded on the request."),
1193
+ rights: import_zod5.z.array(import_zod5.z.enum(["access", "erasure", "rectification", "portability", "restriction", "objection", "opt_out_sale", "opt_out_targeted", "limit_sensitive"])).min(1).optional().describe("Limit the link to these rights. Default: every right the page offers."),
1194
+ ttlSeconds: import_zod5.z.number().int().min(60).max(3600).optional().describe("How long the link works, in seconds (default 900).")
1089
1195
  },
1090
1196
  (a) => client.rightsLinks.create(a.cbid, {
1091
1197
  subject: { email: a.email, ...typeof a.userId === "string" ? { userId: a.userId } : {} },
@@ -1096,7 +1202,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1096
1202
  tool(
1097
1203
  "delete_test_dsar",
1098
1204
  "Delete a TEST rights request (one created with test: true), with its tasks and their upstream log. Real requests cannot be deleted and are refused. The deletion is recorded in the audit log.",
1099
- { id: import_zod4.z.string().describe("The test request id.") },
1205
+ { id: import_zod5.z.string().describe("The test request id.") },
1100
1206
  async (a) => {
1101
1207
  await client.dsar.delete(a.id);
1102
1208
  return { deleted: a.id };
@@ -1105,17 +1211,18 @@ ${JSON.stringify(r, null, 2)}` : r;
1105
1211
  tool(
1106
1212
  "mark_dsar_test",
1107
1213
  "Mark a CLOSED rights request (completed or rejected) as a test request, after the fact \u2014 for trial requests filed before test: true existed. An open request is refused (request_not_closed), so a live obligation can never be relabelled. Recorded in the audit log; afterwards delete_test_dsar can remove it. Returns { request, changed }.",
1108
- { id: import_zod4.z.string().describe("The closed request id.") },
1214
+ { id: import_zod5.z.string().describe("The closed request id.") },
1109
1215
  (a) => client.dsar.markTest(a.id)
1110
1216
  );
1111
1217
  tool(
1112
1218
  "advance_dsar",
1113
1219
  "Advance a DSAR to a new status (received \u2192 verifying \u2192 in_progress \u2192 completed, or rejected).",
1114
1220
  {
1115
- id: import_zod4.z.string().describe("The DSAR id."),
1116
- toStatus: import_zod4.z.enum(["received", "verifying", "in_progress", "completed", "rejected"]).describe("Target status.")
1221
+ id: import_zod5.z.string().describe("The DSAR id."),
1222
+ toStatus: import_zod5.z.enum(["received", "verifying", "in_progress", "completed", "rejected"]).describe("Target status."),
1223
+ messageToSubject: import_zod5.z.string().max(2e3).optional().describe("Replaces the line the data subject reads in the notice \u2014 for a rejection, why.")
1117
1224
  },
1118
- (a) => client.dsar.advance(a.id, a.toStatus)
1225
+ (a) => typeof a.messageToSubject === "string" ? client.dsar.advance(a.id, a.toStatus, { messageToSubject: a.messageToSubject }) : client.dsar.advance(a.id, a.toStatus)
1119
1226
  );
1120
1227
  tool(
1121
1228
  "export_consent",
@@ -1126,7 +1233,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1126
1233
  tool(
1127
1234
  "get_receipt",
1128
1235
  "Fetch the signed consent receipt for a single consent record (by stamp).",
1129
- { ...cbid, stamp: import_zod4.z.string().describe("The consent record stamp/id.") },
1236
+ { ...cbid, stamp: import_zod5.z.string().describe("The consent record stamp/id.") },
1130
1237
  (a) => client.consent.receipt(a.cbid, a.stamp)
1131
1238
  );
1132
1239
  tool("delete_site", "Delete a site (cbid) and its configuration from your org.", { ...cbid }, async (a) => {
@@ -1138,13 +1245,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1138
1245
  "create_vendor",
1139
1246
  "Register a vendor (processor) and compute its risk score.",
1140
1247
  {
1141
- name: import_zod4.z.string().describe("Vendor name."),
1142
- category: import_zod4.z.string().describe("Vendor category, e.g. analytics."),
1143
- dataShared: import_zod4.z.array(import_zod4.z.string()).describe("Categories of data shared with the vendor."),
1144
- dpaSigned: import_zod4.z.boolean().describe("Whether a Data Processing Agreement is signed."),
1145
- subprocessors: import_zod4.z.number().describe("Number of subprocessors."),
1146
- certifications: import_zod4.z.array(import_zod4.z.string()).describe("Compliance certifications, e.g. ISO27001."),
1147
- region: import_zod4.z.string().describe("Primary processing region, e.g. EU.")
1248
+ name: import_zod5.z.string().describe("Vendor name."),
1249
+ category: import_zod5.z.string().describe("Vendor category, e.g. analytics."),
1250
+ dataShared: import_zod5.z.array(import_zod5.z.string()).describe("Categories of data shared with the vendor."),
1251
+ dpaSigned: import_zod5.z.boolean().describe("Whether a Data Processing Agreement is signed."),
1252
+ subprocessors: import_zod5.z.number().describe("Number of subprocessors."),
1253
+ certifications: import_zod5.z.array(import_zod5.z.string()).describe("Compliance certifications, e.g. ISO27001."),
1254
+ region: import_zod5.z.string().describe("Primary processing region, e.g. EU.")
1148
1255
  },
1149
1256
  (a) => client.vendors.create({
1150
1257
  name: a.name,
@@ -1162,13 +1269,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1162
1269
  "create_ropa",
1163
1270
  "Create a Record of Processing Activity (RoPA) entry.",
1164
1271
  {
1165
- name: import_zod4.z.string().describe("Activity name."),
1166
- purpose: import_zod4.z.string().describe("Purpose of processing."),
1167
- legalBasis: import_zod4.z.enum(["consent", "contract", "legal-obligation", "vital-interests", "public-task", "legitimate-interests"]).describe("GDPR legal basis."),
1168
- dataCategories: import_zod4.z.array(import_zod4.z.string()).describe("Categories of personal data."),
1169
- recipients: import_zod4.z.array(import_zod4.z.string()).describe("Recipients of the data."),
1170
- retentionDays: import_zod4.z.number().describe("Retention period in days."),
1171
- crossBorderTransfer: import_zod4.z.boolean().describe("Whether data is transferred across borders.")
1272
+ name: import_zod5.z.string().describe("Activity name."),
1273
+ purpose: import_zod5.z.string().describe("Purpose of processing."),
1274
+ legalBasis: import_zod5.z.enum(["consent", "contract", "legal-obligation", "vital-interests", "public-task", "legitimate-interests"]).describe("GDPR legal basis."),
1275
+ dataCategories: import_zod5.z.array(import_zod5.z.string()).describe("Categories of personal data."),
1276
+ recipients: import_zod5.z.array(import_zod5.z.string()).describe("Recipients of the data."),
1277
+ retentionDays: import_zod5.z.number().describe("Retention period in days."),
1278
+ crossBorderTransfer: import_zod5.z.boolean().describe("Whether data is transferred across borders.")
1172
1279
  },
1173
1280
  (a) => client.ropa.create({
1174
1281
  name: a.name,
@@ -1188,15 +1295,23 @@ ${JSON.stringify(r, null, 2)}` : r;
1188
1295
  );
1189
1296
  tool(
1190
1297
  "scan_site",
1191
- "Trigger a cookie scan for a site. Returns the scan job state.",
1192
- { ...cbid },
1193
- (a) => client.sites.scan(a.cbid)
1298
+ "Trigger a cookie crawl of a site (at most 90 s). Returns its scanId and state (queued). With wait: true, returns once it is done or failed \u2014 state, cookieCount, pagesVisited, durationMs, error. The stored list keeps cookies earlier crawls and real visits found; retire one the site no longer sets.",
1299
+ { ...cbid, wait: import_zod5.z.boolean().optional().describe("Wait for the scan to finish (up to 100 s) and return its outcome.") },
1300
+ async (a) => {
1301
+ let started;
1302
+ try {
1303
+ started = await client.sites.scan(a.cbid);
1304
+ } catch (err) {
1305
+ if (!a.wait || err.status !== 409) throw err;
1306
+ }
1307
+ return a.wait ? client.sites.waitForScan(a.cbid, { timeoutMs: 1e5 }) : started;
1308
+ }
1194
1309
  );
1195
1310
  tool(
1196
1311
  "get_scan_status",
1197
- "Get the status/result of a site\u2019s most recent cookie scan.",
1198
- { ...cbid },
1199
- (a) => client.sites.scanStatus(a.cbid)
1312
+ "Get a site\u2019s last cookie scan: state (queued, scanning, done, failed), scanId, durationMs, cookieCount, pagesVisited and error when it failed.",
1313
+ { ...cbid, wait: import_zod5.z.number().min(0).max(60).optional().describe("Seconds (\u226460) to wait for a running scan to settle before answering.") },
1314
+ (a) => a.wait !== void 0 ? client.sites.scanStatus(a.cbid, { wait: a.wait }) : client.sites.scanStatus(a.cbid)
1200
1315
  );
1201
1316
  tool(
1202
1317
  "get_ab_results",
@@ -1207,16 +1322,25 @@ ${JSON.stringify(r, null, 2)}` : r;
1207
1322
  tool("list_brand_kits", "List reusable brand kits (colors/logo/typography) for your org.", {}, () => client.brandKits.list());
1208
1323
  tool("list_preferences", "List configurable consent preferences/purposes for your org.", {}, () => client.preferences.list());
1209
1324
  tool("list_members", "List the members of your organization.", {}, () => client.members.list());
1210
- tool("list_api_keys", "List the API keys for your organization (secrets are not returned).", {}, () => client.keys.list());
1325
+ tool("list_api_keys", "List the API keys for your organization (secrets are not returned), with each key\u2019s scopes, expiry and when it was last used.", {}, () => client.keys.list());
1326
+ tool(
1327
+ "api_key_report",
1328
+ "Key hygiene: keys not used for a while, keys with broad (full or wide write) access, and keys expiring soon, each with the reason. Read-only.",
1329
+ {
1330
+ unusedDays: import_zod5.z.number().int().min(1).max(3650).optional().describe("Unused for at least this many days (default 90)."),
1331
+ expiringDays: import_zod5.z.number().int().min(1).max(3650).optional().describe("Expiring within this many days (default 14).")
1332
+ },
1333
+ (a) => client.keys.report({ ...a.unusedDays !== void 0 ? { unusedDays: a.unusedDays } : {}, ...a.expiringDays !== void 0 ? { expiringDays: a.expiringDays } : {} })
1334
+ );
1211
1335
  tool("get_usage", "Get the current usage/quota summary for your organization.", {}, () => client.usage());
1212
1336
  tool("list_webhooks", "List webhook subscriptions for your organization.", {}, () => client.webhooks.list());
1213
1337
  tool(
1214
1338
  "create_webhook",
1215
1339
  "Create a webhook subscription. The response includes the signing secret (shown once).",
1216
1340
  {
1217
- url: import_zod4.z.string().describe("HTTPS endpoint to deliver events to."),
1218
- events: import_zod4.z.array(import_zod4.z.string()).describe("Event names to subscribe to, e.g. consent.created."),
1219
- cbid: import_zod4.z.string().optional().describe("Optional site cbid to scope the subscription to.")
1341
+ url: import_zod5.z.string().describe("HTTPS endpoint to deliver events to."),
1342
+ events: import_zod5.z.array(import_zod5.z.string()).describe("Event names to subscribe to, e.g. consent.created."),
1343
+ cbid: import_zod5.z.string().optional().describe("Optional site cbid to scope the subscription to.")
1220
1344
  },
1221
1345
  (a) => client.webhooks.create({
1222
1346
  url: a.url,
@@ -1227,13 +1351,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1227
1351
  tool(
1228
1352
  "roll_webhook_secret",
1229
1353
  "Rotate a webhook subscription\u2019s signing secret. The new secret is returned once; the receiving endpoint must be updated to verify with it.",
1230
- { id: import_zod4.z.string() },
1354
+ { id: import_zod5.z.string() },
1231
1355
  (a) => client.webhooks.rollSecret(a.id)
1232
1356
  );
1233
1357
  tool(
1234
1358
  "test_webhook",
1235
1359
  "Send a signed test event to a webhook subscription now, and report what the endpoint answered.",
1236
- { id: import_zod4.z.string() },
1360
+ { id: import_zod5.z.string() },
1237
1361
  (a) => client.webhooks.test(a.id)
1238
1362
  );
1239
1363
  tool(
@@ -1245,18 +1369,18 @@ ${JSON.stringify(r, null, 2)}` : r;
1245
1369
  tool(
1246
1370
  "replay_webhook_dead_letter",
1247
1371
  "Deliver a dead-lettered webhook event again, to the subscription as it is now.",
1248
- { id: import_zod4.z.string() },
1372
+ { id: import_zod5.z.string() },
1249
1373
  (a) => client.webhooks.replayDeadLetter(a.id)
1250
1374
  );
1251
1375
  tool(
1252
1376
  "update_webhook",
1253
1377
  "Change a webhook subscription, or pause it with active:false (delivery stops; the subscription is kept). Only the fields given change. cbid: null widens it to every property in the org.",
1254
1378
  {
1255
- id: import_zod4.z.string(),
1256
- url: import_zod4.z.string().optional(),
1257
- events: import_zod4.z.array(import_zod4.z.string()).optional(),
1258
- cbid: import_zod4.z.string().nullable().optional(),
1259
- active: import_zod4.z.boolean().optional()
1379
+ id: import_zod5.z.string(),
1380
+ url: import_zod5.z.string().optional(),
1381
+ events: import_zod5.z.array(import_zod5.z.string()).optional(),
1382
+ cbid: import_zod5.z.string().nullable().optional(),
1383
+ active: import_zod5.z.boolean().optional()
1260
1384
  },
1261
1385
  (a) => client.webhooks.update(a.id, {
1262
1386
  ...a.url !== void 0 ? { url: a.url } : {},
@@ -1265,20 +1389,20 @@ ${JSON.stringify(r, null, 2)}` : r;
1265
1389
  ...a.active !== void 0 ? { active: a.active } : {}
1266
1390
  })
1267
1391
  );
1268
- tool("delete_webhook", "Delete a webhook subscription by id.", { id: import_zod4.z.string().describe("The webhook subscription id.") }, async (a) => {
1392
+ tool("delete_webhook", "Delete a webhook subscription by id.", { id: import_zod5.z.string().describe("The webhook subscription id.") }, async (a) => {
1269
1393
  await client.webhooks.delete(a.id);
1270
1394
  return { ok: true };
1271
1395
  });
1272
1396
  tool(
1273
1397
  "verify_site",
1274
1398
  "Verify that your organization controls a domain by one of three challenge methods (dns / meta / file). Required to unlock consent export and signed receipts.",
1275
- { ...cbid, method: import_zod4.z.enum(["dns", "meta", "file"]).describe("Challenge method: dns (TXT record), meta (HTML tag), or file (/.well-known/cookiemunch-verify.txt).") },
1399
+ { ...cbid, method: import_zod5.z.enum(["dns", "meta", "file"]).describe("Challenge method: dns (TXT record), meta (HTML tag), or file (/.well-known/cookiemunch-verify.txt).") },
1276
1400
  (a) => client.sites.verify(a.cbid, a.method)
1277
1401
  );
1278
1402
  tool(
1279
1403
  "get_verification_challenge",
1280
1404
  "Exactly what to publish to prove control of a site\u2019s domain: the DNS TXT record, the meta tag, the file, or installing the embed. Read-only \u2014 publish one, then call verify_site.",
1281
- { cbid: import_zod4.z.string() },
1405
+ { cbid: import_zod5.z.string() },
1282
1406
  (a) => client.sites.verifyChallenge(a.cbid)
1283
1407
  );
1284
1408
  tool(
@@ -1290,15 +1414,15 @@ ${JSON.stringify(r, null, 2)}` : r;
1290
1414
  tool(
1291
1415
  "get_flow",
1292
1416
  "Get the v2 banner flow config for a site, including current views, categories, and any lint issues.",
1293
- { cbid: import_zod4.z.string().describe("Site identifier (cbid).") },
1417
+ { cbid: import_zod5.z.string().describe("Site identifier (cbid).") },
1294
1418
  (a) => client.sites.getFlow(a.cbid)
1295
1419
  );
1296
1420
  tool(
1297
1421
  "edit_flow",
1298
1422
  "Apply a batch of structured edit operations to a site's v2 banner flow. All ops are validated server-side and the final config must be lint-clean before it is saved.",
1299
1423
  {
1300
- cbid: import_zod4.z.string().describe("Site identifier (cbid)."),
1301
- operations: import_zod4.z.array(import_zod4.z.record(import_zod4.z.unknown())).describe(
1424
+ cbid: import_zod5.z.string().describe("Site identifier (cbid)."),
1425
+ operations: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).describe(
1302
1426
  'Ordered list of ops. Each must have an "op" field: addView | removeView | addElement | setButtonTransition | addCustomCategory.'
1303
1427
  )
1304
1428
  },
@@ -1308,21 +1432,22 @@ ${JSON.stringify(r, null, 2)}` : r;
1308
1432
  "set_flow",
1309
1433
  "Wholesale replace a site's v2 banner flow with a complete config (e.g. from a template). Validated server-side before it is saved.",
1310
1434
  {
1311
- cbid: import_zod4.z.string().describe("Site identifier (cbid)."),
1312
- config: import_zod4.z.record(import_zod4.z.unknown()).describe("A full v2 FlowConfig object ({ v:2, flow, categories, ... }).")
1435
+ cbid: import_zod5.z.string().describe("Site identifier (cbid)."),
1436
+ config: import_zod5.z.record(import_zod5.z.unknown()).describe("A full v2 FlowConfig object ({ v:2, flow, categories, ... }).")
1313
1437
  },
1314
1438
  (a) => client.sites.setFlow(a.cbid, a.config)
1315
1439
  );
1316
1440
  registerConfigTools(tool, client);
1317
1441
  registerPlatformTools(tool, client);
1442
+ registerIntegrationTools(tool, client);
1318
1443
  registerRightsTools(tool, client);
1319
1444
  registerRightsPageTools(tool, client);
1320
1445
  tool(
1321
1446
  "invite_member",
1322
1447
  "Invite a person to your organization by email. role must be admin, member, or viewer. The org is derived from the API key \u2014 you cannot invite into a different org.",
1323
1448
  {
1324
- email: import_zod4.z.string().describe("Email address of the person to invite."),
1325
- role: import_zod4.z.enum(["admin", "member", "viewer"]).describe("Role to assign: admin, member, or viewer. owner is not assignable via API key.")
1449
+ email: import_zod5.z.string().describe("Email address of the person to invite."),
1450
+ role: import_zod5.z.enum(["admin", "member", "viewer"]).describe("Role to assign: admin, member, or viewer. owner is not assignable via API key.")
1326
1451
  },
1327
1452
  (a) => client.members.invite(a.email, a.role)
1328
1453
  );
@@ -1330,8 +1455,8 @@ ${JSON.stringify(r, null, 2)}` : r;
1330
1455
  "set_member_role",
1331
1456
  "Change the role of a member in your organization. The org owner's role cannot be changed.",
1332
1457
  {
1333
- userId: import_zod4.z.string().describe("The userId of the member whose role to change."),
1334
- role: import_zod4.z.enum(["admin", "member", "viewer"]).describe("New role: admin, member, or viewer.")
1458
+ userId: import_zod5.z.string().describe("The userId of the member whose role to change."),
1459
+ role: import_zod5.z.enum(["admin", "member", "viewer"]).describe("New role: admin, member, or viewer.")
1335
1460
  },
1336
1461
  (a) => client.members.setRole(a.userId, a.role)
1337
1462
  );
@@ -1339,7 +1464,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1339
1464
  "remove_member",
1340
1465
  "Remove a member from your organization. The org owner cannot be removed.",
1341
1466
  {
1342
- userId: import_zod4.z.string().describe("The userId of the member to remove.")
1467
+ userId: import_zod5.z.string().describe("The userId of the member to remove.")
1343
1468
  },
1344
1469
  async (a) => {
1345
1470
  await client.members.remove(a.userId);
@@ -1350,11 +1475,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1350
1475
  "create_brand_kit",
1351
1476
  "Create a reusable brand kit (colors, logo, typography) for your organization's consent banners.",
1352
1477
  {
1353
- name: import_zod4.z.string().describe("Display name for the brand kit."),
1354
- theme: import_zod4.z.record(import_zod4.z.unknown()).describe("Theme tokens (colors, fonts, etc.) as a JSON object."),
1355
- content: import_zod4.z.record(import_zod4.z.unknown()).optional().describe("Optional banner copy overrides."),
1356
- logoUrl: import_zod4.z.string().optional().describe("Optional URL for your org logo."),
1357
- customCss: import_zod4.z.string().optional().describe("Optional custom CSS string to inject into the banner.")
1478
+ name: import_zod5.z.string().describe("Display name for the brand kit."),
1479
+ theme: import_zod5.z.record(import_zod5.z.unknown()).describe("Theme tokens (colors, fonts, etc.) as a JSON object."),
1480
+ content: import_zod5.z.record(import_zod5.z.unknown()).optional().describe("Optional banner copy overrides."),
1481
+ logoUrl: import_zod5.z.string().optional().describe("Optional URL for your org logo."),
1482
+ customCss: import_zod5.z.string().optional().describe("Optional custom CSS string to inject into the banner.")
1358
1483
  },
1359
1484
  (a) => client.brandKits.create({
1360
1485
  name: a.name,
@@ -1368,7 +1493,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1368
1493
  "delete_brand_kit",
1369
1494
  "Delete a brand kit by id. The kit must belong to your organization (cross-org deletes are rejected).",
1370
1495
  {
1371
- id: import_zod4.z.string().describe("The brand kit id to delete.")
1496
+ id: import_zod5.z.string().describe("The brand kit id to delete.")
1372
1497
  },
1373
1498
  async (a) => {
1374
1499
  await client.brandKits.delete(a.id);
@@ -1379,63 +1504,65 @@ ${JSON.stringify(r, null, 2)}` : r;
1379
1504
  "save_preference",
1380
1505
  "Save or update the consent preferences for an end-user (by subjectId) within your organization. purposes is a map of purpose-name \u2192 boolean.",
1381
1506
  {
1382
- subjectId: import_zod4.z.string().describe("The end-user identifier (e.g. email or internal user id)."),
1383
- purposes: import_zod4.z.record(import_zod4.z.boolean()).describe('Map of purpose names to consent values, e.g. { "newsletter": true, "analytics": false }.')
1507
+ subjectId: import_zod5.z.string().describe("The end-user identifier (e.g. email or internal user id)."),
1508
+ purposes: import_zod5.z.record(import_zod5.z.boolean()).describe('Map of purpose names to consent values, e.g. { "newsletter": true, "analytics": false }.')
1384
1509
  },
1385
1510
  (a) => client.preferences.save(a.subjectId, a.purposes)
1386
1511
  );
1387
1512
  tool(
1388
1513
  "get_preference",
1389
1514
  "One end-user\u2019s saved preferences, by subjectId. Read-only.",
1390
- { subjectId: import_zod4.z.string() },
1515
+ { subjectId: import_zod5.z.string() },
1391
1516
  (a) => client.preferences.get(a.subjectId)
1392
1517
  );
1393
1518
  tool(
1394
1519
  "issue_api_key",
1395
1520
  "Issue a new API key. The secret is returned once and never again. Prefer the least privilege the job needs: `scopes` limits what it can do, `cbids` locks it to specific sites (it then cannot reach anything org-wide), `expiresInDays` retires it. Omitting all three mints a full-access, org-wide, non-expiring key.",
1396
1521
  {
1397
- name: import_zod4.z.string().optional(),
1398
- scopes: import_zod4.z.array(import_zod4.z.string()).optional(),
1399
- cbids: import_zod4.z.array(import_zod4.z.string()).min(1).optional(),
1400
- expiresInDays: import_zod4.z.number().int().min(1).max(3650).optional()
1522
+ name: import_zod5.z.string().optional(),
1523
+ scopes: import_zod5.z.array(import_zod5.z.string()).optional(),
1524
+ cbids: import_zod5.z.array(import_zod5.z.string()).min(1).optional(),
1525
+ expiresInDays: import_zod5.z.number().int().min(1).max(3650).optional(),
1526
+ expiresAt: import_zod5.z.string().optional().describe("Or the exact expiry, an ISO date-time (not with expiresInDays).")
1401
1527
  },
1402
1528
  (a) => client.keys.issue({
1529
+ ...a.expiresAt ? { expiresAt: a.expiresAt } : {},
1403
1530
  ...a.name ? { name: a.name } : {},
1404
1531
  ...a.scopes ? { scopes: a.scopes } : {},
1405
1532
  ...a.cbids ? { cbids: a.cbids } : {},
1406
1533
  ...a.expiresInDays !== void 0 ? { expiresInDays: a.expiresInDays } : {}
1407
1534
  })
1408
1535
  );
1409
- tool("revoke_api_key", "Revoke an API key by its prefix. Takes effect immediately; anything using that key stops working.", { prefix: import_zod4.z.string() }, async (a) => {
1536
+ tool("revoke_api_key", "Revoke an API key by its prefix. Takes effect immediately; anything using that key stops working.", { prefix: import_zod5.z.string() }, async (a) => {
1410
1537
  await client.keys.revoke(a.prefix);
1411
1538
  return { revoked: a.prefix };
1412
1539
  });
1413
1540
  tool(
1414
1541
  "import_cookie_declaration",
1415
1542
  "Read a cookie declaration exported from another CMP (OneTrust, Cookiebot, CookieYes, or any CSV/JSON with the same columns) and translate its categories into ours. Nothing is applied \u2014 it comes back for review, with the rows whose category could not be placed listed separately.",
1416
- { cbid: import_zod4.z.string(), data: import_zod4.z.string().describe("The exported file, as text (CSV or JSON).") },
1543
+ { cbid: import_zod5.z.string(), data: import_zod5.z.string().describe("The exported file, as text (CSV or JSON).") },
1417
1544
  (a) => client.sites.importDeclaration(a.cbid, a.data)
1418
1545
  );
1419
1546
  tool(
1420
1547
  "apply_cookie_import",
1421
1548
  "Import a cookie declaration exported from another CMP AND declare it: every row whose category mapped to ours and that has a purpose becomes a site declaration; the rest come back in `skipped` with the reason. Cookies the site already declared are kept unless overwrite is true. Prefer import_cookie_declaration first to review.",
1422
- { cbid: import_zod4.z.string(), data: import_zod4.z.string().describe("The exported file, as text (CSV or JSON)."), overwrite: import_zod4.z.boolean().optional() },
1549
+ { cbid: import_zod5.z.string(), data: import_zod5.z.string().describe("The exported file, as text (CSV or JSON)."), overwrite: import_zod5.z.boolean().optional() },
1423
1550
  (a) => client.sites.applyImport(a.cbid, a.data, a.overwrite ? { overwrite: true } : void 0)
1424
1551
  );
1425
1552
  const declarationShape = {
1426
- category: import_zod4.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
1427
- purpose: import_zod4.z.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
1428
- purposes: import_zod4.z.record(import_zod4.z.string(), import_zod4.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.'),
1429
- provider: import_zod4.z.string().optional(),
1430
- expiry: import_zod4.z.string().optional().describe('e.g. "Session", "30 days", "1 year" (the banner localises these forms).'),
1431
- domain: import_zod4.z.string().optional(),
1432
- pattern: import_zod4.z.boolean().optional().describe("Treat the name as a prefix wildcard (a trailing * does the same).")
1553
+ category: import_zod5.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
1554
+ purpose: import_zod5.z.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
1555
+ purposes: import_zod5.z.record(import_zod5.z.string(), import_zod5.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.'),
1556
+ provider: import_zod5.z.string().optional(),
1557
+ expiry: import_zod5.z.string().optional().describe('e.g. "Session", "30 days", "1 year" (the banner localises these forms).'),
1558
+ domain: import_zod5.z.string().optional(),
1559
+ pattern: import_zod5.z.boolean().optional().describe("Treat the name as a prefix wildcard (a trailing * does the same).")
1433
1560
  };
1434
- const dryRunArg = import_zod4.z.boolean().optional().describe("Store nothing: answer with the would-be declarations and a diff (added / removed / changed) to check first.");
1561
+ const dryRunArg = import_zod5.z.boolean().optional().describe("Store nothing: answer with the would-be declarations and a diff (added / removed / changed) to check first.");
1435
1562
  tool(
1436
1563
  "declare_cookie",
1437
1564
  'Declare what one of the site\u2019s cookies is. Overrides the scanner, observed visits and the cookie database everywhere the declaration is shown (API, preference modal, data-cc="declaration"). Use for the site\u2019s own cookies the database cannot know. A name ending in * covers every cookie with that prefix.',
1438
- { cbid: import_zod4.z.string(), name: import_zod4.z.string(), ...declarationShape, dryRun: dryRunArg },
1565
+ { cbid: import_zod5.z.string(), name: import_zod5.z.string(), ...declarationShape, dryRun: dryRunArg },
1439
1566
  (a) => {
1440
1567
  const { cbid: cbid2, name, dryRun, ...rest } = a;
1441
1568
  return client.sites.declareCookie(cbid2, name, rest, dryRun ? { dryRun: true } : void 0);
@@ -1444,7 +1571,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1444
1571
  tool(
1445
1572
  "declare_cookies",
1446
1573
  "Declare many cookies at once. All-or-nothing: one invalid item refuses the whole request and nothing is saved. replace: true also removes every declaration the list does not name.",
1447
- { cbid: import_zod4.z.string(), cookies: import_zod4.z.array(import_zod4.z.object({ name: import_zod4.z.string(), ...declarationShape })).max(500), replace: import_zod4.z.boolean().optional(), dryRun: dryRunArg },
1574
+ { cbid: import_zod5.z.string(), cookies: import_zod5.z.array(import_zod5.z.object({ name: import_zod5.z.string(), ...declarationShape })).max(500), replace: import_zod5.z.boolean().optional(), dryRun: dryRunArg },
1448
1575
  (a) => {
1449
1576
  const o = { ...a.replace ? { replace: true } : {}, ...a.dryRun ? { dryRun: true } : {} };
1450
1577
  return client.sites.declareCookies(a.cbid, a.cookies, Object.keys(o).length ? o : void 0);
@@ -1453,35 +1580,118 @@ ${JSON.stringify(r, null, 2)}` : r;
1453
1580
  tool(
1454
1581
  "undeclare_cookie",
1455
1582
  "Remove a cookie declaration; the scanned/observed classification applies again.",
1456
- { cbid: import_zod4.z.string(), name: import_zod4.z.string(), dryRun: dryRunArg },
1583
+ { cbid: import_zod5.z.string(), name: import_zod5.z.string(), dryRun: dryRunArg },
1457
1584
  async (a) => {
1458
1585
  if (a.dryRun) return client.sites.undeclareCookie(a.cbid, a.name, { dryRun: true });
1459
1586
  await client.sites.undeclareCookie(a.cbid, a.name);
1460
1587
  return { undeclared: a.name };
1461
1588
  }
1462
1589
  );
1590
+ tool(
1591
+ "retire_cookie",
1592
+ 'Retire a cookie the site renamed or stopped setting: it leaves the banner\u2019s cookie list, data-cc="declaration" and the public feed, and stays listed for the owner with retired. A name ending in * retires every cookie with that prefix; the name must match a scanned, observed or declared cookie. If a crawl or a real visit sees it again afterwards, it is listed again with review: retired_but_seen.',
1593
+ {
1594
+ cbid: import_zod5.z.string(),
1595
+ name: import_zod5.z.string(),
1596
+ renamedTo: import_zod5.z.string().max(256).optional().describe("The cookie\u2019s new name, if it was renamed."),
1597
+ note: import_zod5.z.string().max(1e3).optional(),
1598
+ dryRun: import_zod5.z.boolean().optional().describe("Store nothing: answer with the would-be retirement and list to check first.")
1599
+ },
1600
+ (a) => {
1601
+ const input = { ...a.renamedTo ? { renamedTo: a.renamedTo } : {}, ...a.note ? { note: a.note } : {} };
1602
+ return client.sites.retireCookie(a.cbid, a.name, input, a.dryRun ? { dryRun: true } : void 0);
1603
+ }
1604
+ );
1605
+ tool(
1606
+ "unretire_cookie",
1607
+ "Un-retire a cookie: it is listed again everywhere.",
1608
+ { cbid: import_zod5.z.string(), name: import_zod5.z.string(), dryRun: import_zod5.z.boolean().optional().describe("Store nothing: answer with what the list would be.") },
1609
+ async (a) => {
1610
+ if (a.dryRun) return client.sites.unretireCookie(a.cbid, a.name, { dryRun: true });
1611
+ await client.sites.unretireCookie(a.cbid, a.name);
1612
+ return { unretired: a.name };
1613
+ }
1614
+ );
1615
+ tool(
1616
+ "list_cookie_presets",
1617
+ "Declaration presets for the platforms a site is built on (atlas, forumulate, chatly, cookiemunch): each one\u2019s parameters, what it has declared on this site, and whether the vendor\u2019s live manifest can be imported yet. Read-only.",
1618
+ { cbid: import_zod5.z.string() },
1619
+ (a) => client.sites.cookiePresets(a.cbid)
1620
+ );
1621
+ tool(
1622
+ "apply_cookie_preset",
1623
+ "Apply (or re-sync) a vendor preset: declares exactly what that platform writes \u2014 cookies and browser storage, with domain and lifetime \u2014 marked as declared by that vendor. Re-applying removes keys the vendor no longer writes. Names the owner declared are kept (skipped). Atlas needs frontendApiHost (and crossSubdomainCookies, default true); Chatly needs publicId.",
1624
+ {
1625
+ cbid: import_zod5.z.string(),
1626
+ vendor: import_zod5.z.enum(["atlas", "forumulate", "chatly", "cookiemunch"]),
1627
+ frontendApiHost: import_zod5.z.string().optional().describe("Atlas: your frontend API host, e.g. auth.example.com."),
1628
+ crossSubdomainCookies: import_zod5.z.boolean().optional().describe("Atlas: default true \u2014 the cookies live on the parent domain."),
1629
+ publicId: import_zod5.z.string().optional().describe("Chatly: the channel public id (ch_web_\u2026)."),
1630
+ dragging: import_zod5.z.boolean().optional().describe("Chatly: the launcher can be dragged (adds the drag-position key)."),
1631
+ category: import_zod5.z.string().optional().describe("Chatly: the category for its keys. Default necessary."),
1632
+ dryRun: dryRunArg
1633
+ },
1634
+ (a) => {
1635
+ const params = {};
1636
+ for (const k of ["frontendApiHost", "crossSubdomainCookies", "publicId", "dragging", "category"]) if (a[k] !== void 0) params[k] = a[k];
1637
+ return client.sites.applyCookiePreset(a.cbid, a.vendor, params, a.dryRun ? { dryRun: true } : void 0);
1638
+ }
1639
+ );
1640
+ tool(
1641
+ "remove_cookie_preset",
1642
+ "Remove every declaration a vendor preset made on this site.",
1643
+ { cbid: import_zod5.z.string(), vendor: import_zod5.z.enum(["atlas", "forumulate", "chatly", "cookiemunch"]), dryRun: dryRunArg },
1644
+ (a) => client.sites.removeCookiePreset(a.cbid, a.vendor, a.dryRun ? { dryRun: true } : void 0)
1645
+ );
1646
+ tool(
1647
+ "delete_observed_cookie",
1648
+ "Remove every stored row of this name that crawls or real visits put in the site\u2019s cookie list (e.g. a name someone reported that the site never sets). A declaration of it stays. If real visits keep reporting it, it comes back quarantined.",
1649
+ { cbid: import_zod5.z.string(), name: import_zod5.z.string(), dryRun: dryRunArg },
1650
+ async (a) => {
1651
+ if (a.dryRun) return client.sites.deleteObservedCookie(a.cbid, a.name, { dryRun: true });
1652
+ await client.sites.deleteObservedCookie(a.cbid, a.name);
1653
+ return { deleted: a.name };
1654
+ }
1655
+ );
1656
+ tool(
1657
+ "purge_observed_cookies",
1658
+ "Purge observed since T: remove every row a real visit first reported at or after `since` (and before `until`). Crawled rows and declarations stay. Rows from before provenance was recorded use their last-seen time, so run with dryRun first.",
1659
+ {
1660
+ cbid: import_zod5.z.string(),
1661
+ since: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number()]).describe("ISO-8601 time or epoch milliseconds."),
1662
+ until: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number()]).optional().describe("Optional end of the window (exclusive)."),
1663
+ dryRun: dryRunArg
1664
+ },
1665
+ (a) => client.sites.purgeObservedCookies(
1666
+ a.cbid,
1667
+ { since: a.since, ...a.until !== void 0 ? { until: a.until } : {} },
1668
+ a.dryRun ? { dryRun: true } : void 0
1669
+ )
1670
+ );
1463
1671
  tool(
1464
1672
  "get_blocked_pages",
1465
1673
  "Pages where the embed could not load its banner renderer \u2014 the page\u2019s Content Security Policy or Trusted Types policy refused it, so nobody there can be asked for consent. An empty list is healthy. Read-only.",
1466
- { cbid: import_zod4.z.string() },
1674
+ { cbid: import_zod5.z.string() },
1467
1675
  (a) => client.sites.blocked(a.cbid)
1468
1676
  );
1469
1677
  tool(
1470
1678
  "roll_api_key",
1471
1679
  "Rotate an API key: returns a new secret once, with the same name, scopes, property lock and expiry. The old secret stops working immediately \u2014 if it is the key this server runs with, this server stops working too until it is reconfigured.",
1472
- { prefix: import_zod4.z.string() },
1680
+ { prefix: import_zod5.z.string() },
1473
1681
  (a) => client.keys.roll(a.prefix)
1474
1682
  );
1475
1683
  tool(
1476
1684
  "update_api_key",
1477
- "Rename an API key, or replace its scopes or the properties it is locked to. Only the fields given change; the secret does not.",
1685
+ "Rename an API key, replace its scopes or the properties it is locked to, or set or remove its expiry. Only the fields given change; the secret does not.",
1478
1686
  {
1479
- prefix: import_zod4.z.string(),
1480
- name: import_zod4.z.string().optional(),
1481
- scopes: import_zod4.z.array(import_zod4.z.string()).optional(),
1482
- cbids: import_zod4.z.array(import_zod4.z.string()).min(1).optional()
1687
+ prefix: import_zod5.z.string(),
1688
+ name: import_zod5.z.string().optional(),
1689
+ scopes: import_zod5.z.array(import_zod5.z.string()).optional(),
1690
+ cbids: import_zod5.z.array(import_zod5.z.string()).min(1).optional(),
1691
+ expiresAt: import_zod5.z.string().nullable().optional().describe("A new expiry (ISO date-time), or null to remove it.")
1483
1692
  },
1484
1693
  (a) => client.keys.update(a.prefix, {
1694
+ ...a.expiresAt !== void 0 ? { expiresAt: a.expiresAt } : {},
1485
1695
  ...a.name !== void 0 ? { name: a.name } : {},
1486
1696
  ...a.scopes ? { scopes: a.scopes } : {},
1487
1697
  ...a.cbids ? { cbids: a.cbids } : {}
@@ -1491,7 +1701,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1491
1701
  tool(
1492
1702
  "update_org",
1493
1703
  "Rename your organisation or set its logo. logoUrl: null removes the logo; upload an image with upload_asset to get a URL. Deleting the organisation is not possible here.",
1494
- { name: import_zod4.z.string().min(1).optional(), logoUrl: import_zod4.z.string().nullable().optional() },
1704
+ { name: import_zod5.z.string().min(1).optional(), logoUrl: import_zod5.z.string().nullable().optional() },
1495
1705
  (a) => client.org.update({
1496
1706
  ...a.name !== void 0 ? { name: a.name } : {},
1497
1707
  ...a.logoUrl !== void 0 ? { logoUrl: a.logoUrl } : {}
@@ -1507,20 +1717,20 @@ ${JSON.stringify(r, null, 2)}` : r;
1507
1717
  "set_mail_provider",
1508
1718
  "Connect your own mail provider for rights-request mail \u2014 recommended, so codes come from your own domain. Replaces the stored one. It carries mail only after test_mail_provider succeeds; every save clears that. Omit secret to keep the stored one (same provider only).",
1509
1719
  {
1510
- provider: import_zod4.z.enum(["brevo", "sendgrid", "postmark", "resend", "ses", "smtp"]),
1511
- fromEmail: import_zod4.z.string().describe("An address on a domain your provider has verified."),
1512
- fromName: import_zod4.z.string().max(100).nullable().optional(),
1513
- replyTo: import_zod4.z.string().nullable().optional(),
1514
- secret: import_zod4.z.string().optional().describe("API key (Brevo, SendGrid, Resend), server token (Postmark), secret access key (SES) or SMTP password. Write-only."),
1515
- ses: import_zod4.z.object({ region: import_zod4.z.string(), accessKeyId: import_zod4.z.string() }).optional().describe("Required for ses."),
1516
- smtp: import_zod4.z.object({ host: import_zod4.z.string(), port: import_zod4.z.union([import_zod4.z.literal(25), import_zod4.z.literal(465), import_zod4.z.literal(587), import_zod4.z.literal(2525)]), security: import_zod4.z.enum(["tls", "starttls"]), username: import_zod4.z.string() }).optional().describe("Required for smtp. TLS is always required.")
1720
+ provider: import_zod5.z.enum(["brevo", "sendgrid", "postmark", "resend", "ses", "smtp"]),
1721
+ fromEmail: import_zod5.z.string().describe("An address on a domain your provider has verified."),
1722
+ fromName: import_zod5.z.string().max(100).nullable().optional(),
1723
+ replyTo: import_zod5.z.string().nullable().optional(),
1724
+ secret: import_zod5.z.string().optional().describe("API key (Brevo, SendGrid, Resend), server token (Postmark), secret access key (SES) or SMTP password. Write-only."),
1725
+ ses: import_zod5.z.object({ region: import_zod5.z.string(), accessKeyId: import_zod5.z.string() }).optional().describe("Required for ses."),
1726
+ smtp: import_zod5.z.object({ host: import_zod5.z.string(), port: import_zod5.z.union([import_zod5.z.literal(25), import_zod5.z.literal(465), import_zod5.z.literal(587), import_zod5.z.literal(2525)]), security: import_zod5.z.enum(["tls", "starttls"]), username: import_zod5.z.string() }).optional().describe("Required for smtp. TLS is always required.")
1517
1727
  },
1518
1728
  (a) => client.org.mailProvider.set(a)
1519
1729
  );
1520
1730
  tool(
1521
1731
  "test_mail_provider",
1522
1732
  "Send a test message through your own mail provider (never Cookie Munch\u2019s) and report what it answered. Success marks the configuration verified, after which it carries all rights mail.",
1523
- { to: import_zod4.z.string().optional().describe("Recipient. Default: the reply-to, else the from address.") },
1733
+ { to: import_zod5.z.string().optional().describe("Recipient. Default: the reply-to, else the from address.") },
1524
1734
  (a) => client.org.mailProvider.test(a.to)
1525
1735
  );
1526
1736
  tool(
@@ -1534,11 +1744,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1534
1744
  );
1535
1745
  const CAPTCHA_OFF = "Off removes spam protection beyond the hidden spam-trap field, the rate limits and the email code: expect more spam requests. Own keys are recommended.";
1536
1746
  const captchaInput = {
1537
- mode: import_zod4.z.enum(["own", "off"]).describe(`own: your own captcha provider keys (recommended). off: no captcha. ${CAPTCHA_OFF}`),
1538
- provider: import_zod4.z.enum(["turnstile", "hcaptcha", "recaptcha_v2", "recaptcha_v3"]).optional().describe("Required for own."),
1539
- siteKey: import_zod4.z.string().optional().describe("Required for own: the public site key. List your rights-page hostnames on it at the provider."),
1540
- secret: import_zod4.z.string().optional().describe("The provider secret key. Write-only; never returned. Omit to keep the stored one (same provider)."),
1541
- minScore: import_zod4.z.number().min(0.1).max(0.9).optional().describe("reCAPTCHA v3 only. Default 0.5.")
1747
+ mode: import_zod5.z.enum(["own", "off"]).describe(`own: your own captcha provider keys (recommended). off: no captcha. ${CAPTCHA_OFF}`),
1748
+ provider: import_zod5.z.enum(["turnstile", "hcaptcha", "recaptcha_v2", "recaptcha_v3"]).optional().describe("Required for own."),
1749
+ siteKey: import_zod5.z.string().optional().describe("Required for own: the public site key. List your rights-page hostnames on it at the provider."),
1750
+ secret: import_zod5.z.string().optional().describe("The provider secret key. Write-only; never returned. Omit to keep the stored one (same provider)."),
1751
+ minScore: import_zod5.z.number().min(0.1).max(0.9).optional().describe("reCAPTCHA v3 only. Default 0.5.")
1542
1752
  };
1543
1753
  const captchaBody = (a) => ({
1544
1754
  mode: a.mode,
@@ -1550,19 +1760,19 @@ ${JSON.stringify(r, null, 2)}` : r;
1550
1760
  tool(
1551
1761
  "get_rights_captcha",
1552
1762
  "The captcha on a site\u2019s hosted rights page: its own setting, else the organisation default, else off (`source` says which). Never returns the secret. Read-only.",
1553
- { cbid: import_zod4.z.string() },
1763
+ { cbid: import_zod5.z.string() },
1554
1764
  (a) => client.rightsCaptcha.get(a.cbid)
1555
1765
  );
1556
1766
  tool(
1557
1767
  "set_rights_captcha",
1558
1768
  `Set a site\u2019s rights-page captcha: your own Turnstile, hCaptcha or reCAPTCHA keys (recommended; the provider must accept the secret before it is saved), or off. ${CAPTCHA_OFF} Audited with the old and new mode.`,
1559
- { cbid: import_zod4.z.string(), ...captchaInput },
1769
+ { cbid: import_zod5.z.string(), ...captchaInput },
1560
1770
  (a) => client.rightsCaptcha.set(a.cbid, captchaBody(a))
1561
1771
  );
1562
1772
  tool(
1563
1773
  "remove_rights_captcha",
1564
1774
  "Remove a site\u2019s own captcha setting: it inherits the organisation default again (or off). Returns the setting now in force.",
1565
- { cbid: import_zod4.z.string() },
1775
+ { cbid: import_zod5.z.string() },
1566
1776
  (a) => client.rightsCaptcha.remove(a.cbid)
1567
1777
  );
1568
1778
  tool(
@@ -1585,15 +1795,15 @@ ${JSON.stringify(r, null, 2)}` : r;
1585
1795
  );
1586
1796
  const IDENTITY_NOTE = "The JWKS is fetched and checked before anything is saved. The session token must carry the email and a verified-email claim (default email_verified) set to true (Clerk: add email: {{user.primary_email_address}} to the session token; Clerk documents no claim for whether that address is verified, so either add your own or set trustEmailClaim). oidc_jwt needs an audience or authorizedParties.";
1587
1797
  const identityInput = {
1588
- type: import_zod4.z.enum(["clerk", "atlas", "oidc_jwt"]).describe("clerk, atlas (Clerk-shaped), or oidc_jwt (any issuer that signs session JWTs with a published JWKS)."),
1589
- issuer: import_zod4.z.string().describe("https URL exactly as in the token\u2019s iss (Clerk: your Frontend API URL)."),
1590
- jwksUrl: import_zod4.z.string().optional().describe("Required for oidc_jwt; clerk/atlas default to <issuer>/.well-known/jwks.json."),
1591
- audience: import_zod4.z.string().optional().describe("Expected aud. For oidc_jwt an audience or authorizedParties is required (a shared issuer mints tokens for every app)."),
1592
- authorizedParties: import_zod4.z.array(import_zod4.z.string()).optional().describe("Your own origins (https://www.example.com) the token\u2019s azp must be one of. Required for clerk and atlas; for oidc_jwt when there is no audience."),
1593
- emailClaim: import_zod4.z.string().optional().describe("Default email."),
1594
- emailVerifiedClaim: import_zod4.z.string().optional().describe("Default email_verified; must be exactly true."),
1595
- sessionCookieName: import_zod4.z.string().optional().describe("Default __session: the cookie the hosted page on your custom domain reads."),
1596
- trustEmailClaim: import_zod4.z.boolean().optional().describe("clerk/atlas only, default false. True: a token without the verified claim is accepted, its email claim taken as verified. Set only if every address your provider puts in that claim is verified.")
1798
+ type: import_zod5.z.enum(["clerk", "atlas", "oidc_jwt"]).describe("clerk, atlas (Clerk-shaped), or oidc_jwt (any issuer that signs session JWTs with a published JWKS)."),
1799
+ issuer: import_zod5.z.string().describe("https URL exactly as in the token\u2019s iss (Clerk: your Frontend API URL)."),
1800
+ jwksUrl: import_zod5.z.string().optional().describe("Required for oidc_jwt; clerk/atlas default to <issuer>/.well-known/jwks.json."),
1801
+ audience: import_zod5.z.string().optional().describe("Expected aud. For oidc_jwt an audience or authorizedParties is required (a shared issuer mints tokens for every app)."),
1802
+ authorizedParties: import_zod5.z.array(import_zod5.z.string()).optional().describe("Your own origins (https://www.example.com) the token\u2019s azp must be one of. Required for clerk and atlas; for oidc_jwt when there is no audience."),
1803
+ emailClaim: import_zod5.z.string().optional().describe("Default email."),
1804
+ emailVerifiedClaim: import_zod5.z.string().optional().describe("Default email_verified; must be exactly true."),
1805
+ sessionCookieName: import_zod5.z.string().optional().describe("Default __session: the cookie the hosted page on your custom domain reads."),
1806
+ trustEmailClaim: import_zod5.z.boolean().optional().describe("clerk/atlas only, default false. True: a token without the verified claim is accepted, its email claim taken as verified. Set only if every address your provider puts in that claim is verified.")
1597
1807
  };
1598
1808
  const identityBody = (a) => {
1599
1809
  const out = { type: a.type, issuer: a.issuer };
@@ -1603,19 +1813,19 @@ ${JSON.stringify(r, null, 2)}` : r;
1603
1813
  tool(
1604
1814
  "get_rights_identity",
1605
1815
  "The sign-in provider a site\u2019s rights requests are verified with: its own setting, else the organisation default, else none (`source` says which). Read-only.",
1606
- { cbid: import_zod4.z.string() },
1816
+ { cbid: import_zod5.z.string() },
1607
1817
  (a) => client.rightsIdentity.get(a.cbid)
1608
1818
  );
1609
1819
  tool(
1610
1820
  "set_rights_identity",
1611
1821
  `Connect a site\u2019s sign-in provider so a visitor signed in to the site is verified by their session, with no code mail. ${IDENTITY_NOTE} Audited.`,
1612
- { cbid: import_zod4.z.string(), ...identityInput },
1822
+ { cbid: import_zod5.z.string(), ...identityInput },
1613
1823
  (a) => client.rightsIdentity.set(a.cbid, identityBody(a))
1614
1824
  );
1615
1825
  tool(
1616
1826
  "remove_rights_identity",
1617
1827
  "Remove a site\u2019s own sign-in provider: it inherits the organisation default again (or none). Returns the setting now in force.",
1618
- { cbid: import_zod4.z.string() },
1828
+ { cbid: import_zod5.z.string() },
1619
1829
  (a) => client.rightsIdentity.remove(a.cbid)
1620
1830
  );
1621
1831
  tool(
@@ -1639,22 +1849,22 @@ ${JSON.stringify(r, null, 2)}` : r;
1639
1849
  tool(
1640
1850
  "get_audit_log",
1641
1851
  "The organisation\u2019s audit log, newest first: administrative changes made in the dashboard or through the API, and who made them. Read-only.",
1642
- { limit: import_zod4.z.number().int().min(1).max(500).optional() },
1852
+ { limit: import_zod5.z.number().int().min(1).max(500).optional() },
1643
1853
  (a) => client.audit(a.limit)
1644
1854
  );
1645
1855
  tool(
1646
1856
  "upload_asset",
1647
1857
  "Upload an image \u2014 a banner logo \u2014 and get its public URL. data is base64 (a data: URL also works); PNG, JPEG, WebP, GIF or SVG, up to 1,000,000 bytes.",
1648
1858
  {
1649
- data: import_zod4.z.string(),
1650
- contentType: import_zod4.z.enum(["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"])
1859
+ data: import_zod5.z.string(),
1860
+ contentType: import_zod5.z.enum(["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"])
1651
1861
  },
1652
1862
  (a) => client.assets.upload({ data: a.data, contentType: a.contentType })
1653
1863
  );
1654
1864
  tool(
1655
1865
  "delete_asset",
1656
1866
  "Delete a stored image by its URL (or file name). Only your own organisation\u2019s images can be named.",
1657
- { url: import_zod4.z.string().describe("The URL upload_asset returned, or just its file name.") },
1867
+ { url: import_zod5.z.string().describe("The URL upload_asset returned, or just its file name.") },
1658
1868
  async (a) => {
1659
1869
  await client.assets.delete(a.url);
1660
1870
  return { deleted: a.url };
@@ -1669,18 +1879,18 @@ ${JSON.stringify(r, null, 2)}` : r;
1669
1879
  tool(
1670
1880
  "get_customer",
1671
1881
  "One child org: its controller details and usage. Read-only.",
1672
- { id: import_zod4.z.string() },
1882
+ { id: import_zod5.z.string() },
1673
1883
  (a) => client.reseller.get(a.id)
1674
1884
  );
1675
1885
  tool(
1676
1886
  "provision_customer",
1677
1887
  "Create a new child org under this reseller. With `mintKey`, its first API key is returned once. Counts toward the reseller plan\u2019s pooled limits.",
1678
1888
  {
1679
- name: import_zod4.z.string(),
1680
- ownerEmail: import_zod4.z.string().optional(),
1681
- delegatedAccess: import_zod4.z.boolean().optional().describe("Whether this reseller may act inside the child."),
1682
- mintKey: import_zod4.z.boolean().optional(),
1683
- keyScopes: import_zod4.z.array(import_zod4.z.string()).optional()
1889
+ name: import_zod5.z.string(),
1890
+ ownerEmail: import_zod5.z.string().optional(),
1891
+ delegatedAccess: import_zod5.z.boolean().optional().describe("Whether this reseller may act inside the child."),
1892
+ mintKey: import_zod5.z.boolean().optional(),
1893
+ keyScopes: import_zod5.z.array(import_zod5.z.string()).optional()
1684
1894
  },
1685
1895
  (a) => client.reseller.create({
1686
1896
  name: a.name,
@@ -1694,10 +1904,10 @@ ${JSON.stringify(r, null, 2)}` : r;
1694
1904
  "update_customer",
1695
1905
  "Change a child org\u2019s status, delegated access or DSAR routing. `dsarRouting: null` clears the override.",
1696
1906
  {
1697
- id: import_zod4.z.string(),
1698
- status: import_zod4.z.enum(["active", "suspended"]).optional(),
1699
- delegatedAccess: import_zod4.z.boolean().optional(),
1700
- dsarRouting: import_zod4.z.enum(["reseller", "child"]).nullable().optional()
1907
+ id: import_zod5.z.string(),
1908
+ status: import_zod5.z.enum(["active", "suspended"]).optional(),
1909
+ delegatedAccess: import_zod5.z.boolean().optional(),
1910
+ dsarRouting: import_zod5.z.enum(["reseller", "child"]).nullable().optional()
1701
1911
  },
1702
1912
  (a) => client.reseller.update(a.id, {
1703
1913
  ...a.status ? { status: a.status } : {},
@@ -1708,7 +1918,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1708
1918
  tool(
1709
1919
  "suspend_customer",
1710
1920
  "Suspend a child org: it stops ingesting consent and its keys stop working, and it can be reactivated with update_customer. Its data is kept. (Permanent deletion is deliberately not available here.)",
1711
- { id: import_zod4.z.string() },
1921
+ { id: import_zod5.z.string() },
1712
1922
  async (a) => {
1713
1923
  await client.reseller.deprovision(a.id);
1714
1924
  return { suspended: a.id };
@@ -1717,72 +1927,72 @@ ${JSON.stringify(r, null, 2)}` : r;
1717
1927
  tool(
1718
1928
  "list_customer_keys",
1719
1929
  "A child org's API key prefixes. Never the secrets. Read-only.",
1720
- { id: import_zod4.z.string() },
1930
+ { id: import_zod5.z.string() },
1721
1931
  (a) => client.reseller.listKeys(a.id)
1722
1932
  );
1723
1933
  tool(
1724
1934
  "issue_customer_key",
1725
1935
  "Mint an API key for a child org. The secret is returned once. Prefer scopes and a property lock over a full-access key.",
1726
- { id: import_zod4.z.string(), name: import_zod4.z.string().optional(), scopes: import_zod4.z.array(import_zod4.z.string()).optional(), cbids: import_zod4.z.array(import_zod4.z.string()).min(1).optional() },
1936
+ { id: import_zod5.z.string(), name: import_zod5.z.string().optional(), scopes: import_zod5.z.array(import_zod5.z.string()).optional(), cbids: import_zod5.z.array(import_zod5.z.string()).min(1).optional() },
1727
1937
  (a) => client.reseller.mintKey(a.id, {
1728
1938
  ...a.name ? { name: a.name } : {},
1729
1939
  ...a.scopes ? { scopes: a.scopes } : {},
1730
1940
  ...a.cbids ? { cbids: a.cbids } : {}
1731
1941
  })
1732
1942
  );
1733
- tool("revoke_customer_key", "Revoke a child org's API key by prefix. Takes effect immediately.", { id: import_zod4.z.string(), prefix: import_zod4.z.string() }, async (a) => {
1943
+ tool("revoke_customer_key", "Revoke a child org's API key by prefix. Takes effect immediately.", { id: import_zod5.z.string(), prefix: import_zod5.z.string() }, async (a) => {
1734
1944
  await client.reseller.revokeKey(a.id, a.prefix);
1735
1945
  return { revoked: a.prefix };
1736
1946
  });
1737
1947
  tool(
1738
1948
  "erase_subject_data",
1739
1949
  "IRREVERSIBLY crypto-erase a data subject's consent records by their consent-receipt stamp (GDPR/CCPA deletion). Destroys the encryption key; the tamper-evident chain stays intact.",
1740
- { cbid: import_zod4.z.string(), stamp: import_zod4.z.string() },
1950
+ { cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1741
1951
  (a) => client.consent.eraseSubject(a.cbid, a.stamp)
1742
1952
  );
1743
1953
  tool(
1744
1954
  "export_subject_data",
1745
1955
  "Export a data subject's consent records (GDPR access/portability).",
1746
- { cbid: import_zod4.z.string(), stamp: import_zod4.z.string() },
1956
+ { cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1747
1957
  (a) => client.consent.exportSubject(a.cbid, a.stamp)
1748
1958
  );
1749
1959
  tool("list_banners", "List reusable banner designs in your org.", {}, () => client.banners.list());
1750
1960
  tool(
1751
1961
  "create_banner",
1752
1962
  "Create a reusable banner design.",
1753
- { name: import_zod4.z.string(), json: import_zod4.z.record(import_zod4.z.unknown()).describe("A v2 BannerConfig.") },
1963
+ { name: import_zod5.z.string(), json: import_zod5.z.record(import_zod5.z.unknown()).describe("A v2 BannerConfig.") },
1754
1964
  (a) => client.banners.create({ name: a.name, json: a.json })
1755
1965
  );
1756
- tool("get_banner", "Get a banner design by id.", { id: import_zod4.z.string() }, (a) => client.banners.get(a.id));
1966
+ tool("get_banner", "Get a banner design by id.", { id: import_zod5.z.string() }, (a) => client.banners.get(a.id));
1757
1967
  tool(
1758
1968
  "update_banner",
1759
1969
  "Update a banner design (name and/or config).",
1760
- { id: import_zod4.z.string(), name: import_zod4.z.string().optional(), json: import_zod4.z.record(import_zod4.z.unknown()).optional() },
1970
+ { id: import_zod5.z.string(), name: import_zod5.z.string().optional(), json: import_zod5.z.record(import_zod5.z.unknown()).optional() },
1761
1971
  (a) => client.banners.update(a.id, {
1762
1972
  ...a.name !== void 0 ? { name: a.name } : {},
1763
1973
  ...a.json !== void 0 ? { json: a.json } : {}
1764
1974
  })
1765
1975
  );
1766
- tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id: import_zod4.z.string() }, async (a) => {
1976
+ tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id: import_zod5.z.string() }, async (a) => {
1767
1977
  await client.banners.delete(a.id);
1768
1978
  return { ok: true };
1769
1979
  });
1770
1980
  tool(
1771
1981
  "get_banner_assignments",
1772
1982
  "The sites (cbids) a banner design is currently assigned to. Read-only.",
1773
- { id: import_zod4.z.string() },
1983
+ { id: import_zod5.z.string() },
1774
1984
  (a) => client.banners.assignments(a.id)
1775
1985
  );
1776
1986
  tool(
1777
1987
  "assign_banner",
1778
1988
  "Set which sites (cbids) use a banner design.",
1779
- { id: import_zod4.z.string(), cbids: import_zod4.z.array(import_zod4.z.string()) },
1989
+ { id: import_zod5.z.string(), cbids: import_zod5.z.array(import_zod5.z.string()) },
1780
1990
  (a) => client.banners.setAssignments(a.id, a.cbids)
1781
1991
  );
1782
1992
  tool(
1783
1993
  "publish_banner",
1784
1994
  "Publish a design live to all its assigned sites.",
1785
- { id: import_zod4.z.string() },
1995
+ { id: import_zod5.z.string() },
1786
1996
  (a) => client.banners.publish(a.id)
1787
1997
  );
1788
1998
  }