@clipform/mcp-server 3.3.1 → 3.7.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.
@@ -2,8 +2,10 @@ import {
2
2
  MCP_ANONYMOUS_HEADER,
3
3
  MCP_AUTH_VIA_HEADER,
4
4
  MCP_MINT_PROOF_HEADER,
5
+ MCP_SESSION_ID_HEADER,
6
+ MCP_SESSION_PROOF_HEADER,
5
7
  getMcpAuth
6
- } from "./chunk-A5CFGL27.js";
8
+ } from "./chunk-VPF6MLKM.js";
7
9
  import {
8
10
  isAuthFault,
9
11
  isServerFault,
@@ -761,6 +763,38 @@ var FEATURE_FLAGS = {
761
763
  }
762
764
  };
763
765
 
766
+ // ../config/help-links.js
767
+ var HELP_TOPICS = {
768
+ goLive: { path: "/help/sharing", anchor: "go-live" },
769
+ cantGoLive: { path: "/help/sharing", anchor: "cant-go-live" },
770
+ liveAndDraft: { path: "/help/managing-forms", anchor: "live-and-draft" },
771
+ publishingChanges: { path: "/help/managing-forms", anchor: "publishing-changes" },
772
+ embedding: { path: "/help/embed", anchor: null },
773
+ emailShare: { path: "/help/sharing", anchor: "share-by-email" },
774
+ publicResults: { path: "/help/public-results", anchor: null },
775
+ trash: { path: "/help/managing-forms", anchor: "trash" },
776
+ customDomains: { path: "/help/domains", anchor: null },
777
+ customPath: { path: "/help/links", anchor: "custom-path-on-your-domain" },
778
+ // Per-node-type deep-links into help/node-types.mdx (#3963). Keyed
779
+ // `node_<nodeType>` so nodeHelpLink() (index.js) can look one up straight
780
+ // from a node's type id.
781
+ node_choice: { path: "/help/node-types", anchor: "choice" },
782
+ node_open: { path: "/help/node-types", anchor: "open-ended" },
783
+ node_details: { path: "/help/node-types", anchor: "details" },
784
+ node_button: { path: "/help/node-types", anchor: "button" },
785
+ node_end_screen: { path: "/help/node-types", anchor: "end-screen" },
786
+ node_redirect: { path: "/help/node-types", anchor: "redirect" },
787
+ node_file_download: { path: "/help/node-types", anchor: "file-download" },
788
+ node_payment: { path: "/help/node-types", anchor: "payment" }
789
+ };
790
+ function buildHelpLinks(docsBaseUrl) {
791
+ const links = {};
792
+ for (const [key, { path, anchor }] of Object.entries(HELP_TOPICS)) {
793
+ links[key] = `${docsBaseUrl}${path}${anchor ? `#${anchor}` : ""}`;
794
+ }
795
+ return links;
796
+ }
797
+
764
798
  // ../config/node-types.js
765
799
  var RESPONSE_FORMATS = ["text", "audio", "video"];
766
800
  var CONSENT_TYPES = ["consent", "opt_in"];
@@ -2629,38 +2663,6 @@ function getDiscoveryParams(formType, variant, mode = "full") {
2629
2663
  return params;
2630
2664
  }
2631
2665
 
2632
- // ../config/help-links.js
2633
- var HELP_TOPICS = {
2634
- goLive: { path: "/help/sharing", anchor: "go-live" },
2635
- cantGoLive: { path: "/help/sharing", anchor: "cant-go-live" },
2636
- liveAndDraft: { path: "/help/managing-forms", anchor: "live-and-draft" },
2637
- publishingChanges: { path: "/help/managing-forms", anchor: "publishing-changes" },
2638
- embedding: { path: "/help/embed", anchor: null },
2639
- emailShare: { path: "/help/sharing", anchor: "share-by-email" },
2640
- publicResults: { path: "/help/public-results", anchor: null },
2641
- trash: { path: "/help/managing-forms", anchor: "trash" },
2642
- customDomains: { path: "/help/domains", anchor: null },
2643
- customPath: { path: "/help/links", anchor: "custom-path-on-your-domain" },
2644
- // Per-node-type deep-links into help/node-types.mdx (#3963). Keyed
2645
- // `node_<nodeType>` so nodeHelpLink() (index.js) can look one up straight
2646
- // from a node's type id.
2647
- node_choice: { path: "/help/node-types", anchor: "choice" },
2648
- node_open: { path: "/help/node-types", anchor: "open-ended" },
2649
- node_details: { path: "/help/node-types", anchor: "details" },
2650
- node_button: { path: "/help/node-types", anchor: "button" },
2651
- node_end_screen: { path: "/help/node-types", anchor: "end-screen" },
2652
- node_redirect: { path: "/help/node-types", anchor: "redirect" },
2653
- node_file_download: { path: "/help/node-types", anchor: "file-download" },
2654
- node_payment: { path: "/help/node-types", anchor: "payment" }
2655
- };
2656
- function buildHelpLinks(docsBaseUrl) {
2657
- const links = {};
2658
- for (const [key, { path, anchor }] of Object.entries(HELP_TOPICS)) {
2659
- links[key] = `${docsBaseUrl}${path}${anchor ? `#${anchor}` : ""}`;
2660
- }
2661
- return links;
2662
- }
2663
-
2664
2666
  // ../config/logic-types.js
