@starreel/mcp 0.1.62 → 0.1.63
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/SKILL.md +1 -0
- package/dist/client.js +2 -2
- package/dist/path-guard.js +3 -1
- package/dist/tools/guide-data.js +3 -2
- package/dist/tools/produce.js +12 -0
- package/openapi.json +53 -2
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -72,6 +72,7 @@ announces a condensed version as MCP `instructions` at connect time.
|
|
|
72
72
|
| A finished **shot list** (per-shot seconds / shot size / camera move) | `get_storyboard_table_spec` (the contract: shot-size / camera-move vocabulary, body layout, text-card syntax, a prompt for the external AI) → `check_storyboard_table` (same parser as the import; clear `errors`, read every `warning` — a missing duration, an unrecognised shot size or an empty body all get imported as-is) → `import_storyboard_table` (defaults to `auto_complete`: one background batch fills the professional fields and expands every shot's platform-built base description into full image / video prompts — metered text, tell the customer first; `auto_complete: false` imports only) → `get_autofill_status` until `done` → `review_storyboards` | `rewrite_script` + `generate_storyboards` — strips every production parameter (measured: 8 shots / 36 s became 20 shots / 109 s); importing without the check; reviewing before the completion batch finishes (the token expires when shots change) |
|
|
73
73
|
| **Structured data** — their own tool / spreadsheet export, or an external AI producing JSON (cast + scenes + shots in one go) | `get_bulk_import_spec` (contract + template + worked example + enums, same source as the validator) → `check_bulk_import` (same zod schema; unresolved character / scene references, dead shots and stage directions inside dialogue are surfaced) → `bulk_import_storyboards` (`mode: "replace"` only with the customer's explicit OK; defaults to `auto_complete`: professional fields for every shot, full image / video prompts only for shots that had no `image_prompt` — prompts you supply yourself are kept verbatim — metered text, tell the customer first) → `get_autofill_status` until `done` → `review_storyboards` | converting the JSON to text for `import_storyboard_table`; hand-building shots with `update_shot`; reviewing before the completion batch finishes |
|
|
74
74
|
| Their own portraits / scene / prop / shot images | `upload_image` · `set_character_portrait` · `upload_scene_image` · `upload_prop_sheet` · `upload_shot_frame` | rendering a "fix" elsewhere and uploading it — use `generate_shot_frame` |
|
|
75
|
+
| Their own **footage** for a shot (screen recording, product b-roll, an existing clip) | `upload_shot_footage` → that shot is no longer AI-generated (frames/video skipped, final cut uses the clip as-is, duration written back from the clip); `clear_shot_footage` to revert | pasting an externally AI-generated clip to "fix" a shot — it carries none of this film's identity / style anchors; use `regenerate_shot_video` instead |
|
|
75
76
|
| A scene plate that came out wrong (backdrop, era, light, layout) | `get_scene_prompt` → `update_scene` (`image_prompt`) → `regenerate_scene_image`; already-rendered shot frames still anchor on the old plate, so regenerate those shots too | re-running `generate_scene_images` (it only fills scenes that have **no** plate — it will not touch this one) |
|
|
76
77
|
| A voice sample / a required voice | `clone_voice` → `speak_with_voice` → `set_character_voice` / `assign_voices` | cloning without the rights-holder's consent |
|
|
77
78
|
| A song + lyrics | `create_drama` (`project_type: "mv"`) → `set_mv_lyrics` → `generate_mv_story` → `generate_mv_script` | `rewrite_script` (blocked for MV) |
|
package/dist/client.js
CHANGED
|
@@ -18,7 +18,7 @@ import { assertSafeLocalMediaPath } from './path-guard.js'; // v0.1.37 — P0③
|
|
|
18
18
|
const MIME_BY_EXT = {
|
|
19
19
|
'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp',
|
|
20
20
|
'.gif': 'image/gif', '.bmp': 'image/bmp',
|
|
21
|
-
'.mp4': 'video/mp4', '.mov': 'video/quicktime',
|
|
21
|
+
'.mp4': 'video/mp4', '.mov': 'video/quicktime', '.webm': 'video/webm', '.m4v': 'video/x-m4v',
|
|
22
22
|
'.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.m4a': 'audio/mp4', '.aac': 'audio/aac',
|
|
23
23
|
'.ogg': 'audio/ogg', '.flac': 'audio/flac',
|
|
24
24
|
};
|
|
@@ -157,7 +157,7 @@ export class StarReelClient {
|
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
159
|
* 本地文件 → 我方 COS:presign(门面 /upload-url)→ 直传字节到预签名 URL → 返回 public_url。
|
|
160
|
-
* 字节不经我们的业务服务器,只走 COS。kind: image(默认)/video/audio。
|
|
160
|
+
* 字节不经我们的业务服务器,只走 COS。kind: image(默认)/video(参考视频)/audio/footage(实拍素材整段视频,额度更大)。
|
|
161
161
|
*/
|
|
162
162
|
async uploadLocalFile(filePath, kind = 'image') {
|
|
163
163
|
// v0.1.37 — P0③:媒体扩展名白名单 + 隐藏/系统目录拒绝(realpath 后判,防符号链接绕过)。
|
package/dist/path-guard.js
CHANGED
|
@@ -15,6 +15,8 @@ import { sep } from 'node:path';
|
|
|
15
15
|
export const MEDIA_EXT_BY_KIND = {
|
|
16
16
|
image: new Set(['.jpg', '.jpeg', '.png', '.webp', '.gif']),
|
|
17
17
|
video: new Set(['.mp4', '.mov', '.webm', '.m4v']),
|
|
18
|
+
// 0.1.63 实拍素材镜(整段视频当某镜的成片):格式同 video,额度更大(后端 presign kind=footage)
|
|
19
|
+
footage: new Set(['.mp4', '.mov', '.webm', '.m4v']),
|
|
18
20
|
audio: new Set(['.mp3', '.wav', '.m4a', '.aac', '.flac', '.ogg']),
|
|
19
21
|
};
|
|
20
22
|
const SYSTEM_PREFIXES = ['/etc/', '/private/etc/', '/proc/', '/sys/'];
|
|
@@ -22,7 +24,7 @@ const SYSTEM_PREFIXES = ['/etc/', '/private/etc/', '/proc/', '/sys/'];
|
|
|
22
24
|
export function assertSafeLocalMediaPath(filePath, kind, resolve = realpathSync) {
|
|
23
25
|
const ext = (filePath.match(/\.[a-z0-9]+$/i)?.[0] || '').toLowerCase();
|
|
24
26
|
if (!MEDIA_EXT_BY_KIND[kind].has(ext)) {
|
|
25
|
-
throw new Error(`file_path 只接受${kind === 'image' ? '图片' : kind === 'video' ? '视频' : '音频'}媒体文件`
|
|
27
|
+
throw new Error(`file_path 只接受${kind === 'image' ? '图片' : (kind === 'video' || kind === 'footage') ? '视频' : '音频'}媒体文件`
|
|
26
28
|
+ `(${[...MEDIA_EXT_BY_KIND[kind]].join('/')});收到 "${ext || '无扩展名'}"。`
|
|
27
29
|
+ '不要用本工具上传配置/密钥/文档类文件。');
|
|
28
30
|
}
|
package/dist/tools/guide-data.js
CHANGED
|
@@ -81,9 +81,10 @@ export const ENTRY_POINTS = [
|
|
|
81
81
|
'upload_scene_image',
|
|
82
82
|
'upload_prop_sheet',
|
|
83
83
|
'upload_shot_frame(只用于客户自有真实素材)',
|
|
84
|
+
'upload_shot_footage(客户自有整段视频当某镜成片:录屏/产品实拍/已有片段;登记后该镜不再 AI 出图出视频,终拼原样用,时长按素材回写;清除用 clear_shot_footage)',
|
|
84
85
|
],
|
|
85
86
|
avoid: '要「改某一镜画面」走 `generate_shot_frame`(平台自动带该镜身份锚·场景道具参考·画风锚);别在外部工具画好再 `upload_shot_frame`——外部图没有任何锚,人物/服装/画风必漂。',
|
|
86
|
-
flow: 'upload_image · set_character_portrait · upload_scene_image · upload_prop_sheet · upload_shot_frame(仅客户自有素材;要改画面走 generate_shot_frame)',
|
|
87
|
+
flow: 'upload_image · set_character_portrait · upload_scene_image · upload_prop_sheet · upload_shot_frame(仅客户自有素材;要改画面走 generate_shot_frame) · upload_shot_footage(整段实拍/录屏当某镜成片)',
|
|
87
88
|
},
|
|
88
89
|
{
|
|
89
90
|
customer_has: '自己的声音样本 / 指定音色',
|
|
@@ -204,7 +205,7 @@ export const PIPELINE = [
|
|
|
204
205
|
},
|
|
205
206
|
{
|
|
206
207
|
step: '8 出视频',
|
|
207
|
-
tools: ['quote_videos', 'generate_videos', 'get_scene_group_plan', 'generate_scene_groups', 'quote_regenerate_shot_video', 'regenerate_shot_video', 'quote_edit_video_shot', 'edit_video_shot', 'get_edit_capabilities'],
|
|
208
|
+
tools: ['quote_videos', 'generate_videos', 'get_scene_group_plan', 'generate_scene_groups', 'quote_regenerate_shot_video', 'regenerate_shot_video', 'quote_edit_video_shot', 'edit_video_shot', 'upload_shot_footage(实拍素材镜:客户录屏/产品实拍直接当该镜视频,不出视频不扣费)', 'get_edit_capabilities'],
|
|
208
209
|
billing: '报价确认后扣点',
|
|
209
210
|
note: 'video_engine 必须在出视频前定(seedance-2.5 默认 / hailuo-3 降本 / wan3.0 风格化·绝不用于写实真人);切换不回溯已生成镜头。',
|
|
210
211
|
},
|
package/dist/tools/produce.js
CHANGED
|
@@ -687,6 +687,18 @@ export function registerProduceTools(server, client) {
|
|
|
687
687
|
const image_url = await client.uploadLocalFile(file_path, 'image');
|
|
688
688
|
return jsonResult(await client.producePost(`/storyboards/${storyboard_id}/frame`, { image_url, frame_type: frame_type ?? 'first_frame' }));
|
|
689
689
|
});
|
|
690
|
+
server.tool('upload_shot_footage', '用**客户自有的整段视频**(录屏 / 产品实拍 / 第三方成片)直接当某镜的视频——实拍素材镜。' +
|
|
691
|
+
'登记后该镜不再 AI 出图/出视频(generate_videos 会跳过它,单镜重生会被拒),终拼原样使用,镜头时长按素材真实长度回写,' +
|
|
692
|
+
'首/尾帧从素材抽帧供帧链与预览用。免费。适用:宣传片里的到账界面录屏、后台大屏实录、产品实拍、客户已有的成片片段。' +
|
|
693
|
+
'⚠️ 别用它把外部 AI 生成的视频贴进来"改画面"——那不带本片身份锚/画风锚,人物·画风必漂;要改画面走 regenerate_shot_video。' +
|
|
694
|
+
'要换回 AI 生成请先 clear_shot_footage。', {
|
|
695
|
+
storyboard_id: z.number().int().positive(),
|
|
696
|
+
file_path: z.string().describe('本地视频路径(mp4/mov/webm/m4v,≤300MB)'),
|
|
697
|
+
}, async ({ storyboard_id, file_path }) => {
|
|
698
|
+
const video_url = await client.uploadLocalFile(file_path, 'footage');
|
|
699
|
+
return jsonResult(await client.producePost(`/storyboards/${storyboard_id}/footage`, { video_url }));
|
|
700
|
+
});
|
|
701
|
+
server.tool('clear_shot_footage', '清除某镜的实拍素材(video_url 置空、来源标记清掉),让这一镜恢复可 AI 生成视频。免费。', { storyboard_id: z.number().int().positive() }, async ({ storyboard_id }) => jsonResult(await client.produceDelete(`/storyboards/${storyboard_id}/footage`)));
|
|
690
702
|
server.tool('upload_scene_image', '用客户自有图片作为某场景的参考图。自动上传+登记。免费。', { scene_id: z.number().int().positive(), file_path: z.string().describe('本地场景图路径') }, async ({ scene_id, file_path }) => {
|
|
691
703
|
const image_url = await client.uploadLocalFile(file_path, 'image');
|
|
692
704
|
return jsonResult(await client.producePost(`/scenes/${scene_id}/image`, { image_url }));
|
package/openapi.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "StarReel Production API",
|
|
5
|
-
"version": "0.1.
|
|
6
|
-
"description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → portraits & sheets → storyboards → keyframes → video shots → TTS → final cut (.mp4).\n\n**Billing is prepaid and agent-safe**: big-ticket stages are quote-then-generate (`quote_*` returns a `quote_id`; for video, quote == actual charge). Insufficient balance returns 402 — nothing half-runs and the account never goes negative.\n\nAuth: exchange your API key at `POST /v1/agent/token` for a 15-minute bearer token.\n\nGenerated from the @starreel/mcp v0.1.
|
|
5
|
+
"version": "0.1.63",
|
|
6
|
+
"description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → portraits & sheets → storyboards → keyframes → video shots → TTS → final cut (.mp4).\n\n**Billing is prepaid and agent-safe**: big-ticket stages are quote-then-generate (`quote_*` returns a `quote_id`; for video, quote == actual charge). Insufficient balance returns 402 — nothing half-runs and the account never goes negative.\n\nAuth: exchange your API key at `POST /v1/agent/token` for a 15-minute bearer token.\n\nGenerated from the @starreel/mcp v0.1.63 tool surface (operationIds match MCP tool names 1:1)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
9
9
|
{
|
|
@@ -6612,6 +6612,53 @@
|
|
|
6612
6612
|
}
|
|
6613
6613
|
}
|
|
6614
6614
|
},
|
|
6615
|
+
"/storyboards/{storyboard_id}/footage": {
|
|
6616
|
+
"delete": {
|
|
6617
|
+
"operationId": "clear_shot_footage",
|
|
6618
|
+
"summary": "清除某镜的实拍素材(video_url 置空、来源标记清掉),让这一镜恢复可 AI 生成视频",
|
|
6619
|
+
"description": "清除某镜的实拍素材(video_url 置空、来源标记清掉),让这一镜恢复可 AI 生成视频。免费。",
|
|
6620
|
+
"tags": [
|
|
6621
|
+
"storyboards"
|
|
6622
|
+
],
|
|
6623
|
+
"parameters": [
|
|
6624
|
+
{
|
|
6625
|
+
"name": "storyboard_id",
|
|
6626
|
+
"in": "path",
|
|
6627
|
+
"required": true,
|
|
6628
|
+
"schema": {
|
|
6629
|
+
"type": "integer",
|
|
6630
|
+
"exclusiveMinimum": 0
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
],
|
|
6634
|
+
"responses": {
|
|
6635
|
+
"200": {
|
|
6636
|
+
"description": "StarReel envelope",
|
|
6637
|
+
"content": {
|
|
6638
|
+
"application/json": {
|
|
6639
|
+
"schema": {
|
|
6640
|
+
"type": "object",
|
|
6641
|
+
"properties": {
|
|
6642
|
+
"code": {
|
|
6643
|
+
"type": "integer"
|
|
6644
|
+
},
|
|
6645
|
+
"message": {
|
|
6646
|
+
"type": "string"
|
|
6647
|
+
},
|
|
6648
|
+
"data": {
|
|
6649
|
+
"description": "Operation result payload"
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
},
|
|
6656
|
+
"402": {
|
|
6657
|
+
"description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
}
|
|
6661
|
+
},
|
|
6615
6662
|
"/storyboards/{storyboard_id}/frame/generate": {
|
|
6616
6663
|
"post": {
|
|
6617
6664
|
"operationId": "generate_shot_frame",
|
|
@@ -7536,6 +7583,10 @@
|
|
|
7536
7583
|
"tool": "upload_shot_frame",
|
|
7537
7584
|
"reason": "unmappable: local file upload flow"
|
|
7538
7585
|
},
|
|
7586
|
+
{
|
|
7587
|
+
"tool": "upload_shot_footage",
|
|
7588
|
+
"reason": "unmappable: local file upload flow"
|
|
7589
|
+
},
|
|
7539
7590
|
{
|
|
7540
7591
|
"tool": "upload_scene_image",
|
|
7541
7592
|
"reason": "unmappable: local file upload flow"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.63",
|
|
4
4
|
"mcpName": "ai.starreel/starreel",
|
|
5
5
|
"description": "StarReel MCP server — drive the AI short-drama production pipeline (script → storyboards → frames → video → final cut) from Claude, Cursor, or any MCP client",
|
|
6
6
|
"license": "MIT",
|
package/server.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
|
|
3
3
|
"name": "ai.starreel/starreel",
|
|
4
4
|
"description": "Turn a script into a finished, downloadable short-drama episode — via MCP or REST.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.63",
|
|
6
6
|
"websiteUrl": "https://starreel.ai",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "@starreel/mcp",
|
|
11
|
-
"version": "0.1.
|
|
11
|
+
"version": "0.1.63",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
},
|