@clipform/mcp-server 3.0.0 → 3.3.0
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 +2 -2
- package/README.template.md +1 -1
- package/dist/auth-context.d.ts +13 -0
- package/dist/auth-context.js +1 -1
- package/dist/{chunk-KCF7ZVDI.js → chunk-22BV4NSB.js} +2 -2
- package/dist/{chunk-QBPE32AV.js → chunk-4XCXDH3I.js} +359 -83
- package/dist/chunk-4XCXDH3I.js.map +1 -0
- package/dist/{chunk-HZMMOSEM.js → chunk-A5CFGL27.js} +1 -1
- package/dist/chunk-A5CFGL27.js.map +1 -0
- package/dist/{chunk-EXV5M7YV.js → chunk-ELK26KWM.js} +2 -2
- package/dist/{chunk-KNOCYZHG.js → chunk-SEZ37YSH.js} +105 -22
- package/dist/chunk-SEZ37YSH.js.map +1 -0
- 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 +3 -2
- package/dist/chunk-HZMMOSEM.js.map +0 -1
- package/dist/chunk-KNOCYZHG.js.map +0 -1
- package/dist/chunk-QBPE32AV.js.map +0 -1
- /package/dist/{chunk-KCF7ZVDI.js.map → chunk-22BV4NSB.js.map} +0 -0
- /package/dist/{chunk-EXV5M7YV.js.map → chunk-ELK26KWM.js.map} +0 -0
|
@@ -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 // #3822: set ONLY on the OAuth branch of apps/api's mcp/handler.ts. Lets a\n // single tool call target another workspace the connected user belongs to\n // (per-call, never per-request - see the #3330 note in the package\n // CLAUDE.md). The host re-checks membership on every call and returns that\n // workspace's own bot key, or null to mean \"act in the default workspace\n // unchanged\" (target is the default, or a form_id the user can't reach -\n // the API then answers exactly as it did before targeting existed). Anon + stdio contexts never carry it, so they\n // stay pinned to one workspace.\n resolveWorkspace?: (target: {\n workspace_id?: string;\n form_id?: string;\n }) => Promise<{ workspace_id: string; workspace_name: string; api_key: string } | null>;\n // #3822: the workspaces the connected user may target (same set\n // resolveWorkspace accepts). OAuth lane only.\n listWorkspaces?: () => Promise<{ id: string; name: string }[]>;\n // #3822: the workspace picked at authorize time - what a call with no\n // `workspace_id` acts in. OAuth lane only (workspace_id above is swapped\n // per call when a target is resolved, this never is).\n default_workspace_id?: 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;AAyE3B,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":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
FULL_CAPS,
|
|
6
6
|
callApi,
|
|
7
7
|
getSessionContext
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SEZ37YSH.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-ELK26KWM.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
MCP_AUTH_VIA_HEADER,
|
|
4
4
|
MCP_MINT_PROOF_HEADER,
|
|
5
5
|
getMcpAuth
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-A5CFGL27.js";
|
|
7
7
|
import {
|
|
8
8
|
isAuthFault,
|
|
9
9
|
isServerFault,
|
|
@@ -37,9 +37,10 @@ var FEATURES = {
|
|
|
37
37
|
consent_documents: {
|
|
38
38
|
name: "Agreement documents",
|
|
39
39
|
description: "Attach a PDF agreement to a consent item, read inline in the viewer with scroll-to-accept",
|
|
40
|
-
enabled:
|
|
41
|
-
status: "
|
|
42
|
-
category: "builder"
|
|
40
|
+
enabled: true,
|
|
41
|
+
status: "live",
|
|
42
|
+
category: "builder",
|
|
43
|
+
wentLiveAt: "2026-10-02"
|
|
43
44
|
},
|
|
44
45
|
node_logic: {
|
|
45
46
|
name: "Node routing logic",
|
|
@@ -156,8 +157,8 @@ var FEATURES = {
|
|
|
156
157
|
// Widened (#4338): the checkbox items are typed 'consent' (required,
|
|
157
158
|
// blocks submission until checked) or 'opt_in' (optional) - see
|
|
158
159
|
// CONSENT_TYPES in node-types.js and the viewer's Contact.tsx. Both are
|
|
159
|
-
// plain text checkboxes available to every creator with no gate
|
|
160
|
-
//
|
|
160
|
+
// plain text checkboxes available to every creator with no gate. Attaching
|
|
161
|
+
// a PDF agreement document is the separate consent_documents feature (live).
|
|
161
162
|
description: "Structured fields (name, email, phone, company) with consent and opt-in checkboxes",
|
|
162
163
|
enabled: true,
|
|
163
164
|
status: "live",
|
|
@@ -794,6 +795,7 @@ var NODE_TYPES = {
|
|
|
794
795
|
// Never appears in a completed submission's answers (system node, no
|
|
795
796
|
// output_schema) - false is a no-op default, set for guard-test coverage.
|
|
796
797
|
notify_inline: false,
|
|
798
|
+
owner_scoped_config_keys: [],
|
|
797
799
|
default_config: null,
|
|
798
800
|
config_schema: null,
|
|
799
801
|
response_schema: null,
|
|
@@ -820,6 +822,7 @@ var NODE_TYPES = {
|
|
|
820
822
|
show_in_results: true,
|
|
821
823
|
// Short selected-option label - safe to render inline in a notification (#4154).
|
|
822
824
|
notify_inline: true,
|
|
825
|
+
owner_scoped_config_keys: [],
|
|
823
826
|
default_config: {
|
|
824
827
|
selection_mode: "single",
|
|
825
828
|
choice: { enable_branching: false, record_scores: false },
|
|
@@ -931,6 +934,7 @@ var NODE_TYPES = {
|
|
|
931
934
|
// still swaps a recorded audio/video answer for a typed placeholder
|
|
932
935
|
// based on the answer's own media type, not this flag.
|
|
933
936
|
notify_inline: true,
|
|
937
|
+
owner_scoped_config_keys: [],
|
|
934
938
|
default_config: {
|
|
935
939
|
formats: [
|
|
936
940
|
{ order: 0, format: "text" },
|
|
@@ -1070,6 +1074,7 @@ var NODE_TYPES = {
|
|
|
1070
1074
|
show_in_results: true,
|
|
1071
1075
|
// A bare numeric value - short enough to render inline (#4154).
|
|
1072
1076
|
notify_inline: true,
|
|
1077
|
+
owner_scoped_config_keys: [],
|
|
1073
1078
|
default_config: null,
|
|
1074
1079
|
config_schema: {
|
|
1075
1080
|
type: "object",
|
|
@@ -1107,6 +1112,13 @@ var NODE_TYPES = {
|
|
|
1107
1112
|
// Structured provider data (calendly/google_meet), not a flat value -
|
|
1108
1113
|
// a notification renders a typed placeholder instead (#4154).
|
|
1109
1114
|
notify_inline: false,
|
|
1115
|
+
// Object granularity, not a dotted path (#4618): every property under
|
|
1116
|
+
// these provider objects (scheduling_url, event_type_uri, calendar_id) is
|
|
1117
|
+
// the source workspace's own calendar, so save_form strips the whole
|
|
1118
|
+
// object on cross-workspace copy. google_meet is included even though it
|
|
1119
|
+
// is absent from the publish gate below (pre-existing drift, not widened
|
|
1120
|
+
// here) because calendar_id is owner-scoped regardless.
|
|
1121
|
+
owner_scoped_config_keys: ["calendly", "calcom", "google_meet"],
|
|
1110
1122
|
default_config: null,
|
|
1111
1123
|
config_schema: {
|
|
1112
1124
|
type: "object",
|
|
@@ -1188,6 +1200,7 @@ var NODE_TYPES = {
|
|
|
1188
1200
|
// Key contact fields (first name, email) are the whole point of a
|
|
1189
1201
|
// notification for this node type - always inline (#4154).
|
|
1190
1202
|
notify_inline: true,
|
|
1203
|
+
owner_scoped_config_keys: [],
|
|
1191
1204
|
default_config: {
|
|
1192
1205
|
fields: [
|
|
1193
1206
|
{ id: "first_name", type: "first_name", label: "First Name", enabled: true, required: true },
|
|
@@ -1282,7 +1295,17 @@ var NODE_TYPES = {
|
|
|
1282
1295
|
// document version they saw, and when they accepted.
|
|
1283
1296
|
reached_end: { type: "boolean" },
|
|
1284
1297
|
document_version: { type: "string" },
|
|
1285
|
-
accepted_at: { type: "string" }
|
|
1298
|
+
accepted_at: { type: "string" },
|
|
1299
|
+
// Server-stamped on write (#4552) when the node's current document
|
|
1300
|
+
// matches document_version; any client-supplied value is discarded.
|
|
1301
|
+
document: {
|
|
1302
|
+
type: "object",
|
|
1303
|
+
properties: {
|
|
1304
|
+
storage_path: { type: "string" },
|
|
1305
|
+
url: { type: "string" },
|
|
1306
|
+
filename: { type: "string" }
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1286
1309
|
}
|
|
1287
1310
|
},
|
|
1288
1311
|
description: "Consent checkbox entries"
|
|
@@ -1321,7 +1344,15 @@ var NODE_TYPES = {
|
|
|
1321
1344
|
// Scrollwrap audit trail (#2760), emitted only for document-gated items.
|
|
1322
1345
|
reached_end: { type: "boolean" },
|
|
1323
1346
|
document_version: { type: "string" },
|
|
1324
|
-
accepted_at: { type: "string" }
|
|
1347
|
+
accepted_at: { type: "string" },
|
|
1348
|
+
// The exact agreement file accepted (#4552). storage_path is not emitted.
|
|
1349
|
+
document: {
|
|
1350
|
+
type: "object",
|
|
1351
|
+
properties: {
|
|
1352
|
+
url: { type: "string" },
|
|
1353
|
+
filename: { type: "string" }
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1325
1356
|
}
|
|
1326
1357
|
}
|
|
1327
1358
|
}
|
|
@@ -1346,6 +1377,7 @@ var NODE_TYPES = {
|
|
|
1346
1377
|
show_in_results: true,
|
|
1347
1378
|
// Files, not a flat value - a notification renders a typed placeholder (#4154).
|
|
1348
1379
|
notify_inline: false,
|
|
1380
|
+
owner_scoped_config_keys: [],
|
|
1349
1381
|
default_config: null,
|
|
1350
1382
|
config_schema: {
|
|
1351
1383
|
type: "object",
|
|
@@ -1437,6 +1469,7 @@ var NODE_TYPES = {
|
|
|
1437
1469
|
show_in_results: true,
|
|
1438
1470
|
// An image, not a flat value - a notification renders a typed placeholder (#4154).
|
|
1439
1471
|
notify_inline: false,
|
|
1472
|
+
owner_scoped_config_keys: [],
|
|
1440
1473
|
default_config: {
|
|
1441
1474
|
paper_color: "#FAF9F6",
|
|
1442
1475
|
stroke_colors: ["#1F2937", "#EF4444", "#3B82F6", "#22C55E", "#FACC15"],
|
|
@@ -1610,6 +1643,7 @@ var NODE_TYPES = {
|
|
|
1610
1643
|
// A captured photo/video, not a flat value - a notification renders a
|
|
1611
1644
|
// typed placeholder (#4154).
|
|
1612
1645
|
notify_inline: false,
|
|
1646
|
+
owner_scoped_config_keys: [],
|
|
1613
1647
|
default_config: null,
|
|
1614
1648
|
config_schema: {
|
|
1615
1649
|
type: "object",
|
|
@@ -1721,6 +1755,7 @@ var NODE_TYPES = {
|
|
|
1721
1755
|
// notification, same as the other control nodes (redirect, link_list,
|
|
1722
1756
|
// end_screen). Required by the #4154 notify_inline invariant.
|
|
1723
1757
|
notify_inline: false,
|
|
1758
|
+
owner_scoped_config_keys: [],
|
|
1724
1759
|
default_config: {
|
|
1725
1760
|
options: [
|
|
1726
1761
|
{ content: "Branch 1" },
|
|
@@ -1747,13 +1782,14 @@ var NODE_TYPES = {
|
|
|
1747
1782
|
supports_media: false,
|
|
1748
1783
|
is_system: false,
|
|
1749
1784
|
show_in_results: true,
|
|
1750
|
-
// Config keys that
|
|
1751
|
-
// via workspace_integrations)
|
|
1752
|
-
//
|
|
1753
|
-
//
|
|
1754
|
-
//
|
|
1755
|
-
//
|
|
1756
|
-
|
|
1785
|
+
// Config keys that are owner-scoped to the authoring workspace - a connected
|
|
1786
|
+
// account (Stripe/etc via workspace_integrations), the owner's own uploaded
|
|
1787
|
+
// files, or a calendar link - and so must NOT survive a cross-workspace copy
|
|
1788
|
+
// (#4619/#4617/#4618/#4620 generalised this from the payment-only
|
|
1789
|
+
// connection_config_keys). The SoT for save_form's strip. The publish gate's
|
|
1790
|
+
// own showcase waiver (graph-validation.js) still names workspace_integration_id
|
|
1791
|
+
// directly since it's the only per-type check today.
|
|
1792
|
+
owner_scoped_config_keys: ["workspace_integration_id"],
|
|
1757
1793
|
// A payment confirmation line is the whole point of a notification for
|
|
1758
1794
|
// this node type - always inline (#4154).
|
|
1759
1795
|
notify_inline: true,
|
|
@@ -1903,6 +1939,7 @@ var NODE_TYPES = {
|
|
|
1903
1939
|
show_in_results: true,
|
|
1904
1940
|
// Short selected-option label - safe to render inline (#4154).
|
|
1905
1941
|
notify_inline: true,
|
|
1942
|
+
owner_scoped_config_keys: [],
|
|
1906
1943
|
default_config: {
|
|
1907
1944
|
choice: { enable_branching: false },
|
|
1908
1945
|
options: [
|
|
@@ -1967,6 +2004,7 @@ var NODE_TYPES = {
|
|
|
1967
2004
|
show_in_results: false,
|
|
1968
2005
|
// Short selected-option label - safe to render inline (#4154).
|
|
1969
2006
|
notify_inline: true,
|
|
2007
|
+
owner_scoped_config_keys: [],
|
|
1970
2008
|
default_config: { options: [{ content: "Continue" }] },
|
|
1971
2009
|
config_schema: {
|
|
1972
2010
|
type: "object",
|
|
@@ -2008,6 +2046,7 @@ var NODE_TYPES = {
|
|
|
2008
2046
|
// Terminal node - never appears in a completed submission's answers
|
|
2009
2047
|
// (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
|
|
2010
2048
|
notify_inline: false,
|
|
2049
|
+
owner_scoped_config_keys: [],
|
|
2011
2050
|
default_config: { url: "", auto_redirect: true },
|
|
2012
2051
|
config_schema: {
|
|
2013
2052
|
type: "object",
|
|
@@ -2041,6 +2080,7 @@ var NODE_TYPES = {
|
|
|
2041
2080
|
// Terminal node - never appears in a completed submission's answers
|
|
2042
2081
|
// (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
|
|
2043
2082
|
notify_inline: false,
|
|
2083
|
+
owner_scoped_config_keys: [],
|
|
2044
2084
|
default_config: { links: [{ id: "default", url: "", title: "", description: "", order: 0 }], auto_redirect: false },
|
|
2045
2085
|
config_schema: {
|
|
2046
2086
|
type: "object",
|
|
@@ -2088,6 +2128,10 @@ var NODE_TYPES = {
|
|
|
2088
2128
|
show_in_results: true,
|
|
2089
2129
|
// Files, not a flat value - a notification renders a typed placeholder (#4154).
|
|
2090
2130
|
notify_inline: false,
|
|
2131
|
+
// The owner's own uploaded files (#4617) - stripped on cross-workspace
|
|
2132
|
+
// copy so a forked node can't keep serving the source workspace's files;
|
|
2133
|
+
// the publish gate's "No files uploaded" check then forces a fresh upload.
|
|
2134
|
+
owner_scoped_config_keys: ["files"],
|
|
2091
2135
|
default_config: null,
|
|
2092
2136
|
config_schema: {
|
|
2093
2137
|
type: "object",
|
|
@@ -2170,6 +2214,7 @@ var NODE_TYPES = {
|
|
|
2170
2214
|
show_in_results: false,
|
|
2171
2215
|
// No response_schema - never carries a flat answer value; false is a no-op default.
|
|
2172
2216
|
notify_inline: false,
|
|
2217
|
+
owner_scoped_config_keys: [],
|
|
2173
2218
|
default_config: { provider: "shopify", cta_mode: "checkout", source_mode: "manual" },
|
|
2174
2219
|
config_schema: {
|
|
2175
2220
|
type: "object",
|
|
@@ -2241,6 +2286,7 @@ var NODE_TYPES = {
|
|
|
2241
2286
|
// Terminal node - never appears in a completed submission's answers
|
|
2242
2287
|
// (filtered by NON_COUNTABLE_FILTER); false is a no-op default.
|
|
2243
2288
|
notify_inline: false,
|
|
2289
|
+
owner_scoped_config_keys: [],
|
|
2244
2290
|
default_config: {
|
|
2245
2291
|
title: "Thank you!",
|
|
2246
2292
|
message: "Your response has been submitted."
|
|
@@ -2303,8 +2349,8 @@ for (const [type, def] of Object.entries(NODE_TYPES)) {
|
|
|
2303
2349
|
var NODE_TYPES_LIST = Object.entries(NODE_TYPES).map(([type, def]) => ({ type, ...def })).sort((a, b) => a.sort_order - b.sort_order);
|
|
2304
2350
|
var ACTIVE_NODE_TYPES = Object.entries(NODE_TYPES).filter(([, def]) => def.is_active && !def.is_system).map(([type]) => type);
|
|
2305
2351
|
var NODE_TYPE_KEYS = Object.keys(NODE_TYPES);
|
|
2306
|
-
var
|
|
2307
|
-
Object.entries(NODE_TYPES).filter(([, def]) => Array.isArray(def.
|
|
2352
|
+
var OWNER_SCOPED_CONFIG_KEYS = Object.fromEntries(
|
|
2353
|
+
Object.entries(NODE_TYPES).filter(([, def]) => Array.isArray(def.owner_scoped_config_keys) && def.owner_scoped_config_keys.length > 0).map(([type, def]) => [type, def.owner_scoped_config_keys])
|
|
2308
2354
|
);
|
|
2309
2355
|
var RESPONSE_SCHEMAS = Object.fromEntries(
|
|
2310
2356
|
Object.entries(NODE_TYPES).map(([k, v]) => [k, v.response_schema])
|
|
@@ -2593,7 +2639,6 @@ var HELP_TOPICS = {
|
|
|
2593
2639
|
emailShare: { path: "/help/sharing", anchor: "share-by-email" },
|
|
2594
2640
|
publicResults: { path: "/help/public-results", anchor: null },
|
|
2595
2641
|
trash: { path: "/help/managing-forms", anchor: "trash" },
|
|
2596
|
-
agreementVersions: { path: "/help/responses", anchor: "agreement-versions" },
|
|
2597
2642
|
customDomains: { path: "/help/domains", anchor: null },
|
|
2598
2643
|
customPath: { path: "/help/links", anchor: "custom-path-on-your-domain" },
|
|
2599
2644
|
// Per-node-type deep-links into help/node-types.mdx (#3963). Keyed
|
|
@@ -2750,6 +2795,7 @@ var BUSINESS = {
|
|
|
2750
2795
|
};
|
|
2751
2796
|
var MEDIA_DIRECT_MAX_BYTES = 20 * 1024 * 1024;
|
|
2752
2797
|
var MEDIA_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
2798
|
+
var MEDIA_DOCUMENT_MAX_BYTES = 20 * 1024 * 1024;
|
|
2753
2799
|
var SUPABASE_STORAGE_MAX_BYTES = 200 * 1024 * 1024;
|
|
2754
2800
|
var VIDEO_COMPRESS_FLOOR_BYTES = 1 * 1024 * 1024;
|
|
2755
2801
|
var HELP_LINKS = buildHelpLinks(BUSINESS.urls.docs);
|
|
@@ -3010,6 +3056,19 @@ var MCP_TOOL_TOOLSETS = {
|
|
|
3010
3056
|
clipform_list_assets: "media",
|
|
3011
3057
|
clipform_list_video_templates: "media"
|
|
3012
3058
|
};
|
|
3059
|
+
var MCP_TOOL_SECURITY_SCHEMES = Object.freeze([
|
|
3060
|
+
Object.freeze({ type: "noauth" }),
|
|
3061
|
+
Object.freeze({ type: "oauth2", scopes: ["mcp"] })
|
|
3062
|
+
]);
|
|
3063
|
+
var MCP_TOOL_SECURITY = Object.freeze(
|
|
3064
|
+
Object.fromEntries(
|
|
3065
|
+
Object.keys(MCP_TOOL_TOOLSETS).map((name) => [name, MCP_TOOL_SECURITY_SCHEMES])
|
|
3066
|
+
)
|
|
3067
|
+
);
|
|
3068
|
+
var MCP_ANON_PUBLISH_GATE = Object.freeze({
|
|
3069
|
+
tool: "clipform_update_form",
|
|
3070
|
+
argument: "is_live"
|
|
3071
|
+
});
|
|
3013
3072
|
|
|
3014
3073
|
// src/lib/caps.ts
|
|
3015
3074
|
var FULL_CAPS = Object.freeze({ media: true, research: true });
|
|
@@ -3117,10 +3176,14 @@ async function callApi(path, options = {}) {
|
|
|
3117
3176
|
api_path: `${prefix}${path}`
|
|
3118
3177
|
});
|
|
3119
3178
|
}
|
|
3179
|
+
const details = data.details;
|
|
3180
|
+
const reason = details && typeof details.reason === "string" ? details.reason : void 0;
|
|
3120
3181
|
return {
|
|
3121
3182
|
ok: false,
|
|
3122
3183
|
status: response.status,
|
|
3123
|
-
error: errorMsg
|
|
3184
|
+
error: errorMsg,
|
|
3185
|
+
code: errorCode,
|
|
3186
|
+
reason
|
|
3124
3187
|
};
|
|
3125
3188
|
}
|
|
3126
3189
|
return { ok: true, data };
|
|
@@ -3139,12 +3202,28 @@ function recoveryHint(status, path) {
|
|
|
3139
3202
|
}
|
|
3140
3203
|
return void 0;
|
|
3141
3204
|
}
|
|
3142
|
-
function errorResult(message) {
|
|
3205
|
+
function errorResult(message, meta) {
|
|
3143
3206
|
return {
|
|
3144
3207
|
content: [{ type: "text", text: message }],
|
|
3145
|
-
isError: true
|
|
3208
|
+
isError: true,
|
|
3209
|
+
...meta ? { _meta: meta } : {}
|
|
3146
3210
|
};
|
|
3147
3211
|
}
|
|
3212
|
+
var PROTECTED_RESOURCE_METADATA_URL = `${BUSINESS.urls.mcp}/.well-known/oauth-protected-resource`;
|
|
3213
|
+
function escapeChallengeValue(value) {
|
|
3214
|
+
return value.replace(/[\r\n]/g, "").replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
3215
|
+
}
|
|
3216
|
+
function isAnonymousAccountRequired(result) {
|
|
3217
|
+
return result.status === 403 && result.code === "FORBIDDEN" && result.reason === "anonymous_not_allowed";
|
|
3218
|
+
}
|
|
3219
|
+
function authChallengeMeta(errorCode, description) {
|
|
3220
|
+
const challenge = [
|
|
3221
|
+
`Bearer error="${escapeChallengeValue(errorCode)}"`,
|
|
3222
|
+
`error_description="${escapeChallengeValue(description)}"`,
|
|
3223
|
+
`resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}"`
|
|
3224
|
+
].join(", ");
|
|
3225
|
+
return { "mcp/www_authenticate": [challenge] };
|
|
3226
|
+
}
|
|
3148
3227
|
function textResult(text) {
|
|
3149
3228
|
return {
|
|
3150
3229
|
content: [{ type: "text", text }]
|
|
@@ -3226,13 +3305,17 @@ export {
|
|
|
3226
3305
|
exposedCompositionIds,
|
|
3227
3306
|
MCP_TOOL_TIERS,
|
|
3228
3307
|
MCP_TOOL_TOOLSETS,
|
|
3308
|
+
MCP_TOOL_SECURITY,
|
|
3309
|
+
MCP_ANON_PUBLISH_GATE,
|
|
3229
3310
|
FULL_CAPS,
|
|
3230
3311
|
capsFromToolsets,
|
|
3231
3312
|
callApi,
|
|
3232
3313
|
errorResult,
|
|
3314
|
+
isAnonymousAccountRequired,
|
|
3315
|
+
authChallengeMeta,
|
|
3233
3316
|
textResult,
|
|
3234
3317
|
structuredResult,
|
|
3235
3318
|
getSessionContextWithAuth,
|
|
3236
3319
|
getSessionContext
|
|
3237
3320
|
};
|
|
3238
|
-
//# sourceMappingURL=chunk-
|
|
3321
|
+
//# sourceMappingURL=chunk-SEZ37YSH.js.map
|