@starreel/mcp 0.1.247 → 0.1.248

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
@@ -1530,6 +1530,18 @@ to close") tells the vendor to fit that entire sequence into each 3-second shot.
1530
1530
  (explain away a conflict the AI mis-read instead of editing shots),
1531
1531
  `link_world_state_scene_variant`, `derive_pose_chain` (LLM, **billed** — fills
1532
1532
  only the shots whose poses are blank, so cuts connect).
1533
+ - **Intermediate keyframes inside one shot (closed beta)**: `plan_shot_keyframes`
1534
+ (LLM, **billed**; `dry_run:true` to preview) adds 1–3 "at second t the frame
1535
+ shows …" targets between a shot's first and last frame — wind-up, contact,
1536
+ landing — so the video passes those beats instead of skipping them. Only
1537
+ shots on `seedance-2.5` (it follows keyframe timing within about ±1 s), ≥5 s,
1538
+ marked state-change or key moment. Fills empty shots only. Read with
1539
+ `get_shot_keyframes` (returns the allowed window: t in [2, duration−1],
1540
+ ≥2 s apart, max 3) or the `keyframes` field of `get_storyboards`; overwrite
1541
+ with `set_shot_keyframes`. Prompts must describe a visible pose — no
1542
+ "about to / starting to" wording and no "no X" negations (both rejected).
1543
+ A 400 "未开启" means the project is not in the beta. This stage only plans;
1544
+ rendering the keyframes and feeding them to the video model come later.
1533
1545
  - **Era contract**: `set_era_contract` / `get_era_contract` — see the project
1534
1546
  settings tier above. Non-contemporary projects must set this before frames.
1535
1547
  - **Lengthen a finished cut**: `quote_extend_final` (free, quote first) →
