@starreel/mcp 0.1.196 → 0.1.201

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.
@@ -281,7 +281,7 @@ export const PIPELINE = [
281
281
  },
282
282
  {
283
283
  step: '10 成片与交付',
284
- tools: ['compose_episode', 'get_final_cut', 'get_export', 'rerender_episode', 'get_deliverables', 'generate_deliverables', 'render_multi_aspect', 'generate_effects', 'generate_transitions', 'generate_episode_poster', 'generate_drama_poster', 'generate_cover', 'translate_subtitles', 'get_pipeline_status'],
284
+ tools: ['compose_episode', 'get_final_cut', 'get_export', 'rerender_episode', 'get_deliverables', 'generate_deliverables', 'render_multi_aspect', 'generate_effects', 'generate_transitions', 'set_drama_logo', 'get_drama_logo', 'generate_episode_poster', 'generate_drama_poster', 'generate_cover', 'translate_subtitles', 'get_pipeline_status'],
285
285
  billing: '免费',
286
286
  note: '终拼免费(ffmpeg+COS);成片前用 `get_pipeline_status` 确认没有缺镜;配乐晚于成片(bgm_stale)重新 compose 即可。',
287
287
  },
@@ -749,16 +749,16 @@ export function buildInstructions() {
749
749
  '★第一步永远是判「客户手上有什么材料」——它决定入口,选错入口的返工都是真扣费(全表与要点:get_capabilities_guide):',
750
750
  entry,
751
751
  '',
752
- '产线顺序(不跳步):create_drama(建剧即设好 setting_brief/画幅/video_engine/image_model/一致性锚,全免费) → set_script → rewrite_script → ★review_script → extract_assets → quote/generate_storyboards → ★review_storyboards → 定妆图+设定图 / 场景图 / 道具图 / 色彩脚本 → ★review_assets → run_precheck → quote/generate_frames(默认只出首帧) → tail_frame_plan(哪几镜要独立尾帧) → quote/generate_frames(last_frame) → chain_frames(dry_run→确认后执行)→get_jobs → ★review_frames → quote/generate_videos → 音频 → ★review_videos → compose_episode → get_final_cut → review_final_cut。用 get_pipeline_status 查进度。',
752
+ '产线顺序(不跳步):create_drama(建剧即设好世界观/画幅/引擎/模型/一致性锚,全免费) → set_script → rewrite_script → ★review_script → extract_assets → quote/generate_storyboards → ★review_storyboards → 定妆图+设定图 / 场景图 / 道具图 / 色彩脚本 → ★review_assets → run_precheck → quote/generate_frames(默认只出首帧) → tail_frame_plan(哪几镜要独立尾帧) → quote/generate_frames(last_frame) → chain_frames(dry_run→确认后执行)→get_jobs → ★review_frames → quote/generate_videos → 音频 → ★review_videos → 成片前自检(recommend_trim_window/audit_seams) → compose_episode → get_final_cut → review_final_cut。用 get_pipeline_status 查进度。',
753
753
  '五道免费硬闸(跳过 → 400):review_script(extract_assets/分镜前)· review_storyboards(出图前,含单镜 generate_shot_frame)· review_assets(出图前,token 作 asset_review_token)· review_frames(出视频前,含单镜 regenerate_shot_video)· review_videos(compose_episode 前);review_token 随下游收费工具传(批量与单镜工具都要),findings 逐条原样告诉客户。',
754
754
  '★每层审查之后你还要亲自质检:按返回的 agent_qc 逐件看素材,submit_qc_report 提交报告;灰度剧没交报告进不了下一步。',
755
755
  '计费纪律:预付费不透支;大额步 quote_* → 把 estimated_points 原样告诉客户 → 客户同意后 generate_*(quote_id),绝不擅自确认;' +
756
756
  '出图类报价给 estimated_points(上界,按它准备余额)与 typical_points(通常花费),两个都说;' +
757
757
  '文本步按 token 后付;402 就停下让客户充值,别重试。',
758
- '长任务异步:generate_* 立即返回,用 get_pipeline_status / get_storyboards / get_run_status 轮询;图片 pending = 还在生成,别重复调(重复扣费)。',
758
+ '长任务异步:generate_* 立即返回,用 get_pipeline_status / get_storyboards / get_run_status 轮询;图片 pending=还在生成,别重复调(重复扣费)。',
759
759
  '改写成功后只 edit_rewritten_script 点改,别重跑 rewrite_script;角色外观唯一真相源是人物档案(update_character),别写进 visual_lock/art_bible。',
760
760
  '选图片模型/视频引擎、客户问「哪个模型好 / 怎么更省」→ get_capabilities_guide(section=model_guide):各模型实测优劣、价格、决策步骤与推荐组合;建剧时就主动讲给客户定。',
761
761
  '做动作 / 打斗 / 技能展示片 → get_capabilities_guide(section=action_film):分镜表直通道、首帧停在起势、并组与节奏剪裁。',
762
- '不确定该用哪个工具、客户问「你们能做什么」→ 先调 get_capabilities_guide(免费、本地、不联网)。',
762
+ '不确定该用哪个工具、客户问「你们能做什么」→ get_capabilities_guide(免费、本地)。',
763
763
  ].join('\n');
