@clipform/mcp-server 2.10.5 → 2.10.7
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 +1 -1
- package/dist/auth-context.d.ts +14 -1
- package/dist/auth-context.js +3 -1
- package/dist/{chunk-A5RVUIGS.js → chunk-6FVQBVKW.js} +2 -2
- package/dist/{chunk-ENHVQDSI.js → chunk-HZMMOSEM.js} +3 -1
- package/dist/chunk-HZMMOSEM.js.map +1 -0
- package/dist/{chunk-44LRAJJ3.js → chunk-JCCGDVUH.js} +15 -9
- package/dist/{chunk-44LRAJJ3.js.map → chunk-JCCGDVUH.js.map} +1 -1
- package/dist/{chunk-QZO6MGNN.js → chunk-RMMQVPZN.js} +2 -2
- package/dist/{chunk-O35IVA4L.js → chunk-SAAH4U7O.js} +6 -2
- package/dist/{chunk-O35IVA4L.js.map → chunk-SAAH4U7O.js.map} +1 -1
- package/dist/index.js +5 -5
- package/dist/prompts.js +3 -3
- package/dist/resources.js +3 -3
- package/dist/server.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-ENHVQDSI.js.map +0 -1
- /package/dist/{chunk-A5RVUIGS.js.map → chunk-6FVQBVKW.js.map} +0 -0
- /package/dist/{chunk-QZO6MGNN.js.map → chunk-RMMQVPZN.js.map} +0 -0
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ Your MCP client lists these automatically on connect (via `tools/list`). Full re
|
|
|
66
66
|
| `clipform_create_form` | Create a new Clipform (interactive video-style form). |
|
|
67
67
|
| `clipform_import_form` | Convert a public Google Form, Typeform, or Tally form into a new Clipform. |
|
|
68
68
|
| `clipform_list_forms` | List forms in your workspace with optional filtering. |
|
|
69
|
-
| `clipform_whoami` | Show the current identity: auth mode (api key, session, or anonymous), active workspace, and plan limits. |
|
|
69
|
+
| `clipform_whoami` | Show the current identity: auth mode (api key, oauth, session, or anonymous), active workspace, and plan limits. |
|
|
70
70
|
| `clipform_get_form` | Retrieve a form's details including all nodes in sequential order and their routing. |
|
|
71
71
|
| `clipform_update_form` | Update a form's title, publish status, settings, or tags. |
|
|
72
72
|
| `clipform_delete_form` | Move a form and all its nodes to the trash. |
|
package/dist/auth-context.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ interface McpAuthContext {
|
|
|
15
15
|
tool_name?: string;
|
|
16
16
|
api_key?: string;
|
|
17
17
|
is_anonymous?: boolean;
|
|
18
|
+
auth_via?: "oauth";
|
|
18
19
|
mcp_mint_proof?: string;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
@@ -29,6 +30,18 @@ interface McpAuthContext {
|
|
|
29
30
|
* never use it to gain anonymous-JWT privileges it doesn't already have.
|
|
30
31
|
*/
|
|
31
32
|
declare const MCP_ANONYMOUS_HEADER = "x-clipform-anonymous";
|
|
33
|
+
/**
|
|
34
|
+
* Marker header the in-process MCP tool layer sets on its outgoing API
|
|
35
|
+
* requests (api-client.ts) when `auth_via` is "oauth", so /v1/me can report
|
|
36
|
+
* `auth_mode: "oauth"` for an OAuth-connected user instead of the generic
|
|
37
|
+
* "api_key" the bot-key lane would otherwise get (#3716). Label-only: it
|
|
38
|
+
* changes nothing but the reported string. Trusting it from the wire is
|
|
39
|
+
* safe because a direct API-key caller who sets this header on their own
|
|
40
|
+
* request only mislabels their own whoami output - they gain no privilege,
|
|
41
|
+
* exactly the same reasoning as MCP_ANONYMOUS_HEADER above (except that
|
|
42
|
+
* header can only restrict, and this one can only relabel).
|
|
43
|
+
*/
|
|
44
|
+
declare const MCP_AUTH_VIA_HEADER = "x-clipform-auth-via";
|
|
32
45
|
/**
|
|
33
46
|
* Carries `mcp_mint_proof` on the same outgoing bot-key request. Unlike
|
|
34
47
|
* MCP_ANONYMOUS_HEADER (a boolean that can only ever RESTRICT), this header's
|
|
@@ -43,4 +56,4 @@ declare function runWithMcpAuth<T>(ctx: McpAuthContext, fn: () => Promise<T> | T
|
|
|
43
56
|
declare function getMcpAuth(): McpAuthContext | undefined;
|
|
44
57
|
declare function runWithMcpTool<T>(toolName: string, fn: () => Promise<T> | T): Promise<T> | T;
|
|
45
58
|
|
|
46
|
-
export { MCP_ANONYMOUS_HEADER, MCP_MINT_PROOF_HEADER, type McpAuthContext, getMcpAuth, runWithMcpAuth, runWithMcpTool };
|
|
59
|
+
export { MCP_ANONYMOUS_HEADER, MCP_AUTH_VIA_HEADER, MCP_MINT_PROOF_HEADER, type McpAuthContext, getMcpAuth, runWithMcpAuth, runWithMcpTool };
|
package/dist/auth-context.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCP_ANONYMOUS_HEADER,
|
|
3
|
+
MCP_AUTH_VIA_HEADER,
|
|
3
4
|
MCP_MINT_PROOF_HEADER,
|
|
4
5
|
getMcpAuth,
|
|
5
6
|
runWithMcpAuth,
|
|
6
7
|
runWithMcpTool
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HZMMOSEM.js";
|
|
8
9
|
import "./chunk-G3PMV62Z.js";
|
|
9
10
|
export {
|
|
10
11
|
MCP_ANONYMOUS_HEADER,
|
|
12
|
+
MCP_AUTH_VIA_HEADER,
|
|
11
13
|
MCP_MINT_PROOF_HEADER,
|
|
12
14
|
getMcpAuth,
|
|
13
15
|
runWithMcpAuth,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
FULL_CAPS,
|
|
6
6
|
callApi,
|
|
7
7
|
getSessionContext
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SAAH4U7O.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/guides.ts
|
|
11
11
|
var guidesPromise = null;
|
|
@@ -143,4 +143,4 @@ export {
|
|
|
143
143
|
getGuideUri,
|
|
144
144
|
registerResources
|
|
145
145
|
};
|
|
146
|
-
//# sourceMappingURL=chunk-
|
|
146
|
+
//# sourceMappingURL=chunk-6FVQBVKW.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/lib/auth-context.ts
|
|
2
2
|
import { AsyncLocalStorage } from "async_hooks";
|
|
3
3
|
var MCP_ANONYMOUS_HEADER = "x-clipform-anonymous";
|
|
4
|
+
var MCP_AUTH_VIA_HEADER = "x-clipform-auth-via";
|
|
4
5
|
var MCP_MINT_PROOF_HEADER = "x-clipform-mcp-mint-proof";
|
|
5
6
|
var storage = new AsyncLocalStorage();
|
|
6
7
|
function runWithMcpAuth(ctx, fn) {
|
|
@@ -17,9 +18,10 @@ function runWithMcpTool(toolName, fn) {
|
|
|
17
18
|
|
|
18
19
|
export {
|
|
19
20
|
MCP_ANONYMOUS_HEADER,
|
|
21
|
+
MCP_AUTH_VIA_HEADER,
|
|
20
22
|
MCP_MINT_PROOF_HEADER,
|
|
21
23
|
runWithMcpAuth,
|
|
22
24
|
getMcpAuth,
|
|
23
25
|
runWithMcpTool
|
|
24
26
|
};
|
|
25
|
-
//# sourceMappingURL=chunk-
|
|
27
|
+
//# sourceMappingURL=chunk-HZMMOSEM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/auth-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\n/**\n * Identity of the end-user a given MCP request is acting on behalf of.\n *\n * Populated by the in-process host (apps/api) after validating an OAuth\n * Bearer on /mcp. The MCP tool layer reads it to decide which workspace\n * forms should land in and which plan tier gates apply.\n *\n * NOT populated when the server runs as a local stdio process (npx) - in\n * that mode tools fall back to edit-token based auth.\n */\nexport interface McpAuthContext {\n user_id: string;\n workspace_id: string;\n scopes: string[];\n tool_name?: string;\n api_key?: string;\n // Set when the human behind this tool call is an anonymous Supabase\n // session (apps/api's app-chat lane, #2983/#2984) - api-client.ts's\n // getAuthHeaders reads it to mark the outgoing bot-key HTTP request so the\n // API can propagate the restriction even though the request itself\n // authenticates with an API key, not a JWT.\n is_anonymous?: boolean;\n // Set on the OAuth branch of apps/api's mcp/handler.ts when this request's\n // bot API key was resolved on behalf of an OAuth-connected user (#3716) -\n // api-client.ts's getAuthHeaders reads it to mark the outgoing request so\n // /v1/me can report auth_mode \"oauth\" instead of the generic \"api_key\" the\n // bot-key lane would otherwise get, even though the request itself\n // authenticates with an API key, not an OAuth token.\n auth_via?: \"oauth\";\n // #3330 review fix (blocker 1): an HMAC proof (apps/api's mcp-mint-proof.ts)\n // that THIS exact request's #1415 anon lane freshly minted a brand-new anon\n // identity for `workspace_id` - set only on the mint branch of\n // resolveAnonymousMcpAuth, never when auth was resolved via an inbound\n // form_id (even the caller's own). Lets create-form.ts safely offer a\n // same-UID claim link without ever deriving \"who to bind it to\" from a\n // body-supplied id, which would let a batch smuggling another tenant's\n // form_id alongside a create_form call mint a claim token for THAT\n // tenant's identity instead of the caller's own.\n mcp_mint_proof?: string;\n}\n\n/**\n * Marker header the in-process MCP tool layer sets on its outgoing API\n * requests (api-client.ts) when `is_anonymous` is true, so an anonymous\n * app-chat session can't launder itself into an unrestricted API-key caller\n * by asking the bot to publish/mint credentials on its behalf. apps/api's\n * authMiddleware / workspaceAccessMiddleware / requireWorkspaceWriteAuth\n * read this on the API-key path and set isAnonymous accordingly - trusting\n * it is safe because it can only RESTRICT a caller: a real integration that\n * sets this header on its own API-key requests only denies itself, it can\n * never use it to gain anonymous-JWT privileges it doesn't already have.\n */\nexport const MCP_ANONYMOUS_HEADER = \"x-clipform-anonymous\";\n\n/**\n * Marker header the in-process MCP tool layer sets on its outgoing API\n * requests (api-client.ts) when `auth_via` is \"oauth\", so /v1/me can report\n * `auth_mode: \"oauth\"` for an OAuth-connected user instead of the generic\n * \"api_key\" the bot-key lane would otherwise get (#3716). Label-only: it\n * changes nothing but the reported string. Trusting it from the wire is\n * safe because a direct API-key caller who sets this header on their own\n * request only mislabels their own whoami output - they gain no privilege,\n * exactly the same reasoning as MCP_ANONYMOUS_HEADER above (except that\n * header can only restrict, and this one can only relabel).\n */\nexport const MCP_AUTH_VIA_HEADER = \"x-clipform-auth-via\";\n\n/**\n * Carries `mcp_mint_proof` on the same outgoing bot-key request. Unlike\n * MCP_ANONYMOUS_HEADER (a boolean that can only ever RESTRICT), this header's\n * VALUE matters - it names an identity a claim token gets bound to - so its\n * value is HMAC-signed (mcp-mint-proof.ts) rather than trusted raw: a direct\n * external caller reaching `POST /v1/forms` with any valid workspace API key\n * could otherwise hand-set an unsigned \"mint uid\" header to an arbitrary\n * victim's uid themselves (#3330 review).\n */\nexport const MCP_MINT_PROOF_HEADER = \"x-clipform-mcp-mint-proof\";\n\nconst storage = new AsyncLocalStorage<McpAuthContext>();\n\nexport function runWithMcpAuth<T>(ctx: McpAuthContext, fn: () => Promise<T> | T): Promise<T> | T {\n return storage.run(ctx, fn);\n}\n\nexport function getMcpAuth(): McpAuthContext | undefined {\n return storage.getStore();\n}\n\nexport function runWithMcpTool<T>(toolName: string, fn: () => Promise<T> | T): Promise<T> | T {\n const parent = storage.getStore();\n if (!parent) return fn();\n return storage.run({ ...parent, tool_name: toolName }, fn);\n}\n"],"mappings":";AAAA,SAAS,yBAAyB;AAsD3B,IAAM,uBAAuB;AAa7B,IAAM,sBAAsB;AAW5B,IAAM,wBAAwB;AAErC,IAAM,UAAU,IAAI,kBAAkC;AAE/C,SAAS,eAAkB,KAAqB,IAA0C;AAC/F,SAAO,QAAQ,IAAI,KAAK,EAAE;AAC5B;AAEO,SAAS,aAAyC;AACvD,SAAO,QAAQ,SAAS;AAC1B;AAEO,SAAS,eAAkB,UAAkB,IAA0C;AAC5F,QAAM,SAAS,QAAQ,SAAS;AAChC,MAAI,CAAC,OAAQ,QAAO,GAAG;AACvB,SAAO,QAAQ,IAAI,EAAE,GAAG,QAAQ,WAAW,SAAS,GAAG,EAAE;AAC3D;","names":[]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getWorkflowText,
|
|
7
7
|
objectType,
|
|
8
8
|
registerPrompts
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RMMQVPZN.js";
|
|
10
10
|
import {
|
|
11
11
|
GUIDE_TYPES,
|
|
12
12
|
QUIZ_VARIANTS,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
getGuideUri,
|
|
16
16
|
guideFallbackText,
|
|
17
17
|
registerResources
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-6FVQBVKW.js";
|
|
19
19
|
import {
|
|
20
20
|
ACTIVE_NODE_TYPES,
|
|
21
21
|
CONTACT_FIELDS,
|
|
@@ -39,11 +39,11 @@ import {
|
|
|
39
39
|
resolveFormType,
|
|
40
40
|
structuredResult,
|
|
41
41
|
textResult
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-SAAH4U7O.js";
|
|
43
43
|
import {
|
|
44
44
|
getMcpAuth,
|
|
45
45
|
runWithMcpTool
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-HZMMOSEM.js";
|
|
47
47
|
import {
|
|
48
48
|
__commonJS,
|
|
49
49
|
__export,
|
|
@@ -18259,11 +18259,11 @@ function registerWhoamiTool(server) {
|
|
|
18259
18259
|
"clipform_whoami",
|
|
18260
18260
|
{
|
|
18261
18261
|
title: "Who Am I",
|
|
18262
|
-
description: `Show the current identity: auth mode (api key, session, or anonymous), active workspace, and plan limits.`,
|
|
18262
|
+
description: `Show the current identity: auth mode (api key, oauth, session, or anonymous), active workspace, and plan limits.`,
|
|
18263
18263
|
inputSchema: {},
|
|
18264
18264
|
outputSchema: {
|
|
18265
|
-
auth_mode: external_exports.enum(["api_key", "session", "anonymous"]).describe("How this session is authenticated"),
|
|
18266
|
-
is_authenticated: external_exports.boolean().describe("True for api_key or session auth; false for anonymous"),
|
|
18265
|
+
auth_mode: external_exports.enum(["api_key", "oauth", "session", "anonymous"]).describe("How this session is authenticated"),
|
|
18266
|
+
is_authenticated: external_exports.boolean().describe("True for api_key, oauth, or session auth; false for anonymous"),
|
|
18267
18267
|
workspace: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable().describe("Active workspace, or null when anonymous"),
|
|
18268
18268
|
plan: external_exports.object({
|
|
18269
18269
|
name: external_exports.string(),
|
|
@@ -18874,7 +18874,7 @@ function registerSetNodeLogicTool(server) {
|
|
|
18874
18874
|
"clipform_set_logic",
|
|
18875
18875
|
{
|
|
18876
18876
|
title: "Set Node Logic",
|
|
18877
|
-
description: `Set the next node for one or more nodes, wiring a linear route (A to B to C). Pass multiple nodes in one call instead of separate tool calls. Each node routes to exactly one target node; conditional branching by which option was picked is not yet supported.
|
|
18877
|
+
description: `Set the next node for one or more nodes, wiring a linear route (A to B to C). Pass multiple nodes in one call instead of separate tool calls. Each node routes to exactly one target node; conditional branching by which option was picked is not yet supported here - to route by which choice a respondent picks, point the user to the form's Build tab in the dashboard (the builder URL from clipform_get_form / clipform_create_form).
|
|
18878
18878
|
|
|
18879
18879
|
A call replaces that node's routing entirely - it does not merge with any prior target.
|
|
18880
18880
|
|
|
@@ -18926,6 +18926,12 @@ Example:
|
|
|
18926
18926
|
allLines.push(`Node ${node_id}: logic set (${rulesCount} rules)`);
|
|
18927
18927
|
results.push({ node_id, ok: true, rules_count: rulesCount });
|
|
18928
18928
|
}
|
|
18929
|
+
if (results.some((r) => r.ok)) {
|
|
18930
|
+
allLines.push(
|
|
18931
|
+
`
|
|
18932
|
+
To branch by which option a respondent picks (not yet supported here), open the form's Build tab in the dashboard - use the builder URL from clipform_get_form or clipform_create_form.`
|
|
18933
|
+
);
|
|
18934
|
+
}
|
|
18929
18935
|
return structuredResult(allLines.join("\n"), { results });
|
|
18930
18936
|
}
|
|
18931
18937
|
);
|
|
@@ -20672,4 +20678,4 @@ export {
|
|
|
20672
20678
|
buildInstructions,
|
|
20673
20679
|
createServer
|
|
20674
20680
|
};
|
|
20675
|
-
//# sourceMappingURL=chunk-
|
|
20681
|
+
//# sourceMappingURL=chunk-JCCGDVUH.js.map
|