@@ -1322,6 +1322,30 @@ export function registerProduceTools(server, client) {
1322
1322
  + '**要花钱**(走 LLM)。'
1323
1323
  + '\n★只填**空着**的那些镜,已经写了姿态的不动;黑场镜自动跳过。'
1324
1324
  + '\n出图前做,能减少「上一镜站着下一镜突然坐着」这类接不上的情况。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/derive-pose-chain`, {})));
1325
+ server.tool('plan_shot_keyframes', '★**内测**·规划**单镜中间关键帧**:给动作复杂的镜头在首帧与尾帧之间加 1~3 个「第 t 秒该是什么画面」的目标'
1326
+ + '(蓄力、命中、落地等节点),让视频动作按节点走、不跳过过程。**要花钱**(走 LLM,文本按 token 后付)。'
1327
+ + '\n★只规划视频引擎为 seedance-2.5 的镜(只有它按秒对齐关键帧,误差约 ±1 秒);时长 ≥5 秒、标为状态变化或关键镜的才会规划。'
1328
+ + '\n★只填**空着**的镜:已经有中间关键帧的(含客户自己写的)一律不动。dry_run:true 只返回规划不写库,先给客户看。'
1329
+ + '\n★结果用 get_storyboards 每镜的 keyframes 字段读;要改用 set_shot_keyframes。'
1330
+ + '\n★回 400「本剧未开启」= 本剧不在内测名单,不是调用错误,别重试。本期只规划、不出图,出中间帧与送进视频是后续功能。', {
1331
+ episode_id: z.number().int().positive(),
1332
+ dry_run: z.boolean().optional().describe('true = 只返回规划结果、不写库'),
1333
+ }, async ({ episode_id, dry_run }) => jsonResult(await client.producePost(`/episodes/${episode_id}/keyframes/plan`, { dry_run: dry_run === true })));
1334
+ server.tool('get_shot_keyframes', '★**内测**·读**某一镜**的中间关键帧与可放范围。免费。'
1335
+ + '回 keyframes(每项 t_sec / prompt / source=planner|author / status)、window(min_t、max_t、相邻最小间隔 gap、本镜最多几张 cap)'
1336
+ + '与 enabled(本剧是否在内测名单)。写之前先读这里,按 window 排秒数,再调 set_shot_keyframes。', { storyboard_id: z.number().int().positive() }, async ({ storyboard_id }) => jsonResult(await client.produceGet(`/storyboards/${storyboard_id}/keyframes`)));
1337
+ server.tool('set_shot_keyframes', '★**内测**·写**某一镜**的中间关键帧(整体覆盖;[] = 清空)。免费(纯文本写库)。'
1338
+ + '\n每项 { t_sec, prompt }:t_sec 是镜内第几秒,必须落在 [2, 时长-1] 之内(开头会定格在首帧、结尾留给尾帧),'
1339
+ + '相邻至少间隔 2 秒,每镜最多 3 张;prompt 写那一刻**看得见的**画面(人在哪、什么姿态、物件什么状态、景别机位与首帧一致)。'
1340
+ + '\n★不收「正要 / 刚开始 / about to」这类起点措辞(单帧画不出「正在开始」),也不收「没有 X / no X」否定句'
1341
+ + '(会把 X 画出来);违规会 400 并说明哪一张哪里不对,照着改写再提交。'
1342
+ + '\n★先 get_storyboards 读现值再改。回 400「本剧未开启」= 本剧不在内测名单。', {
1343
+ storyboard_id: z.number().int().positive(),
1344
+ keyframes: z.array(z.object({
1345
+ t_sec: z.number().describe('镜内秒数'),
1346
+ prompt: z.string().min(2).max(600).describe('这一刻看得见的画面'),
1347
+ })).max(3),
1348
+ }, async ({ storyboard_id, keyframes }) => jsonResult(await client.producePut(`/storyboards/${storyboard_id}/keyframes`, { keyframes })));
1325
1349
  server.tool('quote_extend_final', '★成片续写**报价**(免费·无副作用):在已有成片后面再接几轮 AI 生成的片段,把片子拉长。'
1326
1350
  + '回 rounds(轮数)/duration_per_round(每轮秒数)/max_rounds(上限)/estimated_points(预估点数)。'
1327
1351
  + '\n★**必须先 quote_extend_final 报价,再调 extend_final**' + MODE_DECIDES('报价确认') + '(派发前平台按同参整单报价过预算预检,超出硬上限回 402 BUDGET_WOULD_EXCEED、未扣费,那就停下问客户)' + '——每轮都真扣厂商的钱。'
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.247",
6
- "description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → storyboards → portraits & sheets + scene plates → 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. For images the quote is a *range* — models billed per reference image are priced before those are assembled, so `estimated_points` is the upper bound (size the balance by it and a run never dies half-way) and `typical_points` is the usual cost; fixed-price models return the two equal. 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.247 tool surface (operationIds match MCP tool names 1:1)."
5
+ "version": "0.1.248",
6
+ "description": "Turn a script into a finished, downloadable short-drama episode over REST.\n\nPipeline: script → AI rewrite → cast/scenes/props extraction → storyboards → portraits & sheets + scene plates → 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. For images the quote is a *range* — models billed per reference image are priced before those are assembled, so `estimated_points` is the upper bound (size the balance by it and a run never dies half-way) and `typical_points` is the usual cost; fixed-price models return the two equal. 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.248 tool surface (operationIds match MCP tool names 1:1)."
7
7
  },
8
8
  "servers": [
9
9
  {
@@ -8134,6 +8134,68 @@
8134
8134
  }
8135
8135
  }
8136
8136
  },
