@clipform/mcp-server 1.34.0 → 1.35.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.
@@ -6,14 +6,14 @@ import {
6
6
  getWorkflowText,
7
7
  objectType,
8
8
  registerPrompts
9
- } from "./chunk-JOJJ2XFL.js";
9
+ } from "./chunk-6MLZZSNM.js";
10
10
  import {
11
11
  GUIDE_TYPES,
12
12
  QUIZ_VARIANTS,
13
13
  getGuideContent,
14
14
  getGuideUri,
15
15
  registerResources
16
- } from "./chunk-JID43EDM.js";
16
+ } from "./chunk-TMNXECJI.js";
17
17
  import {
18
18
  BUSINESS,
19
19
  CONTACT_FIELDS,
@@ -29,7 +29,7 @@ import {
29
29
  errorResult,
30
30
  resolveFormType,
31
31
  textResult
32
- } from "./chunk-KWEBCAPF.js";
32
+ } from "./chunk-BYJMRIB6.js";
33
33
  import {
34
34
  __commonJS,
35
35
  __export,
@@ -16984,22 +16984,29 @@ var END_SCREEN_ICONS = _endScreen.icon.enum;
16984
16984
  var END_SCREEN_CTA_TYPES = _endScreen.cta_type.enum;
16985
16985
  var PUBLIC_COMPOSITIONS = [
16986
16986
  "GlobeToCity",
16987
- "CityToGlobe"
16988
- ];
16989
- var LABS_COMPOSITIONS = [
16987
+ "CityToGlobe",
16988
+ "MapPin",
16989
+ "Grid",
16990
+ "GridList",
16991
+ "ObscuredReveal",
16992
+ "Timeline",
16993
+ "NumberLine",
16994
+ "CountdownRing",
16990
16995
  "CountrySilhouetteClip",
16991
- "FourImageGrid",
16992
- "OddOneOutReveal",
16993
16996
  "FlagRevealGB",
16994
16997
  "FlagRevealJP",
16995
16998
  "FlagRevealBR",
16996
16999
  "ColorCards",
16997
17000
  "TextReveal",
16998
17001
  "EmojiPuzzle",
16999
- "StatCounter",
17000
- "ListReveal",
17001
17002
  "BeforeAfter",
17002
- "MediaSlideshow"
17003
+ "MediaSlideshow",
17004
+ "TitleCard",
17005
+ "ParallaxImage"
17006
+ ];
17007
+ var LABS_COMPOSITIONS = [
17008
+ "StatCounter",
17009
+ "ListReveal"
17003
17010
  ];
17004
17011
  var EXPOSED_COMPOSITIONS = process.env.CLIPFORM_LABS === "1" ? [...PUBLIC_COMPOSITIONS, ...LABS_COMPOSITIONS] : PUBLIC_COMPOSITIONS;
17005
17012
 
@@ -18267,6 +18274,98 @@ Example: { queries: [{ query: "saturn rings" }, { query: "mars surface", count:
18267
18274
  );
18268
18275
  }
18269
18276
 
18277
+ // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/stringify.js
18278
+ var byteToHex = [];
18279
+ for (let i = 0; i < 256; ++i) {
18280
+ byteToHex.push((i + 256).toString(16).slice(1));
18281
+ }
18282
+ function unsafeStringify(arr, offset = 0) {
18283
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
18284
+ }
18285
+
18286
+ // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/rng.js
18287
+ import { randomFillSync } from "crypto";
18288
+ var rnds8Pool = new Uint8Array(256);
18289
+ var poolPtr = rnds8Pool.length;
18290
+ function rng() {
18291
+ if (poolPtr > rnds8Pool.length - 16) {
18292
+ randomFillSync(rnds8Pool);
18293
+ poolPtr = 0;
18294
+ }
18295
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
18296
+ }
18297
+
18298
+ // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/native.js
18299
+ import { randomUUID } from "crypto";
18300
+ var native_default = { randomUUID };
18301
+
18302
+ // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/v4.js
18303
+ function v4(options, buf, offset) {
18304
+ if (native_default.randomUUID && !buf && !options) {
18305
+ return native_default.randomUUID();
18306
+ }
18307
+ options = options || {};
18308
+ const rnds = options.random ?? options.rng?.() ?? rng();
18309
+ if (rnds.length < 16) {
18310
+ throw new Error("Random bytes length must be >= 16");
18311
+ }
18312
+ rnds[6] = rnds[6] & 15 | 64;
18313
+ rnds[8] = rnds[8] & 63 | 128;
18314
+ if (buf) {
18315
+ offset = offset || 0;
18316
+ if (offset < 0 || offset + 16 > buf.length) {
18317
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
18318
+ }
18319
+ for (let i = 0; i < 16; ++i) {
18320
+ buf[offset + i] = rnds[i];
18321
+ }
18322
+ return buf;
18323
+ }
18324
+ return unsafeStringify(rnds);
18325
+ }
18326
+ var v4_default = v4;
18327
+
18328
+ // src/lib/render-jobs.ts
18329
+ var jobs = /* @__PURE__ */ new Map();
18330
+ var MAX_AGE_MS = 30 * 60 * 1e3;
18331
+ var RENDER_TIMING = {
18332
+ expectedRange: "15-120 seconds",
18333
+ pollDelay: "~15 seconds"
18334
+ };
18335
+ function createJob(tool) {
18336
+ const job = {
18337
+ id: v4_default(),
18338
+ status: "rendering",
18339
+ tool,
18340
+ createdAt: Date.now()
18341
+ };
18342
+ jobs.set(job.id, job);
18343
+ return job;
18344
+ }
18345
+ function completeJob(id, result) {
18346
+ const job = jobs.get(id);
18347
+ if (job) {
18348
+ job.status = "complete";
18349
+ job.result = result;
18350
+ }
18351
+ }
18352
+ function failJob(id, error2) {
18353
+ const job = jobs.get(id);
18354
+ if (job) {
18355
+ job.status = "failed";
18356
+ job.error = error2;
18357
+ }
18358
+ }
18359
+ function getJob(id) {
18360
+ return jobs.get(id);
18361
+ }
18362
+ function pruneJobs() {
18363
+ const cutoff = Date.now() - MAX_AGE_MS;
18364
+ for (const [id, job] of jobs) {
18365
+ if (job.createdAt < cutoff) jobs.delete(id);
18366
+ }
18367
+ }
18368
+
18270
18369
  // src/tools/render-composition.ts
18271
18370
  function registerRenderCompositionTool(server) {
18272
18371
  server.registerTool(
@@ -18275,19 +18374,22 @@ function registerRenderCompositionTool(server) {
18275
18374
  title: "Render Composition",
18276
18375
  description: `Render a specialised video composition to MP4 or PNG - custom animated visuals that clipform_generate_video can't provide, such as geography animations or designed motion graphics. Available composition names and their required input props schemas come from clipform_list_compositions.
18277
18376
 
18278
- For narrated Ken Burns slideshows from images, use clipform_generate_video instead. Output formats: mp4 (H.264, best for social media) or png (single frame). Returns a public URL when complete.`,
18377
+ For narrated Ken Burns slideshows from images, use clipform_generate_video instead. Output formats: mp4 (H.264, best for social media) or png (single frame). Returns a public URL when complete.
18378
+
18379
+ For multi-render builds (e.g. composition quizzes with a clue + reveal clip per question), pass wait: false on every call: each returns a job ID immediately so renders run in parallel - then collect URLs with clipform_check_render.`,
18279
18380
  inputSchema: {
18280
18381
  compositionId: external_exports.string().describe(`The composition ID. Call clipform_list_compositions to see available options (e.g. ${EXPOSED_COMPOSITIONS.map((id) => `'${id}'`).join(", ")})`),
18281
18382
  outputFormat: external_exports.enum(["mp4", "png"]).default("mp4").describe("Output format (default: mp4)"),
18282
- inputProps: external_exports.record(external_exports.unknown()).optional().describe("Props object matching the composition's schema from clipform_list_compositions. Validated STRICTLY - unknown or missing props fail with the schema in the error, nothing renders silently with defaults. For map compositions (GlobeToCity, CityToGlobe), round lat/lng to 1 decimal place (e.g. 48.9 instead of 48.8566) \u2014 this improves cache hit rates.")
18383
+ inputProps: external_exports.record(external_exports.unknown()).optional().describe("Props object matching the composition's schema from clipform_list_compositions. Validated STRICTLY - unknown or missing props fail with the schema in the error, nothing renders silently with defaults. For map compositions (GlobeToCity, CityToGlobe), round lat/lng to 1 decimal place (e.g. 48.9 instead of 48.8566) \u2014 this improves cache hit rates."),
18384
+ wait: external_exports.boolean().optional().default(true).describe("true (default) blocks until the render is ready and returns its URL. false returns a job ID immediately - fire all renders first, then poll clipform_check_render. Use false whenever rendering more than one clip.")
18283
18385
  },
18284
18386
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
18285
18387
  },
18286
- async ({ compositionId, outputFormat, inputProps }) => {
18388
+ async ({ compositionId, outputFormat, inputProps, wait }) => {
18287
18389
  if (!EXPOSED_COMPOSITIONS.includes(compositionId)) {
18288
18390
  return errorResult(`Composition "${compositionId}" is not available. Call clipform_list_compositions to see available options.`);
18289
18391
  }
18290
- const result = await callApi("/internal/render", {
18392
+ const apiCall = () => callApi("/internal/render", {
18291
18393
  timeoutMs: 3e5,
18292
18394
  // local renders pay a cold webpack bundle; Lambda is fast but bursty
18293
18395
  body: {
@@ -18296,6 +18398,21 @@ For narrated Ken Burns slideshows from images, use clipform_generate_video inste
18296
18398
  inputProps: inputProps ?? {}
18297
18399
  }
18298
18400
  });
18401
+ if (wait === false) {
18402
+ const job = createJob("clipform_render_composition");
18403
+ apiCall().then((r) => {
18404
+ if (r.ok) completeJob(job.id, r.data);
18405
+ else failJob(job.id, r.error);
18406
+ }).catch((err) => failJob(job.id, err instanceof Error ? err.message : String(err)));
18407
+ return textResult(
18408
+ [
18409
+ `Render started (${compositionId}).`,
18410
+ `Job ID: ${job.id}`,
18411
+ `Fire any remaining renders now, then poll clipform_check_render. Renders typically take ${RENDER_TIMING.expectedRange}.`
18412
+ ].join("\n")
18413
+ );
18414
+ }
18415
+ const result = await apiCall();
18299
18416
  if (!result.ok) return errorResult(result.error);
18300
18417
  const data = result.data;
18301
18418
  return textResult(
@@ -18449,98 +18566,6 @@ function registerListAssetsTool(server) {
18449
18566
  );
18450
18567
  }
18451
18568
 
18452
- // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/stringify.js
18453
- var byteToHex = [];
18454
- for (let i = 0; i < 256; ++i) {
18455
- byteToHex.push((i + 256).toString(16).slice(1));
18456
- }
18457
- function unsafeStringify(arr, offset = 0) {
18458
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
18459
- }
18460
-
18461
- // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/rng.js
18462
- import { randomFillSync } from "crypto";
18463
- var rnds8Pool = new Uint8Array(256);
18464
- var poolPtr = rnds8Pool.length;
18465
- function rng() {
18466
- if (poolPtr > rnds8Pool.length - 16) {
18467
- randomFillSync(rnds8Pool);
18468
- poolPtr = 0;
18469
- }
18470
- return rnds8Pool.slice(poolPtr, poolPtr += 16);
18471
- }
18472
-
18473
- // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/native.js
18474
- import { randomUUID } from "crypto";
18475
- var native_default = { randomUUID };
18476
-
18477
- // ../../node_modules/.pnpm/uuid@11.1.1/node_modules/uuid/dist/esm/v4.js
18478
- function v4(options, buf, offset) {
18479
- if (native_default.randomUUID && !buf && !options) {
18480
- return native_default.randomUUID();
18481
- }
18482
- options = options || {};
18483
- const rnds = options.random ?? options.rng?.() ?? rng();
18484
- if (rnds.length < 16) {
18485
- throw new Error("Random bytes length must be >= 16");
18486
- }
18487
- rnds[6] = rnds[6] & 15 | 64;
18488
- rnds[8] = rnds[8] & 63 | 128;
18489
- if (buf) {
18490
- offset = offset || 0;
18491
- if (offset < 0 || offset + 16 > buf.length) {
18492
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
18493
- }
18494
- for (let i = 0; i < 16; ++i) {
18495
- buf[offset + i] = rnds[i];
18496
- }
18497
- return buf;
18498
- }
18499
- return unsafeStringify(rnds);
18500
- }
18501
- var v4_default = v4;
18502
-
18503
- // src/lib/render-jobs.ts
18504
- var jobs = /* @__PURE__ */ new Map();
18505
- var MAX_AGE_MS = 30 * 60 * 1e3;
18506
- var RENDER_TIMING = {
18507
- expectedRange: "15-120 seconds",
18508
- pollDelay: "~15 seconds"
18509
- };
18510
- function createJob(tool) {
18511
- const job = {
18512
- id: v4_default(),
18513
- status: "rendering",
18514
- tool,
18515
- createdAt: Date.now()
18516
- };
18517
- jobs.set(job.id, job);
18518
- return job;
18519
- }
18520
- function completeJob(id, result) {
18521
- const job = jobs.get(id);
18522
- if (job) {
18523
- job.status = "complete";
18524
- job.result = result;
18525
- }
18526
- }
18527
- function failJob(id, error2) {
18528
- const job = jobs.get(id);
18529
- if (job) {
18530
- job.status = "failed";
18531
- job.error = error2;
18532
- }
18533
- }
18534
- function getJob(id) {
18535
- return jobs.get(id);
18536
- }
18537
- function pruneJobs() {
18538
- const cutoff = Date.now() - MAX_AGE_MS;
18539
- for (const [id, job] of jobs) {
18540
- if (job.createdAt < cutoff) jobs.delete(id);
18541
- }
18542
- }
18543
-
18544
18569
  // src/tools/generate-video.ts
18545
18570
  function registerGenerateVideoTool(server) {
18546
18571
  server.registerTool(
@@ -18973,4 +18998,4 @@ export {
18973
18998
  JSONRPCMessageSchema,
18974
18999
  createServer
18975
19000
  };
18976
- //# sourceMappingURL=chunk-ZVHI2V7B.js.map
19001
+ //# sourceMappingURL=chunk-G6JFAKX3.js.map