@kolbo/mcp 1.70.0 → 1.70.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.70.0",
3
+ "version": "1.70.1",
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": {
@@ -16,7 +16,8 @@ const { widgetPage } = require('../html');
16
16
  * model, model_icon, prompt, count,
17
17
  * settings: { duration, resolution, aspect_ratio, quality, audio, voice, mode,
18
18
  * enhance_prompt, web_search, visual_dna, moodboard, preset, cinematic },
19
- * reference_image, // thumbnail URL (optional)
19
+ * reference_images, // all reference thumbnail URLs (optional)
20
+ * reference_image, // legacy single-thumbnail fallback
20
21
  * urls, thumbnail_url, title, duration, credits_used,
21
22
  * tracks: [{ title, duration, thumbnail_url, model }], // optional audio metadata by URL index
22
23
  * scenes: [{ scene_number, title, image_urls, video_urls }],
@@ -135,7 +136,11 @@ function renderChips(sc) {
135
136
  }
136
137
  if (s.mode) h += chip(esc(s.mode));
137
138
  if (sc.count > 1) h += chip('×' + sc.count);
138
- if (sc.reference_image) h += '<img class="k-ref-thumb" src="' + esc(sc.reference_image) + '" alt="" loading="lazy" title="Reference image" onerror="this.style.display=\\'none\\'">';
139
+ var refs = Array.isArray(sc.reference_images) && sc.reference_images.length
140
+ ? sc.reference_images : (sc.reference_image ? [sc.reference_image] : []);
141
+ for (var i = 0; i < refs.length; i++) {
142
+ h += '<img class="k-ref-thumb" src="' + esc(refs[i]) + '" alt="" loading="lazy" title="Reference image ' + (i + 1) + ' of ' + refs.length + '" onerror="this.style.display=\\'none\\'">';
143
+ }
139
144
  el('chips').innerHTML = h;
140
145
  }
141
146
  function chip(inner) { return '<span class="k-chip">' + inner + '</span>'; }
@@ -518,7 +518,7 @@ async function modelChipFields(client, model) {
518
518
  * kind 'image' | 'video' | 'audio' | '3d' | 'scenes'
519
519
  * gen the submit response ({ generation_id, poll_interval_hint })
520
520
  * client KolboClient (for model icon lookup)
521
- * model, prompt, count, settings, reference_image, estimated_seconds
521
+ * model, prompt, count, settings, reference_images, estimated_seconds
522
522
  * voice resolved voice record { name, thumbnail } (speech only)
523
523
  * poll_tool widget-side status tool (default 'get_generation_status')
524
524
  * status_args args for poll_tool (default { generation_id, wait: true })
@@ -542,7 +542,12 @@ async function uiGenerating(p) {
542
542
  prompt: p.prompt,
543
543
  count: p.count || 1,
544
544
  settings: p.settings || {},
545
- reference_image: p.reference_image,
545
+ // `reference_image` is retained for older widget builds. New widgets render
546
+ // every browser-loadable image supplied to the generation.
547
+ reference_images: Array.isArray(p.reference_images)
548
+ ? p.reference_images.filter(Boolean)
549
+ : (p.reference_image ? [p.reference_image] : []),
550
+ reference_image: p.reference_image || p.reference_images?.find(Boolean),
546
551
  open_url: buildOpenUrl(p.tool, p.gen),
547
552
  };
548
553
  // Batch mode (prompts[] fan-out): ONE widget tracks every id in the set.
@@ -581,7 +586,10 @@ async function uiCompleted(p, textPayload) {
581
586
  prompt: p.prompt,
582
587
  count: p.count || 1,
583
588
  settings: p.settings || {},
584
- reference_image: p.reference_image,
589
+ reference_images: Array.isArray(p.reference_images)
590
+ ? p.reference_images.filter(Boolean)
591
+ : (p.reference_image ? [p.reference_image] : []),
592
+ reference_image: p.reference_image || p.reference_images?.find(Boolean),
585
593
  urls: p.urls,
586
594
  thumbnail_url: p.thumbnail_url,
587
595
  title: p.title,
@@ -178,7 +178,7 @@ function registerGenerateTools(server, client, options = {}) {
178
178
  generation_ids: batch.ids, prompts: batch.ok.map((o) => o.prompt),
179
179
  failed_submissions: batch.failed,
180
180
  status_args: { generation_ids: batch.ids, wait: true },
181
- reference_image: reference_images?.[0]
181
+ reference_images
182
182
  });
183
183
  return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 240000 });
