@clipform/mcp-server 2.1.1 → 2.2.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 +1 -0
- package/dist/{chunk-HG3FYVTR.js → chunk-AHJXNS4R.js} +2 -2
- package/dist/{chunk-TTSO4ZPG.js → chunk-HWGDTUKS.js} +2 -2
- package/dist/{chunk-RQKRLXRN.js → chunk-PI3KAC3M.js} +56 -7
- package/dist/chunk-PI3KAC3M.js.map +1 -0
- package/dist/{chunk-CNEUXDNC.js → chunk-VY52B6DR.js} +6 -4
- package/dist/chunk-VY52B6DR.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/prompts.js +2 -2
- package/dist/resources.js +2 -2
- package/dist/server.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-CNEUXDNC.js.map +0 -1
- package/dist/chunk-RQKRLXRN.js.map +0 -1
- /package/dist/{chunk-HG3FYVTR.js.map → chunk-AHJXNS4R.js.map} +0 -0
- /package/dist/{chunk-TTSO4ZPG.js.map → chunk-HWGDTUKS.js.map} +0 -0
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ Your MCP client lists these automatically on connect (via `tools/list`). Full re
|
|
|
72
72
|
| `clipform_update_node` | Update one or more existing nodes' text, type, config, or options. |
|
|
73
73
|
| `clipform_delete_node` | Delete a node from a form. |
|
|
74
74
|
| `clipform_upload_media_asset` | Put one or more media files into your workspace media library (max 10, uploaded sequentially). |
|
|
75
|
+
| `clipform_complete_media_upload` | Confirm a signed-PUT still image upload finished, after PUTting the bytes to the upload_url returned by clipform_upload_media_asset. |
|
|
75
76
|
| `clipform_attach_node_media` | Attach an existing workspace media asset (from clipform_upload_media_asset) to one or more nodes (max 10). |
|
|
76
77
|
| `clipform_get_node_media` | Get the media attached to a node, including processing status. |
|
|
77
78
|
| `clipform_delete_node_media` | Remove media from a node. |
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
FORM_TYPE_KEYS,
|
|
4
4
|
callApi,
|
|
5
5
|
getSessionContext
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VY52B6DR.js";
|
|
7
7
|
|
|
8
8
|
// src/lib/guides.ts
|
|
9
9
|
var guidesPromise = null;
|
|
@@ -136,4 +136,4 @@ export {
|
|
|
136
136
|
getGuideUri,
|
|
137
137
|
registerResources
|
|
138
138
|
};
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-AHJXNS4R.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
WORKFLOW_TYPES,
|
|
3
3
|
getDiscoveryParams,
|
|
4
4
|
getSessionContextWithAuth
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VY52B6DR.js";
|
|
6
6
|
import {
|
|
7
7
|
__export
|
|
8
8
|
} from "./chunk-HCZI2UJ5.js";
|
|
@@ -4708,4 +4708,4 @@ export {
|
|
|
4708
4708
|
getWorkflowText,
|
|
4709
4709
|
registerPrompts
|
|
4710
4710
|
};
|
|
4711
|
-
//# sourceMappingURL=chunk-
|
|
4711
|
+
//# sourceMappingURL=chunk-HWGDTUKS.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getWorkflowText,
|
|
7
7
|
objectType,
|
|
8
8
|
registerPrompts
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-HWGDTUKS.js";
|
|
10
10
|
import {
|
|
11
11
|
GUIDE_TYPES,
|
|
12
12
|
QUIZ_VARIANTS,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
getGuideUri,
|
|
15
15
|
guideFallbackText,
|
|
16
16
|
registerResources
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-AHJXNS4R.js";
|
|
18
18
|
import {
|
|
19
19
|
ACTIVE_NODE_TYPES,
|
|
20
20
|
BUSINESS,
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
resolveFormType,
|
|
34
34
|
structuredResult,
|
|
35
35
|
textResult
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-VY52B6DR.js";
|
|
37
37
|
import {
|
|
38
38
|
__commonJS,
|
|
39
39
|
__export,
|
|
@@ -17923,7 +17923,7 @@ When a public URL is provided, the media is fetched and stored automatically. Fo
|
|
|
17923
17923
|
resultLines.push(
|
|
17924
17924
|
`Upload URL: ${uploadUrl}`,
|
|
17925
17925
|
`Upload method: ${uploadMethod}`,
|
|
17926
|
-
`
|
|
17926
|
+
uploadMethod === "put" ? `PUT the file's bytes directly to the upload URL, then call clipform_complete_media_upload with media_asset_id ${mediaAssetId} to confirm the upload and mark it ready - it stays invisible in the library until you do.` : `Upload the file directly to the upload URL using TUS resumable upload.`
|
|
17927
17927
|
);
|
|
17928
17928
|
} else {
|
|
17929
17929
|
resultLines.push(`Media stored in the workspace library.`);
|
|
@@ -17945,6 +17945,54 @@ When a public URL is provided, the media is fetched and stored automatically. Fo
|
|
|
17945
17945
|
);
|
|
17946
17946
|
}
|
|
17947
17947
|
|
|
17948
|
+
// src/tools/complete-media-upload.ts
|
|
17949
|
+
function registerCompleteMediaUploadTool(server) {
|
|
17950
|
+
server.registerTool(
|
|
17951
|
+
"clipform_complete_media_upload",
|
|
17952
|
+
{
|
|
17953
|
+
title: "Complete Media Upload",
|
|
17954
|
+
description: `Confirm a signed-PUT still image upload finished, after PUTting the bytes to the upload_url returned by clipform_upload_media_asset. The API verifies the object actually landed in storage before flipping the asset from processing to ready - call this right after the PUT succeeds, or the asset stays invisible in the library. Not needed for video uploads (TUS/Mux settle automatically).`,
|
|
17955
|
+
inputSchema: {
|
|
17956
|
+
media_asset_id: external_exports.string().uuid().describe("The media_asset_id returned by clipform_upload_media_asset for the still image")
|
|
17957
|
+
},
|
|
17958
|
+
outputSchema: {
|
|
17959
|
+
media_asset_id: external_exports.string(),
|
|
17960
|
+
status: external_exports.string().describe("The asset's status after this call - ready on success, or its already-settled status when called again (noop)")
|
|
17961
|
+
},
|
|
17962
|
+
annotations: {
|
|
17963
|
+
readOnlyHint: false,
|
|
17964
|
+
destructiveHint: false,
|
|
17965
|
+
idempotentHint: true,
|
|
17966
|
+
openWorldHint: false
|
|
17967
|
+
}
|
|
17968
|
+
},
|
|
17969
|
+
async ({ media_asset_id }) => {
|
|
17970
|
+
const meResult = await callApi("/me", { method: "GET" });
|
|
17971
|
+
if (!meResult.ok) {
|
|
17972
|
+
return errorResult(`Unable to determine workspace: ${meResult.error}`);
|
|
17973
|
+
}
|
|
17974
|
+
const me = meResult.data;
|
|
17975
|
+
const workspaceId = me.workspace?.id ?? null;
|
|
17976
|
+
if (!workspaceId) {
|
|
17977
|
+
return errorResult(
|
|
17978
|
+
"No workspace available. This usually means authentication is misconfigured - check your API key or OAuth connection."
|
|
17979
|
+
);
|
|
17980
|
+
}
|
|
17981
|
+
const result = await callApi(`/workspaces/${workspaceId}/media/${media_asset_id}/complete`, {
|
|
17982
|
+
method: "POST",
|
|
17983
|
+
body: { uploaded: true }
|
|
17984
|
+
});
|
|
17985
|
+
if (!result.ok) {
|
|
17986
|
+
return errorResult(result.error);
|
|
17987
|
+
}
|
|
17988
|
+
const status = result.data.status ?? "ready";
|
|
17989
|
+
const noop = Boolean(result.data.noop);
|
|
17990
|
+
const text = noop ? `Media asset ${media_asset_id} was already ${status} - no change made.` : `Media asset ${media_asset_id} is now ${status}.`;
|
|
17991
|
+
return structuredResult(text, { media_asset_id, status });
|
|
17992
|
+
}
|
|
17993
|
+
);
|
|
17994
|
+
}
|
|
17995
|
+
|
|
17948
17996
|
// src/tools/attach-node-media.ts
|
|
17949
17997
|
var MEDIA_SUPPORTED_TYPES = Object.entries(NODE_TYPES).filter(([, def]) => def.supports_media).map(([type]) => type);
|
|
17950
17998
|
var AttachMediaItemSchema = external_exports.object({
|
|
@@ -18338,7 +18386,7 @@ var CaptionSchema2 = external_exports.object({
|
|
|
18338
18386
|
});
|
|
18339
18387
|
var TtsItemSchema = external_exports.object({
|
|
18340
18388
|
text: external_exports.string().min(1).max(5e3).describe("Narration text"),
|
|
18341
|
-
voice: external_exports.enum(["ryan", "sonia", "andrew", "ava", "guy"]).optional().default("ryan").describe("Voice: ryan (British male, clear/articulate), sonia (British female, warm/bright), andrew (American male, smooth/neutral), ava (American female, vibrant/friendly), guy (American male, deep/authoritative). Pick
|
|
18389
|
+
voice: external_exports.enum(["ryan", "sonia", "andrew", "ava", "guy"]).optional().default("ryan").describe("Voice: ryan (British male, clear/articulate), sonia (British female, warm/bright), andrew (American male, smooth/neutral), ava (American female, vibrant/friendly), guy (American male, deep/authoritative). Pick ONE voice for the whole form based on its topic and audience, then reuse that same voice on every item and every call - never mix voices within a form unless the user explicitly asks for more than one."),
|
|
18342
18390
|
tone: external_exports.string().max(500).optional().describe("Style instructions for how the voice should sound. E.g. 'Speak like an energetic quiz show host, playful and teasing' or 'Warm and conversational, like chatting with a friend'. Infer from context if not specified by the user.")
|
|
18343
18391
|
});
|
|
18344
18392
|
function registerGenerateTtsTool(server) {
|
|
@@ -18348,7 +18396,7 @@ function registerGenerateTtsTool(server) {
|
|
|
18348
18396
|
title: "Generate Text-to-Speech",
|
|
18349
18397
|
description: `Generate narration audio from text with word-level captions. Use this for quiz question narration, survey introductions, form instructions, or any node that benefits from a human voice. Proactively suggest narration for quizzes and content-rich forms - it significantly improves engagement.
|
|
18350
18398
|
|
|
18351
|
-
Available voices: ryan (British male, clear), sonia (British female, warm), andrew (American male, smooth), ava (American female, vibrant), guy (American male, deep). Pick
|
|
18399
|
+
Available voices: ryan (British male, clear), sonia (British female, warm), andrew (American male, smooth), ava (American female, vibrant), guy (American male, deep). Pick ONE voice that fits the topic - e.g. a London quiz gets ryan or sonia, a US sports quiz gets andrew or guy - and reuse that SAME voice for every item and every call across the whole form. Never mix voices within one form unless the user explicitly asks for multiple voices.
|
|
18352
18400
|
|
|
18353
18401
|
Use the tone parameter to direct HOW the voice speaks. Always set a tone that matches the form's mood - e.g. quizzes: "Energetic and playful, like a quiz show host teasing the audience", surveys: "Professional but warm, encouraging honest answers", personality quizzes: "Curious and reflective". This dramatically improves the narration quality.
|
|
18354
18402
|
|
|
@@ -19889,6 +19937,7 @@ function createServer(options) {
|
|
|
19889
19937
|
registerUpdateNodeTool(server);
|
|
19890
19938
|
registerDeleteNodeTool(server);
|
|
19891
19939
|
registerUploadMediaAssetTool(server);
|
|
19940
|
+
registerCompleteMediaUploadTool(server);
|
|
19892
19941
|
registerAttachNodeMediaTool(server);
|
|
19893
19942
|
registerGetNodeMediaTool(server);
|
|
19894
19943
|
registerDeleteNodeMediaTool(server);
|
|
@@ -19919,4 +19968,4 @@ export {
|
|
|
19919
19968
|
RENDER_TIMING,
|
|
19920
19969
|
createServer
|
|
19921
19970
|
};
|
|
19922
|
-
//# sourceMappingURL=chunk-
|
|
19971
|
+
//# sourceMappingURL=chunk-PI3KAC3M.js.map
|