@clipform/mcp-server 1.22.1 → 1.23.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,19 +6,30 @@ import {
6
6
  getWorkflowText,
7
7
  objectType,
8
8
  registerPrompts
9
- } from "./chunk-DWFACCUE.js";
9
+ } from "./chunk-UW6HXM2U.js";
10
10
  import {
11
11
  GUIDE_TYPES,
12
12
  QUIZ_VARIANTS,
13
13
  getGuideContent,
14
14
  getGuideUri,
15
15
  registerResources
16
- } from "./chunk-DDSNGWKB.js";
16
+ } from "./chunk-ZJJBZGO6.js";
17
17
  import {
18
+ BUSINESS,
19
+ CONTACT_FIELDS,
20
+ FEATURES,
21
+ FORM_TYPE_ALIASES,
22
+ KEN_BURNS_EFFECTS,
23
+ KEN_BURNS_FIT_MODES,
24
+ KEN_BURNS_PRESETS,
25
+ NODE_TYPES,
26
+ NON_COUNTABLE_TYPES,
27
+ SLIDESHOW_TRANSITIONS,
18
28
  callApi,
19
29
  errorResult,
30
+ resolveFormType,
20
31
  textResult
21
- } from "./chunk-Z7CP5LVY.js";
32
+ } from "./chunk-4EXXG7OF.js";
22
33
  import {
23
34
  __commonJS,
24
35
  __export,
@@ -16880,1302 +16891,6 @@ import { readFileSync } from "fs";
16880
16891
  import { dirname, join } from "path";
16881
16892
  import { fileURLToPath } from "url";
16882
16893
 
16883
- // ../config/node-types.js
16884
- var NODE_TYPES = {
16885
- start: {
16886
- label: "Start",
16887
- shorthand: "Start",
16888
- icon: "ArrowRight",
16889
- color: "#D1FAE5",
16890
- description: "Entry point for the form - connects to the first node",
16891
- category: "start",
16892
- sort_order: 0,
16893
- has_options: false,
16894
- is_terminal: false,
16895
- show_nav_bar: false,
16896
- loading: "eager",
16897
- supports_prompt: false,
16898
- supports_media: false,
16899
- is_system: true,
16900
- is_active: true,
16901
- show_in_results: false,
16902
- default_config: null,
16903
- config_schema: null,
16904
- response_schema: null,
16905
- output_schema: null
16906
- },
16907
- choice: {
16908
- label: "Multiple Choice",
16909
- shorthand: "Multi",
16910
- icon: "CheckSquare",
16911
- color: "#DBEAFE",
16912
- description: "Single or multiple choice node with predefined options",
16913
- category: "input",
16914
- sort_order: 1,
16915
- has_options: true,
16916
- min_options: 1,
16917
- max_options: 6,
16918
- max_option_length: 36,
16919
- is_terminal: false,
16920
- show_nav_bar: true,
16921
- loading: "eager",
16922
- supports_prompt: true,
16923
- supports_media: true,
16924
- is_system: false,
16925
- is_active: true,
16926
- show_in_results: true,
16927
- default_config: {
16928
- selection_mode: "single",
16929
- choice: { enable_branching: true, record_scores: false },
16930
- randomise_options: false,
16931
- show_option_count: false,
16932
- options: [
16933
- { content: "Option 1" },
16934
- { content: "Option 2" }
16935
- ]
16936
- },
16937
- config_schema: {
16938
- type: "object",
16939
- properties: {
16940
- choice: {
16941
- type: "object",
16942
- properties: {
16943
- enable_branching: {
16944
- type: "boolean",
16945
- label: "Enable branching logic",
16946
- default: true,
16947
- description: "Allow each option to have its own logic path. When disabled, all options share a single jump action."
16948
- },
16949
- show_answer_feedback: {
16950
- type: "boolean",
16951
- label: "Show answer feedback",
16952
- default: false,
16953
- description: "Show correct/incorrect feedback after selection (requires scored options)."
16954
- },
16955
- record_scores: {
16956
- type: "boolean",
16957
- label: "Mark correct answer",
16958
- default: false,
16959
- description: "Select which option is the correct answer."
16960
- }
16961
- }
16962
- },
16963
- selection_mode: {
16964
- enum: ["single", "multiple"],
16965
- type: "string",
16966
- label: "Selection mode",
16967
- default: "single",
16968
- description: "Allow single or multiple selections"
16969
- },
16970
- allow_text_response: {
16971
- type: "boolean",
16972
- label: "Allow text response",
16973
- default: false,
16974
- description: "Allow free-text response in addition to options (single choice only)"
16975
- },
16976
- randomise_options: {
16977
- type: "boolean",
16978
- label: "Randomise options",
16979
- default: false,
16980
- description: "Show options in random order"
16981
- },
16982
- show_option_count: {
16983
- type: "boolean",
16984
- label: "Show option count",
16985
- default: false,
16986
- description: "Display number of options"
16987
- },
16988
- content_media_type: {
16989
- enum: ["upload", "recorded"],
16990
- type: "string",
16991
- label: "Content media type",
16992
- description: "How the node media was provided"
16993
- }
16994
- }
16995
- },
16996
- response_schema: {
16997
- type: "string",
16998
- description: "Selected option ID"
16999
- },
17000
- output_schema: {
17001
- type: "object",
17002
- required: ["type", "label", "option_id"],
17003
- properties: {
17004
- type: { type: "string", const: "choice" },
17005
- label: { type: "string", description: "Human-readable option label" },
17006
- option_id: { type: "string", format: "uuid", description: "Selected option UUID" }
17007
- }
17008
- }
17009
- },
17010
- open: {
17011
- label: "Open Ended",
17012
- shorthand: "Open",
17013
- icon: "Type",
17014
- color: "#DBEAFE",
17015
- description: "Free-form text responses from users",
17016
- category: "input",
17017
- sort_order: 2,
17018
- has_options: false,
17019
- is_terminal: false,
17020
- show_nav_bar: true,
17021
- loading: "eager",
17022
- supports_prompt: true,
17023
- supports_media: true,
17024
- is_system: false,
17025
- is_active: true,
17026
- show_in_results: true,
17027
- default_config: {
17028
- formats: [
17029
- { order: 0, format: "text" },
17030
- { order: 1, format: "audio" },
17031
- { order: 2, format: "video" }
17032
- ]
17033
- },
17034
- config_schema: {
17035
- type: "object",
17036
- properties: {
17037
- formats: {
17038
- type: "array",
17039
- items: {
17040
- type: "object",
17041
- properties: {
17042
- format: { enum: ["text", "audio", "video"], type: "string" },
17043
- order: { type: "number" }
17044
- }
17045
- },
17046
- label: "Allowed response formats",
17047
- description: "Which formats the user can respond with, in display order"
17048
- },
17049
- content_media_type: {
17050
- enum: ["upload", "recorded"],
17051
- type: "string",
17052
- label: "Content media type",
17053
- description: "How the node media was provided"
17054
- }
17055
- }
17056
- },
17057
- response_schema: {
17058
- type: "object",
17059
- required: ["response_type"],
17060
- properties: {
17061
- text: {
17062
- type: "string",
17063
- description: "Text response (when response_type is text) or transcribed text from audio/video"
17064
- },
17065
- media: {
17066
- type: "object",
17067
- properties: {
17068
- type: { enum: ["audio", "video"], type: "string" },
17069
- storage_path: { type: "string" },
17070
- facing_mode: { enum: ["user", "environment"], type: "string" },
17071
- preview_crop: {
17072
- type: "object",
17073
- properties: {
17074
- stream_width: { type: "number" },
17075
- stream_height: { type: "number" },
17076
- preview_width: { type: "number" },
17077
- preview_height: { type: "number" }
17078
- }
17079
- }
17080
- },
17081
- description: "Media response (when response_type is audio or video)"
17082
- },
17083
- response_type: {
17084
- enum: ["text", "audio", "video"],
17085
- type: "string"
17086
- },
17087
- transcription: {
17088
- type: "object",
17089
- properties: {
17090
- text: { type: "string" },
17091
- language: { type: "string" },
17092
- duration: { type: "number" },
17093
- words: { type: "array" }
17094
- },
17095
- description: "Whisper transcription data for audio/video responses"
17096
- }
17097
- }
17098
- },
17099
- output_schema: {
17100
- type: "object",
17101
- required: ["type"],
17102
- properties: {
17103
- type: { type: "string", const: "text" },
17104
- text: { type: "string", description: "Text response or transcription" },
17105
- media: {
17106
- type: "object",
17107
- properties: {
17108
- type: { enum: ["audio", "video"], type: "string" },
17109
- storage_path: { type: "string" },
17110
- facing_mode: { enum: ["user", "environment"], type: "string" },
17111
- preview_crop: {
17112
- type: "object",
17113
- properties: {
17114
- stream_width: { type: "number" },
17115
- stream_height: { type: "number" },
17116
- preview_width: { type: "number" },
17117
- preview_height: { type: "number" }
17118
- }
17119
- }
17120
- }
17121
- },
17122
- transcription: {
17123
- type: "object",
17124
- properties: {
17125
- text: { type: "string" },
17126
- language: { type: "string" }
17127
- }
17128
- }
17129
- }
17130
- }
17131
- },
17132
- scale: {
17133
- label: "Scale",
17134
- shorthand: "Scale",
17135
- icon: "BarChart3",
17136
- color: "#DBEAFE",
17137
- description: "Numerical rating or scale node (1-10, etc.)",
17138
- category: "input",
17139
- sort_order: 3,
17140
- has_options: false,
17141
- is_terminal: false,
17142
- show_nav_bar: true,
17143
- loading: "eager",
17144
- supports_prompt: true,
17145
- supports_media: true,
17146
- is_system: false,
17147
- is_active: false,
17148
- show_in_results: true,
17149
- default_config: null,
17150
- config_schema: {
17151
- type: "object",
17152
- properties: {
17153
- max: { type: "number", label: "Maximum value", default: 10, required: true },
17154
- min: { type: "number", label: "Minimum value", default: 1, required: true },
17155
- step: { min: 0.1, type: "number", label: "Step increment", default: 1 },
17156
- left_label: { type: "string", label: "Left label", placeholder: "Not likely" },
17157
- right_label: { type: "string", label: "Right label", placeholder: "Very likely" },
17158
- show_numbers: { type: "boolean", label: "Show numbers", default: true }
17159
- }
17160
- },
17161
- response_schema: {
17162
- type: "number",
17163
- description: "Selected scale value"
17164
- },
17165
- output_schema: null
17166
- },
17167
- booking: {
17168
- label: "Booking",
17169
- shorthand: "Booking",
17170
- icon: "Calendar",
17171
- color: "#E9D5FF",
17172
- description: null,
17173
- category: "action",
17174
- sort_order: 4,
17175
- has_options: false,
17176
- is_terminal: false,
17177
- show_nav_bar: true,
17178
- loading: "lazy",
17179
- supports_prompt: false,
17180
- supports_media: false,
17181
- is_system: false,
17182
- is_active: false,
17183
- show_in_results: true,
17184
- default_config: null,
17185
- config_schema: {
17186
- type: "object",
17187
- oneOf: [
17188
- {
17189
- required: ["calendly"],
17190
- properties: {
17191
- calendly: {
17192
- type: "object",
17193
- properties: {
17194
- event_name: { type: "string", label: "Event name", description: "Display name for the event" },
17195
- event_type_uri: { type: "string", label: "Event type URI", format: "uri", description: "Your Calendly event type URI", placeholder: "https://calendly.com/your-link" }
17196
- }
17197
- }
17198
- }
17199
- },
17200
- {
17201
- required: ["google_meet"],
17202
- properties: {
17203
- google_meet: {
17204
- type: "object",
17205
- properties: {
17206
- duration: { type: "number", label: "Duration (minutes)", default: 30, description: "Meeting duration in minutes" },
17207
- calendar_id: { type: "string", label: "Calendar", description: "Google Calendar to use for bookings" },
17208
- event_title: { type: "string", label: "Event title", default: "Meeting", description: "Default title for scheduled meetings" },
17209
- calendar_name: { type: "string", label: "Calendar name", description: "Display name for the selected calendar" }
17210
- }
17211
- }
17212
- }
17213
- }
17214
- ],
17215
- description: "Booking provider configuration (one provider per node)"
17216
- },
17217
- response_schema: {
17218
- type: "object",
17219
- oneOf: [
17220
- {
17221
- required: ["calendly"],
17222
- properties: {
17223
- calendly: {
17224
- type: "object",
17225
- required: ["event_uri", "scheduled_time"],
17226
- properties: {
17227
- event_uri: { type: "string", format: "uri" },
17228
- event_type: { type: "string" },
17229
- invitee_uri: { type: "string", format: "uri" },
17230
- reschedule_url: { type: "string", format: "uri" },
17231
- scheduled_time: { type: "string", format: "date-time" },
17232
- cancellation_url: { type: "string", format: "uri" }
17233
- }
17234
- }
17235
- }
17236
- }
17237
- ],
17238
- description: "Booking response with provider-specific data"
17239
- },
17240
- output_schema: null
17241
- },
17242
- contact: {
17243
- label: "Contact Form",
17244
- shorthand: "Contact",
17245
- icon: "User",
17246
- color: "#FEF9C3",
17247
- description: "Collect standardized contact information (name, email, phone, company)",
17248
- category: "input",
17249
- sort_order: 5,
17250
- has_options: false,
17251
- is_terminal: false,
17252
- show_nav_bar: true,
17253
- loading: "lazy",
17254
- supports_prompt: false,
17255
- supports_media: false,
17256
- is_system: false,
17257
- is_active: true,
17258
- show_in_results: false,
17259
- default_config: {
17260
- fields: [
17261
- { id: "first_name", type: "first_name", label: "First Name", enabled: true, required: true },
17262
- { id: "email", type: "email", label: "Email", enabled: true, required: true }
17263
- ],
17264
- consent_items: [
17265
- { id: "default-consent", name: "Privacy policy", label: "I agree to the privacy policy and terms of service", order: 0, type: "consent" }
17266
- ]
17267
- },
17268
- config_schema: {
17269
- type: "object",
17270
- required: ["fields"],
17271
- properties: {
17272
- title: { type: "string" },
17273
- fields: {
17274
- type: "array",
17275
- minItems: 1,
17276
- items: {
17277
- type: "object",
17278
- required: ["id", "required"],
17279
- properties: {
17280
- id: { type: "string" },
17281
- type: { enum: ["text", "textarea", "email", "tel", "url"], type: "string" },
17282
- label: { type: "string" },
17283
- order: { type: "number" },
17284
- required: { type: "boolean", default: true },
17285
- is_custom: { type: "boolean", default: false }
17286
- }
17287
- }
17288
- },
17289
- description: { type: "string" },
17290
- consent_items: {
17291
- type: "array",
17292
- items: {
17293
- type: "object",
17294
- properties: {
17295
- id: { type: "string" },
17296
- name: { type: "string" },
17297
- label: { type: "string" },
17298
- order: { type: "number" },
17299
- type: { type: "string", enum: ["consent", "opt_in"] }
17300
- }
17301
- }
17302
- }
17303
- }
17304
- },
17305
- response_schema: {
17306
- type: "object",
17307
- required: ["fields"],
17308
- properties: {
17309
- fields: {
17310
- type: "array",
17311
- items: {
17312
- type: "object",
17313
- required: ["id", "type", "label", "value"],
17314
- properties: {
17315
- id: { type: "string" },
17316
- type: { type: "string" },
17317
- label: { type: "string" },
17318
- value: { type: "string" }
17319
- }
17320
- },
17321
- description: "Contact form field entries with metadata"
17322
- },
17323
- consent: {
17324
- type: "array",
17325
- items: {
17326
- type: "object",
17327
- required: ["id", "name", "label", "accepted", "type"],
17328
- properties: {
17329
- id: { type: "string" },
17330
- name: { type: "string" },
17331
- label: { type: "string" },
17332
- accepted: { type: "boolean" },
17333
- type: { type: "string", enum: ["consent", "opt_in"] }
17334
- }
17335
- },
17336
- description: "Consent checkbox entries"
17337
- }
17338
- }
17339
- },
17340
- output_schema: {
17341
- type: "object",
17342
- required: ["type", "fields"],
17343
- properties: {
17344
- type: { type: "string", const: "contact" },
17345
- fields: {
17346
- type: "array",
17347
- items: {
17348
- type: "object",
17349
- required: ["type", "value"],
17350
- properties: {
17351
- type: { type: "string" },
17352
- value: { type: "string" }
17353
- }
17354
- }
17355
- }
17356
- }
17357
- }
17358
- },
17359
- file_upload: {
17360
- label: "File Upload",
17361
- shorthand: "Upload",
17362
- icon: "Upload",
17363
- color: "#FEF9C3",
17364
- description: "Collect file uploads from respondents",
17365
- category: "input",
17366
- sort_order: 6,
17367
- has_options: false,
17368
- is_terminal: false,
17369
- show_nav_bar: true,
17370
- loading: "lazy",
17371
- supports_prompt: false,
17372
- supports_media: false,
17373
- is_system: false,
17374
- is_active: false,
17375
- show_in_results: true,
17376
- default_config: null,
17377
- config_schema: {
17378
- type: "object",
17379
- properties: {
17380
- max_files: { max: 20, min: 1, type: "number", label: "Max files", default: 5, description: "Maximum number of files respondents can upload" },
17381
- max_file_size_mb: { max: 500, min: 1, type: "number", label: "Max file size (MB)", default: 50, description: "Maximum size per file (1-500 MB)" },
17382
- allowed_media_types: {
17383
- type: "array",
17384
- items: { enum: ["images", "videos", "documents", "all"], type: "string" },
17385
- label: "Allowed media types",
17386
- default: ["images", "documents"],
17387
- enumLabels: {
17388
- all: "All file types",
17389
- images: "Images (JPEG, PNG, GIF, WebP, HEIC)",
17390
- videos: "Videos (MP4, MOV, WebM, AVI)",
17391
- documents: "Documents (PDF, DOC, DOCX, XLS, XLSX, TXT, CSV)"
17392
- },
17393
- description: "Select which types of files respondents can upload"
17394
- }
17395
- }
17396
- },
17397
- response_schema: {
17398
- type: "object",
17399
- required: ["files"],
17400
- properties: {
17401
- files: {
17402
- type: "array",
17403
- items: {
17404
- type: "object",
17405
- required: ["id", "name", "storage_path", "url", "mime_type", "size", "uploaded_at"],
17406
- properties: {
17407
- id: { type: "string", format: "uuid", description: "Unique file identifier" },
17408
- url: { type: "string", format: "uri", description: "Signed Supabase Storage URL for download" },
17409
- name: { type: "string", description: "Original filename" },
17410
- size: { type: "integer", minimum: 1, description: "File size in bytes" },
17411
- mime_type: { type: "string", description: "File MIME type" },
17412
- uploaded_at: { type: "string", format: "date-time", description: "ISO timestamp of upload completion" },
17413
- storage_path: { type: "string", description: "Full storage path: workspace_id/form_id/node_id/uuid.ext" }
17414
- }
17415
- },
17416
- minItems: 1,
17417
- description: "Array of uploaded file metadata"
17418
- }
17419
- }
17420
- },
17421
- output_schema: null
17422
- },
17423
- payment: {
17424
- label: "Payment",
17425
- shorthand: "Payment",
17426
- icon: "DollarSign",
17427
- color: "#E9D5FF",
17428
- description: null,
17429
- category: "action",
17430
- sort_order: 7,
17431
- has_options: false,
17432
- is_terminal: false,
17433
- show_nav_bar: true,
17434
- loading: "lazy",
17435
- supports_prompt: false,
17436
- supports_media: false,
17437
- is_system: false,
17438
- is_active: false,
17439
- show_in_results: true,
17440
- default_config: { amount: null, currency: "usd", provider: "stripe" },
17441
- config_schema: {
17442
- type: "object",
17443
- required: ["amount", "currency", "provider"],
17444
- properties: {
17445
- amount: { type: "number", label: "Amount (in cents)", minimum: 50, required: true, description: "Payment amount in cents (e.g., 5000 = $50.00)" },
17446
- currency: { enum: ["usd", "eur", "gbp", "cad", "aud"], type: "string", label: "Currency", default: "usd", required: true, description: "Three-letter ISO currency code" },
17447
- provider: { enum: ["stripe", "paddle"], type: "string", label: "Payment Provider", default: "stripe", required: true, description: "Payment provider to use" },
17448
- workspace_integration_id: { type: "string", label: "Workspace Integration ID", description: "UUID of the workspace_integrations record for the connected payment account" }
17449
- },
17450
- description: "Payment configuration with provider-agnostic flat structure"
17451
- },
17452
- response_schema: {
17453
- type: "object",
17454
- oneOf: [
17455
- {
17456
- required: ["stripe"],
17457
- properties: {
17458
- stripe: {
17459
- type: "object",
17460
- required: ["payment_intent_id", "status", "amount", "currency"],
17461
- properties: {
17462
- name: { type: "string", description: "Customer name from Stripe billing details" },
17463
- email: { type: "string", format: "email", description: "Customer email from Stripe billing details" },
17464
- amount: { type: "number", description: "Payment amount in cents" },
17465
- status: { enum: ["pending", "succeeded", "failed"], type: "string", description: "Payment status" },
17466
- currency: { type: "string", description: "Three-letter ISO currency code (e.g., usd, eur)" },
17467
- payment_intent_id: { type: "string", description: "Stripe payment intent ID" }
17468
- }
17469
- }
17470
- }
17471
- },
17472
- {
17473
- required: ["square"],
17474
- properties: {
17475
- square: {
17476
- type: "object",
17477
- properties: {
17478
- amount: { type: "number" },
17479
- status: { type: "string" },
17480
- order_id: { type: "string" },
17481
- payment_id: { type: "string" }
17482
- }
17483
- }
17484
- }
17485
- },
17486
- {
17487
- required: ["paddle"],
17488
- properties: {
17489
- paddle: {
17490
- type: "object",
17491
- properties: {
17492
- amount: { type: "number" },
17493
- status: { type: "string" },
17494
- order_id: { type: "string" },
17495
- checkout_id: { type: "string" }
17496
- }
17497
- }
17498
- }
17499
- }
17500
- ],
17501
- description: "Payment response with provider-specific data"
17502
- },
17503
- output_schema: null
17504
- },
17505
- binary: {
17506
- label: "Binary",
17507
- shorthand: "A/B",
17508
- icon: "CircleCheck",
17509
- color: "#D1FAE5",
17510
- description: "Two-option choice - yes/no, true/false, or this vs that",
17511
- category: "input",
17512
- sort_order: 1.5,
17513
- has_options: true,
17514
- min_options: 2,
17515
- max_options: 2,
17516
- max_option_length: 12,
17517
- is_terminal: false,
17518
- show_nav_bar: true,
17519
- loading: "eager",
17520
- supports_prompt: true,
17521
- supports_media: true,
17522
- is_system: false,
17523
- is_active: false,
17524
- show_in_results: true,
17525
- default_config: {
17526
- choice: { enable_branching: true },
17527
- options: [
17528
- { content: "Yes" },
17529
- { content: "No" }
17530
- ]
17531
- },
17532
- config_schema: {
17533
- type: "object",
17534
- properties: {
17535
- choice: {
17536
- type: "object",
17537
- properties: {
17538
- enable_branching: {
17539
- type: "boolean",
17540
- label: "Enable branching logic",
17541
- default: true,
17542
- description: "Allow each option to have its own logic path."
17543
- }
17544
- }
17545
- },
17546
- content_media_type: {
17547
- enum: ["upload", "recorded"],
17548
- type: "string",
17549
- label: "Content media type",
17550
- description: "How the node media was provided"
17551
- }
17552
- }
17553
- },
17554
- response_schema: {
17555
- type: "string",
17556
- description: "Selected option ID"
17557
- },
17558
- output_schema: {
17559
- type: "object",
17560
- required: ["type", "label", "option_id"],
17561
- properties: {
17562
- type: { type: "string", const: "binary" },
17563
- label: { type: "string", description: "Human-readable option label" },
17564
- option_id: { type: "string", format: "uuid", description: "Selected option UUID" }
17565
- }
17566
- }
17567
- },
17568
- button: {
17569
- label: "Button",
17570
- shorthand: "Button",
17571
- icon: "RectangleHorizontal",
17572
- color: "#DBEAFE",
17573
- description: "Simple button for acknowledgment or navigation",
17574
- category: "input",
17575
- sort_order: 3,
17576
- has_options: true,
17577
- min_options: 1,
17578
- max_options: 1,
17579
- max_option_length: 28,
17580
- is_terminal: false,
17581
- show_nav_bar: true,
17582
- loading: "eager",
17583
- supports_prompt: true,
17584
- supports_media: true,
17585
- is_system: false,
17586
- is_active: true,
17587
- show_in_results: false,
17588
- default_config: { options: [{ content: "Continue" }] },
17589
- config_schema: {
17590
- type: "object",
17591
- properties: {
17592
- button_text: { type: "string", label: "Button text", default: "Continue" },
17593
- button_style: { enum: ["primary", "secondary", "outline"], type: "string", label: "Button style", default: "primary" }
17594
- }
17595
- },
17596
- response_schema: {
17597
- type: "string",
17598
- description: "Selected option ID"
17599
- },
17600
- output_schema: {
17601
- type: "object",
17602
- required: ["type", "label", "option_id"],
17603
- properties: {
17604
- type: { type: "string", const: "button" },
17605
- label: { type: "string", description: "Human-readable option label" },
17606
- option_id: { type: "string", format: "uuid", description: "Selected option UUID" }
17607
- }
17608
- }
17609
- },
17610
- redirect: {
17611
- label: "Redirect",
17612
- shorthand: "Redirect",
17613
- icon: "ExternalLink",
17614
- color: "#FEE2E2",
17615
- description: "Redirect users to an external URL",
17616
- category: "end",
17617
- sort_order: 101,
17618
- has_options: false,
17619
- is_terminal: true,
17620
- show_nav_bar: false,
17621
- loading: "lazy",
17622
- supports_prompt: false,
17623
- supports_media: false,
17624
- is_system: false,
17625
- is_active: true,
17626
- show_in_results: false,
17627
- default_config: { url: "", auto_redirect: true },
17628
- config_schema: {
17629
- type: "object",
17630
- properties: {
17631
- url: { type: "string", label: "Redirect URL", placeholder: "https://example.com" },
17632
- auto_redirect: { type: "boolean", label: "Auto-redirect", default: true, description: "Automatically redirect to the URL instead of showing a button" }
17633
- }
17634
- },
17635
- response_schema: {
17636
- type: "string",
17637
- description: "URL the user was redirected to"
17638
- },
17639
- output_schema: null
17640
- },
17641
- link_list: {
17642
- label: "Link List",
17643
- shorthand: "Links",
17644
- icon: "ExternalLink",
17645
- color: "#FEE2E2",
17646
- description: "Display a list of links for users to choose from",
17647
- category: "end",
17648
- sort_order: 102,
17649
- has_options: false,
17650
- is_terminal: true,
17651
- show_nav_bar: false,
17652
- loading: "lazy",
17653
- supports_prompt: false,
17654
- supports_media: false,
17655
- is_system: false,
17656
- is_active: false,
17657
- show_in_results: false,
17658
- default_config: { links: [{ id: "default", url: "", title: "", description: "", order: 0 }], auto_redirect: false },
17659
- config_schema: {
17660
- type: "object",
17661
- properties: {
17662
- links: {
17663
- type: "array",
17664
- items: {
17665
- type: "object",
17666
- required: ["id", "url"],
17667
- properties: {
17668
- id: { type: "string" },
17669
- url: { type: "string", label: "URL", placeholder: "https://example.com" },
17670
- title: { type: "string", label: "Heading" },
17671
- description: { type: "string", label: "Description" },
17672
- order: { type: "number", label: "Sort order" }
17673
- }
17674
- },
17675
- label: "Links",
17676
- minItems: 1
17677
- },
17678
- auto_redirect: { type: "boolean", label: "Auto-redirect", default: false, description: "Automatically redirect to the URL instead of showing a button" }
17679
- }
17680
- },
17681
- response_schema: {
17682
- type: "string",
17683
- description: "URL of the link that was clicked"
17684
- },
17685
- output_schema: null
17686
- },
17687
- file_download: {
17688
- label: "File Download",
17689
- shorthand: "Download",
17690
- icon: "Download",
17691
- color: "#E9D5FF",
17692
- description: "Provide a file for respondents to download",
17693
- category: "action",
17694
- sort_order: 103,
17695
- has_options: false,
17696
- is_terminal: false,
17697
- show_nav_bar: true,
17698
- loading: "lazy",
17699
- supports_prompt: false,
17700
- supports_media: false,
17701
- is_system: false,
17702
- is_active: false,
17703
- show_in_results: true,
17704
- default_config: null,
17705
- config_schema: {
17706
- type: "object",
17707
- properties: {
17708
- files: {
17709
- type: "array",
17710
- items: {
17711
- type: "object",
17712
- properties: {
17713
- file_name: { type: "string", label: "Display file name", required: true },
17714
- file_path: { type: "string", label: "File path in storage", required: true },
17715
- file_size: { type: "number", label: "File size in bytes" },
17716
- mime_type: { type: "string", label: "MIME type" }
17717
- }
17718
- },
17719
- label: "Downloadable files"
17720
- },
17721
- button_text: { type: "string", label: "Button text", default: "Download Files" },
17722
- description: { type: "string", label: "Description text" }
17723
- }
17724
- },
17725
- response_schema: {
17726
- type: "object",
17727
- required: ["files"],
17728
- properties: {
17729
- files: {
17730
- type: "array",
17731
- items: {
17732
- type: "object",
17733
- required: ["file_path", "file_name", "downloaded_at"],
17734
- properties: {
17735
- file_name: { type: "string", description: "Display name of the file" },
17736
- file_path: { type: "string", description: "Storage path of the downloaded file" },
17737
- downloaded_at: { type: "string", format: "date-time", description: "Timestamp when download was initiated" }
17738
- }
17739
- },
17740
- description: "List of files downloaded by respondent"
17741
- }
17742
- }
17743
- },
17744
- output_schema: null
17745
- },
17746
- shopping: {
17747
- label: "Shopping",
17748
- shorthand: "Shop",
17749
- icon: "ShoppingBag",
17750
- color: "#D1FAE5",
17751
- description: "Product recommendations with direct checkout",
17752
- category: "action",
17753
- sort_order: 8,
17754
- has_options: false,
17755
- is_terminal: true,
17756
- show_nav_bar: true,
17757
- loading: "lazy",
17758
- supports_prompt: false,
17759
- supports_media: false,
17760
- is_system: false,
17761
- is_active: false,
17762
- show_in_results: false,
17763
- default_config: { provider: "shopify", cta_mode: "checkout", source_mode: "manual" },
17764
- config_schema: {
17765
- type: "object",
17766
- required: ["provider", "cta_mode"],
17767
- properties: {
17768
- title: { type: "string", label: "Heading", description: "Heading shown above the product list" },
17769
- description: { type: "string", label: "Description", description: "Body text shown below the heading" },
17770
- provider: { enum: ["shopify"], type: "string", label: "Provider", default: "shopify", description: "Ecommerce provider" },
17771
- workspace_integration_id: { type: "string", label: "Workspace Integration ID", description: "UUID of the workspace_integrations record for the connected store" },
17772
- cta_mode: { enum: ["checkout", "add_to_cart"], type: "string", label: "CTA Mode", default: "checkout", description: "Whether to go to checkout or add to cart" },
17773
- source_mode: { enum: ["manual", "collection"], type: "string", label: "Product source", default: "manual", description: "How products are selected: manually picked or from a collection" },
17774
- collection_id: { type: "string", label: "Collection ID", description: "Shopify collection GID (when source_mode is collection)" },
17775
- collection_title: { type: "string", label: "Collection title", description: "Display name of the selected collection" },
17776
- products: {
17777
- type: "array",
17778
- label: "Selected Products",
17779
- description: "Products to show (static mode)",
17780
- items: {
17781
- type: "object",
17782
- properties: {
17783
- product_id: { type: "string", description: "Shopify product GID" },
17784
- variant_id: { type: "string", description: "Shopify variant GID" },
17785
- title: { type: "string" },
17786
- handle: { type: "string" },
17787
- image_url: { type: "string" },
17788
- price: { type: "string" },
17789
- currency: { type: "string" },
17790
- recommended: { type: "boolean", default: true, description: "Pre-ticked in viewer" }
17791
- }
17792
- }
17793
- },
17794
- product_mappings: {
17795
- type: "array",
17796
- label: "Score-based product mappings",
17797
- description: "Map score ranges to different product sets. First matching range wins.",
17798
- items: {
17799
- type: "object",
17800
- required: ["min", "max"],
17801
- properties: {
17802
- min: { type: "integer", label: "Minimum score (inclusive)" },
17803
- max: { type: "integer", label: "Maximum score (inclusive)" },
17804
- message: { type: "string", label: "Message" },
17805
- products: { type: "array", description: "Products for this score range" }
17806
- }
17807
- }
17808
- }
17809
- },
17810
- description: "Shopping configuration with provider-agnostic structure"
17811
- },
17812
- response_schema: null,
17813
- output_schema: null
17814
- },
17815
- end_screen: {
17816
- label: "Ending",
17817
- shorthand: "End",
17818
- icon: "Flag",
17819
- color: "#FEE2E2",
17820
- description: "Final screen shown when form is completed",
17821
- category: "end",
17822
- sort_order: 999,
17823
- has_options: false,
17824
- is_terminal: true,
17825
- show_nav_bar: false,
17826
- loading: "eager",
17827
- supports_prompt: false,
17828
- supports_media: false,
17829
- is_system: false,
17830
- is_active: true,
17831
- show_in_results: false,
17832
- default_config: null,
17833
- config_schema: {
17834
- type: "object",
17835
- properties: {
17836
- title: { type: "string", label: "Title", default: "Thank you!", description: "Heading shown on completion" },
17837
- message: { type: "string", label: "Message", default: "Your response has been submitted.", description: "Message shown on completion" },
17838
- show_score: { type: "boolean", label: "Show score", default: false, description: 'Display score on the end screen (e.g. "You scored 4 out of 5")' },
17839
- icon: { type: "string", label: "Icon", enum: ["tick", "trophy", "star", "crown", "party", "none"], default: "tick", description: "Icon shown above the title" },
17840
- show_share_button: { type: "boolean", label: "Show share button", default: false, description: "Show a share button above the CTA" },
17841
- cta_type: { type: "string", label: "CTA type", enum: ["none", "restart", "external_link"], default: "none", description: "Primary call-to-action button type" },
17842
- cta_text: { type: "string", label: "CTA button text", default: "Continue", description: "Button label for the CTA" },
17843
- cta_url: { type: "string", label: "CTA URL", format: "uri", description: "URL to open (only for external_link CTA type)", placeholder: "https://example.com" },
17844
- score_ranges: {
17845
- type: "array",
17846
- label: "Score-based content",
17847
- description: "Show different content based on cumulative score. First matching range wins.",
17848
- items: {
17849
- type: "object",
17850
- required: ["min", "max", "title"],
17851
- properties: {
17852
- min: { type: "integer", label: "Minimum score (inclusive)" },
17853
- max: { type: "integer", label: "Maximum score (inclusive)" },
17854
- title: { type: "string", label: "Title" },
17855
- message: { type: "string", label: "Message" }
17856
- }
17857
- }
17858
- },
17859
- scoring_results: {
17860
- type: "array",
17861
- label: "Category-based results",
17862
- description: "Results keyed by scoring category. The winning category (highest non-knocked-out score) determines which result is shown.",
17863
- items: {
17864
- type: "object",
17865
- required: ["category", "title"],
17866
- properties: {
17867
- category: { type: "string", label: "Category key (must match keys used in option scores)" },
17868
- title: { type: "string", label: "Title" },
17869
- message: { type: "string", label: "Message" },
17870
- cta_url: { type: "string", label: "CTA URL", format: "uri" },
17871
- cta_text: { type: "string", label: "CTA button text" }
17872
- }
17873
- }
17874
- }
17875
- }
17876
- },
17877
- response_schema: null,
17878
- output_schema: null
17879
- }
17880
- };
17881
- var NODE_TYPES_LIST = Object.entries(NODE_TYPES).map(([type, def]) => ({ type, ...def })).sort((a, b) => a.sort_order - b.sort_order);
17882
- var NODE_TYPE_KEYS = Object.keys(NODE_TYPES);
17883
- var RESPONSE_SCHEMAS = Object.fromEntries(
17884
- Object.entries(NODE_TYPES).map(([k, v]) => [k, v.response_schema])
17885
- );
17886
- var CONFIG_SCHEMAS = Object.fromEntries(
17887
- Object.entries(NODE_TYPES).map(([k, v]) => [k, v.config_schema])
17888
- );
17889
- var OUTPUT_SCHEMAS = Object.fromEntries(
17890
- Object.entries(NODE_TYPES).map(([k, v]) => [k, v.output_schema])
17891
- );
17892
- var NODE_TYPE_METADATA = Object.fromEntries(
17893
- Object.entries(NODE_TYPES).map(([k, v]) => [k, {
17894
- supports_prompt: v.supports_prompt,
17895
- supports_media: v.supports_media,
17896
- is_terminal: v.is_terminal,
17897
- show_nav_bar: v.show_nav_bar,
17898
- category: v.category,
17899
- loading: v.loading
17900
- }])
17901
- );
17902
- var TERMINAL_TYPES = Object.entries(NODE_TYPES).filter(([, v]) => v.is_terminal).map(([k]) => k);
17903
- var NON_COUNTABLE_TYPES = Object.entries(NODE_TYPES).filter(([, v]) => v.is_system || v.is_terminal).map(([k]) => k);
17904
- var NON_COUNTABLE_FILTER = `(${NON_COUNTABLE_TYPES.map((t) => `"${t}"`).join(",")})`;
17905
- var RESULTS_EXCLUDED_TYPES = Object.entries(NODE_TYPES).filter(([, v]) => !v.show_in_results).map(([k]) => k);
17906
-
17907
- // ../config/integration-catalog.js
17908
- var INTEGRATION_CATALOG = {
17909
- stripe: {
17910
- name: "Stripe",
17911
- category: "form_action",
17912
- description: "Accept payments directly in your forms",
17913
- logo_url: "https://cdn.brandfetch.io/stripe.com/w/400/h/400",
17914
- color: "#635BFF",
17915
- sort_order: 1,
17916
- tags: ["payment"],
17917
- external_account_id_field: "account_id",
17918
- display_name_field: "account_name",
17919
- is_active: true
17920
- },
17921
- paddle: {
17922
- name: "Paddle",
17923
- category: "form_action",
17924
- description: "Accept payments with Paddle",
17925
- logo_url: "https://cdn.brandfetch.io/paddle.com/w/400/h/400",
17926
- color: "#6837FC",
17927
- sort_order: 2,
17928
- tags: ["payment"],
17929
- external_account_id_field: null,
17930
- display_name_field: null,
17931
- is_active: true
17932
- },
17933
- square: {
17934
- name: "Square",
17935
- category: "form_action",
17936
- description: "Accept payments with Square",
17937
- logo_url: "https://cdn.brandfetch.io/square.com/w/400/h/400",
17938
- color: "#000000",
17939
- sort_order: 3,
17940
- tags: ["payment"],
17941
- external_account_id_field: null,
17942
- display_name_field: null,
17943
- is_active: true
17944
- },
17945
- calendly: {
17946
- name: "Calendly",
17947
- category: "form_action",
17948
- description: "Schedule meetings directly in your forms",
17949
- logo_url: "https://cdn.brandfetch.io/calendly.com/w/400/h/400",
17950
- color: "#006BFF",
17951
- sort_order: 4,
17952
- tags: ["booking"],
17953
- external_account_id_field: "user_uri",
17954
- display_name_field: "user_name",
17955
- is_active: true
17956
- },
17957
- calcom: {
17958
- name: "Cal.com",
17959
- category: "form_action",
17960
- description: "Open-source scheduling platform for booking meetings",
17961
- logo_url: null,
17962
- color: "#292929",
17963
- sort_order: 4,
17964
- tags: ["booking"],
17965
- external_account_id_field: "id",
17966
- display_name_field: "name",
17967
- is_active: true
17968
- },
17969
- docusign: {
17970
- name: "DocuSign",
17971
- category: "form_action",
17972
- description: "Collect signatures in your forms",
17973
- logo_url: "https://cdn.brandfetch.io/docusign.com/w/400/h/400",
17974
- color: "#FF0037",
17975
- sort_order: 5,
17976
- tags: ["document", "e-signature", "contract"],
17977
- external_account_id_field: null,
17978
- display_name_field: null,
17979
- is_active: true
17980
- },
17981
- webhook: {
17982
- name: "Webhook",
17983
- category: "automation",
17984
- description: "Send responses to custom webhooks",
17985
- logo_url: null,
17986
- color: "#6B7280",
17987
- sort_order: 100,
17988
- tags: ["webhook", "automation", "developer"],
17989
- external_account_id_field: null,
17990
- display_name_field: null,
17991
- is_active: true
17992
- },
17993
- zapier: {
17994
- name: "Zapier",
17995
- category: "automation",
17996
- description: "Connect to 5,000+ apps and automate workflows",
17997
- logo_url: "https://cdn.brandfetch.io/zapier.com/w/400/h/400",
17998
- color: "#FF4A00",
17999
- sort_order: 101,
18000
- tags: ["automation", "workflow", "no-code"],
18001
- external_account_id_field: null,
18002
- display_name_field: null,
18003
- is_active: true
18004
- },
18005
- make: {
18006
- name: "Make",
18007
- category: "automation",
18008
- description: "Advanced automation and integrations",
18009
- logo_url: "https://cdn.brandfetch.io/make.com/w/400/h/400",
18010
- color: "#6B4AFF",
18011
- sort_order: 102,
18012
- tags: ["automation", "workflow", "integration"],
18013
- external_account_id_field: null,
18014
- display_name_field: null,
18015
- is_active: true
18016
- },
18017
- hubspot: {
18018
- name: "HubSpot",
18019
- category: "automation",
18020
- description: "Sync responses to HubSpot CRM",
18021
- logo_url: "https://cdn.brandfetch.io/hubspot.com/w/400/h/400",
18022
- color: "#FF7A59",
18023
- sort_order: 103,
18024
- tags: ["automation", "crm", "marketing"],
18025
- external_account_id_field: "portal_id",
18026
- display_name_field: "portal_name",
18027
- is_active: true
18028
- },
18029
- salesforce: {
18030
- name: "Salesforce",
18031
- category: "automation",
18032
- description: "Sync responses to Salesforce CRM",
18033
- logo_url: "https://cdn.brandfetch.io/salesforce.com/w/400/h/400",
18034
- color: "#00A1E0",
18035
- sort_order: 104,
18036
- tags: ["automation", "crm", "sales"],
18037
- external_account_id_field: null,
18038
- display_name_field: null,
18039
- is_active: true
18040
- },
18041
- slack: {
18042
- name: "Slack",
18043
- category: "automation",
18044
- description: "Send notifications to Slack channels",
18045
- logo_url: "https://cdn.brandfetch.io/slack.com/w/400/h/400",
18046
- color: "#4A154B",
18047
- sort_order: 105,
18048
- tags: ["automation", "communication", "notifications"],
18049
- external_account_id_field: null,
18050
- display_name_field: null,
18051
- is_active: true
18052
- },
18053
- shopify: {
18054
- name: "Shopify",
18055
- category: "ecommerce",
18056
- description: "Product recommendations from quiz results with direct checkout",
18057
- logo_url: "https://cdn.brandfetch.io/shopify.com/w/400/h/400",
18058
- color: "#95BF47",
18059
- sort_order: 200,
18060
- tags: ["ecommerce", "product", "checkout", "quiz"],
18061
- external_account_id_field: "shop_domain",
18062
- display_name_field: "shop_name",
18063
- is_active: true
18064
- }
18065
- };
18066
- var INTEGRATION_CATALOG_LIST = Object.entries(INTEGRATION_CATALOG).map(([slug, def]) => ({ slug, ...def })).sort((a, b) => a.sort_order - b.sort_order);
18067
- var INTEGRATION_SLUGS = Object.keys(INTEGRATION_CATALOG);
18068
-
18069
- // ../config/index.js
18070
- var isServer = typeof window === "undefined";
18071
- var isBrowser = typeof window !== "undefined";
18072
- var isLocalhost = isBrowser && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.includes("local"));
18073
- var isDevelopment = isServer ? process.env.NODE_ENV !== "production" : isLocalhost;
18074
- var ENV = {
18075
- isDevelopment,
18076
- isProduction: !isDevelopment,
18077
- isLocalhost: isDevelopment
18078
- // alias for clarity
18079
- };
18080
- var COOKIE_DOMAIN = ENV.isDevelopment ? void 0 : ".clipform.io";
18081
- var isTunnelBrowser = isBrowser && window.location.hostname.endsWith(".smith-forge.com");
18082
- function getUrls() {
18083
- if (isTunnelBrowser) {
18084
- return {
18085
- marketing: "https://marketing-dev.smith-forge.com",
18086
- dashboard: "https://dashboard-dev.smith-forge.com",
18087
- viewer: "https://viewer-dev.smith-forge.com",
18088
- api: "https://api-dev.smith-forge.com",
18089
- mcp: "https://api-dev.smith-forge.com/mcp",
18090
- docs: "https://docs.clipform.io"
18091
- };
18092
- }
18093
- if (ENV.isDevelopment) {
18094
- return {
18095
- marketing: "http://localhost:3002",
18096
- dashboard: "http://localhost:3000",
18097
- viewer: "http://localhost:3001",
18098
- api: "http://localhost:3003",
18099
- // No separate MCP host in dev - tools live on the api subpath.
18100
- mcp: "http://localhost:3003/mcp",
18101
- docs: "http://localhost:3004"
18102
- };
18103
- }
18104
- return {
18105
- marketing: "https://www.clipform.io",
18106
- dashboard: "https://app.clipform.io",
18107
- viewer: "https://clipform.io",
18108
- api: "https://api.clipform.io",
18109
- // Dedicated subdomain for the remote MCP server. Same Render service
18110
- // as `api`, just routed by Host header. Token audience is bound here.
18111
- mcp: "https://mcp.clipform.io",
18112
- docs: "https://docs.clipform.io"
18113
- };
18114
- }
18115
- var BUSINESS = {
18116
- name: "Clipform",
18117
- tagline: "Video-Driven Form Builder",
18118
- description: "Create engaging forms that combine video content with interactive questions. Capture authentic responses with text, audio, or video recordings.",
18119
- shortDescription: "Interactive video forms that capture authentic responses. Build engaging forms in minutes.",
18120
- domain: "clipform.io",
18121
- email: {
18122
- support: "support@clipform.io",
18123
- sales: "sales@clipform.io",
18124
- hello: "hello@clipform.io"
18125
- },
18126
- phone: "+1 (555) 123-4567",
18127
- urls: getUrls()
18128
- };
18129
- var CONTACT_FIELDS = [
18130
- { id: "first_name", label: "First Name", type: "text", placeholder: "Enter first name", order: 1 },
18131
- { id: "last_name", label: "Last Name", type: "text", placeholder: "Enter last name", order: 2 },
18132
- { id: "email", label: "Email Address", type: "email", placeholder: "you@example.com", order: 3 },
18133
- { id: "phone", label: "Phone Number", type: "tel", placeholder: "(555) 123-4567", order: 4 }
18134
- ];
18135
- var CONTACT_FIELDS_MAP = Object.fromEntries(
18136
- CONTACT_FIELDS.map((f) => [f.id, f])
18137
- );
18138
- var KEN_BURNS_EFFECTS = [
18139
- "pan-left",
18140
- "pan-right",
18141
- "pan-up",
18142
- "pan-down",
18143
- "zoom-in-pan-left",
18144
- "zoom-in-pan-right",
18145
- "zoom-in",
18146
- "zoom-out",
18147
- "static"
18148
- ];
18149
- var KEN_BURNS_PRESETS = [
18150
- "cinematic",
18151
- "dramatic",
18152
- "calm",
18153
- "documentary",
18154
- "dreamy",
18155
- "moody"
18156
- ];
18157
- var KEN_BURNS_FIT_MODES = ["cover", "blur-pad", "auto"];
18158
- var SLIDESHOW_TRANSITIONS = [
18159
- "fade",
18160
- "fadeblack",
18161
- "fadewhite",
18162
- "slideleft",
18163
- "slideright",
18164
- "circlecrop",
18165
- "circleopen",
18166
- "circleclose",
18167
- "dissolve",
18168
- "pixelize",
18169
- "radial",
18170
- "smoothleft",
18171
- "smoothright",
18172
- "wipeleft",
18173
- "wiperight",
18174
- "diagtl",
18175
- "diagbr",
18176
- "hblur"
18177
- ];
18178
-
18179
16894
  // src/lib/config.ts
