@cookiemunch/mcp 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/bin.cjs +600 -239
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-IQLCPEWI.js → chunk-QCLUFJZ5.js} +601 -240
- package/dist/chunk-QCLUFJZ5.js.map +1 -0
- package/dist/index.cjs +600 -239
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-IQLCPEWI.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { createCookieMunch } from "@cookiemunch/sdk";
|
|
4
4
|
|
|
5
5
|
// src/tools.ts
|
|
6
|
-
import { z as
|
|
6
|
+
import { z as z6 } from "zod";
|
|
7
7
|
|
|
8
8
|
// src/tools-config.ts
|
|
9
9
|
import { z } from "zod";
|
|
@@ -534,6 +534,12 @@ function registerPlatformTools(tool, client) {
|
|
|
534
534
|
{},
|
|
535
535
|
() => client.fulfillment.executors()
|
|
536
536
|
);
|
|
537
|
+
tool(
|
|
538
|
+
"get_dsar_executor",
|
|
539
|
+
"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.",
|
|
540
|
+
{ id: z2.string().describe("The connection id.") },
|
|
541
|
+
(a) => client.fulfillment.executor(a.id)
|
|
542
|
+
);
|
|
537
543
|
tool(
|
|
538
544
|
"connect_dsar_executor",
|
|
539
545
|
"Connect a system that runs part of a rights request \u2014 an identity platform, a CRM, anything with a rights API. Cookie Munch is not specific to any platform: the `profile` describes that system's API (paths, the words it uses for export/erase, its status vocabulary, how it signs webhooks), so connecting a new one needs no code. The secret key is stored encrypted and never returned; the response carries the webhook URL to configure in that system. Sub-tasks open automatically once a request reaches fulfilment (after identity verification), and completions are picked up by webhook or by polling.",
|
|
@@ -541,12 +547,15 @@ function registerPlatformTools(tool, client) {
|
|
|
541
547
|
preset: z2.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."),
|
|
542
548
|
presetVersion: z2.number().int().optional().describe("With preset: the version to build. Default the latest."),
|
|
543
549
|
orgId: z2.string().optional().describe("A preset param, when the preset's params list it."),
|
|
544
|
-
atlasIdAppId: z2.string().optional().describe("A preset param, when the preset's params list it: the identity platform's app id,
|
|
550
|
+
atlasIdAppId: z2.string().optional().describe("A preset param, when the preset's params list it: the identity platform's app id, kept for revokeAtlasIdGrant."),
|
|
551
|
+
revokeAtlasIdGrant: z2.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."),
|
|
552
|
+
label: z2.string().optional().describe("Your name for the credential, shown beside keyPrefix."),
|
|
545
553
|
system: z2.string().optional().describe("The name this connection answers to in a plan, e.g. identity or crm. Required unless the preset has a default."),
|
|
546
554
|
baseUrl: z2.string().optional().describe("The system's public https origin. Required unless the preset sets it."),
|
|
547
555
|
secretKey: z2.string().describe("Its API key, with whatever scope that system needs to export and erase a user."),
|
|
548
556
|
webhookSecret: z2.string().optional().describe("Signing secret of its webhook endpoint. Optional: polling closes tasks without it."),
|
|
549
557
|
auto: z2.boolean().optional().describe("Open a sub-task automatically when a request reaches fulfilment. Default true."),
|
|
558
|
+
orchestrator: z2.union([z2.literal(1), z2.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."),
|
|
550
559
|
profile: z2.record(z2.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."),
|
|
551
560
|
dryRun: z2.boolean().optional().describe("Validate everything and answer the connection that would be created, storing nothing.")
|
|
552
561
|
},
|
|
@@ -555,6 +564,12 @@ function registerPlatformTools(tool, client) {
|
|
|
555
564
|
return dryRun === true ? client.fulfillment.dryRunConnectExecutor(input) : client.fulfillment.connectExecutor(input);
|
|
556
565
|
}
|
|
557
566
|
);
|
|
567
|
+
tool(
|
|
568
|
+
"get_category_registry",
|
|
569
|
+
"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.",
|
|
570
|
+
{},
|
|
571
|
+
() => client.consent.categoryRegistry()
|
|
572
|
+
);
|
|
558
573
|
tool(
|
|
559
574
|
"list_dsar_executor_presets",
|
|
560
575
|
"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.",
|
|
@@ -563,13 +578,15 @@ function registerPlatformTools(tool, client) {
|
|
|
563
578
|
);
|
|
564
579
|
tool(
|
|
565
580
|
"upgrade_dsar_executor_preset",
|
|
566
|
-
"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.
|
|
581
|
+
"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.",
|
|
567
582
|
{
|
|
568
583
|
id: z2.string().describe("The connection id."),
|
|
569
584
|
preset: z2.string().optional().describe("Only to adopt a preset on a connection that has none."),
|
|
570
585
|
presetVersion: z2.number().int().optional(),
|
|
571
586
|
orgId: z2.string().optional(),
|
|
572
587
|
atlasIdAppId: z2.string().optional(),
|
|
588
|
+
revokeAtlasIdGrant: z2.boolean().optional(),
|
|
589
|
+
acceptPreset: z2.array(z2.string()).optional().describe(`Overridden paths (profileOverrides) that take the preset's value again, e.g. ["profile.grantRevoke"]. Every other override is kept.`),
|
|
573
590
|
dryRun: z2.boolean().optional().describe("Answer the diff and change nothing.")
|
|
574
591
|
},
|
|
575
592
|
(a) => {
|
|
@@ -593,6 +610,18 @@ function registerPlatformTools(tool, client) {
|
|
|
593
610
|
{ id: z2.string().describe("The connection id.") },
|
|
594
611
|
(a) => client.fulfillment.executorWebhookDeliveries(a.id)
|
|
595
612
|
);
|
|
613
|
+
tool(
|
|
614
|
+
"recheck_dsar_executor",
|
|
615
|
+
"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.",
|
|
616
|
+
{ id: z2.string().describe("The connection id.") },
|
|
617
|
+
(a) => client.fulfillment.recheckExecutor(a.id)
|
|
618
|
+
);
|
|
619
|
+
tool(
|
|
620
|
+
"list_dsar_executor_health_history",
|
|
621
|
+
"A connected system's last health checks, newest first (each with ok, verdict and lastCheckedAt). Read-only.",
|
|
622
|
+
{ id: z2.string().describe("The connection id."), limit: z2.number().int().min(1).max(50).optional().describe("Default 50.") },
|
|
623
|
+
(a) => client.fulfillment.executorHealthHistory(a.id, typeof a.limit === "number" ? { limit: a.limit } : {})
|
|
624
|
+
);
|
|
596
625
|
tool(
|
|
597
626
|
"disconnect_dsar_executor",
|
|
598
627
|
"Disconnect a system. Its open sub-tasks stop being driven, and the stored credentials are deleted.",
|
|
@@ -625,6 +654,18 @@ function registerPlatformTools(tool, client) {
|
|
|
625
654
|
...typeof a.open === "boolean" ? { open: a.open } : {}
|
|
626
655
|
})
|
|
627
656
|
);
|
|
657
|
+
tool(
|
|
658
|
+
"run_executor_conformance",
|
|
659
|
+
"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.",
|
|
660
|
+
{ id: z2.string().describe("The connection id.") },
|
|
661
|
+
(a) => client.fulfillment.executorConformance(a.id)
|
|
662
|
+
);
|
|
663
|
+
tool(
|
|
664
|
+
"roll_executor_completion_secret",
|
|
665
|
+
"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.",
|
|
666
|
+
{ id: z2.string().describe("The connection id.") },
|
|
667
|
+
(a) => client.fulfillment.rollExecutorCompletionSecret(a.id)
|
|
668
|
+
);
|
|
628
669
|
tool(
|
|
629
670
|
"get_dsar_task_export",
|
|
630
671
|
"The export bundle a connected system produced for one sub-task, fetched from that system on demand. The platform keeps no copy.",
|
|
@@ -731,13 +772,44 @@ function registerIntegrationTools(tool, client) {
|
|
|
731
772
|
{ cbid: z3.string().optional().describe("Site identifier; optional when the org has one site.") },
|
|
732
773
|
(a) => client.integrationHealth(a.cbid)
|
|
733
774
|
);
|
|
775
|
+
tool(
|
|
776
|
+
"list_health_waivers",
|
|
777
|
+
"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.",
|
|
778
|
+
{ cbid: z3.string().optional().describe("Site identifier; optional when the org has one site.") },
|
|
779
|
+
(a) => client.healthWaivers.list(a.cbid)
|
|
780
|
+
);
|
|
781
|
+
const waiverSchema = z3.object({
|
|
782
|
+
cbid: z3.string().optional().describe("Site identifier; optional when the org has one site."),
|
|
783
|
+
check: z3.string().describe("A row\u2019s check or kind, e.g. atlas.cookie_consent."),
|
|
784
|
+
subject: z3.string().optional().describe("A row\u2019s subject; omitted: every subject of the check."),
|
|
785
|
+
reason: z3.string().describe("Why this is deliberate (shown on the row and in the audit log)."),
|
|
786
|
+
until: z3.union([z3.string(), z3.number()]).nullable().optional().describe("When the waiver ends (ISO date or epoch ms, within a year); omitted: never.")
|
|
787
|
+
});
|
|
788
|
+
tool(
|
|
789
|
+
"set_health_waiver",
|
|
790
|
+
"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.",
|
|
791
|
+
waiverSchema.shape,
|
|
792
|
+
(a) => client.healthWaivers.set(waiverSchema.parse(a))
|
|
793
|
+
);
|
|
794
|
+
tool(
|
|
795
|
+
"remove_health_waiver",
|
|
796
|
+
"Remove an integration-health waiver, so the check reports its real state again. Audited.",
|
|
797
|
+
{ check: z3.string(), cbid: z3.string().optional(), subject: z3.string().optional().describe("Default: every subject (*).") },
|
|
798
|
+
(a) => client.healthWaivers.remove(a.check, { ...a.cbid ? { cbid: a.cbid } : {}, ...a.subject ? { subject: a.subject } : {} })
|
|
799
|
+
);
|
|
800
|
+
tool(
|
|
801
|
+
"get_embed_manifest",
|
|
802
|
+
"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.",
|
|
803
|
+
{ cbid: z3.string() },
|
|
804
|
+
(a) => client.embedManifest(a.cbid)
|
|
805
|
+
);
|
|
734
806
|
const provisionSchema = z3.object({
|
|
735
807
|
product: z3.string().describe("A slug naming the product."),
|
|
736
808
|
domain: z3.string().describe("The product\u2019s domain (bare hostname)."),
|
|
737
809
|
name: z3.string().optional(),
|
|
738
810
|
aliases: z3.array(z3.string()).optional(),
|
|
739
811
|
cbid: z3.string().optional().describe("Update this site instead of matching by domain."),
|
|
740
|
-
atlas: z3.object({ secretKey: z3.string(), cookieConsent: z3.boolean().optional(), dsrWebhook: z3.boolean().optional(), frontendApiHost: z3.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."),
|
|
812
|
+
atlas: z3.object({ secretKey: z3.string(), cookieConsent: z3.boolean().optional(), dsrWebhook: z3.boolean().optional(), rightsIdentity: z3.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: z3.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."),
|
|
741
813
|
forumulate: z3.object({ token: z3.string(), orgId: z3.string(), consent: z3.boolean().optional(), executorKey: z3.boolean().optional(), label: z3.string().optional() }).optional().describe("Forumulate org token \u2014 used for this call only, never stored or returned."),
|
|
742
814
|
rightsApi: z3.object({ baseUrl: z3.string(), secretKey: z3.string(), profilePreset: z3.string().optional() }).optional(),
|
|
743
815
|
dryRun: z3.boolean().optional().describe("Report what each step would do; write nothing on any platform. Run this first.")
|
|
@@ -753,13 +825,13 @@ function registerIntegrationTools(tool, client) {
|
|
|
753
825
|
);
|
|
754
826
|
tool(
|
|
755
827
|
"list_site_partners",
|
|
756
|
-
"Which partner platforms
|
|
828
|
+
"Which partner platforms receive this site\u2019s consent events, each with its status, and which partners are on offer. Read-only.",
|
|
757
829
|
{ cbid: z3.string() },
|
|
758
830
|
(a) => client.sites.listPartners(a.cbid)
|
|
759
831
|
);
|
|
760
832
|
const linkSchema = z3.object({
|
|
761
833
|
cbid: z3.string(),
|
|
762
|
-
partner: z3.
|
|
834
|
+
partner: z3.string().describe("A partner this deployment knows: forumulate, atlas, chatly, referalli, or any other registered on it (list_site_partners shows them)."),
|
|
763
835
|
externalId: z3.string().describe("The partner\u2019s id for the receiving account, e.g. a Forumulate organisation id."),
|
|
764
836
|
label: z3.string().optional().describe('Shown with the partner name, e.g. "docs".'),
|
|
765
837
|
events: z3.array(z3.enum(["consent.recorded", "consent.withdrawn"])).optional(),
|
|
@@ -782,31 +854,144 @@ function registerIntegrationTools(tool, client) {
|
|
|
782
854
|
);
|
|
783
855
|
}
|
|
784
856
|
|
|
785
|
-
// src/tools-
|
|
857
|
+
// src/tools-keys-tags.ts
|
|
786
858
|
import { z as z4 } from "zod";
|
|
859
|
+
var TAGGED = ["org", "site", "webhook", "executor", "dsar", "partner_link"];
|
|
860
|
+
function registerKeyAndTagTools(tool, client) {
|
|
861
|
+
tool(
|
|
862
|
+
"get_own_key",
|
|
863
|
+
"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.",
|
|
864
|
+
{},
|
|
865
|
+
() => client.keys.self()
|
|
866
|
+
);
|
|
867
|
+
tool(
|
|
868
|
+
"list_api_versions",
|
|
869
|
+
"The dated API versions, what each one changed, and the version the key this server runs with is pinned to (`yours`). Read-only.",
|
|
870
|
+
{},
|
|
871
|
+
() => client.versions()
|
|
872
|
+
);
|
|
873
|
+
tool(
|
|
874
|
+
"set_own_api_version",
|
|
875
|
+
"Re-pin the key this server runs with to another dated API version (from list_api_versions). It changes how the API behaves for this key (for example strict request bodies from 2026-10-24), never what the key may do.",
|
|
876
|
+
{ apiVersion: z4.string().describe("A version from list_api_versions, e.g. 2026-10-24.") },
|
|
877
|
+
(a) => client.keys.updateSelf({ apiVersion: a.apiVersion })
|
|
878
|
+
);
|
|
879
|
+
tool(
|
|
880
|
+
"get_sandbox",
|
|
881
|
+
"The organisation\u2019s sandbox (a separate test organisation with the same people and plan features, never billed), or null. Read-only.",
|
|
882
|
+
{},
|
|
883
|
+
() => client.sandbox.get()
|
|
884
|
+
);
|
|
885
|
+
tool(
|
|
886
|
+
"create_sandbox",
|
|
887
|
+
"Make a sandbox of the organisation, or return the one it has, with a new test-format key for it (shown once). Everything in a sandbox is test data: its keys are cookiemunch_test_ keys and every rights request filed there is a test. Needs a full-access key or orgs:create.",
|
|
888
|
+
{ keyName: z4.string().min(1).max(100).optional().describe('A name for the new key. Default "sandbox".') },
|
|
889
|
+
(a) => client.sandbox.create(a.keyName !== void 0 ? { keyName: a.keyName } : {})
|
|
890
|
+
);
|
|
891
|
+
tool(
|
|
892
|
+
"list_api_keys_standard",
|
|
893
|
+
"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.",
|
|
894
|
+
{},
|
|
895
|
+
() => client.keys.listStandard()
|
|
896
|
+
);
|
|
897
|
+
const vendSchema = z4.object({
|
|
898
|
+
scopes: z4.array(z4.string()).min(1).describe("A subset of this key\u2019s own scopes."),
|
|
899
|
+
ttlSeconds: z4.number().int().min(60).max(43200).describe("How long the key works, at most 12 hours."),
|
|
900
|
+
cbids: z4.array(z4.string()).min(1).optional().describe("Lock it to these sites (within this key\u2019s own lock)."),
|
|
901
|
+
name: z4.string().max(100).optional()
|
|
902
|
+
});
|
|
903
|
+
tool(
|
|
904
|
+
"vend_api_key",
|
|
905
|
+
"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.",
|
|
906
|
+
vendSchema.shape,
|
|
907
|
+
(a) => client.keys.vend(vendSchema.parse(a))
|
|
908
|
+
);
|
|
909
|
+
tool(
|
|
910
|
+
"revoke_leaked_key",
|
|
911
|
+
"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.",
|
|
912
|
+
{ key: z4.string().describe("The leaked secret, whole."), source: z4.string().optional().describe("Where it was found (a URL).") },
|
|
913
|
+
(a) => client.keys.revokeLeaked({ key: a.key, ...a.source ? { source: a.source } : {} })
|
|
914
|
+
);
|
|
915
|
+
tool(
|
|
916
|
+
"get_resource_tags",
|
|
917
|
+
"A resource\u2019s tags (metadata), its externalRef and whether it is a sandbox. Read-only.",
|
|
918
|
+
{ type: z4.enum(TAGGED), id: z4.string() },
|
|
919
|
+
(a) => client.metadata.get(a.type, a.id)
|
|
920
|
+
);
|
|
921
|
+
const tagsSchema = z4.object({
|
|
922
|
+
type: z4.enum(TAGGED),
|
|
923
|
+
id: z4.string(),
|
|
924
|
+
metadata: z4.record(z4.union([z4.string(), z4.number(), z4.boolean(), z4.null()])).describe("Keys to set; null removes one. forgedeck_sandbox cannot be set here."),
|
|
925
|
+
dryRun: z4.boolean().optional().describe("Answer with the diff, storing nothing. Do this first.")
|
|
926
|
+
});
|
|
927
|
+
tool(
|
|
928
|
+
"update_resource_tags",
|
|
929
|
+
"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.",
|
|
930
|
+
tagsSchema.shape,
|
|
931
|
+
(a) => {
|
|
932
|
+
const { type, id, metadata, dryRun } = tagsSchema.parse(a);
|
|
933
|
+
return client.metadata.update(type, id, metadata, { dryRun });
|
|
934
|
+
}
|
|
935
|
+
);
|
|
936
|
+
tool(
|
|
937
|
+
"list_partner_links",
|
|
938
|
+
"Every partner link of the organisation (site and org links), with scopes, expiry, last use and calls in the last 30 days. Read-only.",
|
|
939
|
+
{ metadata: z4.record(z4.string()).optional().describe("Keep only links with these tags.") },
|
|
940
|
+
(a) => client.partnerLinks.list(a.metadata ? { metadata: a.metadata } : void 0)
|
|
941
|
+
);
|
|
942
|
+
const linkSchema = z4.object({
|
|
943
|
+
partner: z4.string().describe("A partner this deployment knows (built in or registered)."),
|
|
944
|
+
resource: z4.string().describe("site:<cbid> or org:<this org id>."),
|
|
945
|
+
scopes: z4.array(z4.enum(["consent:read", "receipt:read", "dsar:read", "dsar:write", "dsar:rights-links", "sites:read"])).min(1),
|
|
946
|
+
expires_at: z4.string().optional().describe("ISO 8601, in the future."),
|
|
947
|
+
externalId: z4.string().optional(),
|
|
948
|
+
label: z4.string().max(60).optional()
|
|
949
|
+
});
|
|
950
|
+
tool(
|
|
951
|
+
"create_partner_link",
|
|
952
|
+
"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.",
|
|
953
|
+
linkSchema.shape,
|
|
954
|
+
(a) => client.partnerLinks.create(linkSchema.parse(a))
|
|
955
|
+
);
|
|
956
|
+
tool(
|
|
957
|
+
"revoke_partner_link",
|
|
958
|
+
"Revoke a partner link: the partner\u2019s calls under it and its deliveries stop at once.",
|
|
959
|
+
{ id: z4.string() },
|
|
960
|
+
(a) => client.partnerLinks.revoke(a.id)
|
|
961
|
+
);
|
|
962
|
+
tool(
|
|
963
|
+
"get_provision_env",
|
|
964
|
+
"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.",
|
|
965
|
+
{ ref: z4.string() },
|
|
966
|
+
(a) => client.provisionEnv(a.ref)
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/tools-rights-page.ts
|
|
971
|
+
import { z as z5 } from "zod";
|
|
787
972
|
function registerRightsTools(tool, client) {
|
|
788
|
-
const cbid = { cbid:
|
|
973
|
+
const cbid = { cbid: z5.string().describe("Site identifier (cbid). Must belong to your org.") };
|
|
789
974
|
const base = {
|
|
790
|
-
baseUpdatedAt:
|
|
975
|
+
baseUpdatedAt: z5.union([z5.number().int(), z5.string(), z5.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.")
|
|
791
976
|
};
|
|
792
977
|
const baseOpt = (a) => a.baseUpdatedAt !== void 0 ? { baseUpdatedAt: a.baseUpdatedAt } : {};
|
|
793
978
|
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));
|
|
794
979
|
tool(
|
|
795
980
|
"update_rights_page",
|
|
796
981
|
"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.",
|
|
797
|
-
{ ...cbid, page:
|
|
982
|
+
{ ...cbid, page: z5.record(z5.unknown()).describe("The whole RightsPage document (v: 1)."), ...base },
|
|
798
983
|
(a) => client.rightsPage.put(a.cbid, a.page, baseOpt(a))
|
|
799
984
|
);
|
|
800
985
|
tool(
|
|
801
986
|
"patch_rights_page",
|
|
802
987
|
"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).",
|
|
803
|
-
{ ...cbid, patch:
|
|
988
|
+
{ ...cbid, patch: z5.record(z5.unknown()), ...base },
|
|
804
989
|
(a) => client.rightsPage.patch(a.cbid, a.patch, baseOpt(a))
|
|
805
990
|
);
|
|
806
991
|
tool(
|
|
807
992
|
"preview_rights_page",
|
|
808
993
|
'Validate a rights-page write WITHOUT saving: returns the document as it would be stored and any publish warnings. mode "patch" (default) or "put".',
|
|
809
|
-
{ ...cbid, page:
|
|
994
|
+
{ ...cbid, page: z5.record(z5.unknown()), mode: z5.enum(["patch", "put"]).optional() },
|
|
810
995
|
(a) => client.rightsPage.dryRun(a.cbid, a.page, { mode: a.mode ?? "patch" })
|
|
811
996
|
);
|
|
812
997
|
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));
|
|
@@ -820,14 +1005,14 @@ function registerRightsTools(tool, client) {
|
|
|
820
1005
|
tool(
|
|
821
1006
|
"rollback_rights_page",
|
|
822
1007
|
"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.",
|
|
823
|
-
{ ...cbid, version:
|
|
1008
|
+
{ ...cbid, version: z5.number().int().min(1), ...base },
|
|
824
1009
|
(a) => client.rightsPage.rollback(a.cbid, a.version, baseOpt(a))
|
|
825
1010
|
);
|
|
826
1011
|
}
|
|
827
1012
|
function registerRightsPageTools(tool, client) {
|
|
828
|
-
const site =
|
|
1013
|
+
const site = z5.object({ cbid: z5.string().describe("Site identifier (cbid). Must belong to your org.") });
|
|
829
1014
|
const host = site.extend({
|
|
830
|
-
hostname:
|
|
1015
|
+
hostname: z5.string().describe("The custom hostname, e.g. privacy.example.com (unicode or punycode).")
|
|
831
1016
|
});
|
|
832
1017
|
tool(
|
|
833
1018
|
"list_rights_page_domains",
|
|
@@ -967,10 +1152,10 @@ function registerTools(server, client) {
|
|
|
967
1152
|
}
|
|
968
1153
|
});
|
|
969
1154
|
};
|
|
970
|
-
const cbid = { cbid:
|
|
1155
|
+
const cbid = { cbid: z6.string().describe("Site identifier (cbid). Must belong to your org.") };
|
|
971
1156
|
const range = {
|
|
972
|
-
from:
|
|
973
|
-
to:
|
|
1157
|
+
from: z6.number().optional().describe("Epoch-ms lower bound."),
|
|
1158
|
+
to: z6.number().optional().describe("Epoch-ms upper bound.")
|
|
974
1159
|
};
|
|
975
1160
|
tool(
|
|
976
1161
|
"whoami",
|
|
@@ -988,19 +1173,19 @@ function registerTools(server, client) {
|
|
|
988
1173
|
tool(
|
|
989
1174
|
"get_site",
|
|
990
1175
|
"One site: its domain, cbid and verification status. Read-only.",
|
|
991
|
-
{ cbid:
|
|
1176
|
+
{ cbid: z6.string() },
|
|
992
1177
|
(a) => client.sites.get(a.cbid)
|
|
993
1178
|
);
|
|
994
1179
|
tool(
|
|
995
1180
|
"get_site_banner",
|
|
996
1181
|
"Which banner design a site uses, or bannerId null when none is assigned. Read-only.",
|
|
997
|
-
{ cbid:
|
|
1182
|
+
{ cbid: z6.string() },
|
|
998
1183
|
(a) => client.sites.banner(a.cbid)
|
|
999
1184
|
);
|
|
1000
1185
|
tool(
|
|
1001
1186
|
"get_privacy_policy",
|
|
1002
1187
|
"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.",
|
|
1003
|
-
{ cbid:
|
|
1188
|
+
{ cbid: z6.string(), contactEmail: z6.string().optional(), effectiveDate: z6.string().optional().describe("YYYY-MM-DD; defaults to today."), jurisdictions: z6.array(z6.string()).optional() },
|
|
1004
1189
|
(a) => client.sites.policy(a.cbid, {
|
|
1005
1190
|
...a.contactEmail ? { contactEmail: a.contactEmail } : {},
|
|
1006
1191
|
...a.effectiveDate ? { effectiveDate: a.effectiveDate } : {},
|
|
@@ -1010,7 +1195,7 @@ function registerTools(server, client) {
|
|
|
1010
1195
|
tool(
|
|
1011
1196
|
"set_ad_personalization",
|
|
1012
1197
|
"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.",
|
|
1013
|
-
{ cbid:
|
|
1198
|
+
{ cbid: z6.string(), enabled: z6.boolean(), default: z6.boolean().optional(), label: z6.string().optional() },
|
|
1014
1199
|
(a) => client.sites.setAdPersonalization(a.cbid, {
|
|
1015
1200
|
enabled: a.enabled,
|
|
1016
1201
|
...a.default !== void 0 ? { default: a.default } : {},
|
|
@@ -1021,11 +1206,11 @@ function registerTools(server, client) {
|
|
|
1021
1206
|
"analyze_session",
|
|
1022
1207
|
"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.",
|
|
1023
1208
|
{
|
|
1024
|
-
cbid:
|
|
1025
|
-
har:
|
|
1026
|
-
requests:
|
|
1027
|
-
consent:
|
|
1028
|
-
gpc:
|
|
1209
|
+
cbid: z6.string(),
|
|
1210
|
+
har: z6.unknown().optional().describe("A HAR export of the session."),
|
|
1211
|
+
requests: z6.array(z6.unknown()).optional().describe("Or the requests directly."),
|
|
1212
|
+
consent: z6.record(z6.string(), z6.boolean()).optional(),
|
|
1213
|
+
gpc: z6.boolean().optional()
|
|
1029
1214
|
},
|
|
1030
1215
|
(a) => client.sites.analyzeSession(a.cbid, {
|
|
1031
1216
|
...a.har !== void 0 ? { har: a.har } : {},
|
|
@@ -1037,14 +1222,14 @@ function registerTools(server, client) {
|
|
|
1037
1222
|
tool(
|
|
1038
1223
|
"create_site",
|
|
1039
1224
|
"Create a new site. The cbid is auto-generated if you omit it.",
|
|
1040
|
-
{ domain:
|
|
1225
|
+
{ domain: z6.string().describe("The site domain, e.g. example.com."), cbid: z6.string().optional().describe("Optional explicit cbid.") },
|
|
1041
1226
|
(a) => client.sites.create({ domain: a.domain, ...typeof a.cbid === "string" ? { cbid: a.cbid } : {} })
|
|
1042
1227
|
);
|
|
1043
1228
|
tool(
|
|
1044
1229
|
"create_sites_bulk",
|
|
1045
1230
|
"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.",
|
|
1046
1231
|
{
|
|
1047
|
-
sites:
|
|
1232
|
+
sites: z6.array(z6.object({ domain: z6.string(), cbid: z6.string().optional(), platform: z6.string().optional() })).min(1).max(100)
|
|
1048
1233
|
},
|
|
1049
1234
|
(a) => client.sites.createBulk(a.sites)
|
|
1050
1235
|
);
|
|
@@ -1054,15 +1239,15 @@ function registerTools(server, client) {
|
|
|
1054
1239
|
"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.",
|
|
1055
1240
|
{
|
|
1056
1241
|
...cbid,
|
|
1057
|
-
config:
|
|
1058
|
-
keepUnspecified:
|
|
1242
|
+
config: z6.record(z6.unknown()).describe("The full SiteConfig to write, not a patch. Without keepUnspecified, omitted top-level fields are NOT preserved from the current config."),
|
|
1243
|
+
keepUnspecified: z6.boolean().optional().describe("PUT ?keep=unspecified: keep the stored value of every top-level field `config` omits, instead of reverting it to its default.")
|
|
1059
1244
|
},
|
|
1060
1245
|
(a) => a.keepUnspecified === true ? client.sites.putConfig(a.cbid, a.config, { keep: "unspecified" }) : client.sites.putConfig(a.cbid, a.config)
|
|
1061
1246
|
);
|
|
1062
1247
|
tool(
|
|
1063
1248
|
"patch_site_config",
|
|
1064
1249
|
`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.`,
|
|
1065
|
-
{ ...cbid, config:
|
|
1250
|
+
{ ...cbid, config: z6.record(z6.unknown()).describe('The subset of SiteConfig to change, e.g. { "banner": { "showRightsLink": true } }. Everything else is preserved; null removes a field.') },
|
|
1066
1251
|
(a) => client.sites.patchConfig(a.cbid, a.config)
|
|
1067
1252
|
);
|
|
1068
1253
|
tool(
|
|
@@ -1070,9 +1255,9 @@ function registerTools(server, client) {
|
|
|
1070
1255
|
'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.',
|
|
1071
1256
|
{
|
|
1072
1257
|
...cbid,
|
|
1073
|
-
config:
|
|
1074
|
-
mode:
|
|
1075
|
-
keepUnspecified:
|
|
1258
|
+
config: z6.record(z6.unknown()).describe('The patch (or, with mode "put", the full config) to preview.'),
|
|
1259
|
+
mode: z6.enum(["patch", "put"]).optional().describe("patch (default) merges; put replaces."),
|
|
1260
|
+
keepUnspecified: z6.boolean().optional().describe('With mode "put": preview update_site_config with keepUnspecified (omitted top-level fields keep their stored value).')
|
|
1076
1261
|
},
|
|
1077
1262
|
(a) => client.sites.dryRunConfig(a.cbid, a.config, {
|
|
1078
1263
|
mode: a.mode ?? "patch",
|
|
@@ -1084,8 +1269,8 @@ function registerTools(server, client) {
|
|
|
1084
1269
|
'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.',
|
|
1085
1270
|
{
|
|
1086
1271
|
...cbid,
|
|
1087
|
-
config:
|
|
1088
|
-
replace:
|
|
1272
|
+
config: z6.record(z6.unknown()).describe("The proposed SiteConfig (or a partial one, or a v2 flow design)."),
|
|
1273
|
+
replace: z6.boolean().optional().describe("Check what update_site_config (a full replace) would store, instead of what patch_site_config (a merge) would.")
|
|
1089
1274
|
},
|
|
1090
1275
|
async (a) => {
|
|
1091
1276
|
const r = await client.sites.lintConfig(a.cbid, a.config, a.replace === true ? { replace: true } : {});
|
|
@@ -1106,10 +1291,16 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1106
1291
|
{ ...cbid, ...range },
|
|
1107
1292
|
(a) => client.consent.stats(a.cbid, { from: a.from, to: a.to })
|
|
1108
1293
|
);
|
|
1294
|
+
tool(
|
|
1295
|
+
"get_consent_insights",
|
|
1296
|
+
"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.",
|
|
1297
|
+
{ ...cbid, ...range },
|
|
1298
|
+
(a) => client.consent.insights(a.cbid, { from: a.from, to: a.to })
|
|
1299
|
+
);
|
|
1109
1300
|
tool(
|
|
1110
1301
|
"get_consent_log",
|
|
1111
1302
|
"Get recent anonymised consent records for a site.",
|
|
1112
|
-
{ ...cbid, ...range, limit:
|
|
1303
|
+
{ ...cbid, ...range, limit: z6.number().optional().describe("Max records to return (default 200).") },
|
|
1113
1304
|
(a) => client.consent.log(a.cbid, {
|
|
1114
1305
|
from: a.from,
|
|
1115
1306
|
to: a.to,
|
|
@@ -1119,54 +1310,54 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1119
1310
|
tool(
|
|
1120
1311
|
"get_subject_consent",
|
|
1121
1312
|
"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.",
|
|
1122
|
-
{ subjectId:
|
|
1313
|
+
{ subjectId: z6.string() },
|
|
1123
1314
|
(a) => client.subjects.consent(a.subjectId)
|
|
1124
1315
|
);
|
|
1125
1316
|
tool("list_dsar", "List all Data Subject Access Requests for your organization.", {}, () => client.dsar.list());
|
|
1126
1317
|
tool(
|
|
1127
1318
|
"update_dsar_executor",
|
|
1128
|
-
"Change a connected system in place \u2014 its profile, address, credential
|
|
1319
|
+
"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.",
|
|
1129
1320
|
{
|
|
1130
|
-
id:
|
|
1131
|
-
patch:
|
|
1132
|
-
dryRun:
|
|
1321
|
+
id: z6.string(),
|
|
1322
|
+
patch: z6.record(z6.unknown()),
|
|
1323
|
+
dryRun: z6.boolean().optional().describe("Validate and diff without saving.")
|
|
1133
1324
|
},
|
|
1134
1325
|
(a) => a.dryRun === true ? client.fulfillment.dryRunUpdateExecutor(a.id, a.patch) : client.fulfillment.updateExecutor(a.id, a.patch)
|
|
1135
1326
|
);
|
|
1136
1327
|
tool(
|
|
1137
1328
|
"get_dsar",
|
|
1138
1329
|
"One rights request by id, including its status and the deadline it must be answered by.",
|
|
1139
|
-
{ id:
|
|
1330
|
+
{ id: z6.string() },
|
|
1140
1331
|
(a) => client.dsar.get(a.id)
|
|
1141
1332
|
);
|
|
1142
1333
|
tool(
|
|
1143
1334
|
"erase_dsar_subject",
|
|
1144
1335
|
"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.",
|
|
1145
|
-
{ id:
|
|
1336
|
+
{ id: z6.string(), cbid: z6.string(), stamp: z6.string() },
|
|
1146
1337
|
(a) => client.dsar.erase(a.id, a.cbid, a.stamp)
|
|
1147
1338
|
);
|
|
1148
1339
|
tool(
|
|
1149
1340
|
"export_dsar_subject",
|
|
1150
1341
|
"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.",
|
|
1151
|
-
{ id:
|
|
1342
|
+
{ id: z6.string(), cbid: z6.string(), stamp: z6.string() },
|
|
1152
1343
|
(a) => client.dsar.export(a.id, a.cbid, a.stamp)
|
|
1153
1344
|
);
|
|
1154
1345
|
tool(
|
|
1155
1346
|
"get_dsar_response_notice",
|
|
1156
1347
|
"The subject-facing response notice for a request, as plain text \u2014 what to send the person. Read-only; nothing is sent.",
|
|
1157
|
-
{ id:
|
|
1348
|
+
{ id: z6.string() },
|
|
1158
1349
|
(a) => client.dsar.response(a.id)
|
|
1159
1350
|
);
|
|
1160
1351
|
tool(
|
|
1161
1352
|
"create_dsar",
|
|
1162
1353
|
"Open a new Data Subject Access Request.",
|
|
1163
1354
|
{
|
|
1164
|
-
type:
|
|
1165
|
-
subjectEmail:
|
|
1166
|
-
regulation:
|
|
1167
|
-
note:
|
|
1168
|
-
messageToSubject:
|
|
1169
|
-
test:
|
|
1355
|
+
type: z6.enum(["access", "deletion", "rectification", "portability", "opt-out"]).describe("DSAR right being exercised."),
|
|
1356
|
+
subjectEmail: z6.string().describe("The data subject\u2019s email."),
|
|
1357
|
+
regulation: z6.enum(["gdpr", "ccpa"]).describe("Governing regulation."),
|
|
1358
|
+
note: z6.string().optional().describe("Optional INTERNAL note; never shown to the data subject."),
|
|
1359
|
+
messageToSubject: z6.string().max(2e3).optional().describe("The line the data subject reads in the response notice. Never an API key."),
|
|
1360
|
+
test: z6.boolean().optional().describe("Mark it as a test request: kept off the SLA board and deletable afterwards with delete_test_dsar.")
|
|
1170
1361
|
},
|
|
1171
1362
|
(a) => client.dsar.create({
|
|
1172
1363
|
type: a.type,
|
|
@@ -1181,11 +1372,11 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1181
1372
|
"create_rights_link",
|
|
1182
1373
|
"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.",
|
|
1183
1374
|
{
|
|
1184
|
-
cbid:
|
|
1185
|
-
email:
|
|
1186
|
-
userId:
|
|
1187
|
-
rights:
|
|
1188
|
-
ttlSeconds:
|
|
1375
|
+
cbid: z6.string().describe("Site identifier (cbid). Must belong to your org."),
|
|
1376
|
+
email: z6.string().describe("The signed-in person\u2019s verified email address."),
|
|
1377
|
+
userId: z6.string().optional().describe("Your own account id for them; recorded on the request."),
|
|
1378
|
+
rights: z6.array(z6.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."),
|
|
1379
|
+
ttlSeconds: z6.number().int().min(60).max(3600).optional().describe("How long the link works, in seconds (default 900).")
|
|
1189
1380
|
},
|
|
1190
1381
|
(a) => client.rightsLinks.create(a.cbid, {
|
|
1191
1382
|
subject: { email: a.email, ...typeof a.userId === "string" ? { userId: a.userId } : {} },
|
|
@@ -1196,7 +1387,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1196
1387
|
tool(
|
|
1197
1388
|
"delete_test_dsar",
|
|
1198
1389
|
"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.",
|
|
1199
|
-
{ id:
|
|
1390
|
+
{ id: z6.string().describe("The test request id.") },
|
|
1200
1391
|
async (a) => {
|
|
1201
1392
|
await client.dsar.delete(a.id);
|
|
1202
1393
|
return { deleted: a.id };
|
|
@@ -1205,16 +1396,99 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1205
1396
|
tool(
|
|
1206
1397
|
"mark_dsar_test",
|
|
1207
1398
|
"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 }.",
|
|
1208
|
-
{ id:
|
|
1399
|
+
{ id: z6.string().describe("The closed request id.") },
|
|
1209
1400
|
(a) => client.dsar.markTest(a.id)
|
|
1210
1401
|
);
|
|
1402
|
+
tool(
|
|
1403
|
+
"open_dsar_case",
|
|
1404
|
+
"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.",
|
|
1405
|
+
{
|
|
1406
|
+
cbid: z6.string(),
|
|
1407
|
+
type: z6.string().describe("access | deletion | closure | restriction | rectification, or erasure / erase / export."),
|
|
1408
|
+
emails: z6.array(z6.string()).optional().describe("The person's addresses."),
|
|
1409
|
+
identity: z6.object({ iss: z6.string(), sub: z6.string(), ext: z6.string().optional(), principal: z6.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."),
|
|
1410
|
+
source: z6.enum(["product", "atlas", "admin"]).optional(),
|
|
1411
|
+
reason: z6.string().optional(),
|
|
1412
|
+
skipSystems: z6.array(z6.string()).optional().describe("System names, connection ids, or self."),
|
|
1413
|
+
fulfill: z6.boolean().optional(),
|
|
1414
|
+
test: z6.boolean().optional(),
|
|
1415
|
+
idempotencyKey: z6.string().optional(),
|
|
1416
|
+
trace: z6.string().optional().describe("An X-ForgeDeck-Trace to keep, from the caller.")
|
|
1417
|
+
},
|
|
1418
|
+
(a) => client.dsar.openCase(
|
|
1419
|
+
{
|
|
1420
|
+
cbid: a.cbid,
|
|
1421
|
+
type: a.type,
|
|
1422
|
+
subject: { emails: a.emails ?? [], ...a.identity ? { identity: a.identity } : {} },
|
|
1423
|
+
...a.source ? { source: a.source } : {},
|
|
1424
|
+
...typeof a.reason === "string" ? { reason: a.reason } : {},
|
|
1425
|
+
...Array.isArray(a.skipSystems) ? { skipSystems: a.skipSystems } : {},
|
|
1426
|
+
...typeof a.fulfill === "boolean" ? { fulfill: a.fulfill } : {},
|
|
1427
|
+
...a.test === true ? { test: true } : {}
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
...typeof a.idempotencyKey === "string" ? { idempotencyKey: a.idempotencyKey } : {},
|
|
1431
|
+
...typeof a.trace === "string" ? { trace: a.trace } : {}
|
|
1432
|
+
}
|
|
1433
|
+
)
|
|
1434
|
+
);
|
|
1435
|
+
tool(
|
|
1436
|
+
"get_dsar_case",
|
|
1437
|
+
"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.",
|
|
1438
|
+
{ id: z6.string() },
|
|
1439
|
+
(a) => client.dsar.getCase(a.id)
|
|
1440
|
+
);
|
|
1441
|
+
tool(
|
|
1442
|
+
"cancel_dsar_case",
|
|
1443
|
+
"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.",
|
|
1444
|
+
{ id: z6.string() },
|
|
1445
|
+
(a) => client.dsar.cancelCase(a.id)
|
|
1446
|
+
);
|
|
1447
|
+
tool(
|
|
1448
|
+
"get_dsar_case_receipt",
|
|
1449
|
+
"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.",
|
|
1450
|
+
{ id: z6.string() },
|
|
1451
|
+
(a) => client.dsar.caseReceipt(a.id)
|
|
1452
|
+
);
|
|
1453
|
+
tool(
|
|
1454
|
+
"find_dsar_by_trace",
|
|
1455
|
+
"The rights request carrying one X-ForgeDeck-Trace id \u2014 to follow one event across products. Read-only.",
|
|
1456
|
+
{ trace: z6.string() },
|
|
1457
|
+
(a) => client.dsar.listByTrace(a.trace)
|
|
1458
|
+
);
|
|
1459
|
+
tool(
|
|
1460
|
+
"get_dsar_settings",
|
|
1461
|
+
"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.",
|
|
1462
|
+
{ cbid: z6.string() },
|
|
1463
|
+
(a) => client.dsarSettings.get(a.cbid)
|
|
1464
|
+
);
|
|
1465
|
+
tool(
|
|
1466
|
+
"set_dsar_settings",
|
|
1467
|
+
"Set a site's graceDays (0\u201330). Applies to cases opened afterwards. Audited.",
|
|
1468
|
+
{ cbid: z6.string(), graceDays: z6.number().int().min(0).max(30) },
|
|
1469
|
+
(a) => client.dsarSettings.set(a.cbid, { graceDays: a.graceDays })
|
|
1470
|
+
);
|
|
1471
|
+
tool(
|
|
1472
|
+
"get_subject_card",
|
|
1473
|
+
'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.',
|
|
1474
|
+
{
|
|
1475
|
+
app: z6.string().describe("The sidebar app asking, as a slug, e.g. chatly."),
|
|
1476
|
+
iss: z6.string().optional(),
|
|
1477
|
+
sub: z6.string().optional(),
|
|
1478
|
+
email: z6.string().optional()
|
|
1479
|
+
},
|
|
1480
|
+
(a) => client.integrations.subjectCard(
|
|
1481
|
+
a.app,
|
|
1482
|
+
typeof a.iss === "string" && typeof a.sub === "string" ? { iss: a.iss, sub: a.sub } : { email: String(a.email ?? "") }
|
|
1483
|
+
)
|
|
1484
|
+
);
|
|
1211
1485
|
tool(
|
|
1212
1486
|
"advance_dsar",
|
|
1213
1487
|
"Advance a DSAR to a new status (received \u2192 verifying \u2192 in_progress \u2192 completed, or rejected).",
|
|
1214
1488
|
{
|
|
1215
|
-
id:
|
|
1216
|
-
toStatus:
|
|
1217
|
-
messageToSubject:
|
|
1489
|
+
id: z6.string().describe("The DSAR id."),
|
|
1490
|
+
toStatus: z6.enum(["received", "verifying", "in_progress", "completed", "rejected"]).describe("Target status."),
|
|
1491
|
+
messageToSubject: z6.string().max(2e3).optional().describe("Replaces the line the data subject reads in the notice \u2014 for a rejection, why.")
|
|
1218
1492
|
},
|
|
1219
1493
|
(a) => typeof a.messageToSubject === "string" ? client.dsar.advance(a.id, a.toStatus, { messageToSubject: a.messageToSubject }) : client.dsar.advance(a.id, a.toStatus)
|
|
1220
1494
|
);
|
|
@@ -1227,7 +1501,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1227
1501
|
tool(
|
|
1228
1502
|
"get_receipt",
|
|
1229
1503
|
"Fetch the signed consent receipt for a single consent record (by stamp).",
|
|
1230
|
-
{ ...cbid, stamp:
|
|
1504
|
+
{ ...cbid, stamp: z6.string().describe("The consent record stamp/id.") },
|
|
1231
1505
|
(a) => client.consent.receipt(a.cbid, a.stamp)
|
|
1232
1506
|
);
|
|
1233
1507
|
tool("delete_site", "Delete a site (cbid) and its configuration from your org.", { ...cbid }, async (a) => {
|
|
@@ -1239,13 +1513,13 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1239
1513
|
"create_vendor",
|
|
1240
1514
|
"Register a vendor (processor) and compute its risk score.",
|
|
1241
1515
|
{
|
|
1242
|
-
name:
|
|
1243
|
-
category:
|
|
1244
|
-
dataShared:
|
|
1245
|
-
dpaSigned:
|
|
1246
|
-
subprocessors:
|
|
1247
|
-
certifications:
|
|
1248
|
-
region:
|
|
1516
|
+
name: z6.string().describe("Vendor name."),
|
|
1517
|
+
category: z6.string().describe("Vendor category, e.g. analytics."),
|
|
1518
|
+
dataShared: z6.array(z6.string()).describe("Categories of data shared with the vendor."),
|
|
1519
|
+
dpaSigned: z6.boolean().describe("Whether a Data Processing Agreement is signed."),
|
|
1520
|
+
subprocessors: z6.number().describe("Number of subprocessors."),
|
|
1521
|
+
certifications: z6.array(z6.string()).describe("Compliance certifications, e.g. ISO27001."),
|
|
1522
|
+
region: z6.string().describe("Primary processing region, e.g. EU.")
|
|
1249
1523
|
},
|
|
1250
1524
|
(a) => client.vendors.create({
|
|
1251
1525
|
name: a.name,
|
|
@@ -1263,13 +1537,13 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1263
1537
|
"create_ropa",
|
|
1264
1538
|
"Create a Record of Processing Activity (RoPA) entry.",
|
|
1265
1539
|
{
|
|
1266
|
-
name:
|
|
1267
|
-
purpose:
|
|
1268
|
-
legalBasis:
|
|
1269
|
-
dataCategories:
|
|
1270
|
-
recipients:
|
|
1271
|
-
retentionDays:
|
|
1272
|
-
crossBorderTransfer:
|
|
1540
|
+
name: z6.string().describe("Activity name."),
|
|
1541
|
+
purpose: z6.string().describe("Purpose of processing."),
|
|
1542
|
+
legalBasis: z6.enum(["consent", "contract", "legal-obligation", "vital-interests", "public-task", "legitimate-interests"]).describe("GDPR legal basis."),
|
|
1543
|
+
dataCategories: z6.array(z6.string()).describe("Categories of personal data."),
|
|
1544
|
+
recipients: z6.array(z6.string()).describe("Recipients of the data."),
|
|
1545
|
+
retentionDays: z6.number().describe("Retention period in days."),
|
|
1546
|
+
crossBorderTransfer: z6.boolean().describe("Whether data is transferred across borders.")
|
|
1273
1547
|
},
|
|
1274
1548
|
(a) => client.ropa.create({
|
|
1275
1549
|
name: a.name,
|
|
@@ -1290,7 +1564,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1290
1564
|
tool(
|
|
1291
1565
|
"scan_site",
|
|
1292
1566
|
"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.",
|
|
1293
|
-
{ ...cbid, wait:
|
|
1567
|
+
{ ...cbid, wait: z6.boolean().optional().describe("Wait for the scan to finish (up to 100 s) and return its outcome.") },
|
|
1294
1568
|
async (a) => {
|
|
1295
1569
|
let started;
|
|
1296
1570
|
try {
|
|
@@ -1303,8 +1577,8 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1303
1577
|
);
|
|
1304
1578
|
tool(
|
|
1305
1579
|
"get_scan_status",
|
|
1306
|
-
"Get a site\u2019s last cookie scan: state (queued, scanning, done, failed), scanId, durationMs, cookieCount, pagesVisited and error when it failed.",
|
|
1307
|
-
{ ...cbid, wait:
|
|
1580
|
+
"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.",
|
|
1581
|
+
{ ...cbid, wait: z6.number().min(0).max(60).optional().describe("Seconds (\u226460) to wait for a running scan to settle before answering.") },
|
|
1308
1582
|
(a) => a.wait !== void 0 ? client.sites.scanStatus(a.cbid, { wait: a.wait }) : client.sites.scanStatus(a.cbid)
|
|
1309
1583
|
);
|
|
1310
1584
|
tool(
|
|
@@ -1321,20 +1595,26 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1321
1595
|
"api_key_report",
|
|
1322
1596
|
"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.",
|
|
1323
1597
|
{
|
|
1324
|
-
unusedDays:
|
|
1325
|
-
expiringDays:
|
|
1598
|
+
unusedDays: z6.number().int().min(1).max(3650).optional().describe("Unused for at least this many days (default 90)."),
|
|
1599
|
+
expiringDays: z6.number().int().min(1).max(3650).optional().describe("Expiring within this many days (default 14).")
|
|
1326
1600
|
},
|
|
1327
1601
|
(a) => client.keys.report({ ...a.unusedDays !== void 0 ? { unusedDays: a.unusedDays } : {}, ...a.expiringDays !== void 0 ? { expiringDays: a.expiringDays } : {} })
|
|
1328
1602
|
);
|
|
1329
1603
|
tool("get_usage", "Get the current usage/quota summary for your organization.", {}, () => client.usage());
|
|
1604
|
+
tool(
|
|
1605
|
+
"get_entitlements",
|
|
1606
|
+
"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.",
|
|
1607
|
+
{},
|
|
1608
|
+
() => client.entitlements()
|
|
1609
|
+
);
|
|
1330
1610
|
tool("list_webhooks", "List webhook subscriptions for your organization.", {}, () => client.webhooks.list());
|
|
1331
1611
|
tool(
|
|
1332
1612
|
"create_webhook",
|
|
1333
1613
|
"Create a webhook subscription. The response includes the signing secret (shown once).",
|
|
1334
1614
|
{
|
|
1335
|
-
url:
|
|
1336
|
-
events:
|
|
1337
|
-
cbid:
|
|
1615
|
+
url: z6.string().describe("HTTPS endpoint to deliver events to."),
|
|
1616
|
+
events: z6.array(z6.string()).describe("Event names to subscribe to, e.g. consent.created."),
|
|
1617
|
+
cbid: z6.string().optional().describe("Optional site cbid to scope the subscription to.")
|
|
1338
1618
|
},
|
|
1339
1619
|
(a) => client.webhooks.create({
|
|
1340
1620
|
url: a.url,
|
|
@@ -1345,13 +1625,13 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1345
1625
|
tool(
|
|
1346
1626
|
"roll_webhook_secret",
|
|
1347
1627
|
"Rotate a webhook subscription\u2019s signing secret. The new secret is returned once; the receiving endpoint must be updated to verify with it.",
|
|
1348
|
-
{ id:
|
|
1628
|
+
{ id: z6.string() },
|
|
1349
1629
|
(a) => client.webhooks.rollSecret(a.id)
|
|
1350
1630
|
);
|
|
1351
1631
|
tool(
|
|
1352
1632
|
"test_webhook",
|
|
1353
1633
|
"Send a signed test event to a webhook subscription now, and report what the endpoint answered.",
|
|
1354
|
-
{ id:
|
|
1634
|
+
{ id: z6.string() },
|
|
1355
1635
|
(a) => client.webhooks.test(a.id)
|
|
1356
1636
|
);
|
|
1357
1637
|
tool(
|
|
@@ -1363,40 +1643,48 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1363
1643
|
tool(
|
|
1364
1644
|
"replay_webhook_dead_letter",
|
|
1365
1645
|
"Deliver a dead-lettered webhook event again, to the subscription as it is now.",
|
|
1366
|
-
{ id:
|
|
1646
|
+
{ id: z6.string() },
|
|
1367
1647
|
(a) => client.webhooks.replayDeadLetter(a.id)
|
|
1368
1648
|
);
|
|
1649
|
+
tool(
|
|
1650
|
+
"replay_webhook",
|
|
1651
|
+
"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).",
|
|
1652
|
+
{ id: z6.string(), since: z6.union([z6.number(), z6.string()]).describe("Epoch ms or ISO date."), limit: z6.number().int().min(1).max(500).optional() },
|
|
1653
|
+
(a) => client.webhooks.replay(a.id, a.since, a.limit ? { limit: a.limit } : void 0)
|
|
1654
|
+
);
|
|
1369
1655
|
tool(
|
|
1370
1656
|
"update_webhook",
|
|
1371
|
-
"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.",
|
|
1657
|
+
"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).",
|
|
1372
1658
|
{
|
|
1373
|
-
id:
|
|
1374
|
-
url:
|
|
1375
|
-
events:
|
|
1376
|
-
cbid:
|
|
1377
|
-
active:
|
|
1659
|
+
id: z6.string(),
|
|
1660
|
+
url: z6.string().optional(),
|
|
1661
|
+
events: z6.array(z6.string()).optional(),
|
|
1662
|
+
cbid: z6.string().nullable().optional(),
|
|
1663
|
+
active: z6.boolean().optional(),
|
|
1664
|
+
alertContacts: z6.array(z6.string()).nullable().optional()
|
|
1378
1665
|
},
|
|
1379
1666
|
(a) => client.webhooks.update(a.id, {
|
|
1380
1667
|
...a.url !== void 0 ? { url: a.url } : {},
|
|
1381
1668
|
...a.events !== void 0 ? { events: a.events } : {},
|
|
1382
1669
|
...a.cbid !== void 0 ? { cbid: a.cbid } : {},
|
|
1383
|
-
...a.active !== void 0 ? { active: a.active } : {}
|
|
1670
|
+
...a.active !== void 0 ? { active: a.active } : {},
|
|
1671
|
+
...a.alertContacts !== void 0 ? { alertContacts: a.alertContacts } : {}
|
|
1384
1672
|
})
|
|
1385
1673
|
);
|
|
1386
|
-
tool("delete_webhook", "Delete a webhook subscription by id.", { id:
|
|
1674
|
+
tool("delete_webhook", "Delete a webhook subscription by id.", { id: z6.string().describe("The webhook subscription id.") }, async (a) => {
|
|
1387
1675
|
await client.webhooks.delete(a.id);
|
|
1388
1676
|
return { ok: true };
|
|
1389
1677
|
});
|
|
1390
1678
|
tool(
|
|
1391
1679
|
"verify_site",
|
|
1392
1680
|
"Verify that your organization controls a domain by one of three challenge methods (dns / meta / file). Required to unlock consent export and signed receipts.",
|
|
1393
|
-
{ ...cbid, method:
|
|
1681
|
+
{ ...cbid, method: z6.enum(["dns", "meta", "file"]).describe("Challenge method: dns (TXT record), meta (HTML tag), or file (/.well-known/cookiemunch-verify.txt).") },
|
|
1394
1682
|
(a) => client.sites.verify(a.cbid, a.method)
|
|
1395
1683
|
);
|
|
1396
1684
|
tool(
|
|
1397
1685
|
"get_verification_challenge",
|
|
1398
1686
|
"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.",
|
|
1399
|
-
{ cbid:
|
|
1687
|
+
{ cbid: z6.string() },
|
|
1400
1688
|
(a) => client.sites.verifyChallenge(a.cbid)
|
|
1401
1689
|
);
|
|
1402
1690
|
tool(
|
|
@@ -1405,18 +1693,35 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1405
1693
|
{ ...cbid },
|
|
1406
1694
|
(a) => client.sites.brand(a.cbid)
|
|
1407
1695
|
);
|
|
1696
|
+
tool(
|
|
1697
|
+
"get_site_brand",
|
|
1698
|
+
"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).",
|
|
1699
|
+
{ cbid: z6.string() },
|
|
1700
|
+
(a) => client.sites.getBrand(a.cbid)
|
|
1701
|
+
);
|
|
1702
|
+
tool(
|
|
1703
|
+
"import_site_brand",
|
|
1704
|
+
"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.",
|
|
1705
|
+
{
|
|
1706
|
+
cbid: z6.string(),
|
|
1707
|
+
url: z6.string().optional().describe("https URL of the brand.json. Give this or document."),
|
|
1708
|
+
document: z6.record(z6.unknown()).optional().describe("The brand.json object itself. Give this or url."),
|
|
1709
|
+
dryRun: z6.boolean().optional()
|
|
1710
|
+
},
|
|
1711
|
+
(a) => client.sites.setBrand(a.cbid, typeof a.url === "string" ? { url: a.url } : a.document ?? {}, { dryRun: a.dryRun === true })
|
|
1712
|
+
);
|
|
1408
1713
|
tool(
|
|
1409
1714
|
"get_flow",
|
|
1410
1715
|
"Get the v2 banner flow config for a site, including current views, categories, and any lint issues.",
|
|
1411
|
-
{ cbid:
|
|
1716
|
+
{ cbid: z6.string().describe("Site identifier (cbid).") },
|
|
1412
1717
|
(a) => client.sites.getFlow(a.cbid)
|
|
1413
1718
|
);
|
|
1414
1719
|
tool(
|
|
1415
1720
|
"edit_flow",
|
|
1416
1721
|
"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.",
|
|
1417
1722
|
{
|
|
1418
|
-
cbid:
|
|
1419
|
-
operations:
|
|
1723
|
+
cbid: z6.string().describe("Site identifier (cbid)."),
|
|
1724
|
+
operations: z6.array(z6.record(z6.unknown())).describe(
|
|
1420
1725
|
'Ordered list of ops. Each must have an "op" field: addView | removeView | addElement | setButtonTransition | addCustomCategory.'
|
|
1421
1726
|
)
|
|
1422
1727
|
},
|
|
@@ -1426,22 +1731,23 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1426
1731
|
"set_flow",
|
|
1427
1732
|
"Wholesale replace a site's v2 banner flow with a complete config (e.g. from a template). Validated server-side before it is saved.",
|
|
1428
1733
|
{
|
|
1429
|
-
cbid:
|
|
1430
|
-
config:
|
|
1734
|
+
cbid: z6.string().describe("Site identifier (cbid)."),
|
|
1735
|
+
config: z6.record(z6.unknown()).describe("A full v2 FlowConfig object ({ v:2, flow, categories, ... }).")
|
|
1431
1736
|
},
|
|
1432
1737
|
(a) => client.sites.setFlow(a.cbid, a.config)
|
|
1433
1738
|
);
|
|
1434
1739
|
registerConfigTools(tool, client);
|
|
1435
1740
|
registerPlatformTools(tool, client);
|
|
1436
1741
|
registerIntegrationTools(tool, client);
|
|
1742
|
+
registerKeyAndTagTools(tool, client);
|
|
1437
1743
|
registerRightsTools(tool, client);
|
|
1438
1744
|
registerRightsPageTools(tool, client);
|
|
1439
1745
|
tool(
|
|
1440
1746
|
"invite_member",
|
|
1441
1747
|
"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.",
|
|
1442
1748
|
{
|
|
1443
|
-
email:
|
|
1444
|
-
role:
|
|
1749
|
+
email: z6.string().describe("Email address of the person to invite."),
|
|
1750
|
+
role: z6.enum(["admin", "member", "viewer"]).describe("Role to assign: admin, member, or viewer. owner is not assignable via API key.")
|
|
1445
1751
|
},
|
|
1446
1752
|
(a) => client.members.invite(a.email, a.role)
|
|
1447
1753
|
);
|
|
@@ -1449,8 +1755,8 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1449
1755
|
"set_member_role",
|
|
1450
1756
|
"Change the role of a member in your organization. The org owner's role cannot be changed.",
|
|
1451
1757
|
{
|
|
1452
|
-
userId:
|
|
1453
|
-
role:
|
|
1758
|
+
userId: z6.string().describe("The userId of the member whose role to change."),
|
|
1759
|
+
role: z6.enum(["admin", "member", "viewer"]).describe("New role: admin, member, or viewer.")
|
|
1454
1760
|
},
|
|
1455
1761
|
(a) => client.members.setRole(a.userId, a.role)
|
|
1456
1762
|
);
|
|
@@ -1458,7 +1764,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1458
1764
|
"remove_member",
|
|
1459
1765
|
"Remove a member from your organization. The org owner cannot be removed.",
|
|
1460
1766
|
{
|
|
1461
|
-
userId:
|
|
1767
|
+
userId: z6.string().describe("The userId of the member to remove.")
|
|
1462
1768
|
},
|
|
1463
1769
|
async (a) => {
|
|
1464
1770
|
await client.members.remove(a.userId);
|
|
@@ -1469,11 +1775,11 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1469
1775
|
"create_brand_kit",
|
|
1470
1776
|
"Create a reusable brand kit (colors, logo, typography) for your organization's consent banners.",
|
|
1471
1777
|
{
|
|
1472
|
-
name:
|
|
1473
|
-
theme:
|
|
1474
|
-
content:
|
|
1475
|
-
logoUrl:
|
|
1476
|
-
customCss:
|
|
1778
|
+
name: z6.string().describe("Display name for the brand kit."),
|
|
1779
|
+
theme: z6.record(z6.unknown()).describe("Theme tokens (colors, fonts, etc.) as a JSON object."),
|
|
1780
|
+
content: z6.record(z6.unknown()).optional().describe("Optional banner copy overrides."),
|
|
1781
|
+
logoUrl: z6.string().optional().describe("Optional URL for your org logo."),
|
|
1782
|
+
customCss: z6.string().optional().describe("Optional custom CSS string to inject into the banner.")
|
|
1477
1783
|
},
|
|
1478
1784
|
(a) => client.brandKits.create({
|
|
1479
1785
|
name: a.name,
|
|
@@ -1487,7 +1793,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1487
1793
|
"delete_brand_kit",
|
|
1488
1794
|
"Delete a brand kit by id. The kit must belong to your organization (cross-org deletes are rejected).",
|
|
1489
1795
|
{
|
|
1490
|
-
id:
|
|
1796
|
+
id: z6.string().describe("The brand kit id to delete.")
|
|
1491
1797
|
},
|
|
1492
1798
|
async (a) => {
|
|
1493
1799
|
await client.brandKits.delete(a.id);
|
|
@@ -1498,25 +1804,25 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1498
1804
|
"save_preference",
|
|
1499
1805
|
"Save or update the consent preferences for an end-user (by subjectId) within your organization. purposes is a map of purpose-name \u2192 boolean.",
|
|
1500
1806
|
{
|
|
1501
|
-
subjectId:
|
|
1502
|
-
purposes:
|
|
1807
|
+
subjectId: z6.string().describe("The end-user identifier (e.g. email or internal user id)."),
|
|
1808
|
+
purposes: z6.record(z6.boolean()).describe('Map of purpose names to consent values, e.g. { "newsletter": true, "analytics": false }.')
|
|
1503
1809
|
},
|
|
1504
1810
|
(a) => client.preferences.save(a.subjectId, a.purposes)
|
|
1505
1811
|
);
|
|
1506
1812
|
tool(
|
|
1507
1813
|
"get_preference",
|
|
1508
1814
|
"One end-user\u2019s saved preferences, by subjectId. Read-only.",
|
|
1509
|
-
{ subjectId:
|
|
1815
|
+
{ subjectId: z6.string() },
|
|
1510
1816
|
(a) => client.preferences.get(a.subjectId)
|
|
1511
1817
|
);
|
|
1512
1818
|
tool(
|
|
1513
1819
|
"mint_preference_center_token",
|
|
1514
1820
|
"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.",
|
|
1515
1821
|
{
|
|
1516
|
-
cbid:
|
|
1517
|
-
email:
|
|
1518
|
-
subjectId:
|
|
1519
|
-
ttlSeconds:
|
|
1822
|
+
cbid: z6.string().describe("A site of your organisation."),
|
|
1823
|
+
email: z6.string().optional().describe("The visitor\u2019s address. Give this or subjectId, not both."),
|
|
1824
|
+
subjectId: z6.string().optional().describe("The subject id. Give this or email, not both."),
|
|
1825
|
+
ttlSeconds: z6.number().int().min(1).max(86400).optional()
|
|
1520
1826
|
},
|
|
1521
1827
|
(a) => client.preferenceCenter.mintToken({
|
|
1522
1828
|
cbid: a.cbid,
|
|
@@ -1526,15 +1832,19 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1526
1832
|
);
|
|
1527
1833
|
tool(
|
|
1528
1834
|
"issue_api_key",
|
|
1529
|
-
"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.",
|
|
1835
|
+
"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.",
|
|
1530
1836
|
{
|
|
1531
|
-
name:
|
|
1532
|
-
scopes:
|
|
1533
|
-
cbids:
|
|
1534
|
-
expiresInDays:
|
|
1535
|
-
expiresAt:
|
|
1837
|
+
name: z6.string().optional(),
|
|
1838
|
+
scopes: z6.array(z6.string()).optional(),
|
|
1839
|
+
cbids: z6.array(z6.string()).min(1).optional(),
|
|
1840
|
+
expiresInDays: z6.number().int().min(1).max(3650).optional(),
|
|
1841
|
+
expiresAt: z6.string().optional().describe("Or the exact expiry, an ISO date-time (not with expiresInDays)."),
|
|
1842
|
+
owner: z6.string().optional().describe("Who it belongs to: user:<id>, service:<name> or apikey:<prefix>. Default this key."),
|
|
1843
|
+
strictUnknownFields: z6.boolean().optional().describe("Writes with the new key refuse unknown body fields by default.")
|
|
1536
1844
|
},
|
|
1537
1845
|
(a) => client.keys.issue({
|
|
1846
|
+
...a.owner ? { owner: a.owner } : {},
|
|
1847
|
+
...a.strictUnknownFields !== void 0 ? { strictUnknownFields: a.strictUnknownFields } : {},
|
|
1538
1848
|
...a.expiresAt ? { expiresAt: a.expiresAt } : {},
|
|
1539
1849
|
...a.name ? { name: a.name } : {},
|
|
1540
1850
|
...a.scopes ? { scopes: a.scopes } : {},
|
|
@@ -1542,36 +1852,36 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1542
1852
|
...a.expiresInDays !== void 0 ? { expiresInDays: a.expiresInDays } : {}
|
|
1543
1853
|
})
|
|
1544
1854
|
);
|
|
1545
|
-
tool("revoke_api_key", "Revoke an API key by its prefix. Takes effect immediately; anything using that key stops working.", { prefix:
|
|
1855
|
+
tool("revoke_api_key", "Revoke an API key by its prefix. Takes effect immediately; anything using that key stops working.", { prefix: z6.string() }, async (a) => {
|
|
1546
1856
|
await client.keys.revoke(a.prefix);
|
|
1547
1857
|
return { revoked: a.prefix };
|
|
1548
1858
|
});
|
|
1549
1859
|
tool(
|
|
1550
1860
|
"import_cookie_declaration",
|
|
1551
1861
|
"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.",
|
|
1552
|
-
{ cbid:
|
|
1862
|
+
{ cbid: z6.string(), data: z6.string().describe("The exported file, as text (CSV or JSON).") },
|
|
1553
1863
|
(a) => client.sites.importDeclaration(a.cbid, a.data)
|
|
1554
1864
|
);
|
|
1555
1865
|
tool(
|
|
1556
1866
|
"apply_cookie_import",
|
|
1557
1867
|
"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.",
|
|
1558
|
-
{ cbid:
|
|
1868
|
+
{ cbid: z6.string(), data: z6.string().describe("The exported file, as text (CSV or JSON)."), overwrite: z6.boolean().optional() },
|
|
1559
1869
|
(a) => client.sites.applyImport(a.cbid, a.data, a.overwrite ? { overwrite: true } : void 0)
|
|
1560
1870
|
);
|
|
1561
1871
|
const declarationShape = {
|
|
1562
|
-
category:
|
|
1563
|
-
purpose:
|
|
1564
|
-
purposes:
|
|
1565
|
-
provider:
|
|
1566
|
-
expiry:
|
|
1567
|
-
domain:
|
|
1568
|
-
pattern:
|
|
1872
|
+
category: z6.string().describe("necessary, preferences, statistics, marketing, or one of the site\u2019s categories.custom ids."),
|
|
1873
|
+
purpose: z6.string().describe("What the cookie does, as visitors will read it \u2014 and the fallback for any language purposes lacks."),
|
|
1874
|
+
purposes: z6.record(z6.string(), z6.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.'),
|
|
1875
|
+
provider: z6.string().optional(),
|
|
1876
|
+
expiry: z6.string().optional().describe('e.g. "Session", "30 days", "1 year" (the banner localises these forms).'),
|
|
1877
|
+
domain: z6.string().optional(),
|
|
1878
|
+
pattern: z6.boolean().optional().describe("Treat the name as a prefix wildcard (a trailing * does the same).")
|
|
1569
1879
|
};
|
|
1570
|
-
const dryRunArg =
|
|
1880
|
+
const dryRunArg = z6.boolean().optional().describe("Store nothing: answer with the would-be declarations and a diff (added / removed / changed) to check first.");
|
|
1571
1881
|
tool(
|
|
1572
1882
|
"declare_cookie",
|
|
1573
1883
|
'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.',
|
|
1574
|
-
{ cbid:
|
|
1884
|
+
{ cbid: z6.string(), name: z6.string(), ...declarationShape, dryRun: dryRunArg },
|
|
1575
1885
|
(a) => {
|
|
1576
1886
|
const { cbid: cbid2, name, dryRun, ...rest } = a;
|
|
1577
1887
|
return client.sites.declareCookie(cbid2, name, rest, dryRun ? { dryRun: true } : void 0);
|
|
@@ -1580,7 +1890,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1580
1890
|
tool(
|
|
1581
1891
|
"declare_cookies",
|
|
1582
1892
|
"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.",
|
|
1583
|
-
{ cbid:
|
|
1893
|
+
{ cbid: z6.string(), cookies: z6.array(z6.object({ name: z6.string(), ...declarationShape })).max(500), replace: z6.boolean().optional(), dryRun: dryRunArg },
|
|
1584
1894
|
(a) => {
|
|
1585
1895
|
const o = { ...a.replace ? { replace: true } : {}, ...a.dryRun ? { dryRun: true } : {} };
|
|
1586
1896
|
return client.sites.declareCookies(a.cbid, a.cookies, Object.keys(o).length ? o : void 0);
|
|
@@ -1589,7 +1899,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1589
1899
|
tool(
|
|
1590
1900
|
"undeclare_cookie",
|
|
1591
1901
|
"Remove a cookie declaration; the scanned/observed classification applies again.",
|
|
1592
|
-
{ cbid:
|
|
1902
|
+
{ cbid: z6.string(), name: z6.string(), dryRun: dryRunArg },
|
|
1593
1903
|
async (a) => {
|
|
1594
1904
|
if (a.dryRun) return client.sites.undeclareCookie(a.cbid, a.name, { dryRun: true });
|
|
1595
1905
|
await client.sites.undeclareCookie(a.cbid, a.name);
|
|
@@ -1600,11 +1910,11 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1600
1910
|
"retire_cookie",
|
|
1601
1911
|
'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.',
|
|
1602
1912
|
{
|
|
1603
|
-
cbid:
|
|
1604
|
-
name:
|
|
1605
|
-
renamedTo:
|
|
1606
|
-
note:
|
|
1607
|
-
dryRun:
|
|
1913
|
+
cbid: z6.string(),
|
|
1914
|
+
name: z6.string(),
|
|
1915
|
+
renamedTo: z6.string().max(256).optional().describe("The cookie\u2019s new name, if it was renamed."),
|
|
1916
|
+
note: z6.string().max(1e3).optional(),
|
|
1917
|
+
dryRun: z6.boolean().optional().describe("Store nothing: answer with the would-be retirement and list to check first.")
|
|
1608
1918
|
},
|
|
1609
1919
|
(a) => {
|
|
1610
1920
|
const input = { ...a.renamedTo ? { renamedTo: a.renamedTo } : {}, ...a.note ? { note: a.note } : {} };
|
|
@@ -1614,7 +1924,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1614
1924
|
tool(
|
|
1615
1925
|
"unretire_cookie",
|
|
1616
1926
|
"Un-retire a cookie: it is listed again everywhere.",
|
|
1617
|
-
{ cbid:
|
|
1927
|
+
{ cbid: z6.string(), name: z6.string(), dryRun: z6.boolean().optional().describe("Store nothing: answer with what the list would be.") },
|
|
1618
1928
|
async (a) => {
|
|
1619
1929
|
if (a.dryRun) return client.sites.unretireCookie(a.cbid, a.name, { dryRun: true });
|
|
1620
1930
|
await client.sites.unretireCookie(a.cbid, a.name);
|
|
@@ -1623,41 +1933,74 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1623
1933
|
);
|
|
1624
1934
|
tool(
|
|
1625
1935
|
"list_cookie_presets",
|
|
1626
|
-
"Declaration presets for the platforms a site is built on (atlas, forumulate, chatly, cookiemunch,
|
|
1627
|
-
{ cbid:
|
|
1936
|
+
"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.",
|
|
1937
|
+
{ cbid: z6.string() },
|
|
1628
1938
|
(a) => client.sites.cookiePresets(a.cbid)
|
|
1629
1939
|
);
|
|
1630
1940
|
tool(
|
|
1631
1941
|
"apply_cookie_preset",
|
|
1632
|
-
"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.",
|
|
1942
|
+
"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.",
|
|
1633
1943
|
{
|
|
1634
|
-
cbid:
|
|
1635
|
-
vendor:
|
|
1636
|
-
frontendApiHost:
|
|
1637
|
-
crossSubdomainCookies:
|
|
1638
|
-
publicId:
|
|
1639
|
-
dragging:
|
|
1640
|
-
category:
|
|
1641
|
-
cookieDomain:
|
|
1642
|
-
cookieDays:
|
|
1944
|
+
cbid: z6.string(),
|
|
1945
|
+
vendor: z6.enum(["atlas", "forumulate", "chatly", "cookiemunch", "referalli", "firstpromoter", "partnerstack", "tapfiliate", "impact", "referally"]).describe("referally is the deprecated old name of referalli."),
|
|
1946
|
+
frontendApiHost: z6.string().optional().describe("Atlas: your frontend API host, e.g. auth.example.com."),
|
|
1947
|
+
crossSubdomainCookies: z6.boolean().optional().describe("Atlas: default true \u2014 the cookies live on the parent domain."),
|
|
1948
|
+
publicId: z6.string().optional().describe("Chatly: the channel public id (ch_web_\u2026)."),
|
|
1949
|
+
dragging: z6.boolean().optional().describe("Chatly: the launcher can be dragged (adds the drag-position key)."),
|
|
1950
|
+
category: z6.string().optional().describe("Chatly: the category for its keys (default necessary). Referral and affiliate presets: default the site's referrals category, else marketing."),
|
|
1951
|
+
cookieDomain: z6.string().optional().describe("Referral and affiliate presets: the domain their script sets its cookies on, e.g. .example.com. Default the site domain."),
|
|
1952
|
+
cookieDays: z6.number().int().min(1).max(400).optional().describe("Referral and affiliate presets: your program's cookie window, 1 to 400 days."),
|
|
1953
|
+
legacyName: z6.boolean().optional().describe("referalli: default true, also declare referally_ctx (the pre-rename copy aff.js still writes)."),
|
|
1954
|
+
campaignId: z6.string().optional().describe("impact: your program id; declares IR_<campaignId> too."),
|
|
1643
1955
|
dryRun: dryRunArg
|
|
1644
1956
|
},
|
|
1645
1957
|
(a) => {
|
|
1646
1958
|
const params = {};
|
|
1647
|
-
for (const k of ["frontendApiHost", "crossSubdomainCookies", "publicId", "dragging", "category", "cookieDomain", "cookieDays"]) if (a[k] !== void 0) params[k] = a[k];
|
|
1959
|
+
for (const k of ["frontendApiHost", "crossSubdomainCookies", "publicId", "dragging", "category", "cookieDomain", "cookieDays", "legacyName", "campaignId"]) if (a[k] !== void 0) params[k] = a[k];
|
|
1648
1960
|
return client.sites.applyCookiePreset(a.cbid, a.vendor, params, a.dryRun ? { dryRun: true } : void 0);
|
|
1649
1961
|
}
|
|
1650
1962
|
);
|
|
1963
|
+
tool(
|
|
1964
|
+
"import_cookie_manifest",
|
|
1965
|
+
'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.',
|
|
1966
|
+
{
|
|
1967
|
+
cbid: z6.string(),
|
|
1968
|
+
url: z6.string().optional().describe("An https:// embed manifest URL."),
|
|
1969
|
+
manifest: z6.record(z6.unknown()).optional().describe("The manifest document itself, instead of a URL."),
|
|
1970
|
+
params: z6.record(z6.string()).optional().describe('Values for the manifest\u2019s {placeholders}, e.g. {"publicId": "ch_web_1"}.'),
|
|
1971
|
+
dryRun: dryRunArg
|
|
1972
|
+
},
|
|
1973
|
+
(a) => {
|
|
1974
|
+
const input = a.url !== void 0 ? { url: a.url } : { manifest: a.manifest };
|
|
1975
|
+
return client.sites.importCookieManifest(a.cbid, { ...input, ...a.params ? { params: a.params } : {} }, a.dryRun ? { dryRun: true } : void 0);
|
|
1976
|
+
}
|
|
1977
|
+
);
|
|
1978
|
+
tool(
|
|
1979
|
+
"list_cookie_suggestions",
|
|
1980
|
+
"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.",
|
|
1981
|
+
{ cbid: z6.string() },
|
|
1982
|
+
(a) => client.sites.cookieSuggestions(a.cbid)
|
|
1983
|
+
);
|
|
1984
|
+
tool(
|
|
1985
|
+
"declare_cookie_suggestions",
|
|
1986
|
+
"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.",
|
|
1987
|
+
{ cbid: z6.string(), names: z6.array(z6.string()).optional(), presets: z6.boolean().optional(), dryRun: dryRunArg },
|
|
1988
|
+
(a) => client.sites.declareCookieSuggestions(
|
|
1989
|
+
a.cbid,
|
|
1990
|
+
{ ...a.names ? { names: a.names } : {}, ...a.presets !== void 0 ? { presets: a.presets } : {} },
|
|
1991
|
+
a.dryRun ? { dryRun: true } : void 0
|
|
1992
|
+
)
|
|
1993
|
+
);
|
|
1651
1994
|
tool(
|
|
1652
1995
|
"remove_cookie_preset",
|
|
1653
|
-
"Remove every declaration a vendor preset made on this site.",
|
|
1654
|
-
{ cbid:
|
|
1996
|
+
"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.",
|
|
1997
|
+
{ cbid: z6.string(), vendor: z6.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 },
|
|
1655
1998
|
(a) => client.sites.removeCookiePreset(a.cbid, a.vendor, a.dryRun ? { dryRun: true } : void 0)
|
|
1656
1999
|
);
|
|
1657
2000
|
tool(
|
|
1658
2001
|
"delete_observed_cookie",
|
|
1659
2002
|
"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.",
|
|
1660
|
-
{ cbid:
|
|
2003
|
+
{ cbid: z6.string(), name: z6.string(), dryRun: dryRunArg },
|
|
1661
2004
|
async (a) => {
|
|
1662
2005
|
if (a.dryRun) return client.sites.deleteObservedCookie(a.cbid, a.name, { dryRun: true });
|
|
1663
2006
|
await client.sites.deleteObservedCookie(a.cbid, a.name);
|
|
@@ -1668,9 +2011,9 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1668
2011
|
"purge_observed_cookies",
|
|
1669
2012
|
"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.",
|
|
1670
2013
|
{
|
|
1671
|
-
cbid:
|
|
1672
|
-
since:
|
|
1673
|
-
until:
|
|
2014
|
+
cbid: z6.string(),
|
|
2015
|
+
since: z6.union([z6.string(), z6.number()]).describe("ISO-8601 time or epoch milliseconds."),
|
|
2016
|
+
until: z6.union([z6.string(), z6.number()]).optional().describe("Optional end of the window (exclusive)."),
|
|
1674
2017
|
dryRun: dryRunArg
|
|
1675
2018
|
},
|
|
1676
2019
|
(a) => client.sites.purgeObservedCookies(
|
|
@@ -1682,24 +2025,24 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1682
2025
|
tool(
|
|
1683
2026
|
"get_blocked_pages",
|
|
1684
2027
|
"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.",
|
|
1685
|
-
{ cbid:
|
|
2028
|
+
{ cbid: z6.string() },
|
|
1686
2029
|
(a) => client.sites.blocked(a.cbid)
|
|
1687
2030
|
);
|
|
1688
2031
|
tool(
|
|
1689
2032
|
"roll_api_key",
|
|
1690
2033
|
"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.",
|
|
1691
|
-
{ prefix:
|
|
2034
|
+
{ prefix: z6.string() },
|
|
1692
2035
|
(a) => client.keys.roll(a.prefix)
|
|
1693
2036
|
);
|
|
1694
2037
|
tool(
|
|
1695
2038
|
"update_api_key",
|
|
1696
2039
|
"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.",
|
|
1697
2040
|
{
|
|
1698
|
-
prefix:
|
|
1699
|
-
name:
|
|
1700
|
-
scopes:
|
|
1701
|
-
cbids:
|
|
1702
|
-
expiresAt:
|
|
2041
|
+
prefix: z6.string(),
|
|
2042
|
+
name: z6.string().optional(),
|
|
2043
|
+
scopes: z6.array(z6.string()).optional(),
|
|
2044
|
+
cbids: z6.array(z6.string()).min(1).optional(),
|
|
2045
|
+
expiresAt: z6.string().nullable().optional().describe("A new expiry (ISO date-time), or null to remove it.")
|
|
1703
2046
|
},
|
|
1704
2047
|
(a) => client.keys.update(a.prefix, {
|
|
1705
2048
|
...a.expiresAt !== void 0 ? { expiresAt: a.expiresAt } : {},
|
|
@@ -1712,7 +2055,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1712
2055
|
tool(
|
|
1713
2056
|
"update_org",
|
|
1714
2057
|
"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.",
|
|
1715
|
-
{ name:
|
|
2058
|
+
{ name: z6.string().min(1).optional(), logoUrl: z6.string().nullable().optional() },
|
|
1716
2059
|
(a) => client.org.update({
|
|
1717
2060
|
...a.name !== void 0 ? { name: a.name } : {},
|
|
1718
2061
|
...a.logoUrl !== void 0 ? { logoUrl: a.logoUrl } : {}
|
|
@@ -1728,20 +2071,20 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1728
2071
|
"set_mail_provider",
|
|
1729
2072
|
"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).",
|
|
1730
2073
|
{
|
|
1731
|
-
provider:
|
|
1732
|
-
fromEmail:
|
|
1733
|
-
fromName:
|
|
1734
|
-
replyTo:
|
|
1735
|
-
secret:
|
|
1736
|
-
ses:
|
|
1737
|
-
smtp:
|
|
2074
|
+
provider: z6.enum(["brevo", "sendgrid", "postmark", "resend", "ses", "smtp"]),
|
|
2075
|
+
fromEmail: z6.string().describe("An address on a domain your provider has verified."),
|
|
2076
|
+
fromName: z6.string().max(100).nullable().optional(),
|
|
2077
|
+
replyTo: z6.string().nullable().optional(),
|
|
2078
|
+
secret: z6.string().optional().describe("API key (Brevo, SendGrid, Resend), server token (Postmark), secret access key (SES) or SMTP password. Write-only."),
|
|
2079
|
+
ses: z6.object({ region: z6.string(), accessKeyId: z6.string() }).optional().describe("Required for ses."),
|
|
2080
|
+
smtp: z6.object({ host: z6.string(), port: z6.union([z6.literal(25), z6.literal(465), z6.literal(587), z6.literal(2525)]), security: z6.enum(["tls", "starttls"]), username: z6.string() }).optional().describe("Required for smtp. TLS is always required.")
|
|
1738
2081
|
},
|
|
1739
2082
|
(a) => client.org.mailProvider.set(a)
|
|
1740
2083
|
);
|
|
1741
2084
|
tool(
|
|
1742
2085
|
"test_mail_provider",
|
|
1743
2086
|
"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.",
|
|
1744
|
-
{ to:
|
|
2087
|
+
{ to: z6.string().optional().describe("Recipient. Default: the reply-to, else the from address.") },
|
|
1745
2088
|
(a) => client.org.mailProvider.test(a.to)
|
|
1746
2089
|
);
|
|
1747
2090
|
tool(
|
|
@@ -1763,10 +2106,10 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1763
2106
|
"set_org_controller",
|
|
1764
2107
|
"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.",
|
|
1765
2108
|
{
|
|
1766
|
-
legalName:
|
|
1767
|
-
contactEmail:
|
|
1768
|
-
address:
|
|
1769
|
-
dpoContact:
|
|
2109
|
+
legalName: z6.string().describe("Required: the legal name of the data controller."),
|
|
2110
|
+
contactEmail: z6.string().optional().describe("Where people reach the controller about their data."),
|
|
2111
|
+
address: z6.string().optional(),
|
|
2112
|
+
dpoContact: z6.string().optional().describe("The Data Protection Officer: a name, an email address, or both.")
|
|
1770
2113
|
},
|
|
1771
2114
|
(a) => client.org.controller.set({
|
|
1772
2115
|
legalName: a.legalName,
|
|
@@ -1786,11 +2129,11 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1786
2129
|
);
|
|
1787
2130
|
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.";
|
|
1788
2131
|
const captchaInput = {
|
|
1789
|
-
mode:
|
|
1790
|
-
provider:
|
|
1791
|
-
siteKey:
|
|
1792
|
-
secret:
|
|
1793
|
-
minScore:
|
|
2132
|
+
mode: z6.enum(["own", "off"]).describe(`own: your own captcha provider keys (recommended). off: no captcha. ${CAPTCHA_OFF}`),
|
|
2133
|
+
provider: z6.enum(["turnstile", "hcaptcha", "recaptcha_v2", "recaptcha_v3"]).optional().describe("Required for own."),
|
|
2134
|
+
siteKey: z6.string().optional().describe("Required for own: the public site key. List your rights-page hostnames on it at the provider."),
|
|
2135
|
+
secret: z6.string().optional().describe("The provider secret key. Write-only; never returned. Omit to keep the stored one (same provider)."),
|
|
2136
|
+
minScore: z6.number().min(0.1).max(0.9).optional().describe("reCAPTCHA v3 only. Default 0.5.")
|
|
1794
2137
|
};
|
|
1795
2138
|
const captchaBody = (a) => ({
|
|
1796
2139
|
mode: a.mode,
|
|
@@ -1802,37 +2145,37 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1802
2145
|
tool(
|
|
1803
2146
|
"get_consent_sync_secret",
|
|
1804
2147
|
"Whether hosted consent sync is set up for a site: `configured`, `secretLast4`, `createdAt`. Never returns the secret. Read-only.",
|
|
1805
|
-
{ cbid:
|
|
2148
|
+
{ cbid: z6.string() },
|
|
1806
2149
|
(a) => client.consentSyncSecret.get(a.cbid)
|
|
1807
2150
|
);
|
|
1808
2151
|
tool(
|
|
1809
2152
|
"rotate_consent_sync_secret",
|
|
1810
2153
|
"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.",
|
|
1811
|
-
{ cbid:
|
|
2154
|
+
{ cbid: z6.string() },
|
|
1812
2155
|
(a) => client.consentSyncSecret.rotate(a.cbid)
|
|
1813
2156
|
);
|
|
1814
2157
|
tool(
|
|
1815
2158
|
"remove_consent_sync_secret",
|
|
1816
2159
|
"Remove a site\u2019s consent-sync secret: hosted consent sync stops until a new one is minted. Needs sites:write and consent:write.",
|
|
1817
|
-
{ cbid:
|
|
2160
|
+
{ cbid: z6.string() },
|
|
1818
2161
|
(a) => client.consentSyncSecret.remove(a.cbid)
|
|
1819
2162
|
);
|
|
1820
2163
|
tool(
|
|
1821
2164
|
"get_rights_captcha",
|
|
1822
2165
|
"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.",
|
|
1823
|
-
{ cbid:
|
|
2166
|
+
{ cbid: z6.string() },
|
|
1824
2167
|
(a) => client.rightsCaptcha.get(a.cbid)
|
|
1825
2168
|
);
|
|
1826
2169
|
tool(
|
|
1827
2170
|
"set_rights_captcha",
|
|
1828
2171
|
`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.`,
|
|
1829
|
-
{ cbid:
|
|
2172
|
+
{ cbid: z6.string(), ...captchaInput },
|
|
1830
2173
|
(a) => client.rightsCaptcha.set(a.cbid, captchaBody(a))
|
|
1831
2174
|
);
|
|
1832
2175
|
tool(
|
|
1833
2176
|
"remove_rights_captcha",
|
|
1834
2177
|
"Remove a site\u2019s own captcha setting: it inherits the organisation default again (or off). Returns the setting now in force.",
|
|
1835
|
-
{ cbid:
|
|
2178
|
+
{ cbid: z6.string() },
|
|
1836
2179
|
(a) => client.rightsCaptcha.remove(a.cbid)
|
|
1837
2180
|
);
|
|
1838
2181
|
tool(
|
|
@@ -1855,15 +2198,15 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1855
2198
|
);
|
|
1856
2199
|
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.";
|
|
1857
2200
|
const identityInput = {
|
|
1858
|
-
type:
|
|
1859
|
-
issuer:
|
|
1860
|
-
jwksUrl:
|
|
1861
|
-
audience:
|
|
1862
|
-
authorizedParties:
|
|
1863
|
-
emailClaim:
|
|
1864
|
-
emailVerifiedClaim:
|
|
1865
|
-
sessionCookieName:
|
|
1866
|
-
trustEmailClaim:
|
|
2201
|
+
type: z6.enum(["clerk", "atlas", "oidc_jwt"]).describe("clerk, atlas (Clerk-shaped), or oidc_jwt (any issuer that signs session JWTs with a published JWKS)."),
|
|
2202
|
+
issuer: z6.string().describe("https URL exactly as in the token\u2019s iss (Clerk: your Frontend API URL)."),
|
|
2203
|
+
jwksUrl: z6.string().optional().describe("Required for oidc_jwt; clerk/atlas default to <issuer>/.well-known/jwks.json."),
|
|
2204
|
+
audience: z6.string().optional().describe("Expected aud. For oidc_jwt an audience or authorizedParties is required (a shared issuer mints tokens for every app)."),
|
|
2205
|
+
authorizedParties: z6.array(z6.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."),
|
|
2206
|
+
emailClaim: z6.string().optional().describe("Default email."),
|
|
2207
|
+
emailVerifiedClaim: z6.string().optional().describe("Default email_verified; must be exactly true."),
|
|
2208
|
+
sessionCookieName: z6.string().optional().describe("Default __session: the cookie the hosted page on your custom domain reads."),
|
|
2209
|
+
trustEmailClaim: z6.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.")
|
|
1867
2210
|
};
|
|
1868
2211
|
const identityBody = (a) => {
|
|
1869
2212
|
const out = { type: a.type, issuer: a.issuer };
|
|
@@ -1873,19 +2216,19 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1873
2216
|
tool(
|
|
1874
2217
|
"get_rights_identity",
|
|
1875
2218
|
"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.",
|
|
1876
|
-
{ cbid:
|
|
2219
|
+
{ cbid: z6.string() },
|
|
1877
2220
|
(a) => client.rightsIdentity.get(a.cbid)
|
|
1878
2221
|
);
|
|
1879
2222
|
tool(
|
|
1880
2223
|
"set_rights_identity",
|
|
1881
2224
|
`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.`,
|
|
1882
|
-
{ cbid:
|
|
2225
|
+
{ cbid: z6.string(), ...identityInput },
|
|
1883
2226
|
(a) => client.rightsIdentity.set(a.cbid, identityBody(a))
|
|
1884
2227
|
);
|
|
1885
2228
|
tool(
|
|
1886
2229
|
"remove_rights_identity",
|
|
1887
2230
|
"Remove a site\u2019s own sign-in provider: it inherits the organisation default again (or none). Returns the setting now in force.",
|
|
1888
|
-
{ cbid:
|
|
2231
|
+
{ cbid: z6.string() },
|
|
1889
2232
|
(a) => client.rightsIdentity.remove(a.cbid)
|
|
1890
2233
|
);
|
|
1891
2234
|
tool(
|
|
@@ -1909,22 +2252,40 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1909
2252
|
tool(
|
|
1910
2253
|
"get_audit_log",
|
|
1911
2254
|
"The organisation\u2019s audit log, newest first: administrative changes made in the dashboard or through the API, and who made them. Read-only.",
|
|
1912
|
-
{ limit:
|
|
1913
|
-
(a) => client.audit(a.limit)
|
|
2255
|
+
{ limit: z6.number().int().min(1).max(500).optional(), actor: z6.string().optional().describe('"self" for this key\u2019s own rows (allowed for scoped keys), or one actor id.') },
|
|
2256
|
+
(a) => client.audit(a.limit, a.actor ? { actor: a.actor } : void 0)
|
|
2257
|
+
);
|
|
2258
|
+
tool(
|
|
2259
|
+
"get_audit_sink",
|
|
2260
|
+
"Where the organisation\u2019s audit log is streamed (as CloudEvents) and how the last delivery went. Never the secret. Read-only.",
|
|
2261
|
+
{},
|
|
2262
|
+
() => client.auditSink.get()
|
|
2263
|
+
);
|
|
2264
|
+
tool(
|
|
2265
|
+
"set_audit_sink",
|
|
2266
|
+
"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.",
|
|
2267
|
+
{ type: z6.literal("webhook"), url: z6.string(), secret: z6.string().optional().describe("16\u2013256 characters; omitted: one is generated.") },
|
|
2268
|
+
(a) => client.auditSink.set({ type: "webhook", url: a.url, ...a.secret ? { secret: a.secret } : {} })
|
|
2269
|
+
);
|
|
2270
|
+
tool(
|
|
2271
|
+
"remove_audit_sink",
|
|
2272
|
+
"Stop streaming the audit log. Audited.",
|
|
2273
|
+
{},
|
|
2274
|
+
() => client.auditSink.remove()
|
|
1914
2275
|
);
|
|
1915
2276
|
tool(
|
|
1916
2277
|
"upload_asset",
|
|
1917
2278
|
"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.",
|
|
1918
2279
|
{
|
|
1919
|
-
data:
|
|
1920
|
-
contentType:
|
|
2280
|
+
data: z6.string(),
|
|
2281
|
+
contentType: z6.enum(["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"])
|
|
1921
2282
|
},
|
|
1922
2283
|
(a) => client.assets.upload({ data: a.data, contentType: a.contentType })
|
|
1923
2284
|
);
|
|
1924
2285
|
tool(
|
|
1925
2286
|
"delete_asset",
|
|
1926
2287
|
"Delete a stored image by its URL (or file name). Only your own organisation\u2019s images can be named.",
|
|
1927
|
-
{ url:
|
|
2288
|
+
{ url: z6.string().describe("The URL upload_asset returned, or just its file name.") },
|
|
1928
2289
|
async (a) => {
|
|
1929
2290
|
await client.assets.delete(a.url);
|
|
1930
2291
|
return { deleted: a.url };
|
|
@@ -1939,18 +2300,18 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1939
2300
|
tool(
|
|
1940
2301
|
"get_customer",
|
|
1941
2302
|
"One child org: its controller details and usage. Read-only.",
|
|
1942
|
-
{ id:
|
|
2303
|
+
{ id: z6.string() },
|
|
1943
2304
|
(a) => client.reseller.get(a.id)
|
|
1944
2305
|
);
|
|
1945
2306
|
tool(
|
|
1946
2307
|
"provision_customer",
|
|
1947
2308
|
"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.",
|
|
1948
2309
|
{
|
|
1949
|
-
name:
|
|
1950
|
-
ownerEmail:
|
|
1951
|
-
delegatedAccess:
|
|
1952
|
-
mintKey:
|
|
1953
|
-
keyScopes:
|
|
2310
|
+
name: z6.string(),
|
|
2311
|
+
ownerEmail: z6.string().optional(),
|
|
2312
|
+
delegatedAccess: z6.boolean().optional().describe("Whether this reseller may act inside the child."),
|
|
2313
|
+
mintKey: z6.boolean().optional(),
|
|
2314
|
+
keyScopes: z6.array(z6.string()).optional()
|
|
1954
2315
|
},
|
|
1955
2316
|
(a) => client.reseller.create({
|
|
1956
2317
|
name: a.name,
|
|
@@ -1964,10 +2325,10 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1964
2325
|
"update_customer",
|
|
1965
2326
|
"Change a child org\u2019s status, delegated access or DSAR routing. `dsarRouting: null` clears the override.",
|
|
1966
2327
|
{
|
|
1967
|
-
id:
|
|
1968
|
-
status:
|
|
1969
|
-
delegatedAccess:
|
|
1970
|
-
dsarRouting:
|
|
2328
|
+
id: z6.string(),
|
|
2329
|
+
status: z6.enum(["active", "suspended"]).optional(),
|
|
2330
|
+
delegatedAccess: z6.boolean().optional(),
|
|
2331
|
+
dsarRouting: z6.enum(["reseller", "child"]).nullable().optional()
|
|
1971
2332
|
},
|
|
1972
2333
|
(a) => client.reseller.update(a.id, {
|
|
1973
2334
|
...a.status ? { status: a.status } : {},
|
|
@@ -1978,7 +2339,7 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1978
2339
|
tool(
|
|
1979
2340
|
"suspend_customer",
|
|
1980
2341
|
"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.)",
|
|
1981
|
-
{ id:
|
|
2342
|
+
{ id: z6.string() },
|
|
1982
2343
|
async (a) => {
|
|
1983
2344
|
await client.reseller.deprovision(a.id);
|
|
1984
2345
|
return { suspended: a.id };
|
|
@@ -1987,78 +2348,78 @@ ${JSON.stringify(r, null, 2)}` : r;
|
|
|
1987
2348
|
tool(
|
|
1988
2349
|
"list_customer_keys",
|
|
1989
2350
|
"A child org's API key prefixes. Never the secrets. Read-only.",
|
|
1990
|
-
{ id:
|
|
2351
|
+
{ id: z6.string() },
|
|
1991
2352
|
(a) => client.reseller.listKeys(a.id)
|
|
1992
2353
|
);
|
|
1993
2354
|
tool(
|
|
1994
2355
|
"issue_customer_key",
|
|
1995
2356
|
"Mint an API key for a child org. The secret is returned once. Prefer scopes and a property lock over a full-access key.",
|
|
1996
|
-
{ id:
|
|
2357
|
+
{ id: z6.string(), name: z6.string().optional(), scopes: z6.array(z6.string()).optional(), cbids: z6.array(z6.string()).min(1).optional() },
|
|
1997
2358
|
(a) => client.reseller.mintKey(a.id, {
|
|
1998
2359
|
...a.name ? { name: a.name } : {},
|
|
1999
2360
|
...a.scopes ? { scopes: a.scopes } : {},
|
|
2000
2361
|
...a.cbids ? { cbids: a.cbids } : {}
|
|
2001
2362
|
})
|
|
2002
2363
|
);
|
|
2003
|
-
tool("revoke_customer_key", "Revoke a child org's API key by prefix. Takes effect immediately.", { id:
|
|
2364
|
+
tool("revoke_customer_key", "Revoke a child org's API key by prefix. Takes effect immediately.", { id: z6.string(), prefix: z6.string() }, async (a) => {
|
|
2004
2365
|
await client.reseller.revokeKey(a.id, a.prefix);
|
|
2005
2366
|
return { revoked: a.prefix };
|
|
2006
2367
|
});
|
|
2007
2368
|
tool(
|
|
2008
2369
|
"erase_subject_data",
|
|
2009
2370
|
"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.",
|
|
2010
|
-
{ cbid:
|
|
2371
|
+
{ cbid: z6.string(), stamp: z6.string() },
|
|
2011
2372
|
(a) => client.consent.eraseSubject(a.cbid, a.stamp)
|
|
2012
2373
|
);
|
|
2013
2374
|
tool(
|
|
2014
2375
|
"export_subject_data",
|
|
2015
2376
|
"Export a data subject's consent records (GDPR access/portability).",
|
|
2016
|
-
{ cbid:
|
|
2377
|
+
{ cbid: z6.string(), stamp: z6.string() },
|
|
2017
2378
|
(a) => client.consent.exportSubject(a.cbid, a.stamp)
|
|
2018
2379
|
);
|
|
2019
2380
|
tool("list_banners", "List reusable banner designs in your org.", {}, () => client.banners.list());
|
|
2020
2381
|
tool(
|
|
2021
2382
|
"create_banner",
|
|
2022
2383
|
"Create a reusable banner design.",
|
|
2023
|
-
{ name:
|
|
2384
|
+
{ name: z6.string(), json: z6.record(z6.unknown()).describe("A v2 BannerConfig.") },
|
|
2024
2385
|
(a) => client.banners.create({ name: a.name, json: a.json })
|
|
2025
2386
|
);
|
|
2026
|
-
tool("get_banner", "Get a banner design by id.", { id:
|
|
2387
|
+
tool("get_banner", "Get a banner design by id.", { id: z6.string() }, (a) => client.banners.get(a.id));
|
|
2027
2388
|
tool(
|
|
2028
2389
|
"update_banner",
|
|
2029
2390
|
"Update a banner design (name and/or config).",
|
|
2030
|
-
{ id:
|
|
2391
|
+
{ id: z6.string(), name: z6.string().optional(), json: z6.record(z6.unknown()).optional() },
|
|
2031
2392
|
(a) => client.banners.update(a.id, {
|
|
2032
2393
|
...a.name !== void 0 ? { name: a.name } : {},
|
|
2033
2394
|
...a.json !== void 0 ? { json: a.json } : {}
|
|
2034
2395
|
})
|
|
2035
2396
|
);
|
|
2036
|
-
tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id:
|
|
2397
|
+
tool("delete_banner", "Delete a banner design (fails if assigned to sites).", { id: z6.string() }, async (a) => {
|
|
2037
2398
|
await client.banners.delete(a.id);
|
|
2038
2399
|
return { ok: true };
|
|
2039
2400
|
});
|
|
2040
2401
|
tool(
|
|
2041
2402
|
"get_banner_assignments",
|
|
2042
2403
|
"The sites (cbids) a banner design is currently assigned to. Read-only.",
|
|
2043
|
-
{ id:
|
|
2404
|
+
{ id: z6.string() },
|
|
2044
2405
|
(a) => client.banners.assignments(a.id)
|
|
2045
2406
|
);
|
|
2046
2407
|
tool(
|
|
2047
2408
|
"assign_banner",
|
|
2048
2409
|
"Set which sites (cbids) use a banner design.",
|
|
2049
|
-
{ id:
|
|
2410
|
+
{ id: z6.string(), cbids: z6.array(z6.string()) },
|
|
2050
2411
|
(a) => client.banners.setAssignments(a.id, a.cbids)
|
|
2051
2412
|
);
|
|
2052
2413
|
tool(
|
|
2053
2414
|
"publish_banner",
|
|
2054
2415
|
"Publish a design live to all its assigned sites.",
|
|
2055
|
-
{ id:
|
|
2416
|
+
{ id: z6.string() },
|
|
2056
2417
|
(a) => client.banners.publish(a.id)
|
|
2057
2418
|
);
|
|
2058
2419
|
}
|
|
2059
2420
|
|
|
2060
2421
|
// src/index.ts
|
|
2061
|
-
var MCP_VERSION = "0.
|
|
2422
|
+
var MCP_VERSION = "0.7.0";
|
|
2062
2423
|
function createCookieMunchMcp(opts) {
|
|
2063
2424
|
const client = opts.client ?? createCookieMunch({ apiKey: opts.apiKey, baseUrl: opts.baseUrl, userAgent: opts.userAgent ?? `cookiemunch-mcp/${MCP_VERSION}` });
|
|
2064
2425
|
const server = new McpServer({ name: "cookiemunch", version: "1.0.0" });
|
|
@@ -2071,4 +2432,4 @@ export {
|
|
|
2071
2432
|
MCP_VERSION,
|
|
2072
2433
|
createCookieMunchMcp
|
|
2073
2434
|
};
|
|
2074
|
-
//# sourceMappingURL=chunk-
|
|
2435
|
+
//# sourceMappingURL=chunk-QCLUFJZ5.js.map
|