@clipform/mcp-server 4.4.1 → 4.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.
@@ -6,7 +6,7 @@ import {
6
6
  recoveryHint,
7
7
  structuredResult,
8
8
  textResult
9
- } from "./chunk-N4PLZPKS.js";
9
+ } from "./chunk-FYY23O3F.js";
10
10
  import "./chunk-BV3KA6HC.js";
11
11
  import "./chunk-PBQ5BQWD.js";
12
12
  import "./chunk-PZ5AY32C.js";
@@ -2,7 +2,7 @@ import {
2
2
  CURRENT_PLAN_VERSIONS,
3
3
  PLAN_LIMITS,
4
4
  callApi
5
- } from "./chunk-N4PLZPKS.js";
5
+ } from "./chunk-FYY23O3F.js";
6
6
  import {
7
7
  getMcpAuth
8
8
  } from "./chunk-BV3KA6HC.js";
@@ -123,4 +123,4 @@ export {
123
123
  getSessionContextWithAuth,
124
124
  getSessionContext
125
125
  };
126
- //# sourceMappingURL=chunk-HOBEHRFH.js.map
126
+ //# sourceMappingURL=chunk-74LQFWVD.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  FULL_CAPS,
3
3
  getSessionContextWithAuth
4
- } from "./chunk-HOBEHRFH.js";
4
+ } from "./chunk-74LQFWVD.js";
5
5
  import {
6
6
  FORM_TYPES,
7
7
  WORKFLOW_TYPES,
8
8
  getDiscoveryParams
9
- } from "./chunk-N4PLZPKS.js";
9
+ } from "./chunk-FYY23O3F.js";
10
10
  import {
11
11
  __export
12
12
  } from "./chunk-PZ5AY32C.js";
@@ -15231,4 +15231,4 @@ export {
15231
15231
  getWorkflowText,
15232
15232
  registerPrompts
15233
15233
  };
