@kolbo/mcp 1.113.2 → 1.114.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.113.2",
3
+ "version": "1.114.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": {
@@ -1950,6 +1950,18 @@ function registerGenerateTools(server, client, options = {}) {
1950
1950
  if (!source) throw new Error('source is required (URL or absolute local path to image/video)');
1951
1951
  if (!audio) throw new Error('audio is required (URL or absolute local path to audio file)');
1952
1952
 
1953
+ // Upload local files first so the card can show the face source and the
1954
+ // audio from the same CDN URLs the API receives (multipart left the card
1955
+ // with no references at all).
1956
+ ({ source, audio } = await rehostLocalPaths(client, { source, audio, project_id }, { allowLocalFiles: !options.remote }));
1957
+ const isVideoUrl = (u) => /\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(u);
1958
+ const httpRef = (u) => (typeof u === 'string' && /^https?:\/\//i.test(u) ? [u] : []);
1959
+ const lipsyncRefs = {
1960
+ reference_images: httpRef(source).filter((u) => !isVideoUrl(u)),
1961
+ reference_videos: httpRef(source).filter(isVideoUrl),
1962
+ reference_audio: httpRef(audio),
1963
+ };
1964
+
1953
1965
  const sourceIsUrl = typeof source === 'string' && /^https?:\/\//i.test(source);
1954
1966
  const audioIsUrl = typeof audio === 'string' && /^https?:\/\//i.test(audio);
1955
1967
 
@@ -2005,8 +2017,7 @@ function registerGenerateTools(server, client, options = {}) {
2005
2017
 
2006
2018
  if (returnsImmediately()) return submittedResult({
2007
2019
  tool: 'generate_lipsync', kind: 'video', gen: startResponse, client, model,
2008
- prompt: text_prompt, settings: { mode: 'lipsync' },
2009
- reference_images: sourceIsUrl && !/\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(source) ? [source] : [],
2020
+ prompt: text_prompt, settings: { mode: 'lipsync' }, ...lipsyncRefs,
2010
2021
  });
2011
2022
 
2012
2023
  const poll = await pollOrTimedOut(client, startResponse.generation_id, {
@@ -2018,9 +2029,7 @@ function registerGenerateTools(server, client, options = {}) {
2018
2029
 
2019
2030
  return uiCompleted({
2020
2031
  tool: 'generate_lipsync', kind: 'video', gen: startResponse, client, model,
2021
- prompt: text_prompt, settings: { mode: 'lipsync' },
2022
- reference_images: sourceIsUrl && !/\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(source) ? [source] : [],
2023
- reference_videos: sourceIsUrl && /\.(mp4|mov|webm|mkv|avi|m4v)(\?|$)/i.test(source) ? [source] : [],
2032
+ prompt: text_prompt, settings: { mode: 'lipsync' }, ...lipsyncRefs,
2024
2033
  urls: result.result?.urls || [],
2025
2034
  thumbnail_url: result.result?.thumbnail_url || null,
2026
2035
  duration: result.result?.duration || null,
@@ -113,11 +113,11 @@ function registerVoiceTools(server, client, options = {}) {
113
113
  // ─── clone_voice ───────────────────────────────────────────
114
114
  server.tool(
115
115
  'clone_voice',
116
- 'Clone a custom TTS voice from an audio sample (the user\'s voice or any voice they own the rights to). Costs credits (provider-dependent) — confirm with the user before firing. Providers: "elevenlabs" (recommended, 2s–180s sample) or "deepdub" (2s–300s). After cloning, the voice appears in `list_voices` and can be used with generate_speech. Free plan caps at 3 custom voices.',
116
+ 'Clone a custom TTS voice from an audio sample (the user\'s voice or any voice they own the rights to). One-time setup cost depends on the provider — confirm with the user before firing. Providers (sample length, setup credits): "elevenlabs" (recommended, 8s–180s, 30), "kolbo" (Kolbo Voice Clone, 1s–60s, free), "fish-audio" (10s–120s, free), "cartesia" (3s–60s, 10), "heygen" (10s–180s, 75), "deepdub" (2s–300s, free), "minimax" (10s–180s, 400). After cloning, the voice appears in `list_voices` and can be used with generate_speech. Free plan caps at 3 custom voices.',
117
117
  {
118
118
  audio: z.string().describe('URL or absolute local path of the voice sample audio (any common format; converted server-side).'),
119
119
  voice_name: z.string().describe('Name for the cloned voice.'),
120
- provider: z.enum(['elevenlabs', 'deepdub']).optional().describe('Cloning provider. Default: elevenlabs (recommended).'),
120
+ provider: z.enum(['elevenlabs', 'kolbo', 'fish-audio', 'cartesia', 'heygen', 'deepdub', 'minimax']).optional().describe('Cloning provider (same set as the app\'s voice cloning). Default: elevenlabs (recommended).'),
121
121
  language: z.string().optional().describe('Optional language hint (auto-detected when omitted).'),
122
122
  project_id: z.string().optional().describe('Project to associate the voice with (from list_projects). Omit for the default project.')
123
123
  },
@@ -126,7 +126,8 @@ function registerVoiceTools(server, client, options = {}) {
126
126
  const form = new FormData();
127
127
  form.append('audioFile', resolved.buffer, { filename: resolved.filename, contentType: resolved.contentType });
128
128
  form.append('voiceName', voice_name);
129
- form.append('provider', provider || 'elevenlabs');
129
+ // "kolbo" is the user-facing name of Kolbo Voice Clone; the API keeps its internal id.
130
+ form.append('provider', provider === 'kolbo' ? 'zonos' : (provider || 'elevenlabs'));
130
131
  if (language) form.append('language', language);
131
132
  if (project_id) form.append('project_id', project_id);
132
133
  const result = await client.postMultipart('/v1/voices/clone', form);