@kolbo/mcp 1.42.0 → 1.44.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 CHANGED
@@ -127,11 +127,11 @@ Without the optional skill, the config block alone already exposes every tool
127
127
  | `generate_first_last_frame` | First frame + last frame → interpolated video |
128
128
  | `generate_lipsync` | Source image/video + audio → lipsynced video (Sync-3 adds active-speaker selection, emotion, model mode, temperature) |
129
129
  | `generate_creative_director` | One brief → N coordinated scenes (image or video) |
130
- | `generate_music` | Text (+ optional lyrics) → song |
131
- | `generate_speech` | Text + voice → spoken audio |
132
- | `generate_sound` | Text → sound effect |
130
+ | `generate_music` | Text (+ optional lyrics) → song. Style, title, negative tags, length, and Suno fine-controls (style weight, weirdness, audio weight, persona / singing voice) |
131
+ | `generate_speech` | Text + voice → spoken audio. Full expressive/style control: free-form voice direction (Google/Gemini), preset styles + emotions (DeepDub / MiniMax), speed, and per-provider voice settings (ElevenLabs stability/similarity/style, DeepDub accent/variance/tempo, MiniMax pitch/volume/intensity/timbre) |
132
+ | `generate_sound` | Text → sound effect. Duration, prompt influence, and per-provider controls (Stable Audio guidance, Kie loop/tempo/key, Seed-Audio voice/speed/volume/pitch + reference audio/image) |
133
133
  | `generate_3d` | Text or reference images → 3D model (GLB/FBX/OBJ/USDZ) |
134
- | `transcribe_audio` | Audio/video URL or file → text + SRT subtitles |
134
+ | `transcribe_audio` | Audio/video URL or file → text + SRT subtitles. Language, speaker diarization, audio-event tagging, and SRT formatting (words/line, lines/subtitle, caption stretch) |
135
135
 
136
136
  Every image/video/creative-director tool accepts `visual_dna_ids` and `moodboard_id` for character/style consistency across outputs — you can compose `create_visual_dna` → `generate_image` (with the DNA applied server-side) in a single agent turn. `generate_creative_director` also accepts `moodboard_ids` plural for blending.
137
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.42.0",
3
+ "version": "1.44.0",
4
4
  "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/skill/SKILL.md CHANGED
@@ -103,9 +103,9 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
103
103
  | `generate_elements` | Reference-driven video. **Primary route for DNA → video.** |
104
104
  | `generate_first_last_frame` | Keyframe interpolation between two frames. |
105
105
  | `generate_lipsync` | Lipsync audio to an image or video face. |
106
- | `generate_music` | Music generation (Suno + variants). |
107
- | `generate_speech` | TTS. Use `list_voices` to pick a voice. |
108
- | `generate_sound` | Sound effects. |
106
+ | `generate_music` | Music generation (Suno + variants). Controls: `style`, `title`, `lyrics`, `instrumental`, `vocal_gender`, `negative_tags`, `duration_seconds`, plus Suno fine-controls (`style_weight`, `weirdness`, `audio_weight`, `persona_id`, `singing_dna_id`/`singing_voice_id`). |
107
+ | `generate_speech` | TTS. Use `list_voices` to pick a voice, then steer delivery with per-provider style/emotion controls — see `references/models/voice-tts.md`. |
108
+ | `generate_sound` | Sound effects. Controls: `duration`, `prompt_influence`, plus provider-specific `cfg_strength` (Stable Audio), `sound_loop`/`sound_tempo`/`sound_key` (Kie), and Seed-Audio `seed_*` params. |
109
109
  | `generate_3d` | 3D models from text / single image / multi-view. Returns GLB/FBX/OBJ/USDZ. |
110
110
 
111
111
  ### Discovery, Library, Visual DNA, Moodboards, Chat, App Builder, Publishing
@@ -162,6 +162,7 @@ A user-named tool — in any language — overrides every other rule. Recognized
162
162
  - User named one → use it. Model identifiers resolve leniently — shorthand like `"z-image"` or `"nano banana 2"` auto-resolves to the exact identifier, so don't over-engineer exact-id lookups (`list_models` is still authoritative for constraints, caps, and pricing).
163
163
  - Auto-select → only from "Auto-selectable" section (models with a `summary`). Cheapest fit. Prefer `[RECOMMENDED]` when cost is similar.
164
164
  - Never auto-select from "Named-only" section.
165
+ - **ALWAYS pass an explicit `model` — never omit it.** Omitting routes to the backend "Smart Select" auto-router, which we deliberately avoid: it hides the model choice and the generation used to show just "Auto" instead of the model that ran. YOU pick the specific model (steps above); only omit `model` when the user explicitly asks for auto-pick, or for chat media analysis (video/audio `media_urls`, which routes to Gemini vision).
165
166
  4. **Validate inputs** against model caps — see `references/workflows/cost-and-validation.md`.
166
167
  5. **How calls work**: each tool blocks until generation is fully complete. Images: seconds. Video: minutes. Multiple tool calls in one response run concurrently. On hosts with live widgets the tool instead returns `submitted` instantly — the card updates on its own; you only need `get_generation_status` when a follow-up step needs the output URLs.
167
168
  6. **Checking status — NEVER poll in a loop**: `get_generation_status` takes `wait=true` (blocks server-side until done, ~3 min) and `generation_ids` (check MANY generations in ONE call — returns `all_done` + which are still running). One `wait=true` call replaces any polling loop. If it comes back with some still processing, call it ONCE more with `wait=true` and the remaining ids.
@@ -1,5 +1,5 @@
1
1
  <!-- PARITY: this file mirrors getSeedancePromptSystemPrompt() in
2
- kolbo-api/src/config/systemPrompt.js (lines ~775–855).
2
+ kolbo-api/src/config/systemPrompt.js.
3
3
  When that function changes, update this file in the same session.
4
4
  See packages/opencode/CLAUDE.md "MCP & Skill Sync Rule". -->
5
5
 
@@ -11,7 +11,7 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
11
11
 
