@clipform/mcp-server 4.2.7 → 4.3.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.
@@ -29,7 +29,7 @@ import {
29
29
  union,
30
30
  unknown,
31
31
  url
32
- } from "./chunk-RMFF42S5.js";
32
+ } from "./chunk-63CHR6UP.js";
33
33
  import {
34
34
  GUIDE_TYPES,
35
35
  QUIZ_VARIANTS,
@@ -38,7 +38,7 @@ import {
38
38
  getGuideUri,
39
39
  guideFallbackText,
40
40
  registerResources
41
- } from "./chunk-OVLNACRG.js";
41
+ } from "./chunk-4U4CLCYD.js";
42
42
  import {
43
43
  ANON_PREVIEW_LINK_LABEL,
44
44
  ANON_PREVIEW_NOTICE,
@@ -50,7 +50,7 @@ import {
50
50
  capsFromToolsets,
51
51
  isPreviewViewerUrl,
52
52
  withAdoptedNotice
53
- } from "./chunk-75X4S4LA.js";
53
+ } from "./chunk-QIMA75T4.js";
54
54
  import {
55
55
  ACTIVE_NODE_TYPES,
56
56
  CONTACT_FIELDS,
@@ -68,11 +68,13 @@ import {
68
68
  defaultTarget,
69
69
  errorResult,
70
70
  exposedCompositionIds,
71
+ gatedConfigKeys,
71
72
  isAnonymousAccountRequired,
72
73
  resolveFormType,
74
+ stripGatedConfigKeys,
73
75
  structuredResult,
74
76
  textResult
75
- } from "./chunk-UMO47NOJ.js";
77
+ } from "./chunk-AEU5YBXM.js";
76
78
  import {
77
79
  getMcpAuth,
78
80
  runWithMcpAuth,
@@ -16111,8 +16113,10 @@ var CONTACT_FIELD_IDS = CONTACT_FIELDS.map(
16111
16113
  function generateConfigSummary(configSchema, typeKey) {
16112
16114
  if (!configSchema?.properties) return "";
16113
16115
  const parts = [];
16116
+ const gated = typeKey ? gatedConfigKeys(typeKey) : /* @__PURE__ */ new Set();
16114
16117
  for (const [key, prop] of Object.entries(configSchema.properties)) {
16115
16118
  if (key === "content_media_type") continue;
16119
+ if (gated.has(key)) continue;
16116
16120
  if (!FEATURE_FLAGS.ENABLE_CUSTOM_SCORES && CUSTOM_SCORES_GATED_KEYS.has(key)) continue;
16117
16121
  if (prop.enum) {
16118
16122
  const vals = prop.enum.map((v) => `"${v}"`).join("|");
@@ -16247,6 +16251,24 @@ var NodeSchema = external_exports.object({
16247
16251
  config: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(CONFIG_FIELD_DESCRIPTION),
16248
16252
  options: external_exports.array(OptionSchema).optional().describe(OPTIONS_DESCRIPTION)
16249
16253
  }).superRefine((node, ctx) => refineNodeOptions(ctx, node.type, node.options, []));
16254
+ function stripGatedNodeConfig(node) {
16255
+ const { config, dropped } = stripGatedConfigKeys(node.type, node.config);
16256
+ if (dropped.length > 0) node.config = config;
16257
+ return dropped;
16258
+ }
16259
+ function gatedConfigKeysOnEveryType() {
16260
+ const gatedBy = /* @__PURE__ */ new Map();
16261
+ for (const [type, def] of Object.entries(NODE_TYPES)) {
16262
+ const gated = gatedConfigKeys(type);
16263
+ for (const key of Object.keys(def.config_schema?.properties ?? {})) {
16264
+ gatedBy.set(key, (gatedBy.get(key) ?? true) && gated.has(key));
16265
+ }
16266
+ }
16267
+ return new Set([...gatedBy].filter(([, g]) => g).map(([k]) => k));
16268
+ }
16269
+ function ignoredConfigNote(keys) {
16270
+ return `Ignored unsupported config key(s): ${keys.join(", ")}.`;
16271
+ }
16250
16272
  function applyNodeDefaults(node) {
16251
16273
  const def = NODE_TYPES[node.type];
16252
16274
  if (node.type === "button" && (!node.options || node.options.length === 0)) {
@@ -16431,8 +16453,11 @@ Example: A form that asks a question, collects contact info, then finishes:
16431
16453
  }
16432
16454
  }
16433
16455
  }
16456
+ const ignoredNotes = [];
16434
16457
  for (const q of nodes) {
16435
16458
  applyNodeDefaults(q);
16459
+ const dropped = stripGatedNodeConfig(q);
16460
+ if (dropped.length > 0) ignoredNotes.push(`[${q.type}] ${ignoredConfigNote(dropped)}`);
16436
16461
  }
16437
16462
  const settings = {};
16438
16463
  if (show_step_counter !== void 0) settings.show_step_counter = show_step_counter;
@@ -16495,6 +16520,7 @@ Example: A form that asks a question, collects contact info, then finishes:
16495
16520
  isPreview ? `CLAIM URL (fallback - or open this one-time link to sign up in the browser): ${formUrl}` : `DASHBOARD URL (sign in to edit and manage): ${formUrl}`
16496
16521
  );
16497
16522
  }
16523
+ if (ignoredNotes.length > 0) lines.push(``, ...ignoredNotes);
16498
16524
  const firstUrlLabel = isPreview ? "PREVIEW" : "FORM";
16499
16525
  const secondUrlLabel = isPreview ? "CLAIM" : "DASHBOARD";
16500
16526
  lines.push(
@@ -16871,7 +16897,10 @@ function registerListFormsTool(server, caps = FULL_CAPS) {
16871
16897
  function allowedConfigKeys(nodeType) {
16872
16898
  const schema = NODE_TYPES[nodeType]?.config_schema;
16873
16899
  const properties = schema?.properties;
16874
- if (properties) return new Set(Object.keys(properties));
16900
+ if (properties) {
16901
+ const gated = gatedConfigKeys(nodeType);
16902
+ return new Set(Object.keys(properties).filter((k) => !gated.has(k)));
16903
+ }
16875
16904
  const oneOf = schema?.oneOf;
16876
16905
  if (Array.isArray(oneOf)) {
16877
16906
  const keys = /* @__PURE__ */ new Set();
@@ -17097,6 +17126,7 @@ function registerUpdateFormTool(server) {
17097
17126
  logo_url: external_exports.string().nullable().optional().describe("AI-PROTECTED: Only set when the user explicitly provides a logo URL. Set null to clear."),
17098
17127
  show_branding: external_exports.boolean().optional().describe("Show Clipform branding. Set false to remove (Pro plan)."),
17099
17128
  brand_name: external_exports.string().nullable().optional().describe("AI-PROTECTED: Custom brand name shown in footer. Only set when user explicitly provides."),
17129
+ cover_media_asset_id: external_exports.string().uuid().nullable().optional().describe("Cover image: the picture shown in emails, link previews and on the embed button, cropped to the form's 9:16 frame. A media_asset_id of a ready still image in this form's workspace. Set null to clear and fall back to the first step's media. Goes live on the next publish (is_live: true), which can be in the same call."),
17100
17130
  tags: external_exports.array(external_exports.string()).optional().describe("Replace all tags on this form. Pass the full desired set (e.g. ['quiz', 'trivia', 'slug:elephants']). Omit to leave tags unchanged.")
17101
17131
  }),
17102
17132
  outputSchema: external_exports.object({
@@ -17115,7 +17145,7 @@ function registerUpdateFormTool(server) {
17115
17145
  openWorldHint: true
17116
17146
  }
17117
17147
  },
17118
- async ({ form_id, title, is_live, show_step_counter, disable_back_navigation, total_steps, primary_color, background_color, font_family, description, author, logo_url, show_branding, brand_name, tags }) => {
17148
+ async ({ form_id, title, is_live, show_step_counter, disable_back_navigation, total_steps, primary_color, background_color, font_family, description, author, logo_url, show_branding, brand_name, cover_media_asset_id, tags }) => {
17119
17149
  const body = {};
17120
17150
  if (title !== void 0) body.title = title;
17121
17151
  if (is_live !== void 0) body.is_live = is_live;
@@ -17130,6 +17160,7 @@ function registerUpdateFormTool(server) {
17130
17160
  if (logo_url !== void 0) body.logo_url = logo_url;
17131
17161
  if (show_branding !== void 0) body.show_branding = show_branding;
17132
17162
  if (brand_name !== void 0) body.brand_name = brand_name;
17163
+ if (cover_media_asset_id !== void 0) body.cover_media_asset_id = cover_media_asset_id;
17133
17164
  if (Object.keys(body).length > 0) {
17134
17165
  const result = await callApi(`/forms/${form_id}`, {
17135
17166
  method: "PATCH",
@@ -17208,6 +17239,10 @@ function registerUpdateFormTool(server) {
17208
17239
  updates.push(`Brand name \u2192 ${brand_name === null ? "cleared" : `"${brand_name}"`}`);
17209
17240
  updatedFields.push("brand_name");
17210
17241
  }
17242
+ if (cover_media_asset_id !== void 0) {
17243
+ updates.push(`Cover image \u2192 ${cover_media_asset_id === null ? "cleared" : `set (${cover_media_asset_id})`}`);
17244
+ updatedFields.push("cover_media_asset_id");
17245
+ }
17211
17246
  if (tags) {
17212
17247
  updates.push(`Tags \u2192 [${tags.join(", ")}]`);
17213
17248
  updatedFields.push("tags");
@@ -17744,6 +17779,7 @@ function registerAddNodeTool(server) {
17744
17779
  },
17745
17780
  async ({ form_id, node, after_node_id }) => {
17746
17781
  applyNodeDefaults(node);
17782
+ const droppedKeys = stripGatedNodeConfig(node);
17747
17783
  const body = { node };
17748
17784
  if (after_node_id) body.after_node_id = after_node_id;
17749
17785
  const result = await callApi(`/forms/${form_id}/nodes`, {
@@ -17757,7 +17793,7 @@ function registerAddNodeTool(server) {
17757
17793
  const warnings = result.data.warnings ?? [];
17758
17794
  const relinkNote = warnings.length > 0 ? ` ${warnings.join(" ")}` : " The logic chain was automatically re-linked - no clipform_set_logic call is needed for this insert.";
17759
17795
  return structuredResult(
17760
- `Node added. ID: ${nodeId} | Type: ${node.type}.${relinkNote}`,
17796
+ `Node added. ID: ${nodeId} | Type: ${node.type}.${relinkNote}${droppedKeys.length > 0 ? ` ${ignoredConfigNote(droppedKeys)}` : ""}`,
17761
17797
  { node_id: nodeId, type: node.type }
17762
17798
  );
17763
17799
  }
@@ -17815,7 +17851,18 @@ function registerUpdateNodeTool(server) {
17815
17851
  async ({ form_id, updates }) => {
17816
17852
  const allLines = [];
17817
17853
  const results = [];
17818
- for (const { node_id, prompt, label, type, required, config, options } of updates) {
17854
+ for (const { node_id, prompt, label, type, required, config: rawConfig, options } of updates) {
17855
+ let config = rawConfig;
17856
+ let droppedKeys = [];
17857
+ if (rawConfig !== void 0) {
17858
+ if (type !== void 0) {
17859
+ ({ config, dropped: droppedKeys } = stripGatedConfigKeys(type, rawConfig));
17860
+ } else {
17861
+ const gated = gatedConfigKeysOnEveryType();
17862
+ droppedKeys = Object.keys(rawConfig).filter((k) => gated.has(k));
17863
+ if (droppedKeys.length > 0) config = Object.fromEntries(Object.entries(rawConfig).filter(([k]) => !gated.has(k)));
17864
+ }
17865
+ }
17819
17866
  const body = {};
17820
17867
  if (prompt !== void 0) body.prompt = prompt;
17821
17868
  if (label !== void 0) body.label = label;
@@ -17841,11 +17888,14 @@ function registerUpdateNodeTool(server) {
17841
17888
  if (options !== void 0)
17842
17889
  changes.push(`Options \u2192 ${options.map((o) => o.content).join(", ")}`);
17843
17890
  allLines.push(`Node ${node_id} updated: ${changes.join(", ")}`);
17844
- const warnings = result.data.warnings;
17845
- if (warnings?.length) {
17891
+ const warnings = [
17892
+ ...result.data.warnings ?? [],
17893
+ ...droppedKeys.length > 0 ? [ignoredConfigNote(droppedKeys)] : []
17894
+ ];
17895
+ if (warnings.length) {
17846
17896
  for (const w of warnings) allLines.push(`Node ${node_id} warning: ${w}`);
17847
17897
  }
17848
- results.push({ node_id, ok: true, ...warnings?.length ? { warnings } : {} });
17898
+ results.push({ node_id, ok: true, ...warnings.length ? { warnings } : {} });
17849
17899
  }
17850
17900
  return structuredResult(allLines.join("\n"), { results });
17851
17901
  }
@@ -20213,4 +20263,4 @@ export {
20213
20263
  * MIT Licensed
20214
20264
  *)
20215
20265
  */
20216
- //# sourceMappingURL=chunk-K67KW7GF.js.map
20266
+ //# sourceMappingURL=chunk-JY7OZS6P.js.map