@infimind/video-mcp-cli 1.0.8 → 1.0.10

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 CHANGED
@@ -100,6 +100,8 @@ Parameter applicability:
100
100
  | `sourceImages` | Not supported | allinone / firstlast images | reference / edit reference images |
101
101
  | `sourceVideos` | Not supported | allinone reference videos | edit input videos |
102
102
  | `sourceAudios` | Not supported | allinone reference audio | Not supported |
103
+ | `sourceVideoDurationSeconds` | Not supported | dryRun estimate for videos | dryRun estimate for edit video |
104
+ | `sourceAudioDurationSeconds` | Not supported | dryRun estimate for audio | Not supported |
103
105
  | `taskMode` | Not needed | `allinone` / `firstlast` | `standard` / `reference` / `edit` |
104
106
  | `resolution` | Not supported | `720p` / `1080p` | `720p` / `1080p` |
105
107
  | `ratio` | Not supported | Not supported | reference or text-to-video standard mode |
@@ -107,7 +109,7 @@ Parameter applicability:
107
109
  | `webSearchEnabled` | Not supported | Optional | Not supported |
108
110
  | `dryRun` | Optional preflight | Optional preflight | Optional preflight |
109
111
 
110
- Local file paths and public URLs are both supported. Local files are converted to base64 by the MCP server before being sent to the API.
112
+ Local file paths and public URLs are both supported.
111
113
 
112
114
  Video inputs support MP4/MOV. Audio inputs support MP3/WAV. The server validates media duration, size, count, resolution, and URL safety before estimating credits or creating tasks.
113
115
 
@@ -119,16 +121,15 @@ Media limits:
119
121
  - S5 firstlast: up to 2 images; the first frame is required.
120
122
  - S6 reference: up to 9 images.
121
123
  - S6 edit: up to 1 video and 5 images.
122
- - `inputDurationTier` is not accepted from clients; the server calculates it from the media.
123
124
 
124
125
  URL safety rules:
125
126
 
126
127
  - Only `http` and `https` URLs are accepted.
127
128
  - `localhost`, `127.0.0.1`, private network addresses, reserved IP ranges, and `file:` URLs are rejected.
128
129
  - Redirect targets are revalidated.
129
- - Remote files that are too large, not media, or cannot be safely probed are rejected.
130
+ - Remote files that are too large, not media, or cannot be read safely are rejected.
130
131
 
131
- Use `dryRun: true` to validate parameters, VIP access, estimated credits, and media rules without creating a task or deducting credits. The result includes `success`, `dryRun`, `route`, `engineName`, `taskMode`, `estimatedCredits`, `remainingCredits`, and `validationWarnings`. Specific credit tables are server-side only; use dry run to get the current estimated consumption.
132
+ Use `dryRun: true` to validate parameters, VIP access, media rules, and estimated credits without creating a task or deducting credits. If a dry run includes video or audio, add `sourceVideoDurationSeconds` / `sourceAudioDurationSeconds` to get an estimated credit result. If these duration fields are omitted, dry run can still pass, but the result may not include `estimatedCredits`.
132
133
 
133
134
  #### Dry run before creating a task
134
135
 
@@ -147,6 +148,8 @@ Use `dryRun: true` to validate parameters, VIP access, estimated credits, and me
147
148
 
148
149
  #### 极睿Sa专业版 - 标准生成
149
150
 
151
+ S2 uses `sourceImage`, `seconds`, and `size`; do not pass `taskMode` or `resolution`.
152
+
150
153
  ```json
151
154
  {
152
155
  "prompt": "一个高质感的产品展示视频,柔和布光,镜头缓慢推进",
@@ -170,6 +173,8 @@ Use `dryRun: true` to validate parameters, VIP access, estimated credits, and me
170
173
  "sourceImages": ["/path/to/reference.jpg"],
171
174
  "sourceVideos": ["/path/to/reference.mp4"],
172
175
  "sourceAudios": ["/path/to/music.mp3"],
176
+ "sourceVideoDurationSeconds": [5],
177
+ "sourceAudioDurationSeconds": [5],
173
178
  "seconds": 10,
174
179
  "size": "720x1280",
175
180
  "resolution": "720p",
@@ -251,12 +256,13 @@ Image-to-video:
251
256
  "taskMode": "edit",
252
257
  "sourceVideos": ["/path/to/input.mp4"],
253
258
  "sourceImages": ["/path/to/reference.jpg"],
259
+ "sourceVideoDurationSeconds": [5],
254
260
  "resolution": "720p",
255
261
  "dryRun": true
256
262
  }
257
263
  ```
