@clipform/mcp-server 4.2.3 → 4.2.5
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/dist/api-client.js +1 -1
- package/dist/{caps-DBnfcEyJ.d.ts → caps-KNlvfilv.d.ts} +2 -0
- package/dist/{chunk-MO3ABORB.js → chunk-63PX3SVJ.js} +3 -3
- package/dist/{chunk-UYJLVVM3.js → chunk-BL7T3UBS.js} +3 -3
- package/dist/{chunk-E7C34M2J.js → chunk-ECG7HBWZ.js} +5 -4
- package/dist/chunk-ECG7HBWZ.js.map +1 -0
- package/dist/{chunk-XFGQP52H.js → chunk-EN5TEETY.js} +15 -10
- package/dist/{chunk-XFGQP52H.js.map → chunk-EN5TEETY.js.map} +1 -1
- package/dist/{chunk-ZRBMT7BF.js → chunk-GY5QLQOU.js} +123 -15
- package/dist/chunk-GY5QLQOU.js.map +1 -0
- package/dist/index.js +5 -5
- package/dist/prompts.d.ts +1 -1
- package/dist/prompts.js +3 -3
- package/dist/resources.d.ts +1 -1
- package/dist/resources.js +3 -3
- package/dist/server.d.ts +1 -1
- package/dist/server.js +5 -5
- package/package.json +1 -1
- package/server.json +2 -2
- package/dist/chunk-E7C34M2J.js.map +0 -1
- package/dist/chunk-ZRBMT7BF.js.map +0 -1
- /package/dist/{chunk-MO3ABORB.js.map → chunk-63PX3SVJ.js.map} +0 -0
- /package/dist/{chunk-UYJLVVM3.js.map → chunk-BL7T3UBS.js.map} +0 -0
package/dist/api-client.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FULL_CAPS,
|
|
3
3
|
getSessionContext
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ECG7HBWZ.js";
|
|
5
5
|
import {
|
|
6
6
|
ALL_VARIANTS,
|
|
7
7
|
FORM_TYPES,
|
|
8
8
|
FORM_TYPE_KEYS,
|
|
9
9
|
callApi
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GY5QLQOU.js";
|
|
11
11
|
import {
|
|
12
12
|
getMcpAuth
|
|
13
13
|
} from "./chunk-VPF6MLKM.js";
|
|
@@ -155,4 +155,4 @@ export {
|
|
|
155
155
|
getGuideUri,
|
|
156
156
|
registerResources
|
|
157
157
|
};
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
158
|
+
//# sourceMappingURL=chunk-63PX3SVJ.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FULL_CAPS,
|
|
3
3
|
getSessionContextWithAuth
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ECG7HBWZ.js";
|
|
5
5
|
import {
|
|
6
6
|
WORKFLOW_TYPES,
|
|
7
7
|
getDiscoveryParams
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GY5QLQOU.js";
|
|
9
9
|
import {
|
|
10
10
|
__export
|
|
11
11
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -15224,4 +15224,4 @@ export {
|
|
|
15224
15224
|
getWorkflowText,
|
|
15225
15225
|
registerPrompts
|
|
15226
15226
|
};
|
|
15227
|
-
//# sourceMappingURL=chunk-
|
|
15227
|
+
//# sourceMappingURL=chunk-BL7T3UBS.js.map
|
|
@@ -2,18 +2,19 @@ import {
|
|
|
2
2
|
CURRENT_PLAN_VERSIONS,
|
|
3
3
|
PLAN_LIMITS,
|
|
4
4
|
callApi
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GY5QLQOU.js";
|
|
6
6
|
import {
|
|
7
7
|
getMcpAuth
|
|
8
8
|
} from "./chunk-VPF6MLKM.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/caps.ts
|
|
11
|
-
var FULL_CAPS = Object.freeze({ media: true, research: true });
|
|
11
|
+
var FULL_CAPS = Object.freeze({ media: true, research: true, forms: true });
|
|
12
12
|
function capsFromToolsets(toolsets) {
|
|
13
13
|
if (toolsets === void 0) return FULL_CAPS;
|
|
14
14
|
return {
|
|
15
15
|
media: toolsets.includes("media"),
|
|
16
|
-
research: toolsets.includes("research")
|
|
16
|
+
research: toolsets.includes("research"),
|
|
17
|
+
forms: toolsets.includes("forms")
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -111,4 +112,4 @@ export {
|
|
|
111
112
|
getSessionContextWithAuth,
|
|
112
113
|
getSessionContext
|
|
113
114
|
};
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
115
|
+
//# sourceMappingURL=chunk-ECG7HBWZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/caps.ts","../src/lib/anon-notice.ts","../src/lib/session-context.ts"],"sourcesContent":["import type { McpToolset } from \"@vid-master/config\";\n\n/**\n * What a connected surface can actually do, derived from the connect-time\n * toolset filter (#3309) so the guidance layers (server instructions, prompt\n * recipes, `clipform_get_workflow`, craft guides) never reference a tool the\n * surface doesn't register (#3681).\n *\n * The Claude Connectors Directory surface (`mcp.clipform.io/forms`) is\n * account + forms only: no media generation and no research helpers. A\n * workflow that still says \"call clipform_generate_tts\" there sends the model\n * at a tool that doesn't exist, which shows up in review as failed tool\n * calls. Every guidance producer takes a ServerCaps and gates on it.\n */\nexport interface ServerCaps {\n /** Narration, video, image, music, render, and asset tools are registered. */\n media: boolean;\n /** News lookup and the generation audit log are registered. */\n research: boolean;\n /** Form tools (create, edit, publish) are registered. */\n forms: boolean;\n}\n\n/** Every toolset registered - stdio/npx and the bare remote endpoint. */\nexport const FULL_CAPS: ServerCaps = Object.freeze({ media: true, research: true, forms: true });\n\nexport function capsFromToolsets(toolsets?: readonly McpToolset[]): ServerCaps {\n if (toolsets === undefined) return FULL_CAPS;\n return {\n media: toolsets.includes(\"media\"),\n research: toolsets.includes(\"research\"),\n forms: toolsets.includes(\"forms\"),\n };\n}\n","import { getMcpAuth } from \"./auth-context.js\";\n\n/**\n * #4650: anonymous (preview) accounts are temporary. Date-free by design -\n * the purge is not enforced yet, so no expiry date or day count is promised\n * (exact dates are follow-up #4662). Defined once; every anonymous-lane\n * surface (create/update_form text, whoami, session resource) reuses it.\n */\nexport const ANON_PREVIEW_NOTICE =\n \"Preview accounts are temporary - claim yours to keep your forms.\";\n\n/** The notice for an anonymous MCP caller, or null for everyone else. */\nexport function anonPreviewNotice(): string | null {\n return getMcpAuth()?.is_anonymous ? ANON_PREVIEW_NOTICE : null;\n}\n\n/**\n * #4845: an anonymous build's link is a private preview, never a respondent\n * link (answers are not saved). Wording defined once; create_form, get_form,\n * the format-form link label and the output-schema descriptions all reuse it.\n */\nexport const ANON_PREVIEW_LINK_LABEL = \"Preview (answers not saved)\";\n\nexport const ANON_PREVIEW_ONLY_NOTICE =\n 'The form is ready as a preview. To go live, say \"publish it\" - that prompts sign-in and keeps this chat connected to your account. In the preview, answers are not saved: do not share the preview link with respondents.';\n\nexport const PREVIEW_URL_DESCRIPTION =\n \"Private preview of the form. Answers are not saved, so do not share it with respondents.\";\n\nexport const CLAIM_URL_DESCRIPTION =\n \"One-time link to sign up, keep this form and publish it.\";\n\n/** True for a viewer link in preview mode (an anonymous caller's draft). */\nexport function isPreviewViewerUrl(url: unknown): boolean {\n return typeof url === \"string\" && url.includes(\"mode=preview\");\n}\n","import { BUSINESS, PLAN_LIMITS, CURRENT_PLAN_VERSIONS } from \"@vid-master/config\";\nimport { callApi } from \"./api-client.js\";\nimport { ANON_PREVIEW_NOTICE } from \"./anon-notice.js\";\nimport { getMcpAuth } from \"./auth-context.js\";\n\nexport type AuthMode = \"authenticated\" | \"anonymous\";\n\nexport interface SessionContextResult {\n text: string;\n authMode: AuthMode;\n}\n\nexport async function getSessionContextWithAuth(): Promise<SessionContextResult> {\n let me: any;\n const authCtx = getMcpAuth();\n if (authCtx?.loadInternalContent && !authCtx.api_key) {\n // #4657: the no-workspace anon lane (get_workflow with no mint) has no\n // workspace for /me to describe, so plan caps default to Free.\n const free = PLAN_LIMITS[CURRENT_PLAN_VERSIONS[0]];\n me = {\n auth_mode: \"anonymous\",\n plan: {\n name: free.name,\n tier: free.tier,\n node_limit: free.node_limit,\n form_limit: free.form_limit ?? null,\n custom_theme: free.custom_theme,\n },\n };\n } else {\n let result;\n try {\n result = await callApi(\"/me\", { method: \"GET\" });\n } catch {\n return { text: \"\", authMode: \"anonymous\" };\n }\n if (!result.ok) return { text: \"\", authMode: \"anonymous\" };\n me = result.data as any;\n }\n // The API's auth_mode is \"api_key\" | \"oauth\" | \"session\" | \"anonymous\".\n // Anything credentialed counts as authenticated - the old `=== \"oauth\"`\n // check matched nothing the API returns, so API-key sessions were labelled\n // anonymous with a \"sign in to unlock\" nudge right next to their real\n // plan (#412 F6).\n // The anon MCP lane runs as a minted bot key (/me says \"api_key\"), so the\n // auth context is the truth for anonymous (#4653).\n const apiAuthMode: string = getMcpAuth()?.is_anonymous\n ? \"anonymous\"\n : ((me.auth_mode as string) ?? \"anonymous\");\n const authMode: AuthMode = apiAuthMode === \"anonymous\" ? \"anonymous\" : \"authenticated\";\n const plan = me.plan;\n const lines: string[] = [];\n\n lines.push(\"## Your Session\");\n if (authMode === \"authenticated\") {\n lines.push(\n apiAuthMode === \"api_key\"\n ? \"Auth: API key (workspace-scoped)\"\n : \"Auth: signed in (connected to a Clipform account)\"\n );\n // Workspace NAME only - the workspace UUID and the raw user_id/company_id\n // are internal database identifiers the model never needs (response\n // hygiene / disclosure guard, #2976).\n lines.push(`Workspace: ${me.workspace?.name ?? \"Unknown\"}`);\n } else {\n lines.push(\"Auth: anonymous (not connected to a Clipform account)\");\n if (me.workspace) {\n lines.push(`Workspace: ${me.workspace.name}`);\n }\n }\n lines.push(`Plan: ${plan.name} (tier ${plan.tier})`);\n if (plan.node_limit !== null) {\n lines.push(`Question limit: ${plan.node_limit} per form`);\n } else {\n lines.push(\"Questions: unlimited\");\n }\n if (plan.form_limit !== null) {\n lines.push(`Form limit: ${plan.form_limit} forms`);\n } else {\n lines.push(\"Forms: unlimited\");\n }\n if (plan.custom_theme === false) {\n lines.push(\"Custom themes: not available on this plan\");\n }\n if (authMode === \"anonymous\") {\n // Neutral statement of fact, no upsell/CTA copy (commerce sweep, #2976):\n // an anonymous session's forms are not tied to an account until one signs in.\n lines.push(`\\nAnonymous session: forms are not tied to a Clipform account until you sign in.`);\n lines.push(ANON_PREVIEW_NOTICE);\n }\n\n return { text: lines.join(\"\\n\"), authMode };\n}\n\nexport async function getSessionContext(): Promise<string> {\n const { text } = await getSessionContextWithAuth();\n return text;\n}\n"],"mappings":";;;;;;;;;;AAwBO,IAAM,YAAwB,OAAO,OAAO,EAAE,OAAO,MAAM,UAAU,MAAM,OAAO,KAAK,CAAC;AAExF,SAAS,iBAAiB,UAA8C;AAC7E,MAAI,aAAa,OAAW,QAAO;AACnC,SAAO;AAAA,IACL,OAAO,SAAS,SAAS,OAAO;AAAA,IAChC,UAAU,SAAS,SAAS,UAAU;AAAA,IACtC,OAAO,SAAS,SAAS,OAAO;AAAA,EAClC;AACF;;;ACzBO,IAAM,sBACX;AAGK,SAAS,oBAAmC;AACjD,SAAO,WAAW,GAAG,eAAe,sBAAsB;AAC5D;AAOO,IAAM,0BAA0B;AAEhC,IAAM,2BACX;AAEK,IAAM,0BACX;AAEK,IAAM,wBACX;AAGK,SAAS,mBAAmB,KAAuB;AACxD,SAAO,OAAO,QAAQ,YAAY,IAAI,SAAS,cAAc;AAC/D;;;ACvBA,eAAsB,4BAA2D;AAC/E,MAAI;AACJ,QAAM,UAAU,WAAW;AAC3B,MAAI,SAAS,uBAAuB,CAAC,QAAQ,SAAS;AAGpD,UAAM,OAAO,YAAY,sBAAsB,CAAC,CAAC;AACjD,SAAK;AAAA,MACH,WAAW;AAAA,MACX,MAAM;AAAA,QACJ,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,YAAY,KAAK;AAAA,QACjB,YAAY,KAAK,cAAc;AAAA,QAC/B,cAAc,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,QAAQ,OAAO,EAAE,QAAQ,MAAM,CAAC;AAAA,IACjD,QAAQ;AACN,aAAO,EAAE,MAAM,IAAI,UAAU,YAAY;AAAA,IAC3C;AACA,QAAI,CAAC,OAAO,GAAI,QAAO,EAAE,MAAM,IAAI,UAAU,YAAY;AACzD,SAAK,OAAO;AAAA,EACd;AAQA,QAAM,cAAsB,WAAW,GAAG,eACtC,cACE,GAAG,aAAwB;AACjC,QAAM,WAAqB,gBAAgB,cAAc,cAAc;AACvE,QAAM,OAAO,GAAG;AAChB,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,iBAAiB;AAC5B,MAAI,aAAa,iBAAiB;AAChC,UAAM;AAAA,MACJ,gBAAgB,YACZ,qCACA;AAAA,IACN;AAIA,UAAM,KAAK,cAAc,GAAG,WAAW,QAAQ,SAAS,EAAE;AAAA,EAC5D,OAAO;AACL,UAAM,KAAK,uDAAuD;AAClE,QAAI,GAAG,WAAW;AAChB,YAAM,KAAK,cAAc,GAAG,UAAU,IAAI,EAAE;AAAA,IAC9C;AAAA,EACF;AACA,QAAM,KAAK,SAAS,KAAK,IAAI,UAAU,KAAK,IAAI,GAAG;AACnD,MAAI,KAAK,eAAe,MAAM;AAC5B,UAAM,KAAK,mBAAmB,KAAK,UAAU,WAAW;AAAA,EAC1D,OAAO;AACL,UAAM,KAAK,sBAAsB;AAAA,EACnC;AACA,MAAI,KAAK,eAAe,MAAM;AAC5B,UAAM,KAAK,eAAe,KAAK,UAAU,QAAQ;AAAA,EACnD,OAAO;AACL,UAAM,KAAK,kBAAkB;AAAA,EAC/B;AACA,MAAI,KAAK,iBAAiB,OAAO;AAC/B,UAAM,KAAK,2CAA2C;AAAA,EACxD;AACA,MAAI,aAAa,aAAa;AAG5B,UAAM,KAAK;AAAA,+EAAkF;AAC7F,UAAM,KAAK,mBAAmB;AAAA,EAChC;AAEA,SAAO,EAAE,MAAM,MAAM,KAAK,IAAI,GAAG,SAAS;AAC5C;AAEA,eAAsB,oBAAqC;AACzD,QAAM,EAAE,KAAK,IAAI,MAAM,0BAA0B;AACjD,SAAO;AACT;","names":[]}
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
union,
|
|
30
30
|
unknown,
|
|
31
31
|
url
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-BL7T3UBS.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-
|
|
41
|
+
} from "./chunk-63PX3SVJ.js";
|
|
42
42
|
import {
|
|
43
43
|
ANON_PREVIEW_LINK_LABEL,
|
|
44
44
|
ANON_PREVIEW_NOTICE,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
anonPreviewNotice,
|
|
50
50
|
capsFromToolsets,
|
|
51
51
|
isPreviewViewerUrl
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-ECG7HBWZ.js";
|
|
53
53
|
import {
|
|
54
54
|
ACTIVE_NODE_TYPES,
|
|
55
55
|
CONTACT_FIELDS,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
resolveFormType,
|
|
72
72
|
structuredResult,
|
|
73
73
|
textResult
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-GY5QLQOU.js";
|
|
75
75
|
import {
|
|
76
76
|
getMcpAuth,
|
|
77
77
|
runWithMcpAuth,
|
|
@@ -16769,7 +16769,7 @@ function registerImportFormTool(server) {
|
|
|
16769
16769
|
}
|
|
16770
16770
|
|
|
16771
16771
|
// src/tools/list-forms.ts
|
|
16772
|
-
function registerListFormsTool(server) {
|
|
16772
|
+
function registerListFormsTool(server, caps = FULL_CAPS) {
|
|
16773
16773
|
server.registerTool(
|
|
16774
16774
|
"clipform_list_forms",
|
|
16775
16775
|
{
|
|
@@ -16841,7 +16841,12 @@ function registerListFormsTool(server) {
|
|
|
16841
16841
|
next_cursor: data.next_cursor
|
|
16842
16842
|
};
|
|
16843
16843
|
if (data.forms.length === 0) {
|
|
16844
|
-
|
|
16844
|
+
const unfiltered = !search && !tag && !published && !cursor;
|
|
16845
|
+
if (!unfiltered) {
|
|
16846
|
+
return structuredResult("No forms found matching the criteria.", structured);
|
|
16847
|
+
}
|
|
16848
|
+
const text = caps.forms ? `No forms in this workspace yet. ${ONBOARDING_OFFER_TOOL_CUE} Then build it with clipform_create_form.` : "No forms in this workspace yet.";
|
|
16849
|
+
return structuredResult(text, structured);
|
|
16845
16850
|
}
|
|
16846
16851
|
const lines = [`Found ${data.forms.length} form(s):
|
|
16847
16852
|
`];
|
|
@@ -17852,7 +17857,7 @@ function registerDeleteNodeTool(server) {
|
|
|
17852
17857
|
"clipform_delete_node",
|
|
17853
17858
|
{
|
|
17854
17859
|
title: "Delete Node",
|
|
17855
|
-
description: `Delete a node from a form. The logic chain is automatically re-linked (the previous node will point to the next one). Cannot delete the start node or the last end screen. Requires user confirmation before it runs.`,
|
|
17860
|
+
description: `Delete a node from a form. The logic chain is automatically re-linked (the previous node will point to the next one). Cannot delete the start node or the last end screen. On a live form the node stays on the live form until the form is published. Requires user confirmation before it runs.`,
|
|
17856
17861
|
inputSchema: external_exports.object({
|
|
17857
17862
|
form_id: external_exports.string().uuid().describe("The form UUID (returned by clipform_create_form, not the short share_id from the URL)"),
|
|
17858
17863
|
node_id: external_exports.string().describe("The node ID to delete"),
|
|
@@ -20035,7 +20040,7 @@ function buildInstructions(caps) {
|
|
|
20035
20040
|
"At the start of a build, call clipform_get_workflow to load the recipe for the form type, and clipform_get_guide for craft detail.",
|
|
20036
20041
|
"Every *_id argument is a UUID returned by the tools - not the short share_id from a form URL.",
|
|
20037
20042
|
"For an account-scoped request, call clipform_whoami first to confirm the active workspace and plan.",
|
|
20038
|
-
caps.media ? "Deleting a form moves it to the trash (restorable from the dashboard); deleting a node or media
|
|
20043
|
+
caps.media ? "Deleting a form moves it to the trash (restorable from the dashboard); deleting a node or media cannot be undone (a node deleted on a live form stays on the live form until you publish). Those tools ask the user to confirm before running." : "Deleting a form moves it to the trash (restorable from the dashboard); deleting a node cannot be undone (on a live form it stays on the live form until you publish). Those tools ask the user to confirm before running."
|
|
20039
20044
|
].filter((line) => typeof line === "string").join(" ");
|
|
20040
20045
|
}
|
|
20041
20046
|
function pinDraft07(schema) {
|
|
@@ -20108,7 +20113,7 @@ function createServer(options) {
|
|
|
20108
20113
|
};
|
|
20109
20114
|
registerCreateFormTool(server);
|
|
20110
20115
|
registerImportFormTool(server);
|
|
20111
|
-
registerListFormsTool(server);
|
|
20116
|
+
registerListFormsTool(server, caps);
|
|
20112
20117
|
registerWhoamiTool(server);
|
|
20113
20118
|
registerGetFormTool(server);
|
|
20114
20119
|
registerUpdateFormTool(server);
|
|
@@ -20207,4 +20212,4 @@ export {
|
|
|
20207
20212
|
* MIT Licensed
|
|
20208
20213
|
*)
|
|
20209
20214
|
*/
|
|
20210
|
-
//# sourceMappingURL=chunk-
|
|
20215
|
+
//# sourceMappingURL=chunk-EN5TEETY.js.map
|