@marlinjai/studio-mcp 0.4.0 → 0.6.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.
Files changed (5) hide show
  1. package/README.md +45 -10
  2. package/dist/cli.js +1472 -1647
  3. package/dist/index.d.ts +66 -15
  4. package/dist/index.js +1472 -1647
  5. package/package.json +1 -1
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 (on prepaid credits without a subscription roughly $0.06 per image, $0.84 per character mint and $1.05 per video take; the exact amount is the `costUsd` every job reports). 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,10 @@ 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
+ **Changed in 0.6.0.** `costUsd` and every spend figure are now what the job cost YOUR company: for a company on prepaid credits the amount that left its balance, where 0.5.0 and older described a provider figure. See [What changed in 0.6.0](#what-changed-in-060).
27
+
28
+ **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).
29
+
26
30
  **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
31
 
28
32
  ### Cursor (`.cursor/mcp.json`) and Claude Desktop
@@ -79,24 +83,25 @@ The token is held in memory only. It is never logged, never serialized into a re
79
83
 
80
84
  | Tool | What it does |
81
85
  |---|---|
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_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`. |
86
+ | `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`. |
87
+ | `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`. |
88
+ | `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 (the price follows the model and the quality flags). Refuses a model and image mismatch before submitting. `wait=false` returns the `jobId`. |
85
89
  | `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
90
  | `studio_find_animations` | Search Meshy's 678-preset animation library by words. Local, free, no request. |
87
91
  | `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). |
92
+ | `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. |
93
+ | `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
94
  | `studio_create_character` | Create an empty character record (for your own references). Requires `likenessRightsConfirmed: true`. |
91
95
  | `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
96
  | `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. |
97
+ | `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
98
  | `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. |
99
+ | `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. |
100
+ | `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
101
  | `studio_get_run_output` | Fresh signed URL for one node's output. |
97
102
  | `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. |
103
+ | `studio_get_spend` | Spend ledger: today / 7-day / 30-day totals plus recent paid actions, in what the company paid. |
104
+ | `studio_get_usage` | What limits the key's company and what it has used: month-to-date spend and job count in what the company paid, 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, operatorMonthlyLimit }`: the balance, the daily limit, what left the balance today, when the day resets and whether the operator set a monthly limit on top; 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
105
  | `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
106
  | `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
107
  | `studio_workflow_create` | Build a new saved workflow from ops applied to an empty document. Returns `{ ok, savedId, revision, summary }`. |
@@ -112,6 +117,13 @@ All waiting tools accept `waitSeconds` (default 600) and back off between polls
112
117
  ### Tool signatures (the contract shared with the `lumitra-studio` plugin)
113
118
 
114
119
  ```
120
+ studio_generate_image
121
+ in : { prompt, brandSlug?, brandMode?, characterSlug?, projectId?, model?, aspectRatio?, imageSize?,
122
+ seed?, candidateCount?: 1..4, wait?: true, waitSeconds? }
123
+ out: { jobId, status, model, costUsd, errorMessage, url, assetId, urls[], kind,
124
+ candidates?: { requested, rendered, mayRender? }, notice? }
125
+ wait=false: { jobId, kind, status: "queued", candidates?, notice? }
126
+
115
127
  studio_mint_character
116
128
  in : { projectId, name, slug, description, likenessRightsConfirmed: true, descriptorPrompt?,
117
129
  negativePrompt?, defaultModel?, seedModel?, viewModel?, visibility?: "listed"|"unlisted",
@@ -127,6 +139,24 @@ studio_replace_character_in_video
127
139
 
128
140
  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
141
 
142
+ ### What changed in 0.6.0
143
+
144
+ No argument and no result field was renamed or removed. What changed is the meaning of the amounts the Studio returns to a company on prepaid credits, since 2026-10-11, and the text of the tools that describe them:
145
+
146
+ - **`costUsd` is what the job cost your company.** For a company on prepaid credits it is the amount that left its balance for the job (the same figure the estimate before a run shows), on `studio_generate_image`, `studio_generate_3d`, `studio_rig_3d`, `studio_get_job`, `studio_get_run`, `studio_run_workflow`, `studio_run_published`, `studio_mint_character` and `studio_replace_character_in_video`. A program that added a factor of its own to `costUsd` to predict the balance must stop: the balance falls by `costUsd`. For a company held to a monthly cap arranged with the Lumitra operator nothing changes.
147
+ - **`studio_get_spend` and `studio_get_usage` report what was paid.** For a company on prepaid credits the totals of `studio_get_spend` equal what left the balance for the jobs of each window, and `usedUsd`, `realizedUsd`, `inFlightEstimatedUsd` and `byModel` of `studio_get_usage` are in the same dollars as `credits.balanceUsd`. `capUsd` is always `null` on credits; the new `credits.operatorMonthlyLimit` says whether the Lumitra operator set a monthly limit on top, and a `monthly_cap_reached` refusal of such a company carries `resetsAt` and no amounts.
148
+ - **The typical prices in the descriptions are prices.** The figures in the tool descriptions and the skill are Studio's prices for a company on prepaid credits without a subscription (a character mint is about 0.84 USD, where the text used to say about 0.30 USD).
149
+
150
+ ### What changed in 0.5.0
151
+
152
+ 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.
153
+
154
+ - **`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.
155
+ - **`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.
156
+ - **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.
157
+ - **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.
158
+ - **Descriptions match the Studio of 2026-10-11.** `studio_get_usage` describes 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.
159
+
130
160
  ### The likeness confirmation (every tool that creates a character)
131
161
 
132
162
  `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 +224,11 @@ Generate a 16:9 image for brand "busbasis" with Bruno at a workbench in a bright
194
224
  model kie/nano-banana-2, and tell me the cost.
195
225
  ```
196
226
 
227
+ ```text
228
+ Make one image of a lighthouse at dusk, no brand, and file it in the project "moodboards".
229
+ How much credit do we have left afterwards?
230
+ ```
231
+
197
232
  ```text
198
233
  Here is a frame from our header video: https://.../frame-012.png
199
234
  Put bruno-hartmann into that shot and give me the clip. Use the full-body reference.