Strong domain-specific tool design with excellent descriptions (avg 180 chars, well above baseline 72 chars minimum). All 10 tools have clear, actionable descriptions explaining WHAT, WHEN, and WHY. Input schemas are comprehensive with proper types and constraints. However, output schemas are not explicitly documented in the source code, only inferred from descriptions. Tool names follow verb_noun pattern well (list_*, read_*, apply_*, render_*, suggest_*). Parameters are well-constrained with enums (target in suggest_theme), optional flags, and numeric bounds. Risk annotations (READ_ONLY, WRITE) are present but not formalized as toolAnnotations in the MCP schema. Error handling guidance is minimal, no recovery hints or actionable error messages visible in tool definitions.
Apply an edit set and write the result. Use embed to store the set in the file under meta.themeStudio, so the next reader — person or agent — sees what was done.
The document as a layer tree with each layer's slots, flagging reused precomps, masks, track mattes and raster image layers. Only the top three levels by default — a whole tree is thousands of tokens and read_palette usually answers the question.
Colours carried by effects — a drop shadow's own colour, which no palette shows.
Every gradient in the file as a ramp: its colour stops with positions and slot indices, its alpha ramp, and whether it fades to nothing. A gradient whose alpha reaches zero is a mask dissolving into the page — those stops take the backdrop colour, never an inverted one. Move stops with the `positions` field of an edit set; recolour them by their slot index.
Every colour slot of an animation in layer z-order, with its stable index. Slots sharing a renderKey are the same JSON value seen more than once and cannot be given different colours.
Output schemas not documented. Tool descriptions explain what is returned (e.g., 'returns the edit set and a WCAG audit'), but formal output schema definitions are not visible in the source code. LLMs cannot plan downstream tool calls or extract specific fields without documented return types.
No error handling guidance in tool definitions. Tools lack recovery hints (e.g., 'If file not found, check the path is relative to workspace'). Error responses will not guide LLM recovery actions.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 68 | 2026-07-28+ | v2 |
Unique colours with usage counts, plus any edit set already saved into the file by a person working in the UI — layer names and groups included. Start here: it is the cheapest complete picture of a file.
The bitmaps inside a file, and what to do about them. A quarter of real animations carry a PNG, and it is dark like everything else around it. Reading one has always been possible here; changing one was a browser-only trick, because encoding a PNG needs a canvas — so an agent could see the problem and not fix it. With no `map` this only reports: the asset's size and the colours it is actually built from. With one, each pixel is moved towards its nearest mapped colour by distance in OKLab — no threshold, so antialiased edges stay smooth — and **alpha is never touched**, which is what keeps a bitmap that doubles as a matte working after it is recoloured.
Render the animation to a PNG so you can see the result of your own edit. Pass a background: a gradient that fades to transparent is meaningless without one. The default size is small on purpose — every pixel is tokens, and 384px is enough to see a halo or a washed-out fill. Raise it only to inspect something you have already found.
Read a reference image's colours. Every hex it returns is a value the image really contains, read from the pixels — never eyeball a colour off a picture you were shown and type it in, because a screenshot in a conversation has been rescaled and recompressed and the hex you read from it is a shade or two off. Returns the dominant colours with their share of the picture, and optionally: a mapping from an animation onto them (by how much of the picture a colour covers, not by lightness — a reference is usually the opposite theme), the colour at one pixel, and snap, which moves colours you already intend to use onto the nearest colour the image actually has.
Draft the opposite theme: roles are classified, lightness flips in OKLCH so hues survive, brand colours are protected, and gradients that fade to nothing take the backdrop. Returns the edit set and a WCAG audit; it does not write anything.
Risk annotations (READ_ONLY, WRITE) are informal comments, not formalized as MCP toolAnnotations (readOnlyHint, destructiveHint, idempotentHint). This prevents clients from enforcing safety policies or warning users before destructive operations.
Parameter 'edits' in apply_edits is typed as 'object' with nested properties, but no formal JSON Schema validation rules (minProperties, required fields, or nested type constraints). LLMs may pass incomplete or malformed edit sets.
Numeric parameters (limit, depth, width, height, frame, progress, colors, x, y, strength) lack explicit min/max bounds in schema. LLMs may pass absurd values (e.g., width=999999, limit=1000000) causing timeouts or resource exhaustion.