@cookiemunch/mcp 0.4.1 → 0.6.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/index.cjs CHANGED
@@ -29,7 +29,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
29
29
  var import_sdk = require("@cookiemunch/sdk");
30
30
 
31
31
  // src/tools.ts
32
- var import_zod5 = require("zod");
32
+ var import_zod6 = require("zod");
33
33
 
34
34
  // src/tools-config.ts
35
35
  var import_zod = require("zod");
@@ -560,6 +560,12 @@ function registerPlatformTools(tool, client) {
560
560
  {},
561
561
  () => client.fulfillment.executors()
562
562
  );
563
+ tool(
564
+ "get_dsar_executor",
565
+ "One connected system with its full profile (never its credentials). Read it before changing the profile: update_dsar_executor replaces the whole profile, so send back the complete one with your change made.",
566
+ { id: import_zod2.z.string().describe("The connection id.") },
567
+ (a) => client.fulfillment.executor(a.id)
568
+ );
563
569
  tool(
564
570
  "connect_dsar_executor",
565
571
  "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.",
@@ -567,12 +573,15 @@ function registerPlatformTools(tool, client) {
567
573
  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."),
568
574
  presetVersion: import_zod2.z.number().int().optional().describe("With preset: the version to build. Default the latest."),
569
575
  orgId: import_zod2.z.string().optional().describe("A preset param, when the preset's params list it."),
570
- 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."),
576
+ atlasIdAppId: import_zod2.z.string().optional().describe("A preset param, when the preset's params list it: the identity platform's app id, kept for revokeAtlasIdGrant."),
577
+ revokeAtlasIdGrant: import_zod2.z.boolean().optional().describe("A preset param, when the preset's params list it: default false. True adds an optional step that revokes the person's app grant on erasure; a credential without the scope reports skipped: insufficient_scope."),
578
+ label: import_zod2.z.string().optional().describe("Your name for the credential, shown beside keyPrefix."),
571
579
  system: import_zod2.z.string().optional().describe("The name this connection answers to in a plan, e.g. identity or crm. Required unless the preset has a default."),
572
580
  baseUrl: import_zod2.z.string().optional().describe("The system's public https origin. Required unless the preset sets it."),
573
581
  secretKey: import_zod2.z.string().describe("Its API key, with whatever scope that system needs to export and erase a user."),
574
582
  webhookSecret: import_zod2.z.string().optional().describe("Signing secret of its webhook endpoint. Optional: polling closes tasks without it."),
575
583
  auto: import_zod2.z.boolean().optional().describe("Open a sub-task automatically when a request reaches fulfilment. Default true."),
584
+ orchestrator: import_zod2.z.union([import_zod2.z.literal(1), import_zod2.z.literal(2)]).optional().describe("How it takes part in cases. Default 2 (v2 headers on every call); 1 is the v1 adapter. The answer carries a completionSecret, shown once, that signs its completions."),
576
585
  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."),
577
586
  dryRun: import_zod2.z.boolean().optional().describe("Validate everything and answer the connection that would be created, storing nothing.")
578
587
  },
@@ -581,6 +590,12 @@ function registerPlatformTools(tool, client) {
581
590
  return dryRun === true ? client.fulfillment.dryRunConnectExecutor(input) : client.fulfillment.connectExecutor(input);
582
591
  }
583
592
  );
