@starreel/mcp 0.1.221 → 0.1.222

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
@@ -104,6 +104,7 @@ announces a condensed version as MCP `instructions` at connect time.
104
104
  | Lyrics only, no song (MV) | `create_drama` (`project_type: "mv"`) → `set_mv_lyrics` → `suggest_mv_song_styles` → `quote_mv_song` → `generate_mv_song` → `get_mv_song` → `select_mv_song` → `generate_mv_story` → `generate_mv_script` | Confirming lyric rights on the user's behalf (`lyrics_rights_confirmed` must come from the user); picking a candidate by QC text alone without letting the user listen |
105
105
  | A product / brand | `create_drama` (`project_type: "ad"` or `"brand_film"`) → `add_product` → `generate_product_sheet` | writing brand copy as dialogue (it gets spoken) |
106
106
  | Generated shots / a cut that needs changes | `scan_dialogue_coverage` / `scan_intra_shot_cuts` first, then `get_shot_prompts` · `update_shot` · `replace_shot_dialogue` · `repair_episode_dialogue` · `split_shot` · `trim_shot` · `regenerate_shot_video` · `edit_video_shot` → `rerender_episode`. To put **specific shots on a different video engine** in a whole-episode run, pass `shot_engines` (`{storyboard_id: engine}`) to `quote_videos` (a scene group that contains a picked shot is **split into per-shot generation** — listed in `shot_engines_ungrouped`; its other shots stay on the drama engine but lose the group's one-take continuity, so don't break a good group for one shot; a shot that already has a video is not re-run by the episode run, so picking an engine for it is rejected). Re-quoting after a partial run prices only the shots that will actually be dispatched (`shots_total`; already-finished ones are counted in `shots_already_done`, except that a scene group with any unfinished shot is re-run whole). To make a shot **always** use a different engine (single, batch and regen alike), set `video_engine` with `update_shot` (stored on the shot, shown in the web workbench; such a shot is never put in a scene group; explicit per-call parameters still win). To re-run **one scene group** (one request, keeps in-group continuity) — optionally on a different engine for that run — use `quote_regenerate_scene_group` (`shot_numbers` = exactly one group from `get_scene_group_plan`, optional `video_engine`; the whole group must fit that engine's single-clip limit) → `regenerate_scene_group`. To retry **one shot on a different video engine**, pass `model` to `quote_regenerate_shot_video` (that shot, that regeneration only — the drama's `video_engine` is untouched; the quote pins the engine, so changing it means re-quoting) | re-composing to fix what a clip *says*; switching the whole drama's `video_engine` just to fix one shot |
107
+ | One person at several ages built as separate characters, and their portraits look like different people (or a mole switches sides) | pick the character whose portrait is right as the reference: `quote_derive_character_portrait` (`reference_character_id`, `age_stage`) → customer agrees → `derive_character_portrait` → `get_derived_portrait_candidates` (inspect each) → `adopt_derived_portrait` → `generate_character_sheet`. Check the target's `appearance` describes clothing for that age first — cross-character derivation dresses the target from its own profile, not the reference image | re-running batch portraits hoping the faces line up; editing the reference image elsewhere and uploading it |
107
108
  | Wants old portraits / sheets / a shot's old tail frame "deleted" | `set_character_portrait` (old assets listed in `old_assets`) · `clear_shot_frame` (old tail frame) → `regenerate_shot_video`; `list_unlinked_assets` lists the drama's unlinked old assets (a history list, not proof of ownership). Both only **unlink** — files are not deleted (`physically_deleted` is always empty; `in_history: false` means the platform kept no record, so save that URL if it matters). Tell the customer exactly that | telling the customer the old image was deleted; writing `last_frame_image: null` through the internal API |
108
109
  | Customer explicitly accepted a shot's video, then its frames / scene / character changed (the platform now flags that video stale) | `lock_shot_video` (only after the customer confirms; locks the **current** video plus the inputs it was made from — frames, prompt, reference list). While locked: `review_videos` stops reporting `video_stale` for it (a `video_locked_frames_changed` warning instead), `get_asset_versions` shows `acceptance_locked`, native-voice `stale_shots` skip it, and every call that would replace it (`regenerate_shot_video`, `edit_video_shot`, repaint / reskin, footage upload / clear, a whole-episode `generate_videos` that would re-run its scene group) is refused with **409 VIDEO_LOCKED**. To replace it later, get the customer's OK and `unlock_shot_video` first. If the video is swapped by another path the lock lapses on its own (`video_lock.broken`) | regenerating an accepted shot just because it shows as stale; locking on your own judgement or because generation finished |
109
110
  | Wants an old image **permanently** deleted from storage (not just unlinked) | `preview_delete_asset` → show the customer exactly what it says (blocking references, history that will break, copies) → only after an explicit "confirm delete" → `delete_asset` with the `confirm_token`. Irreversible; only the drama owner; only files with trusted provenance (generated for this drama, or uploaded through the platform with a grant record) | deleting without showing the preview; retrying automatically; treating `list_unlinked_assets` as proof the file is unused |
@@ -100,6 +100,10 @@
100
100
  "generate_scene_images": "After confirmation, batch generate **empty scene plates** (one character-free background image per scene): backend async, only fills scenes that \"do not yet have images\". ★Do this **before generating shot frames**. Skipping will not error or block you, but the cost is real: the platform fallback is \"when frame generation finds the scene has no image → generate one in the background\"; that generated image only benefits **subsequent** shots in the same scene. The triggering shot cannot wait for it, so **the first shot of each scene has no background anchor**—and the first shot is often the tone-setting shot; backgrounds will also drift across subsequent shots. It pairs with character sheets: character sheets anchor people, scene images anchor settings. ★If the output is wrong, do not rerun this tool (it only fills missing scene images and skips all existing ones): `get_scene_prompt` read the text → `update_scene` edit image_prompt → `regenerate_scene_image` regenerate one scene. ★For non-contemporary or surreal genres, set `set_era_contract` first, otherwise plates may be drawn in the wrong era and all downstream shot frames in that scene will follow. ★Check progress via get_pipeline_status generate_scene_images step. ⚠️ Batch quote confirmation flow: first call the corresponding quote_* tool to get estimated_points and quote_id, then call this tool with quote_id (quote confirmation follows execution mode: Professional mode / unconfirmed plan / this step is customer-controlled → explain to the customer and run only after customer approval; do not decide for them. This step in autopilot → do not ask the customer; follow get_production_plan autopilot.default_decisions, and the platform records it in get_autopilot_log). For autopilot steps, the quote must be within the hard budget cap; if blocked by 402 BUDGET_WOULD_EXCEED, stop and ask the customer. ★**Image-generation quotes (character sheets/scene images/frames) provide two numbers**: estimated_points is the **upper bound** (estimated by that model’s maximum reference-image count, ensuring you do not start with too-low a budget and get interrupted by 402 halfway); typical_points in the same response is the **typical cost**. Tell the customer both—only saying the upper bound makes it seem much more expensive (the full-reference upper bound can exceed the typical value by more than 2×), while only saying the typical value may leave insufficient balance. Under fixed-price models they are equal, in which case one number is enough. Video quotes and charges use the same function; this interval does not exist there.\n★【Post-completion QC·free】After generation, wait for images to be saved (poll corresponding get_* status; do not call again while pending), then call review_assets for asset-layer review (missing images / generating / failed / rejected by consistency gate / prop era conflict / color script). Tell the customer the findings verbatim, fix according to action, then re-review; then personally inspect each image according to the returned agent_qc (whether it resembles the profile, whether it is the same person, whether the era is correct; for character sheets, whether all angles are complete and proportions/structure are correct; whether props and scene images make sense in the story—check the referenced used_in_shots shots), submit_qc_report to submit the QC report; when generating shot frames, pass its review_token as asset_review_token to generate_frames / generate_shot_frame.",
