@felores/kie-ai-mcp-server 3.1.0 → 3.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/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, ListResources
5
5
  import { KieAiClient } from "./kie-ai-client.js";
6
6
  import { TaskDatabase } from "./database.js";
7
7
  import { z } from "zod";
8
- import { NanoBananaImageSchema, Veo3GenerateSchema, SunoGenerateSchema, ElevenLabsTTSSchema, ElevenLabsSoundEffectsSchema, ByteDanceSeedanceVideoSchema, ByteDanceSeedreamImageSchema, QwenImageSchema, RunwayAlephVideoSchema, WanVideoSchema, MidjourneyGenerateSchema, OpenAI4oImageSchema, FluxKontextImageSchema, RecraftRemoveBackgroundSchema, IdeogramReframeSchema, KlingVideoSchema, HailuoVideoSchema, SoraVideoSchema, Flux2ImageSchema, WanAnimateSchema, ZImageSchema, GrokImagineSchema, InfiniTalkSchema, KlingAvatarSchema, TopazUpscaleImageSchema, } from "./types.js";
8
+ import { NanoBananaImageSchema, Veo3GenerateSchema, SunoGenerateSchema, ElevenLabsTTSSchema, ElevenLabsSoundEffectsSchema, ByteDanceSeedanceVideoSchema, ByteDanceSeedreamImageSchema, QwenImageSchema, RunwayAlephVideoSchema, Wan27VideoSchema, MidjourneyGenerateSchema, GptImage2Schema, FluxKontextImageSchema, RecraftRemoveBackgroundSchema, IdeogramReframeSchema, KlingVideoSchema, HailuoVideoSchema, SoraVideoSchema, Flux2ImageSchema, WanAnimateSchema, ZImageSchema, GrokImagineSchema, InfiniTalkSchema, KlingAvatarSchema, TopazUpscaleImageSchema, HappyHorseVideoSchema, } from "./types.js";
9
9
  class KieAiMcpServer {
10
10
  server;
11
11
  client;
@@ -17,7 +17,7 @@ class KieAiMcpServer {
17
17
  "nano_banana_image",
18
18
  "bytedance_seedream_image",
19
19
  "qwen_image",
20
- "openai_4o_image",
20
+ "gpt_image_2",
21
21
  "flux_kontext_image",
22
22
  "flux2_image",
23
23
  "z_image",
@@ -33,6 +33,7 @@ class KieAiMcpServer {
33
33
  "bytedance_seedance_video",
34
34
  "wan_video",
35
35
  "wan_animate",
36
+ "happyhorse_video",
36
37
  "hailuo_video",
37
38
  "kling_video",
38
39
  "runway_aleph_video",
@@ -53,7 +54,7 @@ class KieAiMcpServer {
53
54
  constructor() {
54
55
  this.server = new Server({
55
56
  name: "kie-ai-mcp-server",
56
- version: "3.1.0",
57
+ version: "3.2.0",
57
58
  });
58
59
  // Initialize client with config from environment
59
60
  this.config = {
@@ -1237,70 +1238,41 @@ class KieAiMcpServer {
1237
1238
  },
1238
1239
  },
1239
1240
  {
1240
- name: "openai_4o_image",
1241
- description: "Generate images using OpenAI GPT-4o models (unified tool for text-to-image, image editing, and image variants)",
1241
+ name: "gpt_image_2",
1242
+ description: "Generate images using GPT Image 2 (text-to-image and image-to-image with up to 16 reference images)",
1242
1243
  inputSchema: {
1243
1244
  type: "object",
1244
1245
  properties: {
1245
1246
  prompt: {
1246
1247
  type: "string",
1247
- description: "Text prompt describing the desired image (max 5000 characters)",
1248
- maxLength: 5000,
1248
+ description: "Text prompt describing the desired image (max 20000 characters)",
1249
+ maxLength: 20000,
1249
1250
  },
1250
- filesUrl: {
1251
+ input_urls: {
1251
1252
  type: "array",
1252
- description: "Array of up to 5 image URLs for editing or variants",
1253
- items: {
1254
- type: "string",
1255
- format: "uri",
1256
- },
1257
- maxItems: 5,
1253
+ description: "Array of up to 16 image URLs for image-to-image mode. Omit for text-to-image.",
1254
+ items: { type: "string", format: "uri" },
1255
+ maxItems: 16,
1258
1256
  },
1259
- size: {
1257
+ aspect_ratio: {
1260
1258
  type: "string",
1261
1259
  description: "Image aspect ratio",
1262
- enum: ["1:1", "3:2", "2:3"],
1263
- default: "1:1",
1260
+ enum: ["auto", "1:1", "9:16", "16:9", "4:3", "3:4"],
1261
+ default: "auto",
1264
1262
  },
1265
- nVariants: {
1266
- type: "string",
1267
- description: "Number of image variations to generate",
1268
- enum: ["1", "2", "4"],
1269
- default: "4",
1270
- },
1271
- maskUrl: {
1263
+ resolution: {
1272
1264
  type: "string",
1273
- description: "Mask image URL for precise editing (black areas will be modified, white areas preserved)",
1274
- format: "uri",
1265
+ description: "Output resolution",
1266
+ enum: ["1K", "2K", "4K"],
1267
+ default: "1K",
1275
1268
  },
1276
1269
  callBackUrl: {
1277
1270
  type: "string",
1278
1271
  description: "Optional: URL for task completion notifications (uses KIE_AI_CALLBACK_URL env var if not provided)",
1279
1272
  format: "uri",
1280
1273
  },
1281
- isEnhance: {
1282
- type: "boolean",
1283
- description: "Enable prompt enhancement for specialized scenarios like 3D renders",
1284
- default: false,
1285
- },
1286
- uploadCn: {
1287
- type: "boolean",
1288
- description: "Route uploads via China servers",
1289
- default: false,
1290
- },
1291
- enableFallback: {
1292
- type: "boolean",
1293
- description: "Enable automatic fallback to backup models if GPT-4o is unavailable",
1294
- default: true,
1295
- },
1296
- fallbackModel: {
1297
- type: "string",
1298
- description: "Backup model to use when fallback is enabled",
1299
- enum: ["GPT_IMAGE_1", "FLUX_MAX"],
1300
- default: "FLUX_MAX",
1301
- },
1302
1274
  },
1303
- required: [],
1275
+ required: ["prompt"],
1304
1276
  },
1305
1277
  },
1306
1278
  {
@@ -1375,57 +1347,135 @@ class KieAiMcpServer {
1375
1347
  },
1376
1348
  {
1377
1349
  name: "wan_video",
1378
- description: "Generate videos using Alibaba Wan 2.5 models (unified tool for both text-to-video and image-to-video)",
1350
+ description: "Generate videos using Alibaba Wan 2.7 (text-to-video, image-to-video, reference-to-video, video-edit with native audio support)",
1379
1351
  inputSchema: {
1380
1352
  type: "object",
1381
1353
  properties: {
1354
+ mode: {
1355
+ type: "string",
1356
+ description: "Generation mode: text-to-video (default), image-to-video, reference-to-video, or video-edit. Auto-detected from parameters if omitted.",
1357
+ enum: [
1358
+ "text-to-video",
1359
+ "image-to-video",
1360
+ "reference-to-video",
1361
+ "video-edit",
1362
+ ],
1363
+ },
1382
1364
  prompt: {
1383
1365
  type: "string",
1384
- description: "Text prompt for video generation (max 800 characters)",
1366
+ description: "Text prompt for video generation (max 5000 characters)",
1385
1367
  minLength: 1,
1386
- maxLength: 800,
1368
+ maxLength: 5000,
1387
1369
  },
1388
- image_url: {
1370
+ negative_prompt: {
1389
1371
  type: "string",
1390
- description: "URL of input image for image-to-video generation (optional - if not provided, uses text-to-video)",
1372
+ description: "Negative prompt to describe content to avoid (max 500 characters)",
1373
+ maxLength: 500,
1374
+ },
1375
+ audio_url: {
1376
+ type: "string",
1377
+ description: "Audio URL for text-to-video with audio (T2V mode only)",
1391
1378
  format: "uri",
1392
1379
  },
1393
- aspect_ratio: {
1380
+ first_frame_url: {
1394
1381
  type: "string",
1395
- description: "Aspect ratio of the generated video (text-to-video only)",
1396
- enum: ["16:9", "9:16", "1:1"],
1397
- default: "16:9",
1382
+ description: "URL of first frame image for image-to-video mode",
1383
+ format: "uri",
1384
+ },
1385
+ last_frame_url: {
1386
+ type: "string",
1387
+ description: "URL of last frame image for image-to-video mode",
1388
+ format: "uri",
1389
+ },
1390
+ first_clip_url: {
1391
+ type: "string",
1392
+ description: "URL of first video clip for image-to-video mode",
1393
+ format: "uri",
1394
+ },
1395
+ driving_audio_url: {
1396
+ type: "string",
1397
+ description: "Audio URL to drive facial expressions (I2V mode)",
1398
+ format: "uri",
1399
+ },
1400
+ reference_image: {
1401
+ type: "array",
1402
+ description: "Reference images for reference-to-video mode (up to 5)",
1403
+ items: { type: "string", format: "uri" },
1404
+ maxItems: 5,
1405
+ },
1406
+ reference_video: {
1407
+ type: "array",
1408
+ description: "Reference videos for reference-to-video mode (up to 5)",
1409
+ items: { type: "string", format: "uri" },
1410
+ maxItems: 5,
1411
+ },
1412
+ reference_voice: {
1413
+ type: "string",
1414
+ description: "Voice reference URL for R2V mode",
1415
+ format: "uri",
1416
+ },
1417
+ first_frame: {
1418
+ type: "string",
1419
+ description: "First frame image URL for R2V mode",
1420
+ format: "uri",
1421
+ },
1422
+ video_url_edit: {
1423
+ type: "string",
1424
+ description: "Video URL to edit (video-edit mode)",
1425
+ format: "uri",
1426
+ },
1427
+ reference_image_edit: {
1428
+ type: "string",
1429
+ description: "Reference image URL for video-edit mode",
1430
+ format: "uri",
1431
+ },
1432
+ audio_setting: {
1433
+ type: "string",
1434
+ description: "Audio handling for video-edit: auto or origin",
1435
+ enum: ["auto", "origin"],
1398
1436
  },
1399
1437
  resolution: {
1400
1438
  type: "string",
1401
- description: "Video resolution - 720p for faster generation, 1080p for higher quality",
1439
+ description: "Video resolution",
1402
1440
  enum: ["720p", "1080p"],
1403
1441
  default: "1080p",
1404
1442
  },
1405
- duration: {
1443
+ ratio: {
1406
1444
  type: "string",
1407
- description: "Duration of video in seconds (image-to-video only)",
1408
- enum: ["5", "10"],
1409
- default: "5",
1445
+ description: "Aspect ratio of the generated video",
1446
+ enum: ["16:9", "9:16", "1:1", "4:3", "3:4"],
1447
+ default: "16:9",
1410
1448
  },
1411
- negative_prompt: {
1412
- type: "string",
1413
- description: "Negative prompt to describe content to avoid (max 500 characters)",
1414
- maxLength: 500,
1415
- default: "",
1449
+ duration: {
1450
+ type: "integer",
1451
+ description: "Duration in seconds (2-15)",
1452
+ minimum: 2,
1453
+ maximum: 15,
1454
+ default: 5,
1416
1455
  },
1417
- enable_prompt_expansion: {
1456
+ prompt_extend: {
1418
1457
  type: "boolean",
1419
- description: "Whether to enable prompt rewriting using LLM (improves short prompts but increases processing time)",
1458
+ description: "Enable prompt rewriting using LLM for better results",
1420
1459
  default: true,
1421
1460
  },
1461
+ watermark: {
1462
+ type: "boolean",
1463
+ description: "Add watermark to generated video",
1464
+ default: false,
1465
+ },
1422
1466
  seed: {
1423
1467
  type: "integer",
1424
- description: "Random seed for reproducible results",
1468
+ description: "Random seed for reproducible results (0-2147483647)",
1469
+ minimum: 0,
1470
+ },
1471
+ nsfw_checker: {
1472
+ type: "boolean",
1473
+ description: "Enable NSFW content filter",
1474
+ default: false,
1425
1475
  },
1426
1476
  callBackUrl: {
1427
1477
  type: "string",
1428
- description: "Optional: URL for task completion notifications (uses KIE_AI_CALLBACK_URL env var if not provided)",
1478
+ description: "Optional: URL for task completion notifications",
1429
1479
  format: "uri",
1430
1480
  },
1431
1481
  },
@@ -1788,6 +1838,89 @@ class KieAiMcpServer {
1788
1838
  required: ["video_url", "image_url"],
1789
1839
  },
1790
1840
  },
1841
+ {
1842
+ name: "happyhorse_video",
1843
+ description: "Generate videos using Alibaba HappyHorse 1.0 (text-to-video, image-to-video, reference-to-video with up to 9 images, video-edit with native audio)",
1844
+ inputSchema: {
1845
+ type: "object",
1846
+ properties: {
1847
+ mode: {
1848
+ type: "string",
1849
+ description: "Generation mode: text-to-video (default), image-to-video, reference-to-video, or video-edit. Auto-detected from parameters if omitted.",
1850
+ enum: [
1851
+ "text-to-video",
1852
+ "image-to-video",
1853
+ "reference-to-video",
1854
+ "video-edit",
1855
+ ],
1856
+ },
1857
+ prompt: {
1858
+ type: "string",
1859
+ description: "Text prompt for video generation (max 5000 characters)",
1860
+ minLength: 1,
1861
+ maxLength: 5000,
1862
+ },
1863
+ image_urls: {
1864
+ type: "array",
1865
+ description: "Input image URL for image-to-video mode (max 1)",
1866
+ items: { type: "string", format: "uri" },
1867
+ maxItems: 1,
1868
+ },
1869
+ reference_image: {
1870
+ type: "array",
1871
+ description: "Reference images for reference-to-video mode (up to 9)",
1872
+ items: { type: "string", format: "uri" },
1873
+ maxItems: 9,
1874
+ },
1875
+ video_url: {
1876
+ type: "string",
1877
+ description: "Video URL to edit (video-edit mode)",
1878
+ format: "uri",
1879
+ },
1880
+ reference_image_edit: {
1881
+ type: "array",
1882
+ description: "Reference images for video-edit mode (up to 5)",
1883
+ items: { type: "string", format: "uri" },
1884
+ maxItems: 5,
1885
+ },
1886
+ audio_setting: {
1887
+ type: "string",
1888
+ description: "Audio handling for video-edit: auto or origin",
1889
+ enum: ["auto", "origin"],
1890
+ },
1891
+ resolution: {
1892
+ type: "string",
1893
+ description: "Video resolution",
1894
+ enum: ["720p", "1080p"],
1895
+ default: "1080p",
1896
+ },
1897
+ aspect_ratio: {
1898
+ type: "string",
1899
+ description: "Aspect ratio of the generated video",
1900
+ enum: ["16:9", "9:16", "1:1", "4:3", "3:4"],
1901
+ default: "16:9",
1902
+ },
1903
+ duration: {
1904
+ type: "integer",
1905
+ description: "Duration in seconds (3-15)",
1906
+ minimum: 3,
1907
+ maximum: 15,
1908
+ default: 5,
1909
+ },
1910
+ seed: {
1911
+ type: "integer",
1912
+ description: "Random seed for reproducible results (0-2147483647)",
1913
+ minimum: 0,
1914
+ },
1915
+ callBackUrl: {
1916
+ type: "string",
1917
+ description: "Optional: URL for task completion notifications",
1918
+ format: "uri",
1919
+ },
1920
+ },
1921
+ required: ["prompt"],
1922
+ },
1923
+ },
1791
1924
  {
1792
1925
  name: "sora_video",
1793
1926
  description: "Generate videos using OpenAI's Sora 2 models (unified tool for text-to-video, image-to-video, and storyboard generation with standard/high quality)",
@@ -1882,14 +2015,16 @@ class KieAiMcpServer {
1882
2015
  return await this.handleKlingAvatar(args);
1883
2016
  case "midjourney_generate":
1884
2017
  return await this.handleMidjourneyGenerate(args);
1885
- case "openai_4o_image":
1886
- return await this.handleOpenAI4oImage(args);
2018
+ case "gpt_image_2":
2019
+ return await this.handleGptImage2(args);
1887
2020
  case "flux_kontext_image":
1888
2021
  return await this.handleFluxKontextImage(args);
1889
2022
  case "runway_aleph_video":
1890
2023
  return await this.handleRunwayAlephVideo(args);
1891
2024
  case "wan_video":
1892
2025
  return await this.handleWanVideo(args);
2026
+ case "happyhorse_video":
2027
+ return await this.handleHappyHorseVideo(args);
1893
2028
  case "topaz_upscale_image":
1894
2029
  return await this.handleTopazUpscaleImage(args);
1895
2030
  case "recraft_remove_background":
@@ -1954,9 +2089,9 @@ class KieAiMcpServer {
1954
2089
  },
1955
2090
  },
1956
2091
  {
1957
- uri: "kie://models/openai-4o-image",
1958
- name: "OpenAI GPT-4o Image",
1959
- description: "Creative variants (up to 4), mask editing, limited aspect ratios",
2092
+ uri: "kie://models/gpt-image-2",
2093
+ name: "GPT Image 2",
2094
+ description: "Text-to-image and image-to-image with up to 16 reference images",
1960
2095
  mimeType: "text/markdown",
1961
2096
  annotations: {
1962
2097
  audience: ["assistant"],
@@ -1996,8 +2131,18 @@ class KieAiMcpServer {
1996
2131
  },
1997
2132
  {
1998
2133
  uri: "kie://models/wan-video",
1999
- name: "Wan Video 2.5",
2000
- description: "Fast video generation for social media content",
2134
+ name: "Wan 2.7 Video",
2135
+ description: "Multi-mode video generation: T2V, I2V, R2V, video-edit with audio",
2136
+ mimeType: "text/markdown",
2137
+ annotations: {
2138
+ audience: ["assistant"],
2139
+ priority: 0.6,
2140
+ },
2141
+ },
2142
+ {
2143
+ uri: "kie://models/happyhorse-video",
2144
+ name: "HappyHorse 1.0 Video",
2145
+ description: "Multi-mode video: T2V, I2V, R2V (up to 9 refs), video-edit with audio",
2001
2146
  mimeType: "text/markdown",
2002
2147
  annotations: {
2003
2148
  audience: ["assistant"],
@@ -2457,25 +2602,6 @@ class KieAiMcpServer {
2457
2602
  errorMessage = apiData.failMsg;
2458
2603
  }
2459
2604
  }
2460
- else if (localTask?.api_type === "openai-4o-image") {
2461
- // OpenAI 4o Image-specific status mapping
2462
- const successFlag = apiData.successFlag;
2463
- if (successFlag === 1)
2464
- status = "completed";
2465
- else if (successFlag === 2)
2466
- status = "failed";
2467
- else if (successFlag === 0)
2468
- status = "processing";
2469
- // Extract result URLs from OpenAI 4o response
2470
- if (apiData.response?.result_urls &&
2471
- apiData.response.result_urls.length > 0) {
2472
- resultUrl = apiData.response.result_urls[0]; // Use first image URL
2473
- }
2474
- // Extract error message for OpenAI 4o
2475
- if (apiData.errorMessage) {
2476
- errorMessage = apiData.errorMessage;
2477
- }
2478
- }
2479
2605
  else if (localTask?.api_type === "flux-kontext-image") {
2480
2606
  // Flux Kontext Image-specific status mapping
2481
2607
  const successFlag = apiData.successFlag;
@@ -2620,7 +2746,7 @@ class KieAiMcpServer {
2620
2746
  "nano-banana-image",
2621
2747
  "bytedance-seedream-image",
2622
2748
  "qwen-image",
2623
- "openai-4o-image",
2749
+ "gpt-image-2",
2624
2750
  "flux-kontext-image",
2625
2751
  "topaz-upscale",
2626
2752
  "recraft-remove-background",
@@ -2638,6 +2764,7 @@ class KieAiMcpServer {
2638
2764
  "kling-3.0-video",
2639
2765
  "bytedance-seedance-video",
2640
2766
  "wan-video",
2767
+ "happyhorse-video",
2641
2768
  "hailuo",
2642
2769
  "runway-aleph-video",
2643
2770
  ];
@@ -3690,28 +3817,18 @@ class KieAiMcpServer {
3690
3817
  });
3691
3818
  }
3692
3819
  }
3693
- async handleOpenAI4oImage(args) {
3820
+ async handleGptImage2(args) {
3694
3821
  try {
3695
- const request = OpenAI4oImageSchema.parse(args);
3696
- // Use intelligent callback URL fallback
3822
+ const request = GptImage2Schema.parse(args);
3697
3823
  request.callBackUrl = this.getCallbackUrl(request.callBackUrl);
3698
- const response = await this.client.generateOpenAI4oImage(request);
3824
+ const response = await this.client.generateGptImage2(request);
3699
3825
  if (response.code === 200 && response.data?.taskId) {
3700
- // Determine mode for user feedback
3701
- const hasPrompt = !!request.prompt;
3702
- const hasImages = request.filesUrl && request.filesUrl.length > 0;
3703
- const hasMask = !!request.maskUrl;
3704
- let modeDisplay = "Text-to-Image";
3705
- if (hasMask && hasImages) {
3706
- modeDisplay = "Image Editing";
3707
- }
3708
- else if (hasImages && !hasMask) {
3709
- modeDisplay = "Image Variants";
3710
- }
3711
- // Store task in database
3826
+ const mode = request.input_urls?.length
3827
+ ? "Image-to-Image"
3828
+ : "Text-to-Image";
3712
3829
  await this.db.createTask({
3713
3830
  task_id: response.data.taskId,
3714
- api_type: "openai-4o-image",
3831
+ api_type: "gpt-image-2",
3715
3832
  status: "pending",
3716
3833
  });
3717
3834
  return {
@@ -3721,32 +3838,85 @@ class KieAiMcpServer {
3721
3838
  text: JSON.stringify({
3722
3839
  success: true,
3723
3840
  task_id: response.data.taskId,
3724
- message: `OpenAI 4o Image ${modeDisplay} task created successfully`,
3841
+ message: `GPT Image 2 ${mode} task created successfully`,
3725
3842
  parameters: {
3726
- mode: modeDisplay,
3727
- prompt: request.prompt
3728
- ? request.prompt.substring(0, 100) +
3729
- (request.prompt.length > 100 ? "..." : "")
3730
- : undefined,
3731
- size: request.size || "1:1",
3732
- n_variants: request.nVariants || "4",
3733
- is_enhance: request.isEnhance || false,
3734
- enable_fallback: request.enableFallback !== false,
3735
- fallback_model: request.fallbackModel || "FLUX_MAX",
3736
- ...(hasImages && {
3737
- files_url: request.filesUrl,
3738
- }),
3739
- ...(hasMask && {
3740
- mask_url: request.maskUrl,
3843
+ mode,
3844
+ prompt: request.prompt.substring(0, 100) +
3845
+ (request.prompt.length > 100 ? "..." : ""),
3846
+ aspect_ratio: request.aspect_ratio || "auto",
3847
+ resolution: request.resolution || "1K",
3848
+ ...(request.input_urls && {
3849
+ input_urls: request.input_urls,
3741
3850
  }),
3742
3851
  },
3743
3852
  next_steps: [
3744
3853
  `Use get_task_status with task_id: ${response.data.taskId} to check progress`,
3745
3854
  'Generated images will be available when status is "completed"',
3746
3855
  ],
3747
- usage_examples: [
3748
- `get_task_status: {"task_id": "${response.data.taskId}"}`,
3749
- `list_tasks: {"limit": 10}`,
3856
+ }, null, 2),
3857
+ },
3858
+ ],
3859
+ };
3860
+ }
3861
+ else {
3862
+ throw new Error(response.msg || "Failed to create GPT Image 2 task");
3863
+ }
3864
+ }
3865
+ catch (error) {
3866
+ if (error instanceof z.ZodError) {
3867
+ return this.formatError("gpt_image_2", error, {
3868
+ prompt: "Required: Text prompt describing the desired image (max 20000 chars)",
3869
+ input_urls: "Optional: Array of up to 16 image URLs for image-to-image mode",
3870
+ aspect_ratio: "Optional: auto, 1:1, 9:16, 16:9, 4:3, 3:4 (default: auto)",
3871
+ resolution: "Optional: 1K, 2K, 4K (default: 1K)",
3872
+ });
3873
+ }
3874
+ return this.formatError("gpt_image_2", error, {
3875
+ prompt: "Required: Text prompt describing the desired image (max 20000 chars)",
3876
+ input_urls: "Optional: Array of up to 16 image URLs for image-to-image mode",
3877
+ aspect_ratio: "Optional: auto, 1:1, 9:16, 16:9, 4:3, 3:4 (default: auto)",
3878
+ resolution: "Optional: 1K, 2K, 4K (default: 1K)",
3879
+ });
3880
+ }
3881
+ }
3882
+ async handleHappyHorseVideo(args) {
3883
+ try {
3884
+ const request = HappyHorseVideoSchema.parse(args);
3885
+ request.callBackUrl = this.getCallbackUrl(request.callBackUrl);
3886
+ const response = await this.client.generateHappyHorseVideo(request);
3887
+ if (response.code === 200 && response.data?.taskId) {
3888
+ const mode = request.mode ||
3889
+ (request.video_url
3890
+ ? "video-edit"
3891
+ : request.reference_image?.length
3892
+ ? "reference-to-video"
3893
+ : request.image_urls?.length
3894
+ ? "image-to-video"
3895
+ : "text-to-video");
3896
+ await this.db.createTask({
3897
+ task_id: response.data.taskId,
3898
+ api_type: "happyhorse-video",
3899
+ status: "pending",
3900
+ });
3901
+ return {
3902
+ content: [
3903
+ {
3904
+ type: "text",
3905
+ text: JSON.stringify({
3906
+ success: true,
3907
+ task_id: response.data.taskId,
3908
+ message: `HappyHorse 1.0 ${mode} task created successfully`,
3909
+ parameters: {
3910
+ mode,
3911
+ prompt: request.prompt.substring(0, 100) +
3912
+ (request.prompt.length > 100 ? "..." : ""),
3913
+ resolution: request.resolution || "1080p",
3914
+ aspect_ratio: request.aspect_ratio || "16:9",
3915
+ duration: request.duration || 5,
3916
+ },
3917
+ next_steps: [
3918
+ `Use get_task_status with task_id: ${response.data.taskId} to check progress`,
3919
+ 'Video will be available when status is "completed"',
3750
3920
  ],
3751
3921
  }, null, 2),
3752
3922
  },
@@ -3754,35 +3924,22 @@ class KieAiMcpServer {
3754
3924
  };
3755
3925
  }
3756
3926
  else {
3757
- throw new Error(response.msg || "Failed to create OpenAI 4o Image task");
3927
+ throw new Error(response.msg || "Failed to create HappyHorse task");
3758
3928
  }
3759
3929
  }
3760
3930
  catch (error) {
3761
3931
  if (error instanceof z.ZodError) {
3762
- return this.formatError("openai_4o_image", error, {
3763
- prompt: "Optional: Text prompt describing the desired image (max 5000 chars)",
3764
- filesUrl: "Optional: Array of up to 5 image URLs for editing or variants",
3765
- size: "Required: Image aspect ratio (1:1, 3:2, 2:3, default: 1:1)",
3766
- nVariants: "Optional: Number of image variations (1, 2, 4, default: 4)",
3767
- maskUrl: "Optional: Mask image URL for precise editing (black=edit, white=preserve)",
3768
- callBackUrl: "Optional: Webhook URL for completion notifications",
3769
- isEnhance: "Optional: Enable prompt enhancement for specialized scenarios (default: false)",
3770
- uploadCn: "Optional: Route uploads via China servers (default: false)",
3771
- enableFallback: "Optional: Enable automatic fallback to backup models (default: true)",
3772
- fallbackModel: "Optional: Backup model choice (GPT_IMAGE_1, FLUX_MAX, default: FLUX_MAX)",
3932
+ return this.formatError("happyhorse_video", error, {
3933
+ prompt: "Required: Text prompt for video generation (max 5000 chars)",
3934
+ mode: "Optional: text-to-video, image-to-video, reference-to-video, video-edit",
3935
+ image_urls: "I2V: Single image URL",
3936
+ reference_image: "R2V: Up to 9 reference image URLs",
3937
+ video_url: "Video Edit: Video URL to edit",
3773
3938
  });
3774
3939
  }
3775
- return this.formatError("openai_4o_image", error, {
3776
- prompt: "Optional: Text prompt describing the desired image (max 5000 chars)",
3777
- filesUrl: "Optional: Array of up to 5 image URLs for editing or variants",
3778
- size: "Required: Image aspect ratio (1:1, 3:2, 2:3, default: 1:1)",
3779
- nVariants: "Optional: Number of image variations (1, 2, 4, default: 4)",
3780
- maskUrl: "Optional: Mask image URL for precise editing (black=edit, white=preserve)",
3781
- callBackUrl: "Optional: Webhook URL for completion notifications",
3782
- isEnhance: "Optional: Enable prompt enhancement for specialized scenarios (default: false)",
3783
- uploadCn: "Optional: Route uploads via China servers (default: false)",
3784
- enableFallback: "Optional: Enable automatic fallback to backup models (default: true)",
3785
- fallbackModel: "Optional: Backup model choice (GPT_IMAGE_1, FLUX_MAX, default: FLUX_MAX)",
3940
+ return this.formatError("happyhorse_video", error, {
3941
+ prompt: "Required: Text prompt for video generation (max 5000 chars)",
3942
+ mode: "Optional: text-to-video, image-to-video, reference-to-video, video-edit",
3786
3943
  });
3787
3944
  }
3788
3945
  }
@@ -3952,16 +4109,20 @@ class KieAiMcpServer {
3952
4109
  }
3953
4110
  async handleWanVideo(args) {
3954
4111
  try {
3955
- const request = WanVideoSchema.parse(args);
3956
- // Use intelligent callback URL fallback
4112
+ const request = Wan27VideoSchema.parse(args);
3957
4113
  request.callBackUrl = this.getCallbackUrl(request.callBackUrl);
3958
4114
  const response = await this.client.generateWanVideo(request);
3959
4115
  if (response.code === 200 && response.data?.taskId) {
3960
- // Determine mode for user feedback
3961
- const isImageToVideo = !!request.image_url;
3962
- const mode = isImageToVideo ? "Image-to-Video" : "Text-to-Video";
3963
- const resolution = request.resolution || "1080p";
3964
- // Store task in database
4116
+ const mode = request.mode ||
4117
+ (request.video_url_edit
4118
+ ? "video-edit"
4119
+ : request.reference_image?.length || request.reference_video?.length
4120
+ ? "reference-to-video"
4121
+ : request.first_frame_url ||
4122
+ request.last_frame_url ||
4123
+ request.first_clip_url
4124
+ ? "image-to-video"
4125
+ : "text-to-video");
3965
4126
  await this.db.createTask({
3966
4127
  task_id: response.data.taskId,
3967
4128
  api_type: "wan-video",
@@ -3974,27 +4135,18 @@ class KieAiMcpServer {
3974
4135
  text: JSON.stringify({
3975
4136
  success: true,
3976
4137
  task_id: response.data.taskId,
3977
- message: `Alibaba Wan 2.5 ${mode} generation task created successfully`,
4138
+ message: `Wan 2.7 ${mode} task created successfully`,
3978
4139
  parameters: {
3979
- mode: mode,
4140
+ mode,
3980
4141
  prompt: request.prompt.substring(0, 100) +
3981
4142
  (request.prompt.length > 100 ? "..." : ""),
3982
- resolution: resolution,
3983
- negative_prompt: request.negative_prompt || "",
3984
- enable_prompt_expansion: request.enable_prompt_expansion !== false,
3985
- ...(request.seed !== undefined && { seed: request.seed }),
3986
- ...(isImageToVideo && {
3987
- image_url: request.image_url,
3988
- duration: request.duration || "5",
3989
- }),
3990
- ...(!isImageToVideo && {
3991
- aspect_ratio: request.aspect_ratio || "16:9",
3992
- }),
4143
+ resolution: request.resolution || "1080p",
4144
+ ratio: request.ratio || "16:9",
4145
+ duration: request.duration || 5,
3993
4146
  },
3994
4147
  next_steps: [
3995
- "Use get_task_status to check generation progress",
3996
- "Task completion will be sent to the provided callback URL",
3997
- `${mode} generation typically takes 2-6 minutes depending on resolution and complexity`,
4148
+ `Use get_task_status with task_id: ${response.data.taskId} to check progress`,
4149
+ 'Video will be available when status is "completed"',
3998
4150
  ],
3999
4151
  }, null, 2),
4000
4152
  },
@@ -4002,29 +4154,23 @@ class KieAiMcpServer {
4002
4154
  };
4003
4155
  }
4004
4156
  else {
4005
- throw new Error(response.msg || "Failed to create Wan 2.5 video generation task");
4157
+ throw new Error(response.msg || "Failed to create Wan 2.7 video task");
4006
4158
  }
4007
4159
  }
4008
4160
  catch (error) {
4009
4161
  if (error instanceof z.ZodError) {
4010
4162
  return this.formatError("wan_video", error, {
4011
- prompt: "Required: Text prompt for video generation (max 800 characters)",
4012
- image_url: "Optional: URL of input image for image-to-video mode",
4013
- aspect_ratio: "Optional: Video aspect ratio for text-to-video (16:9, 9:16, 1:1, default: 16:9)",
4014
- resolution: "Optional: Video resolution - 720p or 1080p (default: 1080p)",
4015
- duration: "Optional: Video duration for image-to-video - 5 or 10 seconds (default: 5)",
4016
- negative_prompt: "Optional: Negative prompt to describe content to avoid (max 500 characters)",
4017
- enable_prompt_expansion: "Optional: Enable prompt rewriting using LLM (default: true)",
4018
- seed: "Optional: Random seed for reproducible results",
4019
- callBackUrl: "Optional: URL for task completion notifications (uses KIE_AI_CALLBACK_URL env var if not provided)",
4163
+ prompt: "Required: Text prompt for video generation (max 5000 chars)",
4164
+ mode: "Optional: text-to-video, image-to-video, reference-to-video, video-edit",
4165
+ first_frame_url: "I2V: First frame image URL",
4166
+ last_frame_url: "I2V: Last frame image URL",
4167
+ reference_image: "R2V: Up to 5 reference image URLs",
4168
+ video_url_edit: "Video Edit: Video URL to edit",
4020
4169
  });
4021
4170
  }
4022
4171
  return this.formatError("wan_video", error, {
4023
4172
  prompt: "Required: Text prompt for video generation",
4024
- image_url: "Optional: URL of input image",
4025
- aspect_ratio: "Optional: Video aspect ratio",
4026
- resolution: "Optional: Video resolution",
4027
- callBackUrl: "Optional: URL for task completion notifications",
4173
+ mode: "Optional: text-to-video, image-to-video, reference-to-video, video-edit",
4028
4174
  });
4029
4175
  }
4030
4176
  }
@@ -4654,6 +4800,12 @@ class KieAiMcpServer {
4654
4800
  category: "video",
4655
4801
  quality: "standard",
4656
4802
  },
4803
+ {
4804
+ name: "happyhorse_video",
4805
+ status: "available",
4806
+ category: "video",
4807
+ quality: "standard",
4808
+ },
4657
4809
  {
4658
4810
  name: "runway_aleph",
4659
4811
  status: "available",
@@ -4673,7 +4825,7 @@ class KieAiMcpServer {
4673
4825
  quality: "professional",
4674
4826
  },
4675
4827
  {
4676
- name: "openai_4o_image",
4828
+ name: "gpt_image_2",
4677
4829
  status: "available",
4678
4830
  category: "image",
4679
4831
  quality: "professional",
@@ -5189,7 +5341,7 @@ These guidelines ensure optimal balance between quality requirements and cost ma
5189
5341
  "bytedance-seedream": "bytedance_seedream-v4-text-to-image.md",
5190
5342
  "qwen-image": "qwen_text-to-image.md",
5191
5343
  "flux-kontext": "flux_kontext_image.md",
5192
- "openai-4o-image": "openai_4o-image.md",
5344
+ "gpt-image-2": "gpt_image-2.md",
5193
5345
  "nano-banana": "google_nano-banana.md",
5194
5346
  "topaz-upscale": "topaz_image-upscale.md",
5195
5347
  "recraft-bg-removal": "recraft_remove_background.md",
@@ -5197,7 +5349,8 @@ These guidelines ensure optimal balance between quality requirements and cost ma
5197
5349
  // Video models
5198
5350
  veo3: "google_veo3-text-to-image.md",
5199
5351
  "bytedance-seedance": "bytedance_seedance-2.md",
5200
- "wan-video": "wan_2-5-text-to-video.md",
5352
+ "wan-video": "wan_2-7-text-to-video.md",
5353
+ "happyhorse-video": "happyhorse_text-to-video.md",
5201
5354
  "runway-aleph": "runway_aleph_video.md",
5202
5355
  "kling-v2-1": "kling_v2-1-pro.md",
5203
5356
  "kling-v2-5": "kling_v2-5-turbo-text-to-video-pro.md",