12
12
  ## Universal Rules (apply to EVERY Seedance prompt)
13
13
 
14
- - **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.
14
+ - **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.
15
15
  - **Order inside each shot**: Subject → Action → Camera → Style → Constraints → (Audio/SFX if relevant).
16
16
  - **Prompt length**: aim for ~120–280 words TOTAL across all shots combined (not per shot). Shorter than ~120 words = random output. Longer risks the 8000-char cap below and makes the model forget the opening. For 6-shot prompts, keep each shot 1–2 tight sentences.
17
17
  - **Character lock**: if a character recurs, open with `same character throughout all shots` to stop identity drift.
@@ -60,6 +60,136 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
60
60
  - Style anchor: `Cinematic stylized 3D animation, photorealistic <env>, stylized characters`.
61
61
  - Describe physics as precisely as character actions (particle simulation, volumetric dust, sand displacement, energy VFX).
62
62
 
63
+ ### 6. Reference-Anchored Cinematic Sequence (multi-character / named references — highest-fidelity format)
64
+
65
+ Use whenever the user gives named characters or multiple reference images (`@Image1`, `@Image2`, …) — a tactical unit clearing a bunker, a duel between two referenced characters, a war scene. **This is always an Elements-mode prompt** (route the card to `elements`). Structure:
66
+
67
+ 1. **Labeled scene header FIRST** (grounds the scene before any shot):
68
+ - `Time of day:` — hour + light quality + atmosphere (dust, haze, heavy silence before action).
69
+ - `Location:` — the environment in concrete physical detail (materials, wear, light direction, high-contrast blown-out entrance, etc.).
70
+ - `Characters:` — ONE line per person: `Name @ImageN — wardrobe, position in frame, what they carry`. End with "All must match their character references exactly."
71
+ 2. **REFERENCE CONSISTENCY block** — map every reference and pin what must NOT change: `Reference Image 1 is <X>. Preserve exact face, hair, anatomy, wardrobe, colors, props.` Add per-character energy/aura color rules, and any already-established story state (e.g. "the gem is already shattered — no intact gem, no red glow"). End with "Do not redesign, morph, recolor, or swap either character, their clothing, anatomy, weapons, or the environment."
72
+ 3. **Shots** — either titled (`Shot 1 — Medium Wide / Tactical Positioning`) or timecoded (`SHOT 1 — 0:00–0:03`); timecodes must sum to the total duration. Under each shot use **Camera → Action → Audio** in that order.
73
+ 4. **Continuity** — to chain a series, open with `Begin as a seamless continuation from <the exact last beat of the previous video>.`
74
+ 5. Close with whichever **Power Blocks** below actually apply (this format usually warrants all three; a simpler scene may need only AUDIO).
75
+
76
+ ## Power Blocks (CONDITIONAL — add ONLY the ones the shot actually needs; never pad a simple prompt)
77
+
78
+ These elevate rich cinematic / reference-anchored sequences. For a short, tight, single-idea prompt, skip them — the skill's "short prompts can hit hard, don't pad" rule wins. Apply each only when it earns its place:
79
+
80
+ - **AUDIO** — Seedance renders sound, so specify it whenever sound matters to the scene (most cinematic/action shots). Default diegetic: `AUDIO: No musical score. Synchronized production sound only:` then a comma list of the exact sounds in narrative order (boots scraping concrete, sling shift, layered breathing, distant sirens, weapon impacts, cloth movement, rushing air). Call for a musical score if the user wants one. Skip the block entirely for a deliberately silent or trivially simple shot.
81
+ - **AVOID** — add when there's real drift risk: referenced characters/DNAs, an established story state, or a specific content tone to enforce. `AVOID:` + the drifts to forbid: character morphing, costume/anatomy changes, missing signature details (a piercing, a scar), camera looking into the lens, glamorous posing, duplicated characters, extra weapons, text / subtitles / logos, plus content-specific negatives (e.g. "intact gemstone, red aura" once it's destroyed). Skip it when there's nothing meaningful to forbid.
82
+ - **PHYSICAL GROUNDING** — only when the shot has a real contact/impact (a boot planted on a chest, a weapon lock, a body thrown): spell out weight transfer, full contact, stable balance, material reaction, and the victim's physical response. Not needed for talking, walking, or ambient shots.
83
+
84
+ ## Dialogue & expression
85
+
86
+ - Dialogue goes in quotes and may be in ANY language (Hebrew included). For silent tension, deliver it as expression, not speech: `He does not speak. His expression clearly says: "…"`.
87
+
88
+ ## Content tone
89
+
90
+ - **Brutal war realism** — allow `Hollywood-style blood squib` impacts (visible spray, spreading stain on clothing, violent body reaction, hard collapse) when the user wants gritty combat.
91
+ - **Restrained / no-gore** — when intensity is wanted without gore, state it explicitly (`brutal supernatural strike but no blood, no open wound, no exposed flesh`) AND add the gore terms to the AVOID list.
92
+ - **Rapid-cut montage** (`N cuts / 2 seconds each`) — a valid structure: fixed-length hard cuts, vary the angle every cut (wide / medium / low / side / close handheld), state "Hard cuts. No slow motion," and reserve slow motion for a single named beat if any.
93
+
94
+ ## Universal Craft Layer (apply on top of any format above)
95
+
96
+ > This is the universal film-direction layer that lifts every prompt above the boilerplate. **Deep-dive reference:** `~/.kolbo/skills/seedance-2-prompting/SKILL.md` (Craft Edition — full block structure, every optical technique, and the pre-flight checklist).
97
+
98
+ ### Core principle
99
+
100
+ The model reacts to what can be **seen and measured**, not to mood words. Translate abstractions into observables.
101
+
102
+ - ❌ "tense scene" → ✅ "man freezes, slowly clenches his fist, light only from the side, half his face in shadow"
103
+ - ❌ "cool cinematic shot of a car, epic, fast" → ✅ "low tracking shot alongside the car as it powers through a wet curve, headlights glowing, spray off the tyres, hard buffeting camera shake"
104
+
105
+ ### Style — DISTRIBUTED, not a prefix
106
+
107
+ Never pile all style tokens at the top of the prompt. Each aspect lives in the block that already governs it:
108
+
109
+ - Lighting → inside the shot's LIGHTING description
110
+ - Lens / FOV → in OPTICS
111
+ - Color → either an explicit grade (when strong / stylized) or folded into LOCATION + LIGHTING for naturalistic looks
112
+ - Skin / acting → in PERFORMANCE
113
+ - Physics → in PHYSICS
114
+ - Format / resolution / grain → at the END as a suffix stack (before LOCKS)
115
+
116
+ ### Shot sizes
117
+
118
+ | Abbr | Meaning | In frame |
119
+ |------|---------|----------|
120
+ | ECU | Extreme Close-Up | a detail: eyes, button, headlight, hand |
121
+ | CU | Close-Up | full face / one element large |
122
+ | MCU | Medium Close-Up | head and shoulders |
123
+ | MS | Medium Shot | roughly to the waist |
124
+ | WS | Wide Shot | full figure + surroundings |
125
+ | EWS | Extreme Wide | scale, location |
126
+
127
+ ### FOV anchor table (degrees — what to write in the prompt)
128
+
129
+ | FOV | mm equiv | Purpose |
130
+ |-----|----------|---------|
131
+ | 180° | Fisheye | spherical distortion |
132
+ | 107° | 14–16mm | architectural ultra-wide |
133
+ | 84° | 20–24mm | wide |
134
+ | 63° | 28–35mm | observational |
135
+ | 47° | 40–50mm | neutral human perspective |
136
+ | 29° | 75–85mm | portrait compression |
137
+ | 18° | 100–135mm | natural portrait |
138
+ | 12° | 180–200mm | tele-detail |
139
+ | 8° | 300–400mm | extreme compression |
140
+
141
+ Use only the discrete steps. Not "23°" — use 18° or 29°.
142
+
143
+ ### Prompting rules
144
+
145
+ - **Positive only.** ❌ "does not fall backward" → ✅ "stays upright, feet planted."
146
+ - **Speeds in km/h.** ❌ "fast/slow" → ✅ "moves at 40 km/h", "camera pans at 5 km/h."
147
+ - **Atmosphere in % / meters.** ❌ "light fog" → ✅ "fog density 40%", "haze visible at 15 meters depth."
148
+ - **Atmosphere builds in steps across shots.** Shot 1: 20% → Shot 2: 40% → Shot 3: 60%.
149
+ - **Giant scale via human-height.** ❌ "huge, three meters tall" → ✅ "stands as tall as four humans stacked."
150
+ - **Left/right is from the camera.** "Subject moves left" = left from the camera's view.
151
+ - **Emotion through muscle movement**, not labels. ❌ "she looks sad" → ✅ "her eyes drop to the table, jaw tightens, she swallows once before answering."
152
+ - **WB in Kelvin.** 3200K / 4000K / 5600K / 8500K. Pick ONE for the scene's mood.
153
+ - **Color as material + light + role**, never a flat list. ❌ "she wears red, he wears blue" → ✅ "crimson silk scarf catching the cold tungsten spill from the corridor".
154
+ - **No equipment names**, no director references, no "shot on ARRI / Sigma 85mm / Roger Deakins".
155
+
156
+ ### Cuts and timing
157
+
158
+ - **Single continuous shot (oner)** → "one continuous shot, the camera does not cut on its own."
159
+ - **Sequential cuts, no timecodes** → "CUT 1 … CUT 2 … CUT 3".
160
+ - **Timed multishot** → explicit HARD CUTs at stated seconds, with timecode blocks `0.0s to 1.0s — [description]`.
161
+ - **Mixed real-time + slow-mo** → hard cuts only between speed modes. Each shot one speed start to finish.
162
+
163
+ ### Special protocols
164
+
165
+ - **4-mechanism multishot consistency stack** (extreme FOV: 8°, 107°): (1) sequence-wide identity lock, (2) LENS LOCK opener per beat, (3) LENS CHECK closer per beat, (4) color via material + light, not as a list. All four required.
166
+ - **Whip-pan timing:** 0.3s Subject A settled → 0.8s WHIP motion-blur → 1.4s Subject B settled. Whip under 0.8s renders as a hard cut without blur.
167
+ - **Anti-impact lock** (cracks/breaks without impact): "crowd PRESSES, not strikes", "fracture originates from edge stress, not center impact", "no impact point — pressure-based crack."
168
+
169
+ ### Optical techniques
170
+
171
+ - **Observation pattern (hidden-camera):** foreground occlusion 20–30% + atmospheric haze + 8°–12° super-tele vantage.
172
+ - **Sports broadcast:** 8° super-tele + handheld 1–2cm tremor + "anchored at distance, finding the action".
173
+ - **Tele compressed air column** at 8°–12°: "dust suspended in the long compressed air column between camera and subject".
174
+
175
+ ### Camera placement
176
+
177
+ Place CAMERA in the **3rd position** of each shot's core layers (Subject → Action → Camera → Style → Constraints). FOV gets ignored at the end, conflicts with identity at the front.
178
+
179
+ ### Pre-flight checklist (before output)
180
+
181
+ - Distributed style (no top-pile)?
182
+ - One camera movement per time slice?
183
+ - FOV in degrees from the table (not mm, not arbitrary)?
184
+ - WB in Kelvin?
185
+ - Speed in km/h, atmosphere in % or meters?
186
+ - Color via material + light + role?
187
+ - Positive phrasing (no "does not X")?
188
+ - No equipment / director names?
189
+ - Emotion through muscle, not labels?
190
+ - Multishot: FOV per segment + "no drift mid-segment"?
191
+ - 8000-char cap honored?
192
+
63
193
  ## Grid Storyboard Mode (3×3 grid input)