764
764
  }
@@ -105,6 +105,19 @@ const ASSET_QC_HINT = '\n★【完成后质检·免费】出完等图落库(轮
105
105
  const VIDEO_QC_HINT = '\n★【完成后质检·免费】出完等它落库(get_storyboards 看 video_status / get_pipeline_status),再调 review_videos 审视频与配音层' +
106
106
  '(缺视频 / 旧帧出的视频 / 片尾硬切 / 意外人声 / 配音缺失 / 音色未分配 / 原声声线过期),修完复审;' +
107
107
  '再按 agent_qc 亲自逐镜看视频、听配音(动作到位、不变脸、台词念全、嗓音对),submit_qc_report 提交;compose_episode 要带它的 review_token。';
108
+ /**
109
+ * 成片前自检:review_videos 之后、compose_episode 之前(2026-10-19 外部 agent 复盘:五个工具全在却一个没调,
110
+ * 靠反复导出整片、手工试转场定位问题)。只是提示,不加闸;trim_shot / audit_seams 不进视频层指纹,做完不用复审。
111
+ */
112
+ export const PRE_COMPOSE_CHECK_HINT = '★★【成片前自检·review_videos 通过后、compose_episode 之前】别靠反复导出整片、手工试转场来找问题——逐镜与接缝的问题有专门工具,拼之前按序过一遍:' +
113
+ '①这一集换过定妆图 / 设定图 / 场景图 / 镜头帧 → 先 get_stale_portrait_frames(episode_id,免费)看哪些镜的在用帧还基于旧资产,' +
114
+ '拿不准该用哪一版的镜再 get_asset_versions(storyboard_id,免费)逐镜看版本与依赖(unknown 是证据不足、不是已过期;重出要付费,清单讲给客户由客户定);' +
115
+ '②scan_intra_shot_cuts(episode_id,免费)查厂商在单镜内自行硬切的镜;' +
116
+ '③逐镜 recommend_trim_window(storyboard_id,免费)看冻结尾段与有效动作区间(组内镜返回 applicable=false,跳过),有推荐就 trim_shot 应用(免费);' +
117
+ '④audit_seams(episode_id)查相邻镜接缝的剪辑连续性:默认 dry_run 只列待审范围(免费),真执行按实际文本 token 计费,' +
118
+ '讲给客户、客户明确接受后才带 dry_run:false + confirm_usage_billing:true,结果看 get_storyboards 的 seam_review;' +
119
+ '⑤再 compose_episode。拼完成片发现跳切 / 拖尾 / 接不上,回到这几个工具按镜定位后只修那几镜,别整片反复导出试错。' +
120
+ '这些都是提示性检查,不过闸;裁剪与接缝审核不让 review_videos 的 token 失效。';
108
121
  /** 三个被闸的收费工具共用的参数(zod 形状,展开进各自 schema)。 */
