@marlinjai/studio-mcp 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A thin [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server over the **hosted Lumitra Studio HTTP API** (`studio.lumitra.co`). It gives any MCP client (Claude Code, Cursor, Claude Desktop, your own agent) typed tools for brand-consistent image generation, character minting, workflow authoring and runs, published recipes, and the still-swap video recipe, without cloning the Studio repo, without Postgres, without provider keys. The server is a pure HTTP client: every tool maps onto an existing `/api/**` route.
4
4
 
5
- Every generation spends real money on the Studio's provider accounts (roughly $0.04 per image, $0.30 per character mint, $0.70 per video take). Treat the API key like a production credential.
5
+ Every generation spends real money (roughly $0.04 per image, $0.30 per character mint, $0.70 per video take at provider cost; a company on prepaid credits is debited that cost times its rate, 1.50 on pay as you go). Treat the API key like a production credential. A key belongs to one company: everything it reads, creates and spends is that company's.
6
6
 
7
7
  ## Install
8
8
 
@@ -23,6 +23,8 @@ claude mcp add lumitra-studio \
23
23
 
24
24
  If `LUMITRA_STUDIO_API_KEY` is already exported in your shell, drop the `--env` flag: the server reads it from its own environment.
25
25
 
26
+ **New in 0.5.0.** `studio_generate_image` no longer requires a `brandSlug` (leave it out for an image without a brand), takes a `projectId`, and returns the Studio's `candidates` plan and `notice`. Nothing breaks for a caller that sends a real brand slug. See [What changed in 0.5.0](#what-changed-in-050).
27
+
26
28
  **Breaking in 0.4.0.** The legacy variable `LUMITRA_STUDIO_SERVICE_TOKEN` is no longer read. Provide the same key as `LUMITRA_STUDIO_API_KEY`; a server started with only the legacy name stops with an error that says so.
27
29
 
28
30
  ### Cursor (`.cursor/mcp.json`) and Claude Desktop
@@ -79,24 +81,25 @@ The token is held in memory only. It is never logged, never serialized into a re
79
81
 
80
82
  | Tool | What it does |
81
83
  |---|---|
82
- | `studio_list_projects` | List projects (id, slug, name). A `projectId` is needed by the workflow-based tools. |
83
- | `studio_generate_image` | Submit a brand-styled image generation (optionally pinned to a character), wait for it, return the signed URL and cost. `wait=false` returns the `jobId`. |
84
+ | `studio_list_projects` | List projects (id, slug, name). A `projectId` is needed by the workflow-based tools and optional on `studio_generate_image` and `studio_generate_3d`. |
85
+ | `studio_generate_image` | Submit an image generation, wait for it, return the signed URL and cost. Only `prompt` is required: `brandSlug` (a brand of the key's company) applies that brand's style and references, and leaving it out generates without a brand; `characterSlug` pins a character; `projectId` chooses the project the image is filed in. A `brandSlug` or `characterSlug` the company cannot use is refused with `404` `input_not_found` before anything is spent. The result carries `candidates: { requested, rendered, mayRender? }` and, when the model renders fewer images than `candidateCount` asked for, a `notice`. `wait=false` returns the `jobId`. |
84
86
  | `studio_generate_3d` | Generate one 3D model (a textured GLB mesh) from a prompt or one image through 3D AI Studio, wait for it, return the signed GLB URL and cost (typically $0.25 to $0.70 per model). Refuses a model and image mismatch before submitting. `wait=false` returns the `jobId`. |
85
87
  | `studio_rig_3d` | Rig a humanoid Model3D and apply up to 10 Meshy animation presets (by name or id) through a one-node workflow; returns the rigged GLB, each clip's name and url, and the cost ($0.20 per rig plus $0.12 per preset). Refuses an unknown preset, with close matches, before submitting. |
86
88
  | `studio_find_animations` | Search Meshy's 678-preset animation library by words. Local, free, no request. |
87
89
  | `studio_get_job` | Read a job's status, cost, error and fresh result URL; `wait=true` blocks until terminal. |
88
- | `studio_list_characters` | List minted characters. |
89
- | `studio_get_character` | One character with its frozen reference images (category + signed URL). |
90
+ | `studio_list_characters` | List the characters the key can use: its company's own, plus the ones another company shared with everyone (`owned: false`, usable in generations, read-only). A slug is unique within one company. |
91
+ | `studio_get_character` | One character with its frozen reference images (category + URL). For a character the company owns the URL is a direct image URL; for one another company shared (`owned: false`) it is a Studio address that works unchanged as an image input to any Studio tool, is not a public image URL, and stops working when the owner stops sharing. |
90
92
  | `studio_create_character` | Create an empty character record (for your own references). Requires `likenessRightsConfirmed: true`. |
91
93
  | `studio_mint_character` | Run the curated character-sheet workflow inline, wait, create the character, upload the 7 views as references. Requires `likenessRightsConfirmed: true` and refuses before the run starts without it. Returns `slug`, `referenceCount`, `costUsd`, `runId`. |
92
94
  | `studio_create_brand` | Create a brand (style prefix + context). |
93
- | `studio_upload_brand_reference` | Upload a reference image to a brand library from a local path or URL. |
95
+ | `studio_upload_brand_reference` | Upload a reference image to a brand library from a local path or URL. The `brandSlug` must name a brand of the key's company (anything else is a `404`). |
94
96
  | `studio_run_workflow` | Run an inline workflow DAG (or a saved one by `savedId`), with params, node subsets, repeat count and `visibility`; waits by default. |
95
- | `studio_get_run` | Read a run: overall status, per-node status, URLs, cost, errors. |
97
+ | `studio_get_run` | Read a run: overall status, per-node status, URLs, cost, errors. A run parked on a person at a judge node comes back with a `waiting` block naming the node and its candidates. |
98
+ | `studio_decide_judge` | Submit a PERSON'S approve or reject on a parked judge node; approving resumes the run. Never the agent's own judgement. |
96
99
  | `studio_get_run_output` | Fresh signed URL for one node's output. |
97
100
  | `studio_replace_character_in_video` | The proven still-swap recipe: image-edit the character into a scene frame, then image-to-video. Accepts `characterSlug` (full-body reference auto-resolved) or `characterReferenceUrl`, optional `endFrameUrl` (switches to Kling start+end keyframes). Returns `stillUrl`, `videoUrl`, `costUsd`, `runId`. |
98
- | `studio_get_spend` | Spend ledger: today / 7-day / 30-day totals plus recent paid actions. |
99
- | `studio_get_usage` | This key's tenant against its plan: month-to-date spend and job count, the monthly USD cap and requests-per-minute limit (`null` = unlimited), and a per-model breakdown. Call before a large batch to check remaining budget, or after a `402`/`429` to see what tripped. `usedUsd` includes in-flight (not yet settled) job estimates, so it can go DOWN as well as up: a job that later fails releases its estimate. |
101
+ | `studio_get_spend` | Spend ledger: today / 7-day / 30-day totals plus recent paid actions, at provider cost. |
102
+ | `studio_get_usage` | What limits the key's company and what it has used: month-to-date spend and job count at provider cost, the monthly USD cap (`capUsd`) and requests-per-minute limit (`null` = none), a per-model breakdown, and `credits`. For a company on prepaid credits (every new company) `credits` is `{ balanceUsd, dailyLimitUsd, usedTodayUsd, dailyResetsAt }`: the balance, the daily limit, what left the balance today and when the day resets; for a company held to a monthly cap it is `null`. Call before a large batch to check remaining room, or after a `402`/`429` to see what tripped. `usedUsd` includes in-flight (not yet settled) job estimates, so it can go DOWN as well as up: a job that later fails releases its estimate. |
100
103
  | `studio_workflow_describe` | The node vocabulary: every task type with ports, prompt policy and runnability, the input types, the op types, the patch limits. Settings and models only with `includeSettings` / `includeModels`; filter with `tasks`. |
101
104
  | `studio_workflow_get` | A saved workflow as a summary (nodes, wire counts, edge and group counts, `revision`, `readOnly`, `projection`), or the whole response with `full: true`. |
102
105
  | `studio_workflow_create` | Build a new saved workflow from ops applied to an empty document. Returns `{ ok, savedId, revision, summary }`. |
@@ -112,6 +115,13 @@ All waiting tools accept `waitSeconds` (default 600) and back off between polls
112
115
  ### Tool signatures (the contract shared with the `lumitra-studio` plugin)
113
116
 
114
117
  ```
118
+ studio_generate_image
119
+ in : { prompt, brandSlug?, brandMode?, characterSlug?, projectId?, model?, aspectRatio?, imageSize?,
120
+ seed?, candidateCount?: 1..4, wait?: true, waitSeconds? }
121
+ out: { jobId, status, model, costUsd, errorMessage, url, assetId, urls[], kind,
122
+ candidates?: { requested, rendered, mayRender? }, notice? }
123
+ wait=false: { jobId, kind, status: "queued", candidates?, notice? }
124
+
115
125
  studio_mint_character
116
126
  in : { projectId, name, slug, description, likenessRightsConfirmed: true, descriptorPrompt?,
117
127
  negativePrompt?, defaultModel?, seedModel?, viewModel?, visibility?: "listed"|"unlisted",
@@ -127,6 +137,16 @@ studio_replace_character_in_video
127
137
 
128
138
  Reference categories written by the mint: `face`, `three-quarter`, `profile`, `full-body`, `close-up`, `lighting-warm`, `lighting-cool` (the Studio's canonical names, the same ones its in-app mint flow and try-on ranker use).
129
139
 
140
+ ### What changed in 0.5.0
141
+
142
+ Nothing breaks for an existing caller that sends a real brand slug: every argument that existed keeps its name and meaning, and every result keeps its fields.
143
+
144
+ - **`studio_generate_image` no longer requires `brandSlug`.** Leave it out and the image is generated without a brand. Up to 0.4.0 the field was required, so an agent of a company with no brand sent a made-up slug. Since 2026-10-11 the Studio refuses a slug that names no brand of the key's company (`404`, `code: "input_not_found"`) instead of generating without a style into a project of that name, which left such an agent with no way to make an image at all.
145
+ - **`studio_generate_image` takes `projectId`.** The image is filed in that project (one of the company's, from `studio_list_projects`). Without it the image lands in the project named after the brand, or in `default` when there is no brand.
146
+ - **The candidate plan is passed through.** The result carries `candidates: { requested, rendered, mayRender? }` as the Studio reported it when it accepted the job, and a `notice` sentence when fewer images will be made than `candidateCount` asked for: most KIE image models render one image whatever the count. Only rendered images are charged.
147
+ - **A refusal reaches the agent as the Studio worded it.** The Studio's `error` sentence, which names the next step, is handed on unchanged, followed by a `hint` the sentence does not already contain and by the machine `code`, for example `POST /api/generate -> 404: Brand 'acme' not found. Create the brand first (POST /api/brands, or the studio_create_brand tool), or leave brandSlug out to generate without a brand. (code: input_not_found)`. Up to 0.4.0 the `code` and the `hint` were dropped. A client that matched a tool error by its exact full text sees the added ` (code: ...)` suffix; the sentence before it is unchanged.
148
+ - **Descriptions match the Studio of 2026-10-11.** `studio_get_usage` and `studio_get_spend` say what is provider cost and what is credit (the `credits` field: balance, daily limit, used today, reset time); `studio_list_characters`, `studio_get_character` and the `characterSlug` arguments describe shared characters (readable and castable, not editable, reference images as Studio addresses); `studio_upload_brand_reference` and `studio_replace_character_in_video` say that a slug the company cannot use is a `404` before anything is spent.
149
+
130
150
  ### The likeness confirmation (every tool that creates a character)
131
151
 
132
152
  `studio_create_character` and `studio_mint_character` require `likenessRightsConfirmed: true`, and `studio_run_published` requires it for a recipe that creates a character. It records, on the character, that the human the agent acts for confirmed:
@@ -194,6 +214,11 @@ Generate a 16:9 image for brand "busbasis" with Bruno at a workbench in a bright
194
214
  model kie/nano-banana-2, and tell me the cost.
195
215
  ```
196
216
 
217
+ ```text
218
+ Make one image of a lighthouse at dusk, no brand, and file it in the project "moodboards".
219
+ How much credit do we have left afterwards?
220
+ ```
221
+
197
222
  ```text
198
223
  Here is a frame from our header video: https://.../frame-012.png
199
224
  Put bruno-hartmann into that shot and give me the clip. Use the full-body reference.