@clipform/mcp-server 1.27.0 → 1.29.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-45T6WTYP.js";
9
+ } from "./chunk-6SFMF2AQ.js";
10
10
  import {
11
11
  GUIDE_TYPES,
12
12
  QUIZ_VARIANTS,
13
13
  getGuideContent,
14
14
  getGuideUri,
15
15
  registerResources
16
- } from "./chunk-HUHWR2I6.js";
16
+ } from "./chunk-B6ZWH3GD.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-6W5NTDW7.js";
32
+ } from "./chunk-NHFRYNJ3.js";
33
33
  import {
34
34
  __commonJS,
35
35
  __export,
@@ -16986,6 +16986,20 @@ var PUBLIC_COMPOSITIONS = [
16986
16986
  "GlobeToCity",
16987
16987
  "CityToGlobe"
16988
16988
  ];
16989
+ var LABS_COMPOSITIONS = [
16990
+ "CountrySilhouetteClip",
16991
+ "FlagRevealGB",
16992
+ "FlagRevealJP",
16993
+ "FlagRevealBR",
16994
+ "ColorCards",
16995
+ "TextReveal",
16996
+ "EmojiPuzzle",
16997
+ "StatCounter",
16998
+ "ListReveal",
16999
+ "BeforeAfter",
17000
+ "MediaSlideshow"
17001
+ ];
17002
+ var EXPOSED_COMPOSITIONS = process.env.CLIPFORM_LABS === "1" ? [...PUBLIC_COMPOSITIONS, ...LABS_COMPOSITIONS] : PUBLIC_COMPOSITIONS;
16989
17003
 
16990
17004
  // src/lib/schemas.ts
16991
17005
  var ACTIVE_NODE_TYPES = Object.entries(NODE_TYPES).filter(([, def]) => def.is_active && !def.is_system).map(([type]) => type);
@@ -18212,18 +18226,19 @@ function registerRenderCompositionTool(server) {
18212
18226
 
18213
18227
  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.`,
18214
18228
  inputSchema: {
18215
- compositionId: external_exports.string().describe(`The composition ID. Call clipform_list_compositions to see available options (e.g. ${PUBLIC_COMPOSITIONS.map((id) => `'${id}'`).join(", ")})`),
18229
+ compositionId: external_exports.string().describe(`The composition ID. Call clipform_list_compositions to see available options (e.g. ${EXPOSED_COMPOSITIONS.map((id) => `'${id}'`).join(", ")})`),
18216
18230
  outputFormat: external_exports.enum(["mp4", "png"]).default("mp4").describe("Output format (default: mp4)"),
18217
- inputProps: external_exports.record(external_exports.unknown()).optional().describe("Props object matching the composition's expected schema. 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.")
18231
+ 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.")
18218
18232
  },
18219
18233
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
18220
18234
  },
18221
18235
  async ({ compositionId, outputFormat, inputProps }) => {
18222
- if (!PUBLIC_COMPOSITIONS.includes(compositionId)) {
18236
+ if (!EXPOSED_COMPOSITIONS.includes(compositionId)) {
18223
18237
  return errorResult(`Composition "${compositionId}" is not available. Call clipform_list_compositions to see available options.`);
18224
18238
  }
18225
18239
  const result = await callApi("/internal/render", {
18226
- timeoutMs: 9e4,
18240
+ timeoutMs: 3e5,
18241
+ // local renders pay a cold webpack bundle; Lambda is fast but bursty
18227
18242
  body: {
18228
18243
  compositionId,
18229
18244
  outputFormat,
@@ -18279,6 +18294,25 @@ function registerSearchMusicTool(server) {
18279
18294
  }
18280
18295
 
18281
18296
  // src/tools/list-compositions.ts
18297
+ function summarizeSchema(schema) {
18298
+ if (!schema || typeof schema !== "object" || !schema.properties) {
18299
+ return "none (renders built-in defaults only - omit inputProps)";
18300
+ }
18301
+ const required2 = new Set(schema.required ?? []);
18302
+ const typeOf = (prop) => {
18303
+ if (prop.enum) {
18304
+ return prop.enum.length <= 8 ? prop.enum.map((v) => JSON.stringify(v)).join("|") : `enum(${prop.enum.length} values, e.g. ${JSON.stringify(prop.enum[0])})`;
18305
+ }
18306
+ if (prop.anyOf) return prop.anyOf.map(typeOf).join(" | ");
18307
+ if (Array.isArray(prop.type)) return prop.type.join("|");
18308
+ if (prop.type === "array") return `${typeOf(prop.items ?? {})}[]`;
18309
+ return prop.type ?? "object";
18310
+ };
18311
+ const parts = Object.entries(schema.properties).map(
18312
+ ([name, prop]) => `${name}${required2.has(name) ? "*" : "?"}: ${typeOf(prop)}`
18313
+ );
18314
+ return parts.join(", ");
18315
+ }
18282
18316
  function registerListCompositionsTool(server) {
18283
18317
  server.registerTool(
18284
18318
  "clipform_list_compositions",
@@ -18299,16 +18333,17 @@ function registerListCompositionsTool(server) {
18299
18333
  return errorResult(result.error);
18300
18334
  }
18301
18335
  const all = result.data.compositions;
18302
- const compositions = all.filter((c) => PUBLIC_COMPOSITIONS.includes(c.id));
18336
+ const compositions = all.filter((c) => EXPOSED_COMPOSITIONS.includes(c.id));
18303
18337
  if (!compositions.length) return textResult("No compositions found.");
18304
18338
  const lines = [`Available compositions (${compositions.length}):
18305
18339
  `];
18306
18340
  for (const comp of compositions) {
18307
18341
  const duration3 = (comp.durationInFrames / comp.fps).toFixed(0);
18308
18342
  lines.push(`- **${comp.id}** \u2014 ${comp.width}x${comp.height}, ${duration3}s`);
18343
+ lines.push(` props: ${summarizeSchema(comp.propsSchema)}`);
18309
18344
  }
18310
18345
  lines.push("");
18311
- lines.push("Use clipform_render_composition with a compositionId to render. Pass inputProps matching the composition's schema.");
18346
+ lines.push("Use clipform_render_composition with a compositionId to render. inputProps are validated strictly against the schema - unknown or missing props fail.");
18312
18347
  return textResult(lines.join("\n"));
18313
18348
  }
18314
18349
  );
@@ -18399,7 +18434,8 @@ Items: type "image" (Ken Burns motion) or "video" (cover-cropped, muted by defau
18399
18434
  async ({ items, audio_url, duration_seconds, random_effects, transition, style_preset, background_color }) => {
18400
18435
  const workspace_id = getMcpAuth()?.workspace_id;
18401
18436
  const result = await callApi("/internal/generate-video", {
18402
- timeoutMs: 6e4,
18437
+ timeoutMs: 3e5,
18438
+ // local renders pay a cold webpack bundle; Lambda is fast but bursty
18403
18439
  body: {
18404
18440
  items,
18405
18441
  audio_url,
@@ -18793,4 +18829,4 @@ export {
18793
18829
  JSONRPCMessageSchema,
18794
18830
  createServer
18795
18831
  };
18796
- //# sourceMappingURL=chunk-W3KRLWH2.js.map
18832
+ //# sourceMappingURL=chunk-5FG2V7B7.js.map