@felores/kie-ai-mcp-server 1.1.0 → 1.1.2
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 +16 -3
- package/dist/index.js +103 -101
- package/dist/types.d.ts +6 -3
- package/dist/types.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ export KIE_AI_API_KEY="your-api-key-here"
|
|
|
52
52
|
export KIE_AI_BASE_URL="https://api.kie.ai/api/v1" # Default
|
|
53
53
|
export KIE_AI_TIMEOUT="60000" # Default: 60 seconds
|
|
54
54
|
export KIE_AI_DB_PATH="./tasks.db" # Default: ./tasks.db
|
|
55
|
+
export KIE_AI_CALLBACK_URL="https://your-domain.com/api/callback" # Default callback URL for video generation
|
|
55
56
|
```
|
|
56
57
|
|
|
57
58
|
### MCP Configuration
|
|
@@ -146,10 +147,12 @@ Generate videos using Veo3.
|
|
|
146
147
|
- `prompt` (string, required): Video description
|
|
147
148
|
- `imageUrls` (array, optional): Image for image-to-video (max 1)
|
|
148
149
|
- `model` (enum, optional): "veo3" or "veo3_fast" (default: "veo3")
|
|
149
|
-
- `aspectRatio` (enum, optional): "16:9"
|
|
150
|
+
- `aspectRatio` (enum, optional): "16:9", "9:16", or "Auto" (default: "16:9", only 16:9 supports 1080P)
|
|
150
151
|
- `seeds` (integer, optional): Random seed 10000-99999
|
|
151
152
|
- `watermark` (string, optional): Watermark text
|
|
152
|
-
- `
|
|
153
|
+
- `callBackUrl` (string, optional): Callback URL for completion notifications
|
|
154
|
+
- `enableFallback` (boolean, optional): Enable fallback mechanism (default: false, fallback videos cannot use 1080P endpoint)
|
|
155
|
+
- `enableTranslation` (boolean, optional): Auto-translate prompts to English (default: true)
|
|
153
156
|
|
|
154
157
|
**Example:**
|
|
155
158
|
```json
|
|
@@ -157,7 +160,8 @@ Generate videos using Veo3.
|
|
|
157
160
|
"prompt": "A dog playing in a park",
|
|
158
161
|
"model": "veo3",
|
|
159
162
|
"aspectRatio": "16:9",
|
|
160
|
-
"seeds": 12345
|
|
163
|
+
"seeds": 12345,
|
|
164
|
+
"enableTranslation": true
|
|
161
165
|
}
|
|
162
166
|
```
|
|
163
167
|
|
|
@@ -331,6 +335,15 @@ MIT License - see LICENSE file for details.
|
|
|
331
335
|
|
|
332
336
|
## Changelog
|
|
333
337
|
|
|
338
|
+
### v1.1.1 (2025-01-14)
|
|
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
|
+
|
|
334
347
|
### v1.1.0 (2025-01-14)
|
|
335
348
|
|
|
336
349
|
**Breaking Changes:**
|
package/dist/index.js
CHANGED
|
@@ -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.1.
|
|
15
|
+
version: '1.1.2',
|
|
16
16
|
});
|
|
17
17
|
// Initialize client with config from environment
|
|
18
18
|
const config = {
|
|
@@ -27,6 +27,40 @@ class KieAiMcpServer {
|
|
|
27
27
|
this.db = new TaskDatabase(process.env.KIE_AI_DB_PATH);
|
|
28
28
|
this.setupHandlers();
|
|
29
29
|
}
|
|
30
|
+
formatError(toolName, error, paramDescriptions) {
|
|
31
|
+
let errorMessage = 'Unknown error';
|
|
32
|
+
let errorDetails = '';
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
errorMessage = error.message;
|
|
35
|
+
// Check for Zod validation errors
|
|
36
|
+
if (errorMessage.includes('ZodError')) {
|
|
37
|
+
const lines = errorMessage.split('\n');
|
|
38
|
+
const validationErrors = lines.filter(line => line.includes('Expected') || line.includes('Required') || line.includes('Invalid'));
|
|
39
|
+
if (validationErrors.length > 0) {
|
|
40
|
+
errorDetails = `Validation errors:\n${validationErrors.map(err => `- ${err.trim()}`).join('\n')}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Build parameter guidance
|
|
45
|
+
const paramGuidance = Object.entries(paramDescriptions)
|
|
46
|
+
.map(([param, desc]) => `- ${param}: ${desc}`)
|
|
47
|
+
.join('\n');
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: 'text',
|
|
52
|
+
text: JSON.stringify({
|
|
53
|
+
success: false,
|
|
54
|
+
tool: toolName,
|
|
55
|
+
error: errorMessage,
|
|
56
|
+
details: errorDetails,
|
|
57
|
+
parameter_guidance: paramGuidance,
|
|
58
|
+
message: `Failed to execute ${toolName}. Check parameters and try again.`
|
|
59
|
+
}, null, 2)
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
30
64
|
setupHandlers() {
|
|
31
65
|
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
32
66
|
return {
|
|
@@ -152,8 +186,8 @@ class KieAiMcpServer {
|
|
|
152
186
|
},
|
|
153
187
|
aspectRatio: {
|
|
154
188
|
type: 'string',
|
|
155
|
-
enum: ['16:9', '9:16'],
|
|
156
|
-
description: 'Video aspect ratio',
|
|
189
|
+
enum: ['16:9', '9:16', 'Auto'],
|
|
190
|
+
description: 'Video aspect ratio (16:9 supports 1080P)',
|
|
157
191
|
default: '16:9'
|
|
158
192
|
},
|
|
159
193
|
seeds: {
|
|
@@ -162,10 +196,20 @@ class KieAiMcpServer {
|
|
|
162
196
|
minimum: 10000,
|
|
163
197
|
maximum: 99999
|
|
164
198
|
},
|
|
199
|
+
callBackUrl: {
|
|
200
|
+
type: 'string',
|
|
201
|
+
format: 'uri',
|
|
202
|
+
description: 'Callback URL for task completion notifications'
|
|
203
|
+
},
|
|
165
204
|
enableFallback: {
|
|
166
205
|
type: 'boolean',
|
|
167
|
-
description: 'Enable fallback mechanism for content policy failures',
|
|
206
|
+
description: 'Enable fallback mechanism for content policy failures (Note: fallback videos cannot use 1080P endpoint)',
|
|
168
207
|
default: false
|
|
208
|
+
},
|
|
209
|
+
enableTranslation: {
|
|
210
|
+
type: 'boolean',
|
|
211
|
+
description: 'Auto-translate prompts to English for better results',
|
|
212
|
+
default: true
|
|
169
213
|
}
|
|
170
214
|
},
|
|
171
215
|
required: ['prompt']
|
|
@@ -259,8 +303,8 @@ class KieAiMcpServer {
|
|
|
259
303
|
});
|
|
260
304
|
}
|
|
261
305
|
async handleGenerateNanoBanana(args) {
|
|
262
|
-
const request = NanoBananaGenerateSchema.parse(args);
|
|
263
306
|
try {
|
|
307
|
+
const request = NanoBananaGenerateSchema.parse(args);
|
|
264
308
|
const response = await this.client.generateNanoBanana(request);
|
|
265
309
|
if (response.data?.taskId) {
|
|
266
310
|
await this.db.createTask({
|
|
@@ -284,23 +328,16 @@ class KieAiMcpServer {
|
|
|
284
328
|
};
|
|
285
329
|
}
|
|
286
330
|
catch (error) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
text: JSON.stringify({
|
|
293
|
-
success: false,
|
|
294
|
-
error: message
|
|
295
|
-
}, null, 2)
|
|
296
|
-
}
|
|
297
|
-
]
|
|
298
|
-
};
|
|
331
|
+
return this.formatError('generate_nano_banana', error, {
|
|
332
|
+
prompt: 'Required: text description of image to generate (max 5000 chars)',
|
|
333
|
+
output_format: 'Optional: "png" or "jpeg"',
|
|
334
|
+
image_size: 'Optional: aspect ratio like "16:9", "1:1", etc.'
|
|
335
|
+
});
|
|
299
336
|
}
|
|
300
337
|
}
|
|
301
338
|
async handleEditNanoBanana(args) {
|
|
302
|
-
const request = NanoBananaEditSchema.parse(args);
|
|
303
339
|
try {
|
|
340
|
+
const request = NanoBananaEditSchema.parse(args);
|
|
304
341
|
const response = await this.client.editNanoBanana(request);
|
|
305
342
|
if (response.data?.taskId) {
|
|
306
343
|
await this.db.createTask({
|
|
@@ -324,23 +361,17 @@ class KieAiMcpServer {
|
|
|
324
361
|
};
|
|
325
362
|
}
|
|
326
363
|
catch (error) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
success: false,
|
|
334
|
-
error: message
|
|
335
|
-
}, null, 2)
|
|
336
|
-
}
|
|
337
|
-
]
|
|
338
|
-
};
|
|
364
|
+
return this.formatError('edit_nano_banana', error, {
|
|
365
|
+
prompt: 'Required: editing instructions (max 5000 chars)',
|
|
366
|
+
image_urls: 'Required: array of 1-10 image URLs to edit',
|
|
367
|
+
output_format: 'Optional: "png" or "jpeg"',
|
|
368
|
+
image_size: 'Optional: aspect ratio like "16:9", "1:1", etc.'
|
|
369
|
+
});
|
|
339
370
|
}
|
|
340
371
|
}
|
|
341
372
|
async handleUpscaleNanoBanana(args) {
|
|
342
|
-
const request = NanoBananaUpscaleSchema.parse(args);
|
|
343
373
|
try {
|
|
374
|
+
const request = NanoBananaUpscaleSchema.parse(args);
|
|
344
375
|
const response = await this.client.upscaleNanaBanana(request);
|
|
345
376
|
if (response.data?.taskId) {
|
|
346
377
|
await this.db.createTask({
|
|
@@ -364,23 +395,20 @@ class KieAiMcpServer {
|
|
|
364
395
|
};
|
|
365
396
|
}
|
|
366
397
|
catch (error) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
text: JSON.stringify({
|
|
373
|
-
success: false,
|
|
374
|
-
error: message
|
|
375
|
-
}, null, 2)
|
|
376
|
-
}
|
|
377
|
-
]
|
|
378
|
-
};
|
|
398
|
+
return this.formatError('upscale_nano_banana', error, {
|
|
399
|
+
image: 'Required: URL of image to upscale (jpeg/png/webp, max 10MB)',
|
|
400
|
+
scale: 'Optional: upscale factor 1-4 (default: 2)',
|
|
401
|
+
face_enhance: 'Optional: enable face enhancement (default: false)'
|
|
402
|
+
});
|
|
379
403
|
}
|
|
380
404
|
}
|
|
381
405
|
async handleGenerateVeo3Video(args) {
|
|
382
|
-
const request = Veo3GenerateSchema.parse(args);
|
|
383
406
|
try {
|
|
407
|
+
const request = Veo3GenerateSchema.parse(args);
|
|
408
|
+
// Use environment variable as fallback if callBackUrl not provided
|
|
409
|
+
if (!request.callBackUrl && process.env.KIE_AI_CALLBACK_URL) {
|
|
410
|
+
request.callBackUrl = process.env.KIE_AI_CALLBACK_URL;
|
|
411
|
+
}
|
|
384
412
|
const response = await this.client.generateVeo3Video(request);
|
|
385
413
|
if (response.data?.taskId) {
|
|
386
414
|
await this.db.createTask({
|
|
@@ -404,26 +432,25 @@ class KieAiMcpServer {
|
|
|
404
432
|
};
|
|
405
433
|
}
|
|
406
434
|
catch (error) {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
};
|
|
435
|
+
return this.formatError('generate_veo3_video', error, {
|
|
436
|
+
prompt: 'Required: video description (max 2000 chars)',
|
|
437
|
+
imageUrls: 'Optional: array with 1 image URL for image-to-video',
|
|
438
|
+
model: 'Optional: "veo3" (quality) or "veo3_fast" (cost-efficient)',
|
|
439
|
+
watermark: 'Optional: watermark text (max 100 chars)',
|
|
440
|
+
aspectRatio: 'Optional: "16:9", "9:16", or "Auto"',
|
|
441
|
+
seeds: 'Optional: random seed (10000-99999)',
|
|
442
|
+
callBackUrl: 'Optional: callback URL for notifications',
|
|
443
|
+
enableFallback: 'Optional: enable fallback for content policy failures',
|
|
444
|
+
enableTranslation: 'Optional: auto-translate prompts to English'
|
|
445
|
+
});
|
|
419
446
|
}
|
|
420
447
|
}
|
|
421
448
|
async handleGetTaskStatus(args) {
|
|
422
|
-
const { task_id } = args;
|
|
423
|
-
if (!task_id || typeof task_id !== 'string') {
|
|
424
|
-
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
425
|
-
}
|
|
426
449
|
try {
|
|
450
|
+
const { task_id } = args;
|
|
451
|
+
if (!task_id || typeof task_id !== 'string') {
|
|
452
|
+
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
453
|
+
}
|
|
427
454
|
const localTask = await this.db.getTask(task_id);
|
|
428
455
|
// Always try to get updated status from API, passing api_type if available
|
|
429
456
|
let apiResponse = null;
|
|
@@ -481,23 +508,14 @@ class KieAiMcpServer {
|
|
|
481
508
|
};
|
|
482
509
|
}
|
|
483
510
|
catch (error) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
{
|
|
488
|
-
type: 'text',
|
|
489
|
-
text: JSON.stringify({
|
|
490
|
-
success: false,
|
|
491
|
-
error: message
|
|
492
|
-
}, null, 2)
|
|
493
|
-
}
|
|
494
|
-
]
|
|
495
|
-
};
|
|
511
|
+
return this.formatError('get_task_status', error, {
|
|
512
|
+
task_id: 'Required: task ID to check status for'
|
|
513
|
+
});
|
|
496
514
|
}
|
|
497
515
|
}
|
|
498
516
|
async handleListTasks(args) {
|
|
499
|
-
const { limit = 20, status } = args;
|
|
500
517
|
try {
|
|
518
|
+
const { limit = 20, status } = args;
|
|
501
519
|
let tasks;
|
|
502
520
|
if (status) {
|
|
503
521
|
tasks = await this.db.getTasksByStatus(status, limit);
|
|
@@ -520,26 +538,18 @@ class KieAiMcpServer {
|
|
|
520
538
|
};
|
|
521
539
|
}
|
|
522
540
|
catch (error) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
type: 'text',
|
|
528
|
-
text: JSON.stringify({
|
|
529
|
-
success: false,
|
|
530
|
-
error: message
|
|
531
|
-
}, null, 2)
|
|
532
|
-
}
|
|
533
|
-
]
|
|
534
|
-
};
|
|
541
|
+
return this.formatError('list_tasks', error, {
|
|
542
|
+
limit: 'Optional: max tasks to return (1-100, default: 20)',
|
|
543
|
+
status: 'Optional: filter by status (pending, processing, completed, failed)'
|
|
544
|
+
});
|
|
535
545
|
}
|
|
536
546
|
}
|
|
537
547
|
async handleGetVeo1080pVideo(args) {
|
|
538
|
-
const { task_id, index } = args;
|
|
539
|
-
if (!task_id || typeof task_id !== 'string') {
|
|
540
|
-
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
541
|
-
}
|
|
542
548
|
try {
|
|
549
|
+
const { task_id, index } = args;
|
|
550
|
+
if (!task_id || typeof task_id !== 'string') {
|
|
551
|
+
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
552
|
+
}
|
|
543
553
|
const response = await this.client.getVeo1080pVideo(task_id, index);
|
|
544
554
|
return {
|
|
545
555
|
content: [
|
|
@@ -557,18 +567,10 @@ class KieAiMcpServer {
|
|
|
557
567
|
};
|
|
558
568
|
}
|
|
559
569
|
catch (error) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
type: 'text',
|
|
565
|
-
text: JSON.stringify({
|
|
566
|
-
success: false,
|
|
567
|
-
error: message
|
|
568
|
-
}, null, 2)
|
|
569
|
-
}
|
|
570
|
-
]
|
|
571
|
-
};
|
|
570
|
+
return this.formatError('get_veo3_1080p_video', error, {
|
|
571
|
+
task_id: 'Required: Veo3 task ID to get 1080p video for',
|
|
572
|
+
index: 'Optional: video index (for multiple video results)'
|
|
573
|
+
});
|
|
572
574
|
}
|
|
573
575
|
}
|
|
574
576
|
async run() {
|
package/dist/types.d.ts
CHANGED
|
@@ -46,28 +46,31 @@ export declare const Veo3GenerateSchema: z.ZodObject<{
|
|
|
46
46
|
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
47
47
|
model: z.ZodDefault<z.ZodEnum<["veo3", "veo3_fast"]>>;
|
|
48
48
|
watermark: z.ZodOptional<z.ZodString>;
|
|
49
|
-
aspectRatio: z.ZodDefault<z.ZodEnum<["16:9", "9:16"]>>;
|
|
49
|
+
aspectRatio: z.ZodDefault<z.ZodEnum<["16:9", "9:16", "Auto"]>>;
|
|
50
50
|
seeds: z.ZodOptional<z.ZodNumber>;
|
|
51
51
|
callBackUrl: z.ZodOptional<z.ZodString>;
|
|
52
52
|
enableFallback: z.ZodDefault<z.ZodBoolean>;
|
|
53
|
+
enableTranslation: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
53
54
|
}, "strip", z.ZodTypeAny, {
|
|
54
55
|
prompt: string;
|
|
55
56
|
model: "veo3" | "veo3_fast";
|
|
56
|
-
aspectRatio: "9:16" | "16:9";
|
|
57
|
+
aspectRatio: "9:16" | "16:9" | "Auto";
|
|
57
58
|
enableFallback: boolean;
|
|
58
59
|
imageUrls?: string[] | undefined;
|
|
59
60
|
watermark?: string | undefined;
|
|
60
61
|
seeds?: number | undefined;
|
|
61
62
|
callBackUrl?: string | undefined;
|
|
63
|
+
enableTranslation?: boolean | undefined;
|
|
62
64
|
}, {
|
|
63
65
|
prompt: string;
|
|
64
66
|
imageUrls?: string[] | undefined;
|
|
65
67
|
model?: "veo3" | "veo3_fast" | undefined;
|
|
66
68
|
watermark?: string | undefined;
|
|
67
|
-
aspectRatio?: "9:16" | "16:9" | undefined;
|
|
69
|
+
aspectRatio?: "9:16" | "16:9" | "Auto" | undefined;
|
|
68
70
|
seeds?: number | undefined;
|
|
69
71
|
callBackUrl?: string | undefined;
|
|
70
72
|
enableFallback?: boolean | undefined;
|
|
73
|
+
enableTranslation?: boolean | undefined;
|
|
71
74
|
}>;
|
|
72
75
|
export type NanoBananaGenerateRequest = z.infer<typeof NanoBananaGenerateSchema>;
|
|
73
76
|
export type NanaBananaEditRequest = z.infer<typeof NanoBananaEditSchema>;
|
package/dist/types.js
CHANGED
|
@@ -21,8 +21,9 @@ export const Veo3GenerateSchema = z.object({
|
|
|
21
21
|
imageUrls: z.array(z.string().url()).max(1).optional(),
|
|
22
22
|
model: z.enum(['veo3', 'veo3_fast']).default('veo3'),
|
|
23
23
|
watermark: z.string().max(100).optional(),
|
|
24
|
-
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
|
|
24
|
+
aspectRatio: z.enum(['16:9', '9:16', 'Auto']).default('16:9'),
|
|
25
25
|
seeds: z.number().int().min(10000).max(99999).optional(),
|
|
26
26
|
callBackUrl: z.string().url().optional(),
|
|
27
|
-
enableFallback: z.boolean().default(false)
|
|
27
|
+
enableFallback: z.boolean().default(false),
|
|
28
|
+
enableTranslation: z.boolean().default(true).optional()
|
|
28
29
|
});
|