101
101
  "upload_image": "Upload a local image to our COS and return image_url (browser/client uploads bytes directly to COS, not through the business server). Used as a reference image for video editing, or to get a URL before registration. Free.",
102
102
  "set_character_portrait": "Use the customer's own image as the character sheet (identity anchor, higher priority than AI-generated; later AI regeneration will not overwrite it by default). ★★Image requirements (platform auto-checks before registration; noncompliance returns 422 and does not register): **only this one character** (no other people/group photo/background passersby); **single image, single angle** (not a collage/nine-grid/multi-view turnaround—the platform generates turnarounds from the character sheet); front or 3/4 view, clear unobstructed face, clean background; **no text anywhere on the image** (watermarks/subtitles/name labels/logo/text on clothing are all forbidden; text will be replicated into every shot). Before uploading, first inspect the customer's image; if noncompliant, ask the customer to replace it first, do not upload directly. If rejected, tell the customer the issue in message verbatim; only if the customer has seen the issue and explicitly insists on using this image should you retransmit with allow_issues:true (auto-check may be wrong). ★Changing the image invalidates existing derived assets (turnarounds/multi-angle avatars/hair·body references) and rebuilds the face lock, but **the turnaround is not automatically regenerated**—after changing, you must run generate_character_sheet(character_id) to regenerate the turnaround from the new character sheet (next_step in the response will prompt this), otherwise the character has only the character sheet as an anchor. ★After changing the image, the response contains stale_frames=[{storyboard_id,storyboard_number,frames}]—the first frames of these shots were generated from the old character sheet and are contaminated. To make the new character sheet take effect: for each stale_frame, use quote_shot_frame+generate_shot_frame to regenerate that shot (the platform will automatically use the new character sheet/turnaround/face lock as anchors to preserve full-film consistency). No need to specify model/first/last frames shot by shot yourself. ★Never self-make first/last frames and then upload_shot_frame—external images lack character identity anchors/style anchors, so people·costumes·style will drift; that is the root cause of unusable films (not \"preventing unusable films\"). ★Changing the image only **unlinks references**; files for the old character sheet/turnaround are not deleted. old_assets in the response lists unlinked old assets item by item: unlinked=[{kind,url,in_history}] (in_history=false means the platform kept no record—typical for a customer's uploaded old character sheet; save the url yourself if you need to keep it), physically_deleted is always empty. If the customer says \"delete the old image\", tell them truthfully that it is no longer used but the file still exists; do not say it has been deleted. Pass either a local file (file_path, auto-upload to COS) or an already-hosted image URL (image_url). Registration is free; content checking is a small visual audit charged postpaid by usage.\n★【Post-completion QC · free】After generation, wait for images to be stored (poll the corresponding get_* for status; if pending, do not call again), then call review_assets to audit the asset layer (missing image / generating / failed / rejected by consistency gate / prop-era conflict / color script), tell the customer findings verbatim, fix according to action and re-audit; then personally inspect each image according to the returned agent_qc (whether it matches the profile, is the same person, era is correct; for the turnaround itself, whether all angles are complete and proportions/structure are correct; whether prop and scene images make sense in the plot—compare the shots listed in used_in_shots), submit_qc_report to submit the QC report; when generating shot images, pass its review_token as asset_review_token to generate_frames / generate_shot_frame.",