8137
+ "/episodes/{episode_id}/keyframes/plan": {
8138
+ "post": {
8139
+ "operationId": "plan_shot_keyframes",
8140
+ "summary": "★**内测**·规划**单镜中间关键帧**:给动作复杂的镜头在首帧与尾帧之间加 1~3 个「第 t 秒该是什么画面」的目标(蓄力、命中、落地等节点),让视频动作按节点走、不跳过过程",
8141
+ "description": "★**内测**·规划**单镜中间关键帧**:给动作复杂的镜头在首帧与尾帧之间加 1~3 个「第 t 秒该是什么画面」的目标(蓄力、命中、落地等节点),让视频动作按节点走、不跳过过程。**要花钱**(走 LLM,文本按 token 后付)。\n★只规划视频引擎为 seedance-2.5 的镜(只有它按秒对齐关键帧,误差约 ±1 秒);时长 ≥5 秒、标为状态变化或关键镜的才会规划。\n★只填**空着**的镜:已经有中间关键帧的(含客户自己写的)一律不动。dry_run:true 只返回规划不写库,先给客户看。\n★结果用 get_storyboards 每镜的 keyframes 字段读;要改用 set_shot_keyframes。\n★回 400「本剧未开启」= 本剧不在内测名单,不是调用错误,别重试。本期只规划、不出图,出中间帧与送进视频是后续功能。",
8142
+ "tags": [
8143
+ "episodes"
8144
+ ],
8145
+ "parameters": [
8146
+ {
8147
+ "name": "episode_id",
8148
+ "in": "path",
8149
+ "required": true,
8150
+ "schema": {
8151
+ "type": "integer",
8152
+ "exclusiveMinimum": 0
8153
+ }
8154
+ }
8155
+ ],
8156
+ "requestBody": {
8157
+ "required": false,
8158
+ "content": {
8159
+ "application/json": {
8160
+ "schema": {
8161
+ "type": "object",
8162
+ "properties": {
8163
+ "dry_run": {
8164
+ "type": "boolean"
8165
+ }
8166
+ }
8167
+ }
8168
+ }
8169
+ }
8170
+ },
8171
+ "responses": {
8172
+ "200": {
8173
+ "description": "StarReel envelope",
8174
+ "content": {
8175
+ "application/json": {
8176
+ "schema": {
8177
+ "type": "object",
8178
+ "properties": {
8179
+ "code": {
8180
+ "type": "integer"
8181
+ },
8182
+ "message": {
8183
+ "type": "string"
8184
+ },
8185
+ "data": {
8186
+ "description": "Operation result payload"
8187
+ }
8188
+ }
8189
+ }
8190
+ }
8191
+ }
8192
+ },
8193
+ "402": {
8194
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
8195
+ }
8196
+ }
8197
+ }
8198
+ },
8137
8199
  "/episodes/{episode_id}/lipsync-batch": {
8138
8200
  "post": {
8139
8201
  "operationId": "lipsync_episode",
@@ -15788,6 +15850,137 @@
15788
15850
  }
15789
15851
  }
15790
15852
  },