184
184
  }
@@ -188,7 +188,7 @@ function registerGenerateTools(server, client, options = {}) {
188
188
  if (ui()) return uiGenerating({
189
189
  tool: 'generate_image', kind: 'image', gen, client, model, prompt,
190
190
  count: num_images, settings: imageSettings(shared),
191
- reference_image: reference_images?.[0]
191
+ reference_images
192
192
  });
193
193
 
194
194
  const poll = await pollOrTimedOut(client, gen.generation_id, {
@@ -247,7 +247,7 @@ function registerGenerateTools(server, client, options = {}) {
247
247
  tool: 'generate_image_edit', kind: 'image', gen, client, model, prompt,
248
248
  count: num_images,
249
249
  settings: imageSettings({ resolution, aspect_ratio, enhance_prompt, enable_web_search, visual_dna_ids, moodboard_id, preset_id, cinematic }),
250
- reference_image: source_images?.[0]
250
+ reference_images: source_images
251
251
  });
252
252
 
253
253
  // Multi-source compositing or DNA-anchored edits routinely exceed 120s
@@ -309,7 +309,7 @@ function registerGenerateTools(server, client, options = {}) {
309
309
  tool: 'generate_creative_director', kind: 'scenes', gen, client, model, prompt,
310
310
  count: scene_count || 4,
311
311
  settings: { duration, resolution, aspect_ratio, mode: workflow_type || 'image' },
312
- reference_image: reference_images?.[0],
312
+ reference_images,
313
313
  poll_tool: 'get_creative_director_status',
314
314
  status_args: { generation_id: gen.generation_id, wait: true }
315
315
  });
@@ -466,7 +466,7 @@ function registerGenerateTools(server, client, options = {}) {
466
466
  generation_ids: batch.ids, prompts: batch.ok.map((o) => o.prompt),
467
467
  failed_submissions: batch.failed,
468
468
  status_args: { generation_ids: batch.ids, wait: true },
469
- reference_image: reference_images?.[0]
469
+ reference_images
470
470
  });
471
471
  return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 });
472
472
  }
@@ -476,7 +476,7 @@ function registerGenerateTools(server, client, options = {}) {
476
476
  if (ui()) return uiGenerating({
477
477
  tool: 'generate_video', kind: 'video', gen, client, model, prompt,
478
478
  settings: { duration, resolution, aspect_ratio },
479
- reference_image: reference_images?.[0]
479
+ reference_images
480
480
  });
481
481
 
482
482
  // 15 min — Kling O3 4K, Veo 3.1 at higher durations/resolutions, Hailuo 2.3,
@@ -550,7 +550,7 @@ function registerGenerateTools(server, client, options = {}) {
550
550
  generation_ids: batch.ids, prompts: batch.ok.map((o) => o.prompt),
551
551
  failed_submissions: batch.failed,
552
552
  status_args: { generation_ids: batch.ids, wait: true },
553
- reference_image: items[0].image_url
553
+ reference_images: items.map((item) => item.image_url)
554
554
  });
555
555
  return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 });
556
556
  }
