@clipform/mcp-server 1.10.0 → 1.11.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 +3 -3
- package/dist/{chunk-NC3CXX2N.js → chunk-MV3ZI5ZT.js} +224 -6
- package/dist/chunk-MV3ZI5ZT.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-NC3CXX2N.js.map +0 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Use this for stdio-based MCP clients. Pass your API key to authenticate with you
|
|
|
23
23
|
**Claude Code:**
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
claude mcp add clipform -e CLIPFORM_API_KEY=
|
|
26
|
+
claude mcp add clipform -e CLIPFORM_API_KEY=cf_xxx -- npx -y @clipform/mcp-server
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
**Claude Desktop / Cursor / Windsurf / OpenClaw** - add to your MCP config:
|
|
@@ -35,7 +35,7 @@ claude mcp add clipform -e CLIPFORM_API_KEY=cf_live_xxx -- npx -y @clipform/mcp-
|
|
|
35
35
|
"command": "npx",
|
|
36
36
|
"args": ["-y", "@clipform/mcp-server"],
|
|
37
37
|
"env": {
|
|
38
|
-
"CLIPFORM_API_KEY": "
|
|
38
|
+
"CLIPFORM_API_KEY": "cf_xxx"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -44,7 +44,7 @@ claude mcp add clipform -e CLIPFORM_API_KEY=cf_live_xxx -- npx -y @clipform/mcp-
|
|
|
44
44
|
|
|
45
45
|
Generate an API key in your Clipform dashboard under **Settings > API Keys**.
|
|
46
46
|
|
|
47
|
-
You can also pass the key as a CLI flag: `npx -y @clipform/mcp-server --api-key=
|
|
47
|
+
You can also pass the key as a CLI flag: `npx -y @clipform/mcp-server --api-key=cf_xxx`
|
|
48
48
|
|
|
49
49
|
**Anonymous mode** (no API key): Forms go into a shared workspace with the free-tier 3-node limit. You'll get a claim URL to move forms into your account.
|
|
50
50
|
|
|
@@ -22109,7 +22109,6 @@ var CONTACT_FIELDS = [
|
|
|
22109
22109
|
var CONTACT_FIELDS_MAP = Object.fromEntries(
|
|
22110
22110
|
CONTACT_FIELDS.map((f) => [f.id, f])
|
|
22111
22111
|
);
|
|
22112
|
-
var API_KEY_PREFIX = ENV.isProduction ? "cf_live_" : "cf_test_";
|
|
22113
22112
|
|
|
22114
22113
|
// src/lib/schemas.ts
|
|
22115
22114
|
var ACTIVE_NODE_TYPES = Object.entries(NODE_TYPES).filter(([, def]) => def.is_active && !def.is_system).map(([type]) => type);
|
|
@@ -23233,6 +23232,65 @@ If neither native web search nor this tool is available and the topic is post-cu
|
|
|
23233
23232
|
);
|
|
23234
23233
|
}
|
|
23235
23234
|
|
|
23235
|
+
// src/tools/youtube-transcript.ts
|
|
23236
|
+
function registerYouTubeTranscriptTool(server) {
|
|
23237
|
+
server.registerTool(
|
|
23238
|
+
"clipform_youtube_transcript",
|
|
23239
|
+
{
|
|
23240
|
+
title: "Get YouTube Transcript",
|
|
23241
|
+
description: `Extract the transcript, title, and channel info from a YouTube video.
|
|
23242
|
+
|
|
23243
|
+
Use this as the first step when creating a comprehension quiz about a YouTube video. Returns the full transcript text plus metadata (title, channel, duration). Feed this into your quiz-writing process to create questions that test whether someone actually watched and understood the video.
|
|
23244
|
+
|
|
23245
|
+
WHEN TO USE:
|
|
23246
|
+
- User provides a YouTube URL and wants a quiz, summary, or content based on the video
|
|
23247
|
+
- You need to understand what a YouTube video covers before creating content about it
|
|
23248
|
+
|
|
23249
|
+
DOES NOT WORK FOR:
|
|
23250
|
+
- Private or age-restricted videos
|
|
23251
|
+
- Videos with captions disabled
|
|
23252
|
+
- Non-YouTube URLs`,
|
|
23253
|
+
inputSchema: {
|
|
23254
|
+
url: external_exports.string().url().describe(
|
|
23255
|
+
"YouTube video URL (any format: watch?v=, youtu.be/, shorts/)"
|
|
23256
|
+
),
|
|
23257
|
+
lang: external_exports.string().optional().default("en").describe(
|
|
23258
|
+
"Transcript language code (default: 'en'). Try 'en' first, omit for auto-detect if English unavailable."
|
|
23259
|
+
),
|
|
23260
|
+
max_chars: external_exports.number().optional().default(15e3).describe(
|
|
23261
|
+
"Maximum transcript characters to return (default: 15000). Increase for longer videos where full context matters."
|
|
23262
|
+
)
|
|
23263
|
+
},
|
|
23264
|
+
annotations: {
|
|
23265
|
+
readOnlyHint: true,
|
|
23266
|
+
destructiveHint: false,
|
|
23267
|
+
idempotentHint: true,
|
|
23268
|
+
openWorldHint: true
|
|
23269
|
+
}
|
|
23270
|
+
},
|
|
23271
|
+
async ({ url, lang, max_chars }) => {
|
|
23272
|
+
const result = await callInternalApi("/internal/youtube-transcript", {
|
|
23273
|
+
body: { url, lang, max_chars }
|
|
23274
|
+
});
|
|
23275
|
+
if (!result.ok) return errorResult(result.error);
|
|
23276
|
+
const data = result.data;
|
|
23277
|
+
const meta = data.metadata;
|
|
23278
|
+
const lines = [
|
|
23279
|
+
`## Video: ${meta.title}`,
|
|
23280
|
+
`Channel: ${meta.author}`,
|
|
23281
|
+
`Duration: ~${Math.round(data.durationSeconds / 60)} minutes`,
|
|
23282
|
+
`Language: ${data.language}`,
|
|
23283
|
+
`Transcript length: ${data.transcript.length} characters`,
|
|
23284
|
+
``,
|
|
23285
|
+
`## Transcript`,
|
|
23286
|
+
``,
|
|
23287
|
+
data.transcript
|
|
23288
|
+
];
|
|
23289
|
+
return textResult(lines.join("\n"));
|
|
23290
|
+
}
|
|
23291
|
+
);
|
|
23292
|
+
}
|
|
23293
|
+
|
|
23236
23294
|
// src/tools/generate-tts.ts
|
|
23237
23295
|
var TtsItemSchema = external_exports.object({
|
|
23238
23296
|
text: external_exports.string().min(1).max(5e3).describe("Narration text"),
|
|
@@ -23593,17 +23651,16 @@ function registerRenderCompositionTool(server) {
|
|
|
23593
23651
|
"clipform_render_composition",
|
|
23594
23652
|
{
|
|
23595
23653
|
title: "Render Composition",
|
|
23596
|
-
description: `Render a video composition to MP4
|
|
23654
|
+
description: `Render a video composition to MP4 or PNG.
|
|
23597
23655
|
|
|
23598
23656
|
Output formats:
|
|
23599
|
-
- mp4: Video file (H.264 codec, best for social media)
|
|
23657
|
+
- mp4: Video file (H.264 codec, correct BT.709 colors, best for social media)
|
|
23600
23658
|
- png: Still image (single frame)
|
|
23601
|
-
- gif: Animated GIF (looping)
|
|
23602
23659
|
|
|
23603
23660
|
For narrated quiz slideshows, prefer clipform_generate_slideshow which handles the full workflow (focal point detection, audio sync, storage upload). Use this tool for custom compositions like ScorecardQuiz, ShortFormQuiz, or PresenterDirected.`,
|
|
23604
23661
|
inputSchema: {
|
|
23605
23662
|
compositionId: external_exports.string().describe("The composition ID (e.g. 'ScorecardQuiz', 'ShortFormQuiz', 'PresenterDirected')"),
|
|
23606
|
-
outputFormat: external_exports.enum(["mp4", "png"
|
|
23663
|
+
outputFormat: external_exports.enum(["mp4", "png"]).default("mp4").describe("Output format (default: mp4)"),
|
|
23607
23664
|
inputProps: external_exports.record(external_exports.unknown()).optional().describe("Props object matching the composition's expected schema")
|
|
23608
23665
|
},
|
|
23609
23666
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
|
|
@@ -24334,6 +24391,94 @@ There are NO correct answers. Each option maps to one or more outcome categories
|
|
|
24334
24391
|
};
|
|
24335
24392
|
}
|
|
24336
24393
|
);
|
|
24394
|
+
server.registerPrompt(
|
|
24395
|
+
"create-comprehension-quiz",
|
|
24396
|
+
{
|
|
24397
|
+
title: "Create a YouTube Comprehension Quiz",
|
|
24398
|
+
description: "Build a comprehension quiz from a YouTube video - tests whether the viewer actually watched and understood the content"
|
|
24399
|
+
},
|
|
24400
|
+
async () => {
|
|
24401
|
+
const sessionContext = await getSessionContext();
|
|
24402
|
+
return {
|
|
24403
|
+
messages: [
|
|
24404
|
+
{
|
|
24405
|
+
role: "user",
|
|
24406
|
+
content: {
|
|
24407
|
+
type: "text",
|
|
24408
|
+
text: "I want to create a comprehension quiz based on a YouTube video. What's the best approach?"
|
|
24409
|
+
}
|
|
24410
|
+
},
|
|
24411
|
+
{
|
|
24412
|
+
role: "assistant",
|
|
24413
|
+
content: {
|
|
24414
|
+
type: "text",
|
|
24415
|
+
text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build a comprehension quiz from a YouTube video. Read the quiz guide (clipform://guides/quiz) for general craft, and the comprehension guide (clipform://guides/comprehension-quiz) for video-specific techniques.
|
|
24416
|
+
|
|
24417
|
+
## Comprehension Quiz Workflow
|
|
24418
|
+
|
|
24419
|
+
1. **Extract the transcript** with clipform_youtube_transcript - pass the YouTube URL. Returns transcript, title, channel, and duration.
|
|
24420
|
+
2. **Analyse the content** - identify:
|
|
24421
|
+
- Key claims, facts, or arguments made in the video
|
|
24422
|
+
- Specific details a casual viewer might miss
|
|
24423
|
+
- The video's main thesis or conclusion
|
|
24424
|
+
- Any surprising or counterintuitive points
|
|
24425
|
+
3. **Write comprehension questions** - these test whether someone WATCHED the video, not general knowledge:
|
|
24426
|
+
- "According to the video, what is the main reason...?"
|
|
24427
|
+
- "What example does the video use to illustrate...?"
|
|
24428
|
+
- Include 1-2 inference questions: "Based on the video, why does the presenter believe...?"
|
|
24429
|
+
- Avoid questions answerable without watching (e.g., common knowledge about the topic)
|
|
24430
|
+
4. **Adapt to the audience** - if specified (e.g., "for a 5-year-old"), simplify language, reduce option count, focus on concrete/visual details rather than abstract arguments
|
|
24431
|
+
5. **Create the form** with clipform_create_form:
|
|
24432
|
+
- show_step_counter: true
|
|
24433
|
+
- disable_back_navigation: true
|
|
24434
|
+
6. **Add questions** with clipform_add_node (type: "choice"):
|
|
24435
|
+
- config: { choice: { show_answer_feedback: true } }
|
|
24436
|
+
- randomise_options: true in config
|
|
24437
|
+
- score: 1 on correct option, score: 0 on wrong
|
|
24438
|
+
- 3-4 wrong answers per question - make distractors plausible (things someone might guess without watching)
|
|
24439
|
+
7. **Generate narration** with clipform_generate_tts - reference the video naturally: "If you watched closely, you'll know this one..." Keep each narration 5-10 seconds.
|
|
24440
|
+
8. **Build video** for each question:
|
|
24441
|
+
- clipform_search_media (kind: "image") - 3 images per question
|
|
24442
|
+
- clipform_generate_video - Ken Burns video synced to audio
|
|
24443
|
+
9. **Attach media** with clipform_upload_node_media. Include captions, set show_captions: true.
|
|
24444
|
+
10. **Update end screen** with clipform_update_node:
|
|
24445
|
+
- show_score: true, icon: "trophy"
|
|
24446
|
+
- show_share_button: true
|
|
24447
|
+
- cta_type: "restart", cta_text: "Rewatch and try again?"
|
|
24448
|
+
- score_ranges with messages that reference the video:
|
|
24449
|
+
\`\`\`json
|
|
24450
|
+
{ "min": 0, "max": 2, "title": "Were you even watching?", "message": "Time for a rewatch - this video is worth it." },
|
|
24451
|
+
{ "min": 3, "max": 5, "title": "Casual Viewer", "message": "You caught the highlights but missed some details." },
|
|
24452
|
+
{ "min": 6, "max": 8, "title": "Focused Student", "message": "You were paying attention - impressive." }
|
|
24453
|
+
\`\`\`
|
|
24454
|
+
11. **Publish** with clipform_update_form
|
|
24455
|
+
12. **Tag** - tags: ["quiz", "comprehension", "youtube"] + 2-3 topic words from the video
|
|
24456
|
+
13. **Log** with clipform_log_generation - include the YouTube URL, video title, and channel as sources
|
|
24457
|
+
|
|
24458
|
+
## Question Types for Comprehension
|
|
24459
|
+
|
|
24460
|
+
| Type | Example | Tests |
|
|
24461
|
+
|------|---------|-------|
|
|
24462
|
+
| Detail recall | "What specific number did the presenter mention?" | Active listening |
|
|
24463
|
+
| Sequence | "What was discussed BEFORE the section about...?" | Following the structure |
|
|
24464
|
+
| Inference | "Based on the video, why does the presenter believe...?" | Understanding arguments |
|
|
24465
|
+
| Contrast | "The video compares X and Y. What was the key difference?" | Comprehension depth |
|
|
24466
|
+
| Conclusion | "What was the presenter's final point?" | Watched to the end |
|
|
24467
|
+
|
|
24468
|
+
Wrong answers should sound right to someone who didn't watch but googled the topic. The quiz should be unfair to non-watchers and fair to watchers.
|
|
24469
|
+
|
|
24470
|
+
## Before building, ask
|
|
24471
|
+
|
|
24472
|
+
1. What's the YouTube URL?
|
|
24473
|
+
2. How many questions? (default: 8)
|
|
24474
|
+
3. Who's the audience? (age, knowledge level)
|
|
24475
|
+
4. Media style: text only, still images, or slideshow video with narration?`
|
|
24476
|
+
}
|
|
24477
|
+
}
|
|
24478
|
+
]
|
|
24479
|
+
};
|
|
24480
|
+
}
|
|
24481
|
+
);
|
|
24337
24482
|
server.registerPrompt(
|
|
24338
24483
|
"create-funnel",
|
|
24339
24484
|
{
|
|
@@ -24457,6 +24602,7 @@ Each question is a micro variable-reward event - the same dopamine loop that kee
|
|
|
24457
24602
|
|
|
24458
24603
|
## Question Design
|
|
24459
24604
|
|
|
24605
|
+
- **Randomize correct answer position** - never put the correct answer in the same slot for every question. Vary it across A/B/C/D so there's no pattern to guess.
|
|
24460
24606
|
- **Myth-busters**: "Sushi means raw fish - True or False?" (False - it means seasoned rice)
|
|
24461
24607
|
- **Sounds fake but true**: counterintuitive correct answers make people rewatch
|
|
24462
24608
|
- **Common misconceptions**: "Capital of Australia?" (not Sydney - Canberra)
|
|
@@ -24553,6 +24699,77 @@ Do NOT say "let's see if you get this right" - there is no right answer.
|
|
|
24553
24699
|
|
|
24554
24700
|
${WRITING_PRINCIPLES}
|
|
24555
24701
|
|
|
24702
|
+
${MEDIA_WORKFLOW}`
|
|
24703
|
+
}
|
|
24704
|
+
]
|
|
24705
|
+
})
|
|
24706
|
+
);
|
|
24707
|
+
server.registerResource(
|
|
24708
|
+
"guide-comprehension-quiz",
|
|
24709
|
+
"clipform://guides/comprehension-quiz",
|
|
24710
|
+
{
|
|
24711
|
+
description: "Craft knowledge for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation",
|
|
24712
|
+
mimeType: "text/markdown"
|
|
24713
|
+
},
|
|
24714
|
+
async () => ({
|
|
24715
|
+
contents: [
|
|
24716
|
+
{
|
|
24717
|
+
uri: "clipform://guides/comprehension-quiz",
|
|
24718
|
+
mimeType: "text/markdown",
|
|
24719
|
+
text: `# Comprehension Quiz Guide
|
|
24720
|
+
|
|
24721
|
+
## How it differs from a trivia quiz
|
|
24722
|
+
|
|
24723
|
+
A trivia quiz tests general knowledge. A comprehension quiz tests whether someone watched a specific piece of content. The questions should be **unfair to non-watchers and fair to watchers**.
|
|
24724
|
+
|
|
24725
|
+
| | Trivia Quiz | Comprehension Quiz |
|
|
24726
|
+
|---|---|---|
|
|
24727
|
+
| Source | Research + your knowledge | The video transcript |
|
|
24728
|
+
| Questions | General facts | Specific claims from the video |
|
|
24729
|
+
| Wrong answers | Common misconceptions | Things you'd guess without watching |
|
|
24730
|
+
| Goal | Entertainment + learning | Proof of watching + retention |
|
|
24731
|
+
|
|
24732
|
+
## Extracting questions from transcripts
|
|
24733
|
+
|
|
24734
|
+
Read the transcript looking for:
|
|
24735
|
+
|
|
24736
|
+
1. **Specific numbers or data** - "The presenter says it takes X days to..." (detail recall)
|
|
24737
|
+
2. **Causal claims** - "According to the video, this happens because..." (comprehension)
|
|
24738
|
+
3. **Examples used** - "What example does the presenter use to explain...?" (attention)
|
|
24739
|
+
4. **Sequence of topics** - "What does the presenter discuss right after...?" (structure following)
|
|
24740
|
+
5. **The main argument** - "What is the presenter's main point about...?" (thesis comprehension)
|
|
24741
|
+
6. **Counterintuitive points** - anything the presenter says is surprising or commonly misunderstood
|
|
24742
|
+
|
|
24743
|
+
## Distractor design (wrong answers)
|
|
24744
|
+
|
|
24745
|
+
Make wrong answers plausible to someone who **didn't watch**:
|
|
24746
|
+
|
|
24747
|
+
- Use correct facts from other sources about the same topic (tests whether they watched THIS video)
|
|
24748
|
+
- Include things that sound likely based on the title alone
|
|
24749
|
+
- For number questions, use nearby values that seem reasonable
|
|
24750
|
+
- Never include obviously joke answers - every option should feel possible
|
|
24751
|
+
|
|
24752
|
+
## Audience adaptation
|
|
24753
|
+
|
|
24754
|
+
| Audience | Question style | Language | Count |
|
|
24755
|
+
|----------|---------------|----------|-------|
|
|
24756
|
+
| Young children (5-8) | Concrete details, visual moments | Simple, short sentences | 4-6 |
|
|
24757
|
+
| Older children (9-12) | Details + basic inference | Clear, direct | 6-8 |
|
|
24758
|
+
| Teens (13-17) | Inference + sequence + argument | Natural, conversational | 6-10 |
|
|
24759
|
+
| Adults | Full range including critical analysis | Match the video's register | 6-10 |
|
|
24760
|
+
|
|
24761
|
+
For young children: focus on "What did you SEE?" and "Who did what?" rather than abstract arguments.
|
|
24762
|
+
|
|
24763
|
+
## Narration style
|
|
24764
|
+
|
|
24765
|
+
Reference the video naturally but don't spoil:
|
|
24766
|
+
|
|
24767
|
+
- "If you were paying attention during the bit about..."
|
|
24768
|
+
- "This is one of those details most people miss..."
|
|
24769
|
+
- "The presenter made a really specific claim here..."
|
|
24770
|
+
|
|
24771
|
+
${WRITING_PRINCIPLES}
|
|
24772
|
+
|
|
24556
24773
|
${MEDIA_WORKFLOW}`
|
|
24557
24774
|
}
|
|
24558
24775
|
]
|
|
@@ -24776,6 +24993,7 @@ function createServer() {
|
|
|
24776
24993
|
registerAttachNodeAudioTool(server);
|
|
24777
24994
|
registerLogGenerationTool(server);
|
|
24778
24995
|
registerSearchNewsTool(server);
|
|
24996
|
+
registerYouTubeTranscriptTool(server);
|
|
24779
24997
|
registerGenerateTtsTool(server);
|
|
24780
24998
|
registerGenerateSlideshowTool(server);
|
|
24781
24999
|
registerGenerateVideoTool(server);
|
|
@@ -24796,4 +25014,4 @@ export {
|
|
|
24796
25014
|
setApiKey,
|
|
24797
25015
|
createServer
|
|
24798
25016
|
};
|
|
24799
|
-
//# sourceMappingURL=chunk-
|
|
25017
|
+
//# sourceMappingURL=chunk-MV3ZI5ZT.js.map
|