103
+ "quote_derive_character_portrait": "Quote for deriving a character sheet (free, no image generation). Uses one character's sheet as the reference for image-to-image: keeps facial proportions, face shape, eye shape and the position of facial marks (moles/scars), and only progresses the age to age_stage. ★Typical use: **the same person at different ages was created as several separate characters**—batch sheet generation gives them no shared identity anchor, so faces come out as different people and moles switch sides; pick the one whose sheet is correct as the reference (reference_character_id) and derive the other ages one by one. In cross-character derivation, clothing and hairstyle follow the **target character's profile** appearance and wardrobe lock, not the reference image's outfit—before deriving, check with get_characters that the target's appearance describes clothing for that age, and fix it with update_character if not; omitting reference_character_id = use the target's own sheet as the reference, change age only, no clothing injected. Pricing: each candidate = the drama's image model price with 1 reference image (e.g. gpt-image-2.5-flare: 11+18=29 credits) × count. Pass the returned quote_id to derive_character_portrait. ⚠️ Batch quote confirmation flow: first call the corresponding quote_* tool to get estimated_points and quote_id, then use quote_id to call this tool (quote confirmation follows execution mode: professional mode / unconfirmed plan / customer-controlled stage → explain to the customer and proceed only after customer consent, do not decide for the customer; autopilot stage → do not ask the customer, follow get_production_plan autopilot.default_decisions, and the platform records it in get_autopilot_log). Autopilot-stage quotes must fit within the hard budget cap; if blocked by 402 BUDGET_WOULD_EXCEED, stop and ask the customer. ★**Image-generation quotes (character sheet/scene image/frame generation) give two numbers**: estimated_points is the **upper bound** (estimated by the max number of reference images for that model, ensuring you don't start with an under-budget and hit 402 halfway); typical_points in the same response is the **typical cost**. Tell the customer both—only stating the upper bound makes it look much more expensive (the full-reference upper bound can exceed typical by over 2x), while only stating typical may leave insufficient balance. For fixed-price models they are equal, so one number is enough. Video-generation quote and charging use the same function, so this range does not exist.",
104
+ "derive_character_portrait": "Derive character sheet candidates per the quote (generated in the background, charged by usage). Only produces candidates and **does not replace** the target character's current sheet; returns image_generation_ids—poll get_derived_portrait_candidates until completed, show the candidates to the customer, and after they pick one call adopt_derived_portrait to register it. Parameters always follow the quote (passing quote_id alone is enough; passing different parameters returns 409). If the reference character's sheet changed or the drama's image model was changed after quoting ⇒ 409, quote again.",
105
+ "get_derived_portrait_candidates": "Check progress and images of derived character sheet candidates (free). Returns {id,status,image_url,error_msg} for each; pending/processing means still generating—do not derive again (double charge). Once all are completed, **inspect each image yourself**: is it the same person as the reference character (features, facial mark positions), is the age right, does the clothing match the target character's profile—then let the customer choose.",
106
+ "adopt_derived_portrait": "Register the derived candidate chosen by the customer as the target character's sheet (registration is free; the content check is a small visual review, postpaid by usage). Same effect as set_character_portrait: later AI regeneration will not overwrite it by default; the old design sheet/multi-angle headshots/full-body reference are invalidated and **not regenerated automatically**—after registering, follow next_step in the response and run generate_character_sheet(character_id) first; stale_frames in the response are shots whose first frame still uses the old sheet, regenerate them shot by shot with quote_shot_frame + generate_shot_frame. If the content check fails it returns 422 without registering; relay the issues to the customer verbatim and only pass allow_issues:true if the customer insists.\n★【Post-completion QC · free】After generation, wait for the image to land in the DB (poll the corresponding get_* status; if pending, do not call again), then call review_assets to review the asset layer (missing image / generating / failed / rejected by consistency gate / prop-era conflict / color script), relay findings to the customer verbatim, fix per action and review again; then personally inspect each image according to the returned agent_qc (whether it matches the profile, is the same person, era is correct; whether the design image itself has complete angles and correct proportions/structure; whether props and scene images make sense in the plot—check the shots in material used_in_shots), submit_qc_report to submit the QC report; when generating shot images, pass its review_token as asset_review_token to generate_frames / generate_shot_frame.",
103
107
  "upload_shot_frame": "Use a **customer-owned image** as a shot's first_frame or last_frame. last_frame is optional—only pass it when you want to fix a shot's ending image (large camera move/reveal shot); normally only first_frame is needed. Marks any existing video for that shot as stale and awaiting regeneration. Auto-upload + registration. Free. ⚠️ Only use for customer-provided material, or **local repair of this shot's platform candidate** (recovery_options upload_fixed: crop/color-grade/fix small defects on the original image returned by get_frame_candidates, then upload after customer confirmation). To \"redraw a shot\", use generate_shot_frame to let the platform regenerate it—images generated from scratch by external tools do not carry this film's identity anchors and style anchors, so people/costumes/style will drift.",
104
108
  "register_external_delivery": "Register an externally post-produced final cut; the server verifies sha256, size, and duration. Free. If you have the original export, pass the export-time handoff_pack_id and handoff_manifest_sha256; the platform uses the original frozen manifest and does not guess the source from the latest materials at registration time. Without the original export, the source is marked unknown. Registration does not mean customer acceptance; after traceability is enabled, you still need set_current_delivery to choose the current version and confirm_delivery_acceptance to record the customer's explicit confirmation. Pass either file_path or file_url.",
105
109
  "list_deliveries": "List **all final cut versions** for this episode (new→old; platform final cuts and external deliveries share one version sequence). Each entry includes sha256, duration, is_current, and full manifest. Free.\n★source=platform: every platform final cut version (compose_episode / rerender_episode / multi-aspect) is **automatically registered**; the manifest records **the exact timeline used for rendering**—for each shot, whether it used original footage/composited footage/retracked output/lip-sync output (source_kind), which files were used for dialogue/music/SFX, subtitle count and text hash, file sha256, and dialogue audit family counts at registration time. Use this as the authority for delivery notes and for verifying \"which version was delivered\"; do not rely on memory. Platform versions **do not automatically become the current delivery version**; when the customer selects a version, use set_current_delivery to point to it.\n★source=external: external post-produced final cut registered by register_external_delivery.",
@@ -104,6 +104,10 @@
104
104
  "generate_scene_images": "确认后批量出**空景基板**(每场一张无人物的场景底图):后台异步,只补「还没有图」的场景。★**出镜头图前做这一步**。跳过不会报错、不会被拦,但代价是实打实的:平台的兜底是「出帧时发现该场景缺图 → 后台补一张」,补的那张只惠及同场景的**后续**镜,触发它的那一镜等不到,于是**每个场景的第一镜没有背景锚**——而首镜往往正是定调的那一镜;后续镜之间背景也会一路漂。它与定妆图是一对:定妆图锚人、场景图锚景。★出得不对不要重调本工具(它只补缺图的场景、已有图的一律跳过):`get_scene_prompt` 读正文 → `update_scene` 改 image_prompt → `regenerate_scene_image` 单场重出。★非当代或超现实题材先设 `set_era_contract`,否则基板会画成别的时代,下游整场的镜头帧跟着错。★进度看 `get_pipeline_status` 的 generate_scene_images 步。⚠️ 批量报价确认流程:先调对应的 quote_* 工具拿 estimated_points 与 quote_id,再用 quote_id 调本工具(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。托管环节报价须在预算硬上限内,被 402 BUDGET_WOULD_EXCEED 拦下就停下问客户。★**出图类报价(定妆图/场景图/出帧)给的是两个数**:estimated_points 是**上界**(按该模型参考图张数上限估,保证你不会按低了的预算开跑、出到一半 402 中断);同一响应里的 typical_points 是**通常花费**。两个都要告诉客户——只说上界会让人以为贵得多(满参考图的上界可达通常值的 2 倍以上),只说通常值又会让余额准备不足。固定价模型下两者相等,这时说一个数就行。出视频的报价与扣费同函数,不存在这个区间。\n★【完成后质检·免费】出完等图落库(轮询对应 get_* 看状态,pending 别重复调),再调 review_assets 审资产层(缺图 / 生成中 / 失败 / 被一致性闸拒收 / 道具时代冲突 / 色彩脚本),findings 原样告诉客户、按 action 修完复审;再按它返回的 agent_qc 亲自逐张看图(像不像档案、是不是同一个人、时代对不对;设定图本身各角度齐不齐、比例与结构对不对;道具与场景图放在剧情里合不合理——对照素材 used_in_shots 那几镜),submit_qc_report 提交质检报告;出镜头图时把它的 review_token 作为 asset_review_token 传给 generate_frames / generate_shot_frame。",
105
105
  "upload_image": "把本地图片上传到我方 COS,返回 image_url(字节直传 COS、不过业务服务器)。用于给视频编辑当参考图,或先拿 URL 再登记。免费。",