64
194
 
65
195
  When the user uploads a 3×3 grid image and asks for Seedance prompts, switch to this mode:
@@ -80,11 +210,20 @@ When the user uploads a 3×3 grid image and asks for Seedance prompts, switch to
80
210
 
81
211
  ## Output Discipline
82
212
 
83
- - Final prompt(s) ALWAYS in a fenced code block ready to paste into the Seedance `prompt` field (or pass as `prompt` on `generate_video` / `generate_elements`).
213
+ - Final prompt(s) ALWAYS in a fenced code block ready to paste into Seedance.
84
214
  - After the code block, give a 1-line "why this works" note (camera/escalation/physics choice).
85
215
  - If user asked in any language other than English, write your explanation in their language but keep the prompt itself English.
86
- - **Never exceed 8000 characters TOTAL** for the entire prompt as one string — that is the WHOLE prompt including every shot, every line of boilerplate, every SFX list, every newline. NOT 8000 per shot — 8000 for the prompt as one combined unit. Count before output. If over, rewrite tighter (cut adjectives, collapse boilerplate, merge or drop shots). NEVER split into multiple prompts / multiple code blocks / "part 1 / part 2" to work around the limit.
216
+ - **Never exceed 8000 characters TOTAL for the entire prompt as one string** — that is the WHOLE prompt including every shot, every line of boilerplate, every SFX list, every newline. NOT 8000 per shot — 8000 for the prompt as one combined unit. Count before output. If over, rewrite tighter (cut adjectives, collapse boilerplate, merge or drop shots). NEVER split into multiple prompts / multiple code blocks / "part 1 / part 2" to work around the limit.
217
+
218
+ ## Where to run in Kolbo
219
+
220
+ Seedance 2 lives in the **Video** category. Route the prompt card by the INPUTS:
221
+
222
+ - **First & Last Frame** (`first_last_frame` tag) when the video must begin on one frame and end on another (start + end image, morph A→B). This wins even if Visual DNAs / characters / elements are referenced inside it — First-Last-Frame supports DNAs/elements too.
223
+ - **Elements** (`elements` tag) when the scene is built from reference assets — a Visual DNA / character (`@name`), a moodboard (`#name`), or reference images composed into a NEW scene, with no explicit start+end frame. This is the default for any "@Character does X" / loopable-idle / new-scene-from-my-refs request.
224
+ - **Image-to-Video** (`image_to_video` tag) only when a single existing image is animated as-is.
225
+ - **Text-to-Video** (`text_to_video` tag) only when there is no reference image or character at all.
87
226
 