18180
16895
  var _endScreen = NODE_TYPES.end_screen.config_schema.properties;
18181
16896
  var END_SCREEN_ICONS = _endScreen.icon.enum;
@@ -18339,7 +17054,8 @@ Example: A form that asks a question, collects contact info, then finishes:
18339
17054
  destructiveHint: false,
18340
17055
  idempotentHint: false,
18341
17056
  openWorldHint: true
18342
- }
17057
+ },
17058
+ _meta: { "anthropic/alwaysLoad": true }
18343
17059
  },
18344
17060
  async ({ title, nodes, show_step_counter, disable_back_navigation, primary_color, background_color, font_family, tags }) => {
18345
17061
  let planContext = null;
@@ -18423,21 +17139,20 @@ Example: A form that asks a question, collects contact info, then finishes:
18423
17139
  });
18424
17140
  }
18425
17141
  const lines = [
18426
- `Form skeleton created (draft).`,
17142
+ `Form created and live.`,
18427
17143
  ``,
18428
17144
  `Title: ${title}`,
18429
17145
  `Nodes: ${nodes.length}`,
18430
17146
  `Form ID: ${formId}`,
18431
17147
  ``,
18432
- `FORM URL (share this with respondents): ${data.viewer_url}`
17148
+ `FORM URL (live - share this with respondents): ${data.viewer_url}`
18433
17149
  ];
