@instavar/mcp-server 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +39 -14
  2. package/dist/index.js +635 -316
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,11 +1,283 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/paired-announcement.ts
4
+ import { z } from "zod";
5
+
6
+ // src/announcement-source.ts
7
+ var htmlEscape = (value) => value.replace(
8
+ /[&<>"']/g,
9
+ (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]
10
+ );
11
+ function announcementFiles(project) {
12
+ const copy = project.copy;
13
+ const files = {};
14
+ const addFile = (name, contents) => {
15
+ files[name] = contents;
16
+ };
17
+ const css = `@font-face{font-family:AnnouncementDisplay;src:url(__ANNOUNCEMENT_DISPLAY_FONT__);font-weight:100 900;}
18
+ @font-face{font-family:AnnouncementBody;src:url(__ANNOUNCEMENT_BODY_FONT__);font-weight:400;}
19
+ *{box-sizing:border-box}body{margin:0;background:#f4f0e7;color:#202d29}
20
+ #announcement-root{position:relative;width:1280px;height:720px;overflow:hidden;background:#f4f0e7;color:#202d29}
21
+ .clip{position:absolute;inset:0}
22
+ h1,p{margin:0;overflow-wrap:anywhere}h1{position:absolute;left:88px;top:110px;width:1040px;font-family:AnnouncementDisplay;font-size:${copy.title.length > 45 ? 48 : copy.title.length > 24 ? 64 : 92}px;font-weight:650;line-height:1.08;letter-spacing:-3px}
23
+ #body{position:absolute;left:92px;top:370px;width:1050px;font-family:AnnouncementBody;font-size:${copy.body.length > 60 ? 28 : 34}px;font-weight:400;line-height:1.4}
24
+ #cta{position:absolute;left:92px;top:535px;width:1050px;font-family:AnnouncementBody;font-size:${copy.cta.length > 30 ? 26 : 30}px;font-weight:400;line-height:1.4;color:#345a45}
25
+ #rule{position:absolute;left:92px;top:620px;width:1096px;height:4px;background:#345a45;transform-origin:left center}
26
+ html,body,*{text-rendering:auto}
27
+ `;
28
+ addFile("style.css", css);
29
+ const manifest = {
30
+ framework: project.framework,
31
+ copy,
32
+ width: 1280,
33
+ height: 720,
34
+ fps: 30,
35
+ durationSeconds: 10
36
+ };
37
+ addFile("manifest.json", JSON.stringify(manifest, null, 2) + "\n");
38
+ if (project.framework === "hyperframes") {
39
+ addFile(
40
+ "hyperframes.json",
41
+ JSON.stringify({ authoringSkill: "general-video" })
42
+ );
43
+ addFile(
44
+ "index.html",
45
+ `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Instavar announcement card</title><link rel="stylesheet" href="style.css"><script src="gsap.min.js"></script></head><body>
46
+ <div id="announcement-root" data-composition-id="announcement" data-start="0" data-width="1280" data-height="720" data-duration="10">
47
+ <section id="announcement-scene" class="clip" data-start="0" data-duration="10" data-track-index="0">
48
+ <h1 id="title">${htmlEscape(copy.title)}</h1><p id="body">${htmlEscape(
49
+ copy.body
50
+ )}</p><p id="cta">${htmlEscape(
51
+ copy.cta
52
+ )}</p><div id="rule"></div></section></div>
53
+ <script>
54
+ // Adapted from HyperFrames registry staggered-fade-up: three whole text blocks.
55
+ const tl=gsap.timeline({paused:true});
56
+ tl.fromTo('#title',{opacity:0,y:22},{opacity:1,y:0,duration:0.6,ease:'power3.out'},0.25);
57
+ tl.fromTo('#body',{opacity:0,y:22},{opacity:1,y:0,duration:0.6,ease:'power3.out'},2);
58
+ tl.fromTo('#cta',{opacity:0,y:22},{opacity:1,y:0,duration:0.6,ease:'power3.out'},5);
59
+ tl.fromTo('#rule',{scaleX:0},{scaleX:1,duration:9.5,ease:'none'},0.25);
60
+ window.__timelines['announcement']=tl;
61
+ </script></body></html>`
62
+ );
63
+ addFile(
64
+ "index.motion.json",
65
+ JSON.stringify(
66
+ {
67
+ duration: 10,
68
+ assertions: [
69
+ { kind: "appearsBy", selector: "#title", bySec: 1 },
70
+ { kind: "before", a: "#title", b: "#body" },
71
+ { kind: "before", a: "#body", b: "#cta" },
72
+ { kind: "staysInFrame", selector: "#title" },
73
+ { kind: "staysInFrame", selector: "#body" },
74
+ { kind: "staysInFrame", selector: "#cta" }
75
+ ]
76
+ },
77
+ null,
78
+ 2
79
+ )
80
+ );
81
+ } else {
82
+ addFile(
83
+ "index.jsx",
84
+ `import React from 'react';
85
+ import {Composition,registerRoot,useCurrentFrame,useVideoConfig} from 'remotion';
86
+ const css=${JSON.stringify(css)};
87
+ const copy=${JSON.stringify(copy)};
88
+ const ease=t=>1-Math.pow(1-t,4);
89
+ const reveal=(t,start)=>{const p=ease(Math.max(0,Math.min(1,(t-start)/0.6)));return {opacity:p,transform:'translateY('+(22*(1-p))+'px)'}};
90
+ function Announcement(){const frame=useCurrentFrame();const {fps}=useVideoConfig();const t=frame/fps;return <div id="announcement-root"><style>{css}</style><section className="clip"><h1 id="title" style={reveal(t,0.25)}>{copy.title}</h1><p id="body" style={reveal(t,2)}>{copy.body}</p><p id="cta" style={reveal(t,5)}>{copy.cta}</p><div id="rule" style={{transform:'scaleX('+Math.max(0,Math.min(1,(t-0.25)/9.5))+')'}}/></section></div>}
91
+ registerRoot(()=> <Composition id="Announcement" component={Announcement} width={1280} height={720} fps={30} durationInFrames={300}/>);
92
+ `
93
+ );
94
+ }
95
+ const dependencies = project.framework === "hyperframes" ? { hyperframes: "0.8.38", gsap: "3.14.2" } : {
96
+ remotion: "4.0.496",
97
+ "@remotion/cli": "4.0.496",
98
+ react: "19.1.0",
99
+ "react-dom": "19.1.0"
100
+ };
101
+ addFile(
102
+ "package.json",
103
+ JSON.stringify(
104
+ {
105
+ private: true,
106
+ type: "module",
107
+ scripts: {
108
+ setup: "node setup.mjs",
109
+ preview: project.framework === "hyperframes" ? "hyperframes preview" : "remotion studio index.jsx",
110
+ render: project.framework === "hyperframes" ? "hyperframes render --fps 30 --output video.mp4" : "remotion render index.jsx Announcement video.mp4"
111
+ },
112
+ dependencies
113
+ },
114
+ null,
115
+ 2
116
+ )
117
+ );
118
+ addFile(
119
+ "setup.mjs",
120
+ `import {readFile,writeFile,copyFile} from 'node:fs/promises';
121
+ const fonts = [['__ANNOUNCEMENT_DISPLAY_FONT__','Fraunces-Variable.ttf'],['__ANNOUNCEMENT_BODY_FONT__','Inter-Regular.ttf']];
122
+ for (const [marker,name] of fonts) {
123
+ const response = await fetch('https://instavar.com/fonts/'+name);
124
+ if (!response.ok) throw new Error('Font download failed: '+name);
125
+ const uri = 'data:font/ttf;base64,'+Buffer.from(await response.arrayBuffer()).toString('base64');
126
+ for (const file of ${JSON.stringify(
127
+ project.framework === "hyperframes" ? ["style.css"] : ["style.css", "index.jsx"]
128
+ )}) {
129
+ const source = await readFile(file,'utf8');
130
+ await writeFile(file,source.replaceAll(marker,uri));
131
+ }
132
+ }
133
+ ${project.framework === "hyperframes" ? "await copyFile('node_modules/gsap/dist/gsap.min.js','gsap.min.js');" : ""}
134
+ `
135
+ );
136
+ return files;
137
+ }
138
+
139
+ // src/paired-announcement.ts
140
+ var framework = z.enum(["remotion", "hyperframes"]);
141
+ var text = (max) => z.string().trim().min(1).max(max);
142
+ var copyFields = { title: text(70), body: text(100), cta: text(40) };
143
+ var copySchema = z.object(copyFields).strict();
144
+ var announcementProjectSchema = z.object({
145
+ templateId: z.literal("announcement-card-v1"),
146
+ framework,
147
+ revision: z.number().int().min(1).max(Number.MAX_SAFE_INTEGER - 1),
148
+ copy: copySchema
149
+ }).strict();
150
+ var pairedAnnouncementInput = {
151
+ framework: z.enum(["remotion", "hyperframes", "no-preference"]).optional().describe(
152
+ "Only supply an explicit user choice. Omit for an ambiguous request or to inherit the existing project framework."
153
+ ),
154
+ copy: copySchema.optional().describe("Accepted copy for a new project only."),
155
+ project: announcementProjectSchema.optional().describe(
156
+ "The latest project document returned by this tool. Caller-held, not a saved hosted project."
157
+ ),
158
+ expectedRevision: z.number().int().min(1).optional().describe(
159
+ "Required with project. Must match its revision. This checks the supplied document, not a server-side stored version."
160
+ ),
161
+ edits: copySchema.partial().optional().describe(
162
+ "Explicit copy edits to apply before switching. Other source or timeline edits cannot be preserved."
163
+ )
164
+ };
165
+ var inputSchema = z.object(pairedAnnouncementInput).strict();
166
+ var PAIRED_ANNOUNCEMENT_CAPABILITY = {
167
+ templateId: "announcement-card-v1",
168
+ frameworks: ["remotion", "hyperframes"],
169
+ tool: "prepare_announcement",
170
+ dimensions: { width: 1280, height: 720, fps: 30, durationSeconds: 10 },
171
+ scope: "One silent announcement card. Returns portable source and caller-held copy state; does not save or render. Only title, body and action survive switching."
172
+ };
173
+ var PAIRED_ANNOUNCEMENT_INSTRUCTIONS = "For the paired announcement-card-v1 or a HyperFrames announcement request, use prepare_announcement. Never infer a framework from creative wording. Omit framework unless the user explicitly chooses one or says no preference. If needs-selection, ask the user. Continue with the latest returned project and expectedRevision; apply edits through edits before switching. Keep the returned project document for later calls. Never describe this caller-held document as a saved hosted project. The existing VideoSpec catalogue remains Remotion-only.";
174
+ function prepareAnnouncement(raw) {
175
+ const input = inputSchema.parse(raw);
176
+ const inputReceipt = {
177
+ contract: "paired-announcement-input-receipt/v1",
178
+ stage: "validated-input",
179
+ normalizedInput: JSON.parse(JSON.stringify(input))
180
+ };
181
+ const old = input.project;
182
+ if (old && input.expectedRevision !== old.revision)
183
+ throw new Error(
184
+ "Supply the latest project document and its matching expectedRevision."
185
+ );
186
+ if (old && input.copy)
187
+ throw new Error(
188
+ "Use edits to change existing copy; do not replace it with new-project copy."
189
+ );
190
+ if (!old && (input.edits || input.expectedRevision !== void 0))
191
+ throw new Error("Edits and expectedRevision require an existing project.");
192
+ const selected = input.framework === "remotion" || input.framework === "hyperframes" ? input.framework : old?.framework ?? (input.framework === "no-preference" ? "remotion" : void 0);
193
+ if (!selected)
194
+ return {
195
+ inputReceipt,
196
+ status: "needs-selection",
197
+ options: ["remotion", "hyperframes", "no-preference"],
198
+ message: "Which framework would you like: Remotion, HyperFrames, or no preference? No source was generated."
199
+ };
200
+ if (!old && !input.copy)
201
+ return {
202
+ inputReceipt,
203
+ status: "needs-copy",
204
+ framework: selected,
205
+ required: ["title", "body", "cta"]
206
+ };
207
+ const copy = copySchema.parse({
208
+ ...old?.copy ?? input.copy,
209
+ ...input.edits
210
+ });
211
+ const changed = old && Object.keys(copyFields).some(
212
+ (key) => copy[key] !== old.copy[key]
213
+ );
214
+ const project = {
215
+ templateId: "announcement-card-v1",
216
+ framework: selected,
217
+ revision: (old?.revision ?? 1) + (changed ? 1 : 0),
218
+ copy
219
+ };
220
+ return {
221
+ inputReceipt,
222
+ status: "ready",
223
+ reason: input.framework && input.framework !== "no-preference" ? "explicit" : old ? "existing-project" : "visible-default",
224
+ project,
225
+ files: {
226
+ ...announcementFiles(project),
227
+ "announcement.project.json": JSON.stringify(project, null, 2) + "\n"
228
+ },
229
+ commands: [
230
+ "npm install",
231
+ "npm run setup",
232
+ ...selected === "hyperframes" ? ["npx hyperframes check --samples 15 --strict"] : [],
233
+ "npm run preview",
234
+ "npm run render"
235
+ ],
236
+ instructions: "Save these files in a new directory. Install and setup download pinned dependencies and Instavar fonts; setup embeds fonts locally before rendering. Review preview frames before rendering. Keep announcement.project.json as the copy source of truth. This tool has not written files, saved a hosted project or rendered video. Regenerating source preserves only the three copy fields, not custom source edits."
237
+ };
238
+ }
239
+ function registerPairedAnnouncement(server) {
240
+ server.registerTool(
241
+ "prepare_announcement",
242
+ {
243
+ title: "Prepare an announcement in Remotion or HyperFrames",
244
+ description: "Prepare one paired announcement-card-v1 template, continue its caller-held project, edit copy or switch frameworks. Returns source files for local rendering. " + PAIRED_ANNOUNCEMENT_INSTRUCTIONS,
245
+ inputSchema: pairedAnnouncementInput,
246
+ annotations: {
247
+ readOnlyHint: true,
248
+ destructiveHint: false,
249
+ openWorldHint: false
250
+ },
251
+ _meta: { securitySchemes: [{ type: "noauth" }] }
252
+ },
253
+ async (args) => {
254
+ try {
255
+ const result2 = prepareAnnouncement(args);
256
+ return {
257
+ structuredContent: result2,
258
+ content: [{ type: "text", text: JSON.stringify(result2) }]
259
+ };
260
+ } catch (error) {
261
+ return {
262
+ isError: true,
263
+ content: [
264
+ {
265
+ type: "text",
266
+ text: error instanceof Error ? error.message : "Invalid announcement input"
267
+ }
268
+ ]
269
+ };
270
+ }
271
+ }
272
+ );
273
+ }
274
+
3
275
  // src/index.ts
4
276
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
277
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
278
 
7
279
  // src/creative-guides.ts
8
- import { z } from "zod";
280
+ import { z as z2 } from "zod";
9
281
 
10
282
  // src/creative-guides.generated.ts
11
283
  var CREATIVE_GUIDES = [
@@ -36,7 +308,7 @@ var CREATIVE_GUIDES = [
36
308
  ];
37
309
 
38
310
  // src/creative-guides.ts
39
- var creativeGuideIdSchema = z.enum([
311
+ var creativeGuideIdSchema = z2.enum([
40
312
  "visual-copy",
41
313
  "carousel-stories",
42
314
  "visual-design",
@@ -97,7 +369,7 @@ function registerCreativeGuides(server) {
97
369
  }
98
370
 
99
371
  // src/public-templates.ts
100
- import { z as z2 } from "zod";
372
+ import { z as z3 } from "zod";
101
373
  var TEMPLATE_REPOSITORY = "https://github.com/instavar/remotion-templates";
102
374
  var TEMPLATE_ENDPOINT = "https://instavar.com/api/mcp/templates";
103
375
  var VOICE_STUDIO_URL = "https://instavar.com/voice";
@@ -108,8 +380,8 @@ var templateIds = [
108
380
  "social-remix",
109
381
  "finance-brief"
110
382
  ];
111
- var templateIdSchema = z2.enum(templateIds);
112
- var aspectSchema = z2.enum(["9:16", "4:5", "1:1"]);
383
+ var templateIdSchema = z3.enum(templateIds);
384
+ var aspectSchema = z3.enum(["9:16", "4:5", "1:1"]);
113
385
  var templates = [
114
386
  {
115
387
  id: "qa-ad",
@@ -373,6 +645,7 @@ function scaffoldVideoSpec(args) {
373
645
  }
374
646
  function registerPublicTemplateTools(server) {
375
647
  registerCreativeGuides(server);
648
+ registerPairedAnnouncement(server);
376
649
  server.registerTool(
377
650
  "get_capabilities",
378
651
  {
@@ -388,6 +661,7 @@ function registerPublicTemplateTools(server) {
388
661
  repository: TEMPLATE_REPOSITORY,
389
662
  endpoint: TEMPLATE_ENDPOINT,
390
663
  creativeGuides: CREATIVE_GUIDE_INDEX,
664
+ pairedAnnouncement: PAIRED_ANNOUNCEMENT_CAPABILITY,
391
665
  localFeatures: [
392
666
  "template discovery",
393
667
  "VideoSpec schema and examples",
@@ -486,9 +760,9 @@ ${template?.description ?? ""}`
486
760
  description: "Return a deterministic VideoSpec skeleton without writing files.",
487
761
  inputSchema: {
488
762
  templateId: templateIdSchema,
489
- title: z2.string().min(1).max(160),
763
+ title: z3.string().min(1).max(160),
490
764
  aspect: aspectSchema.default("9:16"),
491
- mediaSrc: z2.string().min(1).max(500).optional()
765
+ mediaSrc: z3.string().min(1).max(500).optional()
492
766
  },
493
767
  annotations
494
768
  },
@@ -506,7 +780,7 @@ ${template?.description ?? ""}`
506
780
  title: "Get local render instructions",
507
781
  description: "Return clone, install, validate, preview, and render commands.",
508
782
  inputSchema: {
509
- client: z2.enum(["codex", "claude-code", "manual"]).default("manual")
783
+ client: z3.enum(["codex", "claude-code", "manual"]).default("manual")
510
784
  },
511
785
  annotations
512
786
  },
@@ -533,12 +807,12 @@ ${template?.description ?? ""}`
533
807
  {
534
808
  title: "Diagnose render error",
535
809
  description: "Classify a local validation or render error.",
536
- inputSchema: { errorText: z2.string().min(1).max(1e4) },
810
+ inputSchema: { errorText: z3.string().min(1).max(1e4) },
537
811
  annotations
538
812
  },
539
813
  async ({ errorText }) => {
540
- const text = errorText.toLowerCase();
541
- const code = text.includes("enoent") || text.includes("not found") ? "missing-file" : text.includes("ffmpeg") || text.includes("codec") ? "media-codec" : text.includes("schema") || text.includes("invalid") || text.includes("zod") ? "invalid-video-spec" : text.includes("chrome") || text.includes("browser") ? "browser-runtime" : "unknown-render-error";
814
+ const text2 = errorText.toLowerCase();
815
+ const code = text2.includes("enoent") || text2.includes("not found") ? "missing-file" : text2.includes("ffmpeg") || text2.includes("codec") ? "media-codec" : text2.includes("schema") || text2.includes("invalid") || text2.includes("zod") ? "invalid-video-spec" : text2.includes("chrome") || text2.includes("browser") ? "browser-runtime" : "unknown-render-error";
542
816
  return result(
543
817
  {
544
818
  code,
@@ -551,7 +825,7 @@ ${template?.description ?? ""}`
551
825
  }
552
826
 
553
827
  // src/tools.ts
554
- import { z as z5 } from "zod";
828
+ import { z as z6 } from "zod";
555
829
 
556
830
  // src/http.ts
557
831
  import { randomUUID } from "crypto";
@@ -597,11 +871,11 @@ function requestFailure(error) {
597
871
  return error instanceof Error ? error.message : String(error);
598
872
  }
599
873
  async function parse(res) {
600
- const text = await res.text();
874
+ const text2 = await res.text();
601
875
  try {
602
- return JSON.parse(text);
876
+ return JSON.parse(text2);
603
877
  } catch {
604
- return text;
878
+ return text2;
605
879
  }
606
880
  }
607
881
  async function apiGet(path) {
@@ -625,7 +899,9 @@ async function apiPost(path, payload) {
625
899
  method: "POST",
626
900
  headers: {
627
901
  [API_KEY_HEADER]: getApiKey(),
628
- "content-type": "application/json"
902
+ "content-type": "application/json",
903
+ // Labels person-consent declarations made through MCP (surface only).
904
+ "x-instavar-client": "mcp"
629
905
  },
630
906
  body: JSON.stringify(clean),
631
907
  signal: AbortSignal.timeout(API_REQUEST_TIMEOUT_MS)
@@ -675,7 +951,7 @@ async function runTool(fn) {
675
951
  }
676
952
 
677
953
  // src/brief-schema.ts
678
- import { z as z3 } from "zod";
954
+ import { z as z4 } from "zod";
679
955
  var PUBLISH_TARGETS = [
680
956
  "linkedin",
681
957
  "x",
@@ -707,16 +983,16 @@ var REFERENCE_ROLES = [
707
983
  "environment",
708
984
  "style"
709
985
  ];
710
- var optionalDirectionText = z3.string().trim().min(1).max(500).optional();
711
- var visualDirectionSchema = z3.object({
986
+ var optionalDirectionText = z4.string().trim().min(1).max(500).optional();
987
+ var visualDirectionSchema = z4.object({
712
988
  communicationJob: optionalDirectionText,
713
989
  emotionalTarget: optionalDirectionText,
714
- attentionPath: z3.object({
990
+ attentionPath: z4.object({
715
991
  first: optionalDirectionText,
716
992
  next: optionalDirectionText,
717
993
  proof: optionalDirectionText
718
994
  }).optional(),
719
- visualLanguage: z3.object({
995
+ visualLanguage: z4.object({
720
996
  space: optionalDirectionText,
721
997
  line: optionalDirectionText,
722
998
  shape: optionalDirectionText,
@@ -725,24 +1001,24 @@ var visualDirectionSchema = z3.object({
725
1001
  movement: optionalDirectionText,
726
1002
  rhythm: optionalDirectionText
727
1003
  }).optional(),
728
- camera: z3.object({
1004
+ camera: z4.object({
729
1005
  shotSize: optionalDirectionText,
730
1006
  angle: optionalDirectionText,
731
1007
  movement: optionalDirectionText,
732
1008
  lens: optionalDirectionText
733
1009
  }).optional()
734
1010
  });
735
- var generationContractSchema = z3.object({
736
- globalInvariants: z3.array(z3.string().trim().min(1).max(300)).max(20).optional(),
737
- shotDelta: z3.string().trim().min(1).max(500).optional(),
738
- referenceBindings: z3.array(
739
- z3.object({
740
- assetId: z3.string().trim().min(1).max(200),
741
- roles: z3.array(z3.enum(REFERENCE_ROLES)).min(1).max(7)
1011
+ var generationContractSchema = z4.object({
1012
+ globalInvariants: z4.array(z4.string().trim().min(1).max(300)).max(20).optional(),
1013
+ shotDelta: z4.string().trim().min(1).max(500).optional(),
1014
+ referenceBindings: z4.array(
1015
+ z4.object({
1016
+ assetId: z4.string().trim().min(1).max(200),
1017
+ roles: z4.array(z4.enum(REFERENCE_ROLES)).min(1).max(7)
742
1018
  })
743
1019
  ).max(20).optional(),
744
- prohibitedChanges: z3.array(z3.string().trim().min(1).max(300)).max(20).optional(),
745
- reviewCriteria: z3.array(z3.string().trim().min(1).max(300)).max(20).optional()
1020
+ prohibitedChanges: z4.array(z4.string().trim().min(1).max(300)).max(20).optional(),
1021
+ reviewCriteria: z4.array(z4.string().trim().min(1).max(300)).max(20).optional()
746
1022
  });
747
1023
  var REGION_NAMES = [
748
1024
  "background",
@@ -759,55 +1035,55 @@ var ASSET_ROLES = [
759
1035
  "lower-third",
760
1036
  "diagram-node"
761
1037
  ];
762
- var assetSlotStyleSchema = z3.object({
763
- opacity: z3.number().min(0).max(1).optional(),
764
- fit: z3.enum(["cover", "contain"]).optional(),
765
- z: z3.number().optional()
1038
+ var assetSlotStyleSchema = z4.object({
1039
+ opacity: z4.number().min(0).max(1).optional(),
1040
+ fit: z4.enum(["cover", "contain"]).optional(),
1041
+ z: z4.number().optional()
766
1042
  }).strict();
767
- var assetSlotSchema = z3.object({
768
- id: z3.string().min(1),
769
- sceneId: z3.string().min(1).optional(),
770
- region: z3.enum(REGION_NAMES),
771
- role: z3.enum(ASSET_ROLES),
772
- kind: z3.enum(["image", "video"]),
773
- source: z3.enum(["auto", "stock", "generate"]),
774
- intent: z3.string(),
1043
+ var assetSlotSchema = z4.object({
1044
+ id: z4.string().min(1),
1045
+ sceneId: z4.string().min(1).optional(),
1046
+ region: z4.enum(REGION_NAMES),
1047
+ role: z4.enum(ASSET_ROLES),
1048
+ kind: z4.enum(["image", "video"]),
1049
+ source: z4.enum(["auto", "stock", "generate"]),
1050
+ intent: z4.string(),
775
1051
  style: assetSlotStyleSchema.optional(),
776
- timing: z3.object({
777
- fromPct: z3.number().min(0).max(1).optional(),
778
- toPct: z3.number().min(0).max(1).optional()
1052
+ timing: z4.object({
1053
+ fromPct: z4.number().min(0).max(1).optional(),
1054
+ toPct: z4.number().min(0).max(1).optional()
779
1055
  }).strict().optional(),
780
- url: z3.string().url().optional()
1056
+ url: z4.string().url().optional()
781
1057
  }).strict();
782
- var briefStepSchema = z3.object({
783
- label: z3.string(),
784
- latex: z3.string().optional(),
785
- explanation: z3.string().optional()
1058
+ var briefStepSchema = z4.object({
1059
+ label: z4.string(),
1060
+ latex: z4.string().optional(),
1061
+ explanation: z4.string().optional()
786
1062
  });
787
- var briefAudioLayerSchema = z3.object({
788
- id: z3.string().min(1),
789
- src: z3.string().url(),
790
- startFrame: z3.number().int().nonnegative().default(0),
791
- durationInFrames: z3.number().int().positive().optional(),
792
- volume: z3.number().min(0).max(1).default(1),
793
- fadeFrames: z3.number().int().nonnegative().default(0),
794
- role: z3.enum(["music", "foley", "transition", "effect"])
1063
+ var briefAudioLayerSchema = z4.object({
1064
+ id: z4.string().min(1),
1065
+ src: z4.string().url(),
1066
+ startFrame: z4.number().int().nonnegative().default(0),
1067
+ durationInFrames: z4.number().int().positive().optional(),
1068
+ volume: z4.number().min(0).max(1).default(1),
1069
+ fadeFrames: z4.number().int().nonnegative().default(0),
1070
+ role: z4.enum(["music", "foley", "transition", "effect"])
795
1071
  });
796
- var protectedRegionEffectSchema = z3.object({
797
- id: z3.string().min(1).max(80),
798
- kind: z3.literal("border-glint"),
799
- coordinateSpace: z3.literal("output-frame-v1").default("output-frame-v1"),
800
- region: z3.object({
801
- leftPercent: z3.number().min(0).max(100),
802
- topPercent: z3.number().min(0).max(100),
803
- widthPercent: z3.number().positive().max(100),
804
- heightPercent: z3.number().positive().max(100)
1072
+ var protectedRegionEffectSchema = z4.object({
1073
+ id: z4.string().min(1).max(80),
1074
+ kind: z4.literal("border-glint"),
1075
+ coordinateSpace: z4.literal("output-frame-v1").default("output-frame-v1"),
1076
+ region: z4.object({
1077
+ leftPercent: z4.number().min(0).max(100),
1078
+ topPercent: z4.number().min(0).max(100),
1079
+ widthPercent: z4.number().positive().max(100),
1080
+ heightPercent: z4.number().positive().max(100)
805
1081
  }),
806
- startFrame: z3.number().int().nonnegative().default(0),
807
- endFrame: z3.number().int().positive(),
808
- speedUpFrame: z3.number().int().nonnegative().optional(),
809
- color: z3.string().max(64).default("#ffffff"),
810
- thicknessPercent: z3.number().positive().max(20).default(3)
1082
+ startFrame: z4.number().int().nonnegative().default(0),
1083
+ endFrame: z4.number().int().positive(),
1084
+ speedUpFrame: z4.number().int().nonnegative().optional(),
1085
+ color: z4.string().max(64).default("#ffffff"),
1086
+ thicknessPercent: z4.number().positive().max(20).default(3)
811
1087
  }).superRefine((effect2, context) => {
812
1088
  if (effect2.region.leftPercent + effect2.region.widthPercent > 100) {
813
1089
  context.addIssue({
@@ -838,13 +1114,13 @@ var protectedRegionEffectSchema = z3.object({
838
1114
  });
839
1115
  }
840
1116
  });
841
- var beatVisualRequestSchema = z3.object({
842
- intent: z3.string().trim().min(1).optional(),
843
- media: z3.enum(["still", "motion"]).default("still"),
844
- source: z3.enum(["auto", "stock", "generate"]).default("auto")
1117
+ var beatVisualRequestSchema = z4.object({
1118
+ intent: z4.string().trim().min(1).optional(),
1119
+ media: z4.enum(["still", "motion"]).default("still"),
1120
+ source: z4.enum(["auto", "stock", "generate"]).default("auto")
845
1121
  }).strict();
846
- var briefSceneSchema = z3.object({
847
- type: z3.enum([
1122
+ var briefSceneSchema = z4.object({
1123
+ type: z4.enum([
848
1124
  "hero",
849
1125
  "points",
850
1126
  "equation",
@@ -867,156 +1143,188 @@ var briefSceneSchema = z3.object({
867
1143
  "image-window",
868
1144
  "custom"
869
1145
  ]),
870
- durationInFrames: z3.number().optional(),
871
- narrationText: z3.string().optional(),
1146
+ layoutPreset: z4.literal("dark-cafe-announcement").optional().describe(
1147
+ "Built-in portrait coffee illustration with title, subtitle body and text CTA. Use only on a custom scene after the user selects this design. No generated assets."
1148
+ ),
1149
+ durationInFrames: z4.number().optional(),
1150
+ narrationText: z4.string().optional(),
872
1151
  visualResolution: beatVisualRequestSchema.optional(),
873
- title: z3.string().optional(),
874
- subtitle: z3.string().optional(),
875
- text: z3.string().optional(),
876
- points: z3.array(z3.string()).optional(),
877
- latex: z3.string().optional(),
878
- value: z3.union([z3.string(), z3.number()]).optional(),
879
- max: z3.number().optional(),
880
- label: z3.string().optional(),
881
- unit: z3.string().optional(),
882
- prefix: z3.string().optional(),
883
- suffix: z3.string().optional(),
884
- decimals: z3.number().optional(),
885
- color: z3.string().optional(),
886
- tone: z3.string().optional(),
887
- iconKey: z3.string().optional(),
888
- stepNumber: z3.number().optional(),
889
- totalSteps: z3.number().optional(),
890
- items: z3.array(z3.object({ label: z3.string(), value: z3.number() })).optional(),
891
- src: z3.string().optional(),
892
- caption: z3.string().optional(),
1152
+ title: z4.string().optional(),
1153
+ subtitle: z4.string().optional(),
1154
+ text: z4.string().optional(),
1155
+ points: z4.array(z4.string()).optional(),
1156
+ latex: z4.string().optional(),
1157
+ value: z4.union([z4.string(), z4.number()]).optional(),
1158
+ max: z4.number().optional(),
1159
+ label: z4.string().optional(),
1160
+ unit: z4.string().optional(),
1161
+ prefix: z4.string().optional(),
1162
+ suffix: z4.string().optional(),
1163
+ decimals: z4.number().optional(),
1164
+ color: z4.string().optional(),
1165
+ tone: z4.string().optional(),
1166
+ iconKey: z4.string().optional(),
1167
+ stepNumber: z4.number().optional(),
1168
+ totalSteps: z4.number().optional(),
1169
+ items: z4.array(z4.object({ label: z4.string(), value: z4.number() })).optional(),
1170
+ src: z4.string().optional(),
1171
+ caption: z4.string().optional(),
893
1172
  // A-roll generation (video-window scenes): source "generate" triggers
894
1173
  // flag-gated WaveSpeed image/video gen server-side from generatePrompt;
895
1174
  // "url" (default) uses src as-is. Kept in sync with the app's
896
1175
  // briefSceneSchema - see the parity test in the app suite.
897
- source: z3.enum(["url", "generate"]).optional(),
898
- generatePrompt: z3.string().optional(),
1176
+ source: z4.enum(["url", "generate"]).optional(),
1177
+ generatePrompt: z4.string().optional(),
899
1178
  generationContract: generationContractSchema.optional(),
900
- trimStartSeconds: z3.number().nonnegative().optional(),
901
- trimEndSeconds: z3.number().positive().optional(),
902
- playbackRate: z3.number().min(0.25).max(8).optional(),
903
- objectFit: z3.enum(["cover", "contain"]).optional(),
904
- objectPosition: z3.string().optional(),
905
- scaleFrom: z3.number().min(0.5).max(2).optional(),
906
- scaleTo: z3.number().min(0.5).max(2).optional(),
907
- panFromX: z3.number().min(-50).max(50).optional(),
908
- panToX: z3.number().min(-50).max(50).optional(),
909
- panFromY: z3.number().min(-50).max(50).optional(),
910
- panToY: z3.number().min(-50).max(50).optional(),
911
- routeFrom: z3.string().optional(),
912
- routeTo: z3.string().optional(),
913
- routeLabel: z3.string().optional(),
914
- overlayKind: z3.enum(["none", "hook", "stage", "end-card"]).optional(),
915
- overlayPosition: z3.enum(["center", "top", "bottom"]).optional(),
916
- accentColor: z3.string().optional(),
917
- overlayBackgroundColor: z3.string().optional(),
918
- cutFlash: z3.boolean().optional(),
919
- muted: z3.boolean().optional(),
920
- protectedRegionEffects: z3.array(protectedRegionEffectSchema).max(4).optional(),
921
- flashAtFrame: z3.number().int().nonnegative().optional(),
922
- flashDurationFrames: z3.number().int().positive().max(15).optional()
1179
+ trimStartSeconds: z4.number().nonnegative().optional(),
1180
+ trimEndSeconds: z4.number().positive().optional(),
1181
+ playbackRate: z4.number().min(0.25).max(8).optional(),
1182
+ objectFit: z4.enum(["cover", "contain"]).optional(),
1183
+ objectPosition: z4.string().optional(),
1184
+ scaleFrom: z4.number().min(0.5).max(2).optional(),
1185
+ scaleTo: z4.number().min(0.5).max(2).optional(),
1186
+ panFromX: z4.number().min(-50).max(50).optional(),
1187
+ panToX: z4.number().min(-50).max(50).optional(),
1188
+ panFromY: z4.number().min(-50).max(50).optional(),
1189
+ panToY: z4.number().min(-50).max(50).optional(),
1190
+ routeFrom: z4.string().optional(),
1191
+ routeTo: z4.string().optional(),
1192
+ routeLabel: z4.string().optional(),
1193
+ overlayKind: z4.enum(["none", "hook", "stage", "end-card"]).optional(),
1194
+ overlayPosition: z4.enum(["center", "top", "bottom"]).optional(),
1195
+ accentColor: z4.string().optional(),
1196
+ overlayBackgroundColor: z4.string().optional(),
1197
+ cutFlash: z4.boolean().optional(),
1198
+ muted: z4.boolean().optional(),
1199
+ protectedRegionEffects: z4.array(protectedRegionEffectSchema).max(4).optional(),
1200
+ flashAtFrame: z4.number().int().nonnegative().optional(),
1201
+ flashDurationFrames: z4.number().int().positive().max(15).optional()
923
1202
  });
924
- var directionsBriefSchema = z3.object({
925
- subtitle: z3.string().optional(),
926
- unitLabel: z3.string().optional(),
927
- distanceTimeChip: z3.string().optional(),
928
- clips: z3.array(
929
- z3.object({
930
- src: z3.string(),
931
- trimStartSeconds: z3.number().optional(),
932
- trimEndSeconds: z3.number(),
933
- speed: z3.number().optional(),
934
- mirrorFlip: z3.boolean().optional()
1203
+ var directionsBriefSchema = z4.object({
1204
+ subtitle: z4.string().optional(),
1205
+ unitLabel: z4.string().optional(),
1206
+ distanceTimeChip: z4.string().optional(),
1207
+ clips: z4.array(
1208
+ z4.object({
1209
+ src: z4.string(),
1210
+ trimStartSeconds: z4.number().optional(),
1211
+ trimEndSeconds: z4.number(),
1212
+ speed: z4.number().optional(),
1213
+ mirrorFlip: z4.boolean().optional()
935
1214
  })
936
1215
  ).min(1),
937
- cues: z3.array(
938
- z3.object({
939
- atSeconds: z3.number(),
940
- text: z3.string(),
941
- arrow: z3.enum(["left", "right", "forward"]).optional(),
942
- step: z3.number().optional()
1216
+ cues: z4.array(
1217
+ z4.object({
1218
+ atSeconds: z4.number(),
1219
+ text: z4.string(),
1220
+ arrow: z4.enum(["left", "right", "forward"]).optional(),
1221
+ step: z4.number().optional()
943
1222
  })
944
1223
  ),
945
- outro: z3.object({
946
- heading: z3.string().optional(),
947
- body: z3.array(z3.string()).optional(),
948
- seconds: z3.number().optional()
1224
+ outro: z4.object({
1225
+ heading: z4.string().optional(),
1226
+ body: z4.array(z4.string()).optional(),
1227
+ seconds: z4.number().optional()
949
1228
  }).optional(),
950
- music: z3.object({
951
- perSegment: z3.array(
952
- z3.object({
953
- src: z3.string(),
954
- clipIndexStart: z3.number().optional(),
955
- hotOffsetSeconds: z3.number().optional(),
956
- volume: z3.number().optional()
1229
+ music: z4.object({
1230
+ perSegment: z4.array(
1231
+ z4.object({
1232
+ src: z4.string(),
1233
+ clipIndexStart: z4.number().optional(),
1234
+ hotOffsetSeconds: z4.number().optional(),
1235
+ volume: z4.number().optional()
957
1236
  })
958
1237
  ).optional(),
959
- crossfadeSeconds: z3.number().optional()
1238
+ crossfadeSeconds: z4.number().optional()
960
1239
  }).optional()
961
1240
  });
1241
+ var PERSON_CONSENT_WORDING_VERSION = "2026-10-19.1";
1242
+ var PERSON_CONSENT_WORDING = "I have permission from everyone shown, and no one shown is under 18 unless I am their parent or guardian.";
1243
+ var personConsentSchema = z4.object({
1244
+ confirmed: z4.literal(true).describe("Must be true: the caller confirms the declaration below."),
1245
+ wordingVersion: z4.string().describe(
1246
+ `Version of the declaration the caller confirmed. Current: ${PERSON_CONSENT_WORDING_VERSION}.`
1247
+ )
1248
+ }).strict().describe(
1249
+ `Required when the brief uses an uploaded image or video. Ask the user to confirm: "${PERSON_CONSENT_WORDING}"`
1250
+ );
1251
+ var LIKENESS_WARNING_WORDING_VERSION = "2026-10-19.1";
1252
+ var LIKENESS_WARNING_WORDING = "This photo seems to show someone other than you. Only continue if you have their permission.";
1253
+ var LIKENESS_MINOR_WARNING_WORDING_VERSION = "2026-10-19.1";
1254
+ var LIKENESS_MINOR_WARNING_WORDING = "This may show someone under 18. Continue only if you are their parent or guardian, or have their parent or guardian's permission.";
1255
+ var likenessAcknowledgementSchema = z4.object({
1256
+ confirmed: z4.literal(true).describe("Must be true: the user accepted the warning below."),
1257
+ kind: z4.enum(["other_person", "guardian"]).optional().describe(
1258
+ `Which warning was accepted. "other_person" (default): "${LIKENESS_WARNING_WORDING}" "guardian": "${LIKENESS_MINOR_WARNING_WORDING}"`
1259
+ ),
1260
+ wordingVersion: z4.string().describe(
1261
+ `Version of the warning accepted. Current: other_person ${LIKENESS_WARNING_WORDING_VERSION}, guardian ${LIKENESS_MINOR_WARNING_WORDING_VERSION}.`
1262
+ )
1263
+ }).strict().describe(
1264
+ "Optional. Send only after the user has seen and accepted the warning. Without it, a job that animates an uploaded photo of someone other than the account holder stops with likeness_acknowledgement_required, or likeness_guardian_confirmation_required when the person may be under 18."
1265
+ );
962
1266
  var createBriefShape = {
963
- title: z3.string().min(1).max(120).describe("Short title (max 120 chars)"),
964
- script: z3.string().min(1).describe("Full narration script (sent to TTS)"),
965
- caption: z3.string().min(1).describe("Social caption with hooks, hashtags, CTA"),
966
- publishTarget: z3.enum(PUBLISH_TARGETS).describe("Target social platform"),
967
- publishTargets: z3.array(z3.enum(PUBLISH_TARGETS)).max(9).optional().describe("All allowed social destinations for this video"),
968
- objective: z3.enum(BRIEF_OBJECTIVES).describe("Content objective (drives composition routing)"),
969
- targetDurationSeconds: z3.number().int().min(5).max(600).optional().describe("Requested final video duration in seconds"),
970
- narrationMode: z3.enum(["tts", "off"]).optional().describe("Disable synthesized narration for source-audio or silent work"),
971
- lessonTitle: z3.string().optional().describe("Display title rendered inside the video"),
1267
+ title: z4.string().min(1).max(120).describe("Short title (max 120 chars)"),
1268
+ script: z4.string().min(1).describe("Full narration script (sent to TTS)"),
1269
+ caption: z4.string().min(1).describe("Social caption with hooks, hashtags, CTA"),
1270
+ publishTarget: z4.enum(PUBLISH_TARGETS).describe("Target social platform"),
1271
+ publishTargets: z4.array(z4.enum(PUBLISH_TARGETS)).max(9).optional().describe("All allowed social destinations for this video"),
1272
+ objective: z4.enum(BRIEF_OBJECTIVES).describe("Content objective (drives composition routing)"),
1273
+ targetDurationSeconds: z4.number().int().min(5).max(600).optional().describe("Requested final video duration in seconds"),
1274
+ narrationMode: z4.enum(["tts", "off"]).optional().describe("Disable synthesized narration for source-audio or silent work"),
1275
+ lessonTitle: z4.string().optional().describe("Display title rendered inside the video"),
972
1276
  visualDirection: visualDirectionSchema.optional().describe(
973
1277
  "Whole-video communication, attention, visual-language, and camera direction."
974
1278
  ),
975
- steps: z3.array(briefStepSchema).optional().describe("Structured steps for educational content (LaTeX)"),
976
- scenes: z3.array(briefSceneSchema).optional().describe("Scene graph for the UniversalVideo composition"),
1279
+ steps: z4.array(briefStepSchema).optional().describe("Structured steps for educational content (LaTeX)"),
1280
+ scenes: z4.array(briefSceneSchema).optional().describe("Scene graph for the UniversalVideo composition"),
977
1281
  // No zod .default() here: a default would materialize into the parsed tool
978
1282
  // arguments and relay to /api/v1/jobs as if the caller stated it, corrupting
979
1283
  // the resolution provenance the API echoes back. Unset must stay absent;
980
1284
  // the API re-applies 9:16 server-side.
981
- aspectRatio: z3.enum(ASPECT_RATIOS).optional().describe("Aspect ratio (defaults to 9:16 when omitted)"),
982
- compositionId: z3.string().optional().describe("Remotion composition ID override (advanced)"),
983
- voiceId: z3.string().optional().describe(
1285
+ aspectRatio: z4.enum(ASPECT_RATIOS).optional().describe("Aspect ratio (defaults to 9:16 when omitted)"),
1286
+ compositionId: z4.string().optional().describe("Remotion composition ID override (advanced)"),
1287
+ voiceId: z4.string().optional().describe(
984
1288
  "TTS narrator voice ID. Unknown IDs are rejected before rendering; when omitted, the org's saved voice preference or the system default is used and reported in the response's resolution block."
985
1289
  ),
986
1290
  directions: directionsBriefSchema.optional().describe(
987
1291
  "DirectionsWalkthrough 'find-us' payload: source clips (legs), decision-point cues on the realtime walk timeline, outro, and optional music. Set compositionId 'DirectionsWalkthrough' (or objective 'directions')."
988
1292
  ),
989
- assetSlots: z3.array(assetSlotSchema).optional().describe(
1293
+ assetSlots: z4.array(assetSlotSchema).optional().describe(
990
1294
  "Optional storyboard asset slots: region-placed image/video assets or placeholders attached to the whole video or a specific scene."
991
1295
  ),
992
- audioLayers: z3.array(briefAudioLayerSchema).optional().describe("Optional typed music, Foley, transition, and effect layers.")
1296
+ audioLayers: z4.array(briefAudioLayerSchema).optional().describe("Optional typed music, Foley, transition, and effect layers."),
1297
+ personConsent: personConsentSchema.optional(),
1298
+ likenessAcknowledgement: likenessAcknowledgementSchema.optional()
993
1299
  };
994
1300
  var editBriefShape = {
995
- jobId: z3.string().uuid().describe("The job to edit"),
996
- title: z3.string().optional().describe("Updated title"),
997
- script: z3.string().optional().describe("Updated narration script"),
998
- caption: z3.string().optional().describe("Updated social caption"),
999
- lessonTitle: z3.string().optional().describe("Updated lesson title"),
1000
- narrationMode: z3.enum(["tts", "off"]).optional().describe("Updated synthesized narration mode"),
1301
+ jobId: z4.string().uuid().describe("The job to edit"),
1302
+ personConsent: personConsentSchema.optional(),
1303
+ likenessAcknowledgement: likenessAcknowledgementSchema.optional(),
1304
+ title: z4.string().optional().describe("Updated title"),
1305
+ script: z4.string().optional().describe("Updated narration script"),
1306
+ caption: z4.string().optional().describe("Updated social caption"),
1307
+ lessonTitle: z4.string().optional().describe("Updated lesson title"),
1308
+ narrationMode: z4.enum(["tts", "off"]).optional().describe("Updated synthesized narration mode"),
1001
1309
  visualDirection: visualDirectionSchema.optional().describe("Updated whole-video visual direction"),
1002
- steps: z3.array(briefStepSchema).optional().describe("Updated steps (replaces the array)"),
1003
- scenes: z3.array(briefSceneSchema).optional().describe("Updated scenes (replaces the array)"),
1004
- aspectRatio: z3.enum(ASPECT_RATIOS).optional().describe("Updated aspect ratio"),
1005
- objective: z3.enum(BRIEF_OBJECTIVES).optional().describe(
1310
+ steps: z4.array(briefStepSchema).optional().describe("Updated steps (replaces the array)"),
1311
+ scenes: z4.array(briefSceneSchema).optional().describe("Updated scenes (replaces the array)"),
1312
+ aspectRatio: z4.enum(ASPECT_RATIOS).optional().describe("Updated aspect ratio"),
1313
+ objective: z4.enum(BRIEF_OBJECTIVES).optional().describe(
1006
1314
  "Updated content objective. Re-routes the composition and triggers a re-render."
1007
1315
  ),
1008
- publishTarget: z3.enum(PUBLISH_TARGETS).optional().describe(
1316
+ publishTarget: z4.enum(PUBLISH_TARGETS).optional().describe(
1009
1317
  "Updated target social platform. Distribution metadata only - does not trigger a re-render."
1010
1318
  ),
1011
- publishTargets: z3.array(z3.enum(PUBLISH_TARGETS)).max(9).optional().describe("Replacement allowed social destination list"),
1012
- targetDurationSeconds: z3.number().int().min(5).max(600).optional().describe("Updated final video duration in seconds"),
1013
- voiceId: z3.string().optional().describe(
1319
+ publishTargets: z4.array(z4.enum(PUBLISH_TARGETS)).max(9).optional().describe("Replacement allowed social destination list"),
1320
+ targetDurationSeconds: z4.number().int().min(5).max(600).optional().describe("Updated final video duration in seconds"),
1321
+ voiceId: z4.string().optional().describe(
1014
1322
  "Updated TTS narrator voice ID. Triggers a re-render with the new voice."
1015
1323
  ),
1016
- assetSlots: z3.array(assetSlotSchema).optional().describe(
1324
+ assetSlots: z4.array(assetSlotSchema).optional().describe(
1017
1325
  "Replacement storyboard asset slots. Omit to preserve existing slots; pass [] to clear them."
1018
1326
  ),
1019
- audioLayers: z3.array(briefAudioLayerSchema).optional().describe(
1327
+ audioLayers: z4.array(briefAudioLayerSchema).optional().describe(
1020
1328
  "Replacement typed audio layers. Omit to preserve existing layers; pass [] to clear them."
1021
1329
  )
1022
1330
  };
@@ -1124,165 +1432,165 @@ function buildRenderDiagnosticSnapshot(params) {
1124
1432
  }
1125
1433
 
1126
1434
  // src/design-action-schema.ts
1127
- import { z as z4 } from "zod";
1128
- var id = z4.string().min(1).max(120);
1129
- var point = z4.object({ x: z4.number().min(0).max(1), y: z4.number().min(0).max(1) }).strict();
1130
- var polygonShape = z4.object({
1131
- kind: z4.literal("polygon"),
1132
- points: z4.array(point).min(3).max(512)
1435
+ import { z as z5 } from "zod";
1436
+ var id = z5.string().min(1).max(120);
1437
+ var point = z5.object({ x: z5.number().min(0).max(1), y: z5.number().min(0).max(1) }).strict();
1438
+ var polygonShape = z5.object({
1439
+ kind: z5.literal("polygon"),
1440
+ points: z5.array(point).min(3).max(512)
1133
1441
  }).strict();
1134
- var rasterShape = z4.object({
1135
- kind: z4.literal("raster"),
1136
- source: z4.object({
1442
+ var rasterShape = z5.object({
1443
+ kind: z5.literal("raster"),
1444
+ source: z5.object({
1137
1445
  assetId: id,
1138
- expectedSha256: z4.string().regex(/^[a-f0-9]{64}$/),
1139
- sourceRange: z4.object({
1140
- startFrame: z4.number().int().nonnegative(),
1141
- endFrame: z4.number().int().positive()
1446
+ expectedSha256: z5.string().regex(/^[a-f0-9]{64}$/),
1447
+ sourceRange: z5.object({
1448
+ startFrame: z5.number().int().nonnegative(),
1449
+ endFrame: z5.number().int().positive()
1142
1450
  }).strict().optional()
1143
1451
  }).strict(),
1144
- widthPx: z4.number().int().positive().max(8192),
1145
- heightPx: z4.number().int().positive().max(8192)
1452
+ widthPx: z5.number().int().positive().max(8192),
1453
+ heightPx: z5.number().int().positive().max(8192)
1146
1454
  }).strict();
1147
- var shape = z4.discriminatedUnion("kind", [polygonShape, rasterShape]);
1148
- var mask = z4.object({
1455
+ var shape = z5.discriminatedUnion("kind", [polygonShape, rasterShape]);
1456
+ var mask = z5.object({
1149
1457
  id,
1150
1458
  shape,
1151
- operation: z4.enum(["add", "subtract"]),
1152
- inverted: z4.boolean().default(false),
1153
- feather: z4.number().finite().nonnegative().max(0.25).default(0),
1154
- allowedSupportMargin: z4.number().finite().nonnegative().max(0.25).default(0),
1155
- reviewState: z4.enum(["draft", "approved", "rejected"]),
1156
- provenance: z4.object({
1157
- kind: z4.enum(["manual", "imported", "model-proposed"]),
1459
+ operation: z5.enum(["add", "subtract"]),
1460
+ inverted: z5.boolean().default(false),
1461
+ feather: z5.number().finite().nonnegative().max(0.25).default(0),
1462
+ allowedSupportMargin: z5.number().finite().nonnegative().max(0.25).default(0),
1463
+ reviewState: z5.enum(["draft", "approved", "rejected"]),
1464
+ provenance: z5.object({
1465
+ kind: z5.enum(["manual", "imported", "model-proposed"]),
1158
1466
  sourceAssetId: id.optional(),
1159
- modelId: z4.string().min(1).max(160).optional()
1467
+ modelId: z5.string().min(1).max(160).optional()
1160
1468
  }).strict()
1161
1469
  }).strict();
1162
- var transform = z4.object({
1163
- x: z4.number().min(0).max(1),
1164
- y: z4.number().min(0).max(1),
1165
- width: z4.number().positive().max(1),
1166
- height: z4.number().positive().max(1),
1167
- rotationDegrees: z4.number().min(-360).max(360),
1168
- opacity: z4.number().min(0).max(1)
1470
+ var transform = z5.object({
1471
+ x: z5.number().min(0).max(1),
1472
+ y: z5.number().min(0).max(1),
1473
+ width: z5.number().positive().max(1),
1474
+ height: z5.number().positive().max(1),
1475
+ rotationDegrees: z5.number().min(-360).max(360),
1476
+ opacity: z5.number().min(0).max(1)
1169
1477
  }).strict();
1170
1478
  var colourParameters = {
1171
- exposure: z4.number().finite().min(-2).max(2).default(0),
1172
- contrast: z4.number().finite().min(0.5).max(2).default(1),
1173
- saturation: z4.number().finite().min(0).max(2).default(1),
1174
- temperature: z4.number().finite().min(-1).max(1).default(0),
1175
- tint: z4.number().finite().min(-1).max(1).default(0)
1479
+ exposure: z5.number().finite().min(-2).max(2).default(0),
1480
+ contrast: z5.number().finite().min(0.5).max(2).default(1),
1481
+ saturation: z5.number().finite().min(0).max(2).default(1),
1482
+ temperature: z5.number().finite().min(-1).max(1).default(0),
1483
+ tint: z5.number().finite().min(-1).max(1).default(0)
1176
1484
  };
1177
- var effect = z4.object({
1485
+ var effect = z5.object({
1178
1486
  id,
1179
- kind: z4.literal("local-colour"),
1180
- version: z4.literal(1),
1487
+ kind: z5.literal("local-colour"),
1488
+ version: z5.literal(1),
1181
1489
  maskId: id,
1182
1490
  ...colourParameters
1183
1491
  }).strict();
1184
- var motionPath = z4.object({
1492
+ var motionPath = z5.object({
1185
1493
  id,
1186
- kind: z4.literal("cubic-bezier"),
1187
- startFrame: z4.number().int().nonnegative(),
1188
- endFrame: z4.number().int().positive(),
1494
+ kind: z5.literal("cubic-bezier"),
1495
+ startFrame: z5.number().int().nonnegative(),
1496
+ endFrame: z5.number().int().positive(),
1189
1497
  start: point,
1190
1498
  control1: point,
1191
1499
  control2: point,
1192
1500
  end: point,
1193
- easing: z4.enum(["linear", "ease-in", "ease-out", "ease-in-out"]),
1194
- orientToPath: z4.boolean().default(false)
1501
+ easing: z5.enum(["linear", "ease-in", "ease-out", "ease-in-out"]),
1502
+ orientToPath: z5.boolean().default(false)
1195
1503
  }).strict();
1196
- var region = z4.object({ id, shape, label: z4.string().min(1).max(160) }).strict();
1504
+ var region = z5.object({ id, shape, label: z5.string().min(1).max(160) }).strict();
1197
1505
  var base = { actionId: id, sceneId: id };
1198
- var vendoredDesignActionSchema = z4.discriminatedUnion("kind", [
1199
- z4.object({
1506
+ var vendoredDesignActionSchema = z5.discriminatedUnion("kind", [
1507
+ z5.object({
1200
1508
  ...base,
1201
- kind: z4.literal("set-layer-transform"),
1509
+ kind: z5.literal("set-layer-transform"),
1202
1510
  layerId: id,
1203
1511
  transform
1204
1512
  }).strict(),
1205
- z4.object({
1513
+ z5.object({
1206
1514
  ...base,
1207
- kind: z4.literal("set-local-colour-effect"),
1515
+ kind: z5.literal("set-local-colour-effect"),
1208
1516
  effectId: id,
1209
- parameters: z4.object(colourParameters).strict()
1517
+ parameters: z5.object(colourParameters).strict()
1210
1518
  }).strict(),
1211
- z4.object({ ...base, kind: z4.literal("create-mask"), mask }).strict(),
1212
- z4.object({ ...base, kind: z4.literal("set-mask"), maskId: id, mask }).strict(),
1213
- z4.object({
1519
+ z5.object({ ...base, kind: z5.literal("create-mask"), mask }).strict(),
1520
+ z5.object({ ...base, kind: z5.literal("set-mask"), maskId: id, mask }).strict(),
1521
+ z5.object({
1214
1522
  ...base,
1215
- kind: z4.literal("set-mask-review-state"),
1523
+ kind: z5.literal("set-mask-review-state"),
1216
1524
  maskId: id,
1217
- reviewState: z4.enum(["draft", "approved", "rejected"])
1525
+ reviewState: z5.enum(["draft", "approved", "rejected"])
1218
1526
  }).strict(),
1219
- z4.object({ ...base, kind: z4.literal("delete-mask"), maskId: id }).strict(),
1220
- z4.object({
1527
+ z5.object({ ...base, kind: z5.literal("delete-mask"), maskId: id }).strict(),
1528
+ z5.object({
1221
1529
  ...base,
1222
- kind: z4.literal("attach-effect"),
1530
+ kind: z5.literal("attach-effect"),
1223
1531
  effect,
1224
- layerIds: z4.array(id).min(1).max(50)
1532
+ layerIds: z5.array(id).min(1).max(50)
1225
1533
  }).strict(),
1226
- z4.object({ ...base, kind: z4.literal("remove-effect"), effectId: id }).strict(),
1227
- z4.object({
1534
+ z5.object({ ...base, kind: z5.literal("remove-effect"), effectId: id }).strict(),
1535
+ z5.object({
1228
1536
  ...base,
1229
- kind: z4.literal("set-layer-text"),
1537
+ kind: z5.literal("set-layer-text"),
1230
1538
  layerId: id,
1231
- text: z4.string().max(1e4)
1539
+ text: z5.string().max(1e4)
1232
1540
  }).strict(),
1233
- z4.object({
1541
+ z5.object({
1234
1542
  ...base,
1235
- kind: z4.literal("set-layer-visibility"),
1543
+ kind: z5.literal("set-layer-visibility"),
1236
1544
  layerId: id,
1237
- visible: z4.boolean()
1545
+ visible: z5.boolean()
1238
1546
  }).strict(),
1239
- z4.object({
1547
+ z5.object({
1240
1548
  ...base,
1241
- kind: z4.literal("set-layer-locked"),
1549
+ kind: z5.literal("set-layer-locked"),
1242
1550
  layerId: id,
1243
- locked: z4.boolean()
1551
+ locked: z5.boolean()
1244
1552
  }).strict(),
1245
- z4.object({
1553
+ z5.object({
1246
1554
  ...base,
1247
- kind: z4.literal("set-layer-mask-ids"),
1555
+ kind: z5.literal("set-layer-mask-ids"),
1248
1556
  layerId: id,
1249
- maskIds: z4.array(id).max(16)
1557
+ maskIds: z5.array(id).max(16)
1250
1558
  }).strict(),
1251
- z4.object({
1559
+ z5.object({
1252
1560
  ...base,
1253
- kind: z4.literal("set-layer-order"),
1254
- orderedLayerIds: z4.array(id).min(1).max(500)
1561
+ kind: z5.literal("set-layer-order"),
1562
+ orderedLayerIds: z5.array(id).min(1).max(500)
1255
1563
  }).strict(),
1256
- z4.object({
1564
+ z5.object({
1257
1565
  ...base,
1258
- kind: z4.literal("set-motion-path"),
1566
+ kind: z5.literal("set-motion-path"),
1259
1567
  path: motionPath,
1260
- layerIds: z4.array(id).max(50).default([])
1568
+ layerIds: z5.array(id).max(50).default([])
1261
1569
  }).strict(),
1262
- z4.object({ ...base, kind: z4.literal("remove-motion-path"), pathId: id }).strict(),
1263
- z4.object({ ...base, kind: z4.literal("set-protected-region"), region }).strict(),
1264
- z4.object({
1570
+ z5.object({ ...base, kind: z5.literal("remove-motion-path"), pathId: id }).strict(),
1571
+ z5.object({ ...base, kind: z5.literal("set-protected-region"), region }).strict(),
1572
+ z5.object({
1265
1573
  ...base,
1266
- kind: z4.literal("remove-protected-region"),
1574
+ kind: z5.literal("remove-protected-region"),
1267
1575
  regionId: id
1268
1576
  }).strict()
1269
1577
  ]);
1270
- var inspectDesignDocumentToolSchema = z4.object({
1271
- projectId: z4.string().uuid(),
1272
- documentId: z4.string().uuid(),
1273
- includeVersions: z4.boolean().default(true)
1578
+ var inspectDesignDocumentToolSchema = z5.object({
1579
+ projectId: z5.string().uuid(),
1580
+ documentId: z5.string().uuid(),
1581
+ includeVersions: z5.boolean().default(true)
1274
1582
  }).strict();
1275
- var applyDesignActionsToolSchema = z4.object({
1276
- projectId: z4.string().uuid(),
1277
- documentId: z4.string().uuid(),
1278
- actionGroupId: z4.string().min(1).max(120),
1279
- expectedVersion: z4.number().int().positive(),
1280
- actions: z4.array(vendoredDesignActionSchema).min(1).max(50),
1281
- clientCreatedAt: z4.string().datetime()
1583
+ var applyDesignActionsToolSchema = z5.object({
1584
+ projectId: z5.string().uuid(),
1585
+ documentId: z5.string().uuid(),
1586
+ actionGroupId: z5.string().min(1).max(120),
1587
+ expectedVersion: z5.number().int().positive(),
1588
+ actions: z5.array(vendoredDesignActionSchema).min(1).max(50),
1589
+ clientCreatedAt: z5.string().datetime()
1282
1590
  }).strict();
1283
1591
 
1284
1592
  // src/tools.ts
1285
- var uuid = (desc) => z5.string().uuid().describe(desc);
1593
+ var uuid = (desc) => z6.string().uuid().describe(desc);
1286
1594
  var READ_ONLY = {
1287
1595
  readOnlyHint: true,
1288
1596
  destructiveHint: false,
@@ -1302,8 +1610,8 @@ function registerTools(server) {
1302
1610
  title: "List jobs",
1303
1611
  description: "List recent video jobs for the current organization (newest first). Start here to discover job IDs; for one job's full detail use get_job_status.",
1304
1612
  inputSchema: {
1305
- limit: z5.number().int().min(1).max(50).default(10).describe("Number of jobs to return (default 10, max 50)"),
1306
- status: z5.enum([
1613
+ limit: z6.number().int().min(1).max(50).default(10).describe("Number of jobs to return (default 10, max 50)"),
1614
+ status: z6.enum([
1307
1615
  "queued",
1308
1616
  "rendering",
1309
1617
  "draft_ready",
@@ -1368,7 +1676,7 @@ function registerTools(server) {
1368
1676
  description: "Get the latest platform engagement metric snapshots for a published job (newest first). Read-only. Only meaningful after publish_job; for render progress use get_job_status.",
1369
1677
  inputSchema: {
1370
1678
  jobId: uuid("The job ID"),
1371
- limit: z5.number().int().min(1).max(20).default(10).describe("Max metric snapshots (default 10, max 20)")
1679
+ limit: z6.number().int().min(1).max(20).default(10).describe("Max metric snapshots (default 10, max 20)")
1372
1680
  },
1373
1681
  annotations: READ_ONLY
1374
1682
  },
@@ -1384,10 +1692,10 @@ function registerTools(server) {
1384
1692
  title: "Get cost summary",
1385
1693
  description: "Query production infrastructure costs (Lambda, RunPod, R2, WaveSpeed, PoYo), optionally with reconciliation drift. This is spend data, not engagement \u2014 for a published job's audience numbers use get_job_metrics.",
1386
1694
  inputSchema: {
1387
- since: z5.string().optional().describe("ISO date \u2014 only include events after this date"),
1388
- provider: z5.enum(["runpod", "lambda", "r2", "wavespeed", "poyo", "all"]).default("all").describe("Filter by provider"),
1389
- groupBy: z5.enum(["provider", "job", "day"]).default("provider").describe("How to aggregate the summary"),
1390
- includeReconciliation: z5.boolean().default(false).describe("Include account-wide reconciliation events")
1695
+ since: z6.string().optional().describe("ISO date \u2014 only include events after this date"),
1696
+ provider: z6.enum(["runpod", "lambda", "r2", "wavespeed", "poyo", "all"]).default("all").describe("Filter by provider"),
1697
+ groupBy: z6.enum(["provider", "job", "day"]).default("provider").describe("How to aggregate the summary"),
1698
+ includeReconciliation: z6.boolean().default(false).describe("Include account-wide reconciliation events")
1391
1699
  },
1392
1700
  annotations: READ_ONLY
1393
1701
  },
@@ -1403,7 +1711,7 @@ function registerTools(server) {
1403
1711
  {
1404
1712
  title: "Inspect workflow",
1405
1713
  description: "Inspect the current Studio workflow and its version history for a job.",
1406
- inputSchema: z5.object({ jobId: uuid("The job ID") }).strict(),
1714
+ inputSchema: z6.object({ jobId: uuid("The job ID") }).strict(),
1407
1715
  annotations: READ_ONLY
1408
1716
  },
1409
1717
  async ({ jobId }) => runTool(
@@ -1483,10 +1791,10 @@ function registerTools(server) {
1483
1791
  {
1484
1792
  title: "Draft workflow",
1485
1793
  description: "Create a durable Documentary Journey or Transformation Montage workflow version. Inspect first and pass its current version, or 0 only when no workflow exists.",
1486
- inputSchema: z5.object({
1794
+ inputSchema: z6.object({
1487
1795
  jobId: uuid("The job ID"),
1488
- expectedVersion: z5.number().int().nonnegative().describe("Use 0 when no workflow exists yet"),
1489
- document: z5.unknown().describe("The complete Studio workflow document")
1796
+ expectedVersion: z6.number().int().nonnegative().describe("Use 0 when no workflow exists yet"),
1797
+ document: z6.unknown().describe("The complete Studio workflow document")
1490
1798
  }).strict(),
1491
1799
  annotations: SAFE_WRITE
1492
1800
  },
@@ -1497,10 +1805,10 @@ function registerTools(server) {
1497
1805
  {
1498
1806
  title: "Patch workflow",
1499
1807
  description: "Create a new workflow version by recursively merging a patch into the current version.",
1500
- inputSchema: z5.object({
1808
+ inputSchema: z6.object({
1501
1809
  jobId: uuid("The job ID"),
1502
- expectedVersion: z5.number().int().positive(),
1503
- patch: z5.record(z5.string(), z5.unknown())
1810
+ expectedVersion: z6.number().int().positive(),
1811
+ patch: z6.record(z6.string(), z6.unknown())
1504
1812
  }).strict(),
1505
1813
  annotations: SAFE_WRITE
1506
1814
  },
@@ -1511,9 +1819,9 @@ function registerTools(server) {
1511
1819
  {
1512
1820
  title: "Validate workflow",
1513
1821
  description: "Validate and compile the inspected workflow version without rendering or publishing it.",
1514
- inputSchema: z5.object({
1822
+ inputSchema: z6.object({
1515
1823
  jobId: uuid("The job ID"),
1516
- expectedVersion: z5.number().int().positive()
1824
+ expectedVersion: z6.number().int().positive()
1517
1825
  }).strict(),
1518
1826
  annotations: SAFE_WRITE
1519
1827
  },
@@ -1524,7 +1832,7 @@ function registerTools(server) {
1524
1832
  {
1525
1833
  title: "Preview workflow",
1526
1834
  description: "Return the current workflow's compiled UniversalVideo brief for a safe pre-render preview.",
1527
- inputSchema: z5.object({ jobId: uuid("The job ID") }).strict(),
1835
+ inputSchema: z6.object({ jobId: uuid("The job ID") }).strict(),
1528
1836
  annotations: READ_ONLY
1529
1837
  },
1530
1838
  async ({ jobId }) => runTool(
@@ -1538,10 +1846,10 @@ function registerTools(server) {
1538
1846
  {
1539
1847
  title: "Compare workflow versions",
1540
1848
  description: "Compare two durable workflow versions field by field.",
1541
- inputSchema: z5.object({
1849
+ inputSchema: z6.object({
1542
1850
  jobId: uuid("The job ID"),
1543
- fromVersion: z5.number().int().positive(),
1544
- toVersion: z5.number().int().positive()
1851
+ fromVersion: z6.number().int().positive(),
1852
+ toVersion: z6.number().int().positive()
1545
1853
  }).strict(),
1546
1854
  annotations: READ_ONLY
1547
1855
  },
@@ -1565,9 +1873,9 @@ function registerTools(server) {
1565
1873
  {
1566
1874
  title: "Approve workflow",
1567
1875
  description: "Validate and approve the inspected workflow version. This does not approve or publish the video job.",
1568
- inputSchema: z5.object({
1876
+ inputSchema: z6.object({
1569
1877
  jobId: uuid("The job ID"),
1570
- expectedVersion: z5.number().int().positive()
1878
+ expectedVersion: z6.number().int().positive()
1571
1879
  }).strict(),
1572
1880
  annotations: {
1573
1881
  readOnlyHint: false,
@@ -1624,7 +1932,7 @@ function registerTools(server) {
1624
1932
  inputSchema: {
1625
1933
  jobId: uuid("The current job ID"),
1626
1934
  sourceRunId: uuid("The current run ID"),
1627
- trigger: z5.enum(["user_requested", "verifier_recommendation"])
1935
+ trigger: z6.enum(["user_requested", "verifier_recommendation"])
1628
1936
  },
1629
1937
  annotations: SAFE_WRITE
1630
1938
  },
@@ -1643,7 +1951,8 @@ function registerTools(server) {
1643
1951
  inputSchema: { jobId: uuid("The job ID to approve") },
1644
1952
  annotations: {
1645
1953
  readOnlyHint: false,
1646
- destructiveHint: false,
1954
+ // Approval revokes active review links, so this is not purely additive.
1955
+ destructiveHint: true,
1647
1956
  // Approving an already-approved job does not change state further.
1648
1957
  idempotentHint: true,
1649
1958
  openWorldHint: false
@@ -1660,15 +1969,25 @@ function registerTools(server) {
1660
1969
  description: "Publish an APPROVED job to its connected social destination via the gated publish API. All production gates run (paid plan, ownership, abuse, QA, disclosure, destination, rights, moderation). Requires a key with publish scope; the post goes live on the external platform and cannot be recalled by the API. For YouTube pass youtubePrivacyStatus:'private' for safe runs.",
1661
1970
  inputSchema: {
1662
1971
  jobId: uuid("The approved job to publish"),
1663
- youtubePrivacyStatus: z5.enum(["private", "unlisted", "public"]).optional().describe("YouTube only. Use 'private' for safe dogfood runs."),
1664
- tiktokPostMode: z5.enum(["direct_publish", "draft_upload"]).optional().describe("TikTok only. Use 'draft_upload' for safe dogfood runs."),
1665
- connectedAccountDestinationId: z5.string().uuid().optional().describe(
1972
+ xPreviewArtifactId: z6.string().min(1).optional().describe("X only. Exact reviewed video artifact ID."),
1973
+ xCaption: z6.string().trim().min(1).max(2e3).optional().describe("X only. Exact post text approved by the user."),
1974
+ xMadeWithAi: z6.boolean().optional().describe("X only. Enable the Made with AI disclosure."),
1975
+ confirmXPublicPost: z6.boolean().optional().describe("True only after the user authorizes this public X post."),
1976
+ confirmXAutomationPolicy: z6.boolean().optional().describe(
1977
+ "True only after the user confirms the X automation policy."
1978
+ ),
1979
+ confirmXOriginalContent: z6.boolean().optional().describe(
1980
+ "True only after the user confirms ownership or publishing rights."
1981
+ ),
1982
+ youtubePrivacyStatus: z6.enum(["private", "unlisted", "public"]).optional().describe("YouTube only. Use 'private' for safe dogfood runs."),
1983
+ tiktokPostMode: z6.enum(["direct_publish", "draft_upload"]).optional().describe("TikTok only. Use 'draft_upload' for safe dogfood runs."),
1984
+ connectedAccountDestinationId: z6.string().uuid().optional().describe(
1666
1985
  "Specific destination when the org has multiple accounts for the provider."
1667
1986
  ),
1668
- confirmSyntheticDisclosure: z5.boolean().optional().describe(
1987
+ confirmSyntheticDisclosure: z6.boolean().optional().describe(
1669
1988
  "Set true when the job requires an AI synthetic-media disclosure."
1670
1989
  ),
1671
- confirmQaOverride: z5.boolean().optional().describe("Set true to override a non-passing QA gate.")
1990
+ confirmQaOverride: z6.boolean().optional().describe("Set true to override a non-passing QA gate.")
1672
1991
  },
1673
1992
  annotations: {
1674
1993
  readOnlyHint: false,
@@ -1691,7 +2010,7 @@ function registerTools(server) {
1691
2010
  title: "Connect social account",
1692
2011
  description: "Start connecting a social account headlessly (no local browser needed). Returns an approve URL + a short confirm code: open the URL in a browser signed in to Instavar, check the code matches THIS terminal, and approve. Then poll connect_account_status with the returned pairingId until it reports 'connected'.",
1693
2012
  inputSchema: {
1694
- provider: z5.enum([
2013
+ provider: z6.enum([
1695
2014
  "youtube",
1696
2015
  "x",
1697
2016
  "tiktok",
@@ -1740,7 +2059,7 @@ function registerConfiguredTools(server, apiKey = process.env.INSTAVAR_API_KEY)
1740
2059
  // package.json
1741
2060
  var package_default = {
1742
2061
  name: "@instavar/mcp-server",
1743
- version: "0.5.0",
2062
+ version: "0.6.0",
1744
2063
  mcpName: "com.instavar/mcp-server",
1745
2064
  description: "Make local videos with Instavar Remotion templates for free, then add an API key for hosted Studio workflows.",
1746
2065
  type: "module",
@@ -1817,7 +2136,7 @@ async function main() {
1817
2136
  const server = new McpServer(
1818
2137
  { name: "instavar", version: VERSION },
1819
2138
  {
1820
- instructions: "Before drafting concise carousel or video copy, call get_creative_guide for visual-copy. Use the carousel-stories, visual-design and human-review guides as relevant. Apply them to the user brief; the guides do not generate, render, save or publish media."
2139
+ instructions: PAIRED_ANNOUNCEMENT_INSTRUCTIONS + " Before drafting concise carousel or video copy, call get_creative_guide for visual-copy. Use the carousel-stories, visual-design and human-review guides as relevant. Apply them to the user brief; the guides do not generate, render, save or publish media."
1821
2140
  }
1822
2141
  );
1823
2142
  registerConfiguredTools(server);