@kolbo/mcp 1.75.7 → 1.76.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/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "@kolbo/mcp",
3
- "version": "1.75.7",
4
- "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
- "main": "src/index.js",
6
- "bin": {
7
- "kolbo-mcp": "./bin/kolbo-mcp.js"
8
- },
9
- "scripts": {
10
- "start": "node src/index.js",
11
- "smoke": "node scripts/smoke.js",
12
- "check-skill-bundle": "node scripts/check-skill-bundle.js",
13
- "check-parity": "node scripts/check-parity.js",
14
- "prepublishOnly": "node scripts/smoke.js && node scripts/check-skill-bundle.js && node scripts/check-parity.js && node scripts/check-widget-fields.js && node scripts/check-widget-render.js && node scripts/check-model-catalog.js && node scripts/check-skill-tools.js && node scripts/check-submission-contract.js && node scripts/check-install.js",
15
- "check-model-catalog": "node scripts/check-model-catalog.js",
16
- "check-widget-fields": "node scripts/check-widget-fields.js",
17
- "check-widget-render": "node scripts/check-widget-render.js",
18
- "check-skill-tools": "node scripts/check-skill-tools.js",
19
- "check-submission-contract": "node scripts/check-submission-contract.js",
20
- "generate-chatgpt-submission": "node scripts/generate-chatgpt-submission.js",
21
- "check-install": "node scripts/check-install.js"
22
- },
23
- "keywords": [
24
- "kolbo",
25
- "mcp",
26
- "ai",
27
- "image-generation",
28
- "video-generation",
29
- "music-generation",
30
- "text-to-speech",
31
- "claude-code",
32
- "claude-desktop",
33
- "model-context-protocol"
34
- ],
35
- "license": "MIT",
36
- "repository": {
37
- "type": "git",
38
- "url": "https://github.com/Zoharvan12/kolbo-mcp"
39
- },
40
- "homepage": "https://docs.kolbo.ai/developer-api/claude-code-skill",
41
- "author": "Kolbo AI <support@kolbo.ai>",
42
- "publishConfig": {
43
- "access": "public"
44
- },
45
- "files": [
46
- "src/",
47
- "bin/",
48
- "skill/",
49
- "README.md"
50
- ],
51
- "dependencies": {
52
- "@modelcontextprotocol/ext-apps": "^1.7.4",
53
- "@modelcontextprotocol/sdk": "1.29.0",
54
- "form-data": "^4.0.6",
55
- "zod": "^3.25.0"
56
- },
57
- "overrides": {
58
- "hono": "^4.12.12",
59
- "@hono/node-server": "^1.19.13",
60
- "path-to-regexp": "^8.4.2"
61
- },
62
- "engines": {
63
- "node": ">=18.0.0"
64
- }
65
- }
1
+ {
2
+ "name": "@kolbo/mcp",
3
+ "version": "1.76.0",
4
+ "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "kolbo-mcp": "./bin/kolbo-mcp.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node src/index.js",
11
+ "smoke": "node scripts/smoke.js",
12
+ "check-skill-bundle": "node scripts/check-skill-bundle.js",
13
+ "check-parity": "node scripts/check-parity.js",
14
+ "prepublishOnly": "node scripts/smoke.js && node scripts/check-skill-bundle.js && node scripts/check-parity.js && node scripts/check-widget-fields.js && node scripts/check-widget-render.js && node scripts/check-model-catalog.js && node scripts/check-skill-tools.js && node scripts/check-submission-contract.js && node scripts/check-install.js",
15
+ "check-model-catalog": "node scripts/check-model-catalog.js",
16
+ "check-widget-fields": "node scripts/check-widget-fields.js",
17
+ "check-widget-render": "node scripts/check-widget-render.js",
18
+ "check-skill-tools": "node scripts/check-skill-tools.js",
19
+ "check-submission-contract": "node scripts/check-submission-contract.js",
20
+ "generate-chatgpt-submission": "node scripts/generate-chatgpt-submission.js",
21
+ "check-install": "node scripts/check-install.js"
22
+ },
23
+ "keywords": [
24
+ "kolbo",
25
+ "mcp",
26
+ "ai",
27
+ "image-generation",
28
+ "video-generation",
29
+ "music-generation",
30
+ "text-to-speech",
31
+ "claude-code",
32
+ "claude-desktop",
33
+ "model-context-protocol"
34
+ ],
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/Zoharvan12/kolbo-mcp"
39
+ },
40
+ "homepage": "https://docs.kolbo.ai/developer-api/claude-code-skill",
41
+ "author": "Kolbo AI <support@kolbo.ai>",
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "files": [
46
+ "src/",
47
+ "bin/",
48
+ "skill/",
49
+ "README.md"
50
+ ],
51
+ "dependencies": {
52
+ "@modelcontextprotocol/ext-apps": "^1.7.4",
53
+ "@modelcontextprotocol/sdk": "1.29.0",
54
+ "form-data": "^4.0.6",
55
+ "zod": "^3.25.0"
56
+ },
57
+ "overrides": {
58
+ "hono": "^4.12.12",
59
+ "@hono/node-server": "^1.19.13",
60
+ "path-to-regexp": "^8.4.2"
61
+ },
62
+ "engines": {
63
+ "node": ">=18.0.0"
64
+ }
65
+ }
@@ -295,10 +295,37 @@ function upload(it) {
295
295
  var xhr = new XMLHttpRequest();
296
296
  xhr.open('POST', state.upload_url, true);
297
297
  xhr.setRequestHeader('Authorization', 'Bearer ' + state.token);
298
+ // A stalled upload used to sit at N% forever: there was no timeout and no
299
+ // ontimeout/onabort handler, only onload/onerror. A file above the CDN body
300
+ // cap in front of the API dies exactly this way — the edge sees Content-Length,
301
+ // kills the connection a few percent in, and the browser never reports it, so
302
+ // the row froze at 1% with no error and no retry. Watch PROGRESS rather than
303
+ // total elapsed time, so a genuinely slow large upload is never punished.
304
+ var STALL_MS = 90000;
305
+ var lastTick = Date.now();
306
+ var stalled = false;
307
+ var watchdog = setInterval(function () {
308
+ if (Date.now() - lastTick < STALL_MS) return;
309
+ stalled = true;
310
+ clearInterval(watchdog);
311
+ try { xhr.abort(); } catch (e) {}
312
+ }, 5000);
313
+ function settle() { clearInterval(watchdog); }
298
314
  xhr.upload.onprogress = function (e) {
315
+ lastTick = Date.now();
299
316
  if (e.lengthComputable) { it.pct = Math.round((e.loaded / e.total) * 100); renderRow(it); }
300
317
  };
318
+ xhr.onabort = function () {
319
+ settle();
320
+ if (!stalled) return;
321
+ active--;
322
+ it.status = 'error';
323
+ it.err = 'Upload stalled — the file may be too large for this connection';
324
+ render();
325
+ pump();
326
+ };
301
327
  xhr.onload = function () {
328
+ settle();
302
329
  active--;
303
330
  var res = null;
304
331
  try { res = JSON.parse(xhr.responseText); } catch (e) {}
@@ -317,6 +344,7 @@ function upload(it) {
317
344
  pump();
318
345
  };
319
346
  xhr.onerror = function () {
347
+ settle();
320
348
  active--;
321
349
  it.status = 'error';
322
350
  it.err = 'Network error — try the full-screen uploader';
@@ -508,13 +508,13 @@ function registerGenerateTools(server, client, options = {}) {
508
508
  );
509
509
 
510
510
  // ─── generate_video ────────────────────────────────────────
511
- // NOTE: text-to-video does NOT support Visual DNA the textToVideoGeneration
512
- // controller in kolbo-api never reads visualDnaIds. For character-consistent
513
- // video, use generate_elements (which DOES honor visual_dna_ids) or animate a
514
- // DNA-locked still via generate_video_from_image.
511
+ // Text-to-video is now a MODE inside videoGeneration/controller.js (sdk/controller.js
512
+ // posts mode:'text_to_video'), and that controller DOES read visualDnaIds so Visual
513
+ // DNA works here. The old "text-to-video never reads visualDnaIds" note described the
514
+ // retired textToVideoGeneration path and was stale.
515
515
  server.tool(
516
516
  'generate_video',
517
- 'Generate a video from a text prompt using Kolbo AI. For SEVERAL different videos, pass all their prompts in `prompts` in ONE call (one combined widget) — never a series of separate calls. For animating an existing still image into motion, use generate_video_from_image instead. For a coordinated multi-scene video campaign, use generate_creative_director with workflow_type="video". Supports reference images (for style/composition guidance). Does NOT support Visual DNA for character-consistent video use generate_elements or animate a DNA-locked still via generate_video_from_image. Returns the final video URL when complete.',
517
+ 'Generate a video from a text prompt using Kolbo AI. For SEVERAL different videos, pass all their prompts in `prompts` in ONE call (one combined widget) — never a series of separate calls. For animating an existing still image into motion, use generate_video_from_image instead. For a coordinated multi-scene video campaign, use generate_creative_director with workflow_type="video". Supports reference images (for style/composition guidance) and Visual DNA for character consistency. Returns the final video URL when complete.',
518
518
  {
519
519
  prompt: z.string().optional().describe('Text description of the video to generate. Required unless `prompts` is provided.'),
520
520
  prompts: promptsField('videos'),
@@ -525,16 +525,17 @@ function registerGenerateTools(server, client, options = {}) {
525
525
  reference_images: z.array(z.string()).optional().describe('Array of image URLs used as visual references (style / composition / subject). **Cap: pass at most `max_reference_images` URLs from list_models for the chosen model — exceeding it is a deterministic 400.**'),
526
526
  resolution: z.string().optional().describe('Video resolution tier (vertical pixels): "720p" / "1080p" / "1440p" / "2160p". Some models use labels like "512P"/"1024P"/"768P"/"1080P". Model-dependent — call list_models and read supported_resolutions. Read resolution_multipliers to predict cost.'),
527
527
  preset_id: z.string().optional().describe('Preset ID from list_presets type="video" to apply a saved motion/style preset to this generation.'),
528
+ visual_dna_ids: z.array(z.string()).optional().describe('Array of Visual DNA profile IDs to apply for character/style consistency. Every DNA passed here MUST also be tagged in the prompt as @ExactDNAName. **Cap: pass at most `max_visual_dna` IDs from list_models for the chosen model; if `supports_visual_dna: false`, DNA is silently ignored.**'),
528
529
  sound_enabled: z.boolean().optional().describe('Enable (`true`) or disable (`false`) AI-generated synced audio on the output video. Honored by `sound_generation_type: "native"` models (Veo 3.1, Kling V3/2.6, PixVerse V6). Seedance 2.x reports type "none" (no toggle) but `sound_baked_in: true` — those still emit real audio; do not tell the user the model is silent. Omit to use `sound_enabled_by_default`. Pass `false` only when the user asks for silent AND the model is native (not baked-in). Enabling sound may apply `sound_credit_multiplier` to cost.'),
529
530
  skip_color_palette: z.boolean().optional().describe('Opt this single call OUT of the account\'s active Color DNA palette (see list_color_palettes / activate_color_palette). By default, if the user has an active palette it strict-grades every generation automatically — pass true only when the user explicitly wants this one video ungraded.'),
530
531
  project_id: projectIdField,
531
532
  session_id: sessionIdField
532
533
  },
533
- async ({ prompt, prompts, model, aspect_ratio, duration, enhance_prompt = false, reference_images, resolution, preset_id, sound_enabled, skip_color_palette, project_id, session_id }) => {
534
+ async ({ prompt, prompts, model, aspect_ratio, duration, enhance_prompt = false, reference_images, resolution, preset_id, visual_dna_ids, sound_enabled, skip_color_palette, project_id, session_id }) => {
534
535
  if (!prompt && !(prompts && prompts.length)) throw new Error('Provide prompt or prompts');
535
536
  model = await canonicalModelId(client, model, 'text_to_video'); // lenient id resolution ("z-image" → "z-image/turbo")
536
537
  const shared = {
537
- model, aspect_ratio, duration, enhance_prompt, reference_images, resolution, preset_id, sound_enabled, skip_color_palette, project_id, session_id
538
+ model, aspect_ratio, duration, enhance_prompt, reference_images, resolution, preset_id, visual_dna_ids, sound_enabled, skip_color_palette, project_id, session_id
538
539
  };
539
540
 
540
541
  // Batch mode: N different prompts, one widget owning all generation ids.
@@ -1147,6 +1148,7 @@ function registerGenerateTools(server, client, options = {}) {
1147
1148
  enhance_prompt: z.boolean().optional().describe('Enhance the prompt. Default: false — only pass true if the user explicitly asks to enhance/improve the prompt.'),
1148
1149
  visual_dna_ids: z.array(z.string()).optional().describe('Array of Visual DNA profile IDs to apply for character/style consistency across outputs. **Cap: pass at most `max_visual_dna` IDs from list_models for the chosen model.**'),
1149
1150
  resolution: z.string().optional().describe('Video resolution tier (vertical pixels): "720p" / "1080p" / "1440p" / "2160p". Model-dependent — call list_models and read supported_resolutions.'),
1151
+ sound_enabled: z.boolean().optional().describe('Enable (`true`) or disable (`false`) AI-generated synced audio on the output video. Honored by `sound_generation_type: "native"` models (Kling O3/V3, Veo 3.1, PixVerse V6). Omit to use `sound_enabled_by_default`. Enabling sound may apply `sound_credit_multiplier` to cost.'),
1150
1152
  keyframes: z.array(z.object({
1151
1153
  image_url: z.string().describe('Public URL of the keyframe image'),
1152
1154
  timestamp_seconds: z.number().describe('Moment on the OUTPUT timeline (seconds, 0 = first frame) where this image is pinned')
@@ -1157,7 +1159,7 @@ function registerGenerateTools(server, client, options = {}) {
1157
1159
  project_id: projectIdField,
1158
1160
  session_id: sessionIdField
1159
1161
  },
1160
- 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 }) => {
1162
+ 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, sound_enabled, keyframes, multi_shots, multi_shot_count, session_name, project_id, session_id }) => {
1161
1163
  model = await canonicalModelId(client, model, 'elements'); // lenient id resolution ("z-image" → "z-image/turbo")
1162
1164
  if (!prompt) throw new Error('prompt is required');
1163
1165
 
@@ -1179,6 +1181,7 @@ function registerGenerateTools(server, client, options = {}) {
1179
1181
  if (reference_audio_urls) form.append('reference_audio_urls', JSON.stringify(reference_audio_urls));
1180
1182
  if (audio_url) form.append('audio_url', audio_url);
1181
1183
  if (resolution) form.append('resolution', resolution);
1184
+ if (sound_enabled !== undefined) form.append('sound_enabled', String(sound_enabled));
1182
1185
  if (keyframes) form.append('keyframes', JSON.stringify(keyframes));
1183
1186
  if (multi_shots !== undefined) form.append('multi_shots', String(multi_shots));
1184
1187
  if (multi_shot_count !== undefined) form.append('multi_shot_count', String(multi_shot_count));
@@ -1192,7 +1195,7 @@ function registerGenerateTools(server, client, options = {}) {
1192
1195
  } else {
1193
1196
  // URL-only mode: plain JSON.
1194
1197
  startResponse = await client.post('/v1/generate/elements', {
1195
- 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
1198
+ prompt, model, reference_images, reference_videos, reference_audio_urls, audio_url, duration, aspect_ratio, motion, preset_id, enhance_prompt, visual_dna_ids, resolution, sound_enabled, keyframes, multi_shots, multi_shot_count, session_name, project_id, session_id
1196
1199
  });
1197
1200
  }
1198
1201
 
@@ -1269,10 +1272,11 @@ function registerGenerateTools(server, client, options = {}) {
1269
1272
  enhance_prompt: z.boolean().optional().describe('Enhance the prompt. Default: false — only pass true if the user explicitly asks to enhance/improve the prompt.'),
1270
1273
  visual_dna_ids: z.array(z.string()).optional().describe('Array of Visual DNA profile IDs to apply. **Cap: pass at most `max_visual_dna` IDs from list_models for the chosen model; if `supports_visual_dna: false`, DNA is silently ignored.**'),
1271
1274
  resolution: z.string().optional().describe('Video resolution tier (vertical pixels): "720p" / "1080p" / "1440p" / "2160p". Model-dependent — call list_models and read supported_resolutions.'),
1275
+ sound_enabled: z.boolean().optional().describe('Enable (`true`) or disable (`false`) AI-generated synced audio on the output video. Honored by `sound_generation_type: "native"` models (Kling O3/V3, Veo 3.1, PixVerse V6). Omit to use `sound_enabled_by_default`. Enabling sound may apply `sound_credit_multiplier` to cost.'),
1272
1276
  project_id: projectIdField,
1273
1277
  session_id: sessionIdField
1274
1278
  },
1275
- async ({ first_frame_url, last_frame_url, first_frame, last_frame, prompt, model, duration, aspect_ratio, enhance_prompt = false, visual_dna_ids, resolution, project_id, session_id }) => {
1279
+ async ({ first_frame_url, last_frame_url, first_frame, last_frame, prompt, model, duration, aspect_ratio, enhance_prompt = false, visual_dna_ids, resolution, sound_enabled, project_id, session_id }) => {
1276
1280
  model = await canonicalModelId(client, model, 'firstlastgenerations'); // lenient id resolution ("z-image" → "z-image/turbo")
1277
1281
  const urlMode = first_frame_url && last_frame_url;
1278
1282
  const fileMode = first_frame && last_frame;
@@ -1299,12 +1303,13 @@ function registerGenerateTools(server, client, options = {}) {
1299
1303
  if (enhance_prompt !== undefined) form.append('enhance_prompt', String(enhance_prompt));
1300
1304
  if (visual_dna_ids) form.append('visual_dna_ids', JSON.stringify(visual_dna_ids));
1301
1305
  if (resolution) form.append('resolution', resolution);
1306
+ if (sound_enabled !== undefined) form.append('sound_enabled', String(sound_enabled));
1302
1307
  if (project_id) form.append('project_id', project_id);
1303
1308
  if (session_id) form.append('session_id', session_id);
1304
1309
  startResponse = await client.postMultipart('/v1/generate/first-last-frame', form);
1305
1310
  } else {
1306
1311
  startResponse = await client.post('/v1/generate/first-last-frame', {
1307
- first_frame_url, last_frame_url, prompt, model, duration, aspect_ratio, enhance_prompt, visual_dna_ids, resolution, project_id, session_id
1312
+ first_frame_url, last_frame_url, prompt, model, duration, aspect_ratio, enhance_prompt, visual_dna_ids, resolution, sound_enabled, project_id, session_id
1308
1313
  });
1309
1314
  }
1310
1315
 
@@ -1477,6 +1482,7 @@ function registerGenerateTools(server, client, options = {}) {
1477
1482
  reference_images: z.array(z.string()).optional().describe('Array of reference image URLs for models that support additional image inputs. **Cap: pass at most `max_images` URLs from list_models — if `max_images === 0` the model does not accept image refs.** Examples: character reference images for Kling O1/O3, style reference for Aleph/gen4_aleph, character image for WAN VACE video-edit.'),
1478
1483
  reference_videos: z.array(z.string()).optional().describe('Array of additional reference video URLs for models that support multiple video inputs. **Cap: pass at most `max_videos` URLs from list_models — if `max_videos <= 1` only the source_video is accepted.** Example: WAN 2.6 reference-to-video accepts 1–3 reference videos.'),
1479
1484
  elements: z.array(z.string()).optional().describe('Array of element image URLs. **Cap: pass at most `max_elements` URLs from list_models — if `max_elements === 0` the model does not accept elements.** Elements are style or character reference assets alongside the main video.'),
1485
+ sound_enabled: z.boolean().optional().describe('Enable (`true`) or disable (`false`) AI-generated synced audio on the output video. Honored by `sound_generation_type: "native"` models (Kling O3/V3, Veo 3.1, PixVerse V6). Omit to use `sound_enabled_by_default`. Enabling sound may apply `sound_credit_multiplier` to cost.'),
1480
1486
  // VEED Subtitles (model: veed/subtitles) — burns styled subtitles into the video
1481
1487
  preset: z.string().optional().describe('VEED Subtitles only: caption style preset (e.g. "glass", "whisper", "fusion", "simple", "vegas"). Call list_models type="video_to_video" for the veed/subtitles model. Ignored by other models.'),
1482
1488
  source_language: z.string().optional().describe('VEED Subtitles only: BCP-47 code of the spoken language to improve transcription accuracy (e.g. "en-US", "es-ES", "he-IL"). Omit to auto-detect.'),
@@ -1498,7 +1504,7 @@ function registerGenerateTools(server, client, options = {}) {
1498
1504
  project_id: projectIdField,
1499
1505
  session_id: sessionIdField
1500
1506
  },
1501
- async ({ source_video, prompt, model, aspect_ratio, duration, enhance_prompt = false, visual_dna_ids, resolution, reference_images, reference_videos, elements, preset, source_language, translation_language, srt_content, srt_file_url, vocabulary, customization, project_id, session_id }) => {
1507
+ async ({ source_video, prompt, model, aspect_ratio, duration, enhance_prompt = false, visual_dna_ids, resolution, sound_enabled, reference_images, reference_videos, elements, preset, source_language, translation_language, srt_content, srt_file_url, vocabulary, customization, project_id, session_id }) => {
1502
1508
  model = await canonicalModelId(client, model, 'video_to_video'); // lenient id resolution ("z-image" → "z-image/turbo")
1503
1509
  if (!source_video) throw new Error('source_video is required');
1504
1510
 
@@ -1506,7 +1512,7 @@ function registerGenerateTools(server, client, options = {}) {
1506
1512
  let startResponse;
1507
1513
  if (isUrl) {
1508
1514
  startResponse = await client.post('/v1/generate/video-from-video', {
1509
- video_url: source_video, prompt, model, aspect_ratio, duration, enhance_prompt, visual_dna_ids, resolution,
1515
+ video_url: source_video, prompt, model, aspect_ratio, duration, enhance_prompt, visual_dna_ids, resolution, sound_enabled,
1510
1516
  reference_images, reference_videos, elements, preset, source_language, translation_language,
1511
1517
  srt_content, srt_file_url, vocabulary, customization, project_id, session_id
1512
1518
  });
@@ -1528,6 +1534,7 @@ function registerGenerateTools(server, client, options = {}) {
1528
1534
  if (enhance_prompt !== undefined) form.append('enhance_prompt', String(enhance_prompt));
1529
1535
  if (visual_dna_ids) form.append('visual_dna_ids', JSON.stringify(visual_dna_ids));
1530
1536
  if (resolution) form.append('resolution', resolution);
1537
+ if (sound_enabled !== undefined) form.append('sound_enabled', String(sound_enabled));
1531
1538
  if (reference_images) form.append('reference_images', JSON.stringify(reference_images));
1532
1539
  if (reference_videos) form.append('reference_videos', JSON.stringify(reference_videos));
1533
1540
  if (elements) form.append('elements', JSON.stringify(elements));