@starreel/mcp 0.1.16 → 0.1.17

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 CHANGED
@@ -96,12 +96,22 @@ content that will be rejected.
96
96
  video: a portrait is one image, but **character sheets (multi-view turnarounds)
97
97
  are the shot consistency anchor every frame references** — portraits alone
98
98
  leave characters drifting across angle / lighting / wardrobe.
99
- `generate_portraits_and_sheets` does both (portraits first, then sheets). `generate_frames` makes **first frames only** — you do
99
+ `generate_portraits_and_sheets` does both (portraits first, then sheets). `generate_frames` makes **first frames only** by default — you do
100
100
  NOT generate first + last together. A **last frame** is optional and never
101
- auto-made; upload it via `upload_shot_frame` (`frame_type=last_frame`) only to
102
- pin a shot's ending (a big camera move or reveal). `generate_videos` needs at
101
+ auto-made; ask for one only to pin a shot's ending (a big camera move or
102
+ reveal), via `generate_frames` with `frame_type=last_frame` or, for a single
103
+ shot, `generate_shot_frame`. `generate_videos` needs at
103
104
  least one first frame in the episode.
104
105
 
106
+ **Redraw on-platform, never off-platform.** When a shot's image is wrong,
107
+ fix it with `quote_shot_frame` → `generate_shot_frame` (`frame_type`:
108
+ `first_frame` / `last_frame` / `both`). That path carries the shot's character
109
+ identity anchors, scene/prop references, style lock and frame audit, so the new
110
+ image still matches the rest of the film. Do **not** render the image in another
111
+ image tool and push it in with `upload_shot_frame` — that bypasses every anchor
112
+ (faces, wardrobe and style drift) and makes you hostage to that tool's queue.
113
+ `upload_shot_frame` is for art the customer already owns.
114
+
105
115
  7. **Poll, don't block; don't hammer.** Long steps return immediately as
106
116
  `status:generating`. Poll `get_pipeline_status` / `get_jobs` /
107
117
  `get_storyboards` with a backoff (start ~5–10s, widen on no change). Stable
