@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.
- package/README.md +5 -7
- package/README.template.md +5 -7
- package/dist/api-client.d.ts +78 -0
- package/dist/api-client.js +22 -0
- package/dist/api-client.js.map +1 -0
- package/dist/auth-context.d.ts +10 -1
- package/dist/auth-context.js +5 -1
- package/dist/{chunk-ELK26KWM.js → chunk-5SCRFNYJ.js} +21 -9
- package/dist/chunk-5SCRFNYJ.js.map +1 -0
- package/dist/{chunk-22BV4NSB.js → chunk-GJ3XQSQY.js} +6 -4
- package/dist/{chunk-22BV4NSB.js.map → chunk-GJ3XQSQY.js.map} +1 -1
- package/dist/{chunk-4XCXDH3I.js → chunk-PXHGG57Z.js} +56 -26
- package/dist/{chunk-4XCXDH3I.js.map → chunk-PXHGG57Z.js.map} +1 -1
- package/dist/{chunk-SEZ37YSH.js → chunk-SHTP4AJC.js} +110 -107
- package/dist/chunk-SHTP4AJC.js.map +1 -0
- package/dist/{chunk-A5CFGL27.js → chunk-VPF6MLKM.js} +5 -1
- package/dist/chunk-VPF6MLKM.js.map +1 -0
- package/dist/chunk-YOVLSXPW.js +102 -0
- package/dist/chunk-YOVLSXPW.js.map +1 -0
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/instrument.d.ts +20 -3
- package/dist/instrument.js +10 -4
- package/dist/instrument.js.map +1 -1
- package/dist/prompts.js +4 -3
- package/dist/resources.js +4 -3
- package/dist/server.js +6 -5
- package/package.json +7 -3
- package/dist/chunk-A5CFGL27.js.map +0 -1
- package/dist/chunk-ELK26KWM.js.map +0 -1
- package/dist/chunk-SEZ37YSH.js.map +0 -1
|
@@ -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-
|
|
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) => [
|
|
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="${
|
|
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-
|
|
3324
|
+
//# sourceMappingURL=chunk-SHTP4AJC.js.map
|