2665
2667
  function isBranchingActive(node) {
2666
2668
  if (!node) return true;
@@ -2974,6 +2976,7 @@ var PLAN_LIMITS = {
2974
2976
  ]
2975
2977
  }
2976
2978
  };
2979
+ var CURRENT_PLAN_VERSIONS = { 0: "free_v1", 1: "pro_v2_1k" };
2977
2980
  var PRO_BANDS = ["pro_v2_1k", "pro_v2_5k", "pro_v2_20k"].map(
2978
2981
  (version) => ({ version, ...PLAN_LIMITS[version] })
2979
2982
  );
@@ -3060,9 +3063,58 @@ var MCP_TOOL_SECURITY_SCHEMES = Object.freeze([
3060
3063
  Object.freeze({ type: "noauth" }),
3061
3064
  Object.freeze({ type: "oauth2", scopes: ["mcp"] })
3062
3065
  ]);
3066
+ var MCP_TOOL_SECURITY_SCHEMES_SIGN_IN = Object.freeze([
3067
+ Object.freeze({ type: "oauth2", scopes: ["mcp"] })
3068
+ ]);
3069
+ var MCP_ANON_TOOLS = Object.freeze({
3070
+ // account
3071
+ clipform_list_forms: "sign_in",
3072
+ clipform_get_form: "anon",
3073
+ clipform_delete_form: "sign_in",
3074
+ clipform_whoami: "sign_in",
3075
+ clipform_get_results: "sign_in",
3076
+ clipform_get_responses: "sign_in",
3077
+ // forms
3078
+ clipform_create_form: "anon",
3079
+ clipform_import_form: "anon",
3080
+ clipform_add_node: "anon",
3081
+ clipform_update_node: "anon",
3082
+ clipform_delete_node: "anon",
3083
+ clipform_update_form: "anon",
3084
+ clipform_set_logic: "anon",
3085
+ clipform_get_guide: "anon_no_workspace",
3086
+ clipform_get_workflow: "anon_no_workspace",
3087
+ // research
3088
+ clipform_search_news: "anon",
3089
+ clipform_log_generation: "anon",
3090
+ // media
3091
+ clipform_fetch_boundary: "anon",
3092
+ clipform_generate_tts: "anon",
3093
+ clipform_render_composition: "anon",
3094
+ clipform_render_video_template: "anon",
3095
+ clipform_check_render: "anon",
3096
+ clipform_upload_media_asset: "anon",
3097
+ clipform_complete_media_upload: "anon",
3098
+ clipform_attach_node_media: "anon",
3099
+ clipform_get_node_media: "anon",
3100
+ clipform_delete_node_media: "anon",
3101
+ clipform_search_media: "anon",
3102
+ clipform_search_music: "anon",
3103
+ clipform_list_compositions: "anon",
3104
+ clipform_list_assets: "anon_no_workspace",
3105
+ clipform_list_video_templates: "anon"
3106
+ });
3107
+ var MCP_VIRTUAL_TOOLS = Object.freeze(["get_more_tools"]);
3108
+ function getMcpAnonAccess(toolName) {
3109
+ if (MCP_VIRTUAL_TOOLS.includes(toolName)) return "anon_no_workspace";
3110
+ return Object.prototype.hasOwnProperty.call(MCP_ANON_TOOLS, toolName) ? MCP_ANON_TOOLS[toolName] : "sign_in";
3111
+ }
3063
3112
  var MCP_TOOL_SECURITY = Object.freeze(
3064
3113
  Object.fromEntries(
3065
- Object.keys(MCP_TOOL_TOOLSETS).map((name) => [name, MCP_TOOL_SECURITY_SCHEMES])
3114
+ Object.keys(MCP_TOOL_TOOLSETS).map((name) => [
3115
+ name,
3116
+ getMcpAnonAccess(name) === "sign_in" ? MCP_TOOL_SECURITY_SCHEMES_SIGN_IN : MCP_TOOL_SECURITY_SCHEMES
3117
+ ])
3066
3118
  )
3067
3119
  );
