@clipform/mcp-server 1.5.1 → 1.8.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.
Files changed (108) hide show
  1. package/README.md +51 -26
  2. package/dist/__tests__/api-parity.test.js +31 -22
  3. package/dist/__tests__/api-parity.test.js.map +1 -1
  4. package/dist/index.js +9 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/api-client.d.ts +3 -1
  7. package/dist/lib/api-client.js +31 -5
  8. package/dist/lib/api-client.js.map +1 -1
  9. package/dist/lib/auth-context.d.ts +17 -0
  10. package/dist/lib/auth-context.js +9 -0
  11. package/dist/lib/auth-context.js.map +1 -0
  12. package/dist/lib/format-form.d.ts +2 -0
  13. package/dist/lib/format-form.js +32 -0
  14. package/dist/lib/format-form.js.map +1 -0
  15. package/dist/lib/render-jobs.d.ts +13 -0
  16. package/dist/lib/render-jobs.js +38 -0
  17. package/dist/lib/render-jobs.js.map +1 -0
  18. package/dist/lib/schemas.d.ts +4 -4
  19. package/dist/lib/schemas.js +11 -11
  20. package/dist/lib/schemas.js.map +1 -1
  21. package/dist/lib/session-context.d.ts +1 -0
  22. package/dist/lib/session-context.js +38 -0
  23. package/dist/lib/session-context.js.map +1 -0
  24. package/dist/prompts.js +262 -125
  25. package/dist/prompts.js.map +1 -1
  26. package/dist/resources.d.ts +2 -0
  27. package/dist/resources.js +336 -0
  28. package/dist/resources.js.map +1 -0
  29. package/dist/server.js +29 -23
  30. package/dist/server.js.map +1 -1
  31. package/dist/tools/add-node.d.ts +2 -0
  32. package/dist/tools/add-node.js +50 -0
  33. package/dist/tools/add-node.js.map +1 -0
  34. package/dist/tools/attach-node-audio.d.ts +2 -0
  35. package/dist/tools/attach-node-audio.js +37 -0
  36. package/dist/tools/attach-node-audio.js.map +1 -0
  37. package/dist/tools/{add-question.d.ts → check-render.d.ts} +1 -1
  38. package/dist/tools/check-render.js +47 -0
  39. package/dist/tools/check-render.js.map +1 -0
  40. package/dist/tools/create-form.js +90 -19
  41. package/dist/tools/create-form.js.map +1 -1
  42. package/dist/tools/delete-form.js +2 -2
  43. package/dist/tools/delete-form.js.map +1 -1
  44. package/dist/tools/delete-node-media.d.ts +2 -0
  45. package/dist/tools/delete-node-media.js +29 -0
  46. package/dist/tools/delete-node-media.js.map +1 -0
  47. package/dist/tools/delete-node.d.ts +2 -0
  48. package/dist/tools/delete-node.js +32 -0
  49. package/dist/tools/delete-node.js.map +1 -0
  50. package/dist/tools/generate-slideshow.js +129 -26
  51. package/dist/tools/generate-slideshow.js.map +1 -1
  52. package/dist/tools/generate-tts.js +56 -31
  53. package/dist/tools/generate-tts.js.map +1 -1
  54. package/dist/tools/generate-video.d.ts +2 -0
  55. package/dist/tools/generate-video.js +119 -0
  56. package/dist/tools/generate-video.js.map +1 -0
  57. package/dist/tools/get-form.js +5 -26
  58. package/dist/tools/get-form.js.map +1 -1
  59. package/dist/tools/get-node-media.d.ts +2 -0
  60. package/dist/tools/{get-question-media.js → get-node-media.js} +11 -11
  61. package/dist/tools/get-node-media.js.map +1 -0
  62. package/dist/tools/list-assets.js +1 -1
  63. package/dist/tools/list-assets.js.map +1 -1
  64. package/dist/tools/list-compositions.js +3 -3
  65. package/dist/tools/list-compositions.js.map +1 -1
  66. package/dist/tools/log-generation.js +3 -3
  67. package/dist/tools/log-generation.js.map +1 -1
  68. package/dist/tools/render-composition.js +22 -15
  69. package/dist/tools/render-composition.js.map +1 -1
  70. package/dist/tools/search-media.js +2 -2
  71. package/dist/tools/search-media.js.map +1 -1
  72. package/dist/tools/search-music.js +1 -1
  73. package/dist/tools/search-music.js.map +1 -1
  74. package/dist/tools/search-news.js +1 -1
  75. package/dist/tools/search-news.js.map +1 -1
  76. package/dist/tools/set-node-logic.d.ts +2 -0
  77. package/dist/tools/set-node-logic.js +56 -0
  78. package/dist/tools/set-node-logic.js.map +1 -0
  79. package/dist/tools/update-form.js +43 -4
  80. package/dist/tools/update-form.js.map +1 -1
  81. package/dist/tools/update-node.d.ts +2 -0
  82. package/dist/tools/{update-question.js → update-node.js} +16 -13
  83. package/dist/tools/update-node.js.map +1 -0
  84. package/dist/tools/upload-node-media.d.ts +2 -0
  85. package/dist/tools/upload-node-media.js +109 -0
  86. package/dist/tools/upload-node-media.js.map +1 -0
  87. package/package.json +3 -2
  88. package/dist/tools/add-question.js +0 -47
  89. package/dist/tools/add-question.js.map +0 -1
  90. package/dist/tools/attach-question-audio.d.ts +0 -2
  91. package/dist/tools/attach-question-audio.js +0 -37
  92. package/dist/tools/attach-question-audio.js.map +0 -1
  93. package/dist/tools/delete-question-media.d.ts +0 -2
  94. package/dist/tools/delete-question-media.js +0 -29
  95. package/dist/tools/delete-question-media.js.map +0 -1
  96. package/dist/tools/delete-question.d.ts +0 -2
  97. package/dist/tools/delete-question.js +0 -29
  98. package/dist/tools/delete-question.js.map +0 -1
  99. package/dist/tools/get-question-media.d.ts +0 -2
  100. package/dist/tools/get-question-media.js.map +0 -1
  101. package/dist/tools/set-question-logic.d.ts +0 -2
  102. package/dist/tools/set-question-logic.js +0 -54
  103. package/dist/tools/set-question-logic.js.map +0 -1
  104. package/dist/tools/update-question.d.ts +0 -2
  105. package/dist/tools/update-question.js.map +0 -1
  106. package/dist/tools/upload-question-media.d.ts +0 -2
  107. package/dist/tools/upload-question-media.js +0 -69
  108. package/dist/tools/upload-question-media.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { BUSINESS } from "@vid-master/config";