15853
+ "/storyboards/{storyboard_id}/keyframes": {
15854
+ "get": {
15855
+ "operationId": "get_shot_keyframes",
15856
+ "summary": "★**内测**·读**某一镜**的中间关键帧与可放范围",
15857
+ "description": "★**内测**·读**某一镜**的中间关键帧与可放范围。免费。回 keyframes(每项 t_sec / prompt / source=planner|author / status)、window(min_t、max_t、相邻最小间隔 gap、本镜最多几张 cap)与 enabled(本剧是否在内测名单)。写之前先读这里,按 window 排秒数,再调 set_shot_keyframes。",
15858
+ "tags": [
15859
+ "storyboards"
15860
+ ],
15861
+ "parameters": [
15862
+ {
15863
+ "name": "storyboard_id",
15864
+ "in": "path",
15865
+ "required": true,
15866
+ "schema": {
15867
+ "type": "integer",
15868
+ "exclusiveMinimum": 0
15869
+ }
15870
+ }
15871
+ ],
15872
+ "responses": {
15873
+ "200": {
15874
+ "description": "StarReel envelope",
15875
+ "content": {
15876
+ "application/json": {
15877
+ "schema": {
15878
+ "type": "object",
15879
+ "properties": {
15880
+ "code": {
15881
+ "type": "integer"
15882
+ },
15883
+ "message": {
15884
+ "type": "string"
15885
+ },
15886
+ "data": {
15887
+ "description": "Operation result payload"
15888
+ }
15889
+ }
15890
+ }
15891
+ }
15892
+ }
15893
+ },
15894
+ "402": {
15895
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
15896
+ }
15897
+ }
15898
+ },
15899
+ "put": {
15900
+ "operationId": "set_shot_keyframes",
15901
+ "summary": "★**内测**·写**某一镜**的中间关键帧(整体覆盖;[] = 清空)",
15902
+ "description": "★**内测**·写**某一镜**的中间关键帧(整体覆盖;[] = 清空)。免费(纯文本写库)。\n每项 { t_sec, prompt }:t_sec 是镜内第几秒,必须落在 [2, 时长-1] 之内(开头会定格在首帧、结尾留给尾帧),相邻至少间隔 2 秒,每镜最多 3 张;prompt 写那一刻**看得见的**画面(人在哪、什么姿态、物件什么状态、景别机位与首帧一致)。\n★不收「正要 / 刚开始 / about to」这类起点措辞(单帧画不出「正在开始」),也不收「没有 X / no X」否定句(会把 X 画出来);违规会 400 并说明哪一张哪里不对,照着改写再提交。\n★先 get_storyboards 读现值再改。回 400「本剧未开启」= 本剧不在内测名单。",
15903
+ "tags": [
15904
+ "storyboards"
15905
+ ],
15906
+ "parameters": [
15907
+ {
15908
+ "name": "storyboard_id",
15909
+ "in": "path",
15910
+ "required": true,
15911
+ "schema": {
15912
+ "type": "integer",
15913
+ "exclusiveMinimum": 0
15914
+ }
15915
+ }
15916
+ ],
15917
+ "requestBody": {
15918
+ "required": true,
15919
+ "content": {
15920
+ "application/json": {
15921
+ "schema": {
15922
+ "type": "object",
15923
+ "properties": {
15924
+ "keyframes": {
15925
+ "type": "array",
15926
+ "items": {
15927
+ "type": "object",
15928
+ "properties": {
15929
+ "t_sec": {
15930
+ "type": "number",
15931
+ "description": "镜内秒数"
15932
+ },
15933
+ "prompt": {
15934
+ "type": "string",
15935
+ "minLength": 2,
15936
+ "maxLength": 600,
15937
+ "description": "这一刻看得见的画面"
15938
+ }
15939
+ },
15940
+ "required": [
15941
+ "t_sec",
15942
+ "prompt"
15943
+ ],
15944
+ "additionalProperties": false
15945
+ },
15946
+ "maxItems": 3
15947
+ }
15948
+ },
15949
+ "required": [
15950
+ "keyframes"
15951
+ ]
15952
+ }
15953
+ }
15954
+ }
15955
+ },
15956
+ "responses": {
15957
+ "200": {
15958
+ "description": "StarReel envelope",
15959
+ "content": {
15960
+ "application/json": {
15961
+ "schema": {
15962
+ "type": "object",
15963
+ "properties": {
15964
+ "code": {
15965
+ "type": "integer"
15966
+ },
15967
+ "message": {
15968
+ "type": "string"
15969
+ },
15970
+ "data": {
15971
+ "description": "Operation result payload"
15972
+ }
15973
+ }
15974
+ }
15975
+ }
15976
+ }
15977
+ },
15978
+ "402": {
15979
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
15980
+ }
15981
+ }
15982
+ }
15983
+ },
15791
15984
  "/storyboards/{storyboard_id}/lipsync": {
15792
15985
  "post": {
15793
15986
  "operationId": "lipsync_shot",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starreel/mcp",
3
- "version": "0.1.247",
3
+ "version": "0.1.248",
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.247",
5
+ "version": "0.1.248",
6
6
  "websiteUrl": "https://starreel.ai",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "@starreel/mcp",
11
- "version": "0.1.247",
11
+ "version": "0.1.248",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  },