18434
17150
  if (formUrl) {
18435
17151
  lines.push(`DASHBOARD URL (sign in to edit and manage): ${formUrl}`);
18436
17152
  }
18437
17153
  lines.push(
18438
17154
  ``,
18439
- `The form is in draft. Continue with media/narration steps, then set it live with clipform_update_form (is_live: true) when everything is ready.`,
18440
- `Only share the FORM URL with the user AFTER setting it live.`,
17155
+ `The form is live and accessible at the FORM URL above. Continue with media/narration steps if needed - changes appear immediately.`,
18441
17156
  `CRITICAL: Copy the URLs above character-for-character into your response. Do NOT construct, guess, or invent any URLs. Only use the exact FORM URL and DASHBOARD URL provided here.`,
18442
17157
  `Pass form_id on follow-up tools (get_form, add_node, upload_node_media, etc.).`
18443
17158
  );
@@ -18733,6 +17448,11 @@ function registerAddNodeTool(server) {
18733
17448
  }
18734
17449
  },
18735
17450
  async ({ form_id, node, after_node_id }) => {
17451
+ if (node.type === "button" && (!node.options || node.options.length === 0)) {
17452
+ const buttonDefault = NODE_TYPES.button?.config_schema?.properties?.button_text?.default || "Continue";
17453
+ const label = node.config?.button_text || buttonDefault;
17454
+ node.options = [{ content: label }];
17455
+ }
18736
17456
  const body = { node };
18737
17457
  if (after_node_id) body.after_node_id = after_node_id;
18738
17458
  const result = await callApi(`/forms/${form_id}/nodes`, {
@@ -18759,23 +17479,26 @@ ${formState}` : confirmMsg);
18759
17479
  }
18760
17480
 
18761
17481
  // src/tools/update-node.ts
17482
+ var NodeUpdateSchema = external_exports.object({
17483
+ node_id: external_exports.string().describe("The node ID to update"),
17484
+ prompt: external_exports.string().optional().describe("New node prompt text"),
17485
+ label: external_exports.string().optional().describe("Short label for the node (used in logic builder)"),
17486
+ type: external_exports.enum(ACTIVE_NODE_TYPES).optional().describe("Change the node type"),
17487
+ required: external_exports.boolean().optional().describe("Whether an answer is required"),
17488
+ config: external_exports.record(external_exports.unknown()).optional().describe(CONFIG_DESCRIPTION),
17489
+ options: external_exports.array(OptionSchema).optional().describe(
17490
+ "Replace all options (for choice nodes). Omit to keep existing options."
17491
+ )
17492
+ });
18762
17493
  function registerUpdateNodeTool(server) {
18763
17494
  server.registerTool(
18764
17495
  "clipform_update_node",
18765
17496
  {
18766
17497
  title: "Update Node",
18767
- description: `Update an existing node's text, type, config, or options. Requires a node ID (returned by clipform_create_form, clipform_add_node, or clipform_get_form). Does not change the node's position in the flow. All type definitions and config schemas are derived from @vid-master/config (answer-types).`,
17498
+ description: `Update one or more existing nodes' text, type, config, or options. Pass multiple updates in one call instead of separate tool calls. Requires node IDs (returned by clipform_create_form, clipform_add_node, or clipform_get_form). Does not change node positions in the flow. All type definitions and config schemas are derived from @vid-master/config (answer-types).`,
18768
17499
  inputSchema: {
18769
17500
  form_id: external_exports.string().uuid().describe("The form UUID (returned by clipform_create_form, not the short share_id from the URL)"),
18770
- node_id: external_exports.string().describe("The node ID to update"),
18771
- prompt: external_exports.string().optional().describe("New node prompt text"),
18772
- label: external_exports.string().optional().describe("Short label for the node (used in logic builder)"),
18773
- type: external_exports.enum(ACTIVE_NODE_TYPES).optional().describe("Change the node type"),
18774
- required: external_exports.boolean().optional().describe("Whether an answer is required"),
18775
- config: external_exports.record(external_exports.unknown()).optional().describe(CONFIG_DESCRIPTION),
18776
- options: external_exports.array(OptionSchema).optional().describe(
18777
- "Replace all options (for choice nodes). Omit to keep existing options."
18778
- )
17501
+ updates: external_exports.array(NodeUpdateSchema).min(1).max(20).describe("One or more node updates to apply")
18779
17502
  },
18780
17503
  annotations: {
18781
17504
  readOnlyHint: false,
@@ -18784,40 +17507,35 @@ function registerUpdateNodeTool(server) {
18784
17507
  openWorldHint: true
18785
17508
  }
18786
17509
  },
18787
- async ({
18788
- form_id,
18789
- node_id,
18790
- prompt,
18791
- label,
18792
- type,
18793
- required: required2,
18794
- config: config2,
18795
- options
18796
- }) => {
18797
- const body = {};
18798
- if (prompt !== void 0) body.prompt = prompt;
18799
- if (label !== void 0) body.label = label;
18800
- if (type !== void 0) body.type = type;
18801
- if (required2 !== void 0) body.required = required2;
18802
- if (config2 !== void 0) body.config = config2;
18803
- if (options !== void 0) body.options = options;
18804
- const result = await callApi(
18805
- `/forms/${form_id}/nodes/${node_id}`,
18806
- { method: "PATCH", body }
18807
- );
18808
- if (!result.ok) {
18809
- return errorResult(result.error);
18810
- }
18811
- const updates = [];
18812
- if (prompt !== void 0) updates.push(`Prompt \u2192 "${prompt}"`);
18813
- if (label !== void 0) updates.push(`Label \u2192 "${label}"`);
18814
- if (type !== void 0) updates.push(`Type \u2192 ${type}`);
18815
- if (required2 !== void 0) updates.push(`Required \u2192 ${required2}`);
18816
- if (config2 !== void 0) updates.push(`Config updated`);
18817
- if (options !== void 0)
18818
- updates.push(`Options \u2192 ${options.map((o) => o.content).join(", ")}`);
18819
- const confirmMsg = `Node ${node_id} updated:
18820
- ${updates.join("\n")}`;
17510
+ async ({ form_id, updates }) => {
17511
+ const allLines = [];
17512
+ for (const { node_id, prompt, label, type, required: required2, config: config2, options } of updates) {
17513
+ const body = {};
17514
+ if (prompt !== void 0) body.prompt = prompt;
17515
+ if (label !== void 0) body.label = label;
17516
+ if (type !== void 0) body.type = type;
17517
+ if (required2 !== void 0) body.required = required2;
17518
+ if (config2 !== void 0) body.config = config2;
17519
+ if (options !== void 0) body.options = options;
17520
+ const result = await callApi(
17521
+ `/forms/${form_id}/nodes/${node_id}`,
17522
+ { method: "PATCH", body }
17523
+ );
17524
+ if (!result.ok) {
17525
+ allLines.push(`Node ${node_id}: FAILED \u2014 ${result.error}`);
17526
+ continue;
17527
+ }
17528
+ const changes = [];
17529
+ if (prompt !== void 0) changes.push(`Prompt \u2192 "${prompt}"`);
17530
+ if (label !== void 0) changes.push(`Label \u2192 "${label}"`);
17531
+ if (type !== void 0) changes.push(`Type \u2192 ${type}`);
17532
+ if (required2 !== void 0) changes.push(`Required \u2192 ${required2}`);
17533
+ if (config2 !== void 0) changes.push(`Config updated`);
17534
+ if (options !== void 0)
17535
+ changes.push(`Options \u2192 ${options.map((o) => o.content).join(", ")}`);
17536
+ allLines.push(`Node ${node_id} updated: ${changes.join(", ")}`);
17537
+ }
17538
+ const confirmMsg = allLines.join("\n");
18821
17539
  const formState = await fetchAndFormatFormState(form_id);
18822
17540
  return textResult(formState ? `${confirmMsg}
18823
17541
 
@@ -19030,6 +17748,7 @@ function registerDeleteNodeMediaTool(server) {
19030
17748
 
19031
17749
  // src/tools/attach-node-audio.ts
19032
17750
  function registerAttachNodeAudioTool(server) {
17751
+ if (!FEATURES.audio_attachments.enabled) return;
19033
17752
  server.registerTool(
19034
17753
  "clipform_attach_audio",
19035
17754
  {
@@ -19073,24 +17792,27 @@ var LogicRuleSchema = external_exports.object({
19073
17792
  ),
19074
17793
  target_node_id: external_exports.string().describe("The node ID to jump to when this rule matches")
19075
17794
  });
17795
+ var NodeLogicSchema = external_exports.object({
17796
+ node_id: external_exports.string().describe("The node ID to set logic on"),
17797
+ rules: external_exports.array(LogicRuleSchema).min(1).describe("Branching rules. Each maps an option or default to a target node.")
17798
+ });
19076
17799
  function registerSetNodeLogicTool(server) {
19077
17800
  server.registerTool(
19078
17801
  "clipform_set_logic",
19079
17802
  {
19080
17803
  title: "Set Node Logic",
19081
- description: `Set routing logic on a node. Linear routing (A to B to C) is supported. NOTE: Conditional branching (different paths based on which option is picked) is a planned feature - do not create conditional branching paths.
17804
+ description: `Set routing logic on one or more nodes. Pass multiple nodes in one call instead of separate tool calls. Linear routing (A to B to C) is supported. NOTE: Conditional branching (different paths based on which option is picked) is a planned feature - do not create conditional branching paths.
19082
17805
 
19083
17806
  Each rule maps an option (by its text content) to a target node. Rules without option_content are "default" rules applied to all unmatched options.
19084
17807
 
19085
17808
  Example:
19086
- rules: [
19087
- { option_content: "42", target_node_id: "well-done-id" },
19088
- { target_node_id: "wrong-id" }
17809
+ nodes: [
17810
+ { node_id: "q1-id", rules: [{ target_node_id: "q2-id" }] },
17811
+ { node_id: "q2-id", rules: [{ target_node_id: "q3-id" }] }
19089
17812
  ]`,
19090
17813
  inputSchema: {
19091
17814
  form_id: external_exports.string().uuid().describe("The form UUID (returned by clipform_create_form, not the short share_id from the URL)"),
19092
- node_id: external_exports.string().describe("The node ID to set logic on"),
19093
- rules: external_exports.array(LogicRuleSchema).min(1).describe("Branching rules. Each maps an option or default to a target node.")
17815
+ nodes: external_exports.array(NodeLogicSchema).min(1).max(20).describe("One or more nodes to set logic on")
19094
17816
  },
19095
17817
  annotations: {
19096
17818
  readOnlyHint: false,
@@ -19099,19 +17821,23 @@ Example:
19099
17821
  openWorldHint: true
19100
17822
  }
19101
17823
  },
19102
- async ({ form_id, node_id, rules }) => {
19103
- const result = await callApi(
19104
- `/forms/${form_id}/nodes/${node_id}/logic`,
19105
- {
19106
- method: "PUT",
19107
- body: { rules }
17824
+ async ({ form_id, nodes }) => {
17825
+ const allLines = [];
17826
+ for (const { node_id, rules } of nodes) {
17827
+ const result = await callApi(
17828
+ `/forms/${form_id}/nodes/${node_id}/logic`,
17829
+ {
17830
+ method: "PUT",
17831
+ body: { rules }
17832
+ }
17833
+ );
17834
+ if (!result.ok) {
17835
+ allLines.push(`Node ${node_id}: FAILED \u2014 ${result.error}`);
17836
+ continue;
19108
17837
  }
19109
- );
19110
- if (!result.ok) {
19111
- return errorResult(result.error);
17838
+ allLines.push(`Node ${node_id}: logic set (${result.data.rules_count} rules)`);
19112
17839
  }
19113
- const confirmMsg = `Logic set on node ${node_id}.
19114
- Rules created: ${result.data.rules_count}`;
17840
+ const confirmMsg = allLines.join("\n");
19115
17841
  const formState = await fetchAndFormatFormState(form_id);
19116
17842
  return textResult(formState ? `${confirmMsg}
19117
17843
 
@@ -19251,7 +17977,8 @@ Supports any public YouTube video with captions enabled. Does NOT work for priva
19251
17977
  // src/tools/generate-tts.ts
19252
17978
  var TtsItemSchema = external_exports.object({
19253
17979
  text: external_exports.string().min(1).max(5e3).describe("Narration text"),
19254
- voice: external_exports.enum(["ryan", "sonia", "andrew", "ava", "guy"]).optional().default("ryan").describe("TTS voice (default: ryan)")
17980
+ voice: external_exports.enum(["ryan", "sonia", "andrew", "ava", "guy"]).optional().default("ryan").describe("Voice: ryan (British male, clear/articulate), sonia (British female, warm/bright), andrew (American male, smooth/neutral), ava (American female, vibrant/friendly), guy (American male, deep/authoritative). Pick based on the form's topic and audience."),
17981
+ tone: external_exports.string().max(500).optional().describe("Style instructions for how the voice should sound. E.g. 'Speak like an energetic quiz show host, playful and teasing' or 'Warm and conversational, like chatting with a friend'. Infer from context if not specified by the user.")
19255
17982
  });
19256
17983
  function registerGenerateTtsTool(server) {
19257
17984
  server.registerTool(
@@ -19260,9 +17987,11 @@ function registerGenerateTtsTool(server) {
19260
17987
  title: "Generate Text-to-Speech",
19261
17988
  description: `Generate narration audio from text with word-level captions. Use this for quiz question narration, survey introductions, form instructions, or any node that benefits from a human voice. Proactively suggest narration for quizzes and content-rich forms - it significantly improves engagement.
19262
17989
 
19263
- Available voices: ryan (British male, default), sonia (British female), andrew (American male), ava (American female), guy (American male casual). Pass one item or many (max 10) - multiple items run in parallel.
17990
+ Available voices: ryan (British male, clear), sonia (British female, warm), andrew (American male, smooth), ava (American female, vibrant), guy (American male, deep). Pick the voice that fits the topic - e.g. a London quiz gets ryan or sonia, a US sports quiz gets andrew or guy.
17991
+
17992
+ Use the tone parameter to direct HOW the voice speaks. Always set a tone that matches the form's mood - e.g. quizzes: "Energetic and playful, like a quiz show host teasing the audience", surveys: "Professional but warm, encouraging honest answers", personality quizzes: "Curious and reflective". This dramatically improves the narration quality.
19264
17993
 
19265
- Returns audio URL and word-level captions per item. Captions enable per-word highlighting when attached to a node via clipform_upload_node_media.`,
17994
+ Pass one item or many (max 10) - multiple items run in parallel. Returns audio URL and word-level captions per item.`,
19266
17995
  inputSchema: {
19267
17996
  items: external_exports.array(TtsItemSchema).min(1).max(10).describe("One or more TTS items to generate")
19268
17997
  },
@@ -19273,7 +18002,7 @@ Returns audio URL and word-level captions per item. Captions enable per-word hig
19273
18002
  const results = await Promise.allSettled(
19274
18003
  items.map(
19275
18004
  (item) => callApi("/internal/tts", {
19276
- body: { text: item.text, voice: item.voice, workspace_id },
18005
+ body: { text: item.text, voice: item.voice, tone: item.tone, workspace_id },
19277
18006
  timeoutMs: 45e3
19278
18007
  })
19279
18008
  )
@@ -19311,99 +18040,53 @@ Returns audio URL and word-level captions per item. Captions enable per-word hig
19311
18040
  );
19312
18041
  }
19313
18042
 
19314
- // src/tools/generate-slideshow.ts
19315
- function registerGenerateSlideshowTool(server) {
19316
- server.registerTool(
19317
- "clipform_generate_slideshow",
19318
- {
19319
- title: "Generate Slideshow",
19320
- description: `Deprecated. Superseded by clipform_generate_video which supports both images and video clips.
19321
-
19322
- Generate a Ken Burns slideshow video (9:16, 720x1280) from images + audio. Blocks until complete. Returns a public URL.`,
19323
- inputSchema: {
19324
- images: external_exports.array(
19325
- external_exports.object({
19326
- url: external_exports.string().url().describe("Image URL"),
19327
- effect: external_exports.string().optional().describe(`Ken Burns effect name: ${[...KEN_BURNS_EFFECTS, "random"].join(", ")}`),
19328
- aspect_ratio: external_exports.number().positive().optional().describe("Source image width / height. Enables auto blur-pad for landscape images in the 9:16 viewport."),
19329
- fit: external_exports.enum(KEN_BURNS_FIT_MODES).optional().describe("Framing mode. 'auto' (default) picks cover for portrait, blur-pad for landscape.")
19330
- })
19331
- ).min(1).max(20).describe("Images for the slideshow (1-20)"),
19332
- audio_url: external_exports.string().url().describe("URL of the audio track (mp3/wav). Slideshow duration matches audio duration."),
19333
- random_effects: external_exports.boolean().optional().default(true).describe("Shuffle effects across all images (default: true). Set false when specifying effects explicitly per-image."),
19334
- transition: external_exports.object({
19335
- type: external_exports.string().optional().default("fade").describe(`Transition type: ${SLIDESHOW_TRANSITIONS.join(", ")}`),
19336
- duration: external_exports.number().optional().default(1).describe("Transition duration in seconds (default: 1).")
19337
- }).optional().describe("Transition between images."),
19338
- style_preset: STYLE_PRESET_ENUM.optional(),
19339
- background_color: external_exports.string().optional().describe("Viewport background color behind all images (default '#000').")
19340
- },
19341
- annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
19342
- },
19343
- async ({ images, audio_url, random_effects, transition, style_preset, background_color }) => {
19344
- const workspace_id = getMcpAuth()?.workspace_id;
19345
- const result = await callApi("/internal/slideshow", {
19346
- timeoutMs: 6e4,
19347
- body: {
19348
- images,
19349
- audio_url,
19350
- random_effects: random_effects ?? true,
19351
- transition: transition ?? { type: "fade", duration: 1 },
19352
- default_style: style_preset ? { preset: style_preset } : void 0,
19353
- background_color,
19354
- workspace_id
19355
- }
19356
- });
19357
- if (!result.ok) return errorResult(result.error);
19358
- const data = result.data;
19359
- return textResult(
19360
- [
19361
- `Slideshow rendered (${images.length} image${images.length > 1 ? "s" : ""}).`,
19362
- ``,
19363
- `Public URL: ${data.public_url}`,
19364
- `Storage path: ${data.storage_path}`,
19365
- data.duration_seconds ? `Duration: ${data.duration_seconds}s` : "",
19366
- ``,
19367
- `Use clipform_upload_node_media with the public URL to attach to a node.`
19368
- ].filter(Boolean).join("\n")
19369
- );
19370
- }
19371
- );
19372
- }
19373
-
19374
18043
  // src/tools/search-media.ts
19375
18044
  function registerSearchMediaTool(server) {
19376
18045
  server.registerTool(
19377
18046
  "clipform_search_media",
19378
18047
  {
19379
18048
  title: "Search Media",
19380
- description: `Search royalty-free images or stock video clips for any topic. Use this to find visuals - either to feed into clipform_generate_video for narrated slideshow videos, or upload directly as still images via clipform_upload_node_media. Searches across multiple providers and picks the most relevant results for your query. All results are royalty-free. Returns URLs, dimensions, attribution, and source info.`,
18049
+ description: `Search royalty-free images or stock video clips. Pass one query or many (max 10) - multiple queries run in one call instead of separate tool calls. Use results to feed into clipform_generate_video for narrated slideshow videos, or upload directly as still images via clipform_upload_node_media. All results are royalty-free.`,
19381
18050
  inputSchema: {
19382
- query: external_exports.string().describe("What to search for (e.g. 'african lion', 'saturn rings', 'city timelapse')"),
19383
- kind: external_exports.enum(["image", "video"]).describe("image = stock photos, video = stock clips"),
19384
- count: external_exports.number().min(1).max(20).default(6).optional().describe("Max results per provider (default 6 for image, 3 for video)")
18051
+ queries: external_exports.array(
18052
+ external_exports.object({
18053
+ query: external_exports.string().describe("What to search for (e.g. 'african lion', 'saturn rings')"),
18054
+ kind: external_exports.enum(["image", "video"]).describe("image = stock photos, video = stock clips"),
18055
+ count: external_exports.number().min(1).max(20).default(6).optional().describe("Max results per provider (default 6 for image, 3 for video)")
18056
+ })
18057
+ ).min(1).max(10).describe("One or more search queries to run")
19385
18058
  },
19386
18059
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
19387
18060
  },
19388
- async ({ query, kind, count }) => {
19389
- const result = await callApi("/internal/search-media", {
19390
- body: { query, kind, count }
19391
- });
19392
- if (!result.ok) return errorResult(result.error);
19393
- const results = result.data.results;
19394
- if (!results.length) return textResult(`No ${kind}s found for "${query}".`);
19395
- const lines = [`Found ${results.length} ${kind}s for "${query}":
19396
- `];
19397
- for (const item of results.slice(0, 15)) {
19398
- lines.push(`- [${item.source}] ${item.title}`);
19399
- lines.push(` URL: ${item.url}`);
19400
- if (item.width && item.height) lines.push(` Size: ${item.width}x${item.height}`);
19401
- if (kind === "video" && item.duration) lines.push(` Duration: ${item.duration}s`);
19402
- if (item.attribution) lines.push(` Attribution: ${item.attribution}`);
19403
- if (item.license) lines.push(` License: ${item.license}`);
19404
- lines.push("");
18061
+ async ({ queries }) => {
18062
+ const allLines = [];
18063
+ for (const { query, kind, count } of queries) {
18064
+ const result = await callApi("/internal/search-media", {
18065
+ body: { query, kind, count }
18066
+ });
18067
+ if (queries.length > 1) allLines.push(`--- "${query}" (${kind}) ---`);
18068
+ if (!result.ok) {
18069
+ allLines.push(`FAILED: ${result.error}`, "");
18070
+ continue;
18071
+ }
18072
+ const results = result.data.results;
18073
+ if (!results.length) {
18074
+ allLines.push(`No ${kind}s found.`, "");
18075
+ continue;
18076
+ }
18077
+ allLines.push(`Found ${results.length} ${kind}s:
18078
+ `);
18079
+ for (const item of results.slice(0, 10)) {
18080
+ allLines.push(`- [${item.source}] ${item.title}`);
18081
+ allLines.push(` URL: ${item.url}`);
18082
+ if (item.width && item.height) allLines.push(` Size: ${item.width}x${item.height}`);
18083
+ if (kind === "video" && item.duration) allLines.push(` Duration: ${item.duration}s`);
18084
+ if (item.attribution) allLines.push(` Attribution: ${item.attribution}`);
18085
+ if (item.license) allLines.push(` License: ${item.license}`);
18086
+ allLines.push("");
18087
+ }
19405
18088
  }
19406
- return textResult(lines.join("\n"));
18089
+ return textResult(allLines.join("\n"));
19407
18090
  }
19408
18091
  );
19409
18092
  }
@@ -19420,7 +18103,7 @@ For narrated Ken Burns slideshows from images, use clipform_generate_video inste
19420
18103
  inputSchema: {
19421
18104
  compositionId: external_exports.string().describe(`The composition ID. Call clipform_list_compositions to see available options (e.g. ${PUBLIC_COMPOSITIONS.map((id) => `'${id}'`).join(", ")})`),
19422
18105
  outputFormat: external_exports.enum(["mp4", "png"]).default("mp4").describe("Output format (default: mp4)"),
19423
- inputProps: external_exports.record(external_exports.unknown()).optional().describe("Props object matching the composition's expected schema")
18106
+ 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.")
19424
18107
  },
19425
18108
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
19426
18109
  },
@@ -19666,7 +18349,7 @@ function registerCheckRenderTool(server) {
19666
18349
  "clipform_check_render",
19667
18350
  {
19668
18351
  title: "Check Render Status",
19669
- description: `Check the status of a render job started by clipform_generate_video, clipform_generate_slideshow, or clipform_render_composition.
18352
+ description: `Check the status of a render job started by clipform_generate_video or clipform_render_composition.
19670
18353
 
19671
18354
  Returns the current status and, when complete, the output URL. Typical render time: 10-60 seconds.`,
19672
18355
  inputSchema: {
@@ -19827,6 +18510,7 @@ mainlandOnly excludes small islands and overseas territories (e.g. Corsica for F
19827
18510
 
19828
18511
  // src/tools/get-guide.ts
19829
18512
  function registerGetGuideTool(server) {
18513
+ const aliasHint = Object.entries(FORM_TYPE_ALIASES).map(([alias, target]) => `${alias} \u2192 ${target}`).join(", ");
19830
18514
  server.registerTool(
19831
18515
  "clipform_get_guide",
19832
18516
  {
@@ -19834,9 +18518,10 @@ function registerGetGuideTool(server) {
19834
18518
  description: `Retrieve craft knowledge for building a specific form type. Returns question psychology, difficulty curves, narration style, scoring setup, and writing principles as markdown. Does NOT return a step-by-step build workflow - use clipform_get_workflow for that.
19835
18519
 
19836
18520
  Available types: ${GUIDE_TYPES.join(", ")}.
18521
+ Aliases also accepted: ${aliasHint}.
19837
18522
  Quiz variants (optional): ${QUIZ_VARIANTS.join(", ")} - appends variant-specific addendum to the base quiz guide.`,
19838
18523
  inputSchema: {
19839
- type: external_exports.enum(GUIDE_TYPES).describe("Form type to get the craft guide for"),
18524
+ type: external_exports.string().describe("Form type to get the craft guide for (accepts aliases like 'feedback' \u2192 survey)"),
19840
18525
  variant: external_exports.enum(QUIZ_VARIANTS).optional().describe("Quiz sub-variant. Only used when type is 'quiz'. Omit for a standard scored quiz.")
19841
18526
  },
19842
18527
  annotations: {
@@ -19846,7 +18531,17 @@ Quiz variants (optional): ${QUIZ_VARIANTS.join(", ")} - appends variant-specific
19846
18531
  openWorldHint: false
19847
18532
  }
19848
18533
  },
19849
- async ({ type, variant }) => {
18534
+ async ({ type: rawType, variant }) => {
18535
+ const resolved = resolveFormType(rawType);
18536
+ if (!resolved) {
18537
+ return {
18538
+ content: [{
18539
+ type: "text",
18540
+ text: `Unknown form type "${rawType}". Available types: ${GUIDE_TYPES.join(", ")}. Aliases: ${aliasHint}.`
18541
+ }]
18542
+ };
18543
+ }
18544
+ const type = resolved;
19850
18545
  const validVariant = type === "quiz" ? variant : void 0;
19851
18546
  const content = getGuideContent(type, validVariant);
19852
18547
  const uri = getGuideUri(type, validVariant);
@@ -19866,6 +18561,7 @@ Quiz variants (optional): ${QUIZ_VARIANTS.join(", ")} - appends variant-specific
19866
18561
 
19867
18562
  // src/tools/get-workflow.ts
19868
18563
  function registerGetWorkflowTool(server) {
18564
+ const aliasHint = Object.entries(FORM_TYPE_ALIASES).map(([alias, target]) => `${alias} \u2192 ${target}`).join(", ");
19869
18565
  server.registerTool(
19870
18566
  "clipform_get_workflow",
19871
18567
  {
@@ -19875,24 +18571,24 @@ function registerGetWorkflowTool(server) {
19875
18571
  Does NOT return craft knowledge (question psychology, difficulty curves, narration style) - use clipform_get_guide for that.
19876
18572
 
19877
18573
  Available types: ${WORKFLOW_TYPES.join(", ")}.
18574
+ Aliases also accepted: ${aliasHint}.
19878
18575
  Quiz variants (optional): ${QUIZ_VARIANTS.join(", ")} - returns the variant-specific workflow instead of the base quiz workflow.
19879
18576
 
19880
18577
  Optional args by type:
19881
- - quiz: topic, question_count (8), media_style (video)
19882
- - quiz (variant: personality): topic, categories, question_count (8), media_style (video)
19883
- - quiz (variant: comprehension): youtube_url, question_count (8), audience, media_style (video)
18578
+ - quiz: topic, question_count (8)
18579
+ - quiz (variant: personality): topic, categories, question_count (8)
18580
+ - quiz (variant: comprehension): youtube_url, question_count (8), audience
19884
18581
  - interview: purpose, response_format (all), needs_consent (true)
19885
18582
  - survey: topic, anonymous (true)
19886
18583
  - funnel: outcomes, criteria, needs_contact (true)
19887
- - testimonial: use_case, media_style (video)
18584
+ - testimonial: use_case
19888
18585
  - application: role
19889
18586
  - booking: event_name, event_type`,
19890
18587
  inputSchema: {
19891
- type: external_exports.enum(WORKFLOW_TYPES).describe("Form type to get the build workflow for"),
18588
+ type: external_exports.string().describe("Form type to get the build workflow for (accepts aliases like 'feedback' \u2192 survey)"),
19892
18589
  variant: external_exports.enum(QUIZ_VARIANTS).optional().describe("Quiz sub-variant. Only used when type is 'quiz'. Omit for a standard scored quiz."),
19893
18590
  topic: external_exports.string().optional().describe("Topic or theme (quiz, survey)"),
19894
18591
  question_count: external_exports.number().optional().describe("Number of questions, default 8 (quiz types)"),
19895
- media_style: external_exports.enum(["text", "images", "video"]).optional().describe("Media style, default 'video' (quiz types, testimonial)"),
19896
18592
  categories: external_exports.string().optional().describe("Comma-separated outcome categories (quiz variant: personality)"),
19897
18593
  youtube_url: external_exports.string().optional().describe("YouTube video URL (quiz variant: comprehension)"),
19898
18594
  audience: external_exports.string().optional().describe("Target audience (quiz variant: comprehension)"),
@@ -19915,7 +18611,12 @@ Optional args by type:
19915
18611
  openWorldHint: false
19916
18612
  }
19917
18613
  },
19918
- async ({ type, variant, ...args }) => {
18614
+ async ({ type: rawType, variant, ...args }) => {
18615
+ const resolved = resolveFormType(rawType);
18616
+ if (!resolved) {
18617
+ return textResult(`Unknown form type "${rawType}". Available types: ${WORKFLOW_TYPES.join(", ")}. Aliases: ${aliasHint}.`);
18618
+ }
18619
+ const type = resolved;
19919
18620
  const validVariant = type === "quiz" ? variant : void 0;
19920
18621
  const text = await getWorkflowText(type, args, validVariant);
19921
18622
  return textResult(text);
@@ -19965,7 +18666,6 @@ function createServer(options) {
19965
18666
  registerSearchNewsTool(server);
19966
18667
  registerYouTubeTranscriptTool(server);
19967
18668
  registerGenerateTtsTool(server);
19968
- registerGenerateSlideshowTool(server);
19969
18669
  registerGenerateVideoTool(server);
19970
18670
  registerSearchMediaTool(server);
19971
18671
  registerRenderCompositionTool(server);
@@ -19985,4 +18685,4 @@ export {
19985
18685
  JSONRPCMessageSchema,
19986
18686
  createServer
19987
18687
  };
19988
- //# sourceMappingURL=chunk-CN4LJK36.js.map
18688
+ //# sourceMappingURL=chunk-M3G76QDR.js.map