2
+ import { callApi } from "./api-client.js";
3
+ export async function getSessionContext() {
4
+ const result = await callApi("/me", { method: "GET" });
5
+ if (!result.ok)
6
+ return "";
7
+ const me = result.data;
8
+ const plan = me.plan;
9
+ const lines = [];
10
+ lines.push("## Your Session");
11
+ if (me.auth_mode === "oauth") {
12
+ lines.push(`Auth: OAuth (connected)`);
13
+ lines.push(`Workspace: ${me.workspace?.name ?? "Unknown"} (${me.workspace?.id ?? "?"})`);
14
+ lines.push(`User: ${me.user_id ?? "?"}`);
15
+ lines.push(`Company: ${me.company_id ?? "none"}`);
16
+ }
17
+ else {
18
+ lines.push("Auth: anonymous (not connected to a Clipform account)");
19
+ if (me.workspace) {
20
+ lines.push(`Workspace: ${me.workspace.name} (${me.workspace.id})`);
21
+ }
22
+ }
23
+ lines.push(`Plan: ${plan.name} (tier ${plan.tier})`);
24
+ if (plan.node_limit !== null) {
25
+ lines.push(`Question limit: ${plan.node_limit} per form`);
26
+ }
27
+ else {
28
+ lines.push("Questions: unlimited");
29
+ }
30
+ if (plan.custom_theme === false) {
31
+ lines.push("Custom themes: not available on this plan");
32
+ }
33
+ if (me.auth_mode !== "oauth") {
34
+ lines.push(`\nTo unlock your full plan: connect your Clipform account in Settings > Connectors > ${BUSINESS.urls.mcp}`);
35
+ }
36
+ return lines.join("\n");
37
+ }
38
+ //# sourceMappingURL=session-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-context.js","sourceRoot":"","sources":["../../src/lib/session-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IAE1B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAW,CAAC;IAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;IACrB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,SAAS,EAAE,IAAI,IAAI,SAAS,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACpE,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IACrD,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,UAAU,WAAW,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,IAAI,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,EAAE,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,wFAAwF,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1H,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
package/dist/prompts.js CHANGED
@@ -1,135 +1,272 @@
1
+ import { getSessionContext } from "./lib/session-context.js";
1
2
  export function registerPrompts(server) {
2
3
  server.registerPrompt("create-quiz", {
3
- title: "Quiz Creation Guide",
4
- description: "Best practices and defaults for creating a quiz with Clipform",
5
- }, async () => ({
6
- messages: [
7
- {
8
- role: "user",
9
- content: { type: "text", text: "How should I create a quiz?" },
10
- },
11
- {
12
- role: "assistant",
13
- content: {
14
- type: "text",
15
- text: `When creating a quiz (knowledge questions with correct/wrong answers):
16
-
17
- **Form settings** (set during clipform_create_form):
18
- - show_step_counter: true (shows "1/5" progress)
19
- - disable_back_navigation: true (no going back to change answers)
20
- - Always set both of these when creating a quiz
21
-
22
- **Question defaults:**
23
- - Randomise answer options (set randomise_options: true in config)
24
- - 3-4 wrong answers per question for good difficulty
25
- - One clearly correct answer
26
-
27
- **Scoring:**
28
- - Set score: 1 on the correct answer option, score: 0 on wrong answers
29
- - This enables automatic score tracking throughout the quiz
30
- - On the end_screen, set show_score: true and icon: "trophy" in config to display the score and a trophy icon
31
-
32
- **Media workflow (if the user wants video):**
33
- 1. clipform_generate_tts - generate narration audio for each question (returns captions)
34
- 2. clipform_search_media (kind: "image") - find 3 images per question
35
- 3. clipform_generate_slideshow - create Ken Burns video from images + audio
36
- 4. clipform_upload_question_media - attach video to question. ALWAYS include the captions from step 1 and set show_captions: true. Captions must always be on for narrated content.
37
-
38
- **Image selection:**
39
- - ONLY use image URLs from clipform_search_media results. These are quality-filtered and high-res.
40
-
41
- **Writing the questions - factual accuracy (IMPORTANT):**
42
- For timeless topics (history, geography, science, nature, general knowledge up to your training cutoff), write questions directly from your own knowledge - a good language model is more accurate and more interesting than a generic trivia API.
43
-
44
- For any topic that is recent (post-training-cutoff) or any fact you are NOT confident about, follow this preference order BEFORE writing the question:
45
- 1. If your client exposes a native web search or web fetch tool (e.g. WebSearch / WebFetch), use that - it is broader and more current.
46
- 2. Otherwise, use clipform_search_news for structured current-news results.
47
- 3. If neither is available, REFUSE rather than fabricate. Tell the user you cannot verify facts about that topic and suggest they provide the source material.
48
-
49
- Never invent dates, names, statistics, or event details you are not sure of. It is always better to refuse a question than to ship a hallucinated one.
50
-
51
- **Narration style:**
52
- - The TTS narration should only read the question - do NOT repeat the answer options verbally. The options are displayed on screen for the user to read and tap.
53
- - Keep narration concise and conversational. Add a brief interesting fact or context if it fits naturally.
54
-
55
- **Audit log (final step):**
56
- After building the quiz, call clipform_log_generation with:
57
- - summary of what was built
58
- - sources used for research (Wikipedia articles, URLs)
59
- - images used with attribution and license
60
-
61
- **Before building, ask the user:**
4
+ title: "Create a Quiz",
5
+ description: "Build a scored knowledge quiz with narrated video questions",
6
+ }, async () => {
7
+ const sessionContext = await getSessionContext();
8
+ return {
9
+ messages: [
10
+ {
11
+ role: "user",
12
+ content: {
13
+ type: "text",
14
+ text: "I want to create a quiz. What's the best approach?",
15
+ },
16
+ },
17
+ {
18
+ role: "assistant",
19
+ content: {
20
+ type: "text",
21
+ text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build a great quiz with Clipform. Read the quiz writing guide (clipform://guides/quiz) for detailed craft knowledge on question design, difficulty curves, and narration style.
22
+
23
+ ## Workflow
24
+
25
+ 1. **Research** the topic - find surprising facts, common misconceptions, myth-busters
26
+ 2. **Write questions** - follow the difficulty curve (easy start, hard middle, satisfying end). Target 5-8 questions.
27
+ 3. **Create the form** with clipform_create_form:
28
+ - show_step_counter: true
29
+ - disable_back_navigation: true
30
+ 4. **Add questions** with clipform_add_node (type: "choice"):
31
+ - config: { choice: { show_answer_feedback: true } }
32
+ - randomise_options: true in config
33
+ - score: 1 on correct option, score: 0 on wrong
34
+ - 3-4 wrong answers per question
35
+ 5. **Generate narration** with clipform_generate_tts for each question. Tease the question - do NOT reveal the answer or read options aloud. Keep each narration 5-15 seconds.
36
+ 6. **Build video** for each question:
37
+ - clipform_search_media (kind: "image") - 3 images per question
38
+ - clipform_generate_video - creates Ken Burns video synced to audio
39
+ 7. **Attach media** with clipform_upload_node_media. Include captions, set show_captions: true.
40
+ 8. **Update end screen** with clipform_update_node - EVERY quiz must have:
41
+ - show_score: true, icon: "trophy"
42
+ - show_share_button: true (drives virality)
43
+ - cta_type: "restart", cta_text: a short challenge like "Beat your score?" or "Try again?"
44
+ - score_ranges with personalised title + message per tier. Write these in the quiz's voice - short, punchy, and specific to the topic (not generic "Good job!"). Example for a geography quiz:
45
+ \`\`\`json
46
+ { "min": 0, "max": 2, "title": "Lost Tourist", "message": "You might need a map - and a compass." },
47
+ { "min": 3, "max": 5, "title": "Frequent Flyer", "message": "Not bad! You know your way around." },
48
+ { "min": 6, "max": 8, "title": "World Explorer", "message": "Impressive - you really know your stuff." }
49
+ \`\`\`
50
+ 9. **Publish** with clipform_update_form
51
+ 10. **Tag the form** - pass tags: one format (quiz/survey/interview/feedback/lead-gen), one genre (trivia/personality/nps/poll/testimonial), and 2-3 topic words
52
+ 11. **Log** with clipform_log_generation (sources, images, attributions)
53
+
54
+ ## Before building, ask
55
+
62
56
  1. How many questions?
63
57
  2. Media style: text only, still images, or slideshow video with narration?
64
58
  3. Any topic or style preferences?`,
59
+ },
60
+ },
61
+ ],
62
+ };
63
+ });
64
+ server.registerPrompt("create-personality-quiz", {
65
+ title: "Create a Personality Quiz",
66
+ description: "Build a 'Which X are you?' personality quiz with category-based scoring and outcome screens",
67
+ }, async () => {
68
+ const sessionContext = await getSessionContext();
69
+ return {
70
+ messages: [
71
+ {
72
+ role: "user",
73
+ content: {
74
+ type: "text",
75
+ text: "I want to create a personality quiz. What's the best approach?",
76
+ },
77
+ },
78
+ {
79
+ role: "assistant",
80
+ content: {
81
+ type: "text",
82
+ text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build a personality quiz with Clipform. Read the personality quiz guide (clipform://guides/personality-quiz) for craft knowledge on category design, option weighting, and outcome writing.
83
+
84
+ ## How it differs from a knowledge quiz
85
+
86
+ There are NO correct answers. Each option maps to one or more outcome categories via \`scores\` (not \`score\`). The winning category at the end determines which result screen the respondent sees.
87
+
88
+ ## Workflow
89
+
90
+ 1. **Define 3-5 outcome categories** - these are the "personalities" (e.g. "Creative", "Analytical", "Leader", "Collaborator"). More than 5 gets muddy.
91
+ 2. **Write questions** - each question should feel revealing but fun. Target 5-8 questions.
92
+ 3. **Create the form** with clipform_create_form:
93
+ - show_step_counter: true
94
+ - disable_back_navigation: true
95
+ 4. **Add questions** with clipform_add_node (type: "choice"):
96
+ - config: { choice: { show_answer_feedback: false } } (no right/wrong!)
97
+ - Do NOT set randomise_options (option order matters for personality quizzes - lead with the most appealing)
98
+ - Each option gets \`scores: { "CategoryA": 2, "CategoryB": 1 }\` - weight towards relevant categories
99
+ - Every option should score in at least one category (no dead options)
100
+ 5. **Generate narration** with clipform_generate_tts - conversational, reflective tone. "What does this say about you?" not "Do you know the answer?"
101
+ 6. **Build video** + **attach media** (same as knowledge quiz workflow)
102
+ 7. **Update end screen** with clipform_update_node - EVERY personality quiz must have:
103
+ - show_score: false, icon: "star"
104
+ - show_share_button: true (personality results are inherently shareable - "I got X, what did you get?")
105
+ - cta_type: "restart", cta_text: "Find out again?" or "Take it again?"
106
+ - scoring_results (NOT score_ranges) with a result per category. Write the title as an identity reveal ("You're a Creative!") and the message as a short, flattering description that makes people want to share it. Be specific to the quiz theme, not generic. Example:
107
+ \`\`\`json
108
+ {
109
+ "show_score": false,
110
+ "icon": "star",
111
+ "show_share_button": true,
112
+ "cta_type": "restart",
113
+ "cta_text": "Retake quiz",
114
+ "scoring_results": [
115
+ { "category": "Creative", "title": "You're a Creative!", "message": "You see the world through colour and possibility. Where others see problems, you see raw material." },
116
+ { "category": "Analytical", "title": "You're an Analyst!", "message": "You don't guess - you figure it out. Your superpower is turning chaos into clarity." }
117
+ ]
118
+ }
119
+ \`\`\`
120
+ 8. **Publish** with clipform_update_form
121
+ 9. **Tag the form** - pass tags: one format (quiz/survey/interview/feedback/lead-gen), one genre (trivia/personality/nps/poll/testimonial), and 2-3 topic words
122
+ 10. **Log** with clipform_log_generation
123
+
124
+ ## Before building, ask
125
+
126
+ 1. What are the possible outcomes/personalities? (3-5 categories)
127
+ 2. What's the theme? ("Which city are you?", "What's your work style?", "Which character are you?")
128
+ 3. Media style: text only, still images, or slideshow video with narration?`,
129
+ },
65
130
  },
66
- },
67
- ],
68
- }));
69
- server.registerPrompt("create-form", {
70
- title: "Form Creation Guide",
71
- description: "Best practices for creating a standard form or survey with Clipform",
72
- }, async () => ({
73
- messages: [
74
- {
75
- role: "user",
76
- content: { type: "text", text: "How should I create a form?" },
77
- },
78
- {
79
- role: "assistant",
80
- content: {
81
- type: "text",
82
- text: `When creating a standard form or survey:
83
-
84
- **Form settings:**
85
- - Back navigation is enabled by default (respondents can review answers)
86
- - Step counter is off by default (optional, enable for longer forms)
87
-
88
- **Common patterns:**
89
- - Use "contact" type for collecting user details (name, email, etc.)
90
- - Use "open" type for free-text responses
91
- - Use "choice" type for multiple choice / single select
92
- - End with an "end_screen" type for a thank you message
93
-
94
- **Media:** Forms can have video or image backgrounds on each question. Use clipform_upload_media to attach media after creation.`,
131
+ ],
132
+ };
133
+ });
134
+ server.registerPrompt("create-interview", {
135
+ title: "Create an Interview",
136
+ description: "Build a form to collect testimonials, case studies, async video interviews, or journalist responses",
137
+ }, async () => {
138
+ const sessionContext = await getSessionContext();
139
+ return {
140
+ messages: [
141
+ {
142
+ role: "user",
143
+ content: {
144
+ type: "text",
145
+ text: "I want to collect responses or testimonials from people. What's the best approach?",
146
+ },
95
147
  },
96
- },
97
- ],
98
- }));
99
- server.registerPrompt("create-journo-request", {
100
- title: "Journalist Request Guide",
101
- description: "Best practices for turning a journalist's callout into a Clipform",
102
- }, async () => ({
103
- messages: [
104
- {
105
- role: "user",
106
- content: { type: "text", text: "How should I create a journalist request form?" },
107
- },
108
- {
109
- role: "assistant",
110
- content: {
111
- type: "text",
112
- text: `When a journalist pastes their callout/request text, turn it into a Clipform. The form replaces "DM me" or "email me" with a shareable link.
113
-
114
- **Form structure (in order):**
115
- 1. **Open question** - The core ask from the journalist's text. Use "open" type. Default to text + audio + video responses.
116
- 2. **Additional short questions** (optional) - Only for distinct secondary asks. Don't over-split.
117
- 3. **Contact collection** - Always include. Minimum: first_name and email.
118
- 4. **Consent checkbox** - "I agree that my response may be used in published media coverage."
119
- 5. **End screen** - "Thanks for your response. The journalist will be in touch if they'd like to take things further."
120
-
121
- **Form settings:**
122
- - disable_back_navigation: false
123
- - show_step_counter: true
124
-
125
- **Two modes:**
126
- - One-shot: build immediately with sensible defaults when asked directly
127
- - Dialogue: ask about video-only/format and extra fields, show wireframe preview first
128
-
129
- Default to dialogue mode unless explicitly asked for one-shot.`,
148
+ {
149
+ role: "assistant",
150
+ content: {
151
+ type: "text",
152
+ text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build an interview or testimonial form with Clipform. Read the interview guide (clipform://guides/interview) for detailed craft knowledge on question design and pacing.
153
+
154
+ ## Workflow
155
+
156
+ 1. **Identify the ask** - what do you need from respondents? Testimonial, case study, expert comment, job application?
157
+ 2. **Create the form** with clipform_create_form:
158
+ - show_step_counter: true
159
+ - disable_back_navigation: false
160
+ 3. **Add a warm-up question** - something easy: "Tell us your name and role" (type: "open")
161
+ 4. **Add core questions** (type: "open") - 2-3 max, one topic per question. Enable text + audio + video responses.
162
+ 5. **Add contact collection** (type: "contact") - first name + email minimum
163
+ 6. **Add consent** if needed - "I agree that my response may be used in [context]"
164
+ 7. **Update end screen** - set expectations: "Thanks! We'll be in touch."
165
+ 8. **Optional: add narration** - warm, inviting tone. "We'd love to hear your story..."
166
+ 9. **Publish** with clipform_update_form
167
+ 10. **Tag the form** - pass tags: one format (quiz/survey/interview/feedback/lead-gen), one genre (trivia/personality/nps/poll/testimonial), and 2-3 topic words
168
+
169
+ ## Before building, ask
170
+
171
+ 1. What are you collecting? (testimonial, case study, interview, application)
172
+ 2. Should respondents reply with video, audio, text, or all three?
173
+ 3. Do you need a consent statement?`,
174
+ },
175
+ },
176
+ ],
177
+ };
178
+ });
179
+ server.registerPrompt("create-survey", {
180
+ title: "Create a Survey",
181
+ description: "Build a feedback survey, NPS form, or research questionnaire",
182
+ }, async () => {
183
+ const sessionContext = await getSessionContext();
184
+ return {
185
+ messages: [
186
+ {
187
+ role: "user",
188
+ content: {
189
+ type: "text",
190
+ text: "I want to collect feedback or run a survey. What's the best approach?",
191
+ },
192
+ },
193
+ {
194
+ role: "assistant",
195
+ content: {
196
+ type: "text",
197
+ text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build a survey with Clipform. Read the survey guide (clipform://guides/survey) for craft knowledge on question design and reducing respondent fatigue.
198
+
199
+ ## Workflow
200
+
201
+ 1. **Define the key metric** - what's the one number you care about? (NPS, satisfaction, likelihood to recommend)
202
+ 2. **Create the form** with clipform_create_form:
203
+ - show_step_counter: true
204
+ - disable_back_navigation: false
205
+ 3. **Add key metric question first** (type: "choice" or "rating") - put it first while attention is highest
206
+ 4. **Add one "why?" follow-up** (type: "open") - "What's the main reason for your score?"
207
+ 5. **Add 2-3 specific questions** (type: "choice") - only ask what you'll act on
208
+ 6. **Contact** (optional) - only if you need to follow up. Many surveys work better anonymous.
209
+ 7. **Update end screen** - "Thanks for your feedback!"
210
+ 8. **Publish** with clipform_update_form
211
+ 9. **Tag the form** - pass tags: one format (quiz/survey/interview/feedback/lead-gen), one genre (trivia/personality/nps/poll/testimonial), and 2-3 topic words
212
+
213
+ ## Key rule: 5 questions max. Every extra question costs completions.
214
+
215
+ ## Before building, ask
216
+
217
+ 1. What feedback are you collecting? (NPS, satisfaction, event feedback, product research)
218
+ 2. Anonymous or identified?
219
+ 3. Any specific areas you want to ask about?`,
220
+ },
221
+ },
222
+ ],
223
+ };
224
+ });
225
+ server.registerPrompt("create-funnel", {
226
+ title: "Create a Funnel",
227
+ description: "Build a lead qualification funnel or product recommendation quiz with branching logic",
228
+ }, async () => {
229
+ const sessionContext = await getSessionContext();
230
+ return {
231
+ messages: [
232
+ {
233
+ role: "user",
234
+ content: {
235
+ type: "text",
236
+ text: "I want to qualify leads or recommend products based on answers. What's the best approach?",
237
+ },
238
+ },
239
+ {
240
+ role: "assistant",
241
+ content: {
242
+ type: "text",
243
+ text: `${sessionContext ? sessionContext + "\n\n" : ""}Here's how to build a qualification funnel with Clipform. Read the funnel guide (clipform://guides/funnel) for craft knowledge on branching logic and conversion.
244
+
245
+ ## Workflow
246
+
247
+ 1. **Define outcomes** - what segments or recommendations exist? (e.g., Basic/Pro/Enterprise, or product categories)
248
+ 2. **Create the form** with clipform_create_form:
249
+ - show_step_counter: false (funnels feel shorter without it)
250
+ - disable_back_navigation: true (prevents answer shopping that breaks scoring)
251
+ 3. **Add hook question** (type: "choice") - "What best describes you?" or "What are you looking for?" This segments the user.
252
+ 4. **Add qualifying questions** (type: "choice") - 2-3 questions that narrow down the need. Assign scores to each option.
253
+ 5. **Set branching logic** with clipform_set_logic - route based on answers
254
+ 6. **Add contact capture** (type: "contact") - name, email, phone. Place AFTER qualifying questions.
255
+ 7. **Update end screen** with score_ranges for personalised outcomes: "Based on your answers, we recommend..."
256
+ 8. **Publish** with clipform_update_form
257
+ 9. **Tag the form** - pass tags: one format (quiz/survey/interview/feedback/lead-gen), one genre (trivia/personality/nps/poll/testimonial), and 2-3 topic words
258
+
259
+ ## Key rule: 3-5 questions max. Every extra step loses leads.
260
+
261
+ ## Before building, ask
262
+
263
+ 1. What outcomes are you routing to? (products, plans, team members, messages)
264
+ 2. What criteria determine the routing?
265
+ 3. Do you need contact capture?`,
266
+ },
130
267
  },
131
- },
132
- ],
133
- }));
268
+ ],
269
+ };
270
+ });
134
271
  }
135
272
  //# sourceMappingURL=prompts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,cAAc,CACnB,aAAa,EACb;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,+DAA+D;KAC7E,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,6BAA6B,EAAE;aACxE;YACD;gBACE,IAAI,EAAE,WAAoB;gBAC1B,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCAiDiB;iBACxB;aACF;SACF;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,cAAc,CACnB,aAAa,EACb;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,qEAAqE;KACnF,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,6BAA6B,EAAE;aACxE;YACD;gBACE,IAAI,EAAE,WAAoB;gBAC1B,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;;;;;;;;;iIAY+G;iBACtH;aACF;SACF;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,cAAc,CACnB,uBAAuB,EACvB;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,mEAAmE;KACjF,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gDAAgD,EAAE;aAC3F;YACD;gBACE,IAAI,EAAE,WAAoB;gBAC1B,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;;;;;;;;;;;;;;+DAiB6C;iBACpD;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerResources(server: McpServer): void;