@clipform/mcp-server 1.47.0 → 1.47.1

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,7 +6,7 @@ import {
6
6
  getWorkflowText,
7
7
  objectType,
8
8
  registerPrompts
9
- } from "./chunk-L3YIUY5R.js";
9
+ } from "./chunk-MV27JVSL.js";
10
10
  import {
11
11
  GUIDE_TYPES,
12
12
  QUIZ_VARIANTS,
@@ -14,7 +14,7 @@ import {
14
14
  getGuideUri,
15
15
  guideFallbackText,
16
16
  registerResources
17
- } from "./chunk-MOKUP5DR.js";
17
+ } from "./chunk-UH77CDNO.js";
18
18
  import {
19
19
  ACTIVE_NODE_TYPES,
20
20
  BUSINESS,
@@ -34,7 +34,7 @@ import {
34
34
  errorResult,
35
35
  resolveFormType,
36
36
  textResult
37
- } from "./chunk-F2JA2N5N.js";
37
+ } from "./chunk-PJNOCHKR.js";
38
38
  import {
39
39
  __commonJS,
40
40
  __export,
@@ -17749,7 +17749,7 @@ var MediaItemSchema = external_exports.object({
17749
17749
  ).optional().describe("Per-word timestamps within the segment")
17750
17750
  })
17751
17751
  ).optional().describe("Word-level captions from clipform_generate_tts. Required for per-word highlighting - pass the full objects including 'words' arrays."),
17752
- show_captions: external_exports.boolean().optional().default(true).describe("Display captions/subtitles on the node"),
17752
+ show_captions: external_exports.boolean().optional().describe("Display captions/subtitles on the node. Defaults to on; pass false to hide them."),
17753
17753
  fit_media: external_exports.boolean().optional().describe("Show the whole frame (contain) instead of cover-cropping. ALWAYS set true when attaching renders from clipform_render_composition or clipform_generate_video - they are composed 9:16 frames that must never be cropped. Leave unset for user-supplied media (arbitrary aspect ratios want the cover default).")
17754
17754
  });
17755
17755
  function registerUploadNodeMediaTool(server) {
@@ -17759,7 +17759,7 @@ function registerUploadNodeMediaTool(server) {
17759
17759
  title: "Upload Node Media",
17760
17760
  description: `Upload media for one or more nodes. Pass one item or many (max 10). Multiple items upload sequentially.
17761
17761
 
17762
- When a public URL is provided, the media is fetched and stored automatically. Only works on node types that support media (${MEDIA_SUPPORTED_TYPES.join(", ")}). For video: ingested via Mux. For image: stored in Supabase. Captions from clipform_generate_tts enable per-word highlighting in the viewer. When attaching renders from clipform_render_composition or clipform_generate_video, set fit_media: true on each item.`,
17762
+ When a public URL is provided, the media is fetched and stored automatically. Only works on node types that support media (${MEDIA_SUPPORTED_TYPES.join(", ")}). For video: ingested via Mux. For image: stored in Supabase. Each upload lands in your workspace media library and is then attached to the node (so it is reusable across nodes), matching the builder. Captions from clipform_generate_tts enable per-word highlighting in the viewer. When attaching renders from clipform_render_composition or clipform_generate_video, set fit_media: true on each item.`,
17763
17763
  inputSchema: {
17764
17764
  form_id: external_exports.string().uuid().describe("The form UUID (returned by clipform_create_form, not the short share_id from the URL)"),
17765
17765
  items: external_exports.array(MediaItemSchema).min(1).max(10).describe("One or more media items to upload")
@@ -17772,42 +17772,75 @@ When a public URL is provided, the media is fetched and stored automatically. On
17772
17772
  }
17773
17773
  },
17774
17774
  async ({ form_id, items }) => {
17775
+ const workspaceId = getMcpAuth()?.workspace_id;
17775
17776
  const lines = [];
17776
17777
  let successCount = 0;
17777
17778
  for (let i = 0; i < items.length; i++) {
17778
17779
  const item = items[i];
17779
17780
  if (items.length > 1) lines.push(`--- Item ${i + 1} (node ${item.node_id}) ---`);
17780
- const body = {
17781
+ if (!workspaceId) {
17782
+ lines.push(
17783
+ "FAILED: no workspace in context - reconnect the MCP or set CLIPFORM_API_KEY so media can land in your library."
17784
+ );
17785
+ lines.push("");
17786
+ continue;
17787
+ }
17788
+ const createBody = {
17781
17789
  media_type: item.media_type,
17782
17790
  media_source: item.media_source
17783
17791
  };
17784
- if (item.url) body.url = item.url;
17785
- if (item.captions) body.captions = item.captions;
17786
- if (item.show_captions !== void 0) body.show_captions = item.show_captions;
17787
- if (item.fit_media !== void 0) body.fit_media = item.fit_media;
17788
- const result = await callApi(
17789
- `/forms/${form_id}/nodes/${item.node_id}/media`,
17790
- { method: "POST", body }
17791
- );
17792
- if (result.ok) {
17793
- successCount++;
17794
- const resultLines = [];
17795
- if (result.data.upload_url) {
17796
- resultLines.push(
17797
- `Upload URL: ${result.data.upload_url}`,
17798
- `Upload method: ${result.data.upload_method}`,
17799
- `Upload the file directly to the upload URL using ${result.data.upload_method === "tus" ? "TUS resumable upload" : "HTTP PUT"}.`
17800
- );
17801
- } else {
17802
- resultLines.push(`Media stored.`);
17803
- }
17804
- if (item.captions) {
17805
- resultLines.push(`Captions: ${item.captions.length} segments saved`);
17792
+ if (item.url) createBody.url = item.url;
17793
+ if (item.captions) createBody.captions = item.captions;
17794
+ const created = await callApi(`/workspaces/${workspaceId}/media`, { method: "POST", body: createBody });
17795
+ if (!created.ok) {
17796
+ lines.push(`FAILED: ${created.error}`);
17797
+ lines.push("");
17798
+ continue;
17799
+ }
17800
+ const mediaAssetId = created.data.media_asset_id;
17801
+ if (!mediaAssetId) {
17802
+ lines.push(`FAILED: upload did not return a media asset id (route ${String(created.data.route ?? "unknown")}).`);
17803
+ lines.push("");
17804
+ continue;
17805
+ }
17806
+ const attached = await callApi(`/forms/${form_id}/nodes/${item.node_id}/media/attach`, {
17807
+ method: "POST",
17808
+ body: { media_asset_id: mediaAssetId }
17809
+ });
17810
+ if (!attached.ok) {
17811
+ lines.push(`FAILED to attach the uploaded media to the node: ${attached.error}`);
17812
+ lines.push("");
17813
+ continue;
17814
+ }
17815
+ const presentation = {};
17816
+ if (item.fit_media !== void 0) presentation.fit_media = item.fit_media;
17817
+ if (item.show_captions !== void 0) presentation.show_captions = item.show_captions;
17818
+ let presentationNote = "";
17819
+ if (Object.keys(presentation).length > 0) {
17820
+ const patched = await callApi(`/forms/${form_id}/nodes/${item.node_id}/media`, {
17821
+ method: "PATCH",
17822
+ body: presentation
17823
+ });
17824
+ if (!patched.ok) {
17825
+ presentationNote = `Note: media attached, but display settings were not applied: ${patched.error}`;
17806
17826
  }
17807
- lines.push(resultLines.join("\n"));
17827
+ }
17828
+ successCount++;
17829
+ const resultLines = [];
17830
+ if (created.data.upload_url) {
17831
+ resultLines.push(
17832
+ `Upload URL: ${created.data.upload_url}`,
17833
+ `Upload method: ${created.data.upload_method}`,
17834
+ `Upload the file directly to the upload URL using ${created.data.upload_method === "tus" ? "TUS resumable upload" : "HTTP PUT"}.`
17835
+ );
17808
17836
  } else {
17809
- lines.push(`FAILED: ${result.error}`);
17837
+ resultLines.push(`Media stored in the workspace library and attached to the node.`);
17838
+ }
17839
+ if (item.captions) {
17840
+ resultLines.push(`Captions: ${item.captions.length} segments saved`);
17810
17841
  }
17842
+ if (presentationNote) resultLines.push(presentationNote);
17843
+ lines.push(resultLines.join("\n"));
17811
17844
  lines.push("");
17812
17845
  }
17813
17846
  if (items.length > 1) {
@@ -19047,4 +19080,4 @@ export {
19047
19080
  JSONRPCMessageSchema,
19048
19081
  createServer
19049
19082
  };
19050
- //# sourceMappingURL=chunk-KP64A2KW.js.map
19083
+ //# sourceMappingURL=chunk-JT7YWEQP.js.map