106
106
  "set_character_portrait": "用客户自有图片作为角色定妆图(身份锚,优先级高于 AI 生成;之后 AI 重生默认不覆盖)。★★图片规范(登记前平台会自动检查,不合规返回 422 且不登记):**只有该角色一人**(不能有其他人/合影/背景路人);**单张单一角度**(不是拼图/九宫格/多视角设定图——设定图由平台据定妆图生成);正面或 3/4 侧、面部清晰无遮挡、干净背景;**图上无任何文字**(水印/字幕/名字标签/logo/衣服印字都不行,字样会被复刻进每一镜)。上传前先看一眼客户给的图,不合规就先请客户换图,别直接传。被拒时把 message 里的问题原样告诉客户;只有客户看过问题后明确坚持用这张图,才带 allow_issues:true 重传(自动检查可能误判)。★换图会失效原有派生资产(设定图/多角度头像/发型·身材参考)并重建人脸锁,但**设定图不会自动重出**——换完必须 generate_character_sheet(character_id) 据新定妆图重出设定图(响应里的 next_step 会提示),否则该角色只剩定妆图一个锚。★换图后响应含 stale_frames=[{storyboard_id,storyboard_number,frames}]——这些镜的首帧还是旧定妆图生成的、已被污染。要让新定妆图生效:对每个 stale_frame 用 quote_shot_frame+generate_shot_frame 重生该镜(平台会自动以新定妆图/设定图/人脸锁作锚,保全片一致)。不必逐镜自己指定模型/首尾帧。★千万别自制首尾帧再 upload_shot_frame——外部图没有角色身份锚/画风锚,人物·服装·画风必漂,那才是废片根源(不是\"杜绝废片\")。★换图只是**解除引用**,旧定妆图/设定图的文件不会被删除。响应里的 old_assets 逐项列出被解除的旧资产:unlinked=[{kind,url,in_history}](in_history=false 表示平台没留记录——典型是客户上传的旧定妆图,要留就把 url 存下来),physically_deleted 恒为空。客户说「删掉旧图」时,如实告诉他只是不再使用、文件仍在,别说成已删除。传本地文件(file_path,自动上传 COS)或已托管的图片 URL(image_url),二选一。登记免费;内容检查是一次小额视觉审核,按用量后付。\n★【完成后质检·免费】出完等图落库(轮询对应 get_* 看状态,pending 别重复调),再调 review_assets 审资产层(缺图 / 生成中 / 失败 / 被一致性闸拒收 / 道具时代冲突 / 色彩脚本),findings 原样告诉客户、按 action 修完复审;再按它返回的 agent_qc 亲自逐张看图(像不像档案、是不是同一个人、时代对不对;设定图本身各角度齐不齐、比例与结构对不对;道具与场景图放在剧情里合不合理——对照素材 used_in_shots 那几镜),submit_qc_report 提交质检报告;出镜头图时把它的 review_token 作为 asset_review_token 传给 generate_frames / generate_shot_frame。",
107
+ "quote_derive_character_portrait": "定妆图派生的报价(免费,不出图)。以一个角色的定妆图为参考做图生图:保留五官比例、脸型、眼型与面部标记(痣/疤)的位置,只把年龄推演到 age_stage。★典型用途:**同一人物的不同年龄建成了几个独立角色**——批量出定妆图时它们彼此没有身份锚,脸会画成不同的人、痣会换边;这时选其中定妆图合格的那个当参考(reference_character_id),给其余年龄的角色逐个派生。跨角色派生时穿着与发型按**目标角色档案**的外貌(appearance)与服装锁出,不沿用参考图的衣服——派生前先 get_characters 核对目标角色的 appearance 写对了年龄相应的穿着,不对先 update_character 改;不传 reference_character_id = 以目标角色自己的定妆图为参考、只改年龄、不注入服装。计价:每张候选 = 本剧图片模型带 1 张参考图的单价(如 gpt-image-2.5-flare 为 11+18=29 点)× count。拿到 quote_id 后传给 derive_character_portrait。⚠️ 批量报价确认流程:先调对应的 quote_* 工具拿 estimated_points 与 quote_id,再用 quote_id 调本工具(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。托管环节报价须在预算硬上限内,被 402 BUDGET_WOULD_EXCEED 拦下就停下问客户。★**出图类报价(定妆图/场景图/出帧)给的是两个数**:estimated_points 是**上界**(按该模型参考图张数上限估,保证你不会按低了的预算开跑、出到一半 402 中断);同一响应里的 typical_points 是**通常花费**。两个都要告诉客户——只说上界会让人以为贵得多(满参考图的上界可达通常值的 2 倍以上),只说通常值又会让余额准备不足。固定价模型下两者相等,这时说一个数就行。出视频的报价与扣费同函数,不存在这个区间。",
108
+ "derive_character_portrait": "按报价派生定妆图候选(后台出图,按用量扣点)。只出候选,**不替换**目标角色现有定妆图;返回 image_generation_ids,用 get_derived_portrait_candidates 轮询到 completed 后把候选图给客户看,客户挑中一张再 adopt_derived_portrait 登记。参数一律以报价时为准(只传 quote_id 即可;另传不同参数会 409)。报价后参考角色换了定妆图或剧的图片模型被改 ⇒ 409,重新报价。",
109
+ "get_derived_portrait_candidates": "查定妆图派生候选的进度与图片(免费)。返回每张 {id,status,image_url,error_msg};pending/processing 是还在出,别重复派生(重复扣费)。全部 completed 后**亲自逐张看图**:是不是参考角色同一个人(五官、面部标记位置)、年龄对不对、穿着是否符合目标角色档案,把候选给客户挑。",
110
+ "adopt_derived_portrait": "把客户选中的派生候选登记为目标角色的定妆图(免费登记;内容检查是一次小额视觉审核,按用量后付)。效果同 set_character_portrait:之后 AI 重生默认不覆盖;原设定图/多角度头像/全身参考失效且**不会自动重出**——登记后按响应里的 next_step 先 generate_character_sheet(character_id) 重出设定图;响应里的 stale_frames 是首帧还用着旧定妆图的镜,要用 quote_shot_frame + generate_shot_frame 逐镜重生。内容检查不合规返回 422 不登记,把问题原样告诉客户,客户坚持才带 allow_issues:true。\n★【完成后质检·免费】出完等图落库(轮询对应 get_* 看状态,pending 别重复调),再调 review_assets 审资产层(缺图 / 生成中 / 失败 / 被一致性闸拒收 / 道具时代冲突 / 色彩脚本),findings 原样告诉客户、按 action 修完复审;再按它返回的 agent_qc 亲自逐张看图(像不像档案、是不是同一个人、时代对不对;设定图本身各角度齐不齐、比例与结构对不对;道具与场景图放在剧情里合不合理——对照素材 used_in_shots 那几镜),submit_qc_report 提交质检报告;出镜头图时把它的 review_token 作为 asset_review_token 传给 generate_frames / generate_shot_frame。",
107
111
  "upload_shot_frame": "用**客户自有图片**作为某镜的首帧(first_frame)或尾帧(last_frame)。尾帧可选——仅在想固定某镜结尾画面(大运镜/揭示镜)时传;常规只需首帧。会把该镜已有视频标为过期待重生。自动上传+登记。免费。⚠️ 只用于客户自己提供的素材,或**本镜平台候选的局部修补**(recovery_options 的 upload_fixed:在 get_frame_candidates 给的原图上裁切/调色/修小瑕疵,客户确认后上传)。想「重画某一镜」请用 generate_shot_frame 让平台重生——外部工具从头生成的图不带本片的身份锚与画风锚,贴进来人物/服装/画风会漂。",