593
+ tool(
594
+ "get_category_registry",
595
+ "The reserved consent categories any site can switch on with categories.suite (support_chat, referrals): each one\u2019s stance, the standard category to fall back on, the regulatory basis, its wording in every banner language, and known vendors. Public, read-only.",
596
+ {},
597
+ () => client.consent.categoryRegistry()
598
+ );
584
599
  tool(
585
600
  "list_dsar_executor_presets",
586
601
  "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.",
@@ -589,13 +604,15 @@ function registerPlatformTools(tool, client) {
589
604
  );
590
605
  tool(
591
606
  "upgrade_dsar_executor_preset",
592
- "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.",
607
+ "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. Your hand edits (profileOverrides) are kept and listed in the diff as kept or conflict; acceptPreset takes the preset's value for a path. A pinned connection (presetPinned) is refused. Use dryRun first: the answer shows exactly what would change and nothing is stored.",
593
608
  {
594
609
  id: import_zod2.z.string().describe("The connection id."),
595
610
  preset: import_zod2.z.string().optional().describe("Only to adopt a preset on a connection that has none."),
596
611
  presetVersion: import_zod2.z.number().int().optional(),
597
612
  orgId: import_zod2.z.string().optional(),
598
613
  atlasIdAppId: import_zod2.z.string().optional(),
614
+ revokeAtlasIdGrant: import_zod2.z.boolean().optional(),
615
+ acceptPreset: import_zod2.z.array(import_zod2.z.string()).optional().describe(`Overridden paths (profileOverrides) that take the preset's value again, e.g. ["profile.grantRevoke"]. Every other override is kept.`),
599
616
  dryRun: import_zod2.z.boolean().optional().describe("Answer the diff and change nothing.")
600
617
  },
601
618
  (a) => {
@@ -619,6 +636,18 @@ function registerPlatformTools(tool, client) {
619
636
  { id: import_zod2.z.string().describe("The connection id.") },
620
637
  (a) => client.fulfillment.executorWebhookDeliveries(a.id)
621
638
  );
639
+ tool(
640
+ "recheck_dsar_executor",
641
+ "Re-check a connected system now: a canary test (no real person) whose answer is recorded as the connection's health, so a stale failure clears at once. For after deploying that system's rights API.",
642
+ { id: import_zod2.z.string().describe("The connection id.") },
643
+ (a) => client.fulfillment.recheckExecutor(a.id)
644
+ );
645
+ tool(
646
+ "list_dsar_executor_health_history",
647
+ "A connected system's last health checks, newest first (each with ok, verdict and lastCheckedAt). Read-only.",
648
+ { id: import_zod2.z.string().describe("The connection id."), limit: import_zod2.z.number().int().min(1).max(50).optional().describe("Default 50.") },
649
+ (a) => client.fulfillment.executorHealthHistory(a.id, typeof a.limit === "number" ? { limit: a.limit } : {})
650
+ );
622
651
  tool(
623
652
  "disconnect_dsar_executor",
624
653
  "Disconnect a system. Its open sub-tasks stop being driven, and the stored credentials are deleted.",
@@ -651,6 +680,18 @@ function registerPlatformTools(tool, client) {
651
680
  ...typeof a.open === "boolean" ? { open: a.open } : {}
652
681
  })
653
682
  );
683
+ tool(
684
+ "run_executor_conformance",
685
+ "Run the cm-standard-v2 conformance kit against a connected system: every rule of the open executor contract (lookup by email and identity, no email match across identities, executeAfter honoured, idempotency, cancel keeps data, 404s, X-Version), on this org's canary subject only \u2014 no real person. Each rule passes, fails or is skipped by name. Only for a cm-standard-v2 connection.",
686
+ { id: import_zod2.z.string().describe("The connection id.") },
687
+ (a) => client.fulfillment.executorConformance(a.id)
688
+ );
689
+ tool(
690
+ "roll_executor_completion_secret",
691
+ "Mint a new completion secret for a connected system's signed completions. The new secret is in the answer, once \u2014 hand it to that system. The old one keeps verifying for 24 hours.",
692
+ { id: import_zod2.z.string().describe("The connection id.") },
693
+ (a) => client.fulfillment.rollExecutorCompletionSecret(a.id)
694
+ );
654
695
  tool(
655
696
  "get_dsar_task_export",
656
697
  "The export bundle a connected system produced for one sub-task, fetched from that system on demand. The platform keeps no copy.",
@@ -757,13 +798,44 @@ function registerIntegrationTools(tool, client) {
757
798
  { cbid: import_zod3.z.string().optional().describe("Site identifier; optional when the org has one site.") },
758
799
  (a) => client.integrationHealth(a.cbid)
759
800
  );
801
+ tool(
802
+ "list_health_waivers",
803
+ "The site\u2019s integration-health waivers: checks the organisation chose not to meet, each with its reason, who set it and until when. Read-only.",
804
+ { cbid: import_zod3.z.string().optional().describe("Site identifier; optional when the org has one site.") },
805
+ (a) => client.healthWaivers.list(a.cbid)
806
+ );
807
+ const waiverSchema = import_zod3.z.object({
808
+ cbid: import_zod3.z.string().optional().describe("Site identifier; optional when the org has one site."),
809
+ check: import_zod3.z.string().describe("A row\u2019s check or kind, e.g. atlas.cookie_consent."),
810
+ subject: import_zod3.z.string().optional().describe("A row\u2019s subject; omitted: every subject of the check."),
811
+ reason: import_zod3.z.string().describe("Why this is deliberate (shown on the row and in the audit log)."),
812
+ until: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number()]).nullable().optional().describe("When the waiver ends (ISO date or epoch ms, within a year); omitted: never.")
813
+ });
814
+ tool(
815
+ "set_health_waiver",
816
+ "Waive an integration-health check the organisation deliberately does not meet: the row then reports ok:null with waived {reason, by, until} instead of failing. Audited. Use only for real, deliberate choices; fix the rest.",
817
+ waiverSchema.shape,
818
+ (a) => client.healthWaivers.set(waiverSchema.parse(a))
819
+ );
820
+ tool(
821
+ "remove_health_waiver",
822
+ "Remove an integration-health waiver, so the check reports its real state again. Audited.",
823
+ { check: import_zod3.z.string(), cbid: import_zod3.z.string().optional(), subject: import_zod3.z.string().optional().describe("Default: every subject (*).") },
824
+ (a) => client.healthWaivers.remove(a.check, { ...a.cbid ? { cbid: a.cbid } : {}, ...a.subject ? { subject: a.subject } : {} })
825
+ );
826
+ tool(
827
+ "get_embed_manifest",
828
+ "A site\u2019s embed manifest (the tenant variant of /.well-known/forgedeck-embed.json): every origin the Cookie Munch embed touches on that site, by CSP directive (non-origin sources such as 'unsafe-inline' under requires), every cookie and browser-storage key it writes with category and lifetime, the checkers\u2019 User-Agent, and the hosts of the site\u2019s rights page and preference centre. Use it to build a Content-Security-Policy. Read-only.",
829
+ { cbid: import_zod3.z.string() },
830
+ (a) => client.embedManifest(a.cbid)
831
+ );
760
832
  const provisionSchema = import_zod3.z.object({
761
833
  product: import_zod3.z.string().describe("A slug naming the product."),
762
834
  domain: import_zod3.z.string().describe("The product\u2019s domain (bare hostname)."),
763
835
  name: import_zod3.z.string().optional(),
764
836
  aliases: import_zod3.z.array(import_zod3.z.string()).optional(),
765
837
  cbid: import_zod3.z.string().optional().describe("Update this site instead of matching by domain."),
766
- 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."),
838
+ atlas: import_zod3.z.object({ secretKey: import_zod3.z.string(), cookieConsent: import_zod3.z.boolean().optional(), dsrWebhook: import_zod3.z.boolean().optional(), rightsIdentity: import_zod3.z.boolean().optional().describe("Default true: make Atlas the site's rights sign-in, so signed-in requests are verified. A provider already in use is kept."), 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."),
767
839
  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."),
768
840
  rightsApi: import_zod3.z.object({ baseUrl: import_zod3.z.string(), secretKey: import_zod3.z.string(), profilePreset: import_zod3.z.string().optional() }).optional(),
769
841
  dryRun: import_zod3.z.boolean().optional().describe("Report what each step would do; write nothing on any platform. Run this first.")
@@ -779,13 +851,13 @@ function registerIntegrationTools(tool, client) {
779
851
  );
780
852
  tool(
781
853
  "list_site_partners",
782
- "Which partner platforms (Forumulate, Atlas) receive this site\u2019s consent events, each with its status, and which partners are on offer. Read-only.",
854
+ "Which partner platforms receive this site\u2019s consent events, each with its status, and which partners are on offer. Read-only.",
783
855
  { cbid: import_zod3.z.string() },
784
856
  (a) => client.sites.listPartners(a.cbid)
785
857
  );
786
858
  const linkSchema = import_zod3.z.object({
787
859
  cbid: import_zod3.z.string(),
788
- partner: import_zod3.z.enum(["forumulate", "atlas"]),
860
+ partner: import_zod3.z.string().describe("A partner this deployment knows: forumulate, atlas, chatly, referalli, or any other registered on it (list_site_partners shows them)."),
789
861
  externalId: import_zod3.z.string().describe("The partner\u2019s id for the receiving account, e.g. a Forumulate organisation id."),
790
862
  label: import_zod3.z.string().optional().describe('Shown with the partner name, e.g. "docs".'),
791
863
  events: import_zod3.z.array(import_zod3.z.enum(["consent.recorded", "consent.withdrawn"])).optional(),
@@ -808,31 +880,120 @@ function registerIntegrationTools(tool, client) {
808
880
  );
809
881
  }
810
882
 
811
- // src/tools-rights-page.ts
883
+ // src/tools-keys-tags.ts
812
884
  var import_zod4 = require("zod");
885
+ var TAGGED = ["org", "site", "webhook", "executor", "dsar", "partner_link"];
886
+ function registerKeyAndTagTools(tool, client) {
887
+ tool(
888
+ "get_own_key",
889
+ "The API key this server runs with: its prefix, name, scopes, properties, expiry, owner and last use. Works with any key, however narrow. Use it to check how long the key has left. Read-only.",
890
+ {},
891
+ () => client.keys.self()
892
+ );
893
+ tool(
894
+ "list_api_keys_standard",
895
+ "The organisation\u2019s keys in the suite-standard shape (id, owner, kind, env, scopes, resources, created_at, expires_at, last_used_at, last_used_ip, status). Needs a full-access key. Read-only.",
896
+ {},
897
+ () => client.keys.listStandard()
898
+ );
899
+ const vendSchema = import_zod4.z.object({
900
+ scopes: import_zod4.z.array(import_zod4.z.string()).min(1).describe("A subset of this key\u2019s own scopes."),
901
+ ttlSeconds: import_zod4.z.number().int().min(60).max(43200).describe("How long the key works, at most 12 hours."),
902
+ cbids: import_zod4.z.array(import_zod4.z.string()).min(1).optional().describe("Lock it to these sites (within this key\u2019s own lock)."),
903
+ name: import_zod4.z.string().max(100).optional()
904
+ });
905
+ tool(
906
+ "vend_api_key",
907
+ "Mint a short-lived key (at most 12 hours) for a sub-task, with a subset of this key\u2019s own scopes and properties; never a key that can vend. The secret is returned once. Needs keys:write or a full-access key.",
908
+ vendSchema.shape,
909
+ (a) => client.keys.vend(vendSchema.parse(a))
910
+ );
911
+ tool(
912
+ "revoke_leaked_key",
913
+ "Revoke an API key whose secret has been published (pasted in a chat, a gist, a log). Pass the whole secret. It only ever revokes, and always answers { received } whether or not the key was live. The owner is mailed.",
914
+ { key: import_zod4.z.string().describe("The leaked secret, whole."), source: import_zod4.z.string().optional().describe("Where it was found (a URL).") },
915
+ (a) => client.keys.revokeLeaked({ key: a.key, ...a.source ? { source: a.source } : {} })
916
+ );
917
+ tool(
918
+ "get_resource_tags",
919
+ "A resource\u2019s tags (metadata), its externalRef and whether it is a sandbox. Read-only.",
920
+ { type: import_zod4.z.enum(TAGGED), id: import_zod4.z.string() },
921
+ (a) => client.metadata.get(a.type, a.id)
922
+ );
923
+ const tagsSchema = import_zod4.z.object({
924
+ type: import_zod4.z.enum(TAGGED),
925
+ id: import_zod4.z.string(),
926
+ metadata: import_zod4.z.record(import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])).describe("Keys to set; null removes one. forgedeck_sandbox cannot be set here."),
927
+ dryRun: import_zod4.z.boolean().optional().describe("Answer with the diff, storing nothing. Do this first.")
928
+ });
929
+ tool(
930
+ "update_resource_tags",
931
+ "Change a resource\u2019s tags (merge). For adopting resources created before tags existed, e.g. forgedeck_product and forgedeck_env. A resource can never be made a sandbox after it was created.",
932
+ tagsSchema.shape,
933
+ (a) => {
934
+ const { type, id, metadata, dryRun } = tagsSchema.parse(a);
935
+ return client.metadata.update(type, id, metadata, { dryRun });
936
+ }
937
+ );
938
+ tool(
939
+ "list_partner_links",
940
+ "Every partner link of the organisation (site and org links), with scopes, expiry, last use and calls in the last 30 days. Read-only.",
941
+ { metadata: import_zod4.z.record(import_zod4.z.string()).optional().describe("Keep only links with these tags.") },
942
+ (a) => client.partnerLinks.list(a.metadata ? { metadata: a.metadata } : void 0)
943
+ );
944
+ const linkSchema = import_zod4.z.object({
945
+ partner: import_zod4.z.string().describe("A partner this deployment knows (built in or registered)."),
946
+ resource: import_zod4.z.string().describe("site:<cbid> or org:<this org id>."),
947
+ scopes: import_zod4.z.array(import_zod4.z.enum(["consent:read", "receipt:read", "dsar:read", "dsar:write", "dsar:rights-links", "sites:read"])).min(1),
948
+ expires_at: import_zod4.z.string().optional().describe("ISO 8601, in the future."),
949
+ externalId: import_zod4.z.string().optional(),
950
+ label: import_zod4.z.string().max(60).optional()
951
+ });
952
+ tool(
953
+ "create_partner_link",
954
+ "Let a partner platform act on a site or on the organisation within these scopes (it calls the API with its own token and the link id), and, with consent:read on a site, receive that site\u2019s consent events. No secret is created. Never grants more than this key holds.",
955
+ linkSchema.shape,
956
+ (a) => client.partnerLinks.create(linkSchema.parse(a))
957
+ );
958
+ tool(
959
+ "revoke_partner_link",
960
+ "Revoke a partner link: the partner\u2019s calls under it and its deliveries stop at once.",
961
+ { id: import_zod4.z.string() },
962
+ (a) => client.partnerLinks.revoke(a.id)
963
+ );
964
+ tool(
965
+ "get_provision_env",
966
+ "What `forgedeck env` writes for a product provisioned with this forgedeck ref: variable names, non-secret values (cbid, script URL, API base) and references for secrets, never a secret. Read-only.",
967
+ { ref: import_zod4.z.string() },
968
+ (a) => client.provisionEnv(a.ref)
969
+ );
970
+ }
971
+
972
+ // src/tools-rights-page.ts
973
+ var import_zod5 = require("zod");
813
974
  function registerRightsTools(tool, client) {
814
- const cbid = { cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org.") };
975
+ const cbid = { cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org.") };
815
976
  const base = {
816
- 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.")
977
+ baseUpdatedAt: import_zod5.z.union([import_zod5.z.number().int(), import_zod5.z.string(), import_zod5.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.")
817
978
  };
818
979
  const baseOpt = (a) => a.baseUpdatedAt !== void 0 ? { baseUpdatedAt: a.baseUpdatedAt } : {};
819
980
  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));
820
981
  tool(
821
982
  "update_rights_page",
822
983
  "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.",
823
- { ...cbid, page: import_zod4.z.record(import_zod4.z.unknown()).describe("The whole RightsPage document (v: 1)."), ...base },
984
+ { ...cbid, page: import_zod5.z.record(import_zod5.z.unknown()).describe("The whole RightsPage document (v: 1)."), ...base },
824
985
  (a) => client.rightsPage.put(a.cbid, a.page, baseOpt(a))
825
986
  );
826
987
  tool(
827
988
  "patch_rights_page",
828
989
  "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).",
829
- { ...cbid, patch: import_zod4.z.record(import_zod4.z.unknown()), ...base },
990
+ { ...cbid, patch: import_zod5.z.record(import_zod5.z.unknown()), ...base },
830
991
  (a) => client.rightsPage.patch(a.cbid, a.patch, baseOpt(a))
831
992
  );
832
993
  tool(
833
994
  "preview_rights_page",
834
995
  'Validate a rights-page write WITHOUT saving: returns the document as it would be stored and any publish warnings. mode "patch" (default) or "put".',
835
- { ...cbid, page: import_zod4.z.record(import_zod4.z.unknown()), mode: import_zod4.z.enum(["patch", "put"]).optional() },
996
+ { ...cbid, page: import_zod5.z.record(import_zod5.z.unknown()), mode: import_zod5.z.enum(["patch", "put"]).optional() },
836
997
  (a) => client.rightsPage.dryRun(a.cbid, a.page, { mode: a.mode ?? "patch" })
837
998
  );
838
999
  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));
@@ -846,14 +1007,14 @@ function registerRightsTools(tool, client) {
846
1007
  tool(
847
1008
  "rollback_rights_page",
848
1009
  "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.",
849
- { ...cbid, version: import_zod4.z.number().int().min(1), ...base },
1010
+ { ...cbid, version: import_zod5.z.number().int().min(1), ...base },
850
1011
  (a) => client.rightsPage.rollback(a.cbid, a.version, baseOpt(a))
851
1012
  );
852
1013
  }
853
1014
  function registerRightsPageTools(tool, client) {
854
- const site = import_zod4.z.object({ cbid: import_zod4.z.string().describe("Site identifier (cbid). Must belong to your org.") });
1015
+ const site = import_zod5.z.object({ cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org.") });
855
1016
  const host = site.extend({
856
- hostname: import_zod4.z.string().describe("The custom hostname, e.g. privacy.example.com (unicode or punycode).")
1017
+ hostname: import_zod5.z.string().describe("The custom hostname, e.g. privacy.example.com (unicode or punycode).")
857
1018
  });
858
1019
  tool(
859
1020
  "list_rights_page_domains",
@@ -993,10 +1154,10 @@ function registerTools(server, client) {
993
1154
  }
994
1155
  });
995
1156
  };
996
- const cbid = { cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org.") };
1157
+ const cbid = { cbid: import_zod6.z.string().describe("Site identifier (cbid). Must belong to your org.") };
997
1158
  const range = {
998
- from: import_zod5.z.number().optional().describe("Epoch-ms lower bound."),
999
- to: import_zod5.z.number().optional().describe("Epoch-ms upper bound.")
1159
+ from: import_zod6.z.number().optional().describe("Epoch-ms lower bound."),
1160
+ to: import_zod6.z.number().optional().describe("Epoch-ms upper bound.")
1000
1161
  };
1001
1162
  tool(
1002
1163
  "whoami",
@@ -1014,19 +1175,19 @@ function registerTools(server, client) {
1014
1175
  tool(
1015
1176
  "get_site",
1016
1177
  "One site: its domain, cbid and verification status. Read-only.",
1017
- { cbid: import_zod5.z.string() },
1178
+ { cbid: import_zod6.z.string() },
1018
1179
  (a) => client.sites.get(a.cbid)
1019
1180
  );
1020
1181
  tool(
1021
1182
  "get_site_banner",
1022
1183
  "Which banner design a site uses, or bannerId null when none is assigned. Read-only.",
1023
- { cbid: import_zod5.z.string() },
1184
+ { cbid: import_zod6.z.string() },
1024
1185
  (a) => client.sites.banner(a.cbid)
1025
1186
  );
1026
1187
  tool(
1027
1188
  "get_privacy_policy",
1028
1189
  "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.",
1029
- { 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() },
1190
+ { cbid: import_zod6.z.string(), contactEmail: import_zod6.z.string().optional(), effectiveDate: import_zod6.z.string().optional().describe("YYYY-MM-DD; defaults to today."), jurisdictions: import_zod6.z.array(import_zod6.z.string()).optional() },
1030
1191
  (a) => client.sites.policy(a.cbid, {
1031
1192
  ...a.contactEmail ? { contactEmail: a.contactEmail } : {},
1032
1193
  ...a.effectiveDate ? { effectiveDate: a.effectiveDate } : {},
@@ -1036,7 +1197,7 @@ function registerTools(server, client) {
1036
1197
  tool(
1037
1198
  "set_ad_personalization",
1038
1199
  "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.",
1039
- { cbid: import_zod5.z.string(), enabled: import_zod5.z.boolean(), default: import_zod5.z.boolean().optional(), label: import_zod5.z.string().optional() },
1200
+ { cbid: import_zod6.z.string(), enabled: import_zod6.z.boolean(), default: import_zod6.z.boolean().optional(), label: import_zod6.z.string().optional() },
1040
1201
  (a) => client.sites.setAdPersonalization(a.cbid, {
1041
1202
  enabled: a.enabled,
1042
1203
  ...a.default !== void 0 ? { default: a.default } : {},
@@ -1047,11 +1208,11 @@ function registerTools(server, client) {
1047
1208
  "analyze_session",
1048
1209
  "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.",
1049
1210
  {
1050
- cbid: import_zod5.z.string(),
1051
- har: import_zod5.z.unknown().optional().describe("A HAR export of the session."),
1052
- requests: import_zod5.z.array(import_zod5.z.unknown()).optional().describe("Or the requests directly."),
1053
- consent: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.boolean()).optional(),
1054
- gpc: import_zod5.z.boolean().optional()
1211
+ cbid: import_zod6.z.string(),
1212
+ har: import_zod6.z.unknown().optional().describe("A HAR export of the session."),
1213
+ requests: import_zod6.z.array(import_zod6.z.unknown()).optional().describe("Or the requests directly."),
1214
+ consent: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.boolean()).optional(),
1215
+ gpc: import_zod6.z.boolean().optional()
1055
1216
  },
1056
1217
  (a) => client.sites.analyzeSession(a.cbid, {
1057
1218
  ...a.har !== void 0 ? { har: a.har } : {},
@@ -1063,14 +1224,14 @@ function registerTools(server, client) {
1063
1224
  tool(
1064
1225
  "create_site",
1065
1226
  "Create a new site. The cbid is auto-generated if you omit it.",
1066
- { domain: import_zod5.z.string().describe("The site domain, e.g. example.com."), cbid: import_zod5.z.string().optional().describe("Optional explicit cbid.") },
1227
+ { domain: import_zod6.z.string().describe("The site domain, e.g. example.com."), cbid: import_zod6.z.string().optional().describe("Optional explicit cbid.") },
1067
1228
  (a) => client.sites.create({ domain: a.domain, ...typeof a.cbid === "string" ? { cbid: a.cbid } : {} })
1068
1229
  );
1069
1230
  tool(
1070
1231
  "create_sites_bulk",
1071
1232
  "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.",
1072
1233
  {
1073
- 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)
1234
+ sites: import_zod6.z.array(import_zod6.z.object({ domain: import_zod6.z.string(), cbid: import_zod6.z.string().optional(), platform: import_zod6.z.string().optional() })).min(1).max(100)
1074
1235
  },
1075
1236
  (a) => client.sites.createBulk(a.sites)
1076
1237
  );
@@ -1080,15 +1241,15 @@ function registerTools(server, client) {
1080
1241
  "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.",
1081
1242
  {
1082
1243
  ...cbid,
1083
- 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."),
1084
- 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.")
1244
+ config: import_zod6.z.record(import_zod6.z.unknown()).describe("The full SiteConfig to write, not a patch. Without keepUnspecified, omitted top-level fields are NOT preserved from the current config."),
1245
+ keepUnspecified: import_zod6.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.")
1085
1246
  },
1086
1247
  (a) => a.keepUnspecified === true ? client.sites.putConfig(a.cbid, a.config, { keep: "unspecified" }) : client.sites.putConfig(a.cbid, a.config)
1087
1248
  );
1088
1249
  tool(
1089
1250
  "patch_site_config",
1090
1251
  `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.`,
1091
- { ...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.') },
1252
+ { ...cbid, config: import_zod6.z.record(import_zod6.z.unknown()).describe('The subset of SiteConfig to change, e.g. { "banner": { "showRightsLink": true } }. Everything else is preserved; null removes a field.') },
1092
1253
  (a) => client.sites.patchConfig(a.cbid, a.config)
1093
1254
  );
1094
1255
  tool(
@@ -1096,9 +1257,9 @@ function registerTools(server, client) {
1096
1257
  '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.',
1097
1258
  {
1098
1259
  ...cbid,
1099
- config: import_zod5.z.record(import_zod5.z.unknown()).describe('The patch (or, with mode "put", the full config) to preview.'),
1100
- mode: import_zod5.z.enum(["patch", "put"]).optional().describe("patch (default) merges; put replaces."),
1101
- keepUnspecified: import_zod5.z.boolean().optional().describe('With mode "put": preview update_site_config with keepUnspecified (omitted top-level fields keep their stored value).')
1260
+ config: import_zod6.z.record(import_zod6.z.unknown()).describe('The patch (or, with mode "put", the full config) to preview.'),
1261
+ mode: import_zod6.z.enum(["patch", "put"]).optional().describe("patch (default) merges; put replaces."),
1262
+ keepUnspecified: import_zod6.z.boolean().optional().describe('With mode "put": preview update_site_config with keepUnspecified (omitted top-level fields keep their stored value).')
1102
1263
  },
1103
1264
  (a) => client.sites.dryRunConfig(a.cbid, a.config, {
1104
1265
  mode: a.mode ?? "patch",
@@ -1110,8 +1271,8 @@ function registerTools(server, client) {
1110
1271
  '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.',
1111
1272
  {
1112
1273
  ...cbid,
1113
- config: import_zod5.z.record(import_zod5.z.unknown()).describe("The proposed SiteConfig (or a partial one, or a v2 flow design)."),
1114
- 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.")
1274
+ config: import_zod6.z.record(import_zod6.z.unknown()).describe("The proposed SiteConfig (or a partial one, or a v2 flow design)."),
1275
+ replace: import_zod6.z.boolean().optional().describe("Check what update_site_config (a full replace) would store, instead of what patch_site_config (a merge) would.")
1115
1276
  },
1116
1277
  async (a) => {
1117
1278
  const r = await client.sites.lintConfig(a.cbid, a.config, a.replace === true ? { replace: true } : {});
@@ -1132,10 +1293,16 @@ ${JSON.stringify(r, null, 2)}` : r;
1132
1293
  { ...cbid, ...range },
1133
1294
  (a) => client.consent.stats(a.cbid, { from: a.from, to: a.to })
1134
1295
  );
1296
+ tool(
1297
+ "get_consent_insights",
1298
+ "Opt-in rates for a site: totals with the decision rate (decisions per banner impression), opt-in by region, and by A/B variant (all-time counters). Opt-in by language and time-to-decision are not recorded; those fields are null and notRecorded says why. Read-only.",
1299
+ { ...cbid, ...range },
1300
+ (a) => client.consent.insights(a.cbid, { from: a.from, to: a.to })
1301
+ );
1135
1302
  tool(
1136
1303
  "get_consent_log",
1137
1304
  "Get recent anonymised consent records for a site.",
1138
- { ...cbid, ...range, limit: import_zod5.z.number().optional().describe("Max records to return (default 200).") },
1305
+ { ...cbid, ...range, limit: import_zod6.z.number().optional().describe("Max records to return (default 200).") },
1139
1306
  (a) => client.consent.log(a.cbid, {
1140
1307
  from: a.from,
1141
1308
  to: a.to,
@@ -1145,54 +1312,54 @@ ${JSON.stringify(r, null, 2)}` : r;
1145
1312
  tool(
1146
1313
  "get_subject_consent",
1147
1314
  "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.",
1148
- { subjectId: import_zod5.z.string() },
1315
+ { subjectId: import_zod6.z.string() },
1149
1316
  (a) => client.subjects.consent(a.subjectId)
1150
1317
  );
1151
1318
  tool("list_dsar", "List all Data Subject Access Requests for your organization.", {}, () => client.dsar.list());
1152
1319
  tool(
1153
1320
  "update_dsar_executor",
1154
- "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.",
1321
+ "Change a connected system in place \u2014 its profile, address, credential, label (null removes it), auto flag or presetPinned (true stops preset upgrades). Only what you pass changes; the stored credential is kept unless you give a new one. A profile edit on a preset-built connection is recorded in profileOverrides, so an upgrade keeps it. With dryRun, answers the connection as it would be and a diff, and changes nothing.",
1155
1322
  {
1156
- id: import_zod5.z.string(),
1157
- patch: import_zod5.z.record(import_zod5.z.unknown()),
1158
- dryRun: import_zod5.z.boolean().optional().describe("Validate and diff without saving.")
1323
+ id: import_zod6.z.string(),
1324
+ patch: import_zod6.z.record(import_zod6.z.unknown()),
1325
+ dryRun: import_zod6.z.boolean().optional().describe("Validate and diff without saving.")
1159
1326
  },
1160
1327
  (a) => a.dryRun === true ? client.fulfillment.dryRunUpdateExecutor(a.id, a.patch) : client.fulfillment.updateExecutor(a.id, a.patch)
1161
1328
  );
1162
1329
  tool(
1163
1330
  "get_dsar",
1164
1331
  "One rights request by id, including its status and the deadline it must be answered by.",
1165
- { id: import_zod5.z.string() },
1332
+ { id: import_zod6.z.string() },
1166
1333
  (a) => client.dsar.get(a.id)
1167
1334
  );
1168
1335
  tool(
1169
1336
  "erase_dsar_subject",
1170
1337
  "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.",
1171
- { id: import_zod5.z.string(), cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1338
+ { id: import_zod6.z.string(), cbid: import_zod6.z.string(), stamp: import_zod6.z.string() },
1172
1339
  (a) => client.dsar.erase(a.id, a.cbid, a.stamp)
1173
1340
  );
1174
1341
  tool(
1175
1342
  "export_dsar_subject",
1176
1343
  "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.",
1177
- { id: import_zod5.z.string(), cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
1344
+ { id: import_zod6.z.string(), cbid: import_zod6.z.string(), stamp: import_zod6.z.string() },
1178
1345
  (a) => client.dsar.export(a.id, a.cbid, a.stamp)
1179
1346
  );
1180
1347
  tool(
1181
1348
  "get_dsar_response_notice",
1182
1349
  "The subject-facing response notice for a request, as plain text \u2014 what to send the person. Read-only; nothing is sent.",
1183
- { id: import_zod5.z.string() },
1350
+ { id: import_zod6.z.string() },
1184
1351
  (a) => client.dsar.response(a.id)
1185
1352
  );
1186
1353
  tool(
1187
1354
  "create_dsar",
1188
1355
  "Open a new Data Subject Access Request.",
1189
1356
  {
1190
- type: import_zod5.z.enum(["access", "deletion", "rectification", "portability", "opt-out"]).describe("DSAR right being exercised."),
1191
- subjectEmail: import_zod5.z.string().describe("The data subject\u2019s email."),
1192
- regulation: import_zod5.z.enum(["gdpr", "ccpa"]).describe("Governing regulation."),
1193
- note: import_zod5.z.string().optional().describe("Optional INTERNAL note; never shown to the data subject."),
1194
- messageToSubject: import_zod5.z.string().max(2e3).optional().describe("The line the data subject reads in the response notice. Never an API key."),
1195
- 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.")
1357
+ type: import_zod6.z.enum(["access", "deletion", "rectification", "portability", "opt-out"]).describe("DSAR right being exercised."),
1358
+ subjectEmail: import_zod6.z.string().describe("The data subject\u2019s email."),
1359
+ regulation: import_zod6.z.enum(["gdpr", "ccpa"]).describe("Governing regulation."),
1360
+ note: import_zod6.z.string().optional().describe("Optional INTERNAL note; never shown to the data subject."),
1361
+ messageToSubject: import_zod6.z.string().max(2e3).optional().describe("The line the data subject reads in the response notice. Never an API key."),
1362
+ test: import_zod6.z.boolean().optional().describe("Mark it as a test request: kept off the SLA board and deletable afterwards with delete_test_dsar.")
1196
1363
  },
1197
1364
  (a) => client.dsar.create({
1198
1365
  type: a.type,
@@ -1207,11 +1374,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1207
1374
  "create_rights_link",
1208
1375
  "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.",
1209
1376
  {
1210
- cbid: import_zod5.z.string().describe("Site identifier (cbid). Must belong to your org."),
1211
- email: import_zod5.z.string().describe("The signed-in person\u2019s verified email address."),
1212
- userId: import_zod5.z.string().optional().describe("Your own account id for them; recorded on the request."),
1213
- 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."),
1214
- ttlSeconds: import_zod5.z.number().int().min(60).max(3600).optional().describe("How long the link works, in seconds (default 900).")
1377
+ cbid: import_zod6.z.string().describe("Site identifier (cbid). Must belong to your org."),
1378
+ email: import_zod6.z.string().describe("The signed-in person\u2019s verified email address."),
1379
+ userId: import_zod6.z.string().optional().describe("Your own account id for them; recorded on the request."),
1380
+ rights: import_zod6.z.array(import_zod6.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."),
1381
+ ttlSeconds: import_zod6.z.number().int().min(60).max(3600).optional().describe("How long the link works, in seconds (default 900).")
1215
1382
  },
1216
1383
  (a) => client.rightsLinks.create(a.cbid, {
1217
1384
  subject: { email: a.email, ...typeof a.userId === "string" ? { userId: a.userId } : {} },
@@ -1222,7 +1389,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1222
1389
  tool(
1223
1390
  "delete_test_dsar",
1224
1391
  "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.",
1225
- { id: import_zod5.z.string().describe("The test request id.") },
1392
+ { id: import_zod6.z.string().describe("The test request id.") },
1226
1393
  async (a) => {
1227
1394
  await client.dsar.delete(a.id);
1228
1395
  return { deleted: a.id };
@@ -1231,16 +1398,99 @@ ${JSON.stringify(r, null, 2)}` : r;
1231
1398
  tool(
1232
1399
  "mark_dsar_test",
1233
1400
  "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 }.",
1234
- { id: import_zod5.z.string().describe("The closed request id.") },
1401
+ { id: import_zod6.z.string().describe("The closed request id.") },
1235
1402
  (a) => client.dsar.markTest(a.id)
1236
1403
  );
1404
+ tool(
1405
+ "open_dsar_case",
1406
+ "Open a rights case fanned out to every connected system \u2014 an account closure from a product, an erasure, an export. type takes the canonical words (access, deletion, closure, restriction, rectification) or an alias (erasure, erase, export). For an erasure or closure, executeAfter = now + the site's graceDays is sent to every system and nothing is erased before it. source product or atlas attests the person (needs dsar:write; atlas needs subject.identity from the site's own sign-in issuer); admin files it received for verification. Pass idempotencyKey (16\u2013128 chars) so a retry answers the same case.",
1407
+ {
1408
+ cbid: import_zod6.z.string(),
1409
+ type: import_zod6.z.string().describe("access | deletion | closure | restriction | rectification, or erasure / erase / export."),
1410
+ emails: import_zod6.z.array(import_zod6.z.string()).optional().describe("The person's addresses."),
1411
+ identity: import_zod6.z.object({ iss: import_zod6.z.string(), sub: import_zod6.z.string(), ext: import_zod6.z.string().optional(), principal: import_zod6.z.string().optional() }).optional().describe("A signed-in identity from the site's sign-in issuer. People are never linked on email when it is present."),
1412
+ source: import_zod6.z.enum(["product", "atlas", "admin"]).optional(),
1413
+ reason: import_zod6.z.string().optional(),
1414
+ skipSystems: import_zod6.z.array(import_zod6.z.string()).optional().describe("System names, connection ids, or self."),
1415
+ fulfill: import_zod6.z.boolean().optional(),
1416
+ test: import_zod6.z.boolean().optional(),
1417
+ idempotencyKey: import_zod6.z.string().optional(),
1418
+ trace: import_zod6.z.string().optional().describe("An X-ForgeDeck-Trace to keep, from the caller.")
1419
+ },
1420
+ (a) => client.dsar.openCase(
1421
+ {
1422
+ cbid: a.cbid,
1423
+ type: a.type,
1424
+ subject: { emails: a.emails ?? [], ...a.identity ? { identity: a.identity } : {} },
1425
+ ...a.source ? { source: a.source } : {},
1426
+ ...typeof a.reason === "string" ? { reason: a.reason } : {},
1427
+ ...Array.isArray(a.skipSystems) ? { skipSystems: a.skipSystems } : {},
1428
+ ...typeof a.fulfill === "boolean" ? { fulfill: a.fulfill } : {},
1429
+ ...a.test === true ? { test: true } : {}
1430
+ },
1431
+ {
1432
+ ...typeof a.idempotencyKey === "string" ? { idempotencyKey: a.idempotencyKey } : {},
1433
+ ...typeof a.trace === "string" ? { trace: a.trace } : {}
1434
+ }
1435
+ )
1436
+ );
1437
+ tool(
1438
+ "get_dsar_case",
1439
+ "One case across every connected system: its status (pending, scheduled, processing, completed, completed_with_retention, rejected, cancelled), executeAfter, trace and one row per system with its status, eta and retention lines. Read-only.",
1440
+ { id: import_zod6.z.string() },
1441
+ (a) => client.dsar.getCase(a.id)
1442
+ );
1443
+ tool(
1444
+ "cancel_dsar_case",
1445
+ "Cancel a case before its executeAfter: work never sent is withdrawn, scheduled work is cancelled in each system, and every system's data stays intact. Refused once executeAfter has passed.",
1446
+ { id: import_zod6.z.string() },
1447
+ (a) => client.dsar.cancelCase(a.id)
1448
+ );
1449
+ tool(
1450
+ "get_dsar_case_receipt",
1451
+ "The signed receipt for a case: every system, its status and date, retention lines, the subject as hashes only. Ed25519, verifiable against GET /v1/partner/jwks.json. Read-only.",
1452
+ { id: import_zod6.z.string() },
1453
+ (a) => client.dsar.caseReceipt(a.id)
1454
+ );
1455
+ tool(
1456
+ "find_dsar_by_trace",
1457
+ "The rights request carrying one X-ForgeDeck-Trace id \u2014 to follow one event across products. Read-only.",
1458
+ { trace: import_zod6.z.string() },
1459
+ (a) => client.dsar.listByTrace(a.trace)
1460
+ );
1461
+ tool(
1462
+ "get_dsar_settings",
1463
+ "A site's rights-request settings: graceDays, how long an erasure or account closure waits before any system acts: 7 for a new site, 0 (opt-in) for one that existed before. Read-only.",
1464
+ { cbid: import_zod6.z.string() },
1465
+ (a) => client.dsarSettings.get(a.cbid)
1466
+ );
1467
+ tool(
1468
+ "set_dsar_settings",
1469
+ "Set a site's graceDays (0\u201330). Applies to cases opened afterwards. Audited.",
1470
+ { cbid: import_zod6.z.string(), graceDays: import_zod6.z.number().int().min(0).max(30) },
1471
+ (a) => client.dsarSettings.set(a.cbid, { graceDays: a.graceDays })
1472
+ );
1473
+ tool(
1474
+ "get_subject_card",
1475
+ 'Open rights requests for one person, as a support or CRM sidebar shows them \u2014 e.g. "erasure scheduled for 1 Nov: do not export this transcript". Name the person by iss and sub (preferred) or email. Read-only.',
1476
+ {
1477
+ app: import_zod6.z.string().describe("The sidebar app asking, as a slug, e.g. chatly."),
1478
+ iss: import_zod6.z.string().optional(),
1479
+ sub: import_zod6.z.string().optional(),
1480
+ email: import_zod6.z.string().optional()
1481
+ },
1482
+ (a) => client.integrations.subjectCard(
1483
+ a.app,
1484
+ typeof a.iss === "string" && typeof a.sub === "string" ? { iss: a.iss, sub: a.sub } : { email: String(a.email ?? "") }
1485
+ )
1486
+ );
1237
1487
  tool(
1238
1488
  "advance_dsar",
1239
1489
  "Advance a DSAR to a new status (received \u2192 verifying \u2192 in_progress \u2192 completed, or rejected).",
1240
1490
  {
1241
- id: import_zod5.z.string().describe("The DSAR id."),
1242
- toStatus: import_zod5.z.enum(["received", "verifying", "in_progress", "completed", "rejected"]).describe("Target status."),
1243
- messageToSubject: import_zod5.z.string().max(2e3).optional().describe("Replaces the line the data subject reads in the notice \u2014 for a rejection, why.")
1491
+ id: import_zod6.z.string().describe("The DSAR id."),
1492
+ toStatus: import_zod6.z.enum(["received", "verifying", "in_progress", "completed", "rejected"]).describe("Target status."),
1493
+ messageToSubject: import_zod6.z.string().max(2e3).optional().describe("Replaces the line the data subject reads in the notice \u2014 for a rejection, why.")
1244
1494
  },
1245
1495
  (a) => typeof a.messageToSubject === "string" ? client.dsar.advance(a.id, a.toStatus, { messageToSubject: a.messageToSubject }) : client.dsar.advance(a.id, a.toStatus)
1246
1496
  );
@@ -1253,7 +1503,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1253
1503
  tool(
1254
1504
  "get_receipt",
1255
1505
  "Fetch the signed consent receipt for a single consent record (by stamp).",
1256
- { ...cbid, stamp: import_zod5.z.string().describe("The consent record stamp/id.") },
1506
+ { ...cbid, stamp: import_zod6.z.string().describe("The consent record stamp/id.") },
1257
1507
  (a) => client.consent.receipt(a.cbid, a.stamp)
1258
1508
  );
1259
1509
  tool("delete_site", "Delete a site (cbid) and its configuration from your org.", { ...cbid }, async (a) => {
@@ -1265,13 +1515,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1265
1515
  "create_vendor",
1266
1516
  "Register a vendor (processor) and compute its risk score.",
1267
1517
  {
1268
- name: import_zod5.z.string().describe("Vendor name."),
1269
- category: import_zod5.z.string().describe("Vendor category, e.g. analytics."),
1270
- dataShared: import_zod5.z.array(import_zod5.z.string()).describe("Categories of data shared with the vendor."),
1271
- dpaSigned: import_zod5.z.boolean().describe("Whether a Data Processing Agreement is signed."),
1272
- subprocessors: import_zod5.z.number().describe("Number of subprocessors."),
1273
- certifications: import_zod5.z.array(import_zod5.z.string()).describe("Compliance certifications, e.g. ISO27001."),
1274
- region: import_zod5.z.string().describe("Primary processing region, e.g. EU.")
1518
+ name: import_zod6.z.string().describe("Vendor name."),
1519
+ category: import_zod6.z.string().describe("Vendor category, e.g. analytics."),
1520
+ dataShared: import_zod6.z.array(import_zod6.z.string()).describe("Categories of data shared with the vendor."),
1521
+ dpaSigned: import_zod6.z.boolean().describe("Whether a Data Processing Agreement is signed."),
1522
+ subprocessors: import_zod6.z.number().describe("Number of subprocessors."),
1523
+ certifications: import_zod6.z.array(import_zod6.z.string()).describe("Compliance certifications, e.g. ISO27001."),
1524
+ region: import_zod6.z.string().describe("Primary processing region, e.g. EU.")
1275
1525
  },
1276
1526
  (a) => client.vendors.create({
1277
1527
  name: a.name,
@@ -1289,13 +1539,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1289
1539
  "create_ropa",
1290
1540
  "Create a Record of Processing Activity (RoPA) entry.",
1291
1541
  {
1292
- name: import_zod5.z.string().describe("Activity name."),
1293
- purpose: import_zod5.z.string().describe("Purpose of processing."),
1294
- legalBasis: import_zod5.z.enum(["consent", "contract", "legal-obligation", "vital-interests", "public-task", "legitimate-interests"]).describe("GDPR legal basis."),
1295
- dataCategories: import_zod5.z.array(import_zod5.z.string()).describe("Categories of personal data."),
1296
- recipients: import_zod5.z.array(import_zod5.z.string()).describe("Recipients of the data."),
1297
- retentionDays: import_zod5.z.number().describe("Retention period in days."),
1298
- crossBorderTransfer: import_zod5.z.boolean().describe("Whether data is transferred across borders.")
1542
+ name: import_zod6.z.string().describe("Activity name."),
1543
+ purpose: import_zod6.z.string().describe("Purpose of processing."),
1544
+ legalBasis: import_zod6.z.enum(["consent", "contract", "legal-obligation", "vital-interests", "public-task", "legitimate-interests"]).describe("GDPR legal basis."),
1545
+ dataCategories: import_zod6.z.array(import_zod6.z.string()).describe("Categories of personal data."),
1546
+ recipients: import_zod6.z.array(import_zod6.z.string()).describe("Recipients of the data."),
1547
+ retentionDays: import_zod6.z.number().describe("Retention period in days."),
1548
+ crossBorderTransfer: import_zod6.z.boolean().describe("Whether data is transferred across borders.")
1299
1549
  },
1300
1550
  (a) => client.ropa.create({
1301
1551
  name: a.name,
@@ -1316,7 +1566,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1316
1566
  tool(
1317
1567
  "scan_site",
1318
1568
  "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.",
1319
- { ...cbid, wait: import_zod5.z.boolean().optional().describe("Wait for the scan to finish (up to 100 s) and return its outcome.") },
1569
+ { ...cbid, wait: import_zod6.z.boolean().optional().describe("Wait for the scan to finish (up to 100 s) and return its outcome.") },
1320
1570
  async (a) => {
1321
1571
  let started;
1322
1572
  try {
@@ -1329,8 +1579,8 @@ ${JSON.stringify(r, null, 2)}` : r;
1329
1579
  );
1330
1580
  tool(
1331
1581
  "get_scan_status",
1332
- "Get a site\u2019s last cookie scan: state (queued, scanning, done, failed), scanId, durationMs, cookieCount, pagesVisited and error when it failed.",
1333
- { ...cbid, wait: import_zod5.z.number().min(0).max(60).optional().describe("Seconds (\u226460) to wait for a running scan to settle before answering.") },
1582
+ "Get a site\u2019s last cookie scan: state (idle when never scanned, queued, scanning, done, failed), scanId, durationMs, cookieCount, pagesVisited and error when it failed.",
1583
+ { ...cbid, wait: import_zod6.z.number().min(0).max(60).optional().describe("Seconds (\u226460) to wait for a running scan to settle before answering.") },
1334
1584
  (a) => a.wait !== void 0 ? client.sites.scanStatus(a.cbid, { wait: a.wait }) : client.sites.scanStatus(a.cbid)
1335
1585
  );
1336
1586
  tool(
@@ -1347,20 +1597,26 @@ ${JSON.stringify(r, null, 2)}` : r;
1347
1597
  "api_key_report",
1348
1598
  "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.",
1349
1599
  {
1350
- unusedDays: import_zod5.z.number().int().min(1).max(3650).optional().describe("Unused for at least this many days (default 90)."),
1351
- expiringDays: import_zod5.z.number().int().min(1).max(3650).optional().describe("Expiring within this many days (default 14).")
1600
+ unusedDays: import_zod6.z.number().int().min(1).max(3650).optional().describe("Unused for at least this many days (default 90)."),
1601
+ expiringDays: import_zod6.z.number().int().min(1).max(3650).optional().describe("Expiring within this many days (default 14).")
1352
1602
  },
1353
1603
  (a) => client.keys.report({ ...a.unusedDays !== void 0 ? { unusedDays: a.unusedDays } : {}, ...a.expiringDays !== void 0 ? { expiringDays: a.expiringDays } : {} })
1354
1604
  );
1355
1605
  tool("get_usage", "Get the current usage/quota summary for your organization.", {}, () => client.usage());
1606
+ tool(
1607
+ "get_entitlements",
1608
+ "What your organization may use, from its plan: every feature (whiteLabel, tcf, sso, abTesting, \u2026) as {key, enabled} and every limit as limits.<name> with limit (null = unlimited) and used. Read-only.",
1609
+ {},
1610
+ () => client.entitlements()
1611
+ );
1356
1612
  tool("list_webhooks", "List webhook subscriptions for your organization.", {}, () => client.webhooks.list());
1357
1613
  tool(
1358
1614
  "create_webhook",
1359
1615
  "Create a webhook subscription. The response includes the signing secret (shown once).",
1360
1616
  {
1361
- url: import_zod5.z.string().describe("HTTPS endpoint to deliver events to."),
1362
- events: import_zod5.z.array(import_zod5.z.string()).describe("Event names to subscribe to, e.g. consent.created."),
1363
- cbid: import_zod5.z.string().optional().describe("Optional site cbid to scope the subscription to.")
1617
+ url: import_zod6.z.string().describe("HTTPS endpoint to deliver events to."),
1618
+ events: import_zod6.z.array(import_zod6.z.string()).describe("Event names to subscribe to, e.g. consent.created."),
1619
+ cbid: import_zod6.z.string().optional().describe("Optional site cbid to scope the subscription to.")
1364
1620
  },
1365
1621
  (a) => client.webhooks.create({
1366
1622
  url: a.url,
@@ -1371,13 +1627,13 @@ ${JSON.stringify(r, null, 2)}` : r;
1371
1627
  tool(
1372
1628
  "roll_webhook_secret",
1373
1629
  "Rotate a webhook subscription\u2019s signing secret. The new secret is returned once; the receiving endpoint must be updated to verify with it.",
1374
- { id: import_zod5.z.string() },
1630
+ { id: import_zod6.z.string() },
1375
1631
  (a) => client.webhooks.rollSecret(a.id)
1376
1632
  );
1377
1633
  tool(
1378
1634
  "test_webhook",
1379
1635
  "Send a signed test event to a webhook subscription now, and report what the endpoint answered.",
1380
- { id: import_zod5.z.string() },
1636
+ { id: import_zod6.z.string() },
1381
1637
  (a) => client.webhooks.test(a.id)
1382
1638
  );
1383
1639
  tool(
@@ -1389,40 +1645,48 @@ ${JSON.stringify(r, null, 2)}` : r;
1389
1645
  tool(
1390
1646
  "replay_webhook_dead_letter",
1391
1647
  "Deliver a dead-lettered webhook event again, to the subscription as it is now.",
1392
- { id: import_zod5.z.string() },
1648
+ { id: import_zod6.z.string() },
1393
1649
  (a) => client.webhooks.replayDeadLetter(a.id)
1394
1650
  );
1651
+ tool(
1652
+ "replay_webhook",
1653
+ "Send what a failing or disabled webhook endpoint missed: its held events since `since` (its failingSince), oldest first, one attempt each, stopping at the first failure. Re-enable the endpoint first (update_webhook active:true).",
1654
+ { id: import_zod6.z.string(), since: import_zod6.z.union([import_zod6.z.number(), import_zod6.z.string()]).describe("Epoch ms or ISO date."), limit: import_zod6.z.number().int().min(1).max(500).optional() },
1655
+ (a) => client.webhooks.replay(a.id, a.since, a.limit ? { limit: a.limit } : void 0)
1656
+ );
1395
1657
  tool(
1396
1658
  "update_webhook",
1397
- "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.",
1659
+ "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. active:true re-enables a disabled endpoint; the answer says how to replay what it missed. alertContacts: who is emailed when it fails (null: the org owners).",
1398
1660
  {
1399
- id: import_zod5.z.string(),
1400
- url: import_zod5.z.string().optional(),
1401
- events: import_zod5.z.array(import_zod5.z.string()).optional(),
1402
- cbid: import_zod5.z.string().nullable().optional(),
1403
- active: import_zod5.z.boolean().optional()
1661
+ id: import_zod6.z.string(),
1662
+ url: import_zod6.z.string().optional(),
1663
+ events: import_zod6.z.array(import_zod6.z.string()).optional(),
1664
+ cbid: import_zod6.z.string().nullable().optional(),
1665
+ active: import_zod6.z.boolean().optional(),
1666
+ alertContacts: import_zod6.z.array(import_zod6.z.string()).nullable().optional()
1404
1667
  },
1405
1668
  (a) => client.webhooks.update(a.id, {
1406
1669
  ...a.url !== void 0 ? { url: a.url } : {},
1407
1670
  ...a.events !== void 0 ? { events: a.events } : {},
1408
1671
  ...a.cbid !== void 0 ? { cbid: a.cbid } : {},
1409
- ...a.active !== void 0 ? { active: a.active } : {}
1672
+ ...a.active !== void 0 ? { active: a.active } : {},
1673
+ ...a.alertContacts !== void 0 ? { alertContacts: a.alertContacts } : {}
1410
1674
  })
1411
1675
  );
1412
- tool("delete_webhook", "Delete a webhook subscription by id.", { id: import_zod5.z.string().describe("The webhook subscription id.") }, async (a) => {
1676
+ tool("delete_webhook", "Delete a webhook subscription by id.", { id: import_zod6.z.string().describe("The webhook subscription id.") }, async (a) => {
1413
1677
  await client.webhooks.delete(a.id);
1414
1678
  return { ok: true };
1415
1679
  });
1416
1680
  tool(
1417
1681
  "verify_site",
1418
1682
  "Verify that your organization controls a domain by one of three challenge methods (dns / meta / file). Required to unlock consent export and signed receipts.",
1419
- { ...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).") },
1683
+ { ...cbid, method: import_zod6.z.enum(["dns", "meta", "file"]).describe("Challenge method: dns (TXT record), meta (HTML tag), or file (/.well-known/cookiemunch-verify.txt).") },
1420
1684
  (a) => client.sites.verify(a.cbid, a.method)
1421
1685
  );
1422
1686
  tool(
1423
1687
  "get_verification_challenge",
1424
1688
  "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.",
1425
- { cbid: import_zod5.z.string() },
1689
+ { cbid: import_zod6.z.string() },
1426
1690
  (a) => client.sites.verifyChallenge(a.cbid)
1427
1691
  );
1428
1692
  tool(
@@ -1431,18 +1695,35 @@ ${JSON.stringify(r, null, 2)}` : r;
1431
1695
  { ...cbid },
1432
1696
  (a) => client.sites.brand(a.cbid)
1433
1697
  );
1698
+ tool(
1699
+ "get_site_brand",
1700
+ "Read back the brand.json last imported for a site: each role (color.accent, font.body, logo.light, \u2026), the theme token it sets, whether the value in force is brand.json's or the site's own (the site wins), variants that override it, plus ignored[] and warnings[] (e.g. a third-party font host).",
1701
+ { cbid: import_zod6.z.string() },
1702
+ (a) => client.sites.getBrand(a.cbid)
1703
+ );
1704
+ tool(
1705
+ "import_site_brand",
1706
+ "Import a DTCG brand.json into a site's banner theme (the hosted rights page uses it too). Pass url (https, fetched once) or document (the brand.json object). Values the site set itself are kept: brand.json < site banner theme < per-banner variant. dryRun answers the read-back and saves nothing.",
1707
+ {
1708
+ cbid: import_zod6.z.string(),
1709
+ url: import_zod6.z.string().optional().describe("https URL of the brand.json. Give this or document."),
1710
+ document: import_zod6.z.record(import_zod6.z.unknown()).optional().describe("The brand.json object itself. Give this or url."),
1711
+ dryRun: import_zod6.z.boolean().optional()
1712
+ },
1713
+ (a) => client.sites.setBrand(a.cbid, typeof a.url === "string" ? { url: a.url } : a.document ?? {}, { dryRun: a.dryRun === true })
1714
+ );
1434
1715
  tool(
1435
1716
  "get_flow",
1436
1717
  "Get the v2 banner flow config for a site, including current views, categories, and any lint issues.",
1437
- { cbid: import_zod5.z.string().describe("Site identifier (cbid).") },
1718
+ { cbid: import_zod6.z.string().describe("Site identifier (cbid).") },
1438
1719
  (a) => client.sites.getFlow(a.cbid)
1439
1720
  );
1440
1721
  tool(
1441
1722
  "edit_flow",
1442
1723
  "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.",
1443
1724
  {
1444
- cbid: import_zod5.z.string().describe("Site identifier (cbid)."),
1445
- operations: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).describe(
1725
+ cbid: import_zod6.z.string().describe("Site identifier (cbid)."),
1726
+ operations: import_zod6.z.array(import_zod6.z.record(import_zod6.z.unknown())).describe(
1446
1727
  'Ordered list of ops. Each must have an "op" field: addView | removeView | addElement | setButtonTransition | addCustomCategory.'
1447
1728
  )
1448
1729
  },
@@ -1452,22 +1733,23 @@ ${JSON.stringify(r, null, 2)}` : r;
1452
1733
  "set_flow",
1453
1734
  "Wholesale replace a site's v2 banner flow with a complete config (e.g. from a template). Validated server-side before it is saved.",
1454
1735
  {
1455
- cbid: import_zod5.z.string().describe("Site identifier (cbid)."),
1456
- config: import_zod5.z.record(import_zod5.z.unknown()).describe("A full v2 FlowConfig object ({ v:2, flow, categories, ... }).")
1736
+ cbid: import_zod6.z.string().describe("Site identifier (cbid)."),
1737
+ config: import_zod6.z.record(import_zod6.z.unknown()).describe("A full v2 FlowConfig object ({ v:2, flow, categories, ... }).")
1457
1738
  },
1458
1739
  (a) => client.sites.setFlow(a.cbid, a.config)
1459
1740
  );
1460
1741
  registerConfigTools(tool, client);
1461
1742
  registerPlatformTools(tool, client);
1462
1743
  registerIntegrationTools(tool, client);
1744
+ registerKeyAndTagTools(tool, client);
1463
1745
  registerRightsTools(tool, client);
1464
1746
  registerRightsPageTools(tool, client);
1465
1747
  tool(
1466
1748
  "invite_member",
1467
1749
  "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.",
1468
1750
  {
1469
- email: import_zod5.z.string().describe("Email address of the person to invite."),
1470
- role: import_zod5.z.enum(["admin", "member", "viewer"]).describe("Role to assign: admin, member, or viewer. owner is not assignable via API key.")
1751
+ email: import_zod6.z.string().describe("Email address of the person to invite."),
1752
+ role: import_zod6.z.enum(["admin", "member", "viewer"]).describe("Role to assign: admin, member, or viewer. owner is not assignable via API key.")
1471
1753
  },
1472
1754
  (a) => client.members.invite(a.email, a.role)
1473
1755
  );
@@ -1475,8 +1757,8 @@ ${JSON.stringify(r, null, 2)}` : r;
1475
1757
  "set_member_role",
1476
1758
  "Change the role of a member in your organization. The org owner's role cannot be changed.",
1477
1759
  {
1478
- userId: import_zod5.z.string().describe("The userId of the member whose role to change."),
1479
- role: import_zod5.z.enum(["admin", "member", "viewer"]).describe("New role: admin, member, or viewer.")
1760
+ userId: import_zod6.z.string().describe("The userId of the member whose role to change."),
1761
+ role: import_zod6.z.enum(["admin", "member", "viewer"]).describe("New role: admin, member, or viewer.")
1480
1762
  },
1481
1763
  (a) => client.members.setRole(a.userId, a.role)
1482
1764
  );
@@ -1484,7 +1766,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1484
1766
  "remove_member",
1485
1767
  "Remove a member from your organization. The org owner cannot be removed.",
1486
1768
  {
1487
- userId: import_zod5.z.string().describe("The userId of the member to remove.")
1769
+ userId: import_zod6.z.string().describe("The userId of the member to remove.")
1488
1770
  },
1489
1771
  async (a) => {
1490
1772
  await client.members.remove(a.userId);
@@ -1495,11 +1777,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1495
1777
  "create_brand_kit",
1496
1778
  "Create a reusable brand kit (colors, logo, typography) for your organization's consent banners.",
1497
1779
  {
1498
- name: import_zod5.z.string().describe("Display name for the brand kit."),
1499
- theme: import_zod5.z.record(import_zod5.z.unknown()).describe("Theme tokens (colors, fonts, etc.) as a JSON object."),
1500
- content: import_zod5.z.record(import_zod5.z.unknown()).optional().describe("Optional banner copy overrides."),
1501
- logoUrl: import_zod5.z.string().optional().describe("Optional URL for your org logo."),
1502
- customCss: import_zod5.z.string().optional().describe("Optional custom CSS string to inject into the banner.")
1780
+ name: import_zod6.z.string().describe("Display name for the brand kit."),
1781
+ theme: import_zod6.z.record(import_zod6.z.unknown()).describe("Theme tokens (colors, fonts, etc.) as a JSON object."),
1782
+ content: import_zod6.z.record(import_zod6.z.unknown()).optional().describe("Optional banner copy overrides."),
1783
+ logoUrl: import_zod6.z.string().optional().describe("Optional URL for your org logo."),
1784
+ customCss: import_zod6.z.string().optional().describe("Optional custom CSS string to inject into the banner.")
1503
1785
  },
1504
1786
  (a) => client.brandKits.create({
1505
1787
  name: a.name,
@@ -1513,7 +1795,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1513
1795
  "delete_brand_kit",
1514
1796
  "Delete a brand kit by id. The kit must belong to your organization (cross-org deletes are rejected).",
1515
1797
  {
1516
- id: import_zod5.z.string().describe("The brand kit id to delete.")
1798
+ id: import_zod6.z.string().describe("The brand kit id to delete.")
1517
1799
  },
1518
1800
  async (a) => {
1519
1801
  await client.brandKits.delete(a.id);
@@ -1524,28 +1806,47 @@ ${JSON.stringify(r, null, 2)}` : r;
1524
1806
  "save_preference",
1525
1807
  "Save or update the consent preferences for an end-user (by subjectId) within your organization. purposes is a map of purpose-name \u2192 boolean.",
1526
1808
  {
1527
- subjectId: import_zod5.z.string().describe("The end-user identifier (e.g. email or internal user id)."),
1528
- purposes: import_zod5.z.record(import_zod5.z.boolean()).describe('Map of purpose names to consent values, e.g. { "newsletter": true, "analytics": false }.')
1809
+ subjectId: import_zod6.z.string().describe("The end-user identifier (e.g. email or internal user id)."),
1810
+ purposes: import_zod6.z.record(import_zod6.z.boolean()).describe('Map of purpose names to consent values, e.g. { "newsletter": true, "analytics": false }.')
1529
1811
  },
1530
1812
  (a) => client.preferences.save(a.subjectId, a.purposes)
1531
1813
  );
1532
1814
  tool(
1533
1815
  "get_preference",
1534
1816
  "One end-user\u2019s saved preferences, by subjectId. Read-only.",
1535
- { subjectId: import_zod5.z.string() },
1817
+ { subjectId: import_zod6.z.string() },
1536
1818
  (a) => client.preferences.get(a.subjectId)
1537
1819
  );
1820
+ tool(
1821
+ "mint_preference_center_token",
1822
+ "Mint a hosted preference-centre token for one visitor (POST /v1/preference-center/tokens), for a page to pass to CookieMunch.setSubjectToken. Give exactly one of email (resolved as the emailed preference link resolves it; an unknown address is subject_not_found) or subjectId. The token is a credential that opens that person\u2019s subscriptions and profile until expiresAt: never paste it into a shared URL, a ticket or a log, and keep ttlSeconds short (default 3600, max 86400). Needs subscriptions:write and profile:write, plus identity:read by email.",
1823
+ {
1824
+ cbid: import_zod6.z.string().describe("A site of your organisation."),
1825
+ email: import_zod6.z.string().optional().describe("The visitor\u2019s address. Give this or subjectId, not both."),
1826
+ subjectId: import_zod6.z.string().optional().describe("The subject id. Give this or email, not both."),
1827
+ ttlSeconds: import_zod6.z.number().int().min(1).max(86400).optional()
1828
+ },
1829
+ (a) => client.preferenceCenter.mintToken({
1830
+ cbid: a.cbid,
1831
+ ...a.email !== void 0 ? { email: a.email } : { subjectId: a.subjectId },
1832
+ ...a.ttlSeconds !== void 0 ? { ttlSeconds: a.ttlSeconds } : {}
1833
+ })
1834
+ );
1538
1835
  tool(
1539
1836
  "issue_api_key",
1540
- "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.",
1837
+ "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 (the answer warns about it). For a sub-task, vend_api_key mints a short-lived one instead.",
1541
1838
  {
1542
- name: import_zod5.z.string().optional(),
1543
- scopes: import_zod5.z.array(import_zod5.z.string()).optional(),
1544
- cbids: import_zod5.z.array(import_zod5.z.string()).min(1).optional(),
1545
- expiresInDays: import_zod5.z.number().int().min(1).max(3650).optional(),
1546
- expiresAt: import_zod5.z.string().optional().describe("Or the exact expiry, an ISO date-time (not with expiresInDays).")
1839
+ name: import_zod6.z.string().optional(),
1840
+ scopes: import_zod6.z.array(import_zod6.z.string()).optional(),
1841
+ cbids: import_zod6.z.array(import_zod6.z.string()).min(1).optional(),
1842
+ expiresInDays: import_zod6.z.number().int().min(1).max(3650).optional(),
1843
+ expiresAt: import_zod6.z.string().optional().describe("Or the exact expiry, an ISO date-time (not with expiresInDays)."),
1844
+ owner: import_zod6.z.string().optional().describe("Who it belongs to: user:<id>, service:<name> or apikey:<prefix>. Default this key."),
1845
+ strictUnknownFields: import_zod6.z.boolean().optional().describe("Writes with the new key refuse unknown body fields by default.")
1547
1846
  },
1548
1847
  (a) => client.keys.issue({
1848
+ ...a.owner ? { owner: a.owner } : {},
1849
+ ...a.strictUnknownFields !== void 0 ? { strictUnknownFields: a.strictUnknownFields } : {},
1549
1850
  ...a.expiresAt ? { expiresAt: a.expiresAt } : {},
1550
1851
  ...a.name ? { name: a.name } : {},
1551
1852
  ...a.scopes ? { scopes: a.scopes } : {},
@@ -1553,36 +1854,36 @@ ${JSON.stringify(r, null, 2)}` : r;
1553
1854
  ...a.expiresInDays !== void 0 ? { expiresInDays: a.expiresInDays } : {}
1554
1855
  })
1555
1856
  );
1556
- 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) => {
1857
+ tool("revoke_api_key", "Revoke an API key by its prefix. Takes effect immediately; anything using that key stops working.", { prefix: import_zod6.z.string() }, async (a) => {
1557
1858
  await client.keys.revoke(a.prefix);
1558
1859
  return { revoked: a.prefix };
1559
1860
  });
1560
1861
  tool(
1561
1862
  "import_cookie_declaration",
1562
1863
  "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.",
1563
- { cbid: import_zod5.z.string(), data: import_zod5.z.string().describe("The exported file, as text (CSV or JSON).") },
1864
+ { cbid: import_zod6.z.string(), data: import_zod6.z.string().describe("The exported file, as text (CSV or JSON).") },
1564
1865
  (a) => client.sites.importDeclaration(a.cbid, a.data)
1565
1866
  );
1566
1867
  tool(
1567
1868
  "apply_cookie_import",
1568
1869
  "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.",
1569
- { 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() },
1870
+ { cbid: import_zod6.z.string(), data: import_zod6.z.string().describe("The exported file, as text (CSV or JSON)."), overwrite: import_zod6.z.boolean().optional() },
1570
1871
  (a) => client.sites.applyImport(a.cbid, a.data, a.overwrite ? { overwrite: true } : void 0)
1571
1872
  );
1572
1873
  const declarationShape = {
1573
- category: import_zod5.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
1574
- purpose: import_zod5.z.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
1575
- 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.'),
1576
- provider: import_zod5.z.string().optional(),
1577
- expiry: import_zod5.z.string().optional().describe('e.g. "Session", "30 days", "1 year" (the banner localises these forms).'),
1578
- domain: import_zod5.z.string().optional(),
1579
- pattern: import_zod5.z.boolean().optional().describe("Treat the name as a prefix wildcard (a trailing * does the same).")
1874
+ category: import_zod6.z.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
1875
+ purpose: import_zod6.z.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
1876
+ purposes: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string().max(1e3)).nullable().optional().describe('The purpose in other languages, keyed by BCP-47 tag: {"es": "\u2026", "pt-BR": "\u2026"}. The banner, data-cc="declaration" and cookie-declaration.js draw the visitor\u2019s language. null clears.'),
1877
+ provider: import_zod6.z.string().optional(),
1878
+ expiry: import_zod6.z.string().optional().describe('e.g. "Session", "30 days", "1 year" (the banner localises these forms).'),
1879
+ domain: import_zod6.z.string().optional(),
1880
+ pattern: import_zod6.z.boolean().optional().describe("Treat the name as a prefix wildcard (a trailing * does the same).")
1580
1881
  };
1581
- 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.");
1882
+ const dryRunArg = import_zod6.z.boolean().optional().describe("Store nothing: answer with the would-be declarations and a diff (added / removed / changed) to check first.");
1582
1883
  tool(
1583
1884
  "declare_cookie",
1584
1885
  '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.',
1585
- { cbid: import_zod5.z.string(), name: import_zod5.z.string(), ...declarationShape, dryRun: dryRunArg },
1886
+ { cbid: import_zod6.z.string(), name: import_zod6.z.string(), ...declarationShape, dryRun: dryRunArg },
1586
1887
  (a) => {
1587
1888
  const { cbid: cbid2, name, dryRun, ...rest } = a;
1588
1889
  return client.sites.declareCookie(cbid2, name, rest, dryRun ? { dryRun: true } : void 0);
@@ -1591,7 +1892,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1591
1892
  tool(
1592
1893
  "declare_cookies",
1593
1894
  "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.",
1594
- { 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 },
1895
+ { cbid: import_zod6.z.string(), cookies: import_zod6.z.array(import_zod6.z.object({ name: import_zod6.z.string(), ...declarationShape })).max(500), replace: import_zod6.z.boolean().optional(), dryRun: dryRunArg },
1595
1896
  (a) => {
1596
1897
  const o = { ...a.replace ? { replace: true } : {}, ...a.dryRun ? { dryRun: true } : {} };
1597
1898
  return client.sites.declareCookies(a.cbid, a.cookies, Object.keys(o).length ? o : void 0);
@@ -1600,7 +1901,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1600
1901
  tool(
1601
1902
  "undeclare_cookie",
1602
1903
  "Remove a cookie declaration; the scanned/observed classification applies again.",
1603
- { cbid: import_zod5.z.string(), name: import_zod5.z.string(), dryRun: dryRunArg },
1904
+ { cbid: import_zod6.z.string(), name: import_zod6.z.string(), dryRun: dryRunArg },
1604
1905
  async (a) => {
1605
1906
  if (a.dryRun) return client.sites.undeclareCookie(a.cbid, a.name, { dryRun: true });
1606
1907
  await client.sites.undeclareCookie(a.cbid, a.name);
@@ -1611,11 +1912,11 @@ ${JSON.stringify(r, null, 2)}` : r;
1611
1912
  "retire_cookie",
1612
1913
  '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.',
1613
1914
  {
1614
- cbid: import_zod5.z.string(),
1615
- name: import_zod5.z.string(),
1616
- renamedTo: import_zod5.z.string().max(256).optional().describe("The cookie\u2019s new name, if it was renamed."),
1617
- note: import_zod5.z.string().max(1e3).optional(),
1618
- dryRun: import_zod5.z.boolean().optional().describe("Store nothing: answer with the would-be retirement and list to check first.")
1915
+ cbid: import_zod6.z.string(),
1916
+ name: import_zod6.z.string(),
1917
+ renamedTo: import_zod6.z.string().max(256).optional().describe("The cookie\u2019s new name, if it was renamed."),
1918
+ note: import_zod6.z.string().max(1e3).optional(),
1919
+ dryRun: import_zod6.z.boolean().optional().describe("Store nothing: answer with the would-be retirement and list to check first.")
1619
1920
  },
1620
1921
  (a) => {
1621
1922
  const input = { ...a.renamedTo ? { renamedTo: a.renamedTo } : {}, ...a.note ? { note: a.note } : {} };
@@ -1625,7 +1926,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1625
1926
  tool(
1626
1927
  "unretire_cookie",
1627
1928
  "Un-retire a cookie: it is listed again everywhere.",
1628
- { 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.") },
1929
+ { cbid: import_zod6.z.string(), name: import_zod6.z.string(), dryRun: import_zod6.z.boolean().optional().describe("Store nothing: answer with what the list would be.") },
1629
1930
  async (a) => {
1630
1931
  if (a.dryRun) return client.sites.unretireCookie(a.cbid, a.name, { dryRun: true });
1631
1932
  await client.sites.unretireCookie(a.cbid, a.name);
@@ -1634,41 +1935,74 @@ ${JSON.stringify(r, null, 2)}` : r;
1634
1935
  );
1635
1936
  tool(
1636
1937
  "list_cookie_presets",
1637
- "Declaration presets for the platforms a site is built on (atlas, forumulate, chatly, cookiemunch, referally): each one\u2019s parameters, what it has declared on this site, and whether the vendor\u2019s live manifest can be imported yet. Read-only.",
1638
- { cbid: import_zod5.z.string() },
1938
+ "Declaration presets for the platforms a site is built on (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter, partnerstack, tapfiliate, impact): each one\u2019s parameters, what it has declared on this site, and whether the vendor\u2019s live manifest can be imported yet. Read-only.",
1939
+ { cbid: import_zod6.z.string() },
1639
1940
  (a) => client.sites.cookiePresets(a.cbid)
1640
1941
  );
1641
1942
  tool(
1642
1943
  "apply_cookie_preset",
1643
- "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.",
1944
+ "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. A row filed under a disabled category comes back in warnings with a suggestedConfigPatch.",
1644
1945
  {
1645
- cbid: import_zod5.z.string(),
1646
- vendor: import_zod5.z.enum(["atlas", "forumulate", "chatly", "cookiemunch", "referally"]),
1647
- frontendApiHost: import_zod5.z.string().optional().describe("Atlas: your frontend API host, e.g. auth.example.com."),
1648
- crossSubdomainCookies: import_zod5.z.boolean().optional().describe("Atlas: default true \u2014 the cookies live on the parent domain."),
1649
- publicId: import_zod5.z.string().optional().describe("Chatly: the channel public id (ch_web_\u2026)."),
1650
- dragging: import_zod5.z.boolean().optional().describe("Chatly: the launcher can be dragged (adds the drag-position key)."),
1651
- category: import_zod5.z.string().optional().describe("Chatly: the category for its keys (default necessary). Referally: default the site's referrals category, else marketing."),
1652
- cookieDomain: import_zod5.z.string().optional().describe("Referally: the domain aff.js sets referally_ctx on, e.g. .example.com. Default the site domain."),
1653
- cookieDays: import_zod5.z.number().int().min(1).max(400).optional().describe("Referally: how long the cookie lives, 1 to 400 days. Default 60."),
1946
+ cbid: import_zod6.z.string(),
1947
+ vendor: import_zod6.z.enum(["atlas", "forumulate", "chatly", "cookiemunch", "referalli", "firstpromoter", "partnerstack", "tapfiliate", "impact", "referally"]).describe("referally is the deprecated old name of referalli."),
1948
+ frontendApiHost: import_zod6.z.string().optional().describe("Atlas: your frontend API host, e.g. auth.example.com."),
1949
+ crossSubdomainCookies: import_zod6.z.boolean().optional().describe("Atlas: default true \u2014 the cookies live on the parent domain."),
1950
+ publicId: import_zod6.z.string().optional().describe("Chatly: the channel public id (ch_web_\u2026)."),
1951
+ dragging: import_zod6.z.boolean().optional().describe("Chatly: the launcher can be dragged (adds the drag-position key)."),
1952
+ category: import_zod6.z.string().optional().describe("Chatly: the category for its keys (default necessary). Referral and affiliate presets: default the site's referrals category, else marketing."),
1953
+ cookieDomain: import_zod6.z.string().optional().describe("Referral and affiliate presets: the domain their script sets its cookies on, e.g. .example.com. Default the site domain."),
1954
+ cookieDays: import_zod6.z.number().int().min(1).max(400).optional().describe("Referral and affiliate presets: your program's cookie window, 1 to 400 days."),
1955
+ legacyName: import_zod6.z.boolean().optional().describe("referalli: default true, also declare referally_ctx (the pre-rename copy aff.js still writes)."),
1956
+ campaignId: import_zod6.z.string().optional().describe("impact: your program id; declares IR_<campaignId> too."),
1654
1957
  dryRun: dryRunArg
1655
1958
  },
1656
1959
  (a) => {
1657
1960
  const params = {};
1658
- for (const k of ["frontendApiHost", "crossSubdomainCookies", "publicId", "dragging", "category", "cookieDomain", "cookieDays"]) if (a[k] !== void 0) params[k] = a[k];
1961
+ for (const k of ["frontendApiHost", "crossSubdomainCookies", "publicId", "dragging", "category", "cookieDomain", "cookieDays", "legacyName", "campaignId"]) if (a[k] !== void 0) params[k] = a[k];
1659
1962
  return client.sites.applyCookiePreset(a.cbid, a.vendor, params, a.dryRun ? { dryRun: true } : void 0);
1660
1963
  }
1661
1964
  );
1965
+ tool(
1966
+ "import_cookie_manifest",
1967
+ 'Declare ANY vendor\u2019s cookies and browser storage from its embed manifest (/.well-known/forgedeck-embed.json): give its https URL (re-read hourly afterwards) or the manifest document. The vendor id is the manifest\u2019s product; rows are marked source "manifest". An invalid manifest is refused with each broken rule named. Use dryRun first; remove it with remove_cookie_preset and the product id.',
1968
+ {
1969
+ cbid: import_zod6.z.string(),
1970
+ url: import_zod6.z.string().optional().describe("An https:// embed manifest URL."),
1971
+ manifest: import_zod6.z.record(import_zod6.z.unknown()).optional().describe("The manifest document itself, instead of a URL."),
1972
+ params: import_zod6.z.record(import_zod6.z.string()).optional().describe('Values for the manifest\u2019s {placeholders}, e.g. {"publicId": "ch_web_1"}.'),
1973
+ dryRun: dryRunArg
1974
+ },
1975
+ (a) => {
1976
+ const input = a.url !== void 0 ? { url: a.url } : { manifest: a.manifest };
1977
+ return client.sites.importCookieManifest(a.cbid, { ...input, ...a.params ? { params: a.params } : {} }, a.dryRun ? { dryRun: true } : void 0);
1978
+ }
1979
+ );
1980
+ tool(
1981
+ "list_cookie_suggestions",
1982
+ "What a site should declare: the vendors its crawls and visits show (by script URL, storage name or embed manifest), the preset for each, and one suggestion per undeclared cookie or storage key with a suggested category, confidence, and whether a crawl saw it before consent (consentStates). Read-only.",
1983
+ { cbid: import_zod6.z.string() },
1984
+ (a) => client.sites.cookieSuggestions(a.cbid)
1985
+ );
1986
+ tool(
1987
+ "declare_cookie_suggestions",
1988
+ "Declare a site\u2019s suggestions in one call: applies detected vendors\u2019 presets that need no parameters and declares every other suggestion that has a purpose. Run with dryRun first to see the diff. names limits it to those suggestions; presets: false declares rows one by one instead.",
1989
+ { cbid: import_zod6.z.string(), names: import_zod6.z.array(import_zod6.z.string()).optional(), presets: import_zod6.z.boolean().optional(), dryRun: dryRunArg },
1990
+ (a) => client.sites.declareCookieSuggestions(
1991
+ a.cbid,
1992
+ { ...a.names ? { names: a.names } : {}, ...a.presets !== void 0 ? { presets: a.presets } : {} },
1993
+ a.dryRun ? { dryRun: true } : void 0
1994
+ )
1995
+ );
1662
1996
  tool(
1663
1997
  "remove_cookie_preset",
1664
- "Remove every declaration a vendor preset made on this site.",
1665
- { cbid: import_zod5.z.string(), vendor: import_zod5.z.enum(["atlas", "forumulate", "chatly", "cookiemunch", "referally"]), dryRun: dryRunArg },
1998
+ "Remove every declaration a vendor preset made on this site: a first-class preset, or a custom one (import_cookie_manifest) by its product id.",
1999
+ { cbid: import_zod6.z.string(), vendor: import_zod6.z.string().describe("atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter, partnerstack, tapfiliate, impact (referally is an alias of referalli), or a custom preset's product id."), dryRun: dryRunArg },
1666
2000
  (a) => client.sites.removeCookiePreset(a.cbid, a.vendor, a.dryRun ? { dryRun: true } : void 0)
1667
2001
  );
1668
2002
  tool(
1669
2003
  "delete_observed_cookie",
1670
2004
  "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.",
1671
- { cbid: import_zod5.z.string(), name: import_zod5.z.string(), dryRun: dryRunArg },
2005
+ { cbid: import_zod6.z.string(), name: import_zod6.z.string(), dryRun: dryRunArg },
1672
2006
  async (a) => {
1673
2007
  if (a.dryRun) return client.sites.deleteObservedCookie(a.cbid, a.name, { dryRun: true });
1674
2008
  await client.sites.deleteObservedCookie(a.cbid, a.name);
@@ -1679,9 +2013,9 @@ ${JSON.stringify(r, null, 2)}` : r;
1679
2013
  "purge_observed_cookies",
1680
2014
  "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.",
1681
2015
  {
1682
- cbid: import_zod5.z.string(),
1683
- since: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number()]).describe("ISO-8601 time or epoch milliseconds."),
1684
- until: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number()]).optional().describe("Optional end of the window (exclusive)."),
2016
+ cbid: import_zod6.z.string(),
2017
+ since: import_zod6.z.union([import_zod6.z.string(), import_zod6.z.number()]).describe("ISO-8601 time or epoch milliseconds."),
2018
+ until: import_zod6.z.union([import_zod6.z.string(), import_zod6.z.number()]).optional().describe("Optional end of the window (exclusive)."),
1685
2019
  dryRun: dryRunArg
1686
2020
  },
1687
2021
  (a) => client.sites.purgeObservedCookies(
@@ -1693,24 +2027,24 @@ ${JSON.stringify(r, null, 2)}` : r;
1693
2027
  tool(
1694
2028
  "get_blocked_pages",
1695
2029
  "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.",
1696
- { cbid: import_zod5.z.string() },
2030
+ { cbid: import_zod6.z.string() },
1697
2031
  (a) => client.sites.blocked(a.cbid)
1698
2032
  );
1699
2033
  tool(
1700
2034
  "roll_api_key",
1701
2035
  "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.",
1702
- { prefix: import_zod5.z.string() },
2036
+ { prefix: import_zod6.z.string() },
1703
2037
  (a) => client.keys.roll(a.prefix)
1704
2038
  );
1705
2039
  tool(
1706
2040
  "update_api_key",
1707
2041
  "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.",
1708
2042
  {
1709
- prefix: import_zod5.z.string(),
1710
- name: import_zod5.z.string().optional(),
1711
- scopes: import_zod5.z.array(import_zod5.z.string()).optional(),
1712
- cbids: import_zod5.z.array(import_zod5.z.string()).min(1).optional(),
1713
- expiresAt: import_zod5.z.string().nullable().optional().describe("A new expiry (ISO date-time), or null to remove it.")
2043
+ prefix: import_zod6.z.string(),
2044
+ name: import_zod6.z.string().optional(),
2045
+ scopes: import_zod6.z.array(import_zod6.z.string()).optional(),
2046
+ cbids: import_zod6.z.array(import_zod6.z.string()).min(1).optional(),
2047
+ expiresAt: import_zod6.z.string().nullable().optional().describe("A new expiry (ISO date-time), or null to remove it.")
1714
2048
  },
1715
2049
  (a) => client.keys.update(a.prefix, {
1716
2050
  ...a.expiresAt !== void 0 ? { expiresAt: a.expiresAt } : {},
@@ -1723,7 +2057,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1723
2057
  tool(
1724
2058
  "update_org",
1725
2059
  "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.",
1726
- { name: import_zod5.z.string().min(1).optional(), logoUrl: import_zod5.z.string().nullable().optional() },
2060
+ { name: import_zod6.z.string().min(1).optional(), logoUrl: import_zod6.z.string().nullable().optional() },
1727
2061
  (a) => client.org.update({
1728
2062
  ...a.name !== void 0 ? { name: a.name } : {},
1729
2063
  ...a.logoUrl !== void 0 ? { logoUrl: a.logoUrl } : {}
@@ -1739,20 +2073,20 @@ ${JSON.stringify(r, null, 2)}` : r;
1739
2073
  "set_mail_provider",
1740
2074
  "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).",
1741
2075
  {
1742
- provider: import_zod5.z.enum(["brevo", "sendgrid", "postmark", "resend", "ses", "smtp"]),
1743
- fromEmail: import_zod5.z.string().describe("An address on a domain your provider has verified."),
1744
- fromName: import_zod5.z.string().max(100).nullable().optional(),
1745
- replyTo: import_zod5.z.string().nullable().optional(),
1746
- secret: import_zod5.z.string().optional().describe("API key (Brevo, SendGrid, Resend), server token (Postmark), secret access key (SES) or SMTP password. Write-only."),
1747
- ses: import_zod5.z.object({ region: import_zod5.z.string(), accessKeyId: import_zod5.z.string() }).optional().describe("Required for ses."),
1748
- 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.")
2076
+ provider: import_zod6.z.enum(["brevo", "sendgrid", "postmark", "resend", "ses", "smtp"]),
2077
+ fromEmail: import_zod6.z.string().describe("An address on a domain your provider has verified."),
2078
+ fromName: import_zod6.z.string().max(100).nullable().optional(),
2079
+ replyTo: import_zod6.z.string().nullable().optional(),
2080
+ secret: import_zod6.z.string().optional().describe("API key (Brevo, SendGrid, Resend), server token (Postmark), secret access key (SES) or SMTP password. Write-only."),
2081
+ ses: import_zod6.z.object({ region: import_zod6.z.string(), accessKeyId: import_zod6.z.string() }).optional().describe("Required for ses."),
2082
+ smtp: import_zod6.z.object({ host: import_zod6.z.string(), port: import_zod6.z.union([import_zod6.z.literal(25), import_zod6.z.literal(465), import_zod6.z.literal(587), import_zod6.z.literal(2525)]), security: import_zod6.z.enum(["tls", "starttls"]), username: import_zod6.z.string() }).optional().describe("Required for smtp. TLS is always required.")
1749
2083
  },
1750
2084
  (a) => client.org.mailProvider.set(a)
1751
2085
  );
1752
2086
  tool(
1753
2087
  "test_mail_provider",
1754
2088
  "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.",
1755
- { to: import_zod5.z.string().optional().describe("Recipient. Default: the reply-to, else the from address.") },
2089
+ { to: import_zod6.z.string().optional().describe("Recipient. Default: the reply-to, else the from address.") },
1756
2090
  (a) => client.org.mailProvider.test(a.to)
1757
2091
  );
1758
2092
  tool(
@@ -1764,13 +2098,44 @@ ${JSON.stringify(r, null, 2)}` : r;
1764
2098
  return { removed: true };
1765
2099
  }
1766
2100
  );
2101
+ tool(
2102
+ "get_org_controller",
2103
+ "The organisation\u2019s own data-controller identity: who every rights notice names, before any site config controller block. `set: false` when there is none. Read-only.",
2104
+ {},
2105
+ () => client.org.controller.get()
2106
+ );
2107
+ tool(
2108
+ "set_org_controller",
2109
+ "Set the organisation\u2019s data-controller identity. Replaces it: a field left out is removed. Needed for a notice on a rights request filed without a cbid when the organisation has several sites. Needs an unscoped key or rights:write. Audited.",
2110
+ {
2111
+ legalName: import_zod6.z.string().describe("Required: the legal name of the data controller."),
2112
+ contactEmail: import_zod6.z.string().optional().describe("Where people reach the controller about their data."),
2113
+ address: import_zod6.z.string().optional(),
2114
+ dpoContact: import_zod6.z.string().optional().describe("The Data Protection Officer: a name, an email address, or both.")
2115
+ },
2116
+ (a) => client.org.controller.set({
2117
+ legalName: a.legalName,
2118
+ ...a.contactEmail !== void 0 ? { contactEmail: a.contactEmail } : {},
2119
+ ...a.address !== void 0 ? { address: a.address } : {},
2120
+ ...a.dpoContact !== void 0 ? { dpoContact: a.dpoContact } : {}
2121
+ })
2122
+ );
2123
+ tool(
2124
+ "remove_org_controller",
2125
+ "Remove the organisation\u2019s data-controller identity. Notices then name the request\u2019s site config controller block; a request without a cbid in an organisation with several sites gets no notice.",
2126
+ {},
2127
+ async () => {
2128
+ await client.org.controller.remove();
2129
+ return { removed: true };
2130
+ }
2131
+ );
1767
2132
  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.";
1768
2133
  const captchaInput = {
1769
- mode: import_zod5.z.enum(["own", "off"]).describe(`own: your own captcha provider keys (recommended). off: no captcha. ${CAPTCHA_OFF}`),
1770
- provider: import_zod5.z.enum(["turnstile", "hcaptcha", "recaptcha_v2", "recaptcha_v3"]).optional().describe("Required for own."),
1771
- siteKey: import_zod5.z.string().optional().describe("Required for own: the public site key. List your rights-page hostnames on it at the provider."),
1772
- secret: import_zod5.z.string().optional().describe("The provider secret key. Write-only; never returned. Omit to keep the stored one (same provider)."),
1773
- minScore: import_zod5.z.number().min(0.1).max(0.9).optional().describe("reCAPTCHA v3 only. Default 0.5.")
2134
+ mode: import_zod6.z.enum(["own", "off"]).describe(`own: your own captcha provider keys (recommended). off: no captcha. ${CAPTCHA_OFF}`),
2135
+ provider: import_zod6.z.enum(["turnstile", "hcaptcha", "recaptcha_v2", "recaptcha_v3"]).optional().describe("Required for own."),
2136
+ siteKey: import_zod6.z.string().optional().describe("Required for own: the public site key. List your rights-page hostnames on it at the provider."),
2137
+ secret: import_zod6.z.string().optional().describe("The provider secret key. Write-only; never returned. Omit to keep the stored one (same provider)."),
2138
+ minScore: import_zod6.z.number().min(0.1).max(0.9).optional().describe("reCAPTCHA v3 only. Default 0.5.")
1774
2139
  };
1775
2140
  const captchaBody = (a) => ({
1776
2141
  mode: a.mode,
@@ -1779,22 +2144,40 @@ ${JSON.stringify(r, null, 2)}` : r;
1779
2144
  ...a.secret !== void 0 ? { secret: a.secret } : {},
1780
2145
  ...a.minScore !== void 0 ? { minScore: a.minScore } : {}
1781
2146
  });
2147
+ tool(
2148
+ "get_consent_sync_secret",
2149
+ "Whether hosted consent sync is set up for a site: `configured`, `secretLast4`, `createdAt`. Never returns the secret. Read-only.",
2150
+ { cbid: import_zod6.z.string() },
2151
+ (a) => client.consentSyncSecret.get(a.cbid)
2152
+ );
2153
+ tool(
2154
+ "rotate_consent_sync_secret",
2155
+ "Mint a site\u2019s consent-sync signing secret, or rotate it. The answer carries `secret` this once; the site owner\u2019s server signs consent-sync tokens with it (mintConsentSyncToken in @cookiemunch/sdk). Rotating stops the old secret at once, so every page holding a token signed with it stops syncing until it gets a new token. Never put the secret in a page. Needs sites:write and consent:write.",
2156
+ { cbid: import_zod6.z.string() },
2157
+ (a) => client.consentSyncSecret.rotate(a.cbid)
2158
+ );
2159
+ tool(
2160
+ "remove_consent_sync_secret",
2161
+ "Remove a site\u2019s consent-sync secret: hosted consent sync stops until a new one is minted. Needs sites:write and consent:write.",
2162
+ { cbid: import_zod6.z.string() },
2163
+ (a) => client.consentSyncSecret.remove(a.cbid)
2164
+ );
1782
2165
  tool(
1783
2166
  "get_rights_captcha",
1784
2167
  "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.",
1785
- { cbid: import_zod5.z.string() },
2168
+ { cbid: import_zod6.z.string() },
1786
2169
  (a) => client.rightsCaptcha.get(a.cbid)
1787
2170
  );
1788
2171
  tool(
1789
2172
  "set_rights_captcha",
1790
2173
  `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.`,
1791
- { cbid: import_zod5.z.string(), ...captchaInput },
2174
+ { cbid: import_zod6.z.string(), ...captchaInput },
1792
2175
  (a) => client.rightsCaptcha.set(a.cbid, captchaBody(a))
1793
2176
  );
1794
2177
  tool(
1795
2178
  "remove_rights_captcha",
1796
2179
  "Remove a site\u2019s own captcha setting: it inherits the organisation default again (or off). Returns the setting now in force.",
1797
- { cbid: import_zod5.z.string() },
2180
+ { cbid: import_zod6.z.string() },
1798
2181
  (a) => client.rightsCaptcha.remove(a.cbid)
1799
2182
  );
1800
2183
  tool(
@@ -1817,15 +2200,15 @@ ${JSON.stringify(r, null, 2)}` : r;
1817
2200
  );
1818
2201
  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.";
1819
2202
  const identityInput = {
1820
- 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)."),
1821
- issuer: import_zod5.z.string().describe("https URL exactly as in the token\u2019s iss (Clerk: your Frontend API URL)."),
1822
- jwksUrl: import_zod5.z.string().optional().describe("Required for oidc_jwt; clerk/atlas default to <issuer>/.well-known/jwks.json."),
1823
- 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)."),
1824
- 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."),
1825
- emailClaim: import_zod5.z.string().optional().describe("Default email."),
1826
- emailVerifiedClaim: import_zod5.z.string().optional().describe("Default email_verified; must be exactly true."),
1827
- sessionCookieName: import_zod5.z.string().optional().describe("Default __session: the cookie the hosted page on your custom domain reads."),
1828
- 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.")
2203
+ type: import_zod6.z.enum(["clerk", "atlas", "oidc_jwt"]).describe("clerk, atlas (Clerk-shaped), or oidc_jwt (any issuer that signs session JWTs with a published JWKS)."),
2204
+ issuer: import_zod6.z.string().describe("https URL exactly as in the token\u2019s iss (Clerk: your Frontend API URL)."),
2205
+ jwksUrl: import_zod6.z.string().optional().describe("Required for oidc_jwt; clerk/atlas default to <issuer>/.well-known/jwks.json."),
2206
+ audience: import_zod6.z.string().optional().describe("Expected aud. For oidc_jwt an audience or authorizedParties is required (a shared issuer mints tokens for every app)."),
2207
+ authorizedParties: import_zod6.z.array(import_zod6.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."),
2208
+ emailClaim: import_zod6.z.string().optional().describe("Default email."),
2209
+ emailVerifiedClaim: import_zod6.z.string().optional().describe("Default email_verified; must be exactly true."),
2210
+ sessionCookieName: import_zod6.z.string().optional().describe("Default __session: the cookie the hosted page on your custom domain reads."),
2211
+ trustEmailClaim: import_zod6.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.")
1829
2212
  };
1830
2213
  const identityBody = (a) => {
1831
2214
  const out = { type: a.type, issuer: a.issuer };
@@ -1835,19 +2218,19 @@ ${JSON.stringify(r, null, 2)}` : r;
1835
2218
  tool(
1836
2219
  "get_rights_identity",
1837
2220
  "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.",
1838
- { cbid: import_zod5.z.string() },
2221
+ { cbid: import_zod6.z.string() },
1839
2222
  (a) => client.rightsIdentity.get(a.cbid)
1840
2223
  );
1841
2224
  tool(
1842
2225
  "set_rights_identity",
1843
2226
  `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.`,
1844
- { cbid: import_zod5.z.string(), ...identityInput },
2227
+ { cbid: import_zod6.z.string(), ...identityInput },
1845
2228
  (a) => client.rightsIdentity.set(a.cbid, identityBody(a))
1846
2229
  );
1847
2230
  tool(
1848
2231
  "remove_rights_identity",
1849
2232
  "Remove a site\u2019s own sign-in provider: it inherits the organisation default again (or none). Returns the setting now in force.",
1850
- { cbid: import_zod5.z.string() },
2233
+ { cbid: import_zod6.z.string() },
1851
2234
  (a) => client.rightsIdentity.remove(a.cbid)
1852
2235
  );
1853
2236
  tool(
@@ -1871,22 +2254,40 @@ ${JSON.stringify(r, null, 2)}` : r;
1871
2254
  tool(
1872
2255
  "get_audit_log",
1873
2256
  "The organisation\u2019s audit log, newest first: administrative changes made in the dashboard or through the API, and who made them. Read-only.",
1874
- { limit: import_zod5.z.number().int().min(1).max(500).optional() },
1875
- (a) => client.audit(a.limit)
2257
+ { limit: import_zod6.z.number().int().min(1).max(500).optional(), actor: import_zod6.z.string().optional().describe('"self" for this key\u2019s own rows (allowed for scoped keys), or one actor id.') },
2258
+ (a) => client.audit(a.limit, a.actor ? { actor: a.actor } : void 0)
2259
+ );
2260
+ tool(
2261
+ "get_audit_sink",
2262
+ "Where the organisation\u2019s audit log is streamed (as CloudEvents) and how the last delivery went. Never the secret. Read-only.",
2263
+ {},
2264
+ () => client.auditSink.get()
2265
+ );
2266
+ tool(
2267
+ "set_audit_sink",
2268
+ "Stream the organisation\u2019s audit log to an HTTPS endpoint as CloudEvents 1.0, signed like webhooks. Replaces any sink. A generated secret is returned once. Audited.",
2269
+ { type: import_zod6.z.literal("webhook"), url: import_zod6.z.string(), secret: import_zod6.z.string().optional().describe("16\u2013256 characters; omitted: one is generated.") },
2270
+ (a) => client.auditSink.set({ type: "webhook", url: a.url, ...a.secret ? { secret: a.secret } : {} })
2271
+ );
2272
+ tool(
2273
+ "remove_audit_sink",
2274
+ "Stop streaming the audit log. Audited.",
2275
+ {},
2276
+ () => client.auditSink.remove()
1876
2277
  );
1877
2278
  tool(
1878
2279
  "upload_asset",
1879
2280
  "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.",
1880
2281
  {
1881
- data: import_zod5.z.string(),
1882
- contentType: import_zod5.z.enum(["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"])
2282
+ data: import_zod6.z.string(),
2283
+ contentType: import_zod6.z.enum(["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"])
1883
2284
  },
1884
2285
  (a) => client.assets.upload({ data: a.data, contentType: a.contentType })
1885
2286
  );
1886
2287
  tool(
1887
2288
  "delete_asset",
1888
2289
  "Delete a stored image by its URL (or file name). Only your own organisation\u2019s images can be named.",
1889
- { url: import_zod5.z.string().describe("The URL upload_asset returned, or just its file name.") },
2290
+ { url: import_zod6.z.string().describe("The URL upload_asset returned, or just its file name.") },
1890
2291
  async (a) => {
1891
2292
  await client.assets.delete(a.url);
1892
2293
  return { deleted: a.url };
@@ -1901,18 +2302,18 @@ ${JSON.stringify(r, null, 2)}` : r;
1901
2302
  tool(
1902
2303
  "get_customer",
1903
2304
  "One child org: its controller details and usage. Read-only.",
1904
- { id: import_zod5.z.string() },
2305
+ { id: import_zod6.z.string() },
1905
2306
  (a) => client.reseller.get(a.id)
1906
2307
  );
1907
2308
  tool(
1908
2309
  "provision_customer",
1909
2310
  "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.",
1910
2311
  {
1911
- name: import_zod5.z.string(),
1912
- ownerEmail: import_zod5.z.string().optional(),
1913
- delegatedAccess: import_zod5.z.boolean().optional().describe("Whether this reseller may act inside the child."),
1914
- mintKey: import_zod5.z.boolean().optional(),
1915
- keyScopes: import_zod5.z.array(import_zod5.z.string()).optional()
2312
+ name: import_zod6.z.string(),
2313
+ ownerEmail: import_zod6.z.string().optional(),
2314
+ delegatedAccess: import_zod6.z.boolean().optional().describe("Whether this reseller may act inside the child."),
2315
+ mintKey: import_zod6.z.boolean().optional(),
2316
+ keyScopes: import_zod6.z.array(import_zod6.z.string()).optional()
1916
2317
  },
1917
2318
  (a) => client.reseller.create({
1918
2319
  name: a.name,
@@ -1926,10 +2327,10 @@ ${JSON.stringify(r, null, 2)}` : r;
1926
2327
  "update_customer",
1927
2328
  "Change a child org\u2019s status, delegated access or DSAR routing. `dsarRouting: null` clears the override.",
1928
2329
  {
1929
- id: import_zod5.z.string(),
1930
- status: import_zod5.z.enum(["active", "suspended"]).optional(),
1931
- delegatedAccess: import_zod5.z.boolean().optional(),
1932
- dsarRouting: import_zod5.z.enum(["reseller", "child"]).nullable().optional()
2330
+ id: import_zod6.z.string(),
2331
+ status: import_zod6.z.enum(["active", "suspended"]).optional(),
2332
+ delegatedAccess: import_zod6.z.boolean().optional(),
2333
+ dsarRouting: import_zod6.z.enum(["reseller", "child"]).nullable().optional()
1933
2334
  },
1934
2335
  (a) => client.reseller.update(a.id, {
1935
2336
  ...a.status ? { status: a.status } : {},
@@ -1940,7 +2341,7 @@ ${JSON.stringify(r, null, 2)}` : r;
1940
2341
  tool(
1941
2342
  "suspend_customer",
1942
2343
  "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.)",
1943
- { id: import_zod5.z.string() },
2344
+ { id: import_zod6.z.string() },
1944
2345
  async (a) => {
1945
2346
  await client.reseller.deprovision(a.id);
1946
2347
  return { suspended: a.id };
@@ -1949,78 +2350,78 @@ ${JSON.stringify(r, null, 2)}` : r;
1949
2350
  tool(
1950
2351
  "list_customer_keys",
1951
2352
  "A child org's API key prefixes. Never the secrets. Read-only.",
1952
- { id: import_zod5.z.string() },
2353
+ { id: import_zod6.z.string() },
1953
2354
  (a) => client.reseller.listKeys(a.id)
1954
2355
  );
1955
2356
  tool(
1956
2357
  "issue_customer_key",
1957
2358
  "Mint an API key for a child org. The secret is returned once. Prefer scopes and a property lock over a full-access key.",
1958
- { 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() },
2359
+ { id: import_zod6.z.string(), name: import_zod6.z.string().optional(), scopes: import_zod6.z.array(import_zod6.z.string()).optional(), cbids: import_zod6.z.array(import_zod6.z.string()).min(1).optional() },
1959
2360
  (a) => client.reseller.mintKey(a.id, {
1960
2361
  ...a.name ? { name: a.name } : {},
1961
2362
  ...a.scopes ? { scopes: a.scopes } : {},
1962
2363
  ...a.cbids ? { cbids: a.cbids } : {}
1963
2364
  })
1964
2365
  );
1965
- 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) => {
2366
+ tool("revoke_customer_key", "Revoke a child org's API key by prefix. Takes effect immediately.", { id: import_zod6.z.string(), prefix: import_zod6.z.string() }, async (a) => {
1966
2367
  await client.reseller.revokeKey(a.id, a.prefix);
1967
2368
  return { revoked: a.prefix };
1968
2369
  });
1969
2370
  tool(
1970
2371
  "erase_subject_data",
1971
2372
  "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.",
1972
- { cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
2373
+ { cbid: import_zod6.z.string(), stamp: import_zod6.z.string() },
1973
2374
  (a) => client.consent.eraseSubject(a.cbid, a.stamp)
1974
2375
  );
1975
2376
  tool(
1976
2377
  "export_subject_data",
1977
2378
  "Export a data subject's consent records (GDPR access/portability).",
1978
- { cbid: import_zod5.z.string(), stamp: import_zod5.z.string() },
2379
+ { cbid: import_zod6.z.string(), stamp: import_zod6.z.string() },
1979
2380
  (a) => client.consent.exportSubject(a.cbid, a.stamp)
1980
2381
  );
1981
2382
  tool("list_banners", "List reusable banner designs in your org.", {}, () => client.banners.list());
1982
2383
  tool(
1983
2384
  "create_banner",
1984
2385
  "Create a reusable banner design.",
1985
- { name: import_zod5.z.string(), json: import_zod5.z.record(import_zod5.z.unknown()).describe("A v2 BannerConfig.") },
2386
+ { name: import_zod6.z.string(), json: import_zod6.z.record(import_zod6.z.unknown()).describe("A v2 BannerConfig.") },
1986
2387
  (a) => client.banners.create({ name: a.name, json: a.json })
1987
2388
  );
1988
- tool("get_banner", "Get a banner design by id.", { id: import_zod5.z.string() }, (a) => client.banners.get(a.id));
2389
+ tool("get_banner", "Get a banner design by id.", { id: import_zod6.z.string() }, (a) => client.banners.get(a.id));
1989
2390
  tool(
1990
2391
  "update_banner",
1991
2392
  "Update a banner design (name and/or config).",
1992
- { id: import_zod5.z.string(), name: import_zod5.z.string().optional(), json: import_zod5.z.record(import_zod5.z.unknown()).optional() },
2393
+ { id: import_zod6.z.string(), name: import_zod6.z.string().optional(), json: import_zod6.z.record(import_zod6.z.unknown()).optional() },
1993
2394
  (a) => client.banners.update(a.id, {
1994
2395
  ...a.name !== void 0 ? { name: a.name } : {},
1995
2396
  ...a.json !== void 0 ? { json: a.json } : {}
1996
2397
  })
1997
2398
  );
1998
- tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id: import_zod5.z.string() }, async (a) => {
2399
+ tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id: import_zod6.z.string() }, async (a) => {
1999
2400
  await client.banners.delete(a.id);
2000
2401
  return { ok: true };
2001
2402
  });
2002
2403
  tool(
2003
2404
  "get_banner_assignments",
2004
2405
  "The sites (cbids) a banner design is currently assigned to. Read-only.",
2005
- { id: import_zod5.z.string() },
2406
+ { id: import_zod6.z.string() },
2006
2407
  (a) => client.banners.assignments(a.id)
2007
2408
  );
2008
2409
  tool(
2009
2410
  "assign_banner",
2010
2411
  "Set which sites (cbids) use a banner design.",
2011
- { id: import_zod5.z.string(), cbids: import_zod5.z.array(import_zod5.z.string()) },
2412
+ { id: import_zod6.z.string(), cbids: import_zod6.z.array(import_zod6.z.string()) },
2012
2413
  (a) => client.banners.setAssignments(a.id, a.cbids)
2013
2414
  );
2014
2415
  tool(
2015
2416
  "publish_banner",
2016
2417
  "Publish a design live to all its assigned sites.",
2017
- { id: import_zod5.z.string() },
2418
+ { id: import_zod6.z.string() },
2018
2419
  (a) => client.banners.publish(a.id)
2019
2420
  );
2020
2421
  }
2021
2422
 
2022
2423
  // src/index.ts
2023
- var MCP_VERSION = "0.4.1";
2424
+ var MCP_VERSION = "0.6.0";
2024
2425
  function createCookieMunchMcp(opts) {
2025
2426
  const client = opts.client ?? (0, import_sdk.createCookieMunch)({ apiKey: opts.apiKey, baseUrl: opts.baseUrl, userAgent: opts.userAgent ?? `cookiemunch-mcp/${MCP_VERSION}` });
2026
2427
  const server = new import_mcp.McpServer({ name: "cookiemunch", version: "1.0.0" });