@starreel/mcp 0.1.39 → 0.1.41
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 +60 -0
- package/dist/tools/produce.js +41 -5
- package/package.json +1 -1
- package/server.json +2 -2
package/SKILL.md
CHANGED
|
@@ -180,6 +180,66 @@ content that will be rejected.
|
|
|
180
180
|
key in an environment variable or secrets manager, never in code or logs.
|
|
181
181
|
The 15-min token auto-re-exchanges; a leaked key is revoked in Settings.
|
|
182
182
|
|
|
183
|
+
## Script fidelity — auto two-pass rewriting
|
|
184
|
+
|
|
185
|
+
`rewrite_script` routes automatically based on what the user put into
|
|
186
|
+
`set_script`:
|
|
187
|
+
|
|
188
|
+
- **Source is already a screenplay** (scene headers / dialogue-line structure):
|
|
189
|
+
the platform runs a two-pass fidelity rewrite. The user's dialogue is
|
|
190
|
+
byte-locked by machine gates (a missing line is rejected and redone
|
|
191
|
+
internally — you never need to babysit this), and the AI adds **no** hooks,
|
|
192
|
+
twists, or emotional beats of its own. Dramaturgy gaps it detects come back
|
|
193
|
+
in `get_script` → `dramaturgy_suggestions`; relay them to the user and let
|
|
194
|
+
the user decide. Ignoring them blocks nothing.
|
|
195
|
+
- **Source is a novel or outline**: the creative single-pass rewrite runs as
|
|
196
|
+
before (the AI builds hooks and emotional beats).
|
|
197
|
+
|
|
198
|
+
Overrides via `update_project_settings`: `rewrite_pipeline`
|
|
199
|
+
(`auto` default / `two_pass` force fidelity / `single_forced` force creative)
|
|
200
|
+
and `fidelity_enforce: 1` (hard-reject any rewrite that drops a dialogue line,
|
|
201
|
+
a cast member, or an action beat).
|
|
202
|
+
|
|
203
|
+
When the user complains "the AI rewrote my script off course": ① confirm the
|
|
204
|
+
full original went into `set_script`; ② set `rewrite_pipeline: "two_pass"` and
|
|
205
|
+
rerun `rewrite_script`; ③ once the user approves a character's look, lock it
|
|
206
|
+
with `update_character` `profile_locked: 1` so later extractions can't
|
|
207
|
+
overwrite appearance (appearance anchors the portrait and face lock — an
|
|
208
|
+
overwrite means face drift across the whole drama).
|
|
209
|
+
|
|
210
|
+
## After the first rewrite — 点改优先 (point-edit, don't re-run)
|
|
211
|
+
|
|
212
|
+
**`rewrite_script` is "start over from the source", not "give me another
|
|
213
|
+
revision."** Once a draft exists, re-running it overwrites the current draft
|
|
214
|
+
together with every fix already made — and the new version does **not**
|
|
215
|
+
inherit what the previous one got right. Measured across three production
|
|
216
|
+
runs of the same episode: a long VO block correctly split in v2 was merged
|
|
217
|
+
back in v3, and era-correct wardrobe in v2 drifted a decade in v3. The
|
|
218
|
+
kickoff response says so explicitly via `overwrites_existing_script: true`.
|
|
219
|
+
|
|
220
|
+
So after the first successful rewrite, **every** change goes through
|
|
221
|
+
`edit_rewritten_script` — free, seconds, deterministic:
|
|
222
|
+
|
|
223
|
+
1. `get_script` → take the **full** `rewritten_script`.
|
|
224
|
+
2. Change **only the scenes that need changing** — split an over-long scene,
|
|
225
|
+
fix a line, drop a `motif` that has no matching visual, add a missing
|
|
226
|
+
`[SFX]`, move a hand-held object out of the wardrobe segment into the
|
|
227
|
+
scene's `[道具]` line. Every other scene is copied back **verbatim**,
|
|
228
|
+
punctuation included.
|
|
229
|
+
3. Submit the **whole** script to `edit_rewritten_script` (it is a full-text
|
|
230
|
+
write, so untouched parts must come back unchanged — never send a fragment,
|
|
231
|
+
and never let the model "tidy up" scenes it wasn't asked to touch).
|
|
232
|
+
|
|
233
|
+
Re-run `rewrite_script` only when the user genuinely wants a different take on
|
|
234
|
+
the whole episode. If a re-run (or an edit) went wrong,
|
|
235
|
+
`get_script` with `include_previous: true` returns the previous draft snapshot.
|
|
236
|
+
|
|
237
|
+
Point-editable by definition — anything the platform can already name: scene
|
|
238
|
+
length, cross-shot dialogue splits, wrong time-of-day or era, orphan motifs,
|
|
239
|
+
props in the wardrobe segment, missing `[SFX]`/`[BGM]`, group-shot head counts.
|
|
240
|
+
Storyboard-level issues do **not** need a script edit at all: use
|
|
241
|
+
`update_shot` / `replace_shot_dialogue`.
|
|
242
|
+
|
|
183
243
|
## Failure playbook
|
|
184
244
|
|
|
185
245
|
Failures surface as a human-readable `message` (MCP throws `Error(message)`;
|
package/dist/tools/produce.js
CHANGED
|
@@ -34,6 +34,10 @@ const WORKFLOW_HINT = '★三档执行策略(别把三档混着问客户):' +
|
|
|
34
34
|
'把自己写好的剧本直接贴进 edit_rewritten_script 绕过改写会被 400 拒(没有改写稿就没有可改的对象),extract_assets 同样要求基于改写稿。' +
|
|
35
35
|
'改写后的所有修改按 AI 产物的结构化格式做:改稿 edit_rewritten_script(润色/纠正)、人物档案 update_character、分镜 update_shot/replace_shot_dialogue——' +
|
|
36
36
|
'别回头整篇替换剧本或在设定字段里另写一套,两套真相源打架是一致性事故的头号根源。' +
|
|
37
|
+
'★★**改写成功一次后就别再重跑 rewrite_script**:它是从原稿整篇重来,当前稿的所有修正全丢,' +
|
|
38
|
+
'且新版不保证保留旧版已改好的地方(三版实测会来回摆)。要修就 edit_rewritten_script 点改' +
|
|
39
|
+
'(get_script 取全文 → 只改那几场、其余逐字照抄 → 提交整篇),免费秒级、结果确定;' +
|
|
40
|
+
'误重跑用 get_script(include_previous=1) 回捞上一版。' +
|
|
37
41
|
'generate_portraits_and_sheets(定妆图+设定图·分镜后建只给出场角色出图更省)→assign_voices(分配音色)→frames→videos→generate_tts→compose;' +
|
|
38
42
|
'★别先建角色形象/道具设定图/动作模板再分镜——分镜是纯文本步、不依赖任何图;资产在分镜后建更省更准(动作模板本就必须分镜后)。收费步照现有 quote 报价确认流程。' +
|
|
39
43
|
'广告另需 add_product+generate_product_sheet;MV 走 set_mv_lyrics→generate_mv_story→generate_mv_script。' +
|
|
@@ -56,6 +60,12 @@ const WORKFLOW_HINT = '★三档执行策略(别把三档混着问客户):' +
|
|
|
56
60
|
'★两条锁定纪律:①**画幅比例**在 create_drama 即定、drama 级锁定,之后所有出图/出视频/成片都用它、**别中途改**' +
|
|
57
61
|
'(改了已生成内容画幅会不一致、漂移);不设默认 9:16。②**拆镜每镜 5-7 秒是对 AI 出视频优化的正常时长**,' +
|
|
58
62
|
'别因「镜偏长」误判就重拆——generate_storyboards 会**替换整集所有分镜**、已出图白费,已有分镜后端会拦、需 confirm_replace。' +
|
|
63
|
+
'★改写保真(默认 auto 智能路由):set_script 的原稿**本身已是剧本形态**(场景头/对白行结构)时,rewrite_script 自动走两步保真——' +
|
|
64
|
+
'客户台词逐句由机器闸锁定(丢一句即内部拒收重做)、AI 绝不加戏;剧作缺口(钩子/情感锚点)不自动补,写进 get_script 返回的 dramaturgy_suggestions 由客户决定采纳。' +
|
|
65
|
+
'原稿是小说/大纲则自动走创作型改写(AI 铺钩子造情感点),两种客户各得其所、无需手动切换。' +
|
|
66
|
+
'要覆盖默认用 update_project_settings 的 rewrite_pipeline(auto/two_pass/single_forced)与 fidelity_enforce(1=保真硬闸)。' +
|
|
67
|
+
'客户说「AI 把我的剧本改偏了」时的处置:①确认完整原稿已进 set_script;②rewrite_pipeline 设 two_pass 强制保真后重跑 rewrite_script;' +
|
|
68
|
+
'③客户确认角色外观后用 update_character 的 profile_locked=1 锁定档案,防后续提取覆盖外貌导致定妆图换脸。' +
|
|
59
69
|
'用 get_pipeline_status 查进度(按项目类型返回专属步骤)。';
|
|
60
70
|
const ETHNICITY_CODES = [
|
|
61
71
|
'east_asian', 'southeast_asian', 'south_asian', 'central_asian',
|
|
@@ -142,6 +152,8 @@ export function registerProduceTools(server, client) {
|
|
|
142
152
|
project_type: z.enum(['drama', 'ad', 'mv', 'brand_film']).optional()
|
|
143
153
|
.describe('项目类型(默认 drama)。ad=广告(改写走 ad_script_rewriter);mv=音乐(走歌词→故事→剧本子流程);brand_film=品牌微电影(默认16:9)'),
|
|
144
154
|
rewrite_mode: z.enum(['standard', 'director']).optional().describe('AI改写深度:standard 或 director(导演级)'),
|
|
155
|
+
rewrite_pipeline: z.enum(['auto', 'two_pass', 'single_forced']).optional().describe('改写流水线:auto(默认,按原稿形态智能路由——剧本形态走两步保真,小说/大纲走创作改写)/two_pass(强制两步保真,客户自带成熟剧本必选)/single_forced(强制单步创作)'),
|
|
156
|
+
fidelity_enforce: z.number().int().min(0).max(1).optional().describe('1=改写保真硬闸:丢台词/丢人物/丢动作节拍直接拒收重做(客户要求逐句保留时开)'),
|
|
145
157
|
director_style: z.string().optional().describe('导演风格包 key'),
|
|
146
158
|
...PROJECT_SETTINGS_FIELDS,
|
|
147
159
|
}, async (args) => {
|
|
@@ -161,13 +173,33 @@ export function registerProduceTools(server, client) {
|
|
|
161
173
|
}, async ({ episode_id, script }) => jsonResult(await client.producePut(`/episodes/${episode_id}/script`, { content: script })));
|
|
162
174
|
// ---------- AI 改写 / 审阅 / 改稿 ----------
|
|
163
175
|
server.tool('rewrite_script', 'AI 改写:把原始剧本改写成可拍稿(读 content → 写 script_content)。按项目类型自动选改写 agent' +
|
|
176
|
+
'★保真自动路由:原稿已是剧本形态时自动走两步保真(台词逐句机器锁定、AI 不加戏,剧作缺口进 dramaturgy_suggestions 由客户决定);原稿是小说/大纲则走创作型改写。' +
|
|
164
177
|
'(广告走 ad 改写;MV 不走标准改写会被拦)。后台异步(分钟级),文本步按 token 后付、不欠费,无需报价。' +
|
|
165
178
|
'完成后用 get_script 审阅、edit_rewritten_script 改稿。' +
|
|
166
179
|
'★典型耗时 2~4 分钟(生产实测 ≈169 秒)。**60 秒内查不到结果是正常的,不是失败**——' +
|
|
167
|
-
'用 get_run_status 判断还在不在跑,别急着重发。' +
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'
|
|
180
|
+
'用 get_run_status 判断还在不在跑,别急着重发。' +
|
|
181
|
+
'★★**本工具是"从原稿整篇重来",不是"再改一版"**:已有可拍稿时重跑会把当前稿连同已做的所有修正' +
|
|
182
|
+
'一起覆盖,而且新一版**不保证保留旧版已经改好的地方**(生产三版实测:上一版拆好的长旁白段下一版又' +
|
|
183
|
+
'合回去、上一版正确的年代服装下一版漂走)。响应里的 overwrites_existing_script=true 就是这个意思。' +
|
|
184
|
+
'所以**首次改写成功之后,后续所有修改一律用 edit_rewritten_script 点改**——免费、秒级、只动指定的' +
|
|
185
|
+
'那几场,其余逐字不变,结果确定不抽卡;只有"要一个完全不同的版本"才重跑本工具。' +
|
|
186
|
+
'误重跑后用 get_script(include_previous=1) 取回上一版。' + WORKFLOW_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/rewrite`)));
|
|
187
|
+
server.tool('get_script', '读某一集的原始内容 + AI 改写后的可拍稿 + 改写状态 + dramaturgy_suggestions(两步保真模式下 AI 识别到但未自动补的剧作缺口——钩子/情感锚点;把它转述给客户决定采纳与否,忽略不影响产线)。免费。' +
|
|
188
|
+
'★改稿工作流:先用本工具取回 rewritten_script 全文 → 只改客户要改的那几场 → 用 edit_rewritten_script 提交(不要重跑改写)。' +
|
|
189
|
+
'previous_script_available=true 表示有上一版快照;传 include_previous=1 可取回上一版全文(误重跑/改坏了的回捞路径,默认不带以免响应翻倍)。', {
|
|
190
|
+
episode_id: z.number().int().positive(),
|
|
191
|
+
include_previous: z.boolean().optional().describe('取回上一版可拍稿全文(previous_script 快照)。默认 false;改坏了或误重跑时用'),
|
|
192
|
+
}, async ({ episode_id, include_previous }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/script${include_previous ? '?include_previous=1' : ''}`)));
|
|
193
|
+
server.tool('edit_rewritten_script', '★改稿的**首选通道**:改 AI 改写后的可拍稿(写 script_content)。免费、秒级、结果确定不抽卡——' +
|
|
194
|
+
'**改写成功一次之后,所有修改都走这里,不要重跑 rewrite_script**(那是从原稿整篇重来,当前稿的修正全丢、' +
|
|
195
|
+
'已改好的地方会退回去)。' +
|
|
196
|
+
'★怎么点改(三步,别跳):① get_script 取回 rewritten_script **全文**;② **只改要改的那几场**——' +
|
|
197
|
+
'目标场次内改动词句/拆场/删挂错的 motif/补 [SFX]/移器物到 [道具] 行,其余场次连标点都逐字照抄;' +
|
|
198
|
+
'③ 把改完的**整篇**提交本工具(本工具是全文覆盖,所以未改动部分必须原样带回,不能只发片段、也不要让模型' +
|
|
199
|
+
'"顺手重写"没让它改的场)。典型可点改的问题:场次太长要拆、台词跨镜断句、时段/年代写错、' +
|
|
200
|
+
'motif 挂在没有该元素的场、[角色档案] 服装段混进手持器物、缺 [SFX]/[BGM] 标注。' +
|
|
201
|
+
'只用于修改 AI 改写产出的稿;本集还没跑过 rewrite_script 时会被 400 拒——这不是绕过改写的通道,' +
|
|
202
|
+
'别把自己写好的剧本直接贴进来。改坏了可用 get_script(include_previous=1) 取回上一版。免费。', {
|
|
171
203
|
episode_id: z.number().int().positive(),
|
|
172
204
|
script: z.string().min(1).describe('改好的可拍剧本(覆盖 AI 改写稿)'),
|
|
173
205
|
}, async ({ episode_id, script }) => jsonResult(await client.producePut(`/episodes/${episode_id}/rewritten-script`, { script_content: script })));
|
|
@@ -332,6 +364,8 @@ export function registerProduceTools(server, client) {
|
|
|
332
364
|
ethnicity: z.enum(ETHNICITY_CODES).optional().describe('角色族裔锁'),
|
|
333
365
|
ethnicity_note: z.string().optional(),
|
|
334
366
|
rewrite_mode: z.enum(['standard', 'director']).optional(),
|
|
367
|
+
rewrite_pipeline: z.enum(['auto', 'two_pass', 'single_forced']).optional().describe('改写流水线:auto 默认智能路由/two_pass 强制两步保真/single_forced 强制单步创作'),
|
|
368
|
+
fidelity_enforce: z.number().int().min(0).max(1).optional().describe('1=改写保真硬闸(丢台词即拒)'),
|
|
335
369
|
director_style: z.string().optional(),
|
|
336
370
|
theme_statement: z.string().optional().describe('一句话主题'),
|
|
337
371
|
subtitle_preset: z.string().optional(),
|
|
@@ -520,7 +554,8 @@ export function registerProduceTools(server, client) {
|
|
|
520
554
|
server.tool('generate_mv_script', 'MV 项目:据歌词+故事写首集可拍剧本(写 scriptContent)。之后走标准 extract_assets → 分镜 → …。按用量后付。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.producePost(`/dramas/${drama_id}/mv/script`)));
|
|
521
555
|
server.tool('get_mv', 'MV 项目:读歌词/故事/剧本当前状态。免费。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/mv`)));
|
|
522
556
|
// ========== P1 · 资产精修(提取后改设定再出图)==========
|
|
523
|
-
server.tool('update_character', '改角色设定(
|
|
557
|
+
server.tool('update_character', '改角色设定(名字/外貌/年龄段/族裔/性别/性格/戏份/档案锁定)。改后需重出定妆图/相关图。免费。' +
|
|
558
|
+
'★profile_locked=1:客户确认外观后锁定档案,后续 AI 提取不再覆盖外貌/性格/描述——外貌锚着定妆图与人脸锁定,被覆盖=全片换脸;确认满意即锁,要再改先传 0 解锁。', {
|
|
524
559
|
character_id: z.number().int().positive(),
|
|
525
560
|
name: z.string().optional(),
|
|
526
561
|
description: z.string().optional(),
|
|
@@ -530,6 +565,7 @@ export function registerProduceTools(server, client) {
|
|
|
530
565
|
gender: z.string().optional(),
|
|
531
566
|
personality: z.string().optional(),
|
|
532
567
|
role: z.string().optional(),
|
|
568
|
+
profile_locked: z.number().int().min(0).max(1).optional().describe('1=锁定档案(AI 提取不再覆盖外貌/性格/描述,防定妆图换脸);0=解锁'),
|
|
533
569
|
}, async ({ character_id, ...fields }) => jsonResult(await client.producePut(`/characters/${character_id}`, fields)));
|
|
534
570
|
server.tool('delete_character', '删除一个角色(提取误建/合并时用)。免费。', { character_id: z.number().int().positive() }, async ({ character_id }) => jsonResult(await client.produceDelete(`/characters/${character_id}`)));
|
|
535
571
|
server.tool('update_scene', '改场景设定(名字/描述/地点/时段/氛围)。免费。', {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starreel/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.41",
|
|
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.41",
|
|
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.41",
|
|
12
12
|
"transport": { "type": "stdio" },
|
|
13
13
|
"environmentVariables": [
|
|
14
14
|
{
|