108
112
  "register_external_delivery": "登记外部后期成片,服务端核验 sha256、大小和时长。免费。有原始导出时传导出时的 handoff_pack_id 与 handoff_manifest_sha256;平台使用原始冻结清单,不按登记时最新素材猜来源。没有原始导出时来源标未知。登记不代表客户接受;启用追溯后还需 set_current_delivery 选择当前版本,confirm_delivery_acceptance 记录客户明确确认。file_path 或 file_url 二选一。",
109
113
  "list_deliveries": "列本集**所有成片版本**(新→旧,平台成片与外部交付共用一条版本号),每条含 sha256、时长、is_current 与完整清单。免费。\n★source=platform:平台每出一版成片(compose_episode / rerender_episode / 多画幅)都会**自动登记**,清单记的是**渲染用的那份时间线**——每镜用的是原片/合成片/换轨产物/口型产物(source_kind)、对白/配乐/音效各用了哪些文件、字幕条数与文本哈希、文件 sha256,以及登记时刻的台词审计分族计数。写交付说明、核对「交出去的是哪一版」以它为准,别凭记忆。平台版本**不会自动成为当前交付版**;客户选定哪一版,用 set_current_delivery 指过去。\n★source=external:register_external_delivery 登记的外部后期成片。",
@@ -198,7 +202,7 @@
198
202
  "select_mv_song": "MV 项目·AI 作曲第 4 步(免费):把某首候选设为本 MV 的整曲,并按本剧歌词自动对轴(之后 generate_mv_story / generate_mv_script 照常走)。",
199
203
  "update_character": "改角色设定(名字/外貌/年龄段/族裔/性别/性格/戏份/档案锁定)。改后需重出定妆图/相关图。本身免费;改了外貌(appearance 真的变了)约 5 分钟后会自动做一次设定一致性检查(文本后付,账单名「设定一致性检查」;同一部剧 5 分钟内多次改动合并成一次,同值保存不触发);只改 profile_locked 等其它字段不触发。★profile_locked=1:客户确认外观后锁定档案,后续 AI 提取不再覆盖外貌/性格/描述——外貌锚着定妆图与人脸锁定,被覆盖=全片换脸;确认满意即锁,要再改先传 0 解锁。",
200
204
  "delete_character": "删除一个角色(提取误建/合并时用)。免费。",
201
- "update_scene": "改场景设定(名字/描述/地点/时段/氛围),以及**场景图的出图提示词正文**(image_prompt)。免费(纯文本写库)。★场景图不满意时,改 image_prompt 才是直接手段——只改地点/时段是让平台重拼,拧不过来;改前先用 get_scene_prompt 读现值,改完用 regenerate_scene_image 重出这一场的图。★场景图变了不会自动重出已生成的镜头帧:那些帧仍拿旧场景图当背景锚,要跟上得逐镜重出。",
205
+ "update_scene": "改场景设定(地点/时段/物理地点归并键/时代契约),以及**场景图的出图提示词正文**(image_prompt)。免费(纯文本写库)。★场景名就是 location;氛围、描述写进 image_prompt。改 time_of_day 后 import_storyboard_table 按「地点+时段」绑场景就能对上。★场景图不满意时,改 image_prompt 才是直接手段——只改地点/时段是让平台重拼,拧不过来;改前先用 get_scene_prompt 读现值,改完用 regenerate_scene_image 重出这一场的图。★场景图变了不会自动重出已生成的镜头帧:那些帧仍拿旧场景图当背景锚,要跟上得逐镜重出。",
202
206
  "set_era_contract": "设**本集**的时代契约(免费,纯文本写库)。★这是唯一压得过视觉锁的时代机制——古装/民国/仙侠类项目**出图前必设**,不设的话平台只能靠提示词正文堆字对抗,时代错乱(现代物件混进古代画面、仙境被画成写实古代)基本都是这里空着导致的。\n五档怎么选:\n· modern —— 现代/当代都市。不确定时用这档。\n· republican —— 民国、二十世纪早期。\n· historical —— 可考据的历史朝代;这档会要求画面向**考据写实**靠拢。\n· fantasy —— ★仙侠/奇幻/仙境:修真世界、妖灵化形一类**非写实**的东方奇幻。这类项目**别填 historical**——那档要求考据写实,会把发光灵气、悬浮地貌、非人化形一并判成「不合时代」,把画面往写实古代拽。\n· surreal —— ★现代 + 超现实:当代都市里有作者设定的超现实元素(超现实人体、都市异象)。基线同 modern;把超现实设定逐条写进 positive,它们被当作世界观正典、审计不判时代冲突;其中描述人物身体的设定适用于画面里每个人(含无参考的路人与人群),描述环境的只作用于世界。这类项目**别填 fantasy**——那档写死东方仙侠并禁当代服装。\n★设完不会自动重出已生成的图:要让画面跟上,得再调 generate_frames / regenerate_scene_image。★某一场要破例,用 update_scene 的 era_contract 单独覆写(场级压过集级)。",
203
207
  "get_drama_logo": "读本剧的成片台标设置(图片地址 / 宽度 / 位置 / 边距 / 不透明度)。免费。null = 没设台标。",
204
208
  "set_drama_logo": "设置本剧成片的图片台标(角标 logo),终拼时叠在全片字幕之上、整片可见。免费、不重出视频。先 upload_image 上传台标(建议透明底 PNG)拿到 URL 再传 src。尺寸/边距按 720p 高度基准、渲染时按成片高度等比缩放(例:1080×1920 竖屏要宽约 260px → width≈98)。改完 compose_episode / rerender_episode 生效。传 logo:null 清除台标。",
