@felores/kie-ai-mcp-server 1.1.2 → 1.2.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 +44 -49
- package/dist/index.js +160 -27
- package/dist/kie-ai-client.d.ts +2 -1
- package/dist/kie-ai-client.js +13 -2
- package/dist/types.d.ts +68 -1
- package/dist/types.js +27 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ An MCP (Model Context Protocol) server that provides access to Kie.ai's AI APIs
|
|
|
9
9
|
- **Nano Banana Image Upscaling**: Upscale images 1-4x with optional face enhancement
|
|
10
10
|
- **Veo3 Video Generation**: Professional-quality video generation with text-to-video and image-to-video capabilities
|
|
11
11
|
- **1080p Video Upgrade**: Get high-definition versions of Veo3 videos
|
|
12
|
+
- **Suno Music Generation**: AI-powered music creation with multiple models (V3_5, V4, V4_5, V4_5PLUS, V5)
|
|
12
13
|
- **Task Management**: SQLite-based task tracking with status polling
|
|
13
14
|
- **Smart Endpoint Routing**: Automatic detection of task types for status checking
|
|
14
15
|
- **Error Handling**: Comprehensive error handling and validation
|
|
@@ -87,7 +88,7 @@ Or if installed globally:
|
|
|
87
88
|
|
|
88
89
|
## Available Tools
|
|
89
90
|
|
|
90
|
-
### 1. `
|
|
91
|
+
### 1. `nano_banana_generate`
|
|
91
92
|
Generate images using Nano Banana.
|
|
92
93
|
|
|
93
94
|
**Parameters:**
|
|
@@ -104,7 +105,7 @@ Generate images using Nano Banana.
|
|
|
104
105
|
}
|
|
105
106
|
```
|
|
106
107
|
|
|
107
|
-
### 2. `
|
|
108
|
+
### 2. `nano_banana_edit`
|
|
108
109
|
Edit images using natural language prompts.
|
|
109
110
|
|
|
110
111
|
**Parameters:**
|
|
@@ -123,7 +124,7 @@ Edit images using natural language prompts.
|
|
|
123
124
|
}
|
|
124
125
|
```
|
|
125
126
|
|
|
126
|
-
### 3. `
|
|
127
|
+
### 3. `nano_banana_upscale`
|
|
127
128
|
Upscale images with optional face enhancement.
|
|
128
129
|
|
|
129
130
|
**Parameters:**
|
|
@@ -140,7 +141,7 @@ Upscale images with optional face enhancement.
|
|
|
140
141
|
}
|
|
141
142
|
```
|
|
142
143
|
|
|
143
|
-
### 4. `
|
|
144
|
+
### 4. `veo3_generate_video`
|
|
144
145
|
Generate videos using Veo3.
|
|
145
146
|
|
|
146
147
|
**Parameters:**
|
|
@@ -178,7 +179,7 @@ List recent tasks with their status.
|
|
|
178
179
|
- `limit` (integer, optional): Max tasks to return (default: 20, max: 100)
|
|
179
180
|
- `status` (string, optional): Filter by status ("pending", "processing", "completed", "failed")
|
|
180
181
|
|
|
181
|
-
### 7. `
|
|
182
|
+
### 7. `veo3_get_1080p_video`
|
|
182
183
|
Get 1080P high-definition version of a Veo3 video.
|
|
183
184
|
|
|
184
185
|
**Parameters:**
|
|
@@ -187,6 +188,38 @@ Get 1080P high-definition version of a Veo3 video.
|
|
|
187
188
|
|
|
188
189
|
**Note**: Not available for videos generated with fallback mode.
|
|
189
190
|
|
|
191
|
+
### 8. `suno_generate_music`
|
|
192
|
+
Generate music with AI using Suno models.
|
|
193
|
+
|
|
194
|
+
**Parameters:**
|
|
195
|
+
- `prompt` (string, required): Description of desired audio content (max 5000 chars for V4_5+, V5; 3000 for V3_5, V4; 500 chars for non-custom mode)
|
|
196
|
+
- `customMode` (boolean, required): Enable advanced parameter customization
|
|
197
|
+
- `instrumental` (boolean, required): Generate instrumental music (no lyrics)
|
|
198
|
+
- `model` (enum, required): AI model version - "V3_5", "V4", "V4_5", "V4_5PLUS", or "V5"
|
|
199
|
+
- `callBackUrl` (string, required): URL to receive task completion updates
|
|
200
|
+
- `style` (string, optional): Music style/genre (required in custom mode, max 1000 chars for V4_5+, V5; 200 for V3_5, V4)
|
|
201
|
+
- `title` (string, optional): Track title (required in custom mode, max 80 chars)
|
|
202
|
+
- `negativeTags` (string, optional): Music styles to exclude (max 200 chars)
|
|
203
|
+
- `vocalGender` (enum, optional): Vocal gender preference - "m" or "f" (custom mode only)
|
|
204
|
+
- `styleWeight` (number, optional): Style adherence strength (0-1, up to 2 decimal places)
|
|
205
|
+
- `weirdnessConstraint` (number, optional): Creative deviation control (0-1, up to 2 decimal places)
|
|
206
|
+
- `audioWeight` (number, optional): Audio feature balance (0-1, up to 2 decimal places)
|
|
207
|
+
|
|
208
|
+
**Example:**
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"prompt": "A calm and relaxing piano track with soft melodies",
|
|
212
|
+
"customMode": true,
|
|
213
|
+
"instrumental": true,
|
|
214
|
+
"model": "V5",
|
|
215
|
+
"callBackUrl": "https://api.example.com/callback",
|
|
216
|
+
"style": "Classical",
|
|
217
|
+
"title": "Peaceful Piano Meditation"
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Note**: In custom mode, `style` and `title` are required. If `instrumental` is false, `prompt` is used as exact lyrics.
|
|
222
|
+
|
|
190
223
|
## API Endpoints
|
|
191
224
|
|
|
192
225
|
The server interfaces with these Kie.ai API endpoints:
|
|
@@ -198,6 +231,8 @@ The server interfaces with these Kie.ai API endpoints:
|
|
|
198
231
|
- **Nano Banana Edit**: `POST /api/v1/jobs/createTask`
|
|
199
232
|
- **Nano Banana Upscale**: `POST /api/v1/jobs/createTask`
|
|
200
233
|
- **Nano Banana Status**: `GET /api/v1/jobs/recordInfo`
|
|
234
|
+
- **Suno Music Generation**: `POST /api/v1/generate` ✅ **VALIDATED**
|
|
235
|
+
- **Suno Music Status**: `GET /api/v1/generate?taskId=XXX` ✅ **VALIDATED**
|
|
201
236
|
|
|
202
237
|
All endpoints follow official Kie.ai API documentation.
|
|
203
238
|
|
|
@@ -209,7 +244,7 @@ The server uses SQLite to track tasks:
|
|
|
209
244
|
CREATE TABLE tasks (
|
|
210
245
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
211
246
|
task_id TEXT UNIQUE NOT NULL,
|
|
212
|
-
api_type TEXT NOT NULL, -- 'nano-banana', 'nano-banana-edit', 'veo3'
|
|
247
|
+
api_type TEXT NOT NULL, -- 'nano-banana', 'nano-banana-edit', 'veo3', 'suno'
|
|
213
248
|
status TEXT DEFAULT 'pending',
|
|
214
249
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
215
250
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
@@ -226,7 +261,7 @@ CREATE TABLE tasks (
|
|
|
226
261
|
curl -X POST http://localhost:3000/tools/call \
|
|
227
262
|
-H "Content-Type: application/json" \
|
|
228
263
|
-d '{
|
|
229
|
-
"name": "
|
|
264
|
+
"name": "nano_banana_generate",
|
|
230
265
|
"arguments": {
|
|
231
266
|
"prompt": "A cat wearing a space helmet"
|
|
232
267
|
}
|
|
@@ -239,7 +274,7 @@ curl -X POST http://localhost:3000/tools/call \
|
|
|
239
274
|
curl -X POST http://localhost:3000/tools/call \
|
|
240
275
|
-H "Content-Type: application/json" \
|
|
241
276
|
-d '{
|
|
242
|
-
"name": "
|
|
277
|
+
"name": "veo3_generate_video",
|
|
243
278
|
"arguments": {
|
|
244
279
|
"prompt": "A peaceful garden with blooming flowers",
|
|
245
280
|
"aspectRatio": "16:9",
|
|
@@ -335,44 +370,4 @@ MIT License - see LICENSE file for details.
|
|
|
335
370
|
|
|
336
371
|
## Changelog
|
|
337
372
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
**Improvements:**
|
|
341
|
-
- Added `KIE_AI_CALLBACK_URL` environment variable for default callback URL
|
|
342
|
-
- Added `enableTranslation` parameter to Veo3 (auto-translate prompts to English)
|
|
343
|
-
- Added `Auto` option to Veo3 `aspectRatio`
|
|
344
|
-
- Exposed `callBackUrl` parameter in Veo3 tool schema
|
|
345
|
-
- Veo3 tool now fully aligned with official Kie.ai API documentation
|
|
346
|
-
|
|
347
|
-
### v1.1.0 (2025-01-14)
|
|
348
|
-
|
|
349
|
-
**Breaking Changes:**
|
|
350
|
-
- Migrated from `/playground/*` to official `/jobs/*` API endpoints for all Nano Banana operations
|
|
351
|
-
- Updated status check endpoint from `/playground/recordInfo` to `/jobs/recordInfo`
|
|
352
|
-
|
|
353
|
-
**New Features:**
|
|
354
|
-
- Added `upscale_nano_banana` tool for image upscaling (1-4x) with optional GFPGAN face enhancement
|
|
355
|
-
- Added `output_format` parameter (png/jpeg) to `generate_nano_banana` and `edit_nano_banana`
|
|
356
|
-
- Added `image_size` parameter (11 aspect ratios) to `generate_nano_banana` and `edit_nano_banana`
|
|
357
|
-
|
|
358
|
-
**Improvements:**
|
|
359
|
-
- Increased prompt max length from 1,000 to 5,000 characters for Nano Banana tools
|
|
360
|
-
- Increased max input images from 5 to 10 for `edit_nano_banana`
|
|
361
|
-
- Enhanced `get_task_status` to properly parse `resultJson` and extract result URLs
|
|
362
|
-
- Improved task status mapping: `waiting` → `processing`, `success` → `completed`, `fail` → `failed`
|
|
363
|
-
- Task status now automatically updates local database with API responses
|
|
364
|
-
- Better error message handling from API responses
|
|
365
|
-
|
|
366
|
-
**Documentation:**
|
|
367
|
-
- Updated README with all new parameters and tools
|
|
368
|
-
- Corrected API endpoints to match official Kie.ai documentation
|
|
369
|
-
- Added comprehensive examples for all tools
|
|
370
|
-
|
|
371
|
-
### v1.0.0 (2024-12-XX)
|
|
372
|
-
- Initial release
|
|
373
|
-
- Nano Banana image generation and editing
|
|
374
|
-
- Veo3 video generation
|
|
375
|
-
- 1080p video upgrade support
|
|
376
|
-
- SQLite task tracking
|
|
377
|
-
- Smart endpoint routing
|
|
378
|
-
- Comprehensive error handling
|
|
373
|
+
See [CHANGELOG.md](CHANGELOG.md) for detailed version history and release notes.
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
4
4
|
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { KieAiClient } from './kie-ai-client.js';
|
|
6
6
|
import { TaskDatabase } from './database.js';
|
|
7
|
-
import { NanoBananaGenerateSchema, NanoBananaEditSchema, NanoBananaUpscaleSchema, Veo3GenerateSchema } from './types.js';
|
|
7
|
+
import { NanoBananaGenerateSchema, NanoBananaEditSchema, NanoBananaUpscaleSchema, Veo3GenerateSchema, SunoGenerateSchema } from './types.js';
|
|
8
8
|
class KieAiMcpServer {
|
|
9
9
|
server;
|
|
10
10
|
client;
|
|
@@ -12,7 +12,7 @@ class KieAiMcpServer {
|
|
|
12
12
|
constructor() {
|
|
13
13
|
this.server = new Server({
|
|
14
14
|
name: 'kie-ai-mcp-server',
|
|
15
|
-
version: '1.
|
|
15
|
+
version: '1.2.0',
|
|
16
16
|
});
|
|
17
17
|
// Initialize client with config from environment
|
|
18
18
|
const config = {
|
|
@@ -66,7 +66,7 @@ class KieAiMcpServer {
|
|
|
66
66
|
return {
|
|
67
67
|
tools: [
|
|
68
68
|
{
|
|
69
|
-
name: '
|
|
69
|
+
name: 'nano_banana_generate',
|
|
70
70
|
description: 'Generate images using Google\'s Gemini 2.5 Flash Image Preview (Nano Banana)',
|
|
71
71
|
inputSchema: {
|
|
72
72
|
type: 'object',
|
|
@@ -94,7 +94,7 @@ class KieAiMcpServer {
|
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
|
-
name: '
|
|
97
|
+
name: 'nano_banana_edit',
|
|
98
98
|
description: 'Edit images using natural language prompts with Nano Banana Edit',
|
|
99
99
|
inputSchema: {
|
|
100
100
|
type: 'object',
|
|
@@ -129,7 +129,7 @@ class KieAiMcpServer {
|
|
|
129
129
|
}
|
|
130
130
|
},
|
|
131
131
|
{
|
|
132
|
-
name: '
|
|
132
|
+
name: 'nano_banana_upscale',
|
|
133
133
|
description: 'Upscale images using Nano Banana Upscale with optional face enhancement',
|
|
134
134
|
inputSchema: {
|
|
135
135
|
type: 'object',
|
|
@@ -156,7 +156,7 @@ class KieAiMcpServer {
|
|
|
156
156
|
}
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
|
-
name: '
|
|
159
|
+
name: 'veo3_generate_video',
|
|
160
160
|
description: 'Generate professional-quality videos using Google\'s Veo3 API',
|
|
161
161
|
inputSchema: {
|
|
162
162
|
type: 'object',
|
|
@@ -250,7 +250,7 @@ class KieAiMcpServer {
|
|
|
250
250
|
}
|
|
251
251
|
},
|
|
252
252
|
{
|
|
253
|
-
name: '
|
|
253
|
+
name: 'veo3_get_1080p_video',
|
|
254
254
|
description: 'Get 1080P high-definition version of a Veo3 video (not available for fallback mode videos)',
|
|
255
255
|
inputSchema: {
|
|
256
256
|
type: 'object',
|
|
@@ -267,6 +267,81 @@ class KieAiMcpServer {
|
|
|
267
267
|
},
|
|
268
268
|
required: ['task_id']
|
|
269
269
|
}
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: 'suno_generate_music',
|
|
273
|
+
description: 'Generate music with AI using Suno models (V3_5, V4, V4_5, V4_5PLUS, V5)',
|
|
274
|
+
inputSchema: {
|
|
275
|
+
type: 'object',
|
|
276
|
+
properties: {
|
|
277
|
+
prompt: {
|
|
278
|
+
type: 'string',
|
|
279
|
+
description: 'Description of the desired audio content. In custom mode: used as exact lyrics (max 5000 chars for V4_5+, V5; 3000 for V3_5, V4). In non-custom mode: core idea for auto-generated lyrics (max 500 chars)',
|
|
280
|
+
minLength: 1,
|
|
281
|
+
maxLength: 5000
|
|
282
|
+
},
|
|
283
|
+
customMode: {
|
|
284
|
+
type: 'boolean',
|
|
285
|
+
description: 'Enable advanced parameter customization. If true: requires style and title. If false: simplified mode with only prompt required'
|
|
286
|
+
},
|
|
287
|
+
instrumental: {
|
|
288
|
+
type: 'boolean',
|
|
289
|
+
description: 'Generate instrumental music (no lyrics). In custom mode: if true, only style and title required; if false, prompt used as exact lyrics'
|
|
290
|
+
},
|
|
291
|
+
model: {
|
|
292
|
+
type: 'string',
|
|
293
|
+
description: 'AI model version for generation',
|
|
294
|
+
enum: ['V3_5', 'V4', 'V4_5', 'V4_5PLUS', 'V5']
|
|
295
|
+
},
|
|
296
|
+
callBackUrl: {
|
|
297
|
+
type: 'string',
|
|
298
|
+
description: 'URL to receive task completion updates (required for all requests)',
|
|
299
|
+
format: 'uri'
|
|
300
|
+
},
|
|
301
|
+
style: {
|
|
302
|
+
type: 'string',
|
|
303
|
+
description: 'Music style/genre (required in custom mode, max 1000 chars for V4_5+, V5; 200 for V3_5, V4)',
|
|
304
|
+
maxLength: 1000
|
|
305
|
+
},
|
|
306
|
+
title: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: 'Track title (required in custom mode, max 80 chars)',
|
|
309
|
+
maxLength: 80
|
|
310
|
+
},
|
|
311
|
+
negativeTags: {
|
|
312
|
+
type: 'string',
|
|
313
|
+
description: 'Music styles to exclude (optional, max 200 chars)',
|
|
314
|
+
maxLength: 200
|
|
315
|
+
},
|
|
316
|
+
vocalGender: {
|
|
317
|
+
type: 'string',
|
|
318
|
+
description: 'Vocal gender preference (optional, only effective in custom mode)',
|
|
319
|
+
enum: ['m', 'f']
|
|
320
|
+
},
|
|
321
|
+
styleWeight: {
|
|
322
|
+
type: 'number',
|
|
323
|
+
description: 'Strength of style adherence (optional, range 0-1, up to 2 decimal places)',
|
|
324
|
+
minimum: 0,
|
|
325
|
+
maximum: 1,
|
|
326
|
+
multipleOf: 0.01
|
|
327
|
+
},
|
|
328
|
+
weirdnessConstraint: {
|
|
329
|
+
type: 'number',
|
|
330
|
+
description: 'Controls experimental/creative deviation (optional, range 0-1, up to 2 decimal places)',
|
|
331
|
+
minimum: 0,
|
|
332
|
+
maximum: 1,
|
|
333
|
+
multipleOf: 0.01
|
|
334
|
+
},
|
|
335
|
+
audioWeight: {
|
|
336
|
+
type: 'number',
|
|
337
|
+
description: 'Balance weight for audio features (optional, range 0-1, up to 2 decimal places)',
|
|
338
|
+
minimum: 0,
|
|
339
|
+
maximum: 1,
|
|
340
|
+
multipleOf: 0.01
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
required: ['prompt', 'customMode', 'instrumental', 'model', 'callBackUrl']
|
|
344
|
+
}
|
|
270
345
|
}
|
|
271
346
|
]
|
|
272
347
|
};
|
|
@@ -275,20 +350,22 @@ class KieAiMcpServer {
|
|
|
275
350
|
try {
|
|
276
351
|
const { name, arguments: args } = request.params;
|
|
277
352
|
switch (name) {
|
|
278
|
-
case '
|
|
279
|
-
return await this.
|
|
280
|
-
case '
|
|
281
|
-
return await this.
|
|
282
|
-
case '
|
|
283
|
-
return await this.
|
|
284
|
-
case '
|
|
285
|
-
return await this.
|
|
353
|
+
case 'nano_banana_generate':
|
|
354
|
+
return await this.handleNanoBananaGenerate(args);
|
|
355
|
+
case 'nano_banana_edit':
|
|
356
|
+
return await this.handleNanoBananaEdit(args);
|
|
357
|
+
case 'nano_banana_upscale':
|
|
358
|
+
return await this.handleNanoBananaUpscale(args);
|
|
359
|
+
case 'veo3_generate_video':
|
|
360
|
+
return await this.handleVeo3GenerateVideo(args);
|
|
286
361
|
case 'get_task_status':
|
|
287
362
|
return await this.handleGetTaskStatus(args);
|
|
288
363
|
case 'list_tasks':
|
|
289
364
|
return await this.handleListTasks(args);
|
|
290
|
-
case '
|
|
291
|
-
return await this.
|
|
365
|
+
case 'veo3_get_1080p_video':
|
|
366
|
+
return await this.handleVeo3Get1080pVideo(args);
|
|
367
|
+
case 'suno_generate_music':
|
|
368
|
+
return await this.handleSunoGenerateMusic(args);
|
|
292
369
|
default:
|
|
293
370
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
294
371
|
}
|
|
@@ -302,7 +379,7 @@ class KieAiMcpServer {
|
|
|
302
379
|
}
|
|
303
380
|
});
|
|
304
381
|
}
|
|
305
|
-
async
|
|
382
|
+
async handleNanoBananaGenerate(args) {
|
|
306
383
|
try {
|
|
307
384
|
const request = NanoBananaGenerateSchema.parse(args);
|
|
308
385
|
const response = await this.client.generateNanoBanana(request);
|
|
@@ -328,14 +405,14 @@ class KieAiMcpServer {
|
|
|
328
405
|
};
|
|
329
406
|
}
|
|
330
407
|
catch (error) {
|
|
331
|
-
return this.formatError('
|
|
408
|
+
return this.formatError('nano_banana_generate', error, {
|
|
332
409
|
prompt: 'Required: text description of image to generate (max 5000 chars)',
|
|
333
410
|
output_format: 'Optional: "png" or "jpeg"',
|
|
334
411
|
image_size: 'Optional: aspect ratio like "16:9", "1:1", etc.'
|
|
335
412
|
});
|
|
336
413
|
}
|
|
337
414
|
}
|
|
338
|
-
async
|
|
415
|
+
async handleNanoBananaEdit(args) {
|
|
339
416
|
try {
|
|
340
417
|
const request = NanoBananaEditSchema.parse(args);
|
|
341
418
|
const response = await this.client.editNanoBanana(request);
|
|
@@ -361,7 +438,7 @@ class KieAiMcpServer {
|
|
|
361
438
|
};
|
|
362
439
|
}
|
|
363
440
|
catch (error) {
|
|
364
|
-
return this.formatError('
|
|
441
|
+
return this.formatError('nano_banana_edit', error, {
|
|
365
442
|
prompt: 'Required: editing instructions (max 5000 chars)',
|
|
366
443
|
image_urls: 'Required: array of 1-10 image URLs to edit',
|
|
367
444
|
output_format: 'Optional: "png" or "jpeg"',
|
|
@@ -369,7 +446,7 @@ class KieAiMcpServer {
|
|
|
369
446
|
});
|
|
370
447
|
}
|
|
371
448
|
}
|
|
372
|
-
async
|
|
449
|
+
async handleNanoBananaUpscale(args) {
|
|
373
450
|
try {
|
|
374
451
|
const request = NanoBananaUpscaleSchema.parse(args);
|
|
375
452
|
const response = await this.client.upscaleNanaBanana(request);
|
|
@@ -395,14 +472,14 @@ class KieAiMcpServer {
|
|
|
395
472
|
};
|
|
396
473
|
}
|
|
397
474
|
catch (error) {
|
|
398
|
-
return this.formatError('
|
|
475
|
+
return this.formatError('nano_banana_upscale', error, {
|
|
399
476
|
image: 'Required: URL of image to upscale (jpeg/png/webp, max 10MB)',
|
|
400
477
|
scale: 'Optional: upscale factor 1-4 (default: 2)',
|
|
401
478
|
face_enhance: 'Optional: enable face enhancement (default: false)'
|
|
402
479
|
});
|
|
403
480
|
}
|
|
404
481
|
}
|
|
405
|
-
async
|
|
482
|
+
async handleVeo3GenerateVideo(args) {
|
|
406
483
|
try {
|
|
407
484
|
const request = Veo3GenerateSchema.parse(args);
|
|
408
485
|
// Use environment variable as fallback if callBackUrl not provided
|
|
@@ -432,7 +509,7 @@ class KieAiMcpServer {
|
|
|
432
509
|
};
|
|
433
510
|
}
|
|
434
511
|
catch (error) {
|
|
435
|
-
return this.formatError('
|
|
512
|
+
return this.formatError('veo3_generate_video', error, {
|
|
436
513
|
prompt: 'Required: video description (max 2000 chars)',
|
|
437
514
|
imageUrls: 'Optional: array with 1 image URL for image-to-video',
|
|
438
515
|
model: 'Optional: "veo3" (quality) or "veo3_fast" (cost-efficient)',
|
|
@@ -544,7 +621,7 @@ class KieAiMcpServer {
|
|
|
544
621
|
});
|
|
545
622
|
}
|
|
546
623
|
}
|
|
547
|
-
async
|
|
624
|
+
async handleVeo3Get1080pVideo(args) {
|
|
548
625
|
try {
|
|
549
626
|
const { task_id, index } = args;
|
|
550
627
|
if (!task_id || typeof task_id !== 'string') {
|
|
@@ -567,12 +644,68 @@ class KieAiMcpServer {
|
|
|
567
644
|
};
|
|
568
645
|
}
|
|
569
646
|
catch (error) {
|
|
570
|
-
return this.formatError('
|
|
647
|
+
return this.formatError('veo3_get_1080p_video', error, {
|
|
571
648
|
task_id: 'Required: Veo3 task ID to get 1080p video for',
|
|
572
649
|
index: 'Optional: video index (for multiple video results)'
|
|
573
650
|
});
|
|
574
651
|
}
|
|
575
652
|
}
|
|
653
|
+
async handleSunoGenerateMusic(args) {
|
|
654
|
+
try {
|
|
655
|
+
const request = SunoGenerateSchema.parse(args);
|
|
656
|
+
const response = await this.client.generateSunoMusic(request);
|
|
657
|
+
if (response.code === 200 && response.data?.taskId) {
|
|
658
|
+
// Store task in database
|
|
659
|
+
await this.db.createTask({
|
|
660
|
+
task_id: response.data.taskId,
|
|
661
|
+
api_type: 'suno',
|
|
662
|
+
status: 'pending'
|
|
663
|
+
});
|
|
664
|
+
return {
|
|
665
|
+
content: [
|
|
666
|
+
{
|
|
667
|
+
type: 'text',
|
|
668
|
+
text: JSON.stringify({
|
|
669
|
+
success: true,
|
|
670
|
+
task_id: response.data.taskId,
|
|
671
|
+
message: 'Music generation task created successfully',
|
|
672
|
+
parameters: {
|
|
673
|
+
model: request.model,
|
|
674
|
+
customMode: request.customMode,
|
|
675
|
+
instrumental: request.instrumental,
|
|
676
|
+
callBackUrl: request.callBackUrl
|
|
677
|
+
},
|
|
678
|
+
next_steps: [
|
|
679
|
+
'Use get_task_status to check generation progress',
|
|
680
|
+
'Task completion will be sent to the provided callback URL',
|
|
681
|
+
'Generation typically takes 1-3 minutes depending on model and length'
|
|
682
|
+
]
|
|
683
|
+
}, null, 2)
|
|
684
|
+
}
|
|
685
|
+
]
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
throw new Error(response.msg || 'Failed to create music generation task');
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
return this.formatError('suno_generate_music', error, {
|
|
694
|
+
prompt: 'Required: Description of desired audio content',
|
|
695
|
+
customMode: 'Required: Enable advanced customization (true/false)',
|
|
696
|
+
instrumental: 'Required: Generate instrumental music (true/false)',
|
|
697
|
+
model: 'Required: AI model version (V3_5, V4, V4_5, V4_5PLUS, V5)',
|
|
698
|
+
callBackUrl: 'Required: URL for task completion notifications',
|
|
699
|
+
style: 'Optional: Music style/genre (required in custom mode)',
|
|
700
|
+
title: 'Optional: Track title (required in custom mode, max 80 chars)',
|
|
701
|
+
negativeTags: 'Optional: Styles to exclude (max 200 chars)',
|
|
702
|
+
vocalGender: 'Optional: Vocal gender preference (m/f, custom mode only)',
|
|
703
|
+
styleWeight: 'Optional: Style adherence strength (0-1, 2 decimal places)',
|
|
704
|
+
weirdnessConstraint: 'Optional: Creative deviation control (0-1, 2 decimal places)',
|
|
705
|
+
audioWeight: 'Optional: Audio feature balance (0-1, 2 decimal places)'
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
}
|
|
576
709
|
async run() {
|
|
577
710
|
const transport = new StdioServerTransport();
|
|
578
711
|
await this.server.connect(transport);
|
package/dist/kie-ai-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KieAiConfig, KieAiResponse, NanoBananaGenerateRequest, NanaBananaEditRequest, NanoBananaUpscaleRequest, Veo3GenerateRequest, ImageResponse, TaskResponse } from './types.js';
|
|
1
|
+
import { KieAiConfig, KieAiResponse, NanoBananaGenerateRequest, NanaBananaEditRequest, NanoBananaUpscaleRequest, Veo3GenerateRequest, SunoGenerateRequest, ImageResponse, TaskResponse } from './types.js';
|
|
2
2
|
export declare class KieAiClient {
|
|
3
3
|
private config;
|
|
4
4
|
constructor(config: KieAiConfig);
|
|
@@ -8,5 +8,6 @@ export declare class KieAiClient {
|
|
|
8
8
|
upscaleNanaBanana(request: NanoBananaUpscaleRequest): Promise<KieAiResponse<ImageResponse>>;
|
|
9
9
|
generateVeo3Video(request: Veo3GenerateRequest): Promise<KieAiResponse<TaskResponse>>;
|
|
10
10
|
getTaskStatus(taskId: string, apiType?: string): Promise<KieAiResponse<any>>;
|
|
11
|
+
generateSunoMusic(request: SunoGenerateRequest): Promise<KieAiResponse<TaskResponse>>;
|
|
11
12
|
getVeo1080pVideo(taskId: string, index?: number): Promise<KieAiResponse<any>>;
|
|
12
13
|
}
|
package/dist/kie-ai-client.js
CHANGED
|
@@ -77,7 +77,10 @@ export class KieAiClient {
|
|
|
77
77
|
else if (apiType === 'nano-banana' || apiType === 'nano-banana-edit' || apiType === 'nano-banana-upscale') {
|
|
78
78
|
return this.makeRequest(`/jobs/recordInfo?taskId=${taskId}`, 'GET');
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
else if (apiType === 'suno') {
|
|
81
|
+
return this.makeRequest(`/generate?taskId=${taskId}`, 'GET');
|
|
82
|
+
}
|
|
83
|
+
// Fallback: try jobs first, then veo, then generate (for tasks not in database)
|
|
81
84
|
try {
|
|
82
85
|
return await this.makeRequest(`/jobs/recordInfo?taskId=${taskId}`, 'GET');
|
|
83
86
|
}
|
|
@@ -86,10 +89,18 @@ export class KieAiClient {
|
|
|
86
89
|
return await this.makeRequest(`/veo/record-info?taskId=${taskId}`, 'GET');
|
|
87
90
|
}
|
|
88
91
|
catch (veoError) {
|
|
89
|
-
|
|
92
|
+
try {
|
|
93
|
+
return await this.makeRequest(`/generate?taskId=${taskId}`, 'GET');
|
|
94
|
+
}
|
|
95
|
+
catch (sunoError) {
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
100
|
}
|
|
101
|
+
async generateSunoMusic(request) {
|
|
102
|
+
return this.makeRequest('/generate', 'POST', request);
|
|
103
|
+
}
|
|
93
104
|
async getVeo1080pVideo(taskId, index) {
|
|
94
105
|
const params = new URLSearchParams({ taskId });
|
|
95
106
|
if (index !== undefined) {
|
package/dist/types.d.ts
CHANGED
|
@@ -72,10 +72,77 @@ export declare const Veo3GenerateSchema: z.ZodObject<{
|
|
|
72
72
|
enableFallback?: boolean | undefined;
|
|
73
73
|
enableTranslation?: boolean | undefined;
|
|
74
74
|
}>;
|
|
75
|
+
export declare const SunoGenerateSchema: z.ZodEffects<z.ZodObject<{
|
|
76
|
+
prompt: z.ZodString;
|
|
77
|
+
customMode: z.ZodBoolean;
|
|
78
|
+
instrumental: z.ZodBoolean;
|
|
79
|
+
model: z.ZodEnum<["V3_5", "V4", "V4_5", "V4_5PLUS", "V5"]>;
|
|
80
|
+
callBackUrl: z.ZodString;
|
|
81
|
+
style: z.ZodOptional<z.ZodString>;
|
|
82
|
+
title: z.ZodOptional<z.ZodString>;
|
|
83
|
+
negativeTags: z.ZodOptional<z.ZodString>;
|
|
84
|
+
vocalGender: z.ZodOptional<z.ZodEnum<["m", "f"]>>;
|
|
85
|
+
styleWeight: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
weirdnessConstraint: z.ZodOptional<z.ZodNumber>;
|
|
87
|
+
audioWeight: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
}, "strip", z.ZodTypeAny, {
|
|
89
|
+
prompt: string;
|
|
90
|
+
model: "V3_5" | "V4" | "V4_5" | "V4_5PLUS" | "V5";
|
|
91
|
+
callBackUrl: string;
|
|
92
|
+
customMode: boolean;
|
|
93
|
+
instrumental: boolean;
|
|
94
|
+
style?: string | undefined;
|
|
95
|
+
title?: string | undefined;
|
|
96
|
+
negativeTags?: string | undefined;
|
|
97
|
+
vocalGender?: "m" | "f" | undefined;
|
|
98
|
+
styleWeight?: number | undefined;
|
|
99
|
+
weirdnessConstraint?: number | undefined;
|
|
100
|
+
audioWeight?: number | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
prompt: string;
|
|
103
|
+
model: "V3_5" | "V4" | "V4_5" | "V4_5PLUS" | "V5";
|
|
104
|
+
callBackUrl: string;
|
|
105
|
+
customMode: boolean;
|
|
106
|
+
instrumental: boolean;
|
|
107
|
+
style?: string | undefined;
|
|
108
|
+
title?: string | undefined;
|
|
109
|
+
negativeTags?: string | undefined;
|
|
110
|
+
vocalGender?: "m" | "f" | undefined;
|
|
111
|
+
styleWeight?: number | undefined;
|
|
112
|
+
weirdnessConstraint?: number | undefined;
|
|
113
|
+
audioWeight?: number | undefined;
|
|
114
|
+
}>, {
|
|
115
|
+
prompt: string;
|
|
116
|
+
model: "V3_5" | "V4" | "V4_5" | "V4_5PLUS" | "V5";
|
|
117
|
+
callBackUrl: string;
|
|
118
|
+
customMode: boolean;
|
|
119
|
+
instrumental: boolean;
|
|
120
|
+
style?: string | undefined;
|
|
121
|
+
title?: string | undefined;
|
|
122
|
+
negativeTags?: string | undefined;
|
|
123
|
+
vocalGender?: "m" | "f" | undefined;
|
|
124
|
+
styleWeight?: number | undefined;
|
|
125
|
+
weirdnessConstraint?: number | undefined;
|
|
126
|
+
audioWeight?: number | undefined;
|
|
127
|
+
}, {
|
|
128
|
+
prompt: string;
|
|
129
|
+
model: "V3_5" | "V4" | "V4_5" | "V4_5PLUS" | "V5";
|
|
130
|
+
callBackUrl: string;
|
|
131
|
+
customMode: boolean;
|
|
132
|
+
instrumental: boolean;
|
|
133
|
+
style?: string | undefined;
|
|
134
|
+
title?: string | undefined;
|
|
135
|
+
negativeTags?: string | undefined;
|
|
136
|
+
vocalGender?: "m" | "f" | undefined;
|
|
137
|
+
styleWeight?: number | undefined;
|
|
138
|
+
weirdnessConstraint?: number | undefined;
|
|
139
|
+
audioWeight?: number | undefined;
|
|
140
|
+
}>;
|
|
75
141
|
export type NanoBananaGenerateRequest = z.infer<typeof NanoBananaGenerateSchema>;
|
|
76
142
|
export type NanaBananaEditRequest = z.infer<typeof NanoBananaEditSchema>;
|
|
77
143
|
export type NanoBananaUpscaleRequest = z.infer<typeof NanoBananaUpscaleSchema>;
|
|
78
144
|
export type Veo3GenerateRequest = z.infer<typeof Veo3GenerateSchema>;
|
|
145
|
+
export type SunoGenerateRequest = z.infer<typeof SunoGenerateSchema>;
|
|
79
146
|
export interface KieAiResponse<T = any> {
|
|
80
147
|
code: number;
|
|
81
148
|
msg: string;
|
|
@@ -91,7 +158,7 @@ export interface TaskResponse {
|
|
|
91
158
|
export interface TaskRecord {
|
|
92
159
|
id?: number;
|
|
93
160
|
task_id: string;
|
|
94
|
-
api_type: 'nano-banana' | 'nano-banana-edit' | 'nano-banana-upscale' | 'veo3';
|
|
161
|
+
api_type: 'nano-banana' | 'nano-banana-edit' | 'nano-banana-upscale' | 'veo3' | 'suno';
|
|
95
162
|
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
96
163
|
created_at: string;
|
|
97
164
|
updated_at: string;
|
package/dist/types.js
CHANGED
|
@@ -27,3 +27,30 @@ export const Veo3GenerateSchema = z.object({
|
|
|
27
27
|
enableFallback: z.boolean().default(false),
|
|
28
28
|
enableTranslation: z.boolean().default(true).optional()
|
|
29
29
|
});
|
|
30
|
+
export const SunoGenerateSchema = z.object({
|
|
31
|
+
prompt: z.string().min(1).max(5000),
|
|
32
|
+
customMode: z.boolean(),
|
|
33
|
+
instrumental: z.boolean(),
|
|
34
|
+
model: z.enum(['V3_5', 'V4', 'V4_5', 'V4_5PLUS', 'V5']),
|
|
35
|
+
callBackUrl: z.string().url(),
|
|
36
|
+
style: z.string().max(1000).optional(),
|
|
37
|
+
title: z.string().max(80).optional(),
|
|
38
|
+
negativeTags: z.string().max(200).optional(),
|
|
39
|
+
vocalGender: z.enum(['m', 'f']).optional(),
|
|
40
|
+
styleWeight: z.number().min(0).max(1).multipleOf(0.01).optional(),
|
|
41
|
+
weirdnessConstraint: z.number().min(0).max(1).multipleOf(0.01).optional(),
|
|
42
|
+
audioWeight: z.number().min(0).max(1).multipleOf(0.01).optional()
|
|
43
|
+
}).refine((data) => {
|
|
44
|
+
if (data.customMode) {
|
|
45
|
+
if (data.instrumental) {
|
|
46
|
+
return data.style && data.title;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return data.style && data.title && data.prompt;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}, {
|
|
54
|
+
message: "In customMode: style and title are always required, prompt is required when instrumental is false",
|
|
55
|
+
path: ["customMode"]
|
|
56
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@felores/kie-ai-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server for Kie.ai APIs (Nano Banana image generation/editing and Veo3 video generation)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,6 +34,13 @@
|
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/felores/kie-ai-mcp-server/issues"
|
|
36
36
|
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/felores/kie-ai-mcp-server.git"
|
|
43
|
+
},
|
|
37
44
|
"dependencies": {
|
|
38
45
|
"@modelcontextprotocol/sdk": "^0.4.0",
|
|
39
46
|
"sqlite3": "^5.1.6",
|