@kolbo/mcp 1.15.0 → 1.16.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,56 +1,56 @@
1
- {
2
- "name": "@kolbo/mcp",
3
- "version": "1.15.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-parity": "node scripts/check-parity.js",
13
- "prepublishOnly": "node scripts/smoke.js && node scripts/check-parity.js"
14
- },
15
- "keywords": [
16
- "kolbo",
17
- "mcp",
18
- "ai",
19
- "image-generation",
20
- "video-generation",
21
- "music-generation",
22
- "text-to-speech",
23
- "claude-code",
24
- "claude-desktop",
25
- "model-context-protocol"
26
- ],
27
- "license": "MIT",
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/Zoharvan12/kolbo-code",
31
- "directory": "packages/kolbo-mcp"
32
- },
33
- "homepage": "https://docs.kolbo.ai/developer-api/claude-code-skill",
34
- "author": "Kolbo AI <support@kolbo.ai>",
35
- "publishConfig": {
36
- "access": "public"
37
- },
38
- "files": [
39
- "src/",
40
- "bin/",
41
- "README.md"
42
- ],
43
- "dependencies": {
44
- "@modelcontextprotocol/sdk": "1.29.0",
45
- "form-data": "^4.0.5",
46
- "zod": "^3.25.0"
47
- },
48
- "overrides": {
49
- "hono": "^4.12.12",
50
- "@hono/node-server": "^1.19.13",
51
- "path-to-regexp": "^8.4.2"
52
- },
53
- "engines": {
54
- "node": ">=18.0.0"
55
- }
56
- }
1
+ {
2
+ "name": "@kolbo/mcp",
3
+ "version": "1.16.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-parity": "node scripts/check-parity.js",
13
+ "prepublishOnly": "node scripts/smoke.js && node scripts/check-parity.js"
14
+ },
15
+ "keywords": [
16
+ "kolbo",
17
+ "mcp",
18
+ "ai",
19
+ "image-generation",
20
+ "video-generation",
21
+ "music-generation",
22
+ "text-to-speech",
23
+ "claude-code",
24
+ "claude-desktop",
25
+ "model-context-protocol"
26
+ ],
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/Zoharvan12/kolbo-code",
31
+ "directory": "packages/kolbo-mcp"
32
+ },
33
+ "homepage": "https://docs.kolbo.ai/developer-api/claude-code-skill",
34
+ "author": "Kolbo AI <support@kolbo.ai>",
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "files": [
39
+ "src/",
40
+ "bin/",
41
+ "README.md"
42
+ ],
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "1.29.0",
45
+ "form-data": "^4.0.5",
46
+ "zod": "^3.25.0"
47
+ },
48
+ "overrides": {
49
+ "hono": "^4.12.12",
50
+ "@hono/node-server": "^1.19.13",
51
+ "path-to-regexp": "^8.4.2"
52
+ },
53
+ "engines": {
54
+ "node": ">=18.0.0"
55
+ }
56
+ }
package/src/polling.js CHANGED
@@ -6,9 +6,10 @@ class PollingTimeoutError extends Error {
6
6
  constructor(generationId, timeoutMs) {
7
7
  const seconds = Math.round(timeoutMs / 1000);
8
8
  super(
9
- `Generation timed out after ${seconds}s of polling. The generation may STILL be running on the server — ` +
10
- `call get_generation_status with generation_id="${generationId}" to check its current state. ` +
11
- `Videos, deep-think chat, and large batches can take longer than the default polling window.`
9
+ `Generation timed out after ${seconds}s of polling. The generation is STILL RUNNING on the server — ` +
10
+ `DO NOT re-issue the original generation tool. A retry would burn credits while the original keeps producing the result you already paid for. ` +
11
+ `Instead, IMMEDIATELY call get_generation_status with generation_id="${generationId}" (it block-polls server-side, no need to loop). ` +
12
+ `Videos, deep-think chat, and large batches can legitimately take 5–15+ minutes beyond the default polling window.`
12
13
  );
13
14
  this.name = 'PollingTimeoutError';
14
15
  this.generationId = generationId;
package/src/tools/chat.js CHANGED
@@ -1,140 +1,140 @@
1
- /* ⛔ BACKWARD COMPATIBILITY: Tool names and arg names below are a PUBLIC
2
- * CONTRACT. Never rename, remove, or break an existing tool/arg — old cached
3
- * `npx @kolbo/mcp` installs in the wild will break silently. Add new tools or
4
- * new OPTIONAL args only. Full rules: ../index.js top-of-file and CLAUDE.md. */
5
-
6
- const { z } = require('zod');
7
- const { pollUntilDone } = require('../polling');
8
- const { creditFields } = require('./_shared');
9
-
10
- function registerChatTools(server, client) {
11
- // ─── chat_send_message ─────────────────────────────────────
12
- server.tool(
13
- 'chat_send_message',
14
- 'Send a chat message to Kolbo AI. Starts a new conversation (omit session_id) or continues an existing one. Returns the assistant response when complete. Supports image/video/audio analysis via media_urls — pass public URLs and the model auto-routes to a vision-capable model (e.g. Gemini) when media is detected. Supports web search and deep think modes.',
15
- {
16
- message: z.string().describe('The user message to send'),
17
- model: z.string().optional().describe('Model identifier (e.g. "gpt-4o", "claude-sonnet-4-6"). Omit for Smart Select (auto) — recommended default. When media_urls contains video or audio, Smart Select automatically routes to a Gemini vision model regardless of this field.'),
18
- session_id: z.string().optional().describe('Existing chat session ID to continue. Omit to start a new conversation.'),
19
- system_prompt: z.string().optional().describe('System prompt for the conversation. Only applied when creating a new session.'),
20
- web_search: z.boolean().optional().describe('Enable web search for this message. Default: false'),
21
- deep_think: z.boolean().optional().describe('Enable deep think (extended reasoning). Default: false'),
22
- enhance_prompt: z.boolean().optional().describe('Enhance the prompt. Default: true'),
23
- media_urls: z.array(z.string()).optional().describe('Public URLs of images, videos, or audio files to analyze. The model auto-routes to a vision-capable model when media is present. Use upload_media first to get a public URL for local files.')
24
- },
25
- async ({ message, model, session_id, system_prompt, web_search, deep_think, enhance_prompt, media_urls }) => {
26
- const gen = await client.post('/v1/chat', {
27
- message,
28
- model,
29
- session_id,
30
- system_prompt,
31
- web_search,
32
- deep_think,
33
- enhance_prompt,
34
- media_urls
35
- });
36
-
37
- // Deep think reasoning can run far longer than normal chat. Also grant
38
- // extra time when web_search is on (may fetch + analyze multiple pages).
39
- const timeout = deep_think ? 600000 : (web_search ? 240000 : 120000);
40
-
41
- const result = await pollUntilDone(client, gen.message_id, {
42
- interval: (gen.poll_interval_hint || 2) * 1000,
43
- timeout
44
- });
45
-
46
- // Chat status shape (from extractResult in kolbo-api sdk/controller.js):
47
- // { content, reasoning_content, image_urls?, video_urls?, audio_urls?, model, created_at }
48
- const r = result.result || {};
49
- return {
50
- content: [{
51
- type: 'text',
52
- text: JSON.stringify({
53
- ...creditFields(result),
54
- session_id: gen.session_id,
55
- message_id: gen.message_id,
56
- model: r.model || gen.model,
57
- content: r.content || '',
58
- reasoning_content: r.reasoning_content || null,
59
- image_urls: r.image_urls || null,
60
- video_urls: r.video_urls || null,
61
- audio_urls: r.audio_urls || null
62
- }, null, 2)
63
- }]
64
- };
65
- }
66
- );
67
-
68
- // ─── chat_list_conversations ───────────────────────────────
69
- server.tool(
70
- 'chat_list_conversations',
71
- 'List your SDK chat conversations, most-recent first. Returns session_id, name, and activity timestamps.',
72
- {
73
- page: z.number().optional().describe('Page number, 1-indexed. Default: 1'),
74
- limit: z.number().optional().describe('Results per page, max 50. Default: 20')
75
- },
76
- async ({ page, limit }) => {
77
- const params = new URLSearchParams();
78
- if (page) params.set('page', String(page));
79
- if (limit) params.set('limit', String(limit));
80
-
81
- const qs = params.toString();
82
- const result = await client.get(`/v1/chat/conversations${qs ? '?' + qs : ''}`);
83
-
84
- return {
85
- content: [{
86
- type: 'text',
87
- text: JSON.stringify({
88
- conversations: result.conversations || [],
89
- pagination: result.pagination || null
90
- }, null, 2)
91
- }]
92
- };
93
- }
94
- );
95
-
96
- // ─── chat_get_messages ─────────────────────────────────────
97
- server.tool(
98
- 'chat_get_messages',
99
- 'Fetch messages in a chat conversation. Returns role, content, model, and any media URLs attached to each message.',
100
- {
101
- session_id: z.string().describe('The chat session ID'),
102
- page: z.number().optional().describe('Page number, 1-indexed. Default: 1'),
103
- limit: z.number().optional().describe('Messages per page, max 100. Default: 50')
104
- },
105
- async ({ session_id, page, limit }) => {
106
- const params = new URLSearchParams();
107
- if (page) params.set('page', String(page));
108
- if (limit) params.set('limit', String(limit));
109
-
110
- const qs = params.toString();
111
- const result = await client.get(
112
- `/v1/chat/conversations/${encodeURIComponent(session_id)}/messages${qs ? '?' + qs : ''}`
113
- );
114
-
115
- // Trim each message to avoid flooding context.
116
- const messages = (result.messages || []).map(m => ({
117
- role: m.role,
118
- content: m.content,
119
- model: m.model?.name || m.model?.identifier || null,
120
- status: m.status,
121
- created_at: m.createdAt || m.created_at,
122
- image_url: m.image_url || null,
123
- video_url: m.video_url || null,
124
- audio_url: m.audio_url || null
125
- }));
126
-
127
- return {
128
- content: [{
129
- type: 'text',
130
- text: JSON.stringify({
131
- messages,
132
- pagination: result.pagination || null
133
- }, null, 2)
134
- }]
135
- };
136
- }
137
- );
138
- }
139
-
140
- module.exports = { registerChatTools };
1
+ /* ⛔ BACKWARD COMPATIBILITY: Tool names and arg names below are a PUBLIC
2
+ * CONTRACT. Never rename, remove, or break an existing tool/arg — old cached
3
+ * `npx @kolbo/mcp` installs in the wild will break silently. Add new tools or
4
+ * new OPTIONAL args only. Full rules: ../index.js top-of-file and CLAUDE.md. */
5
+
6
+ const { z } = require('zod');
7
+ const { pollUntilDone } = require('../polling');
8
+ const { creditFields } = require('./_shared');
9
+
10
+ function registerChatTools(server, client) {
11
+ // ─── chat_send_message ─────────────────────────────────────
12
+ server.tool(
13
+ 'chat_send_message',
14
+ 'Send a chat message to Kolbo AI. Starts a new conversation (omit session_id) or continues an existing one. Returns the assistant response when complete. Supports image/video/audio analysis via media_urls — pass public URLs and the model auto-routes to a vision-capable model (e.g. Gemini) when media is detected. Supports web search and deep think modes.',
15
+ {
16
+ message: z.string().describe('The user message to send'),
17
+ model: z.string().optional().describe('Model identifier (e.g. "gpt-4o", "claude-sonnet-4-6"). Omit for Smart Select (auto) — recommended default. When media_urls contains video or audio, Smart Select automatically routes to a Gemini vision model regardless of this field.'),
18
+ session_id: z.string().optional().describe('Existing chat session ID to continue. Omit to start a new conversation.'),
19
+ system_prompt: z.string().optional().describe('System prompt for the conversation. Only applied when creating a new session.'),
20
+ web_search: z.boolean().optional().describe('Enable web search for this message. Default: false'),
21
+ deep_think: z.boolean().optional().describe('Enable deep think (extended reasoning). Default: false'),
22
+ enhance_prompt: z.boolean().optional().describe('Set true to ask the API to rewrite your prompt for richer detail. Default: false — by default we send your prompt as-is.'),
23
+ media_urls: z.array(z.string()).optional().describe('Public URLs of images, videos, or audio files to analyze. The model auto-routes to a vision-capable model when media is present. Use upload_media first to get a public URL for local files.')
24
+ },
25
+ async ({ message, model, session_id, system_prompt, web_search, deep_think, enhance_prompt = false, media_urls }) => {
26
+ const gen = await client.post('/v1/chat', {
27
+ message,
28
+ model,
29
+ session_id,
30
+ system_prompt,
31
+ web_search,
32
+ deep_think,
33
+ enhance_prompt,
34
+ media_urls
35
+ });
36
+
37
+ // Deep think reasoning can run far longer than normal chat. Also grant
38
+ // extra time when web_search is on (may fetch + analyze multiple pages).
39
+ const timeout = deep_think ? 600000 : (web_search ? 240000 : 120000);
40
+
41
+ const result = await pollUntilDone(client, gen.message_id, {
42
+ interval: (gen.poll_interval_hint || 2) * 1000,
43
+ timeout
44
+ });
45
+
46
+ // Chat status shape (from extractResult in kolbo-api sdk/controller.js):
47
+ // { content, reasoning_content, image_urls?, video_urls?, audio_urls?, model, created_at }
48
+ const r = result.result || {};
49
+ return {
50
+ content: [{
51
+ type: 'text',
52
+ text: JSON.stringify({
53
+ ...creditFields(result),
54
+ session_id: gen.session_id,
55
+ message_id: gen.message_id,
56
+ model: r.model || gen.model,
57
+ content: r.content || '',
58
+ reasoning_content: r.reasoning_content || null,
59
+ image_urls: r.image_urls || null,
60
+ video_urls: r.video_urls || null,
61
+ audio_urls: r.audio_urls || null
62
+ }, null, 2)
63
+ }]
64
+ };
65
+ }
66
+ );
67
+
68
+ // ─── chat_list_conversations ───────────────────────────────
69
+ server.tool(
70
+ 'chat_list_conversations',
71
+ 'List your SDK chat conversations, most-recent first. Returns session_id, name, and activity timestamps.',
72
+ {
73
+ page: z.number().optional().describe('Page number, 1-indexed. Default: 1'),
74
+ limit: z.number().optional().describe('Results per page, max 50. Default: 20')
75
+ },
76
+ async ({ page, limit }) => {
77
+ const params = new URLSearchParams();
78
+ if (page) params.set('page', String(page));
79
+ if (limit) params.set('limit', String(limit));
80
+
81
+ const qs = params.toString();
82
+ const result = await client.get(`/v1/chat/conversations${qs ? '?' + qs : ''}`);
83
+
84
+ return {
85
+ content: [{
86
+ type: 'text',
87
+ text: JSON.stringify({
88
+ conversations: result.conversations || [],
89
+ pagination: result.pagination || null
90
+ }, null, 2)
91
+ }]
92
+ };
93
+ }
94
+ );
95
+
96
+ // ─── chat_get_messages ─────────────────────────────────────
97
+ server.tool(
98
+ 'chat_get_messages',
99
+ 'Fetch messages in a chat conversation. Returns role, content, model, and any media URLs attached to each message.',
100
+ {
101
+ session_id: z.string().describe('The chat session ID'),
102
+ page: z.number().optional().describe('Page number, 1-indexed. Default: 1'),
103
+ limit: z.number().optional().describe('Messages per page, max 100. Default: 50')
104
+ },
105
+ async ({ session_id, page, limit }) => {
106
+ const params = new URLSearchParams();
107
+ if (page) params.set('page', String(page));
108
+ if (limit) params.set('limit', String(limit));
109
+
110
+ const qs = params.toString();
111
+ const result = await client.get(
112
+ `/v1/chat/conversations/${encodeURIComponent(session_id)}/messages${qs ? '?' + qs : ''}`
113
+ );
114
+
115
+ // Trim each message to avoid flooding context.
116
+ const messages = (result.messages || []).map(m => ({
117
+ role: m.role,
118
+ content: m.content,
119
+ model: m.model?.name || m.model?.identifier || null,
120
+ status: m.status,
121
+ created_at: m.createdAt || m.created_at,
122
+ image_url: m.image_url || null,
123
+ video_url: m.video_url || null,
124
+ audio_url: m.audio_url || null
125
+ }));
126
+
127
+ return {
128
+ content: [{
129
+ type: 'text',
130
+ text: JSON.stringify({
131
+ messages,
132
+ pagination: result.pagination || null
133
+ }, null, 2)
134
+ }]
135
+ };
136
+ }
137
+ );
138
+ }
139
+
140
+ module.exports = { registerChatTools };