@@ -367,6 +367,7 @@ export const COMMON_REQUESTS = [
367
367
  { customer_says: '我有分镜表了,直接出片', do: '先 `get_storyboard_table_spec` 把契约给客户/外部工具,`check_storyboard_table` 自检全绿再 `import_storyboard_table`(默认 auto_complete,告知客户按文本计费),不要走改写;`get_autofill_status` 到 done 后 `review_storyboards` 再出图。' },
368
368
  { customer_says: '我的工具能导出表格 / 我想让别的 AI 直接生成结构化数据', do: '`get_bulk_import_spec`(契约 + 模板 + 成品示例给对方)→ `check_bulk_import`(errors 清零)→ `bulk_import_storyboards`;replace 模式先取得客户同意。' },
369
369
  { customer_says: '换了定妆图 / 换脸后镜头没变', do: '`set_character_portrait` 响应里的 stale_frames 逐镜 `generate_shot_frame`,再重生视频。' },
370
+ { customer_says: '同一人物不同年龄建成了几个角色,定妆图脸不像同一个人 / 痣换了边', do: '选定妆图合格的那个当参考:`quote_derive_character_portrait(character_id=目标, reference_character_id=参考, age_stage)` → 客户同意 → `derive_character_portrait` → `get_derived_portrait_candidates` 逐张看 → 客户挑中 `adopt_derived_portrait` → 按 next_step `generate_character_sheet`。派生前先核对目标角色 appearance 写的是该年龄的穿着。' },
370
371
  { customer_says: '图片一直没出来', do: '`get_storyboards` 看 frame_status:pending=在生成(每张几十秒到数分钟、整集十几分钟),别重复调 `generate_frames`;failed 才是失败,读 fail_reason / fail_hint。' },
371
372
  { customer_says: '预算多少 / 怎么更便宜', do: '各步 quote_* + `get_cost_estimate`;降本:hailuo-3(约 1/3)或 wan3.0(约 4 折,仅风格化/空镜/产品镜,写实真人绝不选)+ 草稿期低分辨率。' },
372
373
  { customer_says: '镜头之间接不上 / 画面跳 / 衔接不顺', do: '`get_storyboards` 看 seam_state:unchained / broken 才要修(unknown 是系统没判、intended 是有意切换,都别动)。还没出视频:整集 `chain_frames`(先 dry_run),单道同景别 `chain_shot_from_prev`(免费)、景别有变化 `quote_chain_shot_from` → `chain_shot_from` mode=reframe。上一镜视频已出好、不想动本镜首帧:`quote_align_prev_shot` → `align_prev_shot`(重生上一镜视频)。改了首帧的镜视频要重生。' },
@@ -1430,6 +1430,43 @@ export function registerProduceTools(server, client) {
1430
1430
  throw new Error('file_path 或 image_url 至少提供一个');
1431
1431
  return jsonResult(await client.producePost(`/characters/${character_id}/portrait`, { image_url: url, ...(allow_issues ? { allow_issues: true } : {}) }));
1432
1432
  });
1433
+ server.tool('quote_derive_character_portrait', '定妆图派生的报价(免费,不出图)。以一个角色的定妆图为参考做图生图:保留五官比例、脸型、眼型与面部标记(痣/疤)的位置,' +
1434
+ '只把年龄推演到 age_stage。★典型用途:**同一人物的不同年龄建成了几个独立角色**——批量出定妆图时它们彼此没有身份锚,' +
1435
+ '脸会画成不同的人、痣会换边;这时选其中定妆图合格的那个当参考(reference_character_id),给其余年龄的角色逐个派生。' +
1436
+ '跨角色派生时穿着与发型按**目标角色档案**的外貌(appearance)与服装锁出,不沿用参考图的衣服——派生前先 get_characters 核对目标角色的 appearance 写对了年龄相应的穿着,' +
1437
+ '不对先 update_character 改;不传 reference_character_id = 以目标角色自己的定妆图为参考、只改年龄、不注入服装。' +
1438
+ '计价:每张候选 = 本剧图片模型带 1 张参考图的单价(如 gpt-image-2.5-flare 为 11+18=29 点)× count。' +
1439
+ '拿到 quote_id 后传给 derive_character_portrait。' + CONFIRM_HINT, {
1440
+ character_id: z.number().int().positive().describe('目标角色(要出新定妆图的那个)'),
1441
+ reference_character_id: z.number().int().positive().optional()
1442
+ .describe('参考角色(同剧、已有合格定妆图;通常是同一人物另一年龄的角色)。不传 = 目标角色自己'),
1443
+ age_stage: z.string().describe('目标年龄,如「65」「65岁」「中年」'),
1444
+ count: z.number().int().min(1).max(6).optional().describe('候选张数 1~6,默认 2;每张单独计费'),
1445
+ }, async ({ character_id, reference_character_id, age_stage, count }) => jsonResult(await client.producePost(`/characters/${character_id}/derive-portrait/quote`, {
1446
+ age_stage, ...(reference_character_id ? { reference_character_id } : {}), ...(count ? { count } : {}),
1447
+ })));
1448
+ server.tool('derive_character_portrait', '按报价派生定妆图候选(后台出图,按用量扣点)。只出候选,**不替换**目标角色现有定妆图;' +
1449
+ '返回 image_generation_ids,用 get_derived_portrait_candidates 轮询到 completed 后把候选图给客户看,' +
1450
+ '客户挑中一张再 adopt_derived_portrait 登记。参数一律以报价时为准(只传 quote_id 即可;另传不同参数会 409)。' +
1451
+ '报价后参考角色换了定妆图或剧的图片模型被改 ⇒ 409,重新报价。', {
1452
+ character_id: z.number().int().positive(),
1453
+ quote_id: z.string().describe('来自 quote_derive_character_portrait'),
1454
+ }, async ({ character_id, quote_id }) => jsonResult(await client.producePost(`/characters/${character_id}/derive-portrait`, { quote_id })));
1455
+ server.tool('get_derived_portrait_candidates', '查定妆图派生候选的进度与图片(免费)。返回每张 {id,status,image_url,error_msg};pending/processing 是还在出,别重复派生(重复扣费)。' +
1456
+ '全部 completed 后**亲自逐张看图**:是不是参考角色同一个人(五官、面部标记位置)、年龄对不对、穿着是否符合目标角色档案,把候选给客户挑。', {
1457
+ character_id: z.number().int().positive(),
1458
+ image_generation_ids: z.array(z.number().int().positive()).min(1).describe('derive_character_portrait 返回的 image_generation_ids'),
1459
+ }, async ({ character_id, image_generation_ids }) => jsonResult(await client.produceGet(`/characters/${character_id}/derive-portrait/candidates?ids=${image_generation_ids.join(',')}`)));
1460
+ server.tool('adopt_derived_portrait', '把客户选中的派生候选登记为目标角色的定妆图(免费登记;内容检查是一次小额视觉审核,按用量后付)。' +
1461
+ '效果同 set_character_portrait:之后 AI 重生默认不覆盖;原设定图/多角度头像/全身参考失效且**不会自动重出**——' +
1462
+ '登记后按响应里的 next_step 先 generate_character_sheet(character_id) 重出设定图;响应里的 stale_frames 是首帧还用着旧定妆图的镜,' +
1463
+ '要用 quote_shot_frame + generate_shot_frame 逐镜重生。内容检查不合规返回 422 不登记,把问题原样告诉客户,客户坚持才带 allow_issues:true。' + ASSET_QC_HINT, {
1464
+ character_id: z.number().int().positive(),
1465
+ image_generation_id: z.number().int().positive().describe('get_derived_portrait_candidates 里客户选中的那张 id'),
1466
+ allow_issues: z.boolean().optional().describe('内容检查报了问题、客户看过后仍明确坚持用这张图时才传 true'),
1467
+ }, async ({ character_id, image_generation_id, allow_issues }) => jsonResult(await client.producePost(`/characters/${character_id}/derive-portrait/adopt`, {
1468
+ image_generation_id, ...(allow_issues ? { allow_issues: true } : {}),
1469
+ })));
1433
1470
  server.tool('upload_shot_frame', '用**客户自有图片**作为某镜的首帧(first_frame)或尾帧(last_frame)。尾帧可选——仅在想固定某镜结尾画面(大运镜/揭示镜)时传;常规只需首帧。会把该镜已有视频标为过期待重生。自动上传+登记。免费。' +
1434
1471
  '⚠️ 只用于客户自己提供的素材,或**本镜平台候选的局部修补**(recovery_options 的 upload_fixed:在 get_frame_candidates 给的原图上裁切/调色/修小瑕疵,客户确认后上传)。' +
1435
1472
  '想「重画某一镜」请用 generate_shot_frame 让平台重生——外部工具从头生成的图不带本片的身份锚与画风锚,贴进来人物/服装/画风会漂。', {
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.221",
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.221 tool surface (operationIds match MCP tool names 1:1)."
5
+ "version": "0.1.222",
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.222 tool surface (operationIds match MCP tool names 1:1)."
7
7
  },
8
8
  "servers": [
9
9
  {
@@ -373,6 +373,279 @@
373
373
  }
374
374
  }
375
375
  },