258
264
 
259
- After dry run succeeds and `estimatedCredits` looks correct, remove `dryRun` or set it to `false` to create the real task. After creating a task, use `get_video_status` with the returned `taskId` to query progress and video links.
265
+ After dry run succeeds and the estimated credits look correct, remove `dryRun` or set it to `false` to create the real task. After creating a task, use `get_video_status` with the returned `taskId` to query progress and video links.
260
266
 
261
267
  ## Development
262
268
 
package/dist/server.js CHANGED
@@ -67,8 +67,7 @@ export function createServer(token, apiBaseUrl) {
67
67
  name: "create_video_task",
68
68
  title: "创建视频生成任务",
69
69
  description: "创建视频生成任务。支持本地文件路径或公网 URL 作为参考图片。" +
70
- "支持极睿Sd专业版和极睿Ha专业版的多模态素材输入。" +
71
- "提示词会根据目标语言自动翻译和优化。",
70
+ "支持极睿Sd专业版和极睿Ha专业版的多模态素材输入。",
72
71
  inputSchema: {
73
72
  type: "object",
74
73
  properties: {
@@ -78,23 +77,33 @@ export function createServer(token, apiBaseUrl) {
78
77
  },
79
78
  sourceImage: {
80
79
  type: "string",
81
- description: "可选的单张参考图片。S2 使用此字段;S6 标准模式可用作单图图生视频。可以是本地文件路径或公网 URL,本地文件会被自动转换为 base64",
80
+ description: "可选的单张参考图片。S2 使用此字段;S6 标准模式可用作单图图生视频。可以是本地文件路径或公网 URL",
82
81
  },
83
82
  sourceImages: {
84
83
  type: "array",
85
- description: "S5/S6 多张参考图片。本地文件路径或公网 URL 数组;本地文件会被自动转换为 base64。S5 首尾帧模式下第1张为首帧、第2张为尾帧;S6 reference/edit 模式作为参考图",
84
+ description: "S5/S6 多张参考图片。本地文件路径或公网 URL 数组。S5 首尾帧模式下第1张为首帧、第2张为尾帧;S6 reference/edit 模式作为参考图",
86
85
  items: { type: "string" },
87
86
  },
88
87
  sourceVideos: {
89
88
  type: "array",
90
- description: "S5 全能参考或 S6 视频编辑模式的视频素材。本地文件路径或公网 URL 数组;本地文件会被自动转换为 base64",
89
+ description: "S5 全能参考或 S6 视频编辑模式的视频素材。本地文件路径或公网 URL 数组",
91
90
  items: { type: "string" },
92
91
  },
93
92
  sourceAudios: {
94
93
  type: "array",
95
- description: "S5 全能参考模式的音频素材。本地文件路径或公网 URL 数组;本地文件会被自动转换为 base64",
94
+ description: "S5 全能参考模式的音频素材。本地文件路径或公网 URL 数组",
96
95
  items: { type: "string" },
97
96
  },
97
+ sourceVideoDurationSeconds: {
98
+ type: "array",
99
+ description: "可选。dryRun 使用的视频素材时长秒数数组,顺序与 sourceVideos 一致;用于获得预估积分",
100
+ items: { type: "number" },
101
+ },
102
+ sourceAudioDurationSeconds: {
103
+ type: "array",
104
+ description: "可选。dryRun 使用的音频素材时长秒数数组,顺序与 sourceAudios 一致;用于获得预估积分",
105
+ items: { type: "number" },
106
+ },
98
107
  size: {
99
108
  type: "string",
100
109
  description: "视频方向/比例。S2 支持横竖屏;S5/S6 还支持正方形、4:3、3:4(默认:1280x720)",
@@ -163,6 +172,7 @@ export function createServer(token, apiBaseUrl) {
163
172
  videoCount: { type: "number" },
164
173
  dryRun: { type: "boolean" },
165
174
  estimatedCredits: { type: "number" },
175
+ estimateSource: { type: "string" },
166
176
  remainingCredits: { type: "number" },
167
177
  statusHint: { type: "string" },
168
178
  validationWarnings: {
@@ -245,13 +255,13 @@ export function createServer(token, apiBaseUrl) {
245
255
  name: "create_video_analysis_task",
246
256
  title: "创建视频拆解任务",
247
257
  description: "创建视频拆解任务,将视频拆解为脚本、风格、卖点话术、爆款公式,并生成用于视频创作的提示词。" +
248
- "支持本地文件路径或公网 URL 作为视频文件。本地文件会被自动转换为 base64。",
258
+ "支持本地文件路径或公网 URL。",
249
259
  inputSchema: {
250
260
  type: "object",
251
261
  properties: {
252
262
  videoFile: {
253
263
  type: "string",
254
- description: "要分析的视频文件 - 可以是本地文件路径(如 /path/to/video.mp4)或公网 URL。本地文件会被自动转换为 base64",
264
+ description: "要分析的视频文件,可以是本地文件路径或公网 URL",
255
265
  },
256
266
  },
257
267
  required: ["videoFile"],
@@ -361,8 +371,8 @@ async function handleGetUserInfo(apiBaseUrl, token) {
361
371
  `# 用户信息`,
362
372
  ``,
363
373
  `- **用户名**: ${response.username}`,
364
- `- **姓名**: ${response.name || "N/A"}`,
365
- `- **邮箱**: ${response.email || "N/A"}`,
374
+ `- **姓名**: ${response.name || "未提供"}`,
375
+ `- **邮箱**: ${response.email || "未提供"}`,
366
376
  `- **角色**: ${response.role === "admin" ? "管理员" : "用户"}`,
367
377
  `- **积分**: ${response.credits}`,
368
378
  `- **VIP 状态**: ${response.isVip ? "是" : "否"}`,
@@ -495,9 +505,6 @@ function validateCreateVideoArgs(args) {
495
505
  const taskMode = normalizeTaskMode(route, args.taskMode);
496
506
  const resolution = typeof args.resolution === "string" ? args.resolution : "720p";
497
507
  const dryRun = args.dryRun === true;
498
- if (args.inputDurationTier !== undefined) {
499
- throw new McpToolError("inputDurationTier 不再支持由 MCP 传入;输入视频时长档位由服务端根据素材自动计算。", "UNSUPPORTED_FIELD", route);
500
- }
501
508
  if ((route === "S5" || route === "S6") && resolution !== "720p" && resolution !== "1080p") {
502
509
  throw new McpToolError(`${getMcpEngineName(route)} 仅支持 720p 或 1080p。`, "INVALID_RESOLUTION", route);
503
510
  }
@@ -591,26 +598,36 @@ function validateCreateVideoArgs(args) {
591
598
  */
592
599
  async function handleCreateVideoTask(apiBaseUrl, token, args) {
593
600
  const normalized = validateCreateVideoArgs(args);
594
- const response = await callRestApi(apiBaseUrl, "/mcp/video/create", {
601
+ const isProfessionalRoute = normalized.route === "S5" || normalized.route === "S6";
602
+ const requestBody = {
595
603
  token,
596
604
  prompt: args.prompt,
597
- sourceImage: args.sourceImage ? (await processFileInput(args.sourceImage, "image")).data : undefined,
598
- sourceImages: await processFileInputs(args.sourceImages, "image"),
599
- sourceVideos: await processFileInputs(args.sourceVideos, "video"),
600
- sourceAudios: await processFileInputs(args.sourceAudios, "audio"),
605
+ sourceImage: args.sourceImage
606
+ ? (await processFileInput(args.sourceImage, "image")).data
607
+ : undefined,
601
608
  size: args.size || "1280x720",
602
609
  seconds: args.seconds || 10,
603
610
  language: args.language || "zh-CN",
604
611
  count: args.count || 1,
605
612
  route: normalized.route,
606
- taskMode: normalized.taskMode,
607
- isFirstLastMode: normalized.taskMode === "firstlast",
608
- resolution: normalized.resolution,
609
- ratio: args.ratio || undefined,
610
- generateAudio: args.generateAudio,
611
- webSearchEnabled: args.webSearchEnabled,
612
613
  dryRun: normalized.dryRun,
613
- }, "POST");
614
+ };
615
+ if (isProfessionalRoute) {
616
+ requestBody.sourceImages = await processFileInputs(args.sourceImages, "image");
617
+ requestBody.sourceVideos = await processFileInputs(args.sourceVideos, "video");
618
+ requestBody.sourceAudios = await processFileInputs(args.sourceAudios, "audio");
619
+ requestBody.taskMode = normalized.taskMode;
620
+ requestBody.isFirstLastMode = normalized.taskMode === "firstlast";
621
+ requestBody.resolution = normalized.resolution;
622
+ requestBody.ratio = args.ratio || undefined;
623
+ requestBody.generateAudio = args.generateAudio;
624
+ requestBody.webSearchEnabled = args.webSearchEnabled;
625
+ if (normalized.dryRun) {
626
+ requestBody.sourceVideoDurationSeconds = args.sourceVideoDurationSeconds;
627
+ requestBody.sourceAudioDurationSeconds = args.sourceAudioDurationSeconds;
628
+ }
629
+ }
630
+ const response = await callRestApi(apiBaseUrl, "/mcp/video/create", requestBody, "POST");
614
631
  const route = response.route || normalized.route;
615
632
  const engineName = response.engineName || getMcpEngineName(route);
616
633
  const taskMode = response.taskMode || normalized.taskMode;
@@ -624,9 +641,11 @@ async function handleCreateVideoTask(apiBaseUrl, token, args) {
624
641
  `- **模式**: ${taskMode}`,
625
642
  `- **消息**: ${response.message}`,
626
643
  `- **生成视频数量**: ${response.videoCount}`,
627
- `- **预估积分**: ${estimatedCredits ?? "N/A"}(视频完成后按成功扣费)`,
628
644
  `- **当前积分**: ${response.remainingCredits}`,
629
645
  ];
646
+ if (typeof estimatedCredits === "number") {
647
+ result.splice(6, 0, `- **预估积分**: ${estimatedCredits}(视频完成后按成功扣费)`);
648
+ }
630
649
  if (!dryRun && response.taskId !== undefined) {
631
650
  result.splice(4, 0, `- **任务 ID**: ${response.taskId}`);
632
651
  }
@@ -650,6 +669,7 @@ async function handleCreateVideoTask(apiBaseUrl, token, args) {
650
669
  videoCount: response.videoCount,
651
670
  dryRun,
652
671
  estimatedCredits,
672
+ estimateSource: response.estimateSource,
653
673
  remainingCredits: response.remainingCredits,
654
674
  statusHint,
655
675
  validationWarnings: response.validationWarnings || [],
@@ -1,6 +1,6 @@
1
1
  export type McpRoute = "S2" | "S5" | "S6";
2
2
  export type McpTaskMode = "allinone" | "firstlast" | "standard" | "reference" | "edit";
3
- export declare const MCP_SERVER_VERSION = "1.0.5";
3
+ export declare const MCP_SERVER_VERSION = "1.0.10";
4
4
  export declare const MCP_VIDEO_STATUS_HINT = "\u4EFB\u52A1\u5DF2\u521B\u5EFA\u540E\uFF0C\u4F7F\u7528 get_video_status \u5E76\u4F20\u5165 taskId \u67E5\u8BE2\u751F\u6210\u8FDB\u5EA6\u548C\u89C6\u9891\u94FE\u63A5\u3002";
5
5
  export declare const MCP_VIDEO_DRY_RUN_HINT = "dryRun \u4EC5\u5B8C\u6210\u53C2\u6570\u3001\u6743\u9650\u3001\u79EF\u5206\u548C\u7D20\u6750\u89C4\u5219\u9884\u68C0\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u4EFB\u52A1\u6216\u6263\u8D39\u3002";
6
6
  export declare const MCP_VIDEO_ENGINES: Record<McpRoute, {
@@ -1,4 +1,4 @@
1
- export const MCP_SERVER_VERSION = "1.0.5";
1
+ export const MCP_SERVER_VERSION = "1.0.10";
2
2
  export const MCP_VIDEO_STATUS_HINT = "任务已创建后,使用 get_video_status 并传入 taskId 查询生成进度和视频链接。";
3
3
  export const MCP_VIDEO_DRY_RUN_HINT = "dryRun 仅完成参数、权限、积分和素材规则预检,不会创建任务或扣费。";
4
4
  export const MCP_VIDEO_ENGINES = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infimind/video-mcp-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "MCP Server for Sora AI Video Generator - Access video generation features through Claude Desktop",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",