@@ -560,7 +560,7 @@ function registerGenerateTools(server, client, options = {}) {
560
560
  if (ui()) return uiGenerating({
561
561
  tool: 'generate_video_from_image', kind: 'video', gen, client, model, prompt,
562
562
  settings: { duration, resolution, aspect_ratio },
563
- reference_image: image_url
563
+ reference_images: [image_url]
564
564
  });
565
565
 
566
566
  // 15 min — same real-world generation times as generate_video (Kling O3 4K,
@@ -791,7 +791,8 @@ function registerGenerateTools(server, client, options = {}) {
791
791
 
792
792
  if (ui()) return uiGenerating({
793
793
  tool: 'generate_sound', kind: 'audio', gen, client, model, prompt,
794
- settings: { duration }
794
+ settings: { duration },
795
+ reference_images: seed_reference_image_url ? [seed_reference_image_url] : []
795
796
  });
796
797
 
797
798
  const poll = await pollOrTimedOut(client, gen.generation_id, {
@@ -1050,7 +1051,11 @@ function registerGenerateTools(server, client, options = {}) {
1050
1051
  if (ui()) return uiGenerating({
1051
1052
  tool: 'generate_elements', kind: 'video', gen: startResponse, client, model, prompt,
1052
1053
  settings: { duration, resolution, aspect_ratio },
1053
- reference_image: reference_images?.[0]
1054
+ reference_images: [
1055
+ ...(reference_images || []),
1056
+ ...(keyframes || []).map((keyframe) => keyframe.image_url),
1057
+ ...(files || []).filter((source) => /^https?:\/\//i.test(source))
1058
+ ]
1054
1059
  });
1055
1060
 
1056
1061
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -1134,7 +1139,8 @@ function registerGenerateTools(server, client, options = {}) {
1134
1139
  if (ui()) return uiGenerating({
1135
1140
  tool: 'generate_first_last_frame', kind: 'video', gen: startResponse, client, model, prompt,
1136
1141
  settings: { duration, resolution, aspect_ratio },
1137
- reference_image: first_frame_url || undefined
1142
+ reference_images: [first_frame_url || first_frame, last_frame_url || last_frame]
1143
+ .filter((source) => /^https?:\/\//i.test(source || ''))
1138
1144
  });
1139
1145
 
1140
1146
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -1249,7 +1255,7 @@ function registerGenerateTools(server, client, options = {}) {
1249
1255
  if (ui()) return uiGenerating({
1250
1256
  tool: 'generate_lipsync', kind: 'video', gen: startResponse, client, model,
1251
1257
  prompt: text_prompt, settings: { mode: 'lipsync' },
1252
- reference_image: sourceIsUrl && !/\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(source) ? source : undefined,
1258
+ reference_images: sourceIsUrl && !/\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(source) ? [source] : [],
1253
1259
  });
1254
1260
 
1255
1261
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -1354,7 +1360,7 @@ function registerGenerateTools(server, client, options = {}) {
1354
1360
  tool: 'generate_video_from_video', kind: 'video', gen: startResponse, client, model,
1355
1361
  prompt: prompt || (preset ? `Subtitles preset: ${preset}` : undefined),
1356
1362
  settings: { duration, resolution, aspect_ratio, mode: preset ? 'subtitles' : 'restyle' },
1357
- reference_image: reference_images?.[0]
1363
+ reference_images: [...(reference_images || []), ...(elements || [])]
1358
1364
  });
1359
1365
 
1360
1366
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -1497,7 +1503,7 @@ function registerGenerateTools(server, client, options = {}) {
1497
1503
  if (ui()) return uiGenerating({
1498
1504
  tool: 'generate_3d', kind: '3d', gen: startResponse, client, model, prompt,
1499
1505
  settings: { mode: mode || (reference_images?.length > 1 ? 'multi' : reference_images?.length === 1 ? 'single' : 'text') },
1500
- reference_image: reference_images?.[0]
1506
+ reference_images
1501
1507
  });
1502
1508
 
1503
1509
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -1643,7 +1649,7 @@ function registerGenerateTools(server, client, options = {}) {
1643
1649
  tool: 'edit_image', kind: 'image', gen, client, model,
1644
1650
  prompt: prompt || operation,
1645
1651
  settings: { mode: operation, aspect_ratio, scale, resolution },
1646
- reference_image: image_url
1652
+ reference_images: [image_url, mask_image_url, ...(additional_images || [])].filter(Boolean)
1647
1653
  });
1648
1654
 
1649
1655
  const poll = await pollOrTimedOut(client, gen.generation_id, {
@@ -1808,7 +1814,7 @@ function registerGenerateTools(server, client, options = {}) {
1808
1814
  tool: 'edit_video', kind: 'video', gen, client, model,
1809
1815
  prompt: prompt || operation,
1810
1816
  settings: { mode: operation, duration, aspect_ratio, resolution },
1811
- reference_image: image_url
1817
+ reference_images: image_url ? [image_url] : []
1812
1818
  });
1813
1819
 
1814
1820
  const poll = await pollOrTimedOut(client, gen.generation_id, {