{"openapi":"3.1.0","info":{"title":"WriteForYou MCP API","version":"0.1.0"},"paths":{"/api/mcp/list_models":{"post":{"tags":["mcp"],"summary":"List Models","description":"List LLM models the caller can pass via the `model` parameter\non `generate_story`, `revise_chapter`, `plan_revision`, etc.\n\nReturns `{models: [{id, label, ...}]}`. Omit `model` (or pass an\nempty string) to use the server default. No auth required.","operationId":"list_models","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmptyInput"},{"type":"null"}],"title":"Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListModelsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_credits":{"post":{"tags":["mcp"],"summary":"Get Credits","description":"Report the authenticated user's billing and subscription state.\n\nFree, read-only probe. Use before a chargeable call to avoid a 402\nmid-flow and to surface whether WriteForYou Pro access is active.\n\nReturns entitlement plus credit_accounting. In subscription mode,\ncredit_accounting is legacy/free-trial bookkeeping and does not gate\naccess; use entitlement.allows_access and subscription.allows_access.","operationId":"get_credits","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmptyInput"},{"type":"null"}],"title":"Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCreditsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_job_status":{"post":{"tags":["mcp"],"summary":"Get Job Status","description":"Lean status probe for a story, revision, asset, article, or chat op.\n\n`is_terminal` is the only terminal signal clients should use.\nPrefer wait_for_status over a client poll loop.","operationId":"get_job_status","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/wait_for_status":{"post":{"tags":["mcp"],"summary":"Wait For Status","description":"Block until the job reaches `target`/`until` (or timeout).\n\nCovers story writes, revisions, assets, articles, and chat\noperations via `kind`. On timeout returns current status with\ntimed_out=true — not an error.","operationId":"wait_for_status","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitForStatusInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_activity":{"post":{"tags":["mcp"],"summary":"Get Activity","description":"Agent-activity feed for one story or article job.","operationId":"get_activity","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetActivityInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/start_checkout":{"post":{"tags":["mcp"],"summary":"Start Checkout","operationId":"start_checkout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartCheckoutInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_billing_portal":{"post":{"tags":["mcp"],"summary":"Get Billing Portal","operationId":"get_billing_portal","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmptyInput"},{"type":"null"}],"title":"Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPortalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/sync_subscription":{"post":{"tags":["mcp"],"summary":"Sync Subscription","operationId":"sync_subscription","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncSubscriptionInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncSubscriptionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/start_article_job":{"post":{"tags":["mcp"],"summary":"Start Article Job","description":"Create an article job from a Codex MCP request and return its URL.\n\nThis is only the Created phase. The article writer's tone and style\nare server-side defaults, so callers provide the article request but\ndo not pass a tone field.","operationId":"start_article_job","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartArticleJobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/attach_article_research":{"post":{"tags":["mcp"],"summary":"Attach Article Research","description":"Attach Codex/Claude research to an article job.\n\nDefault server mode stores the handoff, writes the first draft with\nthe server article writer, and returns the review URL. Client mode\n(`authoring_mode=\"client\"` or `server_llm=false`) stores the handoff\nand returns a no-server-LLM drafting brief; call this same tool again\nwith `base_text_hash` and `text` to commit the client-authored draft.","operationId":"attach_article_research","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachArticleResearchInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/upsert_article_note":{"post":{"tags":["mcp"],"summary":"Upsert Article Note","description":"Add or update a review note on an article draft.\n\nNotes can come from Codex or the website review UI. They stay visible\non the article page and are consumed by revise_article_from_notes.","operationId":"upsert_article_note","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertArticleNoteInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/resolve_article_note":{"post":{"tags":["mcp"],"summary":"Resolve Article Note","description":"Mark one article review note resolved without running a revision.","operationId":"resolve_article_note","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleNoteInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_article_note":{"post":{"tags":["mcp"],"summary":"Delete Article Note","description":"Delete one article review note from an article job.","operationId":"delete_article_note","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleNoteInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/revise_article_from_notes":{"post":{"tags":["mcp"],"summary":"Revise Article From Notes","description":"Apply open article notes and produce the next draft revision.\n\nOpen review notes are the highest-priority edit contract and override\nstale original request constraints. If a note says to replace\ntitle/deck/body exactly and supplies Title:, Deck:, and Body: sections,\nthe replacement is applied deterministically without a server LLM call.\n\nDefault server mode uses the server article revision writer. Client\nmode (`authoring_mode=\"client\"` or `server_llm=false`) returns a\nno-server-LLM revision brief; call this same tool again with\n`base_text_hash` and revised Markdown `text` to commit.","operationId":"revise_article_from_notes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseArticleFromNotesInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/prepare_publish_draft":{"post":{"tags":["mcp"],"summary":"Prepare Publish Draft","description":"Prepare a draft-only publishing package.\n\nThis does not publish externally. It packages the final article so a\nhuman can approve and copy it into the configured destination.","operationId":"prepare_publish_draft","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreparePublishDraftInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/publish_article_draft":{"post":{"tags":["mcp"],"summary":"Publish Article Draft","description":"Create a draft article on Dev.to from the prepared publish package.\n\nThe Dev.to payload always uses published=false. This endpoint is\nidempotent: if the article already has a Dev.to draft id, it returns\nthe stored draft metadata instead of creating another draft.","operationId":"publish_article_draft","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishArticleDraftInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/list_articles":{"post":{"tags":["mcp"],"summary":"List Articles","description":"List article jobs owned by the caller.","operationId":"list_articles","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmptyInput"},{"type":"null"}],"title":"Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListArticlesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_article":{"post":{"tags":["mcp"],"summary":"Delete Article","description":"Delete one article job owned by the caller.","operationId":"delete_article","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_asset":{"post":{"tags":["mcp"],"summary":"Generate Asset","description":"Start an async Writer visual-asset generation through DesignForYou.\n\nNormalizes a structured `asset-generation/v1` brief, then kicks off a\nbackground job that asks DesignForYou to recommend a template and\ncalls its `/api/mcp/generate` tool. Returns immediately with\n`{job_id, status: \"running\"}` — poll `get_asset_status` until the job\nis terminal. The expert image-edit path can take well over two\nminutes, so this never blocks the HTTP request. Pass\n`generation.session_id` to refine a previous result, and\n`generation.context_ids` to use prior DesignForYou designs as visual\nreferences.","operationId":"generate_asset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateAssetInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/list_location_references":{"post":{"tags":["mcp"],"summary":"List Location References","description":"List durable reusable Writer location references saved on a story.","operationId":"list_location_references","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListLocationReferencesInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationReferencesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/set_location_reference":{"post":{"tags":["mcp"],"summary":"Set Location Reference","description":"Persist or update a reusable Writer location reference from a D4U asset.","operationId":"set_location_reference","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetLocationReferenceInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_location_reference":{"post":{"tags":["mcp"],"summary":"Delete Location Reference","description":"Delete a saved Writer location reference from a story.","operationId":"delete_location_reference","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteLocationReferenceInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_writer_scene_still":{"post":{"tags":["mcp"],"summary":"Generate Writer Scene Still","description":"Generate one full-bleed 16:9 scene still via hosted DesignForYou or local Grok CLI.","operationId":"generate_writer_scene_still","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateWriterSceneStillInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/set_scene_stills":{"post":{"tags":["mcp"],"summary":"Set Scene Stills","description":"Persist a generated selected-paragraph scene-stills grid on a chapter.","operationId":"set_scene_stills","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSceneStillsInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_cover":{"post":{"tags":["mcp"],"summary":"Generate Chapter Cover","description":"Generate a non-spoiler cover image for a chapter.\n\nReads the chapter, plans an establishing scene that sets the chapter up\nwithout revealing its climax or twist, grounds it on the featured cast's\nreference art (gpt-image-2 multi-reference edit — pose sheet preferred\nper character), and renders it through DesignForYou.\nReturns `{cover_job_id, status: \"running\"}` — poll\n`get_chapter_cover_status` until terminal. The generated cover is saved\non the chapter (`output_artifacts.chapters[n].cover`).","operationId":"generate_cover","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateChapterCoverInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/suggest_cover_scenes":{"post":{"tags":["mcp"],"summary":"Suggest Cover Scenes Route","description":"Suggest distinct one-line, non-spoiler establishing cover-scene ideas.\n\nCall on open for the first 3 ideas. Call again for MORE options — pass the\nalready-shown lines in `exclude` and any steer in `message` (and the running\n`messages`). Returns `{chapter, scenes: [str], editorial_summary}`.","operationId":"suggest_cover_scenes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestCoverScenesInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/set_cover":{"post":{"tags":["mcp"],"summary":"Set Chapter Cover","description":"Persist a chosen generated image as the chapter's cover.\n\n`image` is an object returned by get_cover_image_status (`result.image`).\nReturns `{chapter, cover}`. Overwrites any existing cover for the chapter.","operationId":"set_cover","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChapterCoverInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/list_stories":{"post":{"tags":["mcp"],"summary":"List Stories","description":"List every story in the caller's library.\n\nReturns a lightweight summary per story — no plan / cast / prose —\nsuitable for picking which `job_id` to drill into with `get_story`.\nEach entry includes status, title, synopsis, chapter count, model,\ntimestamps, and (when available) `story_url` for a click-through.\nCheap; safe to call frequently.","operationId":"list_stories","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmptyInput"},{"type":"null"}],"title":"Input"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStoriesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/upsert_chapter_note":{"post":{"tags":["mcp"],"summary":"Upsert Chapter Note","description":"Add or update a review note on a generated story chapter.\n\nNotes can come from Codex or the website reader UI. They stay visible\non the chapter and can be consumed by revise_chapter_from_notes.","operationId":"upsert_chapter_note","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertChapterNoteInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_chapter_note":{"post":{"tags":["mcp"],"summary":"Delete Chapter Note","description":"Delete an open review note from a generated story chapter.","operationId":"delete_chapter_note","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteChapterNoteInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_story":{"post":{"tags":["mcp"],"summary":"Generate Story","description":"Kick off a new story — planner + characterizer run in the background.\n\nStatus state machine:\n  pending → in_progress → reviewing → in_progress → completed\n\nBy default the job settles at 'reviewing' so the caller can edit\nthe outline/cast via update_outline / update_characters and then\ncall start_writing. Pass auto_approve=true to skip review and go\nstraight to 'completed'.\n\nTerminal statuses: completed, failed, cancelled. Use\nwait_for_status to block until one is reached instead of polling\nget_job_status manually.","operationId":"generate_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateStoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/plan_story":{"post":{"tags":["mcp"],"summary":"Plan Story","description":"Granular alternative to generate_story — runs the PLANNER ONLY.\n\nCreates a fresh job and kicks off the planner in the background.\nSettles at status='outlining' with the plan committed; does NOT\nauto-chain into characterizer or setting research. Use this when\nyou want explicit control over each phase (call generate_cast and\nregenerate_setting separately afterwards).\n\nFor one-shot \"give me a complete story foundation\" use generate_story.\n\nReturns immediately with `{job_id, status: \"pending\", story_url?}`;\npoll get_job_status / wait_for_status for progress.","operationId":"plan_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanStoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/start_story_foundation":{"post":{"tags":["mcp"],"summary":"Start Story Foundation","description":"Create a premise-only story shell for the guided creation wizard.\n\nThis call deliberately performs no LLM work and creates no outline.\nThe intended sequence is research_world -> generate_cast ->\ngenerate_outline -> start_writing, allowing each artifact to be\nreviewed before it becomes context for the next one.","operationId":"start_story_foundation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStoryFoundationInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_cast":{"post":{"tags":["mcp"],"summary":"Generate Cast","description":"Granular alternative to generate_story — runs the CHARACTERIZER ONLY.\n\nRequires either an approved world or an existing outline.\nKicks off cast generation in the background; settles at\nstatus='reviewing' with the cast committed. Does NOT auto-research\nthe world — call regenerate_setting if you need that.\n\nReturns immediately with `{job_id, status: \"starting\", story_url?}`.","operationId":"generate_cast","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/generate_outline":{"post":{"tags":["mcp"],"summary":"Generate Outline","description":"Generate the first and only outline from the approved world and cast.","operationId":"generate_outline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/resume_writing":{"post":{"tags":["mcp"],"summary":"Resume Writing","description":"Resume chapter generation for a story with unwritten outlines.\n\nDetects the gap between `plan.chapter_outlines` and written\nchapters (those with non-empty text). Kicks off a background\nworker that writes only the missing chapters in outline order,\nseeding ledger context from chapters already on disk.\n\nUse when:\n  - A prior generation failed or was cancelled mid-write.\n  - The user grew the outline post-generation through the Outline\n    chat (refine_outline → Apply) and wants the new chapter(s) written.\n\nNo-op if every outline already has a written chapter — settles the\nstory back at status='completed'. Refused (409) while a write or\nrevision is already in flight.","operationId":"resume_writing","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/write_chapter":{"post":{"tags":["mcp"],"summary":"Write Chapter","description":"Write one unwritten chapter by number, possibly out of order.\n\nDiffers from resume_writing in that the caller picks which chapter\ninstead of always starting from the lowest unwritten one. Useful\nwhen the user wants to attempt a later chapter after an earlier one\nfailed (e.g. an LLM safety rejection) and they don't want to\nre-trigger the failing chapter first.\n\nRefused (409) when the chapter has no outline, is already written,\nor another writing/revision job is in flight.","operationId":"write_chapter","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteChapterInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_chapter_text":{"post":{"tags":["mcp"],"summary":"Get Chapter Text","description":"Fetch text for a specific chapter revision — used when switching versions.","operationId":"get_chapter_text","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetChapterTextResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/refresh_chapter_context":{"post":{"tags":["mcp"],"summary":"Refresh Chapter Context","description":"Regenerate continuity context for an existing chapter/revision.\n\nRe-runs the same continuity extractor used after chapter writes and\nfull chapter revisions. If the refreshed revision is the latest one,\nthe chapter-level metadata is refreshed too so future context ledgers\nsee the new facts.","operationId":"refresh_chapter_context","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshChapterContextInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_chapter_memory":{"post":{"tags":["mcp"],"summary":"Update Chapter Memory","description":"Edit saved continuity memory for a chapter/revision.\n\nThis is a manual correction path for bad extracted memory. It replaces\n`carry_forward_facts` on the selected revision (latest by default). If\nthe edited revision is the latest revision, the chapter-level memory is\nupdated too so future prior-context ledgers stop carrying stale facts.","operationId":"update_chapter_memory","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChapterMemoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_story":{"post":{"tags":["mcp"],"summary":"Get Story","description":"Fetch the full story artifact — plan, cast, chapter prose, revisions.\n\nSafe to call in any state, but the heavy payload only becomes\nuseful once status is 'reviewing' (outline + cast populated) or\n'completed' (all chapters written). During 'pending' / 'in_progress'\nmost fields are empty — prefer get_job_status for cheap polling.","operationId":"get_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetStoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetStoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/cancel_job":{"post":{"tags":["mcp"],"summary":"Cancel Job","description":"Cancel an in-flight story job (`pending` or `in_progress`).\n\nFlips both the persisted story status and the in-process job queue\nso unstarted work short-circuits immediately. Already-running\nchapter writes finish their current LLM call before stopping.\nSafe to call on terminal jobs — no-op.","operationId":"cancel_job","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_story":{"post":{"tags":["mcp"],"summary":"Delete Story","description":"Permanently delete a story from the caller's library.\n\nRemoves the story document, all chapters, all revisions, and any\nsaved chat threads. Irreversible — there is no soft-delete or\nrestore. Caller should confirm with the user before invoking.","operationId":"delete_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_story_title":{"post":{"tags":["mcp"],"summary":"Update Story Title","description":"Rename the story in the caller's library through an audited mutation.","operationId":"update_story_title","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStoryTitleInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStoryTitleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_revision_beats":{"post":{"tags":["mcp"],"summary":"Get Revision Beats","description":"Return historical beat artifacts and any fresh rewrite plan.\n\nRead-only. Computes text_hash and paragraph_count on the server.\nNever fabricates an exact map from unmapped legacy plan beats.\n``authoring_plan`` remains historical; ``active_revision_plan`` is the\nhash-bound client plan to use for a pending rewrite. Does not return\nchapter prose.","operationId":"get_revision_beats","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRevisionBeatsInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRevisionBeatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/chapter_chat":{"post":{"tags":["mcp"],"summary":"Chapter Chat","description":"Conversational reply for back-and-forth in the revise panel.\n\nUse this on every user-typed message. Returns a short free-text\neditor response — questions answered, ideas brainstormed, critique\ngiven, suggested changes described — WITHOUT generating a\nstructured plan. The UI shows a \"Ready for plan?\" button after\neach reply; clicking that calls plan_revision with the full\nconversation to synthesize the plan.\n\nReturns: {chapter: int, editorial_summary: str}","operationId":"chapter_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChapterChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/paragraph_chat":{"post":{"tags":["mcp"],"summary":"Selected Paragraph Chat","description":"Multi-purpose chat about one selected paragraph.\n\nThis is the chat-first replacement for the inline note apply flow. It\ncan explain, critique, retrieve prior context through story-query tools,\ndiscuss revision options, or prepare for a later rewrite plan. It does\nnot change story text.","operationId":"paragraph_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectedParagraphChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/outline_chat":{"post":{"tags":["mcp"],"summary":"Outline Chat","description":"Discuss the outline with the user. No changes are committed — call\nthis repeatedly across turns to explore direction, ask the user what\nthey want changed, react to their answers. Pass the running\nconversation back in `messages` each turn so the editor has context.\n\nReturns {editorial_summary} — free-text editor reply, usually ending\nwith a question to keep the conversation moving. When the user is\nsatisfied with a direction, call refine_outline(apply=true) to\ngenerate and commit the updated plan in one shot.\n\nValid while story.status == 'reviewing'. Free to call (no credit cost).","operationId":"outline_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutlineChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/character_chat":{"post":{"tags":["mcp"],"summary":"Character Chat","description":"Discuss the cast with the user. No changes are committed — call\nthis repeatedly across turns to explore who the characters are,\nwhat needs changing, etc. Pass the running `messages` back each turn.\n\nReturns {editorial_summary}. When the user is satisfied, call\nrefine_characters(apply=true) to commit a refined cast in one shot.\n\nValid while status == 'reviewing'. Free to call.","operationId":"character_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CharacterChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/world_chat":{"post":{"tags":["mcp"],"summary":"World Chat","description":"Discuss the world document (location, time period, culture) with the user.\nNo changes are committed — conversational only. Returns {editorial_summary}.","operationId":"world_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/get_chat":{"post":{"tags":["mcp"],"summary":"Get Chat","description":"Load a saved chat thread for a chapter+revision.\n\nReturns `{job_id, chapter, revision, messages}`. `messages` is a\nlist of `{role, content, plan?}` entries in chronological order.\nEmpty list if nothing was ever saved for this slot. Use\n`revision=0` (or omit) for the pre-revision draft thread.","operationId":"get_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/save_chat":{"post":{"tags":["mcp"],"summary":"Save Chat","description":"Persist a chat thread to a chapter+revision slot.\n\nReplaces any prior thread at that slot — pass the FULL message\nhistory each time, not a delta. `chapter_chat(auto_save=true)`\ndoes this automatically; this endpoint is for callers that build\nthe thread themselves.","operationId":"save_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/clear_chat":{"post":{"tags":["mcp"],"summary":"Clear Chat","description":"Delete the saved chat thread for a chapter+revision.\n\nIrreversible. Subsequent `get_chat` calls return an empty list.\nDoes not affect the chapter prose, only the conversation history.","operationId":"clear_chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/query_story":{"post":{"tags":["mcp"],"summary":"Query Story","description":"Semantic search over a story's text (whole story, latest revision).\n\nReturns `{job_id, question, passages}` where each passage is\n`{chapter, para, text, score}` — the most relevant excerpts for the\nquestion, with citations. Use to pull a specific fact, check continuity,\nor find where something happened. Pass `chapter` to scope to one chapter.\n`score` is the final hybrid relevance score; `semantic_score` is the\nraw embedding similarity before lexical/phrase reranking. Lexical\nfallback expands common rewrite-check concepts, so\n`matched_query_expansions` may include synonym or morphology hits.\nquery_story is a locator, not proof. For rewrite claims, inspect `retrieval_mode`, `confidence`, and\n`needs_read_story_verification`; use `read_story` on `recommended_read`\nwhen confidence is not high or fallback retrieval was used.","operationId":"query_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryStoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryStoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/read_story":{"post":{"tags":["mcp"],"summary":"Read Story","description":"Read exact text by address: a chapter + 0-based paragraph range\n(latest revision). Omit `para_end` for the rest of the chapter. Returns\n`{job_id, chapter, para_start, para_end, text, total_paras}`.","operationId":"read_story","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadStoryInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadStoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/plan_chapter":{"post":{"tags":["mcp"],"summary":"Plan Chapter","description":"Create or register a versioned initial beat plan for an unwritten chapter.","operationId":"plan_chapter","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanChapterInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/refine_outline":{"post":{"tags":["mcp"],"summary":"Refine Outline Endpoint","description":"Generate a refined outline from the conversation so far. Pass the\nfull running `messages` plus a synthesis instruction in `message`\n(e.g. \"based on our discussion, update the outline\").\n\n  apply=false (default): returns reply.updated_plan for inspection.\n    Use when you want to preview the rewrite before committing.\n  apply=true: atomically commits the refined plan. Use when the\n    user has said \"go ahead\" — saves a round-trip vs refine ->\n    serialize -> update_outline and eliminates re-serialization drift.\n\nReturns {editorial_summary, reply.{short_reply, long_reply,\nupdated_plan}, applied, title}. Valid while status == 'reviewing'.","operationId":"refine_outline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefineOutlineInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_outline":{"post":{"tags":["mcp"],"summary":"Update Outline","description":"Low-level direct replacement of the plan. Caller sends the full\nplan dict; this endpoint does not merge or diff — it replaces.\n\nPrefer refine_outline(apply=true) for conversational edits: it\nbuilds the new plan from the running chat and commits atomically.\nReach for update_outline only when you already have a fully-formed\nplan dict (e.g. programmatic transforms, reapplying a saved plan).\n\nValid after planning has produced a plan, including post-write and\ncancelled stories. Written chapter rows remain frozen unless an\noutline-review client explicitly sets allow_written_outline_edits.","operationId":"update_outline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOutlineInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/refine_characters":{"post":{"tags":["mcp"],"summary":"Refine Characters Endpoint","description":"Generate a refined character list from the conversation so far.\nPass `messages` plus a synthesis instruction (e.g. \"based on our\ndiscussion, update the cast\").\n\n  apply=false: returns reply.updated_cast for preview.\n  apply=true: atomically commits. Use when the user says \"go ahead\".\n\nReturns {editorial_summary, reply.{short_reply, long_reply,\nupdated_cast}, applied, character_count}.","operationId":"refine_characters","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefineCharactersInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_characters":{"post":{"tags":["mcp"],"summary":"Update Characters","description":"Low-level direct replacement of the character list. Prefer\nrefine_characters(apply=true) for conversational edits —\nupdate_characters is for programmatic / fully-formed cast dicts.\n\nValid in any state. Edits made after writing has started apply to\nfuture revisions only — already-written chapter text is not retouched.","operationId":"update_characters","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCharactersInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_character_asset":{"post":{"tags":["mcp"],"summary":"Update Character Asset","description":"Patch generated image metadata for one cast member.\n\nUse this for concept art and character sheets. It avoids resending the\nwhole cast through update_characters when only one generated asset\nchanged.","operationId":"update_character_asset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCharacterAssetInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/create_character_reference":{"post":{"tags":["mcp"],"summary":"Create Character Reference","description":"Make one cast member's reference image with your own image tools, then attach it.\n\nReturns a brief built from the story: a prompt in the house reference\nformat (one square image: front full body, face close-up, back full\nbody; fitted tank top and compression shorts, barefoot; neutral pose\nand expression), any existing images of the character to use as\nidentity references, generator settings (local Codex CLI first, fal\ngpt-image-2.5 flare as backup), acceptance checks, and a 60-minute\nupload URL. Generate the image locally, check it against brief.checks,\nthen PUT the file to upload.url (curl given; add ?model=<label>). The\nserver hosts it and sets the character's character_sheet (default) or\nconcept_art, replacing the previous one. No server image generation.","operationId":"create_character_reference","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCharacterReferenceInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/create_scene_still":{"post":{"tags":["mcp"],"summary":"Create Scene Still","description":"Make one paragraph's scene still with your own image tools, then attach it.\n\nReturns a brief built from the chapter: a 16:9 photographic prompt for\nthe paragraph (with up to ~900 characters of lead-in), the cast in\nthe shot with their attached reference images for identity (in the\norder to pass them), the story's fixed still style, acceptance checks,\ngenerator settings (local Codex CLI first, fal gpt-image-2.5 flare as\nbackup) and a 60-minute upload URL. Cast without a reference image are\nlisted in missing_references: call create_character_reference for them\nfirst for consistent faces. Generate locally, check against\nbrief.checks, then PUT the file to upload.url (curl given; add\n?model=<label>&caption=<short caption>). The still replaces any earlier\nstill on that paragraph and revision. No server image generation.","operationId":"create_scene_still","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSceneStillInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/start_writing":{"post":{"tags":["mcp"],"summary":"Start Writing","description":"Commit the current outline + cast and kick off chapter writing.\n\nThe single action that advances a story from 'reviewing' into\nwriting. Replaces the old two-step Apply-outline → Apply-cast\nflow: the review screen edits both together, and this endpoint\nstarts the writer regardless of which tab the user was on.","operationId":"start_writing","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCharactersInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoryMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/plan_revision":{"post":{"tags":["mcp"],"summary":"Plan Revision","description":"Produce a structured revision plan for the given chapter+instruction.\n\nReturns:\n  {\n    chapter: int,\n    editorial_summary: str,   # legacy field = plan.short_plan\n    plan: {                    # new structured payload\n      short_plan: str,         # chat-bubble text\n      long_plan: str,          # markdown: What's changing / Why / What stays\n      beats: [ ... ],          # ordered beats for the REVISED chapter\n      recommended_beat_review: [\n        # shortlist of high-risk beats to approve or regenerate before revise_chapter\n      ],\n      beat_review_guidance: str\n    }\n  }\n\nOld clients reading only `editorial_summary` keep working; new clients\ncan read `plan` and render the long plan + beats in an expander.","operationId":"plan_revision","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChapterChatInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/writer_thinking":{"post":{"tags":["mcp"],"summary":"Writer Thinking Endpoint","description":"Show the writer's approach before applying a chapter revision.\n\nDirect MCP form of the website's `start_chat_operation(kind=\"writer_thinking\")`.\nReturns rendered `editorial_summary` for human inspection plus compact\n`thinking` data that can be passed to `revise_chapter.writer_thinking`.\n\nClient path (authoring_mode='client' / server_llm=false):\n  - without client_thinking: no-LLM brief (contract + prompt + base_plan_hash)\n  - with client_thinking + base_plan_hash: commit client approach, no server LLM","operationId":"writer_thinking","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriterThinkingInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/rehearse_dialogue":{"post":{"tags":["mcp"],"summary":"Rehearse Dialogue","description":"Regenerate the dialogue-rehearsal packet for a planned chapter.","operationId":"rehearse_dialogue","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialogueRehearsalInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/refine_world":{"post":{"tags":["mcp"],"summary":"Refine World Endpoint","description":"Generate a refined world document from the conversation so far.\n\n  apply=false: returns reply.updated_world for preview.\n  apply=true: atomically commits.\n\nReturns {editorial_summary, reply.{short_reply, long_reply, updated_world}, applied}.","operationId":"refine_world","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefineWorldInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/update_world":{"post":{"tags":["mcp"],"summary":"Update World","description":"Low-level direct replacement of the world/setting doc.\n\nPrefer refine_world(apply=true) for conversational edits — this\nendpoint is for inline UI edits and programmatic overwrites.\nEmpty string is allowed (clears the doc).\n\nValid in any state. Edits made after writing has started apply\nto future revisions only — already-written chapter text is not\nretouched.","operationId":"update_world","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorldInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/revise_chapter":{"post":{"tags":["mcp"],"summary":"Revise Chapter","description":"Apply a chapter-scope revision plan and produce a new chapter revision.\n\nUse this when the requested change affects chapter structure: beat\norder, scene sequence, chapter goal, ending, whole-scene rebuilds, or\ncontinuity handoff. For major rewrites, call start_plan_revision or\nplan_revision first, inspect/refine the accepted plan, then pass the\nstructured_plan or plan_id here.\n\nReturns immediately with `{job_id, status: \"starting\", chapter,\nbase_revision, new_revision}`; the actual planner+writer+evaluator\nchain runs in the background. Poll progress via `get_revision_status`.\nPass `structured_plan` (from `plan_revision`) for best results;\n`editorial_plan` is the legacy free-text path. `base_revision`\ndefaults to the latest committed revision.","operationId":"revise_chapter","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseChapterInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/revise_chapter_from_notes":{"post":{"tags":["mcp"],"summary":"Revise Chapter From Notes","description":"Gather open chapter review notes and start a normal chapter revision.\n\nThis is a convenience bridge for Codex and the website: notes are\nstored on the chapter, gathered here, then fed through the existing\nrevise_chapter pipeline. Notes resolve only after the worker commits\na new chapter revision.","operationId":"revise_chapter_from_notes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseChapterFromNotesInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/revise_paragraph":{"post":{"tags":["mcp"],"summary":"Revise Paragraph","description":"Revise a single paragraph in-place. The user selects a paragraph by\nindex (0-based, split on double-newline) and provides a note describing\nthe desired change. Only the target paragraph is rewritten; the rest of\nthe chapter is preserved byte-for-byte. Use this for one paragraph that\nneeds reflow, voice, localized logic, or characterization. If adjacent\nparagraphs or a beat/scene range also need to change, use the selected\nparagraph chat/finalize/apply flow instead. Costs 1 credit.","operationId":"revise_paragraph","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseParagraphInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/paragraph_apply":{"post":{"tags":["mcp"],"summary":"Selected Paragraph Apply Plan","description":"Apply an approved selected-paragraph chat plan.\n\nProduct-facing replacement for the old note apply action. It uses a\ndedicated selected-paragraph segment writer: approved plan, cast/world,\nbeat description, and the target paragraphs only. Use it for scoped\nlocal prose work across one selected paragraph plus nearby paragraphs,\nor a small beat/scene range. If the range or intent is unclear, call\nget_selected_paragraph_context, continue_selected_paragraph_chat, and\nfinalize_selected_paragraph_chat first; if the user already supplied a\nclear range and final plan, pass force_range directly here.","operationId":"paragraph_apply","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectedParagraphApplyPlanInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/paragraph_undo":{"post":{"tags":["mcp"],"summary":"Selected Paragraph Undo","description":"Restore specific paragraphs to a client-provided snapshot.\n\nPure DB write — no LLM call. The client snapshots the\npre-apply paragraphs before calling selected_paragraph_apply_plan; if\nthe user dislikes the result, the snapshot comes back here and we write\nit into the chapter's latest revision in-place. Costs 0 credits (free\nundo).","operationId":"paragraph_undo","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectedParagraphUndoInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp/delete_revision":{"post":{"tags":["mcp"],"summary":"Delete Revision","description":"Delete a specific revision of a chapter.\n\nRemaining revisions are renumbered sequentially from 1 (with\nmatching `v0`, `v1`, … labels). The original chapter text — the\nbaseline before any revisions — is never deletable through this\npath. Irreversible.","operationId":"delete_revision","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRevisionInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp_tokens":{"get":{"tags":["mcp-token-management"],"summary":"List Mcp Tokens","operationId":"list_mcp_tokens","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["mcp-token-management"],"summary":"Create Mcp Token","operationId":"create_mcp_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpTokenInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mcp_tokens/{token_id}":{"delete":{"tags":["mcp-token-management"],"summary":"Revoke Mcp Token","operationId":"revoke_mcp_token","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/account/delete":{"post":{"summary":"Delete Account","operationId":"delete_account_api_account_delete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Delete Account Api Account Delete Post"}}}}}}},"/api/billing/credits":{"get":{"summary":"Billing Credits","operationId":"billing_credits_api_billing_credits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/checkout-subscription":{"post":{"summary":"Billing Checkout Subscription","operationId":"billing_checkout_subscription_api_billing_checkout_subscription_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/sync":{"post":{"summary":"Billing Sync","operationId":"billing_sync_api_billing_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/app-store/sync":{"post":{"summary":"Billing App Store Sync","description":"Re-read RevenueCat for the signed-in iOS user and return their tier.\n\nThe client may send its current RevenueCat customerInfo as diagnostic\ncontext, but the server does not trust it for access or identity:\nmcp-core looks up the signed-in account's own RevenueCat id (the Logto\nsubject) with the server-side secret and stores ``store_subscription``.","operationId":"billing_app_store_sync_api_billing_app_store_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/billing/portal":{"get":{"summary":"Billing Portal Get","operationId":"billing_portal_get_api_billing_portal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Billing Portal Post","operationId":"billing_portal_post_api_billing_portal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/register":{"post":{"summary":"Oauth Register","operationId":"oauth_register_oauth_register_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/authorize":{"get":{"summary":"Logto Authorize Proxy","operationId":"logto_authorize_proxy_oauth_authorize_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/oauth/token":{"post":{"summary":"Logto Token Proxy","operationId":"logto_token_proxy_oauth_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"summary":"Logto Metadata Proxy","operationId":"logto_metadata_proxy__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/stripe/webhook":{"post":{"summary":"Stripe Webhook","operationId":"stripe_webhook_api_stripe_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"summary":"Oauth Metadata","operationId":"oauth_metadata__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ActivityResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"entries":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Entries"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"}},"additionalProperties":true,"type":"object","title":"ActivityResponse"},"ApplyCharactersInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override for chapter generation."},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Per-chapter word target override applied to the writer."}},"type":"object","required":["job_id"],"title":"ApplyCharactersInput"},"ArticleNoteInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"note_id":{"type":"string","minLength":1,"title":"Note Id","description":"Article review note id."}},"type":"object","required":["job_id","note_id"],"title":"ArticleNoteInput"},"AssetConstraintsInput":{"properties":{"required":{"items":{"type":"string"},"type":"array","title":"Required","description":"Elements that must appear."},"avoid":{"items":{"type":"string"},"type":"array","title":"Avoid","description":"Elements that should not appear."},"forbidden_text":{"items":{"type":"string"},"type":"array","title":"Forbidden Text","description":"Placeholder or banned words to avoid."},"safe_zone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safe Zone","description":"Safe-zone or crop guidance."}},"type":"object","title":"AssetConstraintsInput"},"AssetContentInput":{"properties":{"primary_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Text","description":"Required title, headline, or text to include."},"secondary_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secondary Text","description":"Optional supporting text."},"brand_or_creator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Or Creator","description":"Optional creator name, imprint, or brand."},"description":{"type":"string","minLength":3,"title":"Description","description":"What the asset should depict."}},"type":"object","required":["description"],"title":"AssetContentInput"},"AssetFormatInput":{"properties":{"aspect_ratio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Aspect Ratio","description":"Target aspect ratio, such as 2:3, 1:1, or 16:9.","default":"2:3"},"width":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Width","description":"Optional target width in pixels."},"height":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":1.0},{"type":"null"}],"title":"Height","description":"Optional target height in pixels."},"transparent_background":{"type":"boolean","title":"Transparent Background","description":"Whether the asset should use a transparent background.","default":false}},"type":"object","title":"AssetFormatInput"},"AssetGenerationOptionsInput":{"properties":{"variant_count":{"type":"integer","maximum":4.0,"minimum":1.0,"title":"Variant Count","description":"Number of variants to request.","default":1},"variants":{"items":{"type":"string"},"type":"array","title":"Variants","description":"Optional explicit variant labels."},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Id","description":"Optional pinned DesignForYou template id."},"template_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Category","description":"Optional category filter for recommendation."},"template_subcategory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Subcategory","description":"Optional subcategory filter for recommendation."},"quality":{"type":"string","title":"Quality","description":"Requested quality tier: fast, standard, or high.","default":"standard"},"context_ids":{"items":{"type":"string"},"type":"array","title":"Context Ids","description":"Prior DesignForYou design ids for visual context."},"context_labels":{"items":{"type":"string"},"type":"array","title":"Context Labels","description":"Optional human labels for each context_id, in the SAME order. When the edit routes to a multi-reference model (gpt-image-2), DesignForYou appends an ordered legend ('reference 1 = <label>, ...') so the model binds each named subject to its own reference image instead of blending identities."},"skip_prompt_merge":{"type":"boolean","title":"Skip Prompt Merge","description":"Skip DesignForYou's smart prompt-merge (which compresses to ~150 words) and send the description verbatim. Set for prompts that are already complete and precise — e.g. a multi-character cover where each subject's outfit + reference legend must survive.","default":false},"scene_prompt_final":{"type":"boolean","title":"Scene Prompt Final","description":"Scene-stills only: content.description is already the planned, user-editable shot prompt and should be sent through without running the scene prompt planner again.","default":false},"client_prompt_final":{"type":"boolean","title":"Client Prompt Final","description":"Scene-stills only: the prompt was supplied directly by the client and must be passed to the local provider verbatim without adding a server style preamble.","default":false},"prompt_passthrough":{"type":"boolean","title":"Prompt Passthrough","description":"Internal Writer flag for an already-final prompt. When true, preserve the description without planner rewriting or whitespace normalization before the downstream call.","default":false},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id","description":"Prior DesignForYou session id to refine."},"edit_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Edit Tier","description":"Edit tier: fast, pro, or expert (expert routes refs to gpt-image-2 edit)."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Optional DesignForYou image model override, such as grok-imagine-image-quality, gpt-image-2, minimax-h3-image-balanced, or minimax-h3-image-quality."},"provider":{"anyOf":[{"type":"string","enum":["grok_cli","minimax_h3"]},{"type":"null"}],"title":"Provider","description":"Explicit image provider. 'grok_cli' runs the signed-in local Grok Build CLI and returns a durable S3 URL plus a local data URL for paragraph scene stills and single paragraph images; 'minimax_h3' is forwarded to DesignForYou's hosted MiniMax H3 image model for scene stills. Hosted DesignForYou remains the default."},"reference_urls":{"items":{"type":"string"},"type":"array","title":"Reference Urls","description":"Resolved visual reference image URLs for local providers. Writer can populate this from saved character-sheet and location references or accept client-supplied references directly."},"reference_labels":{"items":{"type":"string"},"type":"array","title":"Reference Labels","description":"Optional ordered labels aligned with reference_urls for local Grok CLI binding. Internal generation metadata; optional/defaulted for compatibility."},"reference_roles":{"items":{"type":"string","enum":["identity","style","location","composition"]},"type":"array","title":"Reference Roles","description":"Optional ordered roles aligned with reference_urls: identity, style, location, or composition. Internal generation metadata; optional/defaulted for compatibility."},"reference_sources":{"items":{"type":"string"},"type":"array","title":"Reference Sources","description":"Optional ordered sources aligned with reference_urls (client, cast, location). Internal generation metadata for diagnostics."},"reference_warnings":{"items":{"type":"string"},"type":"array","title":"Reference Warnings","description":"Optional diagnostic warnings collected while sanitizing references (e.g. duplicate URLs)."},"style_lock":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Style Lock","description":"Optional rendering style lock text forwarded to the local Grok paragraph-image path."},"style_lock_mode":{"anyOf":[{"type":"string","enum":["auto","client","none"]},{"type":"null"}],"title":"Style Lock Mode","description":"How style_lock was chosen: auto (Writer default), client (supplied), or none (disabled)."},"frame_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Frame Mode","description":"Optional local-provider frame contract, e.g. single_full_bleed for paragraph images."},"reference_subject_free":{"items":{"type":"boolean"},"type":"array","title":"Reference Subject Free","description":"Optional ordered flags aligned with reference_urls. A true value declares that a style reference contains no people or character subjects."}},"type":"object","title":"AssetGenerationOptionsInput"},"AssetMetadataInput":{"properties":{"downstream_user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Downstream User","description":"Optional already-opaque downstream user id."},"downstream_project":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Downstream Project","description":"Optional downstream project/story id; Writer hashes it before sending."}},"type":"object","title":"AssetMetadataInput"},"AssetVisualDirectionInput":{"properties":{"genre_or_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Genre Or Category","description":"Optional category, genre, or shelf signal."},"style":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Style","description":"Visual style direction."},"mood":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mood","description":"Tone or emotional feel."},"palette":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Palette","description":"Palette hint."},"motifs":{"items":{"type":"string"},"type":"array","title":"Motifs","description":"Recurring visual motifs to consider."}},"type":"object","title":"AssetVisualDirectionInput"},"AttachArticleResearchInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"research_brief":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Research Brief","description":"Research handoff from Codex/Claude to the article writer. Prefer a single plain text or Markdown string whose authored format should be preserved by the website: one summary paragraph, bullets when useful, and source links inline. A legacy object is accepted for compatibility."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to store the research and return a no-server-LLM drafting brief, or to commit client-authored Markdown when text is supplied."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Hash returned by the client drafting brief; required when submitting client-authored text."},"text":{"anyOf":[{"type":"string","minLength":20},{"type":"null"}],"title":"Text","description":"Client-authored full article Markdown to commit in client mode."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client article drafts.","default":"client-article-draft/v1"}},"type":"object","required":["job_id"],"title":"AttachArticleResearchInput"},"BeatMapUpdateInput":{"properties":{"semantic_impact":{"type":"string","enum":["none","same_beat","changed_beats"],"title":"Semantic Impact","description":"none/same_beat = mechanical range shift when wholly inside one entry; changed_beats = require replacement_entries or the map becomes stale.","default":"changed_beats"},"replacement_entries":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Replacement Entries","description":"Validated as-written entries covering the resulting edited range when semantic_impact is changed_beats."}},"type":"object","title":"BeatMapUpdateInput","description":"Optional as-written map patch for in-place prose mutations."},"BillingPortalResponse":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}},"additionalProperties":true,"type":"object","title":"BillingPortalResponse"},"ChapterChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"message":{"type":"string","minLength":1,"title":"Message","description":"User message — question, brainstorm, or revision instruction."},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages","description":"Conversation history."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override."},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision","description":"Which revision to use as context. None = latest."},"use_story_tool":{"type":"boolean","title":"Use Story Tool","description":"If true, run the chat as an agentic tool-use loop so the model can call the story-query tool (semantic search / read by address) over the whole story mid-conversation. Live models only; default false.","default":false},"target_words":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words","description":"Target word count for the revised chapter. The planner uses this to size beats appropriately — without it, the planner defaults to the base chapter's current length, which produces beats that are too small when the user wants a meaningfully longer rewrite."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to have plan_revision return a no-LLM planning brief or commit client_plan."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"client_plan":{"anyOf":[{"$ref":"#/components/schemas/ClientRevisionPlanInput"},{"type":"null"}],"description":"Client-authored structured revision plan to commit through plan_revision in client mode. Beats require summary, details, and type. Summaries should form the chapter's main event outline; details add local context or expected beat content. Do not include para_range or target_words."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Hash returned by the no-LLM plan_revision brief; required when submitting client_plan."},"scope":{"type":"string","enum":["chapter","paragraph","range"],"title":"Scope","description":"Client revision-planning scope.","default":"chapter"},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"0-based paragraph index for client paragraph-scope revision planning."},"paragraph_range":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Paragraph Range","description":"0-based inclusive [start, end] paragraph range for client range-scope revision planning."},"include_full_text":{"type":"boolean","title":"Include Full Text","description":"Client mode only: include full current chapter text in the planning brief instead of the compact context excerpt.","default":false},"revision_mode":{"anyOf":[{"type":"string","enum":["surgical","scene_rewrite","full_rewrite"]},{"type":"null"}],"title":"Revision Mode","description":"Client-declared revision mode for client_plan provenance."},"plan_purpose":{"anyOf":[{"type":"string","enum":["revision","as_written_rebaseline"]},{"type":"null"}],"title":"Plan Purpose","description":"Purpose of a submitted client revision plan.","default":"revision"},"supersedes_plan_id":{"anyOf":[{"type":"string","minLength":3},{"type":"null"}],"title":"Supersedes Plan Id","description":"Prior immutable plan artifact superseded by this rebaseline."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client_plan artifacts.","default":"client-revision-plan/v1"},"auto_save":{"type":"boolean","title":"Auto Save","description":"If true (default), the server appends user+assistant turns to the chapter's chat history so get_chat returns them next call. Chat clients that manage history themselves can pass false.","default":true},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Client-supplied idempotency key. If the same id is sent again within the cache TTL, the server returns the original response without re-running the LLM. Lets mobile clients retry a backgrounded request without losing the reply or spending the model call again."}},"type":"object","required":["job_id","chapter","message"],"title":"ChapterChatInput"},"CharacterChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message"},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Idempotency key — see ChapterChatInput.request_id."}},"type":"object","required":["job_id","message"],"title":"CharacterChatInput"},"ChatHistoryInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":0.0,"title":"Chapter"},"revision":{"type":"integer","minimum":0.0,"title":"Revision","description":"Revision number. 0 = general chapter chat.","default":0},"slot":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slot","description":"Optional non-chapter chat slot, e.g. selected paragraph thread."}},"type":"object","required":["job_id","chapter"],"title":"ChatHistoryInput"},"CheckoutResponse":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"additionalProperties":true,"type":"object","title":"CheckoutResponse"},"ClientInitialChapterBeatInput":{"properties":{"num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num","description":"1-based beat number in first-draft chapter order."},"index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Index","description":"Compatibility alias for num."},"summary":{"type":"string","title":"Summary","description":"Main event of this beat. Reading all summaries in order should cover the chapter's main things that happen. Use a specific event sentence, not a vague location/title."},"details":{"type":"string","title":"Details","description":"Beat-level elaboration: local context, concrete inclusions, emphasis, action/dialogue texture, or constraints specific to this beat. This is not full prose and not generic style coaching."},"type":{"type":"string","enum":["scene_break","action","revelation","decision","dialogue","reflection","explicit"],"title":"Type","description":"Dominant movement category for this beat's main event."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Compatibility alias for summary."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Compatibility alias for details."},"category":{"anyOf":[{"type":"string","enum":["scene_break","action","revelation","decision","dialogue","reflection","explicit"]},{"type":"null"}],"title":"Category","description":"Compatibility alias for type."},"change":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change","description":"Optional compatibility field for the beat's change."},"story_function":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Function","description":"Optional note on why this beat matters in the chapter sequence."},"budget_action":{"anyOf":[{"type":"string","enum":["bridge","compress","expand","preserve"]},{"type":"null"}],"title":"Budget Action","description":"Optional qualitative budget action. Do not include per-beat target_words."},"budget_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Note","description":"Optional qualitative budget guidance. Do not include word-count budgets."},"characters":{"items":{"type":"string"},"type":"array","title":"Characters","description":"Optional character names present in this beat."}},"additionalProperties":true,"type":"object","required":["summary","details","type"],"title":"ClientInitialChapterBeatInput"},"ClientInitialChapterPlanInput":{"properties":{"short_plan":{"type":"string","title":"Short Plan","description":"Concise user-facing first-draft chapter plan summary."},"long_plan":{"type":"string","title":"Long Plan","description":"Detailed writer-facing first-draft chapter plan."},"beats":{"items":{"$ref":"#/components/schemas/ClientInitialChapterBeatInput"},"type":"array","minItems":1,"title":"Beats","description":"Ordered beats for the first-draft chapter. Beat summaries should read as the chapter's main event outline; details add local beat-specific material only."}},"additionalProperties":true,"type":"object","required":["short_plan","long_plan","beats"],"title":"ClientInitialChapterPlanInput"},"ClientRevisionBeatInput":{"properties":{"num":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num","description":"1-based beat number in revised chapter order."},"index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Index","description":"Compatibility alias for num."},"summary":{"type":"string","title":"Summary","description":"Main event of this beat, written as part of the chapter outline. If all beat summaries are read in order, they should cover the chapter's main things that happen. Use a specific event sentence, not a vague location/title such as 'Character in bedroom'. Each beat should have a unique story function or state change, not merely repeat mood, desire, risk, or setting."},"details":{"type":"string","title":"Details","description":"Beat-level elaboration: local context, concrete inclusions, emphasis, action/dialogue texture, or constraints specific to this beat. This is not full prose and not meta advice about style; it states what the beat should contain beyond the summary. For explicit adult beats, include the specific physical/logistical/camera/clothing continuity the writer must render."},"type":{"type":"string","enum":["scene_break","action","revelation","decision","dialogue","reflection","explicit"],"title":"Type","description":"Dominant movement category for this beat's main event."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Compatibility alias for summary."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Compatibility alias for details."},"category":{"anyOf":[{"type":"string","enum":["scene_break","action","revelation","decision","dialogue","reflection","explicit"]},{"type":"null"}],"title":"Category","description":"Compatibility alias for type."},"change":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change","description":"Compatibility field for the requested change in this beat."},"story_function":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Function","description":"Optional note on why this beat matters in the chapter sequence."},"budget_action":{"anyOf":[{"type":"string","enum":["bridge","compress","expand","preserve"]},{"type":"null"}],"title":"Budget Action","description":"Optional qualitative budget action. Do not include per-beat target_words."},"budget_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Note","description":"Optional qualitative budget guidance. Do not include word-count budgets."},"characters":{"items":{"type":"string"},"type":"array","title":"Characters","description":"Optional character names present in this beat."}},"type":"object","required":["summary","details","type"],"title":"ClientRevisionBeatInput"},"ClientRevisionPlanInput":{"properties":{"short_plan":{"type":"string","title":"Short Plan","description":"Concise user-facing plan summary."},"long_plan":{"type":"string","title":"Long Plan","description":"Detailed writer-facing revision plan."},"revision_mode":{"anyOf":[{"type":"string","enum":["surgical","scene_rewrite","full_rewrite"]},{"type":"null"}],"title":"Revision Mode"},"beats":{"items":{"$ref":"#/components/schemas/ClientRevisionBeatInput"},"type":"array","minItems":1,"title":"Beats","description":"Ordered beats for the revised chapter. The summaries should read as the chapter's main event outline; details add local beat-specific material only."}},"type":"object","required":["short_plan","long_plan","beats"],"title":"ClientRevisionPlanInput"},"CreateCharacterReferenceInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"character_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Character Index","description":"0-based cast index. Required unless character_name uniquely matches one cast member."},"character_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Character Name","description":"Cast member name. Resolves character_index and guards against cast changes."},"asset_type":{"type":"string","enum":["character_sheet","concept_art"],"title":"Asset Type","description":"character_sheet = the full reference image scene stills use for identity; concept_art = a portrait.","default":"character_sheet"}},"type":"object","required":["job_id"],"title":"CreateCharacterReferenceInput","description":"Brief + upload URL for one cast member's client-generated reference image."},"CreateMcpTokenInput":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"Human-readable token label shown in the WriteForYou MCP token list.","default":"Codex WriteForYou MCP"},"expires_in_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Expires In Days","description":"Optional token lifetime in days. Omit for the server default."}},"type":"object","title":"CreateMcpTokenInput"},"CreateSceneStillInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number that owns the paragraph."},"paragraph_index":{"type":"integer","minimum":0.0,"title":"Paragraph Index","description":"0-based paragraph index within the chapter text (blank-line separated)."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Chapter revision whose text to illustrate; omit for the current text."},"character_names":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Character Names","description":"Cast in the shot (full or first names, max 3). Omit to use the cast members named in the paragraph."}},"type":"object","required":["job_id","chapter","paragraph_index"],"title":"CreateSceneStillInput","description":"Brief + upload URL for one paragraph's client-generated scene still."},"DeleteChapterNoteInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number the review note belongs to."},"note_id":{"type":"string","minLength":3,"title":"Note Id","description":"Open chapter review note id to delete."},"initial_plan_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Initial Plan Id","description":"Optional initial chapter plan id when deleting a note from an unwritten chapter plan."}},"type":"object","required":["job_id","chapter","note_id"],"title":"DeleteChapterNoteInput"},"DeleteLocationReferenceInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"location_reference_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Reference Id","description":"Stable Writer location reference id to delete."},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name","description":"Location name to delete when id is not known."},"design_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Design Id","description":"D4U design id to delete when id/name are not known."}},"type":"object","required":["job_id"],"title":"DeleteLocationReferenceInput"},"DeleteRevisionInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"revision":{"type":"integer","minimum":2.0,"title":"Revision","description":"Revision number to delete (cannot delete revision 1 / original)."}},"type":"object","required":["job_id","chapter","revision"],"title":"DeleteRevisionInput"},"DeletedResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"}},"additionalProperties":true,"type":"object","title":"DeletedResponse"},"DialogueRehearsalInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"plan":{"additionalProperties":true,"type":"object","title":"Plan","description":"Structured revision plan (short_plan, long_plan, beats) whose dialogue beats to rehearse."},"chapter_strategy":{"type":"string","title":"Chapter Strategy","description":"Chapter strategy paragraph from the writer-thinking preview, if available.","default":""},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override."},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision","description":"Base revision (operation scoping only)."}},"type":"object","required":["job_id","chapter","plan"],"title":"DialogueRehearsalInput","description":"Input for regenerating only the dialogue-rehearsal packet of a\nwriter-thinking preview, without re-running the other stages."},"EmptyInput":{"properties":{},"type":"object","title":"EmptyInput"},"GenerateAssetInput":{"properties":{"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Optional idempotency/correlation id. Writer creates one if omitted."},"asset_kind":{"type":"string","title":"Asset Kind","description":"cover, poster, icon, social_post, screenshot, character, background, diagram, or other.","default":"cover"},"use_case":{"type":"string","minLength":5,"title":"Use Case","description":"Short natural-language summary of why the asset is needed."},"audience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audience","description":"Optional target audience."},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform","description":"Optional publishing target."},"format":{"$ref":"#/components/schemas/AssetFormatInput"},"content":{"$ref":"#/components/schemas/AssetContentInput"},"visual_direction":{"$ref":"#/components/schemas/AssetVisualDirectionInput"},"constraints":{"$ref":"#/components/schemas/AssetConstraintsInput"},"generation":{"$ref":"#/components/schemas/AssetGenerationOptionsInput"},"metadata":{"$ref":"#/components/schemas/AssetMetadataInput"}},"type":"object","required":["use_case","content"],"title":"GenerateAssetInput"},"GenerateChapterCoverInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job id."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"1-based chapter number to cover."}},"type":"object","required":["job_id","chapter"],"title":"GenerateChapterCoverInput"},"GenerateStoryInput":{"properties":{"premise":{"type":"string","minLength":5,"title":"Premise","description":"The premise for the new story."},"chapter_count":{"type":"integer","maximum":12.0,"minimum":1.0,"title":"Chapter Count","description":"The number of chapters to generate."},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Target word count per chapter."},"nsfw":{"type":"boolean","title":"Nsfw","description":"Content-rating metadata; does not override client safety policies.","default":false},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override (e.g. 'grok-4')."},"auto_approve":{"type":"boolean","title":"Auto Approve","description":"If true, skip the review stage: the planner auto-chains into characterizer and directly into the chapter writer. Removes the need for a follow-up start_writing call when you don't want to review or edit the outline/cast first. Job settles at 'completed' on success.","default":false}},"type":"object","required":["premise","chapter_count"],"title":"GenerateStoryInput"},"GenerateWriterSceneStillInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number containing the selected paragraph."},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"Optional 0-based paragraph index; required when persist=true."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Displayed chapter revision number, if available."},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt","description":"Optional final scene prompt. When supplied, this is authoritative and is sent without Writer planner rewriting or prompt merging."},"character_names":{"items":{"type":"string"},"type":"array","title":"Character Names","description":"Optional cast names. When omitted, Writer resolves cast references automatically."},"reference_urls":{"items":{"type":"string"},"type":"array","title":"Reference Urls","description":"Optional direct reference image URLs. Supplied references override automatic cast references."},"reference_labels":{"items":{"type":"string"},"type":"array","title":"Reference Labels","description":"Optional labels aligned with reference_urls."},"location_design_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Design Id","description":"Optional D4U location design id."},"location_reference_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Reference Id","description":"Optional saved Writer location reference id."},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name","description":"Optional saved location name to resolve."},"location_label":{"type":"string","title":"Location Label","description":"Reference binding label for location_design_id.","default":"Location reference: fixed story location set"},"quality":{"type":"string","enum":["balanced","quality"],"title":"Quality","description":"MiniMax H3 quality profile. Defaults to quality.","default":"quality"},"execution":{"type":"string","enum":["hosted","grok_cli"],"title":"Execution","description":"Image execution path. 'hosted' uses DesignForYou; 'grok_cli' uses the signed-in local Grok Build CLI.","default":"hosted"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Optional image model override. Hosted defaults to the MiniMax H3 model selected by quality; grok_cli defaults to grok-imagine-image-quality."},"persist":{"type":"boolean","title":"Persist","description":"Attach the generated still to the selected paragraph only after successful generation.","default":false},"wait":{"type":"boolean","title":"Wait","description":"Wait for the in-process asset job to finish before returning.","default":true},"wait_timeout_seconds":{"type":"number","maximum":300.0,"exclusiveMinimum":0.0,"title":"Wait Timeout Seconds","description":"Maximum nonblocking wait for the in-process asset job.","default":180.0}},"additionalProperties":false,"type":"object","required":["job_id","chapter"],"title":"GenerateWriterSceneStillInput","description":"Simplified Writer operation for one single-frame scene still."},"GenericToolResponse":{"properties":{"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"},"article_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Article Url"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"is_terminal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Terminal"}},"additionalProperties":true,"type":"object","title":"GenericToolResponse","description":"Fallback for tools whose payload is still being tightened."},"GetActivityInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"},"limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Limit","default":100}},"type":"object","required":["job_id"],"title":"GetActivityInput"},"GetChapterTextResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"chapter":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chapter"},"revision":{"anyOf":[{},{"type":"null"}],"title":"Revision"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"word_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Word Count"},"segment_breaks":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Segment Breaks"},"paragraphs":{"anyOf":[{"items":{"$ref":"#/components/schemas/Paragraph"},"type":"array"},{"type":"null"}],"title":"Paragraphs"}},"additionalProperties":true,"type":"object","title":"GetChapterTextResponse"},"GetChatResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"messages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Messages"},"chat":{"anyOf":[{},{"type":"null"}],"title":"Chat"}},"additionalProperties":true,"type":"object","title":"GetChatResponse"},"GetCreditsResponse":{"properties":{"identity":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Identity"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"plans":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plans"},"entitlement":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Entitlement"},"credit_accounting":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Credit Accounting"},"subscription":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Subscription"},"can_generate_images":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Can Generate Images"},"can_write_articles":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Can Write Articles"},"can_use_pro_experimental":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Can Use Pro Experimental"},"can_use_smart_client_authoring":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Can Use Smart Client Authoring"},"can_use_server_llm_authoring":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Can Use Server Llm Authoring"}},"additionalProperties":true,"type":"object","title":"GetCreditsResponse"},"GetRevisionBeatsInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Revision number. Omit for latest revision."}},"type":"object","required":["job_id","chapter"],"title":"GetRevisionBeatsInput"},"GetRevisionBeatsResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"chapter":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chapter"},"revision":{"anyOf":[{},{"type":"null"}],"title":"Revision"},"beats":{"anyOf":[{},{"type":"null"}],"title":"Beats"},"as_written":{"anyOf":[{},{"type":"null"}],"title":"As Written"}},"additionalProperties":true,"type":"object","title":"GetRevisionBeatsResponse"},"GetStoryInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"version":{"type":"integer","minimum":1.0,"title":"Version","description":"DEPRECATED — stories no longer have a version axis. Ignored; accepted for back-compat.","default":1},"chapter":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Chapter","description":"If provided, only that chapter's text is returned; other chapters come back with text='' so the UI can render the chapter list but pay the network/DB cost only for what's shown. Omit to get full text for every chapter (legacy behavior)."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Fetch text from a specific revision of `chapter` (requires `chapter` to be set). Lets callers compare prior revisions inline without a separate get_chapter_text call. Omit for the latest revision (default)."},"mode":{"type":"string","title":"Mode","description":"'editor' (default) returns the full artifact — plan, cast, ledgers, chapters. 'reader' returns only title, synopsis, chapters[].text|title|word_count, total_word_count, story_url — the minimum for a chat client to present the prose to a user without wading through editor metadata. 'metadata' returns status, chapter counts, word counts, plan metadata, generation params, and progress-log tail without chapter prose.","default":"editor"},"siblings":{"type":"boolean","title":"Siblings","description":"When `chapter` is set, controls whether the other chapters come back with metadata (summary, revisions[]). Default true for UI compatibility. Set false to strip non-requested chapters entirely — cheapest get_story possible.","default":true}},"type":"object","required":["job_id"],"title":"GetStoryInput"},"GetStoryResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"premise":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Premise"},"plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plan"},"chapters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Chapters"},"is_terminal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Terminal"}},"additionalProperties":true,"type":"object","title":"GetStoryResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."}},"type":"object","required":["job_id"],"title":"JobInput"},"JobStatusInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"kind":{"type":"string","title":"Kind","description":"Which job family to probe: story | revision | chat_operation | asset | chapter_cover | cover_image | article. `job_id` is the id of that family (story id, asset job id, cover_job_id, operation_id, or article id).","default":"story"},"include_debug":{"type":"boolean","title":"Include Debug","description":"Include noisy revision debug fields when kind=revision.","default":false}},"type":"object","required":["job_id"],"title":"JobStatusInput"},"JobStatusResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"current_step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Step"},"revision_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revision Status"},"chapters_done":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chapters Done"},"chapter_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chapter Count"},"is_terminal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Terminal"},"timed_out":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Timed Out"},"requested_timeout_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Requested Timeout Seconds"},"effective_timeout_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Effective Timeout Seconds"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"},"article_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Article Url"},"result":{"anyOf":[{},{"type":"null"}],"title":"Result"},"error":{"anyOf":[{},{"type":"null"}],"title":"Error"},"progress":{"anyOf":[{},{"type":"null"}],"title":"Progress"},"current_segment":{"anyOf":[{},{"type":"null"}],"title":"Current Segment"},"segment_events_tail":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Segment Events Tail"}},"additionalProperties":true,"type":"object","title":"JobStatusResponse"},"ListArticlesResponse":{"properties":{"articles":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Articles"}},"additionalProperties":true,"type":"object","title":"ListArticlesResponse"},"ListLocationReferencesInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"include_prompts":{"type":"boolean","title":"Include Prompts","description":"Include saved prompt text for each location reference.","default":true}},"type":"object","required":["job_id"],"title":"ListLocationReferencesInput"},"ListModelsResponse":{"properties":{"models":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Models"}},"additionalProperties":true,"type":"object","title":"ListModelsResponse"},"ListStoriesResponse":{"properties":{"stories":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Stories"}},"additionalProperties":true,"type":"object","title":"ListStoriesResponse"},"LocationReferencesResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"locations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Locations"},"references":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"References"}},"additionalProperties":true,"type":"object","title":"LocationReferencesResponse"},"OutlineChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message"},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Idempotency key — see ChapterChatInput.request_id."}},"type":"object","required":["job_id","message"],"title":"OutlineChatInput"},"Paragraph":{"properties":{"index":{"type":"integer","title":"Index"},"text":{"type":"string","title":"Text"},"hash":{"type":"string","title":"Hash"}},"additionalProperties":true,"type":"object","required":["index","text","hash"],"title":"Paragraph"},"PlanChapterInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Unwritten chapter number to plan."},"message":{"type":"string","minLength":1,"title":"Message","description":"Planning instruction for the initial chapter plan.","default":"Create an initial chapter beat plan for this unwritten chapter."},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages","description":"Complete chapter planning chat transcript to use when generating the beat plan."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override for server-side planning."},"target_words":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words","description":"Target word count for the future chapter."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to return a no-LLM planning brief or commit client_plan without server LLM usage."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"client_plan":{"anyOf":[{"$ref":"#/components/schemas/ClientInitialChapterPlanInput"},{"type":"null"}],"description":"Client-authored initial chapter plan to store as a versioned artifact."},"select":{"type":"boolean","title":"Select","description":"When storing a plan, make it the selected initial plan consumed by write_chapter.","default":true},"notes":{"items":{"type":"string"},"type":"array","title":"Notes","description":"Optional comments/notes to attach to this initial chapter plan artifact."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client_plan artifacts.","default":"client-initial-chapter-plan/v1"},"auto_save":{"type":"boolean","title":"Auto Save","description":"Reserved for future chapter-plan chat persistence. Currently ignored.","default":false},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Optional idempotency key for clients."}},"type":"object","required":["job_id","chapter"],"title":"PlanChapterInput"},"PlanMessage":{"properties":{"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content","default":""},"plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plan"},"cover":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cover"},"writer_thinking":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Writer Thinking"},"writer_thinking_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Writer Thinking Data"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"applied_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied At"},"applied_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Applied Revision"},"applied_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied Status"}},"type":"object","required":["role"],"title":"PlanMessage"},"PlanStoryInput":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id","description":"Client-authoring continuation id. Omit to create a new story shell; include when submitting client_plan."},"premise":{"type":"string","minLength":5,"title":"Premise","description":"The premise for the new story."},"chapter_count":{"type":"integer","maximum":12.0,"minimum":1.0,"title":"Chapter Count","description":"The number of chapters to outline."},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Target word count per chapter (used by the writer later)."},"nsfw":{"type":"boolean","title":"Nsfw","description":"Content-rating metadata; does not override client safety policies.","default":false},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override (e.g. 'grok-4')."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to use the caller's own model/knowledge; the server returns a skill-equivalent planning brief or commits client_plan without server LLM usage."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"client_plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Client Plan","description":"Client-authored story plan to commit through plan_story in client mode."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client_plan artifacts.","default":"client-story-plan/v1"}},"type":"object","required":["premise","chapter_count"],"title":"PlanStoryInput","description":"Input for the standalone `plan_story` MCP tool.\n\nMirrors GenerateStoryInput minus auto_approve. In client mode, the same\ntool also returns/commits no-server-LLM planning artifacts."},"PreparePublishDraftInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"destination":{"type":"string","title":"Destination","description":"Draft-only publishing destination label.","default":"Dev.to draft"}},"type":"object","required":["job_id"],"title":"PreparePublishDraftInput"},"PublishArticleDraftInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."}},"type":"object","required":["job_id"],"title":"PublishArticleDraftInput"},"QueryStoryInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job id."},"question":{"type":"string","minLength":1,"title":"Question","description":"Natural-language question about the story's text."},"k":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"K","description":"How many passages to return.","default":5},"chapter":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Chapter","description":"Narrow the search to one chapter; omit for whole story."}},"type":"object","required":["job_id","question"],"title":"QueryStoryInput"},"QueryStoryResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"answer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Answer"},"citations":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Citations"},"matches":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Matches"}},"additionalProperties":true,"type":"object","title":"QueryStoryResponse"},"ReadStoryInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job id."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"1-based chapter number."},"para_start":{"type":"integer","minimum":0.0,"title":"Para Start","description":"0-based first paragraph (inclusive).","default":0},"para_end":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Para End","description":"0-based last paragraph (inclusive); omit for end of chapter."}},"type":"object","required":["job_id","chapter"],"title":"ReadStoryInput"},"ReadStoryResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"chapters":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Chapters"},"spans":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Spans"}},"additionalProperties":true,"type":"object","title":"ReadStoryResponse"},"RefineCharactersInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message"},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"apply":{"type":"boolean","title":"Apply","description":"If true, atomically commit the refined cast (like calling update_characters with the returned cast in one step).","default":false}},"type":"object","required":["job_id","message"],"title":"RefineCharactersInput"},"RefineOutlineInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message","description":"Synthesis instruction (often 'Based on our conversation, update the outline')."},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages","description":"Full outline-level conversation for context."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"apply":{"type":"boolean","title":"Apply","description":"If true, atomically commit the refined plan (like calling update_outline with the returned plan in one step). Avoids the refine→serialize→update round-trip that risks plan drift from re-serialization.","default":false},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Optional length override applied when apply=true. Updates the writer's per-chapter target so subsequent chapter generation sizes accordingly. Omit to leave unchanged — there is no other way to edit target length mid-review."}},"type":"object","required":["job_id","message"],"title":"RefineOutlineInput"},"RefineWorldInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message"},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"apply":{"type":"boolean","title":"Apply","default":false}},"type":"object","required":["job_id","message"],"title":"RefineWorldInput"},"RefreshChapterContextInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter whose continuity context should be regenerated."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Optional revision to refresh. None = latest."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Optional model override for continuity extraction."}},"type":"object","required":["job_id","chapter"],"title":"RefreshChapterContextInput"},"ReviseArticleFromNotesInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"note_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Note Ids","description":"Optional specific open note ids to apply. Omit to apply all open notes."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to return a no-server-LLM revision brief, or to commit client-authored revised Markdown when text is supplied."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Hash returned by the client revision brief; required when submitting client-authored text."},"text":{"anyOf":[{"type":"string","minLength":20},{"type":"null"}],"title":"Text","description":"Client-authored revised full article Markdown to commit in client mode."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client article revisions.","default":"client-article-revision/v1"}},"type":"object","required":["job_id"],"title":"ReviseArticleFromNotesInput"},"ReviseChapterFromNotesInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number to revise from open review notes."},"note_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Note Ids","description":"Optional specific open note ids to apply. Omit to apply all open notes on the chapter."},"instruction":{"type":"string","minLength":3,"title":"Instruction","description":"Caller instruction wrapped around the gathered open notes.","default":"Gather all open chapter notes and rewrite based on those."},"base_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Revision","description":"Which revision number to revise from. None = latest."},"target_words":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words","description":"Target word count for the revised chapter."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override for the server revision path."},"revision_mode":{"anyOf":[{"type":"string","enum":["surgical","scene_rewrite","full_rewrite"]},{"type":"null"}],"title":"Revision Mode","description":"Caller-declared revision scope. Defaults to scene_rewrite."},"bypass_plan_reason":{"anyOf":[{"type":"string","maxLength":1000,"minLength":10},{"type":"null"}],"title":"Bypass Plan Reason","description":"Optional explicit reason to bypass structured planning for large/full rewrites."}},"type":"object","required":["job_id","chapter"],"title":"ReviseChapterFromNotesInput"},"ReviseChapterInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Chapter","description":"Chapter number to revise. If omitted, the legacy instruction parser is used."},"instruction":{"type":"string","minLength":3,"title":"Instruction"},"base_version":{"type":"integer","minimum":1.0,"title":"Base Version","description":"DEPRECATED — stories no longer have a version axis. Use base_revision. Ignored; accepted for back-compat.","default":1},"base_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Revision","description":"Which revision number to revise from. None = latest."},"target_words":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words","description":"Target word count for the revised chapter."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override (e.g. 'grok-4')."},"editorial_plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Editorial Plan","description":"Legacy editorial plan from chat (free-text). If structured_plan is also supplied, structured_plan wins and this is used only as a fallback summary."},"structured_plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Structured Plan","description":"Structured plan {short_plan, long_plan, beats[]} from the new planner. Writer consumes beats as the primary directive."},"plan_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Id","description":"Optional accepted revision-plan id. In authoring_mode='client' staged revisions, set plan_id on stage='start' only when intentionally linking that plan; omit it or send an empty string to keep the staged commit unlinked. Do not auto-fill this from a prior plan_revision response."},"revision_mode":{"anyOf":[{"type":"string","enum":["surgical","scene_rewrite","full_rewrite"]},{"type":"null"}],"title":"Revision Mode","description":"Caller-declared revision scope. full_rewrite and large targets require an accepted plan or bypass reason."},"bypass_plan_reason":{"anyOf":[{"type":"string","maxLength":1000,"minLength":10},{"type":"null"}],"title":"Bypass Plan Reason","description":"Required for large/full rewrites when the caller deliberately skips the planned-revision path."},"writer_thinking":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Writer Thinking","description":"Previewed writer-thinking dict from the writer_thinking operation ('Show writer plan'). Reused at write time instead of rebuilding, IF its beats and target_words still match structured_plan — otherwise the writer rebuilds it fresh."},"chapter_note_ids":{"items":{"type":"string"},"type":"array","title":"Chapter Note Ids","description":"Open chapter review note ids gathered by revise_chapter_from_notes."},"chapter_notes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Chapter Notes","description":"Open chapter review notes gathered by revise_chapter_from_notes."},"conversation":{"anyOf":[{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array"},{"type":"null"}],"title":"Conversation","description":"Full chat conversation for context."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to have revise_chapter return a no-LLM revision brief or commit client-authored revised text."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"dry_run":{"type":"boolean","title":"Dry Run","description":"Validate client-authored revised text without creating a chapter revision.","default":false},"commit":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Commit","description":"Set false as an alias for dry_run=true; only true/default commits."},"stage":{"anyOf":[{"type":"string","enum":["start","upsert_segment","validate","commit"]},{"type":"null"}],"title":"Stage","description":"Client revision staging step. Only stage='commit' creates a chapter revision."},"segment_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Segment Index","description":"0-based segment index for stage='upsert_segment'."},"beat_range":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Beat Range","description":"Optional inclusive [start, end] beat range covered by a staged segment."},"word_count_policy":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Word Count Policy","description":"Optional guard such as {min: 9500, max: 11500, hard: true}. Hard failures reject before commit."},"validation_anchors":{"items":{"type":"string"},"type":"array","title":"Validation Anchors","description":"Exact anchors expected in the revised text during dry-run/preflight."},"stale_terms":{"items":{"type":"string"},"type":"array","title":"Stale Terms","description":"Terms that should not appear in the revised text; returned as warnings when found."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Hash returned by the no-LLM revise_chapter brief; required when committing client-authored text."},"scope":{"type":"string","enum":["chapter","paragraph","range"],"title":"Scope","description":"Client revision scope.","default":"chapter"},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"0-based paragraph index for client paragraph-scope revisions."},"paragraph_range":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Paragraph Range","description":"0-based inclusive [start, end] paragraph range for client range-scope revisions."},"text":{"anyOf":[{"type":"string","minLength":50},{"type":"null"}],"title":"Text","description":"Full client-authored revised chapter prose to commit in client mode."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Updated chapter summary written by the client."},"handoff":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handoff","description":"Updated end-of-chapter continuity handoff written by the client."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Optional chapter title override."},"beats":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Beats","description":"Optional beat plan that drove this client-authored revision."},"carry_forward_facts":{"items":{"type":"string"},"type":"array","title":"Carry Forward Facts","description":"Continuity facts after this revision."},"facts_removed":{"items":{"type":"string"},"type":"array","title":"Facts Removed","description":"Continuity facts removed by this revision."},"fact_updates":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Fact Updates","description":"Structured continuity updates."},"open_loops_started":{"items":{"type":"string"},"type":"array","title":"Open Loops Started","description":"Open loops introduced by this revision."},"open_loops_resolved":{"items":{"type":"string"},"type":"array","title":"Open Loops Resolved","description":"Open loops resolved by this revision."},"open_loop_resolutions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Open Loop Resolutions","description":"Structured open-loop resolutions."},"open_loops_updated":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Open Loops Updated","description":"Structured open-loop updates."},"writer_approach_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Writer Approach Id","description":"Approach id previously returned by a client writer-approach step."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client revision artifacts.","default":"client-chapter-revision/v1"}},"type":"object","required":["job_id","instruction"],"title":"ReviseChapterInput"},"ReviseParagraphInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number to revise a paragraph in."},"paragraph_index":{"type":"integer","minimum":0.0,"title":"Paragraph Index","description":"0-based index of the paragraph (split on double-newline) the user selected."},"note":{"type":"string","minLength":3,"title":"Note","description":"User's revision note for this paragraph."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override (e.g. 'grok-4')."},"base_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Revision","description":"Which revision number to revise from. None = latest."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to use the caller's own model. Without revised_paragraph, returns a no-LLM paragraph rewrite brief; with revised_paragraph and base_text_hash, commits the client-authored paragraph without a server LLM call."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Full chapter text hash returned by the client paragraph brief; required when committing revised_paragraph."},"revised_paragraph":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revised Paragraph","description":"Client-authored replacement for exactly the selected paragraph. Must not contain a double-newline paragraph break."},"dry_run":{"type":"boolean","title":"Dry Run","description":"Validate revised_paragraph without committing.","default":false},"commit":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Commit","description":"Set false as an alias for dry_run=true; only true/default commits."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client paragraph artifacts.","default":"client-paragraph-revision/v1"},"beat_map_update":{"anyOf":[{"$ref":"#/components/schemas/BeatMapUpdateInput"},{"type":"null"}],"description":"Optional as-written beat-map reconciliation for this apply. Defaults to changed_beats (stale without replacements)."}},"type":"object","required":["job_id","chapter","paragraph_index","note"],"title":"ReviseParagraphInput"},"SaveChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":0.0,"title":"Chapter"},"revision":{"type":"integer","minimum":0.0,"title":"Revision","description":"Revision number. 0 = general chapter chat.","default":0},"slot":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slot","description":"Optional non-chapter chat slot, e.g. selected paragraph thread."},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"}},"type":"object","required":["job_id","chapter"],"title":"SaveChatInput"},"SelectedParagraphApplyPlanInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number containing the selected paragraph."},"paragraph_index":{"type":"integer","minimum":0.0,"title":"Paragraph Index","description":"0-based selected paragraph index."},"final_plan":{"type":"string","minLength":2,"title":"Final Plan","description":"Final writer-facing plan approved by the user."},"plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plan","description":"Structured selected-paragraph plan containing range and rationale."},"force_range":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Force Range","description":"Approved [start, end] paragraph range to apply."},"base_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Revision","description":"Revision number to revise from. None = latest."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override."},"selected_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Text","description":"Selected paragraph text captured when the chat plan was approved."},"selected_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Text Hash","description":"Client hash of selected paragraph text captured when the chat plan was approved."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to use the caller's own model. Without revised_paragraphs, returns a no-LLM beat/range rewrite brief; with revised_paragraphs and base_text_hash, commits the client-authored approved range without a server LLM call."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"base_text_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Text Hash","description":"Full chapter text hash returned by the client selected-paragraph brief; required when committing revised_paragraphs."},"revised_paragraphs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Revised Paragraphs","description":"Client-authored replacement paragraphs for the approved range. Selected-paragraph rewrites may replace the approved range with fewer, the same number, or more non-empty paragraphs when that implements the approved plan; an empty array is valid only for an approved delete_paragraph plan with expected output count 0."},"dry_run":{"type":"boolean","title":"Dry Run","description":"Validate revised_paragraphs without committing.","default":false},"commit":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Commit","description":"Set false as an alias for dry_run=true; only true/default commits."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client selected-paragraph artifacts.","default":"client-selected-paragraph-revision/v1"},"beat_map_update":{"anyOf":[{"$ref":"#/components/schemas/BeatMapUpdateInput"},{"type":"null"}],"description":"Optional as-written beat-map reconciliation for this apply. Defaults to changed_beats (stale without replacements)."}},"type":"object","required":["job_id","chapter","paragraph_index","final_plan"],"title":"SelectedParagraphApplyPlanInput"},"SelectedParagraphChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"paragraph_index":{"type":"integer","minimum":0.0,"title":"Paragraph Index","description":"0-based selected paragraph index."},"selected_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Text","description":"Client-visible selected paragraph text for drift checks/debug context."},"message":{"type":"string","minLength":1,"title":"Message","description":"User message about the selected paragraph."},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages","description":"Conversation history before this user message."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override."},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision","description":"Which revision to use as context. None = latest."},"use_story_tool":{"type":"boolean","title":"Use Story Tool","description":"Allow story-query tools when the user asks for prior context.","default":true},"auto_save":{"type":"boolean","title":"Auto Save","description":"Append user+assistant turns to the paragraph-specific chat slot.","default":false},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Idempotency key - see ChapterChatInput.request_id."}},"type":"object","required":["job_id","chapter","paragraph_index","message"],"title":"SelectedParagraphChatInput"},"SelectedParagraphUndoInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number containing the paragraphs."},"paragraph_indices":{"items":{"type":"integer"},"type":"array","minItems":1,"title":"Paragraph Indices","description":"0-based paragraph indices to restore."},"restored_paragraphs":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Restored Paragraphs","description":"Pre-apply text for each index, in the same order."},"base_revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Base Revision","description":"Revision number to restore into. None = latest."},"operation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operation Id","description":"Optional operation_id from the apply ledger/event used for stronger map-snapshot correlation. Optional for current clients."}},"type":"object","required":["job_id","chapter","paragraph_indices","restored_paragraphs"],"title":"SelectedParagraphUndoInput","description":"Restore specific paragraphs in-place to a client-provided snapshot.\n\nUsed by the reader's \"Undo\" affordance after selected-paragraph apply:\nthe client snapshots the pre-apply paragraphs before applying, then\nif the user dislikes the result it sends them back here. Pure DB\nwrite - no LLM, no decompose. Costs 0 credits.\n\nWhen the lengths match, `restored_paragraphs` is parallel to\n`paragraph_indices`; entry i replaces the chapter's paragraph at index\nparagraph_indices[i]. When the lengths differ, `paragraph_indices` must\nbe one contiguous current range, and that whole range is spliced out and\nreplaced with `restored_paragraphs`. This lets undo collapse a 1->3\nexpansion back to the original single paragraph without duplicating the\nfollowing prose.\n\nMap restore uses only trusted server ledger/event snapshots correlated by\nrange/operation_id. Clients never supply an authoritative map snapshot."},"SetChapterCoverInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id"},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"image":{"additionalProperties":true,"type":"object","title":"Image","description":"A generated image object (from get_cover_image_status result.image) to set as the cover."}},"type":"object","required":["job_id","chapter","image"],"title":"SetChapterCoverInput"},"SetLocationReferenceInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"location_name":{"type":"string","minLength":2,"title":"Location Name","description":"Story location name, such as Paresh Shah cabin."},"design_id":{"type":"string","minLength":3,"title":"Design Id","description":"Durable DesignForYou design id, e.g. dsg_25627817."},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Optional durable asset URL returned by DesignForYou."},"location_reference_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Reference Id","description":"Optional stable Writer id. Omit to derive one from location_name."},"location_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Label","description":"Optional label passed to DesignForYou as a context label."},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt","description":"Prompt used to generate or choose this location reference."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Image model that produced the reference."},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Id","description":"DesignForYou template id that produced the reference."},"prompt_strategy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Strategy","description":"Writer location-reference prompt strategy, if known."},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id","description":"DesignForYou session id, if known."},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider","description":"Image provider, if known."},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"DesignForYou/Writer request id, if known."},"source_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Job Id","description":"Transient asset job id that produced the reference, if known."},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"Optional generated asset result from get_asset_status."},"replace_existing":{"type":"boolean","title":"Replace Existing","description":"Replace an existing reference with the same id, name, or design_id.","default":true}},"type":"object","required":["job_id","location_name","design_id"],"title":"SetLocationReferenceInput"},"SetSceneStillsInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number that owns the selected paragraph."},"paragraph_index":{"type":"integer","minimum":0.0,"title":"Paragraph Index","description":"0-based selected paragraph index within the displayed chapter text."},"source_paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Source Paragraph Index","description":"Optional previous paragraph index to remove when moving an attached still grid."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Displayed chapter revision number, if available."},"selected_paragraph":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Paragraph","description":"Selected paragraph text for later display."},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt","description":"Editable scene prompt used to generate this still grid."},"context":{"additionalProperties":true,"type":"object","title":"Context","description":"Small UI context such as beat label and beat range."},"result":{"additionalProperties":true,"type":"object","title":"Result","description":"Generated scene-stills asset result returned by get_asset_status."}},"type":"object","required":["job_id","chapter","paragraph_index","result"],"title":"SetSceneStillsInput"},"StartArticleJobInput":{"properties":{"request":{"type":"string","minLength":5,"title":"Request","description":"The user's article request from Codex. Tone is controlled by the MCP article writer defaults."}},"type":"object","required":["request"],"title":"StartArticleJobInput"},"StartCheckoutInput":{"properties":{"tier":{"type":"string","title":"Tier","description":"plus or pro","default":"plus"}},"type":"object","title":"StartCheckoutInput"},"StartStoryFoundationInput":{"properties":{"premise":{"type":"string","minLength":5,"title":"Premise","description":"The premise for the new story."},"chapter_count":{"type":"integer","maximum":12.0,"minimum":1.0,"title":"Chapter Count","description":"The number of chapters to generate after the foundation is approved."},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Target word count per chapter."},"nsfw":{"type":"boolean","title":"Nsfw","description":"Content-rating metadata; does not override client safety policies.","default":false},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override used by later foundation and writing steps."}},"type":"object","required":["premise","chapter_count"],"title":"StartStoryFoundationInput","description":"Create a premise-only story shell for the guided foundation flow."},"StoryMutationResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"},"chapter":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chapter"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},"additionalProperties":true,"type":"object","title":"StoryMutationResponse"},"SuggestCoverScenesInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id"},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"message":{"type":"string","title":"Message","description":"Optional user guidance for the next batch of ideas.","default":""},"messages":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Messages","description":"Running cover-chat conversation."},"exclude":{"items":{"type":"string"},"type":"array","title":"Exclude","description":"Scene lines already shown — propose different ones."},"count":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Count","default":3},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"LLM override for scene ideation."}},"type":"object","required":["job_id","chapter"],"title":"SuggestCoverScenesInput"},"SyncSubscriptionInput":{"properties":{"source":{"type":"string","title":"Source","description":"stripe or app_store","default":"stripe"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"type":"object","title":"SyncSubscriptionInput"},"SyncSubscriptionResponse":{"properties":{"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"ok":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ok"},"subscription":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Subscription"}},"additionalProperties":true,"type":"object","title":"SyncSubscriptionResponse"},"UpdateChapterMemoryInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter whose saved continuity memory should be edited."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Optional revision to edit. None = latest."},"target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target","description":"Optional edit target. Use 'active_revision' to edit a failed attempt snapshot."},"carry_forward_facts":{"items":{"type":"string"},"type":"array","title":"Carry Forward Facts","description":"Full replacement list of carry-forward facts for the selected chapter/revision."}},"type":"object","required":["job_id","chapter"],"title":"UpdateChapterMemoryInput"},"UpdateCharacterAssetInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"character_index":{"type":"integer","minimum":0.0,"title":"Character Index","description":"0-based index of the cast member to patch."},"character_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Character Name","description":"Optional name guard; when provided, the indexed character must still match."},"asset_type":{"type":"string","enum":["concept_art","character_sheet","full_body_images"],"title":"Asset Type","description":"Which visual asset field to patch on the cast member. full_body_images accepts {images:[{url:...}]}."},"asset":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Asset","description":"Generated or client-owned asset metadata. Pass null to remove this asset field."},"append":{"type":"boolean","title":"Append","description":"For full_body_images, append the supplied images instead of replacing the collection.","default":false}},"type":"object","required":["job_id","character_index","asset_type"],"title":"UpdateCharacterAssetInput"},"UpdateCharactersInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"characters":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Characters","description":"Full replacement character list."}},"type":"object","required":["job_id","characters"],"title":"UpdateCharactersInput"},"UpdateOutlineInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"plan":{"additionalProperties":true,"type":"object","title":"Plan","description":"Full replacement plan. Same shape as output_artifacts.plan."},"allow_written_outline_edits":{"type":"boolean","title":"Allow Written Outline Edits","description":"Allow outline rows for already-written chapters to change while leaving chapter prose untouched. Defaults to false to preserve the legacy prose/outline consistency guard.","default":false},"target_words_per_chapter":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words Per Chapter","description":"Optional length override. Updates the writer's per-chapter target. Omit to leave unchanged — there is no other way to edit target length mid-review."}},"type":"object","required":["job_id","plan"],"title":"UpdateOutlineInput"},"UpdateStoryTitleInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title","description":"Corrected story title."},"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason","description":"Why this audited title correction is being made."}},"type":"object","required":["job_id","title","reason"],"title":"UpdateStoryTitleInput"},"UpdateStoryTitleResponse":{"properties":{"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id"},"old_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Old Title"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"story_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Story Url"}},"additionalProperties":true,"type":"object","title":"UpdateStoryTitleResponse"},"UpdateWorldInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"setting_doc":{"type":"string","title":"Setting Doc","description":"Replacement setting/world markdown document. Overwrites plan.setting_doc verbatim. Empty string is allowed (clears the world doc — refine_world or regenerate_setting can rebuild it later)."}},"type":"object","required":["job_id","setting_doc"],"title":"UpdateWorldInput"},"UpsertArticleNoteInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"note_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Id","description":"Existing note id to update. Omit to create a new note."},"text":{"type":"string","minLength":2,"title":"Text","description":"Review note to apply to the article draft. Later notes override stale original-request constraints. For deterministic replacement, write 'replace title/deck/body exactly' and include Title:, Deck:, and Body: sections."},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"0-based draft paragraph index the note refers to."},"selected_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Text","description":"Optional text span the note is anchored to."},"origin":{"type":"string","title":"Origin","description":"Where the note came from, such as Codex session or website review.","default":"Codex session"}},"type":"object","required":["job_id","text"],"title":"UpsertArticleNoteInput"},"UpsertChapterNoteInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number the review note belongs to."},"initial_plan_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Initial Plan Id","description":"Optional initial chapter plan id when the note targets an unwritten chapter plan."},"note_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Id","description":"Existing note id to update. Omit to create a new note."},"text":{"type":"string","minLength":2,"title":"Text","description":"Review note to apply to this story chapter. Notes stay visible on the chapter and can be consumed by revise_chapter_from_notes."},"paragraph_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Paragraph Index","description":"0-based displayed paragraph index the note refers to."},"selected_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Text","description":"Optional text span the note is anchored to."},"revision":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Revision","description":"Chapter revision number this note belongs to. Omit to attach the note to the latest revision."},"scope":{"type":"string","title":"Scope","description":"Note scope: paragraph, beat, or chapter. Beat notes may include beat_index/range metadata.","default":"paragraph"},"beat_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Beat Index","description":"0-based beat index when scope is beat."},"beat_num":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Beat Num","description":"1-based beat number when scope is beat."},"beat_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beat Summary","description":"Beat summary shown to the writer when applying beat-level notes."},"range_start":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Range Start","description":"0-based first paragraph covered by the beat note."},"range_end":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Range End","description":"0-based last paragraph covered by the beat note."},"origin":{"type":"string","title":"Origin","description":"Where the note came from, such as Codex session or website review.","default":"Website review"}},"type":"object","required":["job_id","chapter","text"],"title":"UpsertChapterNoteInput"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WaitForStatusInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"kind":{"type":"string","title":"Kind","description":"Which job family to probe: story | revision | chat_operation | asset | chapter_cover | cover_image | article. `job_id` is the id of that family (story id, asset job id, cover_job_id, operation_id, or article id).","default":"story"},"include_debug":{"type":"boolean","title":"Include Debug","description":"Include noisy revision debug fields when kind=revision.","default":false},"target":{"type":"string","title":"Target","description":"Which status to wait for. 'terminal' (default) returns when the job reaches completed/failed/cancelled. 'reviewing' returns as soon as the planner + characterizer finish so callers can edit the outline/cast before writing. 'progress_tick' returns as soon as chapters_done advances OR current_step text changes — use it in a short loop to stream progress to the user during a long generation instead of going silent for minutes. Any other literal status string is matched exactly.","default":"terminal"},"timeout_seconds":{"type":"number","maximum":300.0,"exclusiveMinimum":0.0,"title":"Timeout Seconds","description":"Maximum seconds to wait before returning. On timeout the current status is returned with timed_out=true — no error.","default":60.0},"until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Until","description":"Alias for `target`. Prefer this name in new clients."}},"type":"object","required":["job_id"],"title":"WaitForStatusInput"},"WorldChatInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"message":{"type":"string","minLength":1,"title":"Message"},"messages":{"items":{"$ref":"#/components/schemas/PlanMessage"},"type":"array","title":"Messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Idempotency key — see ChapterChatInput.request_id."}},"type":"object","required":["job_id","message"],"title":"WorldChatInput"},"WriteChapterInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to have write_chapter return a no-LLM chapter brief or commit client-authored text."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Optional title when committing client-authored chapter text."},"text":{"anyOf":[{"type":"string","minLength":50},{"type":"null"}],"title":"Text","description":"Client-authored chapter prose to commit through write_chapter in client mode."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Short client-authored chapter summary for future briefs."},"handoff":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handoff","description":"End-of-chapter continuity handoff for future briefs."},"beats":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Beats","description":"Optional beat plan that drove this client-authored chapter."},"carry_forward_facts":{"items":{"type":"string"},"type":"array","title":"Carry Forward Facts","description":"Continuity facts the client wants carried forward."},"open_loops_started":{"items":{"type":"string"},"type":"array","title":"Open Loops Started","description":"Open loops introduced by this chapter."},"open_loops_resolved":{"items":{"type":"string"},"type":"array","title":"Open Loops Resolved","description":"Open loops resolved by this chapter."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client chapter artifacts.","default":"client-chapter/v1"},"plan_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Id","description":"Selected initial chapter plan id to consume when writing this unwritten chapter."},"dry_run":{"type":"boolean","title":"Dry Run","description":"Preview the missing-chapter write inputs without starting a writer job or committing prose.","default":false},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number to write. Must exist in the outline and not already have written prose. Skips chapters earlier in the outline that are still unwritten — the writer's continuity ledger is built only from chapters that already have text."}},"type":"object","required":["job_id","chapter"],"title":"WriteChapterInput"},"WriterThinkingInput":{"properties":{"job_id":{"type":"string","minLength":1,"title":"Job Id","description":"The story job ID."},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plan","description":"Structured revision plan (short_plan, long_plan, beats) to preview the writer's execution for. Alias of structured_plan."},"structured_plan":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Structured Plan","description":"Alias accepted for pass-through from revise_chapter. Same shape as plan: {short_plan, long_plan, beats[]}."},"target_words":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":200.0},{"type":"null"}],"title":"Target Words","description":"Target word count for the write."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Model override."},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision","description":"Base revision (used for the default target word count)."},"authoring_mode":{"anyOf":[{"type":"string","enum":["server","client"]},{"type":"null"}],"title":"Authoring Mode","description":"Set to 'client' to return a no-LLM writer-thinking brief or commit client_thinking without server LLM usage."},"server_llm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Server Llm","description":"Set false as an alias for authoring_mode='client'. Do not send model in this mode."},"client_thinking":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Client Thinking","description":"Client-authored writer approach/thinking payload to commit in client mode. Same contract as submit_client_writer_approach.approach: require chapter_strategy + segments[]. Alias of client_approach."},"client_approach":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Client Approach","description":"Alias for client_thinking (writer approach payload)."},"base_plan_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Plan Hash","description":"Hash returned by the no-LLM writer_thinking brief; required when submitting client_thinking so the approach matches the planned beats."},"plan_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Id","description":"Optional accepted revision-plan id. When submitting client_thinking, stores the approach on that pending client plan (parity with submit_client_writer_approach)."},"editorial_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Editorial Summary","description":"Optional human-readable approach summary when committing client_thinking."},"client_name":{"type":"string","minLength":1,"title":"Client Name","description":"Client identity for no-LLM provenance.","default":"smart-client"},"client_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Model","description":"Client-side model name for no-LLM provenance. Never used for server API calls."},"artifact_version":{"type":"string","title":"Artifact Version","description":"Version label for submitted client_thinking artifacts.","default":"client-writer-thinking/v1"}},"type":"object","required":["job_id","chapter"],"title":"WriterThinkingInput","description":"Input for the writer-thinking preview (\"Show writer plan\").\n\nSends ONLY the minimal spine (the server adds premise/cast/setting/voice\nfrom the story plan) plus the structured beat plan — deliberately no\nledger or curated prior context. See docs/PLAN_tool_driven_writer.md.\n\nClient path (authoring_mode='client' or server_llm=false):\n  - without client_thinking: no-LLM brief (contract + prompt + context)\n  - with client_thinking (+ base_plan_hash): commit client-authored approach\n    without server LLM usage. Optional plan_id stores it on the pending\n    client revision plan (same as submit_client_writer_approach)."}}}}