@kolbo/mcp 1.64.0 → 1.65.1
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/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -99,7 +99,7 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
|
|
|
99
99
|
| `generate_video` | Text-to-video. Does **not** support Visual DNA — use `generate_elements` for character-consistent video. |
|
|
100
100
|
| `generate_video_from_image` | Animate a still. Prompt describes motion, not subject. |
|
|
101
101
|
| `generate_video_from_video` | Restyle/transform an existing video. Keeps original motion. |
|
|
102
|
-
| `generate_elements` | Reference-driven video. **Primary route for DNA → video.** |
|
|
102
|
+
| `generate_elements` | Reference-driven video. **Primary route for DNA → video.** Supports `multi_shots` / `multi_shot_count` (badge/metadata/native flag only — never rewrites the prompt) and short `session_name`. Crafted demos: `enhance_prompt:false` + put shot structure in the prompt. |
|
|
103
103
|
| `generate_first_last_frame` | Keyframe interpolation between two frames. |
|
|
104
104
|
| `generate_lipsync` | Lipsync audio to an image or video face. |
|
|
105
105
|
| `generate_music` | Music generation (Suno + variants). |
|
|
@@ -9,6 +9,8 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
|
|
|
9
9
|
|
|
10
10
|
**Kolbo MCP routing:** Seedance is a video model — call `generate_video` (text-to-video) or `generate_elements` (when video references / Visual DNA / first-last frames are involved). Run `list_models({ type: "text_to_video" })` and pick a Seedance variant by name.
|
|
11
11
|
|
|
12
|
+
**Multishot (Elements):** Seedance has **no** native provider Multishot switch. Pass `multi_shots: true` on `generate_elements` (optional `multi_shot_count`) for the UI Multishot badge only — it does **not** rewrite or reshape your prompt. **Always send `enhance_prompt: false` for crafted demos** (MCP default) so the prompt stays RAW. Put shot structure in the prompt yourself (`Multishot ON`, `Total: … / N shots`, numbered shots). Optional `session_name` sets a short sidebar title (skips AI auto-name from boilerplate).
|
|
13
|
+
|
|
12
14
|
## Universal Rules (apply to EVERY Seedance prompt)
|
|
13
15
|
|
|
14
16
|
- **First line ALWAYS declares shot structure**: total duration, shot count, aspect ratio. Example: `Total: 15s / 6 shots / 16:9`. Put it at the BOTTOM of the prompt too. For connected narrative sequences the proven phrasing is `N connected cinematic shots, 15 seconds total, 16:9, Multishot ON` — use it and keep `Multishot ON` for any multi-shot story.
|
|
@@ -123,7 +123,7 @@ If the user gives a **product URL** instead of a photo, see `workflows/research-
|
|
|
123
123
|
|
|
124
124
|
## Multi-Slot Board Method (structured shot specs + character consistency)
|
|
125
125
|
|
|
126
|
-
For any multi-shot UGC / review / how-to where the SAME presenter must stay identical across shots, compose the prompt as explicit **slots** and lock identity with a **board-first** pass.
|
|
126
|
+
For any multi-shot UGC / review / how-to where the SAME presenter must stay identical across shots, compose the prompt as explicit **slots** and lock identity with a **board-first** pass. Prefer `generate_elements` with `multi_shots: true` (and a short `session_name`) when animating a single multi-cut Seedance spot; board-first still uses `generate_image` + `generate_elements` / `generate_video_from_image` per slot when you need separate clips.
|
|
127
127
|
|
|
128
128
|
### 1. Structured input slots
|
|
129
129
|
|
package/src/tools/generate.js
CHANGED
|
@@ -987,10 +987,13 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
987
987
|
image_url: z.string().describe('Public URL of the keyframe image'),
|
|
988
988
|
timestamp_seconds: z.number().describe('Moment on the OUTPUT timeline (seconds, 0 = first frame) where this image is pinned')
|
|
989
989
|
})).optional().describe('Timeline-pinned keyframes for multi-keyframe models (e.g. "flux-3-keyframes", "luma-ray-3-2-storyboard"): the model generates the motion BETWEEN the pinned images. Only models with `supports_keyframes: true` in list_models accept this; cap = `max_keyframes` (FLUX 3: 10). Requires an explicit `duration` — timestamps beyond it are clamped. Ignored by ordinary elements models. OPTIONAL for flux-3-keyframes: if omitted, pass the images via reference_images instead — they are played through IN ORDER, timed from timing language in the prompt or spaced evenly. Pass explicit keyframes only when you need exact control.'),
|
|
990
|
+
multi_shots: z.boolean().optional().describe('Enable Multishot metadata/UI badge (and native provider flag when the model supportsMultiShot). Never rewrites or reshapes the prompt — craft shot structure yourself (`Multishot ON`, Total/SHOT lines). MCP default enhance_prompt=false keeps the prompt raw; multi_shots alone is badge/flag only. For crafted demos: enhance_prompt:false + multi_shots:true.'),
|
|
991
|
+
multi_shot_count: z.number().optional().describe('Explicit shot count when multi_shots=true (e.g. 2). Clamped to ~2 shots/sec of duration.'),
|
|
992
|
+
session_name: z.string().optional().describe('Short sidebar session title (max ~60 chars), e.g. "UGC — Hana bathroom light". When set, skips AI auto-naming from the prompt boilerplate.'),
|
|
990
993
|
project_id: projectIdField,
|
|
991
994
|
session_id: sessionIdField
|
|
992
995
|
},
|
|
993
|
-
async ({ prompt, model, reference_images, reference_videos, reference_audio_urls, audio_url, files, duration, aspect_ratio, motion, preset_id, enhance_prompt = false, visual_dna_ids, resolution, keyframes, project_id, session_id }) => {
|
|
996
|
+
async ({ prompt, model, reference_images, reference_videos, reference_audio_urls, audio_url, files, duration, aspect_ratio, motion, preset_id, enhance_prompt = false, visual_dna_ids, resolution, keyframes, multi_shots, multi_shot_count, session_name, project_id, session_id }) => {
|
|
994
997
|
model = await canonicalModelId(client, model, 'elements'); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
995
998
|
if (!prompt) throw new Error('prompt is required');
|
|
996
999
|
|
|
@@ -1013,6 +1016,9 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
1013
1016
|
if (audio_url) form.append('audio_url', audio_url);
|
|
1014
1017
|
if (resolution) form.append('resolution', resolution);
|
|
1015
1018
|
if (keyframes) form.append('keyframes', JSON.stringify(keyframes));
|
|
1019
|
+
if (multi_shots !== undefined) form.append('multi_shots', String(multi_shots));
|
|
1020
|
+
if (multi_shot_count !== undefined) form.append('multi_shot_count', String(multi_shot_count));
|
|
1021
|
+
if (session_name) form.append('session_name', session_name);
|
|
1016
1022
|
if (project_id) form.append('project_id', project_id);
|
|
1017
1023
|
if (session_id) form.append('session_id', session_id);
|
|
1018
1024
|
for (const f of resolved) {
|
|
@@ -1022,7 +1028,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
1022
1028
|
} else {
|
|
1023
1029
|
// URL-only mode: plain JSON.
|
|
1024
1030
|
startResponse = await client.post('/v1/generate/elements', {
|
|
1025
|
-
prompt, model, reference_images, reference_videos, reference_audio_urls, audio_url, duration, aspect_ratio, motion, preset_id, enhance_prompt, visual_dna_ids, resolution, keyframes, project_id, session_id
|
|
1031
|
+
prompt, model, reference_images, reference_videos, reference_audio_urls, audio_url, duration, aspect_ratio, motion, preset_id, enhance_prompt, visual_dna_ids, resolution, keyframes, multi_shots, multi_shot_count, session_name, project_id, session_id
|
|
1026
1032
|
});
|
|
1027
1033
|
}
|
|
1028
1034
|
|
package/src/tools/visual_dna.js
CHANGED
|
@@ -197,7 +197,7 @@ function registerVisualDnaTools(server, client, options = {}) {
|
|
|
197
197
|
'Generate a reference sheet for a Visual DNA from 1+ reference image URLs — the same step the in-app Visual DNA wizard offers, for EVERY DNA type via `sheet_type`: character = multi-angle turnaround, product = angles + branding/material/construction close-ups, environment = location angles + one signature detail, style = a style board (the same look applied to six varied subjects). The sheet is the single strongest consistency booster for a DNA, and it always preserves the reference\'s original art style (2D stays 2D, photo stays photo). CHARGES CREDITS, so when the user is about to create a DNA, OFFER this first ("want me to generate a reference sheet for stronger consistency? it costs a few credits") and only run it on a yes. Returns `character_sheet_url` — pass it as `character_sheet_url` to `create_visual_dna` with the matching `dna_type`.',
|
|
198
198
|
{
|
|
199
199
|
image_urls: z.array(z.string()).min(1).describe('Reference image URLs of the subject (for characters: front/side/varied angles work best). Use generated-image URLs or upload_media output.'),
|
|
200
|
-
sheet_type: z.enum(['character', 'product', 'environment', 'style']).optional().describe('
|
|
200
|
+
sheet_type: z.enum(['character', 'character_headless', 'product', 'environment', 'style']).optional().describe('Sheet layout. character = front/back/face turnaround. character_headless = wardrobe/body refs with a headless front panel (use when clothing must change without fighting the face sheet). product / environment / style = matching DNA types. Defaults to character.')
|
|
201
201
|
},
|
|
202
202
|
async ({ image_urls, sheet_type }) => {
|
|
203
203
|
const result = await client.post('/v1/visual-dna/character-sheet', { image_urls, ...(sheet_type ? { sheet_type } : {}) });
|