@@ -32,6 +32,8 @@ const ETHNICITY_CODES = [
32
32
  // 画幅/分辨率的可选值 —— create_drama 与 update_project_settings **共用同一源**,防两处漂移。
33
33
  // 与后端发现接口 produce-options.ts 的 ASPECT_RATIO_OPTIONS / VIDEO_RESOLUTION_OPTIONS 键集一致
34
34
  // (video_resolution 与后端 VIDEO_RES_WHITELIST 钉死;aspect_ratio 后端柔性,这里给同一策展集)。
35
+ // 帧类型(与后端 produce-facade.parseFrameParam 同一枚举):整集/单镜出帧共用。
36
+ const FRAME_TYPE_ARG = z.enum(['first_frame', 'last_frame', 'both']);
35
37
  const ASPECT_RATIOS = ['9:16', '16:9', '1:1', '4:5', '4:3', '21:9'];
36
38
  const VIDEO_RESOLUTIONS = ['480p', '720p', '1080p', '4k'];
37
39
  /** 把友好 ethnicity 枚举 + note 组装成后端认的结构化族裔锁 { code, note? }。 */
@@ -120,9 +122,33 @@ export function registerProduceTools(server, client) {
120
122
  'insufficient_credits/transient)、retryable(true=可重试;false=改内容换图,重试无效)、fail_hint(人读文案)。' +
121
123
  '照 retryable 判该重试还是该改内容,别解析中文。免费。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/storyboards`)));
122
124
  // ---------- 出首帧(frames) ----------
123
- server.tool('quote_frames', '报价:给某一集缺首帧的分镜批量出首帧要多少点。返回 frames_to_generate、estimated_points、quote_id。零扣费。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/frames/quote`)));
124
- server.tool('generate_frames', '确认后批量出首帧:后台异步。用 get_storyboards 轮询,first_frame_image 逐镜填充即完成。' +
125
- '出视频前必须先出帧,否则视频会退化成无一致性锚点的画面。' + CONFIRM_HINT, { episode_id: z.number().int().positive(), quote_id: z.string().describe('来自 quote_frames') }, async ({ episode_id, quote_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/frames/generate`, { quote_id })));
125
+ server.tool('quote_frames', '报价:给某一集批量出帧要多少点。返回 frames_to_generate、estimated_points、quote_id。零扣费。' +
126
+ 'frame_type 默认 first_frame(只给缺首帧的镜出);last_frame 只给「已有首帧且缺尾帧」的镜出;both 两者都补。', {
127
+ episode_id: z.number().int().positive(),
128
+ frame_type: FRAME_TYPE_ARG.optional().describe('默认 first_frame;last_frame=补尾帧;both=首尾都补'),
129
+ }, async ({ episode_id, frame_type }) => jsonResult(await client.producePost(`/episodes/${episode_id}/frames/quote`, { frame_type })));
130
+ server.tool('generate_frames', '确认后批量出帧:后台异步。用 get_storyboards 轮询,first_frame_image/last_frame_image 逐镜填充即完成。' +
131
+ '出视频前必须先出帧,否则视频会退化成无一致性锚点的画面。' +
132
+ 'frame_type 要与 quote_frames 用的一致(默认 first_frame)。尾帧只在想固定某镜结尾画面时才补,常规只需首帧。' + CONFIRM_HINT, {
133
+ episode_id: z.number().int().positive(),
134
+ quote_id: z.string().describe('来自 quote_frames'),
135
+ frame_type: FRAME_TYPE_ARG.optional().describe('默认 first_frame,须与报价时一致'),
136
+ }, async ({ episode_id, quote_id, frame_type }) => jsonResult(await client.producePost(`/episodes/${episode_id}/frames/generate`, { quote_id, frame_type })));
137
+ // ---------- 单镜出帧/重生(改某一镜的画面走这里,别去外部平台出图再传回来) ----------
138
+ server.tool('quote_shot_frame', '报价:重画/补出**某一镜的某一帧**要多少点(一帧=一张图)。返回 estimated_points、quote_id。零扣费。' +
139
+ '客户说「第 N 镜画错了/要改」时用它,而不是拿别的图像平台出图再 upload_shot_frame。', {
140
+ storyboard_id: z.number().int().positive(),
141
+ frame_type: FRAME_TYPE_ARG.optional().describe('默认 first_frame;both=首尾各一张'),
142
+ }, async ({ storyboard_id, frame_type }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/frame/quote`, { frame_type })));
143
+ server.tool('generate_shot_frame', '确认后给**某一镜**出帧或重生该帧(异步)。这是修某一镜画面的正路:平台会带上该镜的角色身份锚、' +
144
+ '场景/道具参考图、画风锚与帧审计,重生出的图与全片一致;用外部工具出图再上传会绕开这整条链路,人物/服装/画风必漂。' +
145
+ '重生会覆盖该帧现有图(含此前上传的),并把本镜视频标为待重生。尾帧需本镜首帧已就绪(否则先用 first_frame 或 both)。' +
146
+ '完成判据:轮询 get_storyboards 看该镜 first_frame_image/last_frame_image 变化。' + CONFIRM_HINT, {
147
+ storyboard_id: z.number().int().positive(),
148
+ quote_id: z.string().describe('来自 quote_shot_frame'),
149
+ frame_type: FRAME_TYPE_ARG.optional().describe('默认 first_frame,须与报价时一致'),
150
+ replace_user_frame: z.boolean().optional().describe('默认 true(显式重生允许覆盖已上传帧);传 false 则保护已上传帧'),
151
+ }, async ({ storyboard_id, quote_id, frame_type, replace_user_frame }) => jsonResult(await client.producePost(`/storyboards/${storyboard_id}/frame/generate`, { quote_id, frame_type, replace_user_frame })));
126
152
  // ---------- 出视频(videos,大额) ----------
127
153
  server.tool('quote_videos', '报价:给某一集所有分镜批量出视频要多少点(与实际扣费同函数,较准)。返回 estimated_points、quote_id。零扣费。' +
128
154
  '⚠️ 视频是大额花费,务必把点数清楚告诉用户并等其确认。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/videos/quote`)));
@@ -213,7 +239,9 @@ export function registerProduceTools(server, client) {
213
239
  throw new Error('file_path 或 image_url 至少提供一个');
214
240
  return jsonResult(await client.producePost(`/characters/${character_id}/portrait`, { image_url: url }));
215
241
  });
216
- server.tool('upload_shot_frame', '用客户自有图片作为某镜的首帧(first_frame)或尾帧(last_frame)。尾帧可选、系统不自动生成——仅在想固定某镜结尾画面(大运镜/揭示镜)时传;常规只需首帧。会把该镜已有视频标为过期待重生。自动上传+登记。免费。', {
242
+ server.tool('upload_shot_frame', '用**客户自有图片**作为某镜的首帧(first_frame)或尾帧(last_frame)。尾帧可选——仅在想固定某镜结尾画面(大运镜/揭示镜)时传;常规只需首帧。会把该镜已有视频标为过期待重生。自动上传+登记。免费。' +
243
+ '⚠️ 只用于客户自己提供的素材。想「重画/修某一镜」请用 generate_shot_frame 让平台重生——' +
244
+ '外部工具出的图不带本片的身份锚与画风锚,贴进来人物/服装/画风会漂。', {
217
245
  storyboard_id: z.number().int().positive(),
218
246
  file_path: z.string().describe('本地帧图路径'),
219
247
  frame_type: z.enum(['first_frame', 'last_frame']).optional().describe('默认 first_frame'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starreel/mcp",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
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.13",
5
+ "version": "0.1.17",
6
6
  "websiteUrl": "https://starreel.ai",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "@starreel/mcp",
11
- "version": "0.1.13",
11
+ "version": "0.1.17",
12
12
  "transport": { "type": "stdio" },
13
13
  "environmentVariables": [
14
14
  {