88
227
  ## Seedance + Visual DNA / References
89
228
 
90
- When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). Tag the DNA inside the prompt with `@<dna-name>` — see `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`.
229
+ When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). Tag the DNA inside the prompt with `@<dna-name>` — see `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`.
@@ -0,0 +1,85 @@
1
+ # Voice / Text-to-Speech (`generate_speech`) — full style & option reference
2
+
3
+ `generate_speech` turns text into spoken audio. Every voice belongs to a
4
+ **provider** (ElevenLabs, DeepDub, MiniMax, Google/Gemini, OpenAI, Zonos). Each
5
+ provider exposes its own expressive controls. You may pass any control on any
6
+ call — **the engine silently ignores controls that don't apply to the chosen
7
+ voice's provider**, so you never need to branch on provider yourself.
8
+
9
+ ## Pick the voice first
10
+ Call `list_voices` (filter by `provider`, `language`, `gender`) and pass the
11
+ returned `voice_id` — or a display name like `"Rachel"`. Cloned/custom voices
12
+ resolve by name too. The voice determines the provider, which determines which
13
+ controls below take effect.
14
+
15
+ ## Core params (all providers)
16
+ | Param | Type | Notes |
17
+ |---|---|---|
18
+ | `text` | string (required) | The words to speak. |
19
+ | `voice` | string | Voice id or display name. Default `"Rachel"`. |
20
+ | `model` | string | From `list_models type="text_to_speech"`. Default `eleven_v3`. Usually inferred from the voice — only needed to force a specific engine. |
21
+ | `language` | string | BCP-47 code, e.g. `"en-US"`, `"he-IL"`, `"es-ES"`. |
22
+ | `speaking_speed` | number | `0.5` (slow) – `2.0` (fast). Default `1.0`. Applies to ElevenLabs / OpenAI / Google. |
23
+ | `project_id` | string | Scope into a project (see Projects rules). |
24
+
25
+ ## Expressive style / emotion (provider-specific)
26
+ | Param | Provider(s) | Values / notes |
27
+ |---|---|---|
28
+ | `style_instructions` | **Google / Gemini** | Free-form natural-language direction, e.g. `"whisper conspiratorially, slightly amused"`, `"excited sports announcer"`. Max 500 chars. |
29
+ | `selected_style` | **DeepDub**, MiniMax | Preset style. DeepDub: `reading`, `conversational`, `angry`, `breathy`, `panic`, `amused`, `sad`, `whisper`, `singing`, `shout`, `scream`, `mumbling`, `excited`. |
30
+ | `emotion` | **MiniMax** | `happy`, `sad`, `angry`, `fearful`, `disgusted`, `surprised`, `calm`, `fluent`, `whisper`. |
31
+
32
+ ## ElevenLabs voice settings
33
+ | Param | Range | Default | Effect |
34
+ |---|---|---|---|
35
+ | `similarity_boost` | 0–1 | 0.75 | Higher hews closer to the source voice. |
36
+ | `style` | 0–1 | 0.5 | Style exaggeration — higher is more expressive/dramatic. |
37
+ | `use_speaker_boost` | bool | true | Speaker-clarity boost. |
38
+
39
+ ## DeepDub controls
40
+ | Param | Range | Default | Effect |
41
+ |---|---|---|---|
42
+ | `variance` | 0–1 | 0.2 | More variation / takes. |
43
+ | `tempo` | 0–2 | 1.0 | Pacing multiplier. |
44
+ | `promptBoost` | bool | true | Higher fidelity to the text. |
45
+ | `seed` | int | — | Reproducibility (same seed + inputs → same output). Also honored by Zonos. |
46
+ | `accentControl` | object | — | `{ accentBaseLocale, accentLocale, accentRatio }` — blend an accent. Provide BOTH `accentBaseLocale` (e.g. `"en-US"`) and `accentLocale` (e.g. `"en-GB"`); `accentRatio` 0–1 (default 0.5). |
47
+ | `voiceTitle` | string | — | Display title for a custom/cloned voice. |
48
+
49
+ ## MiniMax fine controls
50
+ | Param | Range | Default | Effect |
51
+ |---|---|---|---|
52
+ | `minimax_pitch` | −12 … 12 | 0 | Pitch shift. |
53
+ | `minimax_vol` | 0–10 | 1 | Volume. |
54
+ | `minimax_intensity` | — | — | Voice intensity. |
55
+ | `minimax_timbre` | — | — | Voice timbre. |
56
+
57
+ ## Examples
58
+ Neutral ElevenLabs read:
59
+ ```
60
+ generate_speech(text="Welcome to Kolbo.", voice="Rachel")
61
+ ```
62
+ Whispered, conspiratorial Gemini delivery:
63
+ ```
64
+ generate_speech(text="Meet me at midnight.", voice="Kore",
65
+ style_instructions="whisper conspiratorially, slow and breathy")
66
+ ```
67
+ Angry DeepDub take, faster:
68
+ ```
69
+ generate_speech(text="Get out of my house!", voice="<deepdub voice>",
70
+ selected_style="angry", tempo=1.2)
71
+ ```
72
+ Excited MiniMax with pitch/volume tweaks:
73
+ ```
74
+ generate_speech(text="We won the championship!", voice="<minimax voice>",
75
+ emotion="happy", minimax_pitch=3, minimax_vol=6)
76
+ ```
77
+ British-accented DeepDub blend:
78
+ ```
79
+ generate_speech(text="Good evening.", voice="<deepdub voice>",
80
+ accentControl={ accentBaseLocale: "en-US", accentLocale: "en-GB", accentRatio: 0.7 })
81
+ ```
82
+
83
+ ## Credits
84
+ ~5 credits per 100 characters for most TTS models (Zonos ~3; voice design/clone
85
+ ~30 flat). Charged only on success. Use `check_credits` once per conversation.
@@ -391,22 +391,36 @@ function registerGenerateTools(server, client, options = {}) {
391
391
  // ─── generate_music ────────────────────────────────────────
392
392
  server.tool(
393
393
  'generate_music',
394
- 'Generate music from a text description using Kolbo AI. Supports instrumental mode, custom lyrics, style direction, and vocal gender. Default model is Suno. Returns the final audio URL when complete.',
394
+ 'Generate music from a text description using Kolbo AI. Supports instrumental mode, custom lyrics, style direction, vocal gender, negative tags, song length, and Suno fine-controls (style weight, weirdness, audio weight, persona/singing voice). Default model is Suno. Some controls are Suno-only; the engine ignores controls that do not apply to the chosen model. Returns the final audio URL when complete.',
395
395
  {
396
396
  prompt: z.string().describe('Text description of the music to generate (e.g., "upbeat electronic dance track with synthesizers")'),
397
397
  model: z.string().optional().describe('Model identifier. Use list_models type="music_gen" to see options. Omit for Suno (default).'),
398
398
  style: z.string().optional().describe('Music style / genre (e.g., "pop", "rock", "lo-fi", "electronic", "jazz")'),
399
+ title: z.string().optional().describe('Song title. If omitted, one is generated.'),
399
400
  instrumental: z.boolean().optional().describe('Generate instrumental only, no vocals. Default: false'),
400
401
  lyrics: z.string().optional().describe('Custom lyrics for the song. If omitted, lyrics are generated automatically from the prompt unless instrumental is true.'),
401
402
  vocal_gender: z.string().optional().describe('Preferred vocal gender: "male" or "female". Only applies when instrumental is false.'),
403
+ negative_tags: z.string().optional().describe('Styles / sounds to EXCLUDE, comma-separated (e.g. "heavy metal, screaming, distortion"). Suno.'),
404
+ duration_seconds: z.number().optional().describe('Target song length in seconds (length-capable models like ElevenLabs Music). Clamped 5–300. Omit for the model default.'),
402
405
  enhance_prompt: z.boolean().optional().describe('Enhance the prompt. Default: true'),
403
406
  preset_id: z.string().optional().describe('Preset ID from list_presets type="music" to apply a saved music style preset.'),
407
+ // ── Suno fine controls ──
408
+ style_weight: z.number().optional().describe('Suno: how strongly the style/genre is applied, 0–1.'),
409
+ weirdness: z.number().optional().describe('Suno: creativity / weirdness constraint, 0–1. Higher = more experimental.'),
410
+ audio_weight: z.number().optional().describe('Suno: influence of an audio/persona reference, 0–1.'),
411
+ persona_id: z.string().optional().describe('Suno persona id — reuse a saved singing voice/persona.'),
412
+ use_composition_plan: z.boolean().optional().describe('Suno: enable structured composition planning (verse/chorus structure).'),
413
+ singing_dna_id: z.string().optional().describe('Visual DNA character id whose singing voice to use (must be owned by the caller).'),
414
+ singing_voice_id: z.string().optional().describe('Custom cloned singing-voice id (must be owned by the caller).'),
404
415
  project_id: projectIdField
405
416
  },
406
- async ({ prompt, model, style, instrumental, lyrics, vocal_gender, enhance_prompt, preset_id, project_id }) => {
417
+ async ({ prompt, model, style, title, instrumental, lyrics, vocal_gender, negative_tags, duration_seconds, enhance_prompt, preset_id, style_weight, weirdness, audio_weight, persona_id, use_composition_plan, singing_dna_id, singing_voice_id, project_id }) => {
407
418
  model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
408
419
  const gen = await client.post('/v1/generate/music', {
409
- prompt, model, style, instrumental, lyrics, vocal_gender, enhance_prompt, preset_id, project_id
420
+ prompt, model, style, title, instrumental, lyrics, vocal_gender, negative_tags,
421
+ duration_seconds, enhance_prompt, preset_id,
422
+ style_weight, weirdness, audio_weight, persona_id, use_composition_plan,
423
+ singing_dna_id, singing_voice_id, project_id
410
424
  });
411
425
 
412
426
  if (ui()) return uiGenerating({
@@ -437,23 +451,53 @@ function registerGenerateTools(server, client, options = {}) {
437
451
  // ─── generate_speech ───────────────────────────────────────
438
452
  server.tool(
439
453
  'generate_speech',
440
- 'Convert text to speech using Kolbo AI. Default provider is ElevenLabs. To pick a specific voice by language/gender, call list_voices first and pass the returned voice_id (or a voice display name — both work). Returns the final audio URL when complete.',
454
+ 'Convert text to speech using Kolbo AI. Default provider is ElevenLabs. To pick a specific voice by language/gender, call list_voices first and pass the returned voice_id (or a voice display name — both work). Every voice belongs to a provider (ElevenLabs, DeepDub, MiniMax, Google/Gemini, OpenAI, Zonos) and each provider exposes its own expressive/style controls below — the engine ignores any control that does not apply to the chosen voice\'s provider, so it is safe to pass only what you need. Returns the final audio URL when complete.',
441
455
  {
442
456
  text: z.string().describe('The text to convert to speech'),
443
457
  voice: z.string().optional().describe('Voice ID (from list_voices) or voice display name (e.g., "Rachel", "Adam"). Default: "Rachel"'),
444
458
  model: z.string().optional().describe('Model identifier. Use list_models type="text_to_speech" to see options. Default: eleven_v3'),
445
459
  language: z.string().optional().describe('Language code (e.g., "en-US", "he-IL", "es-ES"). Default: "en-US"'),
460
+ // ── Expressive style / emotion (provider-specific) ──
461
+ style_instructions: z.string().optional().describe('Google/Gemini voices ONLY. Free-form natural-language voice direction, e.g. "whisper conspiratorially, slightly amused" or "excited sports announcer". Max 500 chars. Ignored by other providers.'),
462
+ selected_style: z.string().optional().describe('DeepDub & MiniMax voices. Preset expressive style/emotion. DeepDub supports: reading, conversational, angry, breathy, panic, amused, sad, whisper, singing, shout, scream, mumbling, excited. Ignored by other providers.'),
463
+ emotion: z.string().optional().describe('MiniMax voices. Emotion: happy, sad, angry, fearful, disgusted, surprised, calm, fluent, whisper.'),
464
+ speaking_speed: z.number().optional().describe('Speech speed 0.5 (slow) – 2.0 (fast). Default 1.0. Applies to ElevenLabs / OpenAI / Google.'),
465
+ // ── ElevenLabs voice settings ──
466
+ similarity_boost: z.number().optional().describe('ElevenLabs voice similarity, 0–1. Default 0.75. Higher hews closer to the original voice.'),
467
+ style: z.number().optional().describe('ElevenLabs style exaggeration, 0–1. Default 0.5. Higher = more expressive/dramatic.'),
468
+ use_speaker_boost: z.boolean().optional().describe('ElevenLabs speaker boost. Default true.'),
469
+ // ── DeepDub controls ──
470
+ variance: z.number().optional().describe('DeepDub voice variance, 0–1. Default 0.2. Higher = more takes/variation.'),
471
+ tempo: z.number().optional().describe('DeepDub tempo multiplier, 0–2. Default 1.0.'),
472
+ promptBoost: z.boolean().optional().describe('DeepDub prompt-fidelity boost. Default true.'),
473
+ seed: z.number().optional().describe('Reproducibility seed (DeepDub / Zonos). Same seed + inputs → same output.'),
474
+ accentControl: z.object({
475
+ accentBaseLocale: z.string().describe('Base accent locale, e.g. "en-US".'),
476
+ accentLocale: z.string().describe('Target accent locale, e.g. "en-GB".'),
477
+ accentRatio: z.number().optional().describe('Blend ratio 0–1. Default 0.5.')
478
+ }).optional().describe('DeepDub accent steering. Provide both base and target locale to blend an accent.'),
479
+ voiceTitle: z.string().optional().describe('DeepDub display title for a custom/cloned voice.'),
480
+ // ── MiniMax fine controls ──
481
+ minimax_pitch: z.number().optional().describe('MiniMax pitch, −12 to 12. Default 0.'),
482
+ minimax_vol: z.number().optional().describe('MiniMax volume, 0–10. Default 1.'),
483
+ minimax_intensity: z.number().optional().describe('MiniMax voice intensity.'),
484
+ minimax_timbre: z.number().optional().describe('MiniMax voice timbre.'),
446
485
  project_id: projectIdField
447
486
  },
448
- async ({ text, voice, model, language, project_id }) => {
487
+ async ({ text, voice, model, language, style_instructions, selected_style, emotion, speaking_speed, similarity_boost, style, use_speaker_boost, variance, tempo, promptBoost, seed, accentControl, voiceTitle, minimax_pitch, minimax_vol, minimax_intensity, minimax_timbre, project_id }) => {
449
488
  model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
450
489
  const gen = await client.post('/v1/generate/speech', {
451
- text, voice, model, language, project_id
490
+ text, voice, model, language,
491
+ style_instructions, selected_style, emotion, speaking_speed,
492
+ similarity_boost, style, use_speaker_boost,
493
+ variance, tempo, promptBoost, seed, accentControl, voiceTitle,
494
+ minimax_pitch, minimax_vol, minimax_intensity, minimax_timbre,
495
+ project_id
452
496
  });
453
497
 
454
498
  if (ui()) return uiGenerating({
455
499
  tool: 'generate_speech', kind: 'audio', gen, client, model, prompt: text,
456
- settings: { voice: voice || 'Rachel' }
500
+ settings: { voice: voice || 'Rachel', style: selected_style || emotion || style_instructions }
457
501
  });
458
502
 
459
503
  const result = await pollUntilDone(client, gen.generation_id, {
@@ -478,18 +522,34 @@ function registerGenerateTools(server, client, options = {}) {
478
522
  // ─── generate_sound ────────────────────────────────────────
479
523
  server.tool(
480
524
  'generate_sound',
481
- 'Generate sound effects (not music, not speech) from a text description using Kolbo AI. Use this for ambient sounds, foley, impacts, atmospheres, UI sounds, etc. For music use generate_music; for voice use generate_speech. Returns the final audio URL when complete.',
525
+ 'Generate sound effects (not music, not speech) from a text description using Kolbo AI. Use this for ambient sounds, foley, impacts, atmospheres, UI sounds, etc. For music use generate_music; for voice use generate_speech. Beyond the core prompt/duration, per-provider controls are available (Stable Audio guidance, Kie loop/tempo/key, Seed-Audio voice/speed/volume/pitch + reference audio/image); the engine ignores controls that do not apply to the chosen model. Returns the final audio URL when complete.',
482
526
  {
483
527
  prompt: z.string().describe('Text description of the sound effect (e.g., "thunder clap with rain", "door creaking open", "futuristic UI beep")'),
484
528
  model: z.string().optional().describe('Model identifier. Use list_models type="text_to_sound" to see options. Default: elevenlabs-sound-effects-v1'),
485
529
  duration: z.number().optional().describe('Duration in seconds. Omit for automatic duration.'),
486
- prompt_influence: z.number().optional().describe('How strongly the prompt guides the generation (0–1). Default: 0.5. Lower values give the model more creative freedom; higher values follow the prompt more literally.'),
530
+ prompt_influence: z.number().optional().describe('ElevenLabs: how strongly the prompt guides the generation (0–1). Default: 0.5. Lower = more creative freedom; higher = more literal.'),
531
+ // ── FAL Stable Audio / mmaudio ──
532
+ cfg_strength: z.number().optional().describe('FAL (Stable Audio 3 / mmaudio): classifier-free guidance strength. Higher hews closer to the prompt.'),
533
+ // ── Kie ──
534
+ sound_loop: z.boolean().optional().describe('Kie: generate a seamlessly looping sound.'),
535
+ sound_tempo: z.number().optional().describe('Kie: tempo control.'),
536
+ sound_key: z.string().optional().describe('Kie: musical key / scale.'),
537
+ // ── FAL Seed Audio ──
538
+ seed_voice: z.string().optional().describe('FAL Seed-Audio: voice to use.'),
539
+ seed_speed: z.number().optional().describe('FAL Seed-Audio: speed multiplier, 0.5–2.0.'),
540
+ seed_volume: z.number().optional().describe('FAL Seed-Audio: volume, 0–1.'),
541
+ seed_pitch: z.number().optional().describe('FAL Seed-Audio: pitch shift in semitones.'),
542
+ seed_reference_audio_urls: z.array(z.string()).optional().describe('FAL Seed-Audio: up to 3 reference audio URLs to condition the sound.'),
543
+ seed_reference_image_url: z.string().optional().describe('FAL Seed-Audio: a reference image URL to condition the sound.'),
487
544
  project_id: projectIdField
488
545
  },
489
- async ({ prompt, model, duration, prompt_influence, project_id }) => {
546
+ async ({ prompt, model, duration, prompt_influence, cfg_strength, sound_loop, sound_tempo, sound_key, seed_voice, seed_speed, seed_volume, seed_pitch, seed_reference_audio_urls, seed_reference_image_url, project_id }) => {
490
547
  model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
491
548
  const gen = await client.post('/v1/generate/sound', {
492
- prompt, model, duration, prompt_influence, project_id
549
+ prompt, model, duration, prompt_influence,
550
+ cfg_strength, sound_loop, sound_tempo, sound_key,
551
+ seed_voice, seed_speed, seed_volume, seed_pitch,
552
+ seed_reference_audio_urls, seed_reference_image_url, project_id
493
553
  });
494
554
 
495
555
  if (ui()) return uiGenerating({
@@ -963,23 +1023,39 @@ function registerGenerateTools(server, client, options = {}) {
963
1023
  // ─── transcribe_audio ──────────────────────────────────────
964
1024
  server.tool(
965
1025
  'transcribe_audio',
966
- 'Transcribe audio or video into text + SRT subtitles. Source can be a URL or an absolute local file path. Returns the full text, SRT content, duration, and download URLs for .srt/.txt files. Works on both audio-only files (mp3, wav, m4a) and videos with audio tracks (mp4, mov, webm).',
1026
+ 'Transcribe audio or video into text + SRT subtitles. Source can be a URL or an absolute local file path. Returns the full text, SRT content, duration, and download URLs for .srt/.txt files. Works on both audio-only files (mp3, wav, m4a) and videos with audio tracks (mp4, mov, webm). Supports language selection, speaker diarization, audio-event tagging, and SRT subtitle formatting controls.',
967
1027
  {
968
1028
  source: z.string().describe('URL or absolute local path to the audio / video file to transcribe'),
1029
+ language: z.string().optional().describe('Language code of the speech (e.g. "en", "he", "es"). Omit to auto-detect.'),
1030
+ diarize: z.boolean().optional().describe('Detect and label distinct speakers. Default: false.'),
1031
+ tag_audio_events: z.boolean().optional().describe('Tag non-speech audio events (laughter, applause, music) in the transcript. Default: false.'),
1032
+ remove_punctuation: z.boolean().optional().describe('Strip punctuation from the transcript. Default: false.'),
1033
+ generate_srt: z.boolean().optional().describe('Produce SRT + word-by-word SRT subtitle files. Default: true.'),
1034
+ words_per_line: z.number().optional().describe('SRT: max words per subtitle line, 1–18. Default: 12.'),
1035
+ lines_per_subtitle: z.number().optional().describe('SRT: max lines per subtitle cue, 1–4. Default: 2.'),
1036
+ stretch_captions: z.boolean().optional().describe('SRT: extend each cue\'s end time to the next cue\'s start (gap-free subtitles). Default: true.'),
969
1037
  project_id: projectIdField
970
1038
  },
971
- async ({ source, project_id }) => {
1039
+ async ({ source, language, diarize, tag_audio_events, remove_punctuation, generate_srt, words_per_line, lines_per_subtitle, stretch_captions, project_id }) => {
972
1040
  if (!source) throw new Error('source is required (URL or absolute local path)');
973
1041
 
1042
+ // Advanced transcription controls forwarded when provided (undefined keys are dropped by the client).
1043
+ const opts = {
1044
+ language, diarize, tag_audio_events, remove_punctuation,
1045
+ generate_srt, words_per_line, lines_per_subtitle, stretch_captions, project_id
1046
+ };
1047
+
974
1048
  const isUrl = /^https?:\/\//i.test(source);
975
1049
  let startResponse;
976
1050
  if (isUrl) {
977
- startResponse = await client.post('/v1/transcribe', { audio_url: source, project_id });
1051
+ startResponse = await client.post('/v1/transcribe', { audio_url: source, ...opts });
978
1052
  } else {
979
1053
  const resolved = await resolveToBuffer(source, 'audio');
980
1054
  const form = new FormData();
981
1055
  form.append('file', resolved.buffer, { filename: resolved.filename, contentType: resolved.contentType });
982
- if (project_id) form.append('project_id', project_id);
1056
+ for (const [k, v] of Object.entries(opts)) {
1057
+ if (v !== undefined && v !== null) form.append(k, typeof v === 'boolean' ? String(v) : v);
1058
+ }
983
1059
  startResponse = await client.postMultipart('/v1/transcribe', form);
984
1060
  }
985
1061
 
@@ -20,7 +20,7 @@ function registerVisualDnaTools(server, client, options = {}) {
20
20
  // ─── create_visual_dna ─────────────────────────────────────
21
21
  server.tool(
22
22
  'create_visual_dna',
23
- 'Create a Visual DNA profile from reference media. Each item in images/video/audio can be a public URL or an absolute local file path. Max 4 images, 1 video, 1 audio. Files capped at 25MB each. For CHARACTER DNAs, a multi-angle character sheet dramatically improves consistency — offer to generate one with `generate_character_sheet` first, then pass its URL as `character_sheet_url` here (see that tool).',
23
+ 'Create a Visual DNA profile from reference media. Each item in images/video/audio can be a public URL or an absolute local file path. Max 4 images, 1 video, 1 audio. Files capped at 25MB each. For EVERY DNA type, a reference sheet dramatically improves consistency (character turnaround / product details / location angles / style board) — offer to generate one with `generate_character_sheet` (matching `sheet_type`) first, then pass its URL as `character_sheet_url` here (see that tool).',
24
24
  {
25
25
  name: z.string().describe('Name of the Visual DNA profile. **Pick a short, lowercase, no-space single token** (e.g. `maya`, `tokyo_neon`, `brand_red`, `esther_model`) — never names with spaces (`Sarah Johnson` ❌). The user/LLM types this as `@<name>` inside generation prompts, and the @ parser stops at the first space, so `@Sarah Johnson` matches only `Sarah` and the binding silently drops. Multi-word concepts should use underscores or be a single token. Names are case-insensitive on lookup, but **reserved** values rejected on creation: `Image1`, `Image2`, …, `Video1`, …, `Audio1`, … (any-language characters allowed; max 100 chars).'),
26
26
  dna_type: z.string().optional().describe('Type: "character", "style", "product", "scene", "environment". Default: "character"'),
@@ -28,7 +28,7 @@ function registerVisualDnaTools(server, client, options = {}) {
28
28
  images: z.array(z.string()).optional().describe('Array of image sources (URLs or absolute local paths). Max 4.'),
29
29
  video: z.string().optional().describe('Optional video source (URL or absolute local path)'),
30
30
  audio: z.string().optional().describe('Optional audio source (URL or absolute local path)'),
31
- character_sheet_url: z.string().optional().describe('URL of a multi-angle character sheet (from `generate_character_sheet`) to set as the DNA\'s primary reference. Strongly recommended for character DNAsit is the single biggest consistency booster. Omit for non-character DNAs or when the user declines.')
31
+ character_sheet_url: z.string().optional().describe('URL of a reference sheet (from `generate_character_sheet`, any sheet_type) to set as the DNA\'s primary reference. Works for ALL DNA types — character turnaround, product detail sheet, location sheet, or style board and is the single biggest consistency booster. Omit only when the user declines.')
32
32
  },
33
33
  async ({ name, dna_type, prompt_helper, images, video, audio, character_sheet_url }) => {
34
34
  if (!name || !name.trim()) {
@@ -164,12 +164,13 @@ function registerVisualDnaTools(server, client, options = {}) {
164
164
  // ─── generate_character_sheet ──────────────────────────────
165
165
  server.tool(
166
166
  'generate_character_sheet',
167
- 'Generate a multi-angle character sheet (turnaround) from 1+ reference image URLs — the same step the in-app Visual DNA wizard offers. The sheet is the single strongest consistency booster for a character DNA. CHARGES CREDITS, so when the user is about to create a character DNA, OFFER this first ("want me to generate a character 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`.',
167
+ '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`.',
168
168
  {
169
- image_urls: z.array(z.string()).min(1).describe('Reference image URLs of the character (front/side/varied angles work best). Use generated-image URLs or upload_media output.')
169
+ 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.'),
170
+ sheet_type: z.enum(['character', 'product', 'environment', 'style']).optional().describe('Which sheet layout to generate — match the DNA type it will be attached to. Defaults to character.')
170
171
  },
171
- async ({ image_urls }) => {
172
- const result = await client.post('/v1/visual-dna/character-sheet', { image_urls });
172
+ async ({ image_urls, sheet_type }) => {
173
+ const result = await client.post('/v1/visual-dna/character-sheet', { image_urls, ...(sheet_type ? { sheet_type } : {}) });
173
174
  return {
174
175
  content: [{
175
176
  type: 'text',