@felores/kie-ai-mcp-server 1.0.3 → 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 +82 -17
- package/dist/index.js +214 -86
- package/dist/kie-ai-client.d.ts +2 -1
- package/dist/kie-ai-client.js +25 -10
- package/dist/types.d.ts +33 -4
- package/dist/types.js +15 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ An MCP (Model Context Protocol) server that provides access to Kie.ai's AI APIs
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Nano Banana Image Generation**: Text-to-image generation using Google's Gemini 2.5 Flash Image Preview
|
|
8
|
-
- **Nano Banana Image Editing**: Natural language image editing with up to
|
|
8
|
+
- **Nano Banana Image Editing**: Natural language image editing with up to 10 input images
|
|
9
|
+
- **Nano Banana Image Upscaling**: Upscale images 1-4x with optional face enhancement
|
|
9
10
|
- **Veo3 Video Generation**: Professional-quality video generation with text-to-video and image-to-video capabilities
|
|
10
11
|
- **1080p Video Upgrade**: Get high-definition versions of Veo3 videos
|
|
11
12
|
- **Task Management**: SQLite-based task tracking with status polling
|
|
@@ -51,6 +52,7 @@ export KIE_AI_API_KEY="your-api-key-here"
|
|
|
51
52
|
export KIE_AI_BASE_URL="https://api.kie.ai/api/v1" # Default
|
|
52
53
|
export KIE_AI_TIMEOUT="60000" # Default: 60 seconds
|
|
53
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
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
### MCP Configuration
|
|
@@ -89,12 +91,16 @@ Or if installed globally:
|
|
|
89
91
|
Generate images using Nano Banana.
|
|
90
92
|
|
|
91
93
|
**Parameters:**
|
|
92
|
-
- `prompt` (string, required): Text description of the image to generate
|
|
94
|
+
- `prompt` (string, required): Text description of the image to generate (max 5000 chars)
|
|
95
|
+
- `output_format` (string, optional): "png" or "jpeg" (default: "png")
|
|
96
|
+
- `image_size` (string, optional): Aspect ratio - "1:1", "9:16", "16:9", "3:4", "4:3", "3:2", "2:3", "5:4", "4:5", "21:9", "auto" (default: "1:1")
|
|
93
97
|
|
|
94
98
|
**Example:**
|
|
95
99
|
```json
|
|
96
100
|
{
|
|
97
|
-
"prompt": "A surreal painting of a giant banana floating in space"
|
|
101
|
+
"prompt": "A surreal painting of a giant banana floating in space",
|
|
102
|
+
"output_format": "png",
|
|
103
|
+
"image_size": "16:9"
|
|
98
104
|
}
|
|
99
105
|
```
|
|
100
106
|
|
|
@@ -102,28 +108,51 @@ Generate images using Nano Banana.
|
|
|
102
108
|
Edit images using natural language prompts.
|
|
103
109
|
|
|
104
110
|
**Parameters:**
|
|
105
|
-
- `prompt` (string, required): Description of edits to make
|
|
106
|
-
- `image_urls` (array, required): URLs of images to edit (max
|
|
111
|
+
- `prompt` (string, required): Description of edits to make (max 5000 chars)
|
|
112
|
+
- `image_urls` (array, required): URLs of images to edit (max 10)
|
|
113
|
+
- `output_format` (string, optional): "png" or "jpeg" (default: "png")
|
|
114
|
+
- `image_size` (string, optional): Aspect ratio (default: "1:1")
|
|
107
115
|
|
|
108
116
|
**Example:**
|
|
109
117
|
```json
|
|
110
118
|
{
|
|
111
119
|
"prompt": "Add a rainbow arching over the mountains",
|
|
112
|
-
"image_urls": ["https://example.com/image.jpg"]
|
|
120
|
+
"image_urls": ["https://example.com/image.jpg"],
|
|
121
|
+
"output_format": "png",
|
|
122
|
+
"image_size": "16:9"
|
|
113
123
|
}
|
|
114
124
|
```
|
|
115
125
|
|
|
116
|
-
### 3. `
|
|
126
|
+
### 3. `upscale_nano_banana`
|
|
127
|
+
Upscale images with optional face enhancement.
|
|
128
|
+
|
|
129
|
+
**Parameters:**
|
|
130
|
+
- `image` (string, required): URL of image to upscale (max 10MB, jpeg/png/webp)
|
|
131
|
+
- `scale` (integer, optional): Upscale factor 1-4 (default: 2)
|
|
132
|
+
- `face_enhance` (boolean, optional): Enable GFPGAN face enhancement (default: false)
|
|
133
|
+
|
|
134
|
+
**Example:**
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"image": "https://example.com/image.jpg",
|
|
138
|
+
"scale": 4,
|
|
139
|
+
"face_enhance": true
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 4. `generate_veo3_video`
|
|
117
144
|
Generate videos using Veo3.
|
|
118
145
|
|
|
119
146
|
**Parameters:**
|
|
120
147
|
- `prompt` (string, required): Video description
|
|
121
148
|
- `imageUrls` (array, optional): Image for image-to-video (max 1)
|
|
122
149
|
- `model` (enum, optional): "veo3" or "veo3_fast" (default: "veo3")
|
|
123
|
-
- `aspectRatio` (enum, optional): "16:9"
|
|
150
|
+
- `aspectRatio` (enum, optional): "16:9", "9:16", or "Auto" (default: "16:9", only 16:9 supports 1080P)
|
|
124
151
|
- `seeds` (integer, optional): Random seed 10000-99999
|
|
125
152
|
- `watermark` (string, optional): Watermark text
|
|
126
|
-
- `
|
|
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)
|
|
127
156
|
|
|
128
157
|
**Example:**
|
|
129
158
|
```json
|
|
@@ -131,24 +160,25 @@ Generate videos using Veo3.
|
|
|
131
160
|
"prompt": "A dog playing in a park",
|
|
132
161
|
"model": "veo3",
|
|
133
162
|
"aspectRatio": "16:9",
|
|
134
|
-
"seeds": 12345
|
|
163
|
+
"seeds": 12345,
|
|
164
|
+
"enableTranslation": true
|
|
135
165
|
}
|
|
136
166
|
```
|
|
137
167
|
|
|
138
|
-
###
|
|
168
|
+
### 5. `get_task_status`
|
|
139
169
|
Check the status of a generation task.
|
|
140
170
|
|
|
141
171
|
**Parameters:**
|
|
142
172
|
- `task_id` (string, required): Task ID to check
|
|
143
173
|
|
|
144
|
-
###
|
|
174
|
+
### 6. `list_tasks`
|
|
145
175
|
List recent tasks with their status.
|
|
146
176
|
|
|
147
177
|
**Parameters:**
|
|
148
178
|
- `limit` (integer, optional): Max tasks to return (default: 20, max: 100)
|
|
149
179
|
- `status` (string, optional): Filter by status ("pending", "processing", "completed", "failed")
|
|
150
180
|
|
|
151
|
-
###
|
|
181
|
+
### 7. `get_veo3_1080p_video`
|
|
152
182
|
Get 1080P high-definition version of a Veo3 video.
|
|
153
183
|
|
|
154
184
|
**Parameters:**
|
|
@@ -164,10 +194,12 @@ The server interfaces with these Kie.ai API endpoints:
|
|
|
164
194
|
- **Veo3 Video Generation**: `POST /api/v1/veo/generate` ✅ **VALIDATED**
|
|
165
195
|
- **Veo3 Video Status**: `GET /api/v1/veo/record-info` ✅ **VALIDATED**
|
|
166
196
|
- **Veo3 1080p Upgrade**: `GET /api/v1/veo/get-1080p-video` ✅ **VALIDATED**
|
|
167
|
-
- **Nano Banana Generation**: `POST /api/v1/
|
|
168
|
-
- **Nano Banana
|
|
197
|
+
- **Nano Banana Generation**: `POST /api/v1/jobs/createTask`
|
|
198
|
+
- **Nano Banana Edit**: `POST /api/v1/jobs/createTask`
|
|
199
|
+
- **Nano Banana Upscale**: `POST /api/v1/jobs/createTask`
|
|
200
|
+
- **Nano Banana Status**: `GET /api/v1/jobs/recordInfo`
|
|
169
201
|
|
|
170
|
-
All endpoints
|
|
202
|
+
All endpoints follow official Kie.ai API documentation.
|
|
171
203
|
|
|
172
204
|
## Database Schema
|
|
173
205
|
|
|
@@ -303,7 +335,40 @@ MIT License - see LICENSE file for details.
|
|
|
303
335
|
|
|
304
336
|
## Changelog
|
|
305
337
|
|
|
306
|
-
### v1.
|
|
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
|
+
|
|
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)
|
|
307
372
|
- Initial release
|
|
308
373
|
- Nano Banana image generation and editing
|
|
309
374
|
- Veo3 video generation
|
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, Veo3GenerateSchema } from './types.js';
|
|
7
|
+
import { NanoBananaGenerateSchema, NanoBananaEditSchema, NanoBananaUpscaleSchema, Veo3GenerateSchema } 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.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 {
|
|
@@ -41,7 +75,19 @@ class KieAiMcpServer {
|
|
|
41
75
|
type: 'string',
|
|
42
76
|
description: 'Text prompt for image generation',
|
|
43
77
|
minLength: 1,
|
|
44
|
-
maxLength:
|
|
78
|
+
maxLength: 5000
|
|
79
|
+
},
|
|
80
|
+
output_format: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
enum: ['png', 'jpeg'],
|
|
83
|
+
description: 'Output format for the images',
|
|
84
|
+
default: 'png'
|
|
85
|
+
},
|
|
86
|
+
image_size: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
enum: ['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto'],
|
|
89
|
+
description: 'Aspect ratio for the output image',
|
|
90
|
+
default: '1:1'
|
|
45
91
|
}
|
|
46
92
|
},
|
|
47
93
|
required: ['prompt']
|
|
@@ -57,19 +103,58 @@ class KieAiMcpServer {
|
|
|
57
103
|
type: 'string',
|
|
58
104
|
description: 'Text prompt for image editing',
|
|
59
105
|
minLength: 1,
|
|
60
|
-
maxLength:
|
|
106
|
+
maxLength: 5000
|
|
61
107
|
},
|
|
62
108
|
image_urls: {
|
|
63
109
|
type: 'array',
|
|
64
|
-
description: 'URLs of input images for editing (max
|
|
110
|
+
description: 'URLs of input images for editing (max 10)',
|
|
65
111
|
items: { type: 'string', format: 'uri' },
|
|
66
112
|
minItems: 1,
|
|
67
|
-
maxItems:
|
|
113
|
+
maxItems: 10
|
|
114
|
+
},
|
|
115
|
+
output_format: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
enum: ['png', 'jpeg'],
|
|
118
|
+
description: 'Output format for the images',
|
|
119
|
+
default: 'png'
|
|
120
|
+
},
|
|
121
|
+
image_size: {
|
|
122
|
+
type: 'string',
|
|
123
|
+
enum: ['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto'],
|
|
124
|
+
description: 'Aspect ratio for the output image',
|
|
125
|
+
default: '1:1'
|
|
68
126
|
}
|
|
69
127
|
},
|
|
70
128
|
required: ['prompt', 'image_urls']
|
|
71
129
|
}
|
|
72
130
|
},
|
|
131
|
+
{
|
|
132
|
+
name: 'upscale_nano_banana',
|
|
133
|
+
description: 'Upscale images using Nano Banana Upscale with optional face enhancement',
|
|
134
|
+
inputSchema: {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {
|
|
137
|
+
image: {
|
|
138
|
+
type: 'string',
|
|
139
|
+
format: 'uri',
|
|
140
|
+
description: 'URL of the image to upscale (max 10MB, jpeg/png/webp)'
|
|
141
|
+
},
|
|
142
|
+
scale: {
|
|
143
|
+
type: 'integer',
|
|
144
|
+
description: 'Upscale factor (1-4)',
|
|
145
|
+
minimum: 1,
|
|
146
|
+
maximum: 4,
|
|
147
|
+
default: 2
|
|
148
|
+
},
|
|
149
|
+
face_enhance: {
|
|
150
|
+
type: 'boolean',
|
|
151
|
+
description: 'Enable GFPGAN face enhancement',
|
|
152
|
+
default: false
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
required: ['image']
|
|
156
|
+
}
|
|
157
|
+
},
|
|
73
158
|
{
|
|
74
159
|
name: 'generate_veo3_video',
|
|
75
160
|
description: 'Generate professional-quality videos using Google\'s Veo3 API',
|
|
@@ -101,8 +186,8 @@ class KieAiMcpServer {
|
|
|
101
186
|
},
|
|
102
187
|
aspectRatio: {
|
|
103
188
|
type: 'string',
|
|
104
|
-
enum: ['16:9', '9:16'],
|
|
105
|
-
description: 'Video aspect ratio',
|
|
189
|
+
enum: ['16:9', '9:16', 'Auto'],
|
|
190
|
+
description: 'Video aspect ratio (16:9 supports 1080P)',
|
|
106
191
|
default: '16:9'
|
|
107
192
|
},
|
|
108
193
|
seeds: {
|
|
@@ -111,10 +196,20 @@ class KieAiMcpServer {
|
|
|
111
196
|
minimum: 10000,
|
|
112
197
|
maximum: 99999
|
|
113
198
|
},
|
|
199
|
+
callBackUrl: {
|
|
200
|
+
type: 'string',
|
|
201
|
+
format: 'uri',
|
|
202
|
+
description: 'Callback URL for task completion notifications'
|
|
203
|
+
},
|
|
114
204
|
enableFallback: {
|
|
115
205
|
type: 'boolean',
|
|
116
|
-
description: 'Enable fallback mechanism for content policy failures',
|
|
206
|
+
description: 'Enable fallback mechanism for content policy failures (Note: fallback videos cannot use 1080P endpoint)',
|
|
117
207
|
default: false
|
|
208
|
+
},
|
|
209
|
+
enableTranslation: {
|
|
210
|
+
type: 'boolean',
|
|
211
|
+
description: 'Auto-translate prompts to English for better results',
|
|
212
|
+
default: true
|
|
118
213
|
}
|
|
119
214
|
},
|
|
120
215
|
required: ['prompt']
|
|
@@ -184,6 +279,8 @@ class KieAiMcpServer {
|
|
|
184
279
|
return await this.handleGenerateNanoBanana(args);
|
|
185
280
|
case 'edit_nano_banana':
|
|
186
281
|
return await this.handleEditNanoBanana(args);
|
|
282
|
+
case 'upscale_nano_banana':
|
|
283
|
+
return await this.handleUpscaleNanoBanana(args);
|
|
187
284
|
case 'generate_veo3_video':
|
|
188
285
|
return await this.handleGenerateVeo3Video(args);
|
|
189
286
|
case 'get_task_status':
|
|
@@ -206,8 +303,8 @@ class KieAiMcpServer {
|
|
|
206
303
|
});
|
|
207
304
|
}
|
|
208
305
|
async handleGenerateNanoBanana(args) {
|
|
209
|
-
const request = NanoBananaGenerateSchema.parse(args);
|
|
210
306
|
try {
|
|
307
|
+
const request = NanoBananaGenerateSchema.parse(args);
|
|
211
308
|
const response = await this.client.generateNanoBanana(request);
|
|
212
309
|
if (response.data?.taskId) {
|
|
213
310
|
await this.db.createTask({
|
|
@@ -231,23 +328,16 @@ class KieAiMcpServer {
|
|
|
231
328
|
};
|
|
232
329
|
}
|
|
233
330
|
catch (error) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
text: JSON.stringify({
|
|
240
|
-
success: false,
|
|
241
|
-
error: message
|
|
242
|
-
}, null, 2)
|
|
243
|
-
}
|
|
244
|
-
]
|
|
245
|
-
};
|
|
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
|
+
});
|
|
246
336
|
}
|
|
247
337
|
}
|
|
248
338
|
async handleEditNanoBanana(args) {
|
|
249
|
-
const request = NanoBananaEditSchema.parse(args);
|
|
250
339
|
try {
|
|
340
|
+
const request = NanoBananaEditSchema.parse(args);
|
|
251
341
|
const response = await this.client.editNanoBanana(request);
|
|
252
342
|
if (response.data?.taskId) {
|
|
253
343
|
await this.db.createTask({
|
|
@@ -271,23 +361,54 @@ class KieAiMcpServer {
|
|
|
271
361
|
};
|
|
272
362
|
}
|
|
273
363
|
catch (error) {
|
|
274
|
-
|
|
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
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async handleUpscaleNanoBanana(args) {
|
|
373
|
+
try {
|
|
374
|
+
const request = NanoBananaUpscaleSchema.parse(args);
|
|
375
|
+
const response = await this.client.upscaleNanaBanana(request);
|
|
376
|
+
if (response.data?.taskId) {
|
|
377
|
+
await this.db.createTask({
|
|
378
|
+
task_id: response.data.taskId,
|
|
379
|
+
api_type: 'nano-banana-upscale',
|
|
380
|
+
status: 'pending',
|
|
381
|
+
result_url: response.data.imageUrl
|
|
382
|
+
});
|
|
383
|
+
}
|
|
275
384
|
return {
|
|
276
385
|
content: [
|
|
277
386
|
{
|
|
278
387
|
type: 'text',
|
|
279
388
|
text: JSON.stringify({
|
|
280
|
-
success:
|
|
281
|
-
|
|
389
|
+
success: true,
|
|
390
|
+
response: response,
|
|
391
|
+
message: 'Nano Banana upscale initiated'
|
|
282
392
|
}, null, 2)
|
|
283
393
|
}
|
|
284
394
|
]
|
|
285
395
|
};
|
|
286
396
|
}
|
|
397
|
+
catch (error) {
|
|
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
|
+
});
|
|
403
|
+
}
|
|
287
404
|
}
|
|
288
405
|
async handleGenerateVeo3Video(args) {
|
|
289
|
-
const request = Veo3GenerateSchema.parse(args);
|
|
290
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
|
+
}
|
|
291
412
|
const response = await this.client.generateVeo3Video(request);
|
|
292
413
|
if (response.data?.taskId) {
|
|
293
414
|
await this.db.createTask({
|
|
@@ -311,67 +432,90 @@ class KieAiMcpServer {
|
|
|
311
432
|
};
|
|
312
433
|
}
|
|
313
434
|
catch (error) {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
};
|
|
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
|
+
});
|
|
326
446
|
}
|
|
327
447
|
}
|
|
328
448
|
async handleGetTaskStatus(args) {
|
|
329
|
-
const { task_id } = args;
|
|
330
|
-
if (!task_id || typeof task_id !== 'string') {
|
|
331
|
-
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
332
|
-
}
|
|
333
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
|
+
}
|
|
334
454
|
const localTask = await this.db.getTask(task_id);
|
|
335
455
|
// Always try to get updated status from API, passing api_type if available
|
|
336
456
|
let apiResponse = null;
|
|
457
|
+
let parsedResult = null;
|
|
337
458
|
try {
|
|
338
459
|
apiResponse = await this.client.getTaskStatus(task_id, localTask?.api_type);
|
|
460
|
+
// Update local database with API response
|
|
461
|
+
if (apiResponse?.data) {
|
|
462
|
+
const { state, resultJson, failCode, failMsg } = apiResponse.data;
|
|
463
|
+
// Map API state to our status
|
|
464
|
+
let status = 'pending';
|
|
465
|
+
if (state === 'success')
|
|
466
|
+
status = 'completed';
|
|
467
|
+
else if (state === 'fail')
|
|
468
|
+
status = 'failed';
|
|
469
|
+
else if (state === 'waiting')
|
|
470
|
+
status = 'processing';
|
|
471
|
+
// Parse resultJson if available
|
|
472
|
+
if (resultJson) {
|
|
473
|
+
try {
|
|
474
|
+
parsedResult = JSON.parse(resultJson);
|
|
475
|
+
}
|
|
476
|
+
catch (e) {
|
|
477
|
+
// Invalid JSON in resultJson
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// Update database
|
|
481
|
+
await this.db.updateTask(task_id, {
|
|
482
|
+
status,
|
|
483
|
+
result_url: parsedResult?.resultUrls?.[0] || undefined,
|
|
484
|
+
error_message: failMsg || undefined
|
|
485
|
+
});
|
|
486
|
+
}
|
|
339
487
|
}
|
|
340
488
|
catch (error) {
|
|
341
489
|
// API call failed, use local data if available
|
|
342
490
|
}
|
|
491
|
+
// Fetch updated local task
|
|
492
|
+
const updatedTask = await this.db.getTask(task_id);
|
|
343
493
|
return {
|
|
344
494
|
content: [
|
|
345
495
|
{
|
|
346
496
|
type: 'text',
|
|
347
497
|
text: JSON.stringify({
|
|
348
498
|
success: true,
|
|
349
|
-
|
|
499
|
+
task_id: task_id,
|
|
500
|
+
status: apiResponse?.data?.state || updatedTask?.status,
|
|
501
|
+
result_urls: parsedResult?.resultUrls || (updatedTask?.result_url ? [updatedTask.result_url] : []),
|
|
502
|
+
error: apiResponse?.data?.failMsg || updatedTask?.error_message,
|
|
350
503
|
api_response: apiResponse,
|
|
351
|
-
message:
|
|
504
|
+
message: updatedTask ? 'Task found' : 'Task not found in local database'
|
|
352
505
|
}, null, 2)
|
|
353
506
|
}
|
|
354
507
|
]
|
|
355
508
|
};
|
|
356
509
|
}
|
|
357
510
|
catch (error) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
{
|
|
362
|
-
type: 'text',
|
|
363
|
-
text: JSON.stringify({
|
|
364
|
-
success: false,
|
|
365
|
-
error: message
|
|
366
|
-
}, null, 2)
|
|
367
|
-
}
|
|
368
|
-
]
|
|
369
|
-
};
|
|
511
|
+
return this.formatError('get_task_status', error, {
|
|
512
|
+
task_id: 'Required: task ID to check status for'
|
|
513
|
+
});
|
|
370
514
|
}
|
|
371
515
|
}
|
|
372
516
|
async handleListTasks(args) {
|
|
373
|
-
const { limit = 20, status } = args;
|
|
374
517
|
try {
|
|
518
|
+
const { limit = 20, status } = args;
|
|
375
519
|
let tasks;
|
|
376
520
|
if (status) {
|
|
377
521
|
tasks = await this.db.getTasksByStatus(status, limit);
|
|
@@ -394,26 +538,18 @@ class KieAiMcpServer {
|
|
|
394
538
|
};
|
|
395
539
|
}
|
|
396
540
|
catch (error) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
type: 'text',
|
|
402
|
-
text: JSON.stringify({
|
|
403
|
-
success: false,
|
|
404
|
-
error: message
|
|
405
|
-
}, null, 2)
|
|
406
|
-
}
|
|
407
|
-
]
|
|
408
|
-
};
|
|
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
|
+
});
|
|
409
545
|
}
|
|
410
546
|
}
|
|
411
547
|
async handleGetVeo1080pVideo(args) {
|
|
412
|
-
const { task_id, index } = args;
|
|
413
|
-
if (!task_id || typeof task_id !== 'string') {
|
|
414
|
-
throw new McpError(ErrorCode.InvalidParams, 'task_id is required and must be a string');
|
|
415
|
-
}
|
|
416
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
|
+
}
|
|
417
553
|
const response = await this.client.getVeo1080pVideo(task_id, index);
|
|
418
554
|
return {
|
|
419
555
|
content: [
|
|
@@ -431,18 +567,10 @@ class KieAiMcpServer {
|
|
|
431
567
|
};
|
|
432
568
|
}
|
|
433
569
|
catch (error) {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
type: 'text',
|
|
439
|
-
text: JSON.stringify({
|
|
440
|
-
success: false,
|
|
441
|
-
error: message
|
|
442
|
-
}, null, 2)
|
|
443
|
-
}
|
|
444
|
-
]
|
|
445
|
-
};
|
|
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
|
+
});
|
|
446
574
|
}
|
|
447
575
|
}
|
|
448
576
|
async run() {
|
package/dist/kie-ai-client.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { KieAiConfig, KieAiResponse, NanoBananaGenerateRequest, NanaBananaEditRequest, Veo3GenerateRequest, ImageResponse, TaskResponse } from './types.js';
|
|
1
|
+
import { KieAiConfig, KieAiResponse, NanoBananaGenerateRequest, NanaBananaEditRequest, NanoBananaUpscaleRequest, Veo3GenerateRequest, ImageResponse, TaskResponse } from './types.js';
|
|
2
2
|
export declare class KieAiClient {
|
|
3
3
|
private config;
|
|
4
4
|
constructor(config: KieAiConfig);
|
|
5
5
|
private makeRequest;
|
|
6
6
|
generateNanoBanana(request: NanoBananaGenerateRequest): Promise<KieAiResponse<ImageResponse>>;
|
|
7
7
|
editNanoBanana(request: NanaBananaEditRequest): Promise<KieAiResponse<ImageResponse>>;
|
|
8
|
+
upscaleNanaBanana(request: NanoBananaUpscaleRequest): Promise<KieAiResponse<ImageResponse>>;
|
|
8
9
|
generateVeo3Video(request: Veo3GenerateRequest): Promise<KieAiResponse<TaskResponse>>;
|
|
9
10
|
getTaskStatus(taskId: string, apiType?: string): Promise<KieAiResponse<any>>;
|
|
10
11
|
getVeo1080pVideo(taskId: string, index?: number): Promise<KieAiResponse<any>>;
|
package/dist/kie-ai-client.js
CHANGED
|
@@ -33,23 +33,38 @@ export class KieAiClient {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
async generateNanoBanana(request) {
|
|
36
|
-
const
|
|
36
|
+
const jobRequest = {
|
|
37
37
|
model: 'google/nano-banana',
|
|
38
38
|
input: {
|
|
39
|
-
prompt: request.prompt
|
|
39
|
+
prompt: request.prompt,
|
|
40
|
+
...(request.output_format && { output_format: request.output_format }),
|
|
41
|
+
...(request.image_size && { image_size: request.image_size })
|
|
40
42
|
}
|
|
41
43
|
};
|
|
42
|
-
return this.makeRequest('/
|
|
44
|
+
return this.makeRequest('/jobs/createTask', 'POST', jobRequest);
|
|
43
45
|
}
|
|
44
46
|
async editNanoBanana(request) {
|
|
45
|
-
const
|
|
47
|
+
const jobRequest = {
|
|
46
48
|
model: 'google/nano-banana-edit',
|
|
47
49
|
input: {
|
|
48
50
|
prompt: request.prompt,
|
|
49
|
-
image_urls: request.image_urls
|
|
51
|
+
image_urls: request.image_urls,
|
|
52
|
+
...(request.output_format && { output_format: request.output_format }),
|
|
53
|
+
...(request.image_size && { image_size: request.image_size })
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return this.makeRequest('/jobs/createTask', 'POST', jobRequest);
|
|
57
|
+
}
|
|
58
|
+
async upscaleNanaBanana(request) {
|
|
59
|
+
const jobRequest = {
|
|
60
|
+
model: 'nano-banana-upscale',
|
|
61
|
+
input: {
|
|
62
|
+
image: request.image,
|
|
63
|
+
...(request.scale !== undefined && { scale: request.scale }),
|
|
64
|
+
...(request.face_enhance !== undefined && { face_enhance: request.face_enhance })
|
|
50
65
|
}
|
|
51
66
|
};
|
|
52
|
-
return this.makeRequest('/
|
|
67
|
+
return this.makeRequest('/jobs/createTask', 'POST', jobRequest);
|
|
53
68
|
}
|
|
54
69
|
async generateVeo3Video(request) {
|
|
55
70
|
return this.makeRequest('/veo/generate', 'POST', request);
|
|
@@ -59,12 +74,12 @@ export class KieAiClient {
|
|
|
59
74
|
if (apiType === 'veo3') {
|
|
60
75
|
return this.makeRequest(`/veo/record-info?taskId=${taskId}`, 'GET');
|
|
61
76
|
}
|
|
62
|
-
else if (apiType === 'nano-banana' || apiType === 'nano-banana-edit') {
|
|
63
|
-
return this.makeRequest(`/
|
|
77
|
+
else if (apiType === 'nano-banana' || apiType === 'nano-banana-edit' || apiType === 'nano-banana-upscale') {
|
|
78
|
+
return this.makeRequest(`/jobs/recordInfo?taskId=${taskId}`, 'GET');
|
|
64
79
|
}
|
|
65
|
-
// Fallback: try
|
|
80
|
+
// Fallback: try jobs first, then veo (for tasks not in database)
|
|
66
81
|
try {
|
|
67
|
-
return await this.makeRequest(`/
|
|
82
|
+
return await this.makeRequest(`/jobs/recordInfo?taskId=${taskId}`, 'GET');
|
|
68
83
|
}
|
|
69
84
|
catch (error) {
|
|
70
85
|
try {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,51 +1,80 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const NanoBananaGenerateSchema: z.ZodObject<{
|
|
3
3
|
prompt: z.ZodString;
|
|
4
|
+
output_format: z.ZodOptional<z.ZodDefault<z.ZodEnum<["png", "jpeg"]>>>;
|
|
5
|
+
image_size: z.ZodOptional<z.ZodDefault<z.ZodEnum<["1:1", "9:16", "16:9", "3:4", "4:3", "3:2", "2:3", "5:4", "4:5", "21:9", "auto"]>>>;
|
|
4
6
|
}, "strip", z.ZodTypeAny, {
|
|
5
7
|
prompt: string;
|
|
8
|
+
output_format?: "png" | "jpeg" | undefined;
|
|
9
|
+
image_size?: "1:1" | "9:16" | "16:9" | "3:4" | "4:3" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | "auto" | undefined;
|
|
6
10
|
}, {
|
|
7
11
|
prompt: string;
|
|
12
|
+
output_format?: "png" | "jpeg" | undefined;
|
|
13
|
+
image_size?: "1:1" | "9:16" | "16:9" | "3:4" | "4:3" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | "auto" | undefined;
|
|
8
14
|
}>;
|
|
9
15
|
export declare const NanoBananaEditSchema: z.ZodObject<{
|
|
10
16
|
prompt: z.ZodString;
|
|
11
17
|
image_urls: z.ZodArray<z.ZodString, "many">;
|
|
18
|
+
output_format: z.ZodOptional<z.ZodDefault<z.ZodEnum<["png", "jpeg"]>>>;
|
|
19
|
+
image_size: z.ZodOptional<z.ZodDefault<z.ZodEnum<["1:1", "9:16", "16:9", "3:4", "4:3", "3:2", "2:3", "5:4", "4:5", "21:9", "auto"]>>>;
|
|
12
20
|
}, "strip", z.ZodTypeAny, {
|
|
13
21
|
prompt: string;
|
|
14
22
|
image_urls: string[];
|
|
23
|
+
output_format?: "png" | "jpeg" | undefined;
|
|
24
|
+
image_size?: "1:1" | "9:16" | "16:9" | "3:4" | "4:3" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | "auto" | undefined;
|
|
15
25
|
}, {
|
|
16
26
|
prompt: string;
|
|
17
27
|
image_urls: string[];
|
|
28
|
+
output_format?: "png" | "jpeg" | undefined;
|
|
29
|
+
image_size?: "1:1" | "9:16" | "16:9" | "3:4" | "4:3" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | "auto" | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
export declare const NanoBananaUpscaleSchema: z.ZodObject<{
|
|
32
|
+
image: z.ZodString;
|
|
33
|
+
scale: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
34
|
+
face_enhance: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
image: string;
|
|
37
|
+
scale?: number | undefined;
|
|
38
|
+
face_enhance?: boolean | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
image: string;
|
|
41
|
+
scale?: number | undefined;
|
|
42
|
+
face_enhance?: boolean | undefined;
|
|
18
43
|
}>;
|
|
19
44
|
export declare const Veo3GenerateSchema: z.ZodObject<{
|
|
20
45
|
prompt: z.ZodString;
|
|
21
46
|
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
22
47
|
model: z.ZodDefault<z.ZodEnum<["veo3", "veo3_fast"]>>;
|
|
23
48
|
watermark: z.ZodOptional<z.ZodString>;
|
|
24
|
-
aspectRatio: z.ZodDefault<z.ZodEnum<["16:9", "9:16"]>>;
|
|
49
|
+
aspectRatio: z.ZodDefault<z.ZodEnum<["16:9", "9:16", "Auto"]>>;
|
|
25
50
|
seeds: z.ZodOptional<z.ZodNumber>;
|
|
26
51
|
callBackUrl: z.ZodOptional<z.ZodString>;
|
|
27
52
|
enableFallback: z.ZodDefault<z.ZodBoolean>;
|
|
53
|
+
enableTranslation: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
28
54
|
}, "strip", z.ZodTypeAny, {
|
|
29
55
|
prompt: string;
|
|
30
56
|
model: "veo3" | "veo3_fast";
|
|
31
|
-
aspectRatio: "16:9" | "
|
|
57
|
+
aspectRatio: "9:16" | "16:9" | "Auto";
|
|
32
58
|
enableFallback: boolean;
|
|
33
59
|
imageUrls?: string[] | undefined;
|
|
34
60
|
watermark?: string | undefined;
|
|
35
61
|
seeds?: number | undefined;
|
|
36
62
|
callBackUrl?: string | undefined;
|
|
63
|
+
enableTranslation?: boolean | undefined;
|
|
37
64
|
}, {
|
|
38
65
|
prompt: string;
|
|
39
66
|
imageUrls?: string[] | undefined;
|
|
40
67
|
model?: "veo3" | "veo3_fast" | undefined;
|
|
41
68
|
watermark?: string | undefined;
|
|
42
|
-
aspectRatio?: "16:9" | "
|
|
69
|
+
aspectRatio?: "9:16" | "16:9" | "Auto" | undefined;
|
|
43
70
|
seeds?: number | undefined;
|
|
44
71
|
callBackUrl?: string | undefined;
|
|
45
72
|
enableFallback?: boolean | undefined;
|
|
73
|
+
enableTranslation?: boolean | undefined;
|
|
46
74
|
}>;
|
|
47
75
|
export type NanoBananaGenerateRequest = z.infer<typeof NanoBananaGenerateSchema>;
|
|
48
76
|
export type NanaBananaEditRequest = z.infer<typeof NanoBananaEditSchema>;
|
|
77
|
+
export type NanoBananaUpscaleRequest = z.infer<typeof NanoBananaUpscaleSchema>;
|
|
49
78
|
export type Veo3GenerateRequest = z.infer<typeof Veo3GenerateSchema>;
|
|
50
79
|
export interface KieAiResponse<T = any> {
|
|
51
80
|
code: number;
|
|
@@ -62,7 +91,7 @@ export interface TaskResponse {
|
|
|
62
91
|
export interface TaskRecord {
|
|
63
92
|
id?: number;
|
|
64
93
|
task_id: string;
|
|
65
|
-
api_type: 'nano-banana' | 'nano-banana-edit' | 'veo3';
|
|
94
|
+
api_type: 'nano-banana' | 'nano-banana-edit' | 'nano-banana-upscale' | 'veo3';
|
|
66
95
|
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
67
96
|
created_at: string;
|
|
68
97
|
updated_at: string;
|
package/dist/types.js
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
// Zod schemas for request validation
|
|
3
3
|
export const NanoBananaGenerateSchema = z.object({
|
|
4
|
-
prompt: z.string().min(1).max(
|
|
4
|
+
prompt: z.string().min(1).max(5000),
|
|
5
|
+
output_format: z.enum(['png', 'jpeg']).default('png').optional(),
|
|
6
|
+
image_size: z.enum(['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto']).default('1:1').optional()
|
|
5
7
|
});
|
|
6
8
|
export const NanoBananaEditSchema = z.object({
|
|
7
|
-
prompt: z.string().min(1).max(
|
|
8
|
-
image_urls: z.array(z.string().url()).min(1).max(
|
|
9
|
+
prompt: z.string().min(1).max(5000),
|
|
10
|
+
image_urls: z.array(z.string().url()).min(1).max(10),
|
|
11
|
+
output_format: z.enum(['png', 'jpeg']).default('png').optional(),
|
|
12
|
+
image_size: z.enum(['1:1', '9:16', '16:9', '3:4', '4:3', '3:2', '2:3', '5:4', '4:5', '21:9', 'auto']).default('1:1').optional()
|
|
13
|
+
});
|
|
14
|
+
export const NanoBananaUpscaleSchema = z.object({
|
|
15
|
+
image: z.string().url(),
|
|
16
|
+
scale: z.number().int().min(1).max(4).default(2).optional(),
|
|
17
|
+
face_enhance: z.boolean().default(false).optional()
|
|
9
18
|
});
|
|
10
19
|
export const Veo3GenerateSchema = z.object({
|
|
11
20
|
prompt: z.string().min(1).max(2000),
|
|
12
21
|
imageUrls: z.array(z.string().url()).max(1).optional(),
|
|
13
22
|
model: z.enum(['veo3', 'veo3_fast']).default('veo3'),
|
|
14
23
|
watermark: z.string().max(100).optional(),
|
|
15
|
-
aspectRatio: z.enum(['16:9', '9:16']).default('16:9'),
|
|
24
|
+
aspectRatio: z.enum(['16:9', '9:16', 'Auto']).default('16:9'),
|
|
16
25
|
seeds: z.number().int().min(10000).max(99999).optional(),
|
|
17
26
|
callBackUrl: z.string().url().optional(),
|
|
18
|
-
enableFallback: z.boolean().default(false)
|
|
27
|
+
enableFallback: z.boolean().default(false),
|
|
28
|
+
enableTranslation: z.boolean().default(true).optional()
|
|
19
29
|
});
|