376
+ "/characters/{character_id}/derive-portrait": {
377
+ "post": {
378
+ "operationId": "derive_character_portrait",
379
+ "summary": "按报价派生定妆图候选(后台出图,按用量扣点)",
380
+ "description": "按报价派生定妆图候选(后台出图,按用量扣点)。只出候选,**不替换**目标角色现有定妆图;返回 image_generation_ids,用 get_derived_portrait_candidates 轮询到 completed 后把候选图给客户看,客户挑中一张再 adopt_derived_portrait 登记。参数一律以报价时为准(只传 quote_id 即可;另传不同参数会 409)。报价后参考角色换了定妆图或剧的图片模型被改 ⇒ 409,重新报价。",
381
+ "tags": [
382
+ "characters"
383
+ ],
384
+ "parameters": [
385
+ {
386
+ "name": "character_id",
387
+ "in": "path",
388
+ "required": true,
389
+ "schema": {
390
+ "type": "integer",
391
+ "exclusiveMinimum": 0
392
+ }
393
+ }
394
+ ],
395
+ "requestBody": {
396
+ "required": true,
397
+ "content": {
398
+ "application/json": {
399
+ "schema": {
400
+ "type": "object",
401
+ "properties": {
402
+ "quote_id": {
403
+ "type": "string",
404
+ "description": "来自 quote_derive_character_portrait"
405
+ }
406
+ },
407
+ "required": [
408
+ "quote_id"
409
+ ]
410
+ }
411
+ }
412
+ }
413
+ },
414
+ "responses": {
415
+ "200": {
416
+ "description": "StarReel envelope",
417
+ "content": {
418
+ "application/json": {
419
+ "schema": {
420
+ "type": "object",
421
+ "properties": {
422
+ "code": {
423
+ "type": "integer"
424
+ },
425
+ "message": {
426
+ "type": "string"
427
+ },
428
+ "data": {
429
+ "description": "Operation result payload"
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ },
436
+ "402": {
437
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
438
+ }
439
+ }
440
+ }
441
+ },
442
+ "/characters/{character_id}/derive-portrait/adopt": {
443
+ "post": {
444
+ "operationId": "adopt_derived_portrait",
445
+ "summary": "把客户选中的派生候选登记为目标角色的定妆图(免费登记;内容检查是一次小额视觉审核,按用量后付)",
446
+ "description": "把客户选中的派生候选登记为目标角色的定妆图(免费登记;内容检查是一次小额视觉审核,按用量后付)。效果同 set_character_portrait:之后 AI 重生默认不覆盖;原设定图/多角度头像/全身参考失效且**不会自动重出**——登记后按响应里的 next_step 先 generate_character_sheet(character_id) 重出设定图;响应里的 stale_frames 是首帧还用着旧定妆图的镜,要用 quote_shot_frame + generate_shot_frame 逐镜重生。内容检查不合规返回 422 不登记,把问题原样告诉客户,客户坚持才带 allow_issues:true。\n★【完成后质检·免费】出完等图落库(轮询对应 get_* 看状态,pending 别重复调),再调 review_assets 审资产层(缺图 / 生成中 / 失败 / 被一致性闸拒收 / 道具时代冲突 / 色彩脚本),findings 原样告诉客户、按 action 修完复审;再按它返回的 agent_qc 亲自逐张看图(像不像档案、是不是同一个人、时代对不对;设定图本身各角度齐不齐、比例与结构对不对;道具与场景图放在剧情里合不合理——对照素材 used_in_shots 那几镜),submit_qc_report 提交质检报告;出镜头图时把它的 review_token 作为 asset_review_token 传给 generate_frames / generate_shot_frame。",
447
+ "tags": [
448
+ "characters"
449
+ ],
450
+ "parameters": [
451
+ {
452
+ "name": "character_id",
453
+ "in": "path",
454
+ "required": true,
455
+ "schema": {
456
+ "type": "integer",
457
+ "exclusiveMinimum": 0
458
+ }
459
+ }
460
+ ],
461
+ "requestBody": {
462
+ "required": true,
463
+ "content": {
464
+ "application/json": {
465
+ "schema": {
466
+ "type": "object",
467
+ "properties": {
468
+ "image_generation_id": {
469
+ "type": "integer",
470
+ "exclusiveMinimum": 0,
471
+ "description": "get_derived_portrait_candidates 里客户选中的那张 id"
472
+ },
473
+ "allow_issues": {
474
+ "type": "boolean"
475
+ }
476
+ },
477
+ "required": [
478
+ "image_generation_id"
479
+ ]
480
+ }
481
+ }
482
+ }
483
+ },
484
+ "responses": {
485
+ "200": {
486
+ "description": "StarReel envelope",
487
+ "content": {
488
+ "application/json": {
489
+ "schema": {
490
+ "type": "object",
491
+ "properties": {
492
+ "code": {
493
+ "type": "integer"
494
+ },
495
+ "message": {
496
+ "type": "string"
497
+ },
498
+ "data": {
499
+ "description": "Operation result payload"
500
+ }
501
+ }
502
+ }
503
+ }
504
+ }
505
+ },
506
+ "402": {
507
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
508
+ }
509
+ }
510
+ }
511
+ },
512
+ "/characters/{character_id}/derive-portrait/candidates": {
513
+ "get": {
514
+ "operationId": "get_derived_portrait_candidates",
515
+ "summary": "查定妆图派生候选的进度与图片(免费)",
516
+ "description": "查定妆图派生候选的进度与图片(免费)。返回每张 {id,status,image_url,error_msg};pending/processing 是还在出,别重复派生(重复扣费)。全部 completed 后**亲自逐张看图**:是不是参考角色同一个人(五官、面部标记位置)、年龄对不对、穿着是否符合目标角色档案,把候选给客户挑。",
517
+ "tags": [
518
+ "characters"
519
+ ],
520
+ "parameters": [
521
+ {
522
+ "name": "character_id",
523
+ "in": "path",
524
+ "required": true,
525
+ "schema": {
526
+ "type": "integer",
527
+ "exclusiveMinimum": 0
528
+ }
529
+ },
530
+ {
531
+ "name": "ids",
532
+ "in": "query",
533
+ "required": true,
534
+ "schema": {
535
+ "type": "array",
536
+ "items": {
537
+ "type": "integer",
538
+ "exclusiveMinimum": 0
539
+ },
540
+ "minItems": 1,
541
+ "description": "derive_character_portrait 返回的 image_generation_ids"
542
+ }
543
+ }
544
+ ],
545
+ "responses": {
546
+ "200": {
547
+ "description": "StarReel envelope",
548
+ "content": {
549
+ "application/json": {
550
+ "schema": {
551
+ "type": "object",
552
+ "properties": {
553
+ "code": {
554
+ "type": "integer"
555
+ },
556
+ "message": {
557
+ "type": "string"
558
+ },
559
+ "data": {
560
+ "description": "Operation result payload"
561
+ }
562
+ }
563
+ }
564
+ }
565
+ }
566
+ },
567
+ "402": {
568
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
569
+ }
570
+ }
571
+ }
572
+ },
573
+ "/characters/{character_id}/derive-portrait/quote": {
574
+ "post": {
575
+ "operationId": "quote_derive_character_portrait",
576
+ "summary": "定妆图派生的报价(免费,不出图)",
577
+ "description": "定妆图派生的报价(免费,不出图)。以一个角色的定妆图为参考做图生图:保留五官比例、脸型、眼型与面部标记(痣/疤)的位置,只把年龄推演到 age_stage。★典型用途:**同一人物的不同年龄建成了几个独立角色**——批量出定妆图时它们彼此没有身份锚,脸会画成不同的人、痣会换边;这时选其中定妆图合格的那个当参考(reference_character_id),给其余年龄的角色逐个派生。跨角色派生时穿着与发型按**目标角色档案**的外貌(appearance)与服装锁出,不沿用参考图的衣服——派生前先 get_characters 核对目标角色的 appearance 写对了年龄相应的穿着,不对先 update_character 改;不传 reference_character_id = 以目标角色自己的定妆图为参考、只改年龄、不注入服装。计价:每张候选 = 本剧图片模型带 1 张参考图的单价(如 gpt-image-2.5-flare 为 11+18=29 点)× count。拿到 quote_id 后传给 derive_character_portrait。⚠️ 批量报价确认流程:先调对应的 quote_* 工具拿 estimated_points 与 quote_id,再用 quote_id 调本工具(报价确认按执行模式:专业模式 / 未确认方案 / 本环节由客户把控 → 讲给客户、客户同意才做,别替客户决定;本环节托管 → 不问客户,照 get_production_plan 的 autopilot.default_decisions 执行,平台记进 get_autopilot_log)。托管环节报价须在预算硬上限内,被 402 BUDGET_WOULD_EXCEED 拦下就停下问客户。★**出图类报价(定妆图/场景图/出帧)给的是两个数**:estimated_points 是**上界**(按该模型参考图张数上限估,保证你不会按低了的预算开跑、出到一半 402 中断);同一响应里的 typical_points 是**通常花费**。两个都要告诉客户——只说上界会让人以为贵得多(满参考图的上界可达通常值的 2 倍以上),只说通常值又会让余额准备不足。固定价模型下两者相等,这时说一个数就行。出视频的报价与扣费同函数,不存在这个区间。",
578
+ "tags": [
579
+ "characters"
580
+ ],
581
+ "parameters": [
582
+ {
583
+ "name": "character_id",
584
+ "in": "path",
585
+ "required": true,
586
+ "schema": {
587
+ "type": "integer",
588
+ "exclusiveMinimum": 0,
589
+ "description": "目标角色(要出新定妆图的那个)"
590
+ }
591
+ }
592
+ ],
593
+ "requestBody": {
594
+ "required": true,
595
+ "content": {
596
+ "application/json": {
597
+ "schema": {
598
+ "type": "object",
599
+ "properties": {
600
+ "age_stage": {
601
+ "type": "string",
602
+ "description": "目标年龄,如「65」「65岁」「中年」"
603
+ },
604
+ "reference_character_id": {
605
+ "type": "integer",
606
+ "exclusiveMinimum": 0
607
+ },
608
+ "count": {
609
+ "type": "integer",
610
+ "minimum": 1,
611
+ "maximum": 6
612
+ }
613
+ },
614
+ "required": [
615
+ "age_stage"
616
+ ]
617
+ }
618
+ }
619
+ }
620
+ },
621
+ "responses": {
622
+ "200": {
623
+ "description": "StarReel envelope",
624
+ "content": {
625
+ "application/json": {
626
+ "schema": {
627
+ "type": "object",
628
+ "properties": {
629
+ "code": {
630
+ "type": "integer"
631
+ },
632
+ "message": {
633
+ "type": "string"
634
+ },
635
+ "data": {
636
+ "description": "Operation result payload"
637
+ }
638
+ }
639
+ }
640
+ }
641
+ }
642
+ },
643
+ "402": {
644
+ "description": "Insufficient prepaid balance (never overdrafts); response carries `needed` points"
645
+ }
646
+ }
647
+ }
648
+ },
376
649
  "/characters/{character_id}/portrait": {
377
650
  "post": {
378
651
  "operationId": "set_character_portrait",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starreel/mcp",
3
- "version": "0.1.221",
3
+ "version": "0.1.222",
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.221",
5
+ "version": "0.1.222",
6
6
  "websiteUrl": "https://starreel.ai",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "@starreel/mcp",
11
- "version": "0.1.221",
11
+ "version": "0.1.222",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  },