@clipform/mcp-server 2.0.4 → 2.1.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.
@@ -164,13 +164,26 @@ var FEATURES = {
164
164
  node_draw: {
165
165
  name: "Drawing",
166
166
  description: "Drawing canvas; respondents draw and it is saved as a PNG image",
167
- // Live (#1012): builder picker shows it, the API accepts it, the viewer renders
168
- // the canvas, and dashboard results render the saved PNG (#1012 results pass).
169
- enabled: true,
170
- status: "live",
167
+ // Went GA 2026-06-27 (#1012), pulled back behind the allowlist 2026-07-20
168
+ // (#2289) while pen options / match-to-shape mature. Prod usage at
169
+ // pull-back verified = Clipform Public only, zero external customers.
170
+ // Existing nodes still render (creation-gated only, camera precedent).
171
+ enabled: false,
172
+ status: "beta",
171
173
  wentLiveAt: "2026-06-27",
172
174
  category: "node-types"
173
175
  },
176
+ node_camera: {
177
+ name: "Camera",
178
+ description: "Capture a photo from the device camera",
179
+ // Scaffolded disabled (#2097): code lands ready, but node.type's DB check
180
+ // constraint doesn't accept 'camera' yet - that's a separate parked
181
+ // holds-migration PR. Flip once the migration has merged (= applied to
182
+ // prod) and the apps have deployed.
183
+ enabled: false,
184
+ status: "planned",
185
+ category: "node-types"
186
+ },
174
187
  node_payment: {
175
188
  name: "Payment",
176
189
  description: "Collect payments via Stripe or Paddle inline",
@@ -284,6 +297,21 @@ var FEATURES = {
284
297
  share_node: {
285
298
  name: "Share individual nodes",
286
299
  description: "Share a direct link to a specific node within a form",
300
+ enabled: true,
301
+ status: "live",
302
+ wentLiveAt: "2026-07-17",
303
+ category: "sharing"
304
+ },
305
+ public_results: {
306
+ name: "Public results portal",
307
+ description: "Share a live, read-only results page with anyone via a link",
308
+ // Ships dark (#2129): code lands ready, gated server-side (apps/api) on
309
+ // this flag OR the FEATURE_COMPANY_ALLOWLIST.public_results company
310
+ // allowlist below (companyHasPublicResults) for per-company dogfood ahead
311
+ // of the global flip - same flag-or-allowlist pattern as node_camera /
312
+ // companyHasNodeType. Flip enabled/status together for GA - the API
313
+ // re-checks this flag on every enable/rotate/read, so flipping it on/off
314
+ // (or editing the allowlist) takes effect immediately, no redeploy needed.
287
315
  enabled: false,
288
316
  status: "planned",
289
317
  category: "sharing"
@@ -503,6 +531,13 @@ for (const [key, f] of Object.entries(FEATURES)) {
503
531
  // ../config/node-types.js
504
532
  var RESPONSE_FORMATS = ["text", "audio", "video"];
505
533
  var CONSENT_TYPES = ["consent", "opt_in"];
534
+ var DRAW_GAME_DEFAULT_TIERS = [
535
+ { min_score: 0, label: "Scribble" },
536
+ { min_score: 35, label: "Warming up" },
537
+ { min_score: 55, label: "Nice try" },
538
+ { min_score: 75, label: "Great match" },
539
+ { min_score: 92, label: "Perfect" }
540
+ ];
506
541
  var NODE_TYPES = {
507
542
  start: {
508
543
  label: "Start",
@@ -1111,7 +1146,7 @@ var NODE_TYPES = {
1111
1146
  maxItems: 8,
1112
1147
  label: "Pen colours",
1113
1148
  default: ["#1F2937", "#EF4444", "#3B82F6", "#22C55E", "#FACC15"],
1114
- description: "Colour swatches the respondent can draw with"
1149
+ description: "Colour swatches the respondent can draw with. The first entry is the default selection; a single entry locks the pen to that colour and hides the picker."
1115
1150
  },
1116
1151
  stroke_widths: {
1117
1152
  type: "array",
@@ -1120,7 +1155,7 @@ var NODE_TYPES = {
1120
1155
  maxItems: 5,
1121
1156
  label: "Pen thicknesses",
1122
1157
  default: [3, 6, 12],
1123
- description: "Stroke widths (px) the respondent can choose"
1158
+ description: "Stroke widths (px) the respondent can choose. The first entry is the default selection; a single entry locks the pen to that width and hides the picker."
1124
1159
  },
1125
1160
  // The reference image itself is the node's attached media (media_id,
1126
1161
  // via the same media_asset/create-media.ts pipeline every other
@@ -1134,6 +1169,55 @@ var NODE_TYPES = {
1134
1169
  fit: { type: "string", enum: ["cover", "contain"], default: "contain", label: "Fit", description: "contain letterboxes the image, cover crops it to fill the canvas" },
1135
1170
  opacity: { type: "number", minimum: 0, maximum: 1, default: 1, label: "Opacity", description: "Background image opacity, from 0 (invisible) to 1 (fully opaque)" }
1136
1171
  }
1172
+ },
1173
+ // Optional match-to-shape game (#2148). Absent entirely by default
1174
+ // (not in default_config) - a node with no `game.target` behaves
1175
+ // exactly as it did before this key existed. `target.points` is
1176
+ // authored once in the builder (a simplified sketch modal, see
1177
+ // apps/dashboard) and stored pre-normalized to a [0,1] unit box so the
1178
+ // viewer's scorer (apps/viewer/lib/matchShape.ts) and the reveal
1179
+ // overlay share the same coordinate frame without re-deriving it.
1180
+ game: {
1181
+ type: "object",
1182
+ label: "Match-to-shape game",
1183
+ description: "Optional target shape the drawing is scored against on submit",
1184
+ properties: {
1185
+ target: {
1186
+ type: "object",
1187
+ label: "Target shape",
1188
+ description: "The outline the respondent is scored against, drawn once by the form builder",
1189
+ properties: {
1190
+ points: {
1191
+ type: "array",
1192
+ minItems: 2,
1193
+ maxItems: 500,
1194
+ items: {
1195
+ type: "object",
1196
+ properties: {
1197
+ x: { type: "number", minimum: 0, maximum: 1 },
1198
+ y: { type: "number", minimum: 0, maximum: 1 }
1199
+ }
1200
+ },
1201
+ description: "Closed polyline outline, normalized to a [0,1] unit box (aspect-preserving)"
1202
+ }
1203
+ }
1204
+ },
1205
+ tiers: {
1206
+ type: "array",
1207
+ label: "Score tiers",
1208
+ minItems: 1,
1209
+ maxItems: 10,
1210
+ items: {
1211
+ type: "object",
1212
+ properties: {
1213
+ min_score: { type: "number", minimum: 0, maximum: 100 },
1214
+ label: { type: "string" }
1215
+ }
1216
+ },
1217
+ default: DRAW_GAME_DEFAULT_TIERS,
1218
+ description: "Score bands shown in the reveal, ascending by min_score - defaults to a 5-band Scribble to Perfect scale"
1219
+ }
1220
+ }
1137
1221
  }
1138
1222
  }
1139
1223
  },
@@ -1155,6 +1239,17 @@ var NODE_TYPES = {
1155
1239
  mime_type: { type: "string", description: "Image MIME type (image/png)" }
1156
1240
  },
1157
1241
  description: "The exported sketch, stored as a single image in media-responses"
1242
+ },
1243
+ // Present only when the node has a configured game.target - absent for
1244
+ // every draw node published before #2148 and for one with no target.
1245
+ game: {
1246
+ type: "object",
1247
+ description: "Present when the node has a configured target shape - the respondent's match-to-shape score",
1248
+ properties: {
1249
+ score: { type: "number", minimum: 0, maximum: 100, description: "0-100 match score against the target outline" },
1250
+ avg_deviation: { type: "number", minimum: 0, description: "Average normalized deviation from the target outline (lower is better)" },
1251
+ tier: { type: "string", description: "The configured tier label the score falls into" }
1252
+ }
1158
1253
  }
1159
1254
  }
1160
1255
  },
@@ -1173,6 +1268,105 @@ var NODE_TYPES = {
1173
1268
  download_url: { type: "string", format: "uri", description: "Same link with a forced download (Content-Disposition: attachment)" },
1174
1269
  expires_at: { type: "string", format: "date-time", description: "When url/download_url stop working" }
1175
1270
  }
1271
+ },
1272
+ // Mirrors response_schema.game (piece 1 of #2148) - transformResponse
1273
+ // passes it through unchanged, so this describes the FINAL emitted shape.
1274
+ game: {
1275
+ type: "object",
1276
+ description: "Present when the node has a configured target shape - the respondent's match-to-shape score",
1277
+ properties: {
1278
+ score: { type: "number", minimum: 0, maximum: 100, description: "0-100 match score against the target outline" },
1279
+ avg_deviation: { type: "number", minimum: 0, description: "Average normalized deviation from the target outline (lower is better)" },
1280
+ tier: { type: "string", description: "The configured tier label the score falls into" }
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+ },
1286
+ camera: {
1287
+ label: "Camera",
1288
+ shorthand: "Camera",
1289
+ icon: "Camera",
1290
+ color: "#FCE7F3",
1291
+ description: "Capture a photo from the device camera",
1292
+ category: "input",
1293
+ sort_order: 6.6,
1294
+ has_options: false,
1295
+ is_terminal: false,
1296
+ show_nav_bar: true,
1297
+ loading: "lazy",
1298
+ supports_prompt: false,
1299
+ supports_media: false,
1300
+ is_system: false,
1301
+ show_in_results: true,
1302
+ default_config: null,
1303
+ config_schema: {
1304
+ type: "object",
1305
+ properties: {
1306
+ camera_facing: {
1307
+ type: "string",
1308
+ enum: ["user", "environment"],
1309
+ default: "user",
1310
+ label: "Default camera",
1311
+ description: "Which camera the device opens by default (a hint only - the respondent can still switch)",
1312
+ enumLabels: { user: "Front (selfie)", environment: "Rear" }
1313
+ },
1314
+ allow_library_upload: {
1315
+ type: "boolean",
1316
+ default: true,
1317
+ label: "Allow choosing from photo library",
1318
+ description: "Show a secondary option to pick an existing photo instead of taking a new one"
1319
+ }
1320
+ }
1321
+ },
1322
+ // Reuses file_upload's response shape verbatim (single-item array) so
1323
+ // Results/exports/webhooks treat it the same way (scaffold skill: shape reuse).
1324
+ response_schema: {
1325
+ type: "object",
1326
+ required: ["files"],
1327
+ properties: {
1328
+ files: {
1329
+ type: "array",
1330
+ items: {
1331
+ type: "object",
1332
+ required: ["id", "name", "storage_path", "url", "mime_type", "size", "uploaded_at"],
1333
+ properties: {
1334
+ id: { type: "string", format: "uuid", description: "Unique file identifier" },
1335
+ url: { type: "string", format: "uri", description: "Signed Supabase Storage URL for download" },
1336
+ name: { type: "string", description: "Original filename" },
1337
+ size: { type: "integer", minimum: 1, description: "File size in bytes" },
1338
+ mime_type: { type: "string", description: "File MIME type" },
1339
+ uploaded_at: { type: "string", format: "date-time", description: "ISO timestamp of upload completion" },
1340
+ storage_path: { type: "string", description: "Full storage path: workspace_id/form_id/node_id/uuid.ext" }
1341
+ }
1342
+ },
1343
+ minItems: 1,
1344
+ maxItems: 1,
1345
+ description: "The captured photo (single-item array, mirroring file_upload)"
1346
+ }
1347
+ }
1348
+ },
1349
+ output_schema: {
1350
+ type: "object",
1351
+ required: ["node_type"],
1352
+ properties: {
1353
+ node_type: { type: "string", const: "camera" },
1354
+ files: {
1355
+ type: "array",
1356
+ description: "The captured photo, as a canonical media object with a fresh signed link.",
1357
+ items: {
1358
+ type: "object",
1359
+ properties: {
1360
+ id: { type: "string", description: "Unique file identifier" },
1361
+ filename: { type: "string", description: "Original filename" },
1362
+ content_type: { type: "string", description: "File MIME type" },
1363
+ size: { type: "integer", description: "File size in bytes" },
1364
+ uploaded_at: { type: "string", format: "date-time", description: "ISO timestamp of upload completion" },
1365
+ url: { type: "string", format: "uri", description: "Direct, time-limited signed link (~48h, supports HTTP range)" },
1366
+ download_url: { type: "string", format: "uri", description: "Same link with a forced download (Content-Disposition: attachment)" },
1367
+ expires_at: { type: "string", format: "date-time", description: "When url/download_url stop working" }
1368
+ }
1369
+ }
1176
1370
  }
1177
1371
  }
1178
1372
  }
@@ -1911,7 +2105,8 @@ var HELP_TOPICS = {
1911
2105
  cantGoLive: { path: "/help/sharing", anchor: "cant-go-live" },
1912
2106
  liveAndDraft: { path: "/help/managing-forms", anchor: "live-and-draft" },
1913
2107
  publishingChanges: { path: "/help/managing-forms", anchor: "publishing-changes" },
1914
- embedding: { path: "/help/embed", anchor: null }
2108
+ embedding: { path: "/help/embed", anchor: null },
2109
+ publicResults: { path: "/help/public-results", anchor: null }
1915
2110
  };
1916
2111
  function buildHelpLinks(docsBaseUrl) {
1917
2112
  const links = {};
@@ -2311,4 +2506,4 @@ export {
2311
2506
  getSessionContextWithAuth,
2312
2507
  getSessionContext
2313
2508
  };
2314
- //# sourceMappingURL=chunk-ET43M6YO.js.map
2509
+ //# sourceMappingURL=chunk-CNEUXDNC.js.map