corent-mcp 0.6.0 → 0.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.
- package/README.md +102 -10
- package/dist/http-app.js +227 -0
- package/dist/http.js +12 -198
- package/dist/prompts.js +123 -0
- package/dist/server.js +542 -52
- package/package.json +1 -1
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP prompts: five production recipes built ONLY from the tools this server
|
|
3
|
+
* already exposes. Each is a step list an assistant follows with the user:
|
|
4
|
+
* plan, confirm the budget, stills with references, clips, narration, poll.
|
|
5
|
+
*
|
|
6
|
+
* The long "how to" guidance used to live inside tool descriptions; it lives
|
|
7
|
+
* here now so every tool description stays under 400 characters (ChatGPT and
|
|
8
|
+
* other hosts truncate or reject long ones). The same five recipes ship as
|
|
9
|
+
* markdown in mcp/skills/<name>/SKILL.md for publication as a skills repo.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
// Honest per-unit prices, in the same words the tool descriptions use. Quote
|
|
13
|
+
// these to the user before spending; the exact charge comes back per call.
|
|
14
|
+
export const PRICE_NOTE = "Prices to quote before spending: image premium ~7c each; video premium ~52c per clip, pro ~84c per clip; " +
|
|
15
|
+
"speech ~25-30c per started block of 1,000 characters (send the whole script in ONE generate_speech call). " +
|
|
16
|
+
"Failed generations are never billed. The exact charge is in meta.cost_cents on every result.";
|
|
17
|
+
const BUDGET_RULE = "Add the numbers up, show the user the total against their budget, and do NOT call a paid tool until they say yes. " +
|
|
18
|
+
"Call get_balance first: available_cents is what can actually be spent.";
|
|
19
|
+
const POLLING = "Video is asynchronous: each generate_video returns a job id. Poll get_job every 10-15 seconds until status is " +
|
|
20
|
+
"completed (a clip usually takes 1-4 minutes); the URL is in videos[0].url. If the user changes their mind, cancel_job releases the hold.";
|
|
21
|
+
const DELIVERY = "Corent does not stitch clips together. Deliver every still, clip and narration URL in order with its cost, " +
|
|
22
|
+
"so the user can assemble them in any editor. list_media can find these again later by prompt keyword.";
|
|
23
|
+
function user(text) {
|
|
24
|
+
return { messages: [{ role: "user", content: { type: "text", text } }] };
|
|
25
|
+
}
|
|
26
|
+
export function registerPrompts(server) {
|
|
27
|
+
server.registerPrompt("product-ugc-reel", {
|
|
28
|
+
title: "Product UGC reel",
|
|
29
|
+
description: "A vertical creator-style reel for one product: 3-5 stills that keep the product consistent, one clip per still, and a single narration track.",
|
|
30
|
+
argsSchema: {
|
|
31
|
+
product_url: z.string().describe("Public https URL of a product photo (use upload_image for a local file)"),
|
|
32
|
+
brief: z.string().describe("Who it is for and the one thing the reel must say"),
|
|
33
|
+
budget_usd: z.string().optional().describe("Spend ceiling in US dollars, e.g. 5"),
|
|
34
|
+
},
|
|
35
|
+
}, ({ product_url, brief, budget_usd }) => user([
|
|
36
|
+
`Make a product UGC reel. Product image: ${product_url}. Brief: ${brief}. Budget: $${budget_usd ?? "ask the user"}.`,
|
|
37
|
+
"",
|
|
38
|
+
"1. PLAN. Write a 4-shot vertical (9:16) shot list: hook, product in use, the benefit, call to action. One line of narration per shot; keep the whole script under 1,000 characters.",
|
|
39
|
+
`2. COST. ${PRICE_NOTE} ${BUDGET_RULE}`,
|
|
40
|
+
"3. STILLS. For each shot call generate_image with reference_image_urls=[product image], tier premium (never air or lite: references need an edit-capable model), aspect_ratio 9:16, style photorealistic. If the label or logo must be pixel-exact, generate the scene, then inpaint_image with a mask that is BLACK over the product and WHITE elsewhere: pixels outside the mask stay byte-for-byte.",
|
|
41
|
+
"4. CLIPS. For each approved still call generate_video with image_url = that still, tier premium (pro if the user wants the best), duration_s 5. Omit aspect_ratio when animating a still. Pass audio false; the narration is a separate track.",
|
|
42
|
+
"5. NARRATION. Call list_voices, let the user pick a voice_id, then ONE generate_speech call with the full script.",
|
|
43
|
+
`6. POLL. ${POLLING}`,
|
|
44
|
+
`7. DELIVER. ${DELIVERY}`,
|
|
45
|
+
].join("\n")));
|
|
46
|
+
server.registerPrompt("character-series", {
|
|
47
|
+
title: "Character series",
|
|
48
|
+
description: "One consistent character across many scenes: an anchor portrait, then every scene generated as an edit of that anchor.",
|
|
49
|
+
argsSchema: {
|
|
50
|
+
character: z.string().describe("Who the character is: age, look, clothing, mood"),
|
|
51
|
+
scenes: z.string().describe("The scenes, comma separated, e.g. 'at a cafe, on a train, at the beach'"),
|
|
52
|
+
budget_usd: z.string().optional().describe("Spend ceiling in US dollars"),
|
|
53
|
+
},
|
|
54
|
+
}, ({ character, scenes, budget_usd }) => user([
|
|
55
|
+
`Make a consistent character series. Character: ${character}. Scenes: ${scenes}. Budget: $${budget_usd ?? "ask the user"}.`,
|
|
56
|
+
"",
|
|
57
|
+
"1. ANCHOR. One generate_image, tier premium, aspect_ratio 3:4: the character alone, neutral pose, plain background, face clearly visible. Show it to the user and iterate (same seed, one change) until they approve. This is the only image the series is built from.",
|
|
58
|
+
`2. COST. One image per scene at ~7c (premium). ${BUDGET_RULE}`,
|
|
59
|
+
"3. SCENES. For each scene call generate_image with reference_image_urls=[anchor URL], tier premium or pro, the scene in the prompt, same style every time. Keep the anchor as the FIRST reference if you add a second (e.g. a product).",
|
|
60
|
+
"4. OPTIONAL CLIPS. generate_video with image_url = the scene still, duration_s 5, omit aspect_ratio. Quote ~52c (premium) or ~84c (pro) per clip first.",
|
|
61
|
+
`5. POLL. ${POLLING}`,
|
|
62
|
+
`6. DELIVER. ${DELIVERY} Tell the user the anchor URL: pass it as a reference any time they want this character again.`,
|
|
63
|
+
].join("\n")));
|
|
64
|
+
server.registerPrompt("storyboard-to-clip", {
|
|
65
|
+
title: "Storyboard to clips",
|
|
66
|
+
description: "Turn a numbered storyboard into stills, then one clip per still with a camera move, plus optional narration.",
|
|
67
|
+
argsSchema: {
|
|
68
|
+
storyboard: z.string().describe("Numbered shots, one line each: what is in frame and what moves"),
|
|
69
|
+
style: z.string().optional().describe("Look, e.g. cinematic, anime, documentary"),
|
|
70
|
+
budget_usd: z.string().optional().describe("Spend ceiling in US dollars"),
|
|
71
|
+
},
|
|
72
|
+
}, ({ storyboard, style, budget_usd }) => user([
|
|
73
|
+
`Turn this storyboard into clips. Style: ${style ?? "cinematic"}. Budget: $${budget_usd ?? "ask the user"}.`,
|
|
74
|
+
storyboard,
|
|
75
|
+
"",
|
|
76
|
+
"1. PLAN. Restate the shots as a table: number, frame, movement, seconds (5 each unless told otherwise), narration line if any.",
|
|
77
|
+
`2. COST. One still (~7c) plus one clip (~52c premium, ~84c pro) per shot, plus ~30c if there is narration. ${BUDGET_RULE}`,
|
|
78
|
+
"3. STILLS. generate_image per shot, aspect_ratio 16:9, style cinematic (or the requested style), tier premium. Use reference_image_urls when a character or object recurs across shots, with the first approved still as the reference.",
|
|
79
|
+
"4. CLIPS. generate_video per approved still: image_url = the still, duration_s 5, a camera value that matches the movement (pan_left, zoom_in, orbit_right, static ...). For an A-to-B shot pass end_image_url = the next shot's still. Omit aspect_ratio when animating a still.",
|
|
80
|
+
"5. NARRATION. If the storyboard has lines, list_voices then ONE generate_speech with the whole script.",
|
|
81
|
+
`6. POLL. ${POLLING}`,
|
|
82
|
+
`7. DELIVER. ${DELIVERY}`,
|
|
83
|
+
].join("\n")));
|
|
84
|
+
server.registerPrompt("ad-variations", {
|
|
85
|
+
title: "Ad variations",
|
|
86
|
+
description: "Many versions of one ad visual for testing, in a single batch, with the product kept consistent when a product photo is given.",
|
|
87
|
+
argsSchema: {
|
|
88
|
+
concept: z.string().describe("The ad idea in one or two sentences"),
|
|
89
|
+
count: z.string().optional().describe("How many variations, 2-50 (default 6)"),
|
|
90
|
+
product_url: z.string().optional().describe("Public https URL of the product photo, if the product must stay consistent"),
|
|
91
|
+
},
|
|
92
|
+
}, ({ concept, count, product_url }) => user([
|
|
93
|
+
`Make ${count ?? "6"} variations of this ad: ${concept}.${product_url ? ` Product image: ${product_url}.` : ""}`,
|
|
94
|
+
"",
|
|
95
|
+
"1. PLAN. Choose the axes to vary (setting, angle, time of day, audience, mood) and write one prompt per variation. Same aspect_ratio for all (1:1 for feed, 9:16 for stories). No readable text in the images; headlines go on top in the editor.",
|
|
96
|
+
`2. COST. ~7c per premium image, so count x 7c. ${BUDGET_RULE}`,
|
|
97
|
+
product_url
|
|
98
|
+
? "3. RENDER. With a product photo, batch items cannot carry references: call generate_image once per variation with reference_image_urls=[product image], tier premium. Use inpaint_image (mask BLACK over the product) when the label must be pixel-exact."
|
|
99
|
+
: "3. RENDER. One generate_image_batch call with every prompt as an item, tier premium. Poll get_batch, then get_job for each finished item.",
|
|
100
|
+
"4. REVIEW. Show the user a numbered list with each URL and prompt. Re-render a favourite with the same seed and one change.",
|
|
101
|
+
"5. OPTIONAL MOTION. For the winners, generate_video with image_url = the still, duration_s 5, quoted at ~52c (premium) per clip first.",
|
|
102
|
+
`6. DELIVER. ${DELIVERY}`,
|
|
103
|
+
].join("\n")));
|
|
104
|
+
server.registerPrompt("faceless-explainer", {
|
|
105
|
+
title: "Faceless explainer",
|
|
106
|
+
description: "A narrated explainer with no presenter: a script, one still and one clip per scene, and a single voice track.",
|
|
107
|
+
argsSchema: {
|
|
108
|
+
topic: z.string().describe("What the video explains, and to whom"),
|
|
109
|
+
duration_s: z.string().optional().describe("Target length in seconds (default 30)"),
|
|
110
|
+
budget_usd: z.string().optional().describe("Spend ceiling in US dollars"),
|
|
111
|
+
},
|
|
112
|
+
}, ({ topic, duration_s, budget_usd }) => user([
|
|
113
|
+
`Make a faceless explainer about: ${topic}. Target length ${duration_s ?? "30"} seconds. Budget: $${budget_usd ?? "ask the user"}.`,
|
|
114
|
+
"",
|
|
115
|
+
"1. SCRIPT. Write it yourself (free): about 2.5 words per second, one scene per 5 seconds, each scene = one sentence of narration + one visual. Keep the whole script under 1,000 characters when you can; it bills per started block.",
|
|
116
|
+
`2. COST. Per scene one still (~7c) and one clip (~52c premium), plus ~30c narration. ${BUDGET_RULE}`,
|
|
117
|
+
"3. STILLS. generate_image per scene, aspect_ratio 16:9 (9:16 for shorts), tier premium, one consistent style across scenes. Diagrams and objects rather than faces; no readable text in the image.",
|
|
118
|
+
"4. CLIPS. generate_video per approved still, image_url = the still, duration_s 5, a gentle camera move (zoom_in or pan_right), audio false. Omit aspect_ratio when animating a still.",
|
|
119
|
+
"5. NARRATION. list_voices, pick a clear narration voice, then ONE generate_speech call with the whole script.",
|
|
120
|
+
`6. POLL. ${POLLING}`,
|
|
121
|
+
`7. DELIVER. ${DELIVERY}`,
|
|
122
|
+
].join("\n")));
|
|
123
|
+
}
|