@kolbo/mcp 1.0.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 +65 -0
- package/bin/kolbo-mcp.js +2 -0
- package/package.json +45 -0
- package/src/client.js +47 -0
- package/src/index.js +27 -0
- package/src/polling.js +36 -0
- package/src/tools/generate.js +224 -0
- package/src/tools/models.js +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @kolbo/mcp
|
|
2
|
+
|
|
3
|
+
Use [Kolbo AI](https://kolbo.ai) as native tools in Claude Code and Claude Desktop via MCP (Model Context Protocol).
|
|
4
|
+
|
|
5
|
+
Generate images, videos, music, speech, and sound effects — all from natural language in your coding environment.
|
|
6
|
+
|
|
7
|
+
## Quick Setup
|
|
8
|
+
|
|
9
|
+
### 1. Get an API Key
|
|
10
|
+
|
|
11
|
+
Create a key at [app.kolbo.ai](https://app.kolbo.ai) or via the [API](https://docs.kolbo.ai/developer-api).
|
|
12
|
+
|
|
13
|
+
### 2. Add to Claude Code
|
|
14
|
+
|
|
15
|
+
Add to `.claude/settings.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"kolbo": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": ["-y", "@kolbo/mcp"],
|
|
23
|
+
"env": {
|
|
24
|
+
"KOLBO_API_KEY": "kolbo_live_..."
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 3. Use it
|
|
32
|
+
|
|
33
|
+
Just ask Claude naturally:
|
|
34
|
+
|
|
35
|
+
- *"Generate an image of a sunset over mountains"*
|
|
36
|
+
- *"Create a 5-second video of waves crashing"*
|
|
37
|
+
- *"Make a lo-fi hip hop beat"*
|
|
38
|
+
- *"Convert this text to speech: Hello world"*
|
|
39
|
+
|
|
40
|
+
## Available Tools
|
|
41
|
+
|
|
42
|
+
| Tool | Description |
|
|
43
|
+
|------|-------------|
|
|
44
|
+
| `generate_image` | Generate images from text prompts |
|
|
45
|
+
| `generate_video` | Generate videos from text |
|
|
46
|
+
| `generate_video_from_image` | Animate an image into video |
|
|
47
|
+
| `generate_music` | Generate music from descriptions |
|
|
48
|
+
| `generate_speech` | Convert text to speech |
|
|
49
|
+
| `generate_sound` | Generate sound effects |
|
|
50
|
+
| `list_models` | Browse available AI models |
|
|
51
|
+
| `check_credits` | Check credit balance |
|
|
52
|
+
| `get_generation_status` | Check a generation's status |
|
|
53
|
+
|
|
54
|
+
## Environment Variables
|
|
55
|
+
|
|
56
|
+
| Variable | Required | Description |
|
|
57
|
+
|----------|----------|-------------|
|
|
58
|
+
| `KOLBO_API_KEY` | Yes | Your Kolbo API key |
|
|
59
|
+
| `KOLBO_API_URL` | No | Custom API URL (default: `https://api.kolbo.ai/api`) |
|
|
60
|
+
|
|
61
|
+
## Links
|
|
62
|
+
|
|
63
|
+
- [API Documentation](https://docs.kolbo.ai/developer-api)
|
|
64
|
+
- [Kolbo AI Platform](https://kolbo.ai)
|
|
65
|
+
- [Get API Key](https://app.kolbo.ai)
|
package/bin/kolbo-mcp.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kolbo/mcp",
|
|
3
|
+
"version": "1.0.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
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"kolbo",
|
|
14
|
+
"mcp",
|
|
15
|
+
"ai",
|
|
16
|
+
"image-generation",
|
|
17
|
+
"video-generation",
|
|
18
|
+
"music-generation",
|
|
19
|
+
"text-to-speech",
|
|
20
|
+
"claude-code",
|
|
21
|
+
"claude-desktop",
|
|
22
|
+
"model-context-protocol"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/nicenathapong/kolbo-mcp"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://docs.kolbo.ai/developer-api/claude-code-mcp",
|
|
30
|
+
"author": "Kolbo AI <support@kolbo.ai>",
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"src/",
|
|
36
|
+
"bin/",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.12.1"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/client.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kolbo API HTTP client wrapper
|
|
3
|
+
*/
|
|
4
|
+
class KolboClient {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.apiKey = process.env.KOLBO_API_KEY;
|
|
7
|
+
this.baseUrl = (process.env.KOLBO_API_URL || 'https://api.kolbo.ai/api').replace(/\/$/, '');
|
|
8
|
+
|
|
9
|
+
if (!this.apiKey) {
|
|
10
|
+
throw new Error('KOLBO_API_KEY environment variable is required');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async request(method, path, body = null) {
|
|
15
|
+
const url = `${this.baseUrl}${path}`;
|
|
16
|
+
const options = {
|
|
17
|
+
method,
|
|
18
|
+
headers: {
|
|
19
|
+
'X-API-Key': this.apiKey,
|
|
20
|
+
'Content-Type': 'application/json'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (body) {
|
|
25
|
+
options.body = JSON.stringify(body);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const response = await fetch(url, options);
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
|
|
31
|
+
if (!response.ok || data.success === false) {
|
|
32
|
+
throw new Error(data.error || data.message || `API error: ${response.status}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return data;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async post(path, body) {
|
|
39
|
+
return this.request('POST', path, body);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async get(path) {
|
|
43
|
+
return this.request('GET', path);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = KolboClient;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
2
|
+
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
3
|
+
const KolboClient = require('./client');
|
|
4
|
+
const { registerGenerateTools } = require('./tools/generate');
|
|
5
|
+
const { registerModelTools } = require('./tools/models');
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
const client = new KolboClient();
|
|
9
|
+
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: 'kolbo',
|
|
12
|
+
version: '1.0.0'
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Register all tools
|
|
16
|
+
registerGenerateTools(server, client);
|
|
17
|
+
registerModelTools(server, client);
|
|
18
|
+
|
|
19
|
+
// Start the server with stdio transport
|
|
20
|
+
const transport = new StdioServerTransport();
|
|
21
|
+
await server.connect(transport);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main().catch(err => {
|
|
25
|
+
console.error('Failed to start Kolbo MCP server:', err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
package/src/polling.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll a generation until it reaches a terminal state
|
|
3
|
+
*/
|
|
4
|
+
async function pollUntilDone(client, generationId, options = {}) {
|
|
5
|
+
const {
|
|
6
|
+
interval = 5000,
|
|
7
|
+
timeout = 300000 // 5 minutes default
|
|
8
|
+
} = options;
|
|
9
|
+
|
|
10
|
+
const startTime = Date.now();
|
|
11
|
+
|
|
12
|
+
while (true) {
|
|
13
|
+
if (Date.now() - startTime > timeout) {
|
|
14
|
+
throw new Error(`Generation ${generationId} timed out after ${timeout / 1000}s`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const result = await client.get(`/v1/generate/${generationId}/status`);
|
|
18
|
+
|
|
19
|
+
if (result.state === 'completed') {
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (result.state === 'failed') {
|
|
24
|
+
throw new Error(result.error || 'Generation failed');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (result.state === 'cancelled') {
|
|
28
|
+
throw new Error('Generation was cancelled');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Wait before next poll
|
|
32
|
+
await new Promise(resolve => setTimeout(resolve, interval));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { pollUntilDone };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
const { pollUntilDone } = require('../polling');
|
|
2
|
+
|
|
3
|
+
function registerGenerateTools(server, client) {
|
|
4
|
+
// ─── generate_image ────────────────────────────────────────
|
|
5
|
+
server.tool(
|
|
6
|
+
'generate_image',
|
|
7
|
+
'Generate image(s) from a text prompt using Kolbo AI. Returns the final image URL(s) when complete.',
|
|
8
|
+
{
|
|
9
|
+
prompt: { type: 'string', description: 'Text description of the image to generate' },
|
|
10
|
+
model: { type: 'string', description: 'Model identifier (e.g., "fal-ai/flux/schnell"). Use list_models to see available models. Omit for auto-selection.' },
|
|
11
|
+
aspect_ratio: { type: 'string', description: 'Aspect ratio (e.g., "1:1", "16:9", "9:16"). Default: "1:1"' },
|
|
12
|
+
enhance_prompt: { type: 'boolean', description: 'Enhance the prompt for better results. Default: true' }
|
|
13
|
+
},
|
|
14
|
+
async ({ prompt, model, aspect_ratio, enhance_prompt }) => {
|
|
15
|
+
const gen = await client.post('/v1/generate/image', {
|
|
16
|
+
prompt, model, aspect_ratio, enhance_prompt
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
20
|
+
interval: (gen.poll_interval_hint || 3) * 1000,
|
|
21
|
+
timeout: 120000
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
content: [{
|
|
26
|
+
type: 'text',
|
|
27
|
+
text: JSON.stringify({
|
|
28
|
+
urls: result.result.urls,
|
|
29
|
+
model: result.result.model,
|
|
30
|
+
prompt_used: result.result.prompt_used
|
|
31
|
+
}, null, 2)
|
|
32
|
+
}]
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// ─── generate_video ────────────────────────────────────────
|
|
38
|
+
server.tool(
|
|
39
|
+
'generate_video',
|
|
40
|
+
'Generate a video from a text prompt using Kolbo AI. Returns the final video URL when complete.',
|
|
41
|
+
{
|
|
42
|
+
prompt: { type: 'string', description: 'Text description of the video to generate' },
|
|
43
|
+
model: { type: 'string', description: 'Model identifier. Use list_models with type "video" to see options.' },
|
|
44
|
+
aspect_ratio: { type: 'string', description: 'Aspect ratio (e.g., "16:9", "9:16", "1:1"). Default: "16:9"' },
|
|
45
|
+
duration: { type: 'number', description: 'Duration in seconds (e.g., 5, 10). Default: 5' },
|
|
46
|
+
enhance_prompt: { type: 'boolean', description: 'Enhance the prompt for better results. Default: true' }
|
|
47
|
+
},
|
|
48
|
+
async ({ prompt, model, aspect_ratio, duration, enhance_prompt }) => {
|
|
49
|
+
const gen = await client.post('/v1/generate/video', {
|
|
50
|
+
prompt, model, aspect_ratio, duration, enhance_prompt
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
54
|
+
interval: (gen.poll_interval_hint || 8) * 1000,
|
|
55
|
+
timeout: 300000
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
content: [{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: JSON.stringify({
|
|
62
|
+
urls: result.result.urls,
|
|
63
|
+
model: result.result.model,
|
|
64
|
+
duration: result.result.duration,
|
|
65
|
+
thumbnail_url: result.result.thumbnail_url,
|
|
66
|
+
prompt_used: result.result.prompt_used
|
|
67
|
+
}, null, 2)
|
|
68
|
+
}]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// ─── generate_video_from_image ─────────────────────────────
|
|
74
|
+
server.tool(
|
|
75
|
+
'generate_video_from_image',
|
|
76
|
+
'Animate an image into a video using Kolbo AI. Returns the final video URL when complete.',
|
|
77
|
+
{
|
|
78
|
+
image_url: { type: 'string', description: 'URL of the source image to animate' },
|
|
79
|
+
prompt: { type: 'string', description: 'Text description of the desired motion/animation' },
|
|
80
|
+
model: { type: 'string', description: 'Model identifier. Use list_models with type "video_from_image" to see options.' },
|
|
81
|
+
duration: { type: 'number', description: 'Duration in seconds (e.g., 5, 10). Default: 5' },
|
|
82
|
+
enhance_prompt: { type: 'boolean', description: 'Enhance the prompt. Default: true' }
|
|
83
|
+
},
|
|
84
|
+
async ({ image_url, prompt, model, duration, enhance_prompt }) => {
|
|
85
|
+
const gen = await client.post('/v1/generate/video/from-image', {
|
|
86
|
+
image_url, prompt, model, duration, enhance_prompt
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
90
|
+
interval: (gen.poll_interval_hint || 8) * 1000,
|
|
91
|
+
timeout: 300000
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
content: [{
|
|
96
|
+
type: 'text',
|
|
97
|
+
text: JSON.stringify({
|
|
98
|
+
urls: result.result.urls,
|
|
99
|
+
model: result.result.model,
|
|
100
|
+
duration: result.result.duration,
|
|
101
|
+
thumbnail_url: result.result.thumbnail_url
|
|
102
|
+
}, null, 2)
|
|
103
|
+
}]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// ─── generate_music ────────────────────────────────────────
|
|
109
|
+
server.tool(
|
|
110
|
+
'generate_music',
|
|
111
|
+
'Generate music from a text description using Kolbo AI. Returns the final audio URL when complete.',
|
|
112
|
+
{
|
|
113
|
+
prompt: { type: 'string', description: 'Text description of the music to generate (e.g., "upbeat electronic dance track with synthesizers")' },
|
|
114
|
+
style: { type: 'string', description: 'Music style (e.g., "pop", "rock", "electronic", "jazz")' },
|
|
115
|
+
instrumental: { type: 'boolean', description: 'Generate instrumental only (no vocals). Default: false' },
|
|
116
|
+
lyrics: { type: 'string', description: 'Custom lyrics for the song' }
|
|
117
|
+
},
|
|
118
|
+
async ({ prompt, style, instrumental, lyrics }) => {
|
|
119
|
+
const gen = await client.post('/v1/generate/music', {
|
|
120
|
+
prompt, style, instrumental, lyrics
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
124
|
+
interval: (gen.poll_interval_hint || 8) * 1000,
|
|
125
|
+
timeout: 300000
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
content: [{
|
|
130
|
+
type: 'text',
|
|
131
|
+
text: JSON.stringify({
|
|
132
|
+
urls: result.result.urls,
|
|
133
|
+
title: result.result.title,
|
|
134
|
+
duration: result.result.duration,
|
|
135
|
+
lyrics: result.result.lyrics
|
|
136
|
+
}, null, 2)
|
|
137
|
+
}]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// ─── generate_speech ───────────────────────────────────────
|
|
143
|
+
server.tool(
|
|
144
|
+
'generate_speech',
|
|
145
|
+
'Convert text to speech using Kolbo AI. Returns the final audio URL when complete.',
|
|
146
|
+
{
|
|
147
|
+
text: { type: 'string', description: 'The text to convert to speech' },
|
|
148
|
+
voice: { type: 'string', description: 'Voice ID or name (e.g., "Rachel", "Adam"). Default: "Rachel"' },
|
|
149
|
+
language: { type: 'string', description: 'Language code (e.g., "en-US", "he-IL"). Default: "en-US"' }
|
|
150
|
+
},
|
|
151
|
+
async ({ text, voice, language }) => {
|
|
152
|
+
const gen = await client.post('/v1/generate/speech', {
|
|
153
|
+
text, voice, language
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
157
|
+
interval: (gen.poll_interval_hint || 5) * 1000,
|
|
158
|
+
timeout: 120000
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
content: [{
|
|
163
|
+
type: 'text',
|
|
164
|
+
text: JSON.stringify({
|
|
165
|
+
urls: result.result.urls,
|
|
166
|
+
voice: result.result.voice,
|
|
167
|
+
duration: result.result.duration
|
|
168
|
+
}, null, 2)
|
|
169
|
+
}]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// ─── generate_sound ────────────────────────────────────────
|
|
175
|
+
server.tool(
|
|
176
|
+
'generate_sound',
|
|
177
|
+
'Generate sound effects from a text description using Kolbo AI. Returns the final audio URL when complete.',
|
|
178
|
+
{
|
|
179
|
+
prompt: { type: 'string', description: 'Text description of the sound effect (e.g., "thunder clap with rain", "door creaking open")' },
|
|
180
|
+
duration: { type: 'number', description: 'Duration in seconds. Omit for auto duration.' }
|
|
181
|
+
},
|
|
182
|
+
async ({ prompt, duration }) => {
|
|
183
|
+
const gen = await client.post('/v1/generate/sound', {
|
|
184
|
+
prompt, duration
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const result = await pollUntilDone(client, gen.generation_id, {
|
|
188
|
+
interval: (gen.poll_interval_hint || 5) * 1000,
|
|
189
|
+
timeout: 120000
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
content: [{
|
|
194
|
+
type: 'text',
|
|
195
|
+
text: JSON.stringify({
|
|
196
|
+
urls: result.result.urls,
|
|
197
|
+
duration: result.result.duration
|
|
198
|
+
}, null, 2)
|
|
199
|
+
}]
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// ─── get_generation_status ─────────────────────────────────
|
|
205
|
+
server.tool(
|
|
206
|
+
'get_generation_status',
|
|
207
|
+
'Check the status of a generation. Use this if a generation tool timed out or you need to check progress.',
|
|
208
|
+
{
|
|
209
|
+
generation_id: { type: 'string', description: 'The generation ID to check' }
|
|
210
|
+
},
|
|
211
|
+
async ({ generation_id }) => {
|
|
212
|
+
const result = await client.get(`/v1/generate/${generation_id}/status`);
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
content: [{
|
|
216
|
+
type: 'text',
|
|
217
|
+
text: JSON.stringify(result, null, 2)
|
|
218
|
+
}]
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
module.exports = { registerGenerateTools };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function registerModelTools(server, client) {
|
|
2
|
+
// ─── list_models ───────────────────────────────────────────
|
|
3
|
+
server.tool(
|
|
4
|
+
'list_models',
|
|
5
|
+
'List available AI models on Kolbo. Filter by type to find models for a specific generation type.',
|
|
6
|
+
{
|
|
7
|
+
type: {
|
|
8
|
+
type: 'string',
|
|
9
|
+
description: 'Filter by type: "image", "video", "video_from_image", "music", "speech", "sound". Omit for all models.'
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
async ({ type }) => {
|
|
13
|
+
const path = type ? `/v1/models?type=${encodeURIComponent(type)}` : '/v1/models';
|
|
14
|
+
const result = await client.get(path);
|
|
15
|
+
|
|
16
|
+
// Format for readability
|
|
17
|
+
const summary = result.models.map(m =>
|
|
18
|
+
`${m.identifier} (${m.name}) - ${m.credit} credits${m.recommended ? ' [RECOMMENDED]' : ''}${m.new_model ? ' [NEW]' : ''}`
|
|
19
|
+
).join('\n');
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
content: [{
|
|
23
|
+
type: 'text',
|
|
24
|
+
text: `Available models (${result.count}):\n\n${summary}\n\nUse the "identifier" value as the "model" parameter in generate tools.`
|
|
25
|
+
}]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// ─── check_credits ─────────────────────────────────────────
|
|
31
|
+
server.tool(
|
|
32
|
+
'check_credits',
|
|
33
|
+
'Check your remaining Kolbo credit balance.',
|
|
34
|
+
{},
|
|
35
|
+
async () => {
|
|
36
|
+
const result = await client.get('/v1/account/credits');
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
content: [{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: `Credit Balance:\n- Total: ${result.credits.total}\n- Plan credits: ${result.credits.plan_credits}\n- Credit pack: ${result.credits.credit_pack}\n- Redemption: ${result.credits.redemption}`
|
|
42
|
+
}]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { registerModelTools };
|