3068
3120
  var MCP_ANON_PUBLISH_GATE = Object.freeze({
@@ -3070,16 +3122,6 @@ var MCP_ANON_PUBLISH_GATE = Object.freeze({
3070
3122
  argument: "is_live"
3071
3123
  });
3072
3124
 
3073
- // src/lib/caps.ts
3074
- var FULL_CAPS = Object.freeze({ media: true, research: true });
3075
- function capsFromToolsets(toolsets) {
3076
- if (toolsets === void 0) return FULL_CAPS;
3077
- return {
3078
- media: toolsets.includes("media"),
3079
- research: toolsets.includes("research")
3080
- };
3081
- }
3082
-
3083
3125
  // src/lib/api-client.ts
3084
3126
  function getApiBaseUrl() {
3085
3127
  const url = process.env.API_URL;
@@ -3096,6 +3138,9 @@ function getApiBaseUrl() {
3096
3138
  }
3097
3139
  function getAuthHeaders() {
3098
3140
  const authCtx = getMcpAuth();
3141
+ if (authCtx?.loadInternalContent && !authCtx.api_key) {
3142
+ throw new Error("The anonymous no-workspace lane cannot call the API.");
3143
+ }
3099
3144
  const apiKey = authCtx?.api_key || process.env.CLIPFORM_API_KEY;
3100
3145
  if (!apiKey) {
3101
3146
  const message = "CLIPFORM_API_KEY must be set.";
@@ -3116,6 +3161,12 @@ function getAuthHeaders() {
3116
3161
  if (authCtx?.mcp_mint_proof) {
3117
3162
  headers[MCP_MINT_PROOF_HEADER] = authCtx.mcp_mint_proof;
3118
3163
  }
3164
+ if (authCtx?.mcp_session_proof) {
3165
+ headers[MCP_SESSION_PROOF_HEADER] = authCtx.mcp_session_proof;
3166
+ }
3167
+ if (authCtx?.mcp_session_id) {
3168
+ headers[MCP_SESSION_ID_HEADER] = authCtx.mcp_session_id;
3169
+ }
3119
3170
  return headers;
3120
3171
  }
3121
3172
  async function callApi(path, options = {}) {
@@ -3163,8 +3214,10 @@ async function callApi(path, options = {}) {
3163
3214
  }
3164
3215
  const data = await response.json();
3165
3216
  if (!response.ok) {
3166
- const hint = recoveryHint(response.status, path);
3167
3217
  const apiMsg = data.error || `API error (${response.status})`;
3218
+ const details = data.details;
3219
+ const reason = details && typeof details.reason === "string" ? details.reason : void 0;
3220
+ const hint = recoveryHint(response.status, path, reason);
3168
3221
  const errorMsg = hint ? `${apiMsg} - ${hint}` : apiMsg;
3169
3222
  const errorCode = typeof data.code === "string" ? data.code : void 0;
3170
3223
  if (isServerFault(response.status) || isAuthFault(response.status, errorCode)) {
@@ -3176,20 +3229,22 @@ async function callApi(path, options = {}) {
3176
3229
  api_path: `${prefix}${path}`
3177
3230
  });
3178
3231
  }
3179
- const details = data.details;
3180
- const reason = details && typeof details.reason === "string" ? details.reason : void 0;
3181
3232
  return {
3182
3233
  ok: false,
3183
3234
  status: response.status,
3184
3235
  error: errorMsg,
3236
+ apiMessage: apiMsg,
3185
3237
  code: errorCode,
3186
3238
  reason
3187
3239
  };
3188
3240
  }
3189
3241
  return { ok: true, data };
3190
3242
  }
3191
- function recoveryHint(status, path) {
3243
+ function recoveryHint(status, path, reason) {
3192
3244
  if (status === 401 || status === 403) {
3245
+ if (reason === "anonymous_not_allowed" || getMcpAuth()?.is_anonymous) {
3246
+ return "This session is anonymous - open the claim URL from clipform_create_form (or sign up) to claim your workspace, then retry.";
3247
+ }
3193
3248
  return "Check credentials: the key comes from CLIPFORM_API_KEY or the OAuth session - read clipform://context/session for the active workspace and auth mode.";
3194
3249
  }
3195
3250
  if (status === 404) {
@@ -3216,11 +3271,11 @@ function escapeChallengeValue(value) {
3216
3271
  function isAnonymousAccountRequired(result) {
3217
3272
  return result.status === 403 && result.code === "FORBIDDEN" && result.reason === "anonymous_not_allowed";
3218
3273
  }
3219
- function authChallengeMeta(errorCode, description) {
3274
+ function authChallengeMeta(errorCode, description, resourceMetadata = PROTECTED_RESOURCE_METADATA_URL) {
3220
3275
  const challenge = [
3221
3276
  `Bearer error="${escapeChallengeValue(errorCode)}"`,
3222
3277
  `error_description="${escapeChallengeValue(description)}"`,
3223
- `resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}"`
3278
+ `resource_metadata="${escapeChallengeValue(resourceMetadata)}"`
3224
3279
  ].join(", ");
3225
3280
  return { "mcp/www_authenticate": [challenge] };
3226
3281
  }
@@ -3236,57 +3291,6 @@ function structuredResult(text, structuredContent) {
3236
3291
  };
3237
3292
  }
3238
3293
 
3239
- // src/lib/session-context.ts
3240
- async function getSessionContextWithAuth() {
3241
- let result;
3242
- try {
3243
- result = await callApi("/me", { method: "GET" });
3244
- } catch {
3245
- return { text: "", authMode: "anonymous" };
3246
- }
3247
- if (!result.ok) return { text: "", authMode: "anonymous" };
3248
- const me = result.data;
3249
- const apiAuthMode = me.auth_mode ?? "anonymous";
3250
- const authMode = apiAuthMode === "anonymous" ? "anonymous" : "authenticated";
3251
- const plan = me.plan;
3252
- const lines = [];
3253
- lines.push("## Your Session");
3254
- if (authMode === "authenticated") {
3255
- lines.push(
3256
- apiAuthMode === "api_key" ? "Auth: API key (workspace-scoped)" : "Auth: signed in (connected to a Clipform account)"
3257
- );
3258
- lines.push(`Workspace: ${me.workspace?.name ?? "Unknown"}`);
3259
- } else {
3260
- lines.push("Auth: anonymous (not connected to a Clipform account)");
3261
- if (me.workspace) {
3262
- lines.push(`Workspace: ${me.workspace.name}`);
3263
- }
3264
- }
3265
- lines.push(`Plan: ${plan.name} (tier ${plan.tier})`);
3266
- if (plan.node_limit !== null) {
3267
- lines.push(`Question limit: ${plan.node_limit} per form`);
3268
- } else {
3269
- lines.push("Questions: unlimited");
3270
- }
3271
- if (plan.form_limit !== null) {
3272
- lines.push(`Form limit: ${plan.form_limit} forms`);
3273
- } else {
3274
- lines.push("Forms: unlimited");
3275
- }
3276
- if (plan.custom_theme === false) {
3277
- lines.push("Custom themes: not available on this plan");
3278
- }
3279
- if (authMode === "anonymous") {
3280
- lines.push(`
3281
- Anonymous session: forms are not tied to a Clipform account until you sign in.`);
3282
- }
3283
- return { text: lines.join("\n"), authMode };
3284
- }
3285
- async function getSessionContext() {
3286
- const { text } = await getSessionContextWithAuth();
3287
- return text;
3288
- }
3289
-
3290
3294
  export {
3291
3295
  FEATURE_FLAGS,
3292
3296
  NODE_TYPES,
@@ -3301,21 +3305,20 @@ export {
3301
3305
  getDiscoveryParams,
3302
3306
  defaultTarget,
3303
3307
  bfsOrder,
3308
+ PLAN_LIMITS,
3309
+ CURRENT_PLAN_VERSIONS,
3304
3310
  CONTACT_FIELDS,
3305
3311
  exposedCompositionIds,
3306
3312
  MCP_TOOL_TIERS,
3307
3313
  MCP_TOOL_TOOLSETS,
3308
3314
  MCP_TOOL_SECURITY,
3309
3315
  MCP_ANON_PUBLISH_GATE,
3310
- FULL_CAPS,
3311
- capsFromToolsets,
3312
3316
  callApi,
3317
+ recoveryHint,
3313
3318
  errorResult,
3314
3319
  isAnonymousAccountRequired,
3315
3320
  authChallengeMeta,
3316
3321
  textResult,
3317
- structuredResult,
3318
- getSessionContextWithAuth,
3319
- getSessionContext
3322
+ structuredResult
3320
3323
  };
3321
- //# sourceMappingURL=chunk-SEZ37YSH.js.map
3324
+ //# sourceMappingURL=chunk-SHTP4AJC.js.map