109
122
  const REVIEW_ARGS = {
110
123
  review_token: z.string().optional().describe('★来自本层 review_* 工具的凭据(受闸项目必填;缺了会 400 并告诉你该调哪个审查工具)'),
@@ -216,6 +229,7 @@ export const WORKFLOW_HINT = AUTOPILOT_HINT +
216
229
  '★★【④⑤两道新硬闸 + agent 亲自质检】④资产层:定妆图/设定图/场景图/道具图出完 → review_assets' +
217
230
  '(在 generate_frames / generate_shot_frame 之前,它的 token 作为 asset_review_token、与分镜层 review_token 一起传);' +
218
231
  '⑤视频与配音层:视频/配音/配乐出完 → review_videos(在 compose_episode 之前);成片出来后跑 review_final_cut。' +
232
+ PRE_COMPOSE_CHECK_HINT +
219
233
  '★每一层审查之后你还要**亲自质检**:按返回的 agent_qc 逐件看素材(图下载看、视频抽帧看、文本通读),逐条答清单,' +
220
234
  'submit_qc_report 提交;灰度剧没交报告那张 review_token 进不了下一步,报告有问题与 error 同样默认拦。平台判有没有,你判像不像、对不对。' +
221
235
  '★★【单镜路径同样受审查闸】:generate_shot_frame 同样要带分镜层 review_token,regenerate_shot_video 同样要带镜头图片层 review_token——' +
@@ -828,6 +842,7 @@ export function registerProduceTools(server, client) {
828
842
  '首帧换过而视频还是旧帧出的(video_stale);疑似片尾硬切、无台词镜意外人声(warning);' +
829
843
  '配音剧:台词镜缺配音、会开口的角色没音色、缺旁白角色;原声剧:出片时没挂上当前声线的镜、没锁声线的角色;缺配乐(warning)。' +
830
844
  '★出完视频、配音(generate_tts)、配乐后都调一次;compose_episode 之前必须审过,带返回的 review_token。' +
845
+ '\n' + PRE_COMPOSE_CHECK_HINT + '返回体的 pre_compose_checks 是同一份清单(结构化,逐项 tool/scope/when/cost)。\n' +
831
846
  '更细的检查(要解码画面/音轨)另有 scan_intra_shot_cuts / scan_dialogue_coverage / audit_silent_shot_audio;拼完成片再跑 review_final_cut。' +
832
847
  '★返回带 post_production_advisory = 剧本标注「后期」的叙事必需特效还没处理(平台不会合成):原样告诉客户,用 get_post_production_checklist 看清单。' + AGENT_QC_HINT, { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.producePost(`/episodes/${episode_id}/review/videos`)));
833
848
  server.tool('submit_qc_report', '提交你(agent)亲自看素材做的质检报告。免费。先调对应层的 review_*(script / storyboards / assets / frames / videos),' +
@@ -997,6 +1012,7 @@ export function registerProduceTools(server, client) {
997
1012
  '补齐后重试;确要拼部分成片传 force=true(缺视频镜被跳过,成片缺镜,留痕)。' +
998
1013
  '响应里的 advisories(时长偏差/孤儿任务/缺TTS/post_production_pending 后期特效未完成)只提醒不阻断,建议逐条处理后再拼。发起后用 get_final_cut 轮询。' +
999
1014
  REVIEW_GATE_HINT('review_videos', '视频与配音') +
1015
+ '\n' + PRE_COMPOSE_CHECK_HINT +
1000
1016
  '\n★【完成后质检·免费】成片出来后跑 review_final_cut(缺镜/字幕放不下/身份锚/跳轴/错别字,proofread=false 则不扣费),' +
1001
1017
  '结论讲给客户;客户确认后才 confirm_delivery_acceptance' + ALWAYS_ASK('交付验收') + '。force 只越过终拼预检,不越过审查闸。', {
1002
1018
  episode_id: z.number().int().positive(),
@@ -1873,6 +1889,7 @@ export function registerProduceTools(server, client) {
1873
1889
  '两种用法:①不填 orient/placement/font_size = 角色名卡(画面侧边单列竖排人物名,适合群像出场镜);' +
1874
1890
  '②填了其中任意一个 = 通用版式字卡,name 可以是**整句台词或旁白**(按标点自动切列、按最高列拟合字号)。' +
1875
1891
  'placement="auto" 会按背景亮度与粗糙度自动挑位置(躲开人脸/亮部);orient="auto" 在背景太花时自动回退横排。' +
1892
+ '③position="subtitle" = 叙事字卡,与对白字幕同位同样式,可配 start_ms 从镜中段出现(无对白的镜最合适,避免与对白字幕重叠)。改完调 compose_episode 重新终拼生效(rerender_episode 沿用已存时间轴,带不上)。' +
1876
1893
  '★别自己下载视频叠字再上传——那会绕开渲染机字体与印章素材,预览/成片不一致。', {
1877
1894
  storyboard_id: z.number().int().positive(),
1878
1895
  name: z.string().describe('字卡正文(人物名,或版式模式下的任意文案/整句台词);空字符串=清除字卡'),
@@ -1885,12 +1902,18 @@ export function registerProduceTools(server, client) {
1885
1902
  .describe('选位方式。不填=贴 side 那一边的固定位;auto=按背景亮度/粗糙度滑窗选位,躲开人和亮部'),
1886
1903
  font_size: z.number().int().positive().optional()
1887
1904
  .describe('字号上限(默认 72);实际字号按最高列拟合,不会超过它'),
1888
- }, async ({ storyboard_id, name, seal, side, duration_ms, orient, placement, font_size }) => jsonResult(await client.producePut(`/storyboards/${storyboard_id}/name-card`, {
1905
+ start_ms: z.number().int().min(0).max(60000).nullable().optional()
1906
+ .describe('镜内起点毫秒(相对本镜开头),默认 0;字卡显示到 duration_ms 或镜尾'),
1907
+ position: z.enum(['subtitle']).nullable().optional()
1908
+ .describe('subtitle = 叙事字卡:与对白字幕同位同样式(底部居中),name 里用换行写多行(如双语两行);不画印章、不走选位;不传=保留原值,传 null=清除(回到侧边/版式字卡)'),
1909
+ }, async ({ storyboard_id, name, seal, side, duration_ms, orient, placement, font_size, start_ms, position }) => jsonResult(await client.producePut(`/storyboards/${storyboard_id}/name-card`, {
1889
1910
  name, ...(seal !== undefined ? { seal } : {}), ...(side !== undefined ? { side } : {}),
1890
1911
  ...(duration_ms !== undefined ? { duration_ms } : {}),
1891
1912
  ...(orient !== undefined ? { orient } : {}),
1892
1913
  ...(placement !== undefined ? { placement } : {}),
1893
1914
  ...(font_size !== undefined ? { font_size } : {}),
1915
+ ...(start_ms !== undefined ? { start_ms } : {}),
1916
+ ...(position !== undefined ? { position } : {}),
1894
1917
  })));
1895
1918
  server.tool('extract_segment_to_library', '把某一镜(或某集成片)的某个时间区间抽出来,存成可复用的素材,进我的素材库。免费(纯剪切,不走厂商)。' +
1896
1919
  '典型用法:闪回/回忆蒙太奇——画面全用已有镜头,边际成本为 0。' +
@@ -2138,6 +2161,22 @@ export function registerProduceTools(server, client) {
2138
2161
  negative: z.array(z.string()).optional()
2139
2162
  .describe('额外的禁止项(可留空)。写该档基线没覆盖、但本项目必须禁的东西'),
2140
2163
  }, async ({ episode_id, ...rest }) => jsonResult(await client.producePut(`/episodes/${episode_id}/era-contract`, rest)));
2164
+ server.tool('get_drama_logo', '读本剧的成片台标设置(图片地址 / 宽度 / 位置 / 边距 / 不透明度)。免费。null = 没设台标。', { drama_id: z.number().int().positive() }, async ({ drama_id }) => jsonResult(await client.produceGet(`/dramas/${drama_id}/logo`)));
2165
+ server.tool('set_drama_logo', '设置本剧成片的图片台标(角标 logo),终拼时叠在全片字幕之上、整片可见。免费、不重出视频。'
2166
+ + '先 upload_image 上传台标(建议透明底 PNG)拿到 URL 再传 src。尺寸/边距按 720p 高度基准、渲染时按成片高度等比缩放'
2167
+ + '(例:1080×1920 竖屏要宽约 260px → width≈98)。改完 compose_episode / rerender_episode 生效。传 logo:null 清除台标。', {
2168
+ drama_id: z.number().int().positive(),
2169
+ src: z.string().url().optional().describe('台标图片 URL(http/https,upload_image 返回的地址)'),
2170
+ width: z.number().int().min(8).max(400).optional().describe('宽度 px(720p 基准),默认 90;高按原图比例'),
2171
+ opacity: z.number().min(0).max(1).optional().describe('不透明度 0–1,默认 0.85'),
2172
+ gravity: z.enum(['NorthEast', 'NorthWest', 'SouthEast', 'SouthWest']).optional().describe('角落:NorthEast 右上(默认)/ NorthWest 左上 / SouthEast 右下 / SouthWest 左下'),
2173
+ margin_x: z.number().int().min(0).max(200).optional().describe('距左右边 px(720p 基准),默认 14'),
2174
+ margin_y: z.number().int().min(0).max(200).optional().describe('距上下边 px(720p 基准),默认 14'),
2175
+ logo: z.null().optional().describe('传 null 清除台标(此时别传 src)'),
2176
+ }, async ({ drama_id, ...fields }) => {
2177
+ const payload = Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== undefined));
2178
+ return jsonResult(await client.producePut(`/dramas/${drama_id}/logo`, payload));
2179
+ });
2141
2180
  server.tool('get_era_contract', '读本集的时代契约现值 + 各场的场级覆写清单 + 五个可选档位的用途说明。免费。'
2142
2181
  + '改之前先读一次:能看清「集级设的是哪档、哪几场被单独覆写过」,避免整集统一的时代被逐场填乱。'
2143
2182
  + '★era_contract 为 null 就是**没设**——古装/仙侠项目看到 null 应当先 set_era_contract 再出图。', { episode_id: z.number().int().positive() }, async ({ episode_id }) => jsonResult(await client.produceGet(`/episodes/${episode_id}/era-contract`)));