aseprite-ai-artist
This server is an MCP tool that lets an AI agent create, edit, inspect, and export pixel art directly inside a live Aseprite window.
Read the current sprite: list, open, activate, save, and close documents, plus resize canvas or set sprite properties.
Inspect art visually: generate previews, ASCII grids, filmstrips for animations, and pixel-level diffs between frames.
Compute over pixels: read raw pixel data for sampling colors, finding silhouette edges, or copying regions.
Paint and edit: apply stroke, fill, gradient, outline, replace color, transform, recolor, and other drawing operations with undo-friendly labels.
Manage selections: get, set, invert, grow, shrink, or select by color to scope drawing and transforms.
Manage frames and animation: create/duplicate/delete frames, set timing, and control cels including linked cels.
Manage layers: create, reorder, rename, duplicate, merge, lock, hide, and set layer properties.
Manage tags: create, update, delete, and list animation tags for spritesheet addressing.
Work with palettes: get/set, load presets or files (.gpl/.hex/.pal/.png), generate hue-shifted ramps, and analyze palette health.
Run quality checks: detect off-palette colors, stray pixels, broken outlines, banding, anti-aliasing issues, asymmetry, empty layers, untagged frames, and inconsistent timing.
Import reference images onto a locked semi-transparent layer, sample dominant colors from images, or load reference layers.
Export art to PNG, GIF, spritesheet with JSON atlas, numbered frames, or save an Aseprite copy.
Use tileset operations for tile-based workflows and build tile selections.
Allows AI agents to draw and edit pixel art directly in an open Aseprite document, including creating and modifying sprites, layers, frames, tags, and cels, with tools for pixel-level drawing, selection, recoloring, and validation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@aseprite-ai-artistDraw me a 32x32 knight with a 4-frame idle animation."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Aseprite AI Artist
Your coding agent draws pixel art in the Aseprite window you already have open. Not a copy, not a file on disk — the document you are looking at.
192×96, 54 frames, one palette. Drawn through this server into a live Aseprite window — the paint appears under the brush, every frame. Then the robot wipes the canvas clean and starts again, which is why the loop has no seam.
What it does
You ask for something. It gets drawn, in front of you.
"Draw me a 32×32 knight in the PICO-8 palette, then a 4-frame idle."
The agent picks a palette, blocks in a silhouette, looks at what it drew, shades it, splits it onto layers, animates, tags the cycle, and tells you what it had to compromise on. Every edit is one Ctrl+Z.
Works with Claude Code, Codex CLI, Gemini CLI, Cursor, VS Code and Windsurf from the same one-line config.
Related MCP server: kayamcp
Install
You need Aseprite 1.3+ and Node 22.6+. Open Aseprite once before you start, so its config folder exists.
1 — Install the extension
npx @pebbly/aseprite-ai-artist install-extensionThen quit and reopen Aseprite. It only dials out at startup, so an editor left running from before the install will never connect.
2 — Connect your agent
/plugin marketplace add with-pebbly/aseprite-ai-artist
/plugin install aseprite-ai-artistIt brings its own server plus the /pixel-* commands, the subagents and the
preview hooks. Don't also add the server by hand — you'd load all eighteen tools
twice, on every request.
npx @pebbly/aseprite-ai-artist install codex # ~/.codex/config.toml
npx @pebbly/aseprite-ai-artist install gemini # ~/.gemini/settings.json
npx @pebbly/aseprite-ai-artist install cursor # ~/.cursor/mcp.json
npx @pebbly/aseprite-ai-artist install --all # all of the aboveYour existing config is backed up first. --dry-run shows the change without
making it, --project writes into the repo instead of your home directory.
Restart the agent afterwards so it picks up the new server.
3 — Check it
npx @pebbly/aseprite-ai-artist doctorTicks all the way down and you're ready. If something's missing it says which half, instead of making you guess. More detail in docs/INSTALL.md.
Which model should do the drawing?
Not a benchmark — a log of what actually drew the art on this page. Models we haven't run are listed as untested rather than guessed at.
Model | What it drew | How it went |
Claude Fable 5.1 | the animation up top | Best so far. One session, no review passes needed. |
Codex CLI | the harbour below, and the mascot | Strong, but it took five rounds of critique. |
Claude Opus 5 | the server, the rulebook, every review pass | The planner and the critic. Its own drawing attempt got scrapped. |
Gemini 3 Pro, Sonnet 5, Cursor, others | — | Untested. Run one and send us the sprite. |
Method mattered more than the model. Both good results came the same way:
Generate, don't hand-place. Write a small program that emits every frame, then push it. Placing pixels one call at a time by eye is where the weak attempts died.
Look at frames full-size, one at a time. A filmstrip is a trap — at that size you see what you already know is meant to be there.
Turn reasoning up before you blame the model. A 32×32 grid is a spatial problem.
Why this one
It works everywhere, not just in Claude Code. Most Aseprite MCP projects put their craft knowledge in a Claude Code plugin, so Codex and Cursor get raw tools and none of the discipline. Here the rules and workflows are served over MCP, so every client reads the same source of truth.
Eighteen tools, not ninety. Every tool schema sits in the model's context on
every turn, drawing or not. Grouping by noun with an op enum covers the same
ground at a sixth of the cost — and makes batching the default, so one draw
call is one undo step for you.
It has to look at its own work. look gives the agent an upscaled preview, a
one-glyph-per-pixel text grid, a filmstrip and a frame-to-frame diff. validate
then checks the sprite mechanically before anything is called finished.
It can't quietly wreck your file. With Aseprite detached, every tool refuses
immediately instead of timing out — because an agent that "recovers" by editing
the .aseprite on disk makes changes you never see, and your next save
overwrites them.
There's a whole page on the other projects in this space and where they're still better.
What's inside
Eighteen tools, grouped by noun — preflight · sprite_info ·
sprite_manage · look · read_pixels · draw · select · transform ·
recolor · layer · frame · tag · cel · palette · validate ·
reference · export · tileset, plus run_lua as an escape hatch, off by
default. Full reference: docs/TOOLS.md.
Eleven workflows the agent follows, served to every client — pixel-brief ·
pixel-new · pixel-palette · pixel-draw · pixel-shade · pixel-rig ·
pixel-animate · pixel-tileset · pixel-review · pixel-fix ·
pixel-export. In Claude Code you also get four specialists: pixel-critic,
palette-smith, rig-builder, animation-director.
A rulebook in rules/ — palette discipline, hue-shifted shading,
silhouette, outlines, animation timing, layer rigging, review checklist. Skills
reference rules rather than restating them, so a rule has one place to be wrong.
How it works
your agent ──stdio/MCP──▶ server ──ws:9932──▶ bridge ──ws:9931──▶ AsepriteAseprite's Lua WebSocket is a client only, so the bridge holds the listening socket. It runs as its own process, so restarting the MCP server — which agent hosts do freely — doesn't drop your Aseprite connection, and a second agent window can attach without stealing the first one's replies. Details in docs/ARCHITECTURE.md.
Both ports bind 127.0.0.1 only. run_lua is arbitrary code execution inside
the app holding your unsaved work, and stays off unless you turn it on — full
threat model in SECURITY.md.
Development
npm install && npm run build
npm test # TypeScript
npm run test:pure # Lua that needs no editor — what CI runs
npm run test:extension # the real handlers, headless, against a real spritetest:extension needs Aseprite installed, so CI can't run it.
One more, drawn the same way
256×144, 28 frames, ten layers. Only six of them move — beam, windows, water, smoke, boat, stars — each on its own cycle length, which is what keeps an ambient loop from feeling mechanical.
Licence
MIT — see LICENSE. Aseprite is a trademark of Igara Studio S.A.; this project isn't affiliated with them.
Available Tools
18 toolscelCelsCDestructive
Manage cels — one layer's image on one frame. Ops: 'list', 'create', 'clear', 'delete', 'move', 'copy', 'link', 'unlink', 'set' (position/opacity). 'move' is how you shift a whole limb between frames without redrawing it; 'link' shares one image across frames so a static part of a cycle stays in sync.
| Name | Required | Description | Default |
|---|---|---|---|
| x | No | Cel origin, for 'set' and 'move'. | |
| y | No | ||
| dx | No | Relative move. | |
| dy | No | ||
| op | Yes | ||
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| frames | No | For 'link' across a range. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| opacity | No | ||
| toFrame | No | ||
| toLayer | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| cels | No | |
| sprite | Yes | |
| applied | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false. The description does not add any behavioral context beyond that—it never mentions that ops like 'delete' or 'clear' are destructive, nor does it describe consequences or required permissions. It adds no value beyond what annotations already convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the core concept (cel definition and op list). It avoids fluff and gives targeted hints for two ops. However, it could be better structured by separating op descriptions, but overall it's efficiently written.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with 12 parameters and 9 operations. The description is far too brief to guide correct invocation—it does not explain how parameters map to each op, error conditions, or operational nuances. While an output schema exists, the description still needs to clarify usage per op, which it largely omits. The tool demands far more detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%, meaning several parameters (y, dy, opacity, toFrame, toLayer) lack descriptions in the schema. The tool description does not compensate; it only lists ops and explains two of them. It provides no additional meaning for the parameters, leaving a significant gap for the agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool manages cels (one layer's image on one frame) and lists the supported operations. It distinguishes itself from sibling tools by focusing on cel-level operations, though it does not explicitly name alternatives. The core purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides useful context for 'move' and 'link' (shifting limbs between frames, sharing images across frames), which helps select those ops. However, it gives no guidance on when to use the tool vs alternatives, when not to use specific ops, or prerequisites. The guidance is selective and not comprehensive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
drawDrawA
Apply a batch of drawing operations to one cel, as a single undoable action. Ops: pixels, line, polyline, rect, ellipse, fill, replace, dither, gradient, clear, blit. Batch aggressively — a whole sprite in one call is normal and correct, and it means the user can undo your work with one Ctrl+Z. Set paletteLock (default true) to snap every colour to the sprite's palette by perceptual distance before anything is written, so you cannot silently widen a curated palette. Ops run in array order, so paint fills before outlines and outlines before highlights.
| Name | Required | Description | Default |
|---|---|---|---|
| ops | Yes | Applied in order, in one transaction. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| label | No | Name shown in Aseprite's undo history. Describe the intent, e.g. 'shade helmet'. | |
| layer | No | Layer name. Omit to use the active layer. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| createCel | No | Create the cel if the target layer/frame has none. | |
| paletteLock | No | Snap every colour to the nearest palette entry (CIELAB ΔE). Set false only when the user asked to introduce new colours. | |
| selectionOnly | No | Clip every op to the current selection. |
Output Schema
| Name | Required | Description |
|---|---|---|
| frame | Yes | |
| layer | Yes | |
| bounds | No | Bounding box actually touched. |
| sprite | Yes | |
| opsApplied | Yes | |
| colorsSnapped | Yes | Colours palette-lock moved, and how far. A large ΔE means the palette lacks that colour. |
| pixelsChanged | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already indicate this is a mutating (readOnlyHint=false) and non-idempotent tool, the description adds rich details: it modifies the cel, creates cels when needed (createCel default), respects paletteLock with CIELAB snapping, clips ops to selections, and records undo history. These side effects are fully disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense, covering all essential operational details in a few sentences. It avoids extraneous fluff, and each sentence adds value regarding batching, paletteLock, or execution order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the presence of an output schema, the description fully covers necessary context: how to use it, side effects, transaction semantics, and configuration options. It does not need to explain return values because the output schema exists, and all operational aspects are addressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers 100% of parameters with inline descriptions (e.g., colour format, per-pixel fallback, tolerance, ratio meanings). The prose outside the schema does not add significantly to parameter understanding; it reiterates paletteLock behavior already described in the schema. Thus baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool applies a batch of drawing operations to a cel as a single undoable action, with a specific resource (cel) and operation types. It distinguishes itself from sibling tools focused on reading, selecting, or transforming.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises batching operations aggressively, explains the ordering of ops, and gives concrete guidance on when to set paletteLock to false ('only when the user asked to introduce new colours'). It also clarifies transaction semantics for undo.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exportExportADestructive
Write game-ready files. Ops: 'png' (single frame), 'gif' (animation), 'spritesheet' (packed sheet plus a JSON atlas with per-frame and per-tag data), 'frames' (numbered PNGs), 'aseprite' (save a copy of the source). Spritesheet is what an engine actually consumes: pass sheetType and byTag to control layout. Exporting does not save the working document — use sprite_manage op 'save' for that.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| path | Yes | Output file path. For 'frames', a pattern containing {frame}, e.g. 'walk_{frame}.png' — Aseprite expands it into one file per frame, numbered from 0. | |
| tags | No | Export only these tags. | |
| trim | No | Trim transparent margins; the atlas keeps the original offsets. | |
| byTag | No | Split the sheet by animation tag. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| scale | No | Integer upscale, nearest-neighbour. | |
| layers | No | Export only these layers. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| padding | No | Pixels between frames; prevents bleed at non-integer zoom. | |
| sheetType | No | Spritesheet layout. | horizontal |
| includeJson | No | Write a sibling JSON atlas for 'spritesheet'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| atlas | No | |
| files | Yes | |
| frame | No | Which frame a single-frame export wrote. Defaults to the active frame, which is not always the one you drew on. |
| width | No | |
| height | No | |
| sprite | Yes | |
| frameCount | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, and the description adds meaningful context by clarifying that export does not persist the working document, which is a key behavioral distinction from sprite_manage. It also explains the output format (JSON atlas for spritesheet) without contradicting the annotations. It does not mention overwrite behavior or side effects on existing files, but the annotation already covers destructiveness, so the added context is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences with zero wasted words. The main verb is front-loaded, ops are listed compactly, the critical spritesheet guidance is placed early, and the save-disambiguation is at the end. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (12 parameters, 5 ops, multiple formats), the description covers the essential context: what each op does, the spritesheet consumption hint, and the crucial distinction from sprite_manage. The schema covers parameter details, and an output schema exists (not shown), so the description does not need to explain return values. It is complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 92% (most parameters have descriptions), so the baseline is 3. The description adds value beyond the schema by explaining the ops and how parameters like `sheetType` and `byTag` control spritesheet layout, and by clarifying the `path` pattern for 'frames'. This helps an agent understand the semantics without opening the schema, slightly exceeding the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Write game-ready files') and then enumerates each operation with a short, distinct explanation (png, gif, spritesheet, frames, aseprite). It explicitly differentiates the spritesheet op as the engine-consumable format and names the sibling tool (sprite_manage op 'save') for a different purpose, making its scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit when-not-to-use guidance by stating 'Exporting does not save the working document — use sprite_manage op 'save' for that.' It also gives usage direction for the spritesheet op ('Spritesheet is what an engine actually consumes: pass `sheetType` and `byTag` to control layout'), helping an agent choose the right op and parameters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
frameFramesADestructive
Manage animation frames. Ops: 'list', 'add', 'duplicate', 'delete', 'set_duration', 'activate', 'reorder'. Durations are milliseconds per frame and carry most of the life in a cycle — hold a contact pose longer than a pass pose. Use count to add several at once and durations to set a whole cycle's timing in one call.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| count | No | ||
| frame | No | 1-based frame number. Omit to use the active frame. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| toIndex | No | For 'reorder'. | |
| linkCels | No | For 'duplicate': share the cel image instead of copying it, so edits apply to both. | |
| durations | No | Per-frame durations from frame 1, for 'set_duration'. | |
| afterFrame | No | Insert position. Default: at the end. | |
| durationMs | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| frames | No | |
| sprite | Yes | |
| frameCount | Yes | |
| activeFrame | No | |
| totalDurationMs | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutating nature is known. The description adds domain context about durations carrying the life of a cycle, which is helpful but does not disclose operational details like irreversibility of delete or that operations affect the active sprite. Since annotations cover the core safety profile, the description's modest additional disclosure merits a 3.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly written, with the ops list front-loaded and each sentence earning its place. The usage guidance for durations and batch operations is concise and directly actionable, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (9 parameters, 7 ops), an output schema exists to define returns, and annotations cover safety. The description covers the operation scope and provides key usage tips. It does not explain every edge case (e.g., behavior when frame is omitted, or activate semantics), but the schema already documents frame omission, and the ops list is self-explanatory. This is adequate for an experienced user.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%, with descriptions for frame, sprite, toIndex, linkCels, durations, and afterFrame. The description adds value beyond the schema by explaining the semantics of durations (milliseconds per frame) and the purpose of count and durations in batch operations. This compensates for the undocumented parameters (op, count, durationMs) with practical usage context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Manage animation frames' and enumerates seven operations (list, add, duplicate, delete, set_duration, activate, reorder), making the resource and verb specific. It does not explicitly distinguish this tool from siblings like layer or tag, but the ops list leaves little ambiguity about scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical guidance on when to use certain parameters ('Use count to add several at once and durations to set a whole cycle's timing in one call') and explains the role of durations in animation cycles. It lacks explicit alternative routing to sibling tools, but the context is clear and not misleading.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
layerLayersADestructive
Manage layers. Ops: 'list', 'create', 'rename', 'delete', 'reorder', 'set' (visibility/opacity/blend/lock), 'group', 'ungroup', 'merge', 'duplicate', 'activate'. Pass batch to run several in one undoable action — building a rig in one call is the normal use. A character that will be animated wants its parts on separate layers (head, torso, arm-far, arm-near, leg-far, leg-near) before any frames exist; splitting baked pixels apart later is far more work.
| Name | Required | Description | Default |
|---|---|---|---|
| op | No | Single operation. Use `batch` instead for several. | |
| name | No | ||
| batch | No | Operations applied in order, in one undoable action. Same shape as the single-op arguments. | |
| index | No | Target stack position for 'reorder'; 0 is bottom. | |
| names | No | For 'merge' and bulk 'group'. | |
| parent | No | Group layer to nest under. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| newName | No | ||
| opacity | No | ||
| visible | No | ||
| editable | No | ||
| blendMode | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| layers | No | |
| sprite | Yes | |
| applied | No | |
| activeLayer | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint: true, so the description doesn't need to repeat that. It adds context about undoable batch operations and the value of structuring layers early, but does not detail specific destructive effects (e.g., what happens on delete or merge). This is adequate given annotation coverage, but adds limited new behavioral insight.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with the core purpose and ops listed upfront. The rigging example adds practical context but is a bit lengthy. Still, every sentence earns its place, and it avoids redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (12 params, 11 ops) and the presence of an output schema, the description provides a sufficient high-level overview. It explains the batch usage and gives a concrete use case. It doesn't detail every op's parameters, but the schema covers those, and the output schema handles return values. It feels complete for an agent to decide when to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%, so the description should compensate for the remaining parameters, but it doesn't. It only mentions 'batch' and lists ops without explaining individual parameters like 'index', 'names', or 'blendMode'. The description adds minimal semantic value beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Manage layers' with a comprehensive list of operations. It distinguishes from sibling tools by focusing on layer-specific actions, and the rigging example ties it to animation workflows, making it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool, specifically for building animation rigs with separate layers before frames exist. It also mentions the batch feature for multiple operations in one undoable action. However, it does not explicitly state when not to use it or contrast with alternative tools like sprite_manage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookLook at the spriteARead-only
See what is actually on the canvas. Ops: • 'preview' — a nearest-neighbour upscaled PNG of the active frame (~1024px long edge). Use for overall read: silhouette, colour, whether it looks like the thing. • 'ascii' — an exact text grid, one glyph per pixel with a colour legend and coordinate rulers. Use to verify precise pixel positions and values, to count cells, or on any client without vision. Capped at 64×64; pass a region to crop. • 'filmstrip' — every frame composited into one image. The only reliable way to review an animation, since a vision model reads just the first frame of a GIF. • 'diff' — a pixel-level text diff between two frames: '.' unchanged, '-' erased, glyph = the new colour. Use it to confirm exactly what an edit touched. Draw, then look, then fix. Do not report a sprite finished without looking at it.
| Name | Required | Description | Default |
|---|---|---|---|
| op | No | preview | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Read a single layer instead of the composited image. | |
| scale | No | Integer upscale for image ops, 1-128 (clamped so the output stays under ~2048px). Omit it — the automatic choice targets a ~1024px long edge, which is what a vision model can actually read. | |
| region | No | Crop. Required for 'ascii' on sprites larger than 64×64. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| toFrame | No | Diff: the later frame. | |
| fromFrame | No | Diff: the earlier frame. |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| rows | No | |
| text | No | The grid, for 'ascii' and 'diff'. |
| scale | No | |
| width | Yes | |
| frames | No | |
| height | Yes | |
| legend | No | glyph → #rrggbb. |
| sprite | Yes | |
| columns | No | |
| totalPixels | No | |
| changedPixels | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true and openWorldHint=false, and the description adds substantial behavioral detail beyond that: preview is a nearest-neighbour upscaled PNG, ascii is an exact text grid with legend and rulers, filmstrip composites all frames (and notes why it's needed because vision models read only first GIF frame), and diff shows pixel-level changes. It also discloses constraints like the 64x64 ascii cap and scale clamping, which is excellent transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with bullet points for each op, front-loaded with the overall purpose, and ends with a workflow directive. Each sentence is informative and necessary; there is no fluff. The length is justified by the tool's versatility, and the format makes it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values are covered elsewhere. The description covers all operations, their constraints, and the workflow. It explains when to use each op and even warns about pitfalls (e.g., GIF first-frame issue). There are no obvious gaps for an agent to correctly select and invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 88% (all params except op have descriptions), so the baseline is 3. The description adds extra meaning for scale (explains why omitting it is optimal) and region (required for ascii on large sprites), which goes beyond the schema. It does not repeat schema details but adds practical context, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb+resource ('See what is actually on the canvas') and then enumerates four distinct operations (preview, ascii, filmstrip, diff), each with a specific purpose. It distinguishes itself from sibling tools by focusing on inspection/reading rather than modification, and the ops are well-defined.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given for each op: preview for overall read, ascii for precise pixel verification, filmstrip for animation review, and diff for confirming edits. The workflow directive 'Draw, then look, then fix' and the warning not to report finished without looking add clear usage context. No exclusions are needed because the tool is the canonical inspection tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
palettePaletteA
Read and shape the sprite's palette. Ops: • 'get' — current palette with per-colour usage counts. • 'set' — write specific indices, or replace the palette wholesale. • 'preset' — load a bundled palette (pico8, gameboy, gameboy-pocket, cga, 1bit, grayscale-8). • 'load' — read a .gpl/.hex/.pal/.png palette file from disk. • 'ramp' — generate a hue-shifted ramp from a base colour and append it. Shadows rotate toward blue, highlights toward orange; a ramp that only changes brightness is the clearest tell of machine-made pixel art. • 'analyze' — report ramp structure, contrast, near-duplicate entries and colours used in the art that are not in the palette. Decide the palette before drawing. Retro-fitting one onto finished art means repainting.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| base | No | Base colour for op 'ramp'. | |
| path | No | Palette file for op 'load'. | |
| steps | No | Ramp length. | |
| colors | No | For op 'set': the colours to write. | |
| preset | No | Preset key for op 'preset'. | |
| spread | No | How far the ramp reaches into shadow and light. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| replace | No | For op 'set'/'preset': replace the whole palette instead of merging. | |
| remapArt | No | When replacing a palette, repaint existing pixels to the nearest new colour instead of leaving them off-palette. | |
| startIndex | No | For op 'set': where `colors` starts. Ignored when `replace` is true. |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| path | No | Palette file read by op 'load'. |
| ramp | No | |
| size | No | |
| usage | No | |
| colors | No | |
| sprite | No | |
| analysis | No | |
| availablePresets | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only set readOnlyHint=false, leaving the description to explain mutating behavior. The description does this well: it notes that 'set' can write indices or replace wholesale, 'load' reads files, 'ramp' appends a generated ramp, and 'remapArt' repaints pixels. It also provides nuance like shadow/highlight rotation, which goes beyond the schema. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a bulleted list of ops, making it scannable. The opening sentence is efficient, and the final guidance is a pithy takeaway. It is longer than necessary due to a few editorial asides (e.g., 'machine-made pixel art'), but these add context without sacrificing readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 11 parameters and six operations, the description covers the operations clearly and the schema handles the parameter details. The existence of an output schema means return values are already specified. The main gap is that it does not mention error conditions or edge cases (e.g., what happens if a preset key is invalid), but overall it is complete enough for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 91%, so the schema already documents most parameters. The description adds marginal value by explaining the 'ramp' operation's intent (hue-shifted, with shadow/highlight behavior) and hints at 'remapArt' semantics, but it does not systematically elaborate on each parameter beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb-object statement ('Read and shape the sprite's palette') and enumerates six distinct operations, each with a concise definition. This makes the tool's purpose unambiguous and distinguishes it from siblings like 'recolor' and 'validate' that handle other aspects of color work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a strong timing directive: 'Decide the palette before drawing. Retro-fitting one onto finished art means repainting.' This tells the agent when to use the tool. However, it does not explicitly contrast with sibling tools (e.g., 'recolor' for post-hoc changes), so the guidance is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preflightPreflightARead-only
Check that Aseprite is connected and report what this session can do. Call this FIRST in any pixel-art task and stop if ready is false — every editing tool writes into the user's open Aseprite window, and there is no useful fallback when that window is not there.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ready | Yes | True only when Aseprite is attached and accepting commands. |
| features | Yes | Optional capabilities this extension build supports. |
| directive | Yes | What to do next, in one sentence. |
| activeSprite | No | |
| asepriteVersion | No | |
| bridgeConnected | Yes | |
| pluginConnected | Yes | |
| extensionVersion | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behavioral traits beyond annotations: the tool returns a readiness condition (`ready`), instructs halting when false, and reveals that all editing tools depend on the open window. The readOnlyHint annotation is consistent with the check/report behavior, and no contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The core purpose is front-loaded, followed immediately by the critical usage directive and consequence. Every clause contributes actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter preflight tool, the description is complete: it names the operation, gives the call order, provides the failure condition, and explains the underlying dependency. An output schema exists to describe the return values, so no additional return-format detail is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters and 100% schema description coverage, the baseline is 4. The description does not need to explain parameters, and it fulfills the requirement by adding no irrelevant parameter detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Check') and resource ('Aseprite is connected') and adds the reporting function ('report what this session can do'). This clearly distinguishes preflight as a connectivity/session-check tool from sibling editing tools like layer, draw, and transform.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs 'Call this FIRST in any pixel-art task' and provides the stop condition ('stop if ready is false'). It also explains why this matters, that every editing tool writes into the user's open Aseprite window with no useful fallback, giving the agent a clear decision rule and rationale.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_pixelsRead pixelsARead-only
Read a rectangular region as structured data: a list of distinct colours plus a row-major index grid. Use this when you need to compute over pixels (sample a palette from art, find a silhouette edge, copy a region) rather than just look at them. For eyeballing, 'look' is cheaper.
| Name | Required | Description | Default |
|---|---|---|---|
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| region | No | Omit to read the whole canvas. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| composite | No | Read the flattened image. False reads only the target layer's cel. |
Output Schema
| Name | Required | Description |
|---|---|---|
| x | Yes | |
| y | Yes | |
| grid | Yes | Row-major indices into `colors`. |
| width | Yes | |
| colors | Yes | Distinct colours; index 0 is fully transparent. |
| height | Yes | |
| sprite | Yes | |
| uniqueColors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the read-only behavior is known. The description adds value by describing the output structure ('a list of distinct colours plus a row-major index grid'), which goes beyond the annotation. It doesn't contradict annotations and provides useful context about the tool's non-mutating nature and return format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: two sentences that front-load the core function, then provide usage context and an alternative. Every word earns its place, with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema (as indicated by context signals), the description does not need to detail return values. It covers purpose, usage, and differentiation from a key sibling. With read-only annotations and a fully documented parameter schema, the description is complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with descriptions for all 5 parameters, including nested 'region' details. The tool description does not add any additional parameter-specific meaning beyond what the schema already provides. Per calibration, with high schema coverage, baseline is 3, and no extra param info is given, so this is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Read a rectangular region as structured data: a list of distinct colours plus a row-major index grid.' It uses a specific verb (read) and resource (rectangular region), and explicitly differentiates from the sibling 'look' tool by contrasting computation vs. eyeballing. This allows an agent to distinguish it immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit usage guidance: 'Use this when you need to compute over pixels (sample a palette from art, find a silhouette edge, copy a region) rather than just look at them. For eyeballing, 'look' is cheaper.' This clearly states when to use this tool and when to use an alternative, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recolorRecolorA
Change colours in a region by intent, staying palette-legal. Ops: • 'shade' — darken or lighten with proper hue shifting (shadows cool, highlights warm). Use this instead of picking a darker hex by hand. • 'snap' — pull off-palette pixels onto the nearest palette colour by perceptual (CIELAB) distance. • 'replace' — swap one exact colour for another. • 'hue_shift' — rotate hue, e.g. to make a colour variant of a finished sprite. • 'desaturate' — drop toward grey, useful for a value check. Operates on a region's distinct colours in one pass, so a 64×64 recolour is one undo step, not four thousand.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| to | No | For 'replace'. | |
| from | No | For 'replace'. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| amount | No | For 'shade': negative darkens, positive lightens. One ramp step is roughly 0.15. | |
| region | No | Omit to affect the whole cel. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| degrees | No | For 'hue_shift'. | |
| strength | No | For 'desaturate'. | |
| selectionOnly | No | ||
| clampToPalette | No | Snap the result back onto the palette. Turn off only when growing the palette deliberately. |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| sprite | Yes | |
| mapping | Yes | Exactly which colour became which, and how many pixels each move touched. |
| pixelsChanged | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond annotations by explaining behavioral details: operations run in one pass so a 64×64 recolour is one undo step, and it emphasizes palette legality and the clampToPalette option. It also clarifies that shade does proper hue shifting (shadows cool, highlights warm). Annotations indicate it's not read-only, which aligns with the mutation described. No contradictions, and the description adds valuable context about how the tool behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a clear opening statement followed by a bulleted list of ops, making it scannable. While it is fairly long, each sentence adds information about operations or parameters. The front-loaded purpose and op list help an agent quickly grasp the tool's scope. Some redundancy exists (e.g., palette-legal mentioned twice), but overall it's efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (12 parameters, nested region object), the description is remarkably complete: it explains each op's use case, relevant parameters, and notes on palette behavior and undo granularity. The output schema is present, so return values are covered elsewhere. It could mention edge cases like invalid colors or when clampToPalette might fail, but for an agent deciding to call the tool, it's sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is high (83%), but the description adds crucial meaning: it explains the amount parameter with 'negative darkens, positive lightens. One ramp step is roughly 0.15,' defines from/to for replace, and clarifies clampToPalette's role in palette growth. These enrich the raw schema and help an agent select correct parameter values without needing extra inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Change colours in a region by intent, staying palette-legal.' It then enumerates specific operations (shade, snap, replace, hue_shift, desaturate) with examples, making it obvious what the tool does and how it differs from manual color editing. It's specific and distinct from sibling tools like draw or transform.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance for each operation, e.g., 'Use this instead of picking a darker hex by hand' for shade, and 'useful for a value check' for desaturate. However, it does not explicitly mention alternative tools or when NOT to use recolor in favor of another sibling, so it's not fully exhaustive but gives solid contextual usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
referenceReference imageA
Bring an external image into the sprite as a reference layer, so you can trace proportions or sample colours from it. Ops: 'import' (place an image on a locked, semi-transparent layer above the art), 'sample_palette' (read its dominant colours without importing), 'list', 'remove'. Importing at a different size uses nearest-neighbour; a photo scaled down to 32×32 is a starting point for a silhouette, never a finished sprite.
| Name | Required | Description | Default |
|---|---|---|---|
| x | No | ||
| y | No | ||
| op | Yes | ||
| fit | No | How to size the image against the canvas. | contain |
| name | No | Layer name. Default: 'reference'. | |
| path | No | Image file to read. | |
| colors | No | For 'sample_palette'. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| opacity | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| layer | No | |
| width | No | |
| height | No | |
| sprite | Yes | |
| palette | No | Dominant colours with their share of the image. |
| references | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors: importing places a locked, semi-transparent layer above the art, and scaling uses nearest-neighbour. It also clarifies that a downscaled photo is not a finished sprite. These go beyond the sparse annotations (readOnlyHint=false, openWorldHint=false) and give the agent useful expectations. It does not mention side effects like overwriting existing layers, but the op list and layer description provide reasonable transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the purpose. It lists ops in a compact way and adds a practical note on scaling. It is not overly verbose, though the scaling guidance could be seen as extra, but it is valuable context. Structure is clear and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 9 parameters and 4 distinct ops, the description is incomplete. It does not specify which parameters apply to which ops, nor does it explain return values (though an output schema exists). The scaling note is helpful but does not cover the full operational scope. Given the complexity, more detail on per-op parameter usage would be needed for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 56%, and the description does not compensate. It lists ops but does not map parameters to each op (e.g., 'path' is needed for import, 'colors' for sample_palette). Parameters like 'x', 'y', and 'opacity' have no description in the schema and none in the description. The description adds little semantic value beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear purpose: 'Bring an external image into the sprite as a reference layer'. It names the resource (sprite) and the action (import/reference), and the list of ops (import, sample_palette, list, remove) immediately distinguishes it from siblings like 'look' or 'read_pixels', which deal with viewing or reading pixels rather than managing reference images.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives practical usage context: importing at a different size uses nearest-neighbour and a scaled photo is only a silhouette starting point, not a finished sprite. However, it does not explicitly state when to prefer this tool over alternatives or when not to use it. The ops themselves imply usage, but no exclusions or comparison to sibling tools are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
selectSelectionAIdempotent
Read or change the active selection. Ops: 'get', 'none', 'all', 'rect', 'ellipse', 'color' (select every pixel matching a colour), 'invert', 'grow', 'shrink'. A selection scopes draw, transform and recolor, which is usually cheaper and safer than masking by hand.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| mode | No | How this selection combines with the existing one. | replace |
| rect | No | ||
| color | No | For op 'color'. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| amount | No | Pixels, for grow/shrink. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| tolerance | No | ||
| contiguous | No | For op 'color'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| empty | Yes | |
| bounds | No | |
| sprite | Yes | |
| pixelCount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and idempotentHint=true. The description adds that the tool reads or changes the selection and that it affects downstream operations, which is useful behavioral context beyond the annotations. No contradiction found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the main action and a concise op list. The note about scoping is valuable and adds no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters, a nested object, and an output schema, the description covers the tool's purpose and effect on other operations. It does not explain return values (output schema exists) or detailed param behaviors (schema covers most). Adequate for agent use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides descriptions for several parameters (mode, color, frame, layer, amount, contiguous, sprite). The description itself only clarifies the 'color' op. With 70% schema coverage, the description adds marginal value over the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the verb 'read or change' and the resource 'active selection', then enumerates the supported operations. It clearly distinguishes this tool from drawing/transform/recolor operations by explaining that selection scopes them, which separates it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that a selection scopes draw, transform and recolor, and notes it is cheaper/safer than manual masking. This gives clear context for when to use selection, though it does not explicitly name alternatives or list exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sprite_infoSprite infoARead-only
Full structured state of a sprite: dimensions, colour mode, palette, every layer (with opacity, blend mode, visibility, group nesting), every frame with its duration, animation tags, slices and the current selection. Read this before editing — guessing at layer names or frame counts is the most common way an agent corrupts someone's file.
| Name | Required | Description | Default |
|---|---|---|---|
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| includeSlices | No | ||
| includePalette | No | Include the full palette as hex. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Stable id for this open document. Pass it back as '#<id>'. |
| name | Yes | |
| tags | Yes | |
| width | Yes | |
| frames | Yes | |
| height | Yes | |
| layers | Yes | |
| slices | No | |
| palette | No | |
| filename | No | |
| colorMode | Yes | |
| selection | No | |
| frameCount | Yes | |
| activeFrame | No | |
| activeLayer | No | |
| transparentIndex | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already signals safety, and the description adds meaningful context: it guarantees a 'full structured state' and explains the failure mode of proceeding without it. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with zero filler. The state inventory is front-loaded, and the critical usage warning follows immediately. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape is covered. The description enumerates the state contents, provides a clear usage rule, and annotations cover read-only safety. With no required parameters and no unusual behavior, nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents sprite and includePalette; includeSlices is merely named in the schema. The description mentions palette and slices as part of the state, which reinforces the toggles, but it doesn't explain defaults or how includeSlices changes the result. With 67% schema coverage, the description adds only modest value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific purpose: return the full structured state of a sprite, with a detailed inventory of exactly what is included (dimensions, layers, frames, tags, slices, selection). It also frames the tool as a read-before-editing operation, clearly distinguishing it from mutation/drawing siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to read this before editing and warns that guessing at layer names or frame counts corrupts files, giving a clear trigger for when to use this tool. It doesn't name alternative tools for other read purposes, but the when-to-use guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sprite_manageManage spritesBDestructive
Open, create, focus, resize, save and close sprites in the running Aseprite session. Ops: 'list' (open documents), 'new', 'open', 'activate', 'save', 'save_as', 'close', 'resize_canvas', 'set_properties'. Canvas resize keeps existing pixels — pass an anchor to say where they land.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| path | No | File path for 'open' and 'save_as'. | |
| force | No | Allow 'close' to discard unsaved changes. Ask the user before setting this. | |
| width | No | ||
| anchor | No | Where existing pixels sit after 'resize_canvas'. | center |
| height | No | ||
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| colorMode | No | For 'new'. Indexed keeps a sprite honest about its palette. | |
| pixelAspect | No | e.g. '1:1' or '1:2'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Stable id of the affected document; pass it back as '#<id>'. |
| op | Yes | |
| path | No | |
| width | No | |
| height | No | |
| sprite | No | |
| sprites | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is known. The description adds one behavioral detail: 'Canvas resize keeps existing pixels — pass an anchor to say where they land.' This is useful, but it does not disclose other side effects like overwriting files on save or the impact of 'activate' on the session focus, relying on the schema for such details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, efficient and front-loaded with the primary purpose. The list of ops is clear, and the anchor note is appended logically. No wasted words, though a slightly structured breakdown per op could improve it without adding much length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with 9 ops and 9 parameters. The description only gives an overview and one behavioral detail, leaving many op-specific semantics (e.g., what 'set_properties' does, prerequisites for 'save_as', return formats) implicit. The output schema exists, so returns are covered, but the description does not adequately guide an agent on when and how to use each op, especially for a destructive tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%, so many parameters already have descriptions. The description adds meaning for the 'anchor' parameter by explaining that resize keeps existing pixels and anchor controls their placement. Other parameters like op, width, height are left to the schema, and the description does not compensate for the 33% gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear purpose: 'Open, create, focus, resize, save and close sprites in the running Aseprite session.' It lists the ops explicitly and gives a specific resource (sprites) and session context. However, it does not explicitly differentiate from sibling tools like sprite_info, so it lacks a direct contrast, but the verb+resource is specific enough.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide explicit when-to-use or when-not-to-use guidance relative to sibling tools. It lists operations but never states alternatives or exclusions, such as 'use sprite_info for reading sprite data.' The context is implied but not directly addressed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tagAnimation tagsADestructive
Manage animation tags — the named frame ranges a game engine imports as 'idle', 'walk', 'attack'. Ops: 'list', 'create', 'update', 'delete'. Tag every cycle before export; an untagged spritesheet is a pile of frames the engine cannot address.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| to | No | Last frame, 1-based, inclusive. | |
| from | No | First frame, 1-based, inclusive. | |
| name | No | ||
| color | No | Tag colour in the timeline, #rrggbb. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| newName | No | ||
| repeats | No | Loop count; 0 means forever. | |
| direction | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| tags | Yes | |
| sprite | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate destructiveHint=true and readOnlyHint=false, so the agent is aware this can modify state. The description adds that untagged spritesheets are unusable by the engine, but it does not disclose behavioral details such as immediate persistence or side effects of update/delete. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core concept, and every sentence earns its place. The first sentence defines the resource and operations, and the second gives a practical workflow warning without padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what tags are and why they matter, and the schema provides parameter details. However, it does not clarify which parameters are required for each operation (e.g., create vs. delete vs. update), which is a notable gap for correct invocation. Output schema exists, so return-value documentation is not the missing piece.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents several parameters (from, to, color, sprite, repeats), while 'name' and 'newName' benefit only from the description's 'named frame ranges' context. With 56% schema coverage, the description adds some conceptual meaning but does not fully compensate for the undocumented parameters or op-specific requirements.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool manages animation tags (named frame ranges) and enumerates the supported operations: list, create, update, delete. It uses concrete examples like 'idle', 'walk', 'attack' to make the resource unambiguous. It does not explicitly differentiate from sibling tools, but the resource and examples make the purpose clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear workflow cue: 'Tag every cycle before export', and explains why tagging matters. It does not explicitly state when not to use this tool or point to alternatives among the siblings, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tilesetTilesetsA
Work with Aseprite tilemap layers. Ops:
• 'list' — tilesets in the sprite.
• 'create_layer' — a new empty tilemap layer on a given grid.
• 'get' — tile count and, with a path, the tiles as one packed PNG.
• 'stamp' — place tiles by grid coordinate. x/y are grid cells, not pixels.
• 'pack' — turn a hand-painted mockup layer into a tileset plus a tilemap that reconstructs it exactly. Deduplicates identical cells; tolerance also merges near-identical ones. The canvas must be a whole number of tiles, and the source layer is hidden rather than deleted so you can compare.
• 'export' — writes the packed PNG plus the file the engine reads: 'tiled' (.tsj tileset and a .tmj map that uses it), 'godot' (Godot 4 .tres TileSet), or 'json' (tile grid plus the tilemap layout).
Painting a level by hand and packing it produces better tilesets than authoring tiles in isolation, because you see the whole picture while drawing. layout: 'blob47' adds a Tiled wangset for autotiling, and assumes the tileset is authored in canonical blob47 order after the empty tile — it refuses rather than writing a wangset that would autotile wrongly. Requires an extension build advertising the 'tileset' feature — check preflight first.
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | ||
| name | No | ||
| path | No | Output path for 'export' and 'get'. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| tiles | No | For 'stamp'. x/y are tile-grid cells, not pixels. | |
| format | No | tiled | |
| layout | No | Autotile layout for 'export'. | grid |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| tileWidth | No | ||
| tolerance | No | For 'pack': maximum per-channel difference at which two cells count as the same tile. 0 means exact, which is also much faster — anything above 0 compares every cell against every tile found so far. | |
| tileHeight | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| rows | No | |
| files | No | |
| layer | No | |
| format | No | |
| layout | No | |
| sprite | Yes | |
| columns | No | |
| skipped | No | For 'stamp': placements outside the grid or naming a tile that does not exist. |
| tilesets | No | |
| cellCount | No | For 'pack': grid cells examined. |
| tileCount | No | |
| tileWidth | No | |
| tileHeight | No | |
| reusedExact | No | For 'pack': cells that matched an existing tile exactly. |
| reusedFuzzy | No | For 'pack': cells merged by `tolerance`. A high number here with a low tolerance means the mockup has near-duplicate tiles worth cleaning up. |
| sourceLayer | No | For 'pack': the mockup layer, now hidden. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only set readOnlyHint=false and openWorldHint=false, leaving the description to carry behavioral detail. It discloses non-obvious behaviors: 'stamp' uses grid cells not pixels, 'pack' deduplicates and hides (not deletes) the source layer, 'blob47' refuses when ordering is wrong, and 'tolerance' has performance implications. This goes well beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but appropriately so for a multi-operation tool. It front-loads the purpose, then lists ops in a scannable bullet format, and adds a rationale paragraph at the end. Every sentence serves a purpose, with no filler. It could be slightly more compact, but the structure aids readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 12 parameters and six operations, the description covers most critical details: output formats, grid semantics, preconditions, and error behavior. An output schema exists (per context), which likely covers return structures. Minor gaps include exact return values for 'list' and 'create_layer', but these are not critical for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 58%, so the description must compensate for undocumented parameters. It explains 'tolerance', 'layout', 'sprite', and 'tiles' in detail, and clarifies grid-vs-pixel semantics. While 'name', 'tileWidth', and 'tileHeight' lack description-level context, they are straightforward from the schema defaults and bounds. The description meaningfully enhances understanding of the complex parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with 'Work with Aseprite tilemap layers' and then enumerates six distinct operations (list, create_layer, get, stamp, pack, export). It clearly states what the tool does and each op has a specific verb and resource. It distinguishes itself from sibling tools like 'layer' and 'export' by focusing on tileset-specific functionality, so an agent can immediately understand its scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear guidance on when to use the 'pack' operation ('Painting a level by hand and packing it produces better tilesets than authoring tiles in isolation') and warns about prerequisites ('Requires an extension build advertising the 'tileset' feature — check preflight first'). It does not explicitly contrast with sibling tools like 'layer' or 'export', but the internal op routing is clear and context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
transformTransformA
Move, flip, rotate or scale pixels on ONE cel — the target layer's image on the target frame. Ops: 'translate', 'flip', 'rotate', 'scale', 'outline', 'crop_to_content'. To transform part of a cel, crop the region out with draw op 'blit' first; there is no selection-scoped transform. Rotation is only clean at 90° multiples — arbitrary angles destroy pixel art, so anything else needs allowLossy. Scaling is nearest-neighbour and integer-only for the same reason.
| Name | Required | Description | Default |
|---|---|---|---|
| dx | No | ||
| dy | No | ||
| op | Yes | ||
| axis | No | For 'flip'. | |
| angle | No | Degrees, clockwise. For 'rotate'. | |
| color | No | Outline colour, for 'outline'. | |
| frame | No | 1-based frame number. Omit to use the active frame. | |
| layer | No | Layer name. Omit to use the active layer. | |
| factor | No | For 'scale'. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| thickness | No | ||
| allowLossy | No | Permit a non-90° rotation or non-integer scale. Ask the user first. |
Output Schema
| Name | Required | Description |
|---|---|---|
| op | Yes | |
| bounds | No | |
| sprite | Yes | |
| pixelsChanged | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint=false, destructiveHint=false — they carry no safety or behavioral detail. The description carries the full burden and discloses rich traits: arbitrary-angle rotation destroys pixel art (requires allowLossy), scaling is nearest-neighbour and integer-only, and there is no selection-scoped transform. These go well beyond what annotations provide and are accurate to the mutation semantics. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads the core purpose and ops, then packs the lossiness constraints, the selection limitation, and the alternative tool into compact, high-information sentences. Every sentence earns its place with zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complex 12-parameter mutation tool with an output schema present, so return values need no explanation. The description covers ops, selection scoping, lossy behavior, and the draw/blit alternative. Minor gap: it doesn't spell out required companion params per op (e.g., axis for flip, factor for scale), which is left to the schema — acceptable but not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is ~67%, so the schema already documents op, axis, angle, color, frame, layer, factor, sprite, and allowLossy individually. The description adds behavioral meaning tied to parameters (rotation lossiness → angle/allowLossy, integer scaling → factor) but does not enumerate parameters directly. It adds some value without fully compensating for the undocumented dx/dy/thickness.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Move, flip, rotate or scale pixels on ONE cel') and enumerates the six ops. It clearly delimits scope to a single cel (target layer's image on the target frame), which distinguishes it from sibling tools like draw, read_pixels, and cel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative and the condition that selects it: 'To transform part of a cel, crop the region out with draw op 'blit' first; there is no selection-scoped transform.' This is direct routing to a sibling tool under a stated condition, which fully satisfies the when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validateValidateARead-only
Lint a sprite against pixel-art rules and report concrete, located problems. Checks: off-palette colours, orphan/stray pixels, broken or doubled outlines, banding, unintentional anti-aliasing on a hard-edged sprite, odd-pixel asymmetry, empty layers, untagged frames, inconsistent frame timing, and cross-frame volume drift in an animation. Run this before telling the user a sprite is finished. It answers 'is this actually done' with evidence rather than optimism.
| Name | Required | Description | Default |
|---|---|---|---|
| checks | No | Omit to run everything. | |
| sprite | No | Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused. | |
| strict | No | Treat style warnings as failures. Use when the user asked for a specific discipline. |
Output Schema
| Name | Required | Description |
|---|---|---|
| score | Yes | |
| passed | Yes | |
| sprite | Yes | |
| summary | Yes | |
| findings | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, so the description's safety profile is established. The description adds behavioral detail beyond that by listing the specific categories of problems it detects (off-palette colours, orphan pixels, banding, etc.) and clarifying that it returns 'concrete, located problems.' This goes beyond the structured annotation and helps the agent understand the tool's scope.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph with a clear lead sentence, followed by a list of checks and a closing directive. It is efficient and front-loaded with the primary purpose. It could be slightly more concise by trimming the long enumeration, but it remains well-structured and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (a linting tool with multiple checks) and the presence of an output schema (which presumably describes the report format), the description covers what the tool does and when to use it. It does not need to explain return values because the output schema handles that. It is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — each of the three parameters (checks, sprite, strict) already has a description in the input schema. The tool description itself adds no extra parameter-level detail, so it relies on the schema. This meets the baseline for full coverage, but there is no additional value added.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('lint') and resource ('a sprite'), enumerates concrete checks, and clarifies its role as a final readiness gate ('answers is this actually done'). It is clearly distinct from sibling tools like sprite_info (which likely just reports metadata) or preflight (which might be a broader check), even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides an explicit when-to-use directive: 'Run this before telling the user a sprite is finished.' This gives clear context for the tool's appropriate invocation. However, it does not mention alternatives or exclusions (e.g., when NOT to use it), which would make the guidance fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
17 tool updates
v0.1.6- Changed
cel1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
draw1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
export2 fields changed- changed
Input schema / properties / path / descriptionPrevious value: -"Output file path. For 'frames', a pattern like 'walk_{frame}.png'."New value: +"Output file path. For 'frames', a pattern containing {frame}, e.g. 'walk_{frame}.png' — Aseprite expands it into one file per frame, numbered from 0." - changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
frame1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
layer10 fields changed- changed
Input schema / properties / batch / descriptionPrevious value: -"Array of operation objects, each shaped like the single-op arguments. Applied in order."New value: +"Operations applied in order, in one undoable action. Same shape as the single-op arguments." - changed
Input schema / properties / batch / items / additionalPropertiesPrevious value: -{}New value: +false - added
Input schema / properties / batch / items / propertiesAdded value: +{ + "blendMode": { + "$ref": "#/properties/blendMode" + }, + "editable": { + "type": "boolean" + }, + "index": { + "description": "Target stack position; 0 is bottom.", + "type": "integer" + }, + "name": { + "type": "string" + }, + "names": { + "description": "For 'merge' and bulk 'group'.", + "items": { + "type": "string" + }, + "type": "array" + }, + "newName": { + "type": "string" + }, + "op": { + "$ref": "#/properties/op" + }, + "opacity": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "parent": { + "description": "Group layer to nest under.", + "type": "string" + }, + "visible": { + "type": "boolean" + } +} - added
Input schema / properties / batch / items / requiredAdded value: +[ + "op" +] - added
Input schema / properties / batch / maxItemsAdded value: +128 - changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - added
Output schema / properties / layers / items / properties / celsAdded value: +{ + "description": "1-based frames that have a cel on this layer.", + "items": { + "type": "integer" + }, + "type": "array" +} - added
Output schema / properties / layers / items / properties / editableAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / layers / items / properties / isTilemapAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / layers / items / requiredPrevious value: -[ - "name", - "index", - "visible", - "opacity", - "blendMode", - "isGroup" -]New value: +[ + "name", + "index", + "visible", + "editable", + "opacity", + "blendMode", + "isGroup", + "isTilemap", + "cels" +]
- Changed
look3 fields changed- changed
Input schema / properties / scale / descriptionPrevious value: -"Integer upscale for image ops. Omitted means auto."New value: +"Integer upscale for image ops, 1-128 (clamped so the output stays under ~2048px). Omit it — the automatic choice targets a ~1024px long edge, which is what a vision model can actually read." - changed
Input schema / properties / scale / maximumPrevious value: -16New value: +128 - changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
palette2 fields changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - added
Output schema / properties / pathAdded value: +{ + "description": "Palette file read by op 'load'.", + "type": "string" +}
- Changed
read_pixels1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
recolor1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
reference1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
select1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
sprite_info5 fields changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - added
Output schema / properties / idAdded value: +{ + "description": "Stable id for this open document. Pass it back as '#<id>'.", + "type": "integer" +} - removed
Output schema / properties / tags / items / properties / repeatRemoved value: -{ - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ] -} - added
Output schema / properties / tags / items / properties / repeatsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Loop count; 0 means forever." +} - changed
Output schema / requiredPrevious value: -[ - "name", - "width", - "height", - "colorMode", - "frameCount", - "layers", - "frames", - "tags" -]New value: +[ + "id", + "name", + "width", + "height", + "colorMode", + "frameCount", + "layers", + "frames", + "tags" +]
- Changed
sprite_manage7 fields changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - added
Output schema / properties / idAdded value: +{ + "description": "Stable id of the affected document; pass it back as '#<id>'.", + "type": "integer" +} - added
Output schema / properties / sprites / items / properties / colorModeAdded value: +{ + "type": "string" +} - added
Output schema / properties / sprites / items / properties / framesAdded value: +{ + "type": "integer" +} - added
Output schema / properties / sprites / items / properties / idAdded value: +{ + "type": "integer" +} - added
Output schema / properties / sprites / items / properties / layersAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / sprites / items / requiredPrevious value: -[ - "name", - "width", - "height", - "active", - "modified" -]New value: +[ + "id", + "name", + "width", + "height", + "colorMode", + "frames", + "layers", + "active", + "modified" +]
- Changed
tag3 fields changed- removed
Input schema / properties / repeatRemoved value: -{ - "description": "0 means loop forever.", - "minimum": 0, - "type": "integer" -} - added
Input schema / properties / repeatsAdded value: +{ + "description": "Loop count; 0 means forever.", + "minimum": 0, + "type": "integer" +} - changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
- Changed
tileset14 fields changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - changed
Input schema / properties / tolerance / descriptionPrevious value: -"For 'pack': treat near-identical tiles as one."New value: +"For 'pack': maximum per-channel difference at which two cells count as the same tile. 0 means exact, which is also much faster — anything above 0 compares every cell against every tile found so far." - changed
Input schema / properties / tolerance / maximumPrevious value: -64New value: +255 - added
Output schema / properties / cellCountAdded value: +{ + "description": "For 'pack': grid cells examined.", + "type": "integer" +} - added
Output schema / properties / columnsAdded value: +{ + "type": "integer" +} - added
Output schema / properties / formatAdded value: +{ + "type": "string" +} - added
Output schema / properties / layoutAdded value: +{ + "type": "string" +} - added
Output schema / properties / reusedExactAdded value: +{ + "description": "For 'pack': cells that matched an existing tile exactly.", + "type": "integer" +} - added
Output schema / properties / reusedFuzzyAdded value: +{ + "description": "For 'pack': cells merged by `tolerance`. A high number here with a low tolerance means the mockup has near-duplicate tiles worth cleaning up.", + "type": "integer" +} - added
Output schema / properties / rowsAdded value: +{ + "type": "integer" +} - added
Output schema / properties / skippedAdded value: +{ + "description": "For 'stamp': placements outside the grid or naming a tile that does not exist.", + "type": "integer" +} - added
Output schema / properties / sourceLayerAdded value: +{ + "description": "For 'pack': the mockup layer, now hidden.", + "type": "string" +} - added
Output schema / properties / tileHeightAdded value: +{ + "type": "integer" +} - added
Output schema / properties / tileWidthAdded value: +{ + "type": "integer" +}
- Changed
transform4 fields changed- removed
Input schema / properties / scopeRemoved value: -{ - "default": "selection", - "description": "What the transform applies to. 'selection' falls back to the cel when nothing is selected.", - "enum": [ - "selection", - "cel", - "layer", - "sprite" - ], - "type": "string" -} - changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused." - removed
Output schema / properties / scopeRemoved value: -{ - "type": "string" -} - changed
Output schema / requiredPrevious value: -[ - "sprite", - "op", - "scope", - "pixelsChanged" -]New value: +[ + "sprite", + "op", + "pixelsChanged" +]
- Changed
validate1 field changed- changed
Input schema / properties / sprite / descriptionPrevious value: -"Sprite filename or id. Omit to use the sprite Aseprite has focused."New value: +"Which sprite: its id as '#7' (what every result reports back, and the only unambiguous form — two unsaved documents are both called 'Sprite'), its filename, or its display name. Omit to use the sprite Aseprite has focused."
18 tool updates
v0.1.0- First observed
cel - First observed
draw - First observed
export - First observed
frame - First observed
layer - First observed
look - First observed
palette - First observed
preflight - First observed
read_pixels - First observed
recolor - First observed
reference - First observed
select - First observed
sprite_info - First observed
sprite_manage - First observed
tag - First observed
tileset - First observed
transform - First observed
validate
TDQS
Scored across 18 tools
Each tool targets a distinct Aseprite subsystem, and the descriptions make the differences between sprite_info, look, and read_pixels clear. Minor overlap exists where draw and recolor both offer a replace operation, and sprite_manage save_as vs export aseprite can both save source files.
Names split between single-word verbs (look, draw, transform, validate), resource nouns (layer, frame, palette, tileset), and compounds like sprite_info, sprite_manage, and read_pixels, so there is no uniform verb_noun pattern. All names are lowercase and semantically readable, but the conventions are mixed.
18 tools is above the typical sweet spot, but each tool maps to a major Aseprite capability and carries multiple ops, so none feels redundant. The count is heavy but justified by the broad pixel-art, animation, palette, and tileset scope.
The surface covers document lifecycle, drawing, selection, layers, frames, cels, tags, palettes, recoloring, validation, reference, export, and tilesets. Minor gaps remain, such as slice management and agent-callable undo/redo, but they do not block core workflows.
Maintenance
Related MCP Connectors
Generate pixel art sprites, animations, 8-direction rotations and palettes for games.
AI game assets for agents: consistent sprites, 2D animations, tiles, maps, music and engine exports.
Agent-Native design tool - create and edit visual designs with agent assistance
Create AI animations and export transparent sprite sheets, alpha video, frames, and game assets.
Related MCP Servers
- AlicenseCqualityDmaintenanceEnables AI assistants to control Aseprite for creating pixel art and animated sprites, with 104 tools covering canvas, drawing, animation, palettes, effects, and more.100MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to visually interact with LibreSprite for real-time pixel art creation and automated drawing with self-healing capabilities.MIT
- AlicenseAqualityBmaintenanceEnables AI to create pixel art in Aseprite through pixel-level drawing primitives, read canvas screenshots, and iterate until satisfied.312MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to create, inspect, edit, and export pixel art, sprites, animations, and spritesheets using headless Aseprite, and to convert arbitrary images into indexed pixel art.MIT