15234
- //# sourceMappingURL=chunk-VFZMLB2S.js.map
15234
+ //# sourceMappingURL=chunk-C66UR4R6.js.map
@@ -239,13 +239,13 @@ var FEATURES = {
239
239
  node_draw: {
240
240
  name: "Drawing",
241
241
  description: "Drawing canvas; respondents draw and it is saved as a PNG image",
242
- // Went GA 2026-06-27 (#1012), pulled back behind the allowlist 2026-07-20
243
- // (#2289) while pen options / match-to-shape mature. Prod usage at
244
- // pull-back verified = Clipform Public only, zero external customers.
245
- // Existing nodes still render (creation-gated only, camera precedent).
246
- enabled: false,
247
- status: "beta",
248
- wentLiveAt: "2026-06-27",
242
+ // First GA 2026-06-27 (#1012), pulled back behind the allowlist 2026-07-20
243
+ // (#2289), back to GA 2026-10-26 (#5052). The NODE_COMPANY_ALLOWLIST.node_draw
244
+ // entry below stays as a safety valve: flip enabled back to false to pull it
245
+ // behind the allowlist again (creation-gated only - existing nodes render).
246
+ enabled: true,
247
+ status: "live",
248
+ wentLiveAt: "2026-10-26",
249
249
  category: "node-types"
250
250
  },
251
251
  node_camera: {
@@ -253,12 +253,12 @@ var FEATURES = {
253
253
  // Description mirrors NODE_TYPES.camera.description (the node SSOT) - the
254
254
  // node captures photo OR video (allowed_capture, #2759), not photo only.
255
255
  description: "Capture a photo or video from the device camera",
256
- // Dogfooding in live via NODE_COMPANY_ALLOWLIST.node_camera below. The DB
257
- // node_type_check constraint already accepts 'camera' in prod (migration
258
- // #2103 merged + applied 2026-07-17), so GA is now a pure app-config flip:
259
- // set enabled true + status 'live' and follow feature-lifecycle.
260
- enabled: false,
261
- status: "planned",
256
+ // GA 2026-10-26 (#5017). The NODE_COMPANY_ALLOWLIST.node_camera entry
257
+ // below stays as a safety valve: flip enabled back to false to pull it
258
+ // behind the allowlist again (draw precedent).
259
+ enabled: true,
260
+ status: "live",
261
+ wentLiveAt: "2026-10-26",
262
262
  category: "node-types"
263
263
  },
264
264
  node_conditional: {
@@ -837,6 +837,8 @@ var HELP_TOPICS = {
837
837
  // from a node's type id.
838
838
  node_choice: { path: "/help/node-types", anchor: "choice" },
839
839
  node_open: { path: "/help/node-types", anchor: "open-ended" },
840
+ node_camera: { path: "/help/node-types", anchor: "camera" },
841
+ node_draw: { path: "/help/node-types", anchor: "drawing" },
840
842
  node_details: { path: "/help/node-types", anchor: "details" },
841
843
  node_button: { path: "/help/node-types", anchor: "button" },
842
844
  node_end_screen: { path: "/help/node-types", anchor: "end-screen" },
@@ -852,6 +854,19 @@ function buildHelpLinks(docsBaseUrl) {
852
854
  return links;
853
855
  }
854
856
 
857
+ // ../config/draw-presets.js
858
+ var DRAW_PRESETS = [
859
+ { id: "body-front", label: "Body diagram - front", shortLabel: "Front", file: "body-front.png", group: "body" },
860
+ { id: "body-back", label: "Body diagram - back", shortLabel: "Back", file: "body-back.png", group: "body" },
861
+ { id: "hands-palms", label: "Hands diagram - palms", shortLabel: "Palms", file: "hands-palms.png", group: "body" },
862
+ { id: "hands-backs", label: "Hands diagram - backs", shortLabel: "Backs of hands", file: "hands-backs.png", group: "body" },
863
+ { id: "feet-soles", label: "Feet diagram - soles", shortLabel: "Soles", file: "feet-soles.png", group: "body" },
864
+ { id: "face-profile", label: "Face diagram - profile", shortLabel: "Face", file: "face-profile.png", group: "body" },
865
+ { id: "vehicle-sides", label: "Vehicle diagram - sides", shortLabel: "Sides", file: "vehicle-sides.png", group: "vehicle" },
866
+ { id: "vehicle-top", label: "Vehicle diagram - top and ends", shortLabel: "Top and ends", file: "vehicle-top.png", group: "vehicle" }
867
+ ];
868
+ var DRAW_PRESET_IDS = DRAW_PRESETS.map((p) => p.id);
869
+
855
870
  // ../config/node-types.js
856
871
  var RESPONSE_FORMATS = ["text", "audio", "video"];
857
872
  var CONSENT_TYPES = ["consent", "opt_in"];
@@ -1348,8 +1363,11 @@ var NODE_TYPES = {
1348
1363
  type: { type: "string", enum: CONSENT_TYPES },
1349
1364
  // Optional attached agreement document (PDF only in v1, #2760). Served
1350
1365
  // from the public node-media bucket; `version` bumps on file replace.
1366
+ // anon_locked_file: an outside file on a guest live form (#4847), stripped from the
1367
+ // payload so the item renders as a plain consent checkbox.
1351
1368
  document: {
1352
1369
  type: "object",
1370
+ anon_locked_file: true,
1353
1371
  properties: {
1354
1372
  storage_path: { type: "string" },
1355
1373
  filename: { type: "string" },
@@ -1628,7 +1646,8 @@ var NODE_TYPES = {
1628
1646
  default: [3, 6, 12],
1629
1647
  description: "Stroke widths (px) the respondent can choose. The middle entry is the default selection; a single entry locks the pen to that width and hides the picker."
1630
1648
  },
1631
- // The reference image itself is the node's attached media (media_id,
1649
+ // The reference image is EITHER a built-in outline (`preset`, below: a static image
1650
+ // referenced by name, #5263) OR the node's attached media (media_id,
1632
1651
  // via the same media_asset/create-media.ts pipeline every other
1633
1652
  // supports_media node uses) - not a config field, to avoid a
1634
1653
  // duplicated asset ref. This only tunes its display/bake.
@@ -1637,9 +1656,11 @@ var NODE_TYPES = {
1637
1656
  label: "Diagram",
1638
1657
  description: "Display settings for the optional diagram the respondent draws on (a body, vehicle or your own image)",
1639
1658
  properties: {
1640
- // Fit + position live on the node_media placement (fit_media / position_x), shared with every media node.
1659
+ // Fit + position (uploaded image only) live on the node_media placement (fit_media / position_x), shared with every media node.
1641
1660
  opacity: { type: "number", minimum: 0, maximum: 1, default: 1, label: "Opacity", description: "Diagram opacity, from 0 (invisible) to 1 (fully opaque)" },
1642
- scale: { type: "number", minimum: 0.5, maximum: 1, default: 1, label: "Size", description: "Diagram size as a fraction of its fitted size. Applies only when the diagram is fitted (fit_media true)." }
1661
+ scale: { type: "number", minimum: 0.5, maximum: 1, default: 1, label: "Size", description: "Diagram size as a fraction of its fitted size. Applies only when the diagram is fitted (fit_media true)." },
1662
+ // A built-in outline (#5263): a static image served by the viewer, referenced by name. Not a media asset - no placement. Wins over an attached image; always shown whole and centred.
1663
+ preset: { type: "string", enum: DRAW_PRESETS.map((p) => p.id), label: "Built-in diagram", description: "Use a ready-made outline instead of an uploaded image: " + DRAW_PRESETS.map((p) => `${p.id} (${p.label})`).join(", ") + ". Shown whole and centred, so fit/position do not apply. Shown instead of any attached image while set; unset it to use the attached image of the node." }
1643
1664
  }
1644
1665
  },
1645
1666
  // Optional match-to-shape game (#2148). Absent entirely by default
@@ -1892,7 +1913,25 @@ var NODE_TYPES = {
1892
1913
  storage_path: { type: "string", description: "Bucket-prefixed storage path: respondent-captures/workspace_id/form_id/session_id/uuid.ext" },
1893
1914
  width: { type: "number", description: "Displayed pixel width, when the browser could read it (#5125)" },
1894
1915
  height: { type: "number", description: "Displayed pixel height, when the browser could read it (#5125)" },
1895
- duration: { type: "number", description: "Video duration in seconds, when readable (#5125)" }
1916
+ duration: { type: "number", description: "Video duration in seconds, when readable (#5125)" },
1917
+ // Viewer-written for a video recorded without the on-device 9:16 crop (#5253); the camera
1918
+ // video processor validates it and crops the playback copy server-side.
1919
+ preview_crop: {
1920
+ type: "object",
1921
+ description: "What the viewfinder showed (stream and preview box sizes); untrusted, validated server-side",
1922
+ properties: {
1923
+ stream_width: { type: "number" },
1924
+ stream_height: { type: "number" },
1925
+ preview_width: { type: "number" },
1926
+ preview_height: { type: "number" }
1927
+ }
1928
+ },
1929
+ // Server-written by the camera video processor (#5114); stripped from client input.
1930
+ thumbnail_storage_path: { type: "string", description: "Poster frame (webp) of a video, bucket-prefixed" },
1931
+ playback_storage_path: { type: "string", description: "Browser-safe H.264/AAC mp4 copy of a video, when the original is not one" },
1932
+ processed_at: { type: "string", description: "When the video was processed" },
1933
+ processing_attempts: { type: "integer", description: "Failed processing attempts so far" },
1934
+ processing_failed_at: { type: "string", description: "Set once processing gave up" }
1896
1935
  }
1897
1936
  },
1898
1937
  minItems: 1,
@@ -2005,8 +2044,8 @@ var NODE_TYPES = {
2005
2044
  currency: { enum: ["usd", "eur", "gbp", "cad", "aud"], type: "string", label: "Currency", default: "usd", required: true, description: "Three-letter ISO currency code" },
2006
2045
  provider: { enum: ["stripe", "paddle"], type: "string", label: "Payment Provider", default: "stripe", required: true, description: "Payment provider to use" },
2007
2046
  workspace_integration_id: { type: "string", label: "Workspace Integration ID", description: "UUID of the workspace_integrations record for the connected payment account" },
2008
- title: { type: "string", label: "Heading", description: "Heading shown above the order summary" },
2009
- description: { type: "string", label: "Description", description: "Body text shown below the heading in the order summary" }
2047
+ title: { type: "string", label: "Heading", description: "Heading shown above the order summary", anon_locked_keep: true },
2048
+ description: { type: "string", label: "Description", description: "Body text shown below the heading in the order summary", anon_locked_keep: true }
2010
2049
  },
2011
2050
  description: "Payment configuration with provider-agnostic flat structure"
2012
2051
  },
@@ -2256,7 +2295,7 @@ var NODE_TYPES = {
2256
2295
  config_schema: {
2257
2296
  type: "object",
2258
2297
  properties: {
2259
- url: { type: "string", label: "Redirect URL", placeholder: "https://example.com" },
2298
+ url: { type: "string", label: "Redirect URL", placeholder: "https://example.com", outbound_link: true },
2260
2299
  auto_redirect: { type: "boolean", label: "Auto-redirect", default: true, description: "Automatically redirect to the URL instead of showing a button" }
2261
2300
  }
2262
2301
  },
@@ -2299,7 +2338,7 @@ var NODE_TYPES = {
2299
2338
  required: ["id", "url"],
2300
2339
  properties: {
2301
2340
  id: { type: "string" },
2302
- url: { type: "string", label: "URL", placeholder: "https://example.com" },
2341
+ url: { type: "string", label: "URL", placeholder: "https://example.com", outbound_link: true },
2303
2342
  title: { type: "string", label: "Heading" },
2304
2343
  description: { type: "string", label: "Description" },
2305
2344
  order: { type: "number", label: "Sort order" }
@@ -2360,7 +2399,7 @@ var NODE_TYPES = {
2360
2399
  label: "Downloadable files"
2361
2400
  },
2362
2401
  button_text: { type: "string", label: "Continue button text", default: "Continue" },
2363
- description: { type: "string", label: "Description text" }
2402
+ description: { type: "string", label: "Description text", anon_locked_keep: true }
2364
2403
  }
2365
2404
  },
2366
2405
  response_schema: {
@@ -2629,6 +2668,32 @@ var ANON_MCP_OUTBOUND_LINK_RULES = (() => {
2629
2668
  for (const [type, def] of Object.entries(NODE_TYPES)) walk(type, def.config_schema, []);
2630
2669
  return rules;
2631
2670
  })();
2671
+ var ANON_MCP_STRIPPED_FIELD_RULES = (() => {
2672
+ const rules = ANON_MCP_OUTBOUND_LINK_RULES.filter((r) => r.kind === "non_empty" && !ANON_MCP_BLOCKED_NODE_TYPES.includes(r.type)).map(({ type, path }) => ({ type, path }));
2673
+ const walk = (type, schema, path) => {
2674
+ if (!schema || typeof schema !== "object") return;
2675
+ for (const [key, prop] of Object.entries(schema.properties ?? {})) {
2676
+ const next = [...path, key];
2677
+ if (prop.anon_locked_file === true) rules.push({ type, path: next });
2678
+ walk(type, prop, next);
2679
+ if (prop.items) walk(type, prop.items, [...next, "[]"]);
2680
+ }
2681
+ for (const branch of [...schema.oneOf ?? [], ...schema.anyOf ?? []]) walk(type, branch, path);
2682
+ };
2683
+ for (const [type, def] of Object.entries(NODE_TYPES)) {
2684
+ if (!ANON_MCP_BLOCKED_NODE_TYPES.includes(type)) walk(type, def.config_schema, []);
2685
+ }
2686
+ return rules;
2687
+ })();
2688
+ var ANON_MCP_KEPT_TEXT_KEYS = (() => {
2689
+ const out = {};
2690
+ for (const type of ANON_MCP_BLOCKED_NODE_TYPES) {
2691
+ const props = NODE_TYPES[type]?.config_schema?.properties ?? {};
2692
+ const keys = Object.entries(props).filter(([, p]) => p && p.anon_locked_keep === true && p.type === "string").map(([k]) => k);
2693
+ if (keys.length > 0) out[type] = keys;
2694
+ }
2695
+ return out;
2696
+ })();
2632
2697
 
2633
2698
  // ../config/form-types.js
2634
2699
  var FORM_TYPES = {
@@ -3014,6 +3079,7 @@ var BUSINESS = {
3014
3079
  };
3015
3080
  var MEDIA_DIRECT_MAX_BYTES = 20 * 1024 * 1024;
3016
3081
  var MEDIA_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
3082
+ var DRAW_DIAGRAM_SPEC = `PNG with simple dark outlines on a light or transparent background (no shading or text), portrait, at least 1000px wide. Up to ${Math.round(MEDIA_IMAGE_MAX_BYTES / (1024 * 1024))}MB.`;
3017
3083
  var MEDIA_DOCUMENT_MAX_BYTES = 20 * 1024 * 1024;
3018
3084
  var SUPABASE_STORAGE_MAX_BYTES = 200 * 1024 * 1024;
3019
3085
  var VIDEO_COMPRESS_FLOOR_BYTES = 1 * 1024 * 1024;
@@ -3543,4 +3609,4 @@ export {
3543
3609
  textResult,
3544
3610
  structuredResult
3545
3611
  };
3546
- //# sourceMappingURL=chunk-N4PLZPKS.js.map
3612
+ //# sourceMappingURL=chunk-FYY23O3F.js.map