Skip to main content
Glama

Aseprite MCP

CI License: MIT Python 3.10+ MCP

An extensive Model Context Protocol server that lets an AI agent (Claude Code, Claude Desktop, or any MCP client) create and edit Aseprite sprites: draw pixel art, build animations, manage layers/frames/tags/palettes, and export to PNG/GIF/sprite sheets, all headlessly.

📖 Full tool reference: docs/TOOLS.md: every tool with its parameters.

It works by generating Lua scripts and running them through Aseprite's batch mode (aseprite -b --script ...), plus the Aseprite CLI for exports. Every operation opens a real .aseprite file, edits it, and saves, so your files stay fully editable in the Aseprite GUI.

  • 163 tools across every part of a sprite: drawing (pixel-perfect and anti-aliased), custom brushes and symmetry, ramp-aware shading, selections that scope later edits, palettes, layers, frames, cels, animation tags, slices and 9-patch, effects, text, tilemaps, transforms, and export (per-layer, per-tag, sprite sheets, GIF, onion-skin, Godot, Minecraft). See the tool catalogue or the full reference.

  • Whole assets in one call - workflow tools scaffold and validate a character, an icon set, a tileset or an eight-direction walk template, and a batch op-runner applies hundreds of edits atomically in a single Aseprite process.

  • Shading that stays on the palette - shade_region_by_light turns a flat region into a lit form from a ramp and a light direction (with an optional second, weaker fill light so the shadow side stays readable), gradient_map brings imported or filtered art onto a ramp in the first place, and specular_highlight, contact_shadow, cast_shadow, glow, outline_smart and dither_band finish it. A brightness filter moves every pixel off the palette; these move pixels along the ramp, so the art still uses exactly the colours it was given. A glow of blended alpha or a shadow of multiplied alpha would break that, which is why both are built of ramp steps arranged in space instead.

  • Indexed mode that draws - create_sprite gives an indexed sprite a real 33-entry palette (a transparent entry at index 0, then Aseprite's 32 defaults) rather than the 256 identical blacks that made every colour equidistant, so every draw resolved to index 0 and vanished while reporting success. set_color_mode quantizes the palette from the art instead of mapping onto whatever the file happened to carry, and refuses a conversion that would make drawn pixels disappear.

  • Work you can check - assess_sprite measures the drawing itself: pixels with no neighbour of their own colour, jagged diagonals, how much of the canvas the art fills, whether it is centred, and what fraction of it sits exactly on a declared ramp. An agent cannot look at its own sprite, so every fault comes back as a line saying what it is and which tool puts it right, and remove_stray_pixels is the one that answers for noise.

  • Edits you can check - diff_sprites compares two frames and says what changed, in buckets that mean different things: pixels that entered or left the silhouette, pixels repainted inside it, and pixels that changed only their alpha. An edit that silently went nowhere, to the wrong layer, inside a stale selection, off the canvas, looks exactly like an edit that was not needed, so "nothing changed" is reported loudly rather than quietly. Pass expect= to turn the measurement into a check.

  • Animation you can check - offset_cels moves a cel along a line or an arc across any number of frames in one launch, with the spacing distributed so it reads as speed rather than as a limp; tween_cels does the other three things an inbetween does, scaling, turning and fading one drawn cel across frames, with the anchor on the contact edge so a squash lands on the ground; smear_frame draws one frame's subject along its own movement, stepping down a declared ramp so the trail stays on the palette; apply_timing_curve gives the cycle a shape in time by setting durations, never by duplicating a frame; and validate_loop measures the result and names the faults a still frame hides: a wrap frame repeating the first, a pose held by duplication, placeholder timing, a contact edge that drifts.

  • Calls you can check - the three bullets above measure the artwork; this one measures the call. A tool that did something other than what it was asked for is the failure this server keeps finding, and it is always quiet, so the result says what happened rather than that it happened. A write whose selection excluded every pixel reports pixels_outside_selection rather than a bare ok. shade_region_by_light and specular_highlight report region_components and region_bounds, because base_color scopes by colour distance and two materials' ramps are routinely closer than the default tolerance: every step of a gold ramp is within it of a step of a brass one, so a pass can land somewhere its caller never looked. generate_ramp reports distinct and, when lightness clamping has collapsed two steps onto one colour, the light_range that would not have. dither_band names the two colours its 1-based steps resolved to. Every one of those exists because its absence cost a debugging session, and the showcase generators are where they were spent. Pixel art is authored, not rendered, and the server now takes it that way: draw_pixel_map accepts the same character grid get_pixels(format="map") emits, so per-pixel intent can be written down and read back. A caller handed only a thousand-entry coordinate list does not write a thousand considered pixels, it writes a formula that emits them, and a formula produces the smooth monotone surfaces that make generated pixel art look generated. The shape is uniform rather than nearly uniform: every result that describes a sprite carries ok, which thirty of them did not until the key moved into the one function they all return through, and a workflow manifest reports the same pixel counters at its top level as a bare call does, so one check reads both.

  • Sandboxed file access: by default the file capability is scoped to the workspace (relative paths only; absolute/.. paths rejected unless you opt in).

  • No-clobber by default: output-writing tools refuse to overwrite an existing file; pass overwrite=True to replace it intentionally.

  • Structured results: every editing tool returns JSON describing the updated sprite, and every pixel-writing one returns how many pixels it wrote, clipped, skipped, or lost to an active selection.

  • render_preview returns a PNG so the agent can see its work and self-correct.

  • Deterministic, stateless, robust: each call is an isolated, headless Aseprite run.


Contents

Showcase

What the tools produce, with the numbers behind it: a lit scene, an equipment sheet, per-cel ordering, palette reduction

Requirements · Install · Configuration

Getting it running

Register with an MCP client

Claude Code, Claude Desktop, Cursor, Codex, Continue, Zed, Goose (full guide)

High-level workflows · Batch operations

Whole assets in one call; many edits in one process

Tool catalogue

All 163 tools by domain (full reference)

Live viewing · Example agent workflow

Watching edits land; an end-to-end run

How it works · Security

Architecture, the sandbox, and what is enforced

Notes & limitations · Troubleshooting

Honest edges, and what to do when something breaks


Related MCP server: aseprite-mcp

Showcase

Every image here was produced entirely through MCP tool calls, and every number under them is real output from the same run.

Shade a form, not a filter

create_sprite("orb.aseprite", 32, 32)
ramp = generate_ramp("#5a7fd4", steps=5, hue_shift=-40, saturation_shift=-18)["colors"]
draw_ellipse_in_box("orb.aseprite", 4, 4, 24, 24, ramp[2], filled=True)
shade_region_by_light("orb.aseprite", ramp, light_angle=125, light_z=0.55, rim=0.25)
dither_band("orb.aseprite", ramp, from_step=1, to_step=2, pattern="bayer4", width=2)
outline_smart("orb.aseprite", ramp, darken_steps=2, light_angle=125)

A brightness filter would have moved every pixel off the palette. These tools move pixels along the ramp, so the result still uses exactly the five colours it was given: the shading is made of the palette rather than applied on top of it.

Animate it, then measure the animation

frames = list(range(1, 13))
offset_cels("throw.aseprite", "ball",   frames, dx=46, arc_height=20)   # the arc
offset_cels("throw.aseprite", "shadow", frames, dx=46)                  # straight along the ground
apply_timing_curve("throw.aseprite", curve="hold_extremes", base_ms=70)
validate_loop("throw.aseprite", layer="ball", loops=False)
spacing      8.06  6.4  6.4  5.0  4.03  4.0  4.03  5.0  6.4  6.4  8.06
contact_row    32   25   20   16    13   12    12   13   16   20   25   32
durations     175   70   70   70    70   70   175   70   70   70   70   70
passed: true

An agent cannot watch a GIF play. It can read that the spacing is symmetric about the apex, that the ball slows as it rises and speeds as it falls, and that the extremes are held two and a half times as long as the passing frames.

Reorder one cel, not the layer stack

set_cel_z_index("swing.aseprite", "sword", frame=2, z=0)   # blade behind the shield
set_cel_z_index("swing.aseprite", "sword", frame=3, z=2)   # blade in front, same layer

A blade that crosses a shield is behind it on the approach and in front of it on the follow-through, and a layer stack cannot say that: a layer's position applies to every frame at once. Moving the layer changes the other frames; duplicating the sword onto a second layer means hiding one of the two per frame and keeping two drawings in step forever.

z is an offset on the layer's own stack position, so 0 means "wherever this layer sits" and a cel one layer down needs only z=1 to draw in front of the one above it. The result reports the frame's competing cels back to front, because a number alone does not tell you the arm moved:

frame 2  z=0  renders: sword then shield   pixel (45,20) is #5c7a3a, the shield's oak
frame 3  z=2  renders: shield then sword   pixel (45,20) is #eef1f5, the blade's steel

That pixel is the whole claim, and the generator asserts it: a z-index that round-tripped through the file while changing nothing about the render would produce an identical-looking strip. The blade is drawn long enough to show its tip on the far side, because "behind" only reads as occlusion when you can see both ends of the thing being occluded. Note also that z is refused outside -32768 to 32767, because the editor accepts a larger number in memory and then stores it in a 16-bit field, so saving and reopening turned 32768 into -32768.

Turn a blend into pixel art

quantize_palette("dusk.aseprite", max_colors=14)            # derive a palette from the art
set_color_mode("dusk.aseprite", "indexed", palette_source="keep")   # then map the art onto it

extract_palette reports the colours an image already uses and set_color_mode maps art onto a palette that exists; quantize_palette is the step in between, deriving a small palette from the artwork.

It is two calls on purpose, and the first one touches no pixels. Quantizing derives the palette and says so:

max_colors=14   palette holds 14, art has 117, 8 of them exactly
    warning: 109 of the 117 colours in the art are not in the derived palette and will be
             approximated by their nearest entry when the sprite is converted to indexed.
converted to indexed   3888 drawn pixels, verified=True, now 13 colours

verified=True is the conversion confirming it did not lose a single drawn pixel, which is the one thing a mode change must never do quietly. max_colors is also a ceiling with a cliff in it: a budget equal to the number of colours in the art is where the reduction collapses, and four colours at max_colors=4 come back as one averaged grey while max_colors=5 returns all four. The result says which happened rather than reporting a clean reduction either way.

Light a room, not a sprite

Three things in that picture are worth more than the picture.

Thirty-five blocks, one shading call. shade_region_by_light builds a distance field over everything matching one base colour, and a field over a mask with thirty-five disconnected parts describes each part on its own. The mortar joints are what make the mask thirty-five components instead of one slab, so the whole wall takes its form from a single call:

shade_region_by_light("dungeon.aseprite", STONE, base_color=STONE[8],
                      light_angle=155, bulge=0.75, tolerance=1.0, layer="wall")

An earlier version of this section claimed that and left out what it cost. The claim is only worth anything if the blocks come out different, and with every block 17 pixels wide they did not: a distance field over two components of the same size is the same field twice, so same-sized blocks are shaded identically and differ only in how far the falloff pushed them. Measured by normalising value away, so two blocks count as the same when their pixels rank the same whatever their brightness, 8 of 24 sampled blocks came back pixel for pixel identical at 6 tones, all in the dim zone where shift_along_ramp had clamped their darks together. The far wall was one tile repeated.

Two changes fixed it, and the generator now asserts both. Block widths cycle through (17, 11, 23, 14, 20) with a per-course phase, so the fields differ; and the ramps are thirteen steps rather than nine, so a darkened block still has somewhere to go:

wall: 35 blocks, 31 distinct shading patterns, 28 of them unique, every block at 4 tones or more

The falloff is zones down a ramp. No tool here lights a scene from a point, and faking one by blending would land every pixel between palette entries. shift_along_ramp moves a rectangle one or two steps down the surface's own ramp instead, which is how a pixel artist builds a falloff. The trick is hiding the seams, and that is why it is a rectangle per course rather than one band across the room: the only cut that does not show is one along a joint, and because the courses are staggered no single column is a joint on all of them.

falloff (one rectangle per course per zone)
  wall   45 blocks, 12 runs darkened, 6 blocks off-value
  floor  22 blocks,  8 runs darkened, 4 blocks off-value

floor row 56: step 8 at x=20, step 3 at x=95

That last line is asserted by the generator, because a falloff nobody measured is a falloff you have to take on trust. At one step a zone the assertion still passed and the room still looked evenly lit, which is a measurement being satisfied by something no reader can see. The reverse cost more: that same assertion went on passing while the far wall was a repeating tile, because nothing was measuring that. An assertion covers the failure it was written for and no other, which is why there are now three of them on this one picture.

The flicker is four frames with four durations. set_all_frame_durations would give an even pulse, and an even pulse reads as a machine rather than as fire. The flame also leans a different way and stands a different height on each frame, and the generator asserts all four silhouettes differ:

flame     rows  lean   ms  halo
  frame 1   14  +0.00   90  115 pixels in 3 rings
  frame 2   12  +0.18   70  103 pixels in 3 rings
  frame 3   15  -0.14  110  122 pixels in 3 rings
  frame 4   12  +0.10   80  116 pixels in 3 rings

The torchlight is the wall, brightened. This is the part that took the longest to get right, and the answer turned out not to be a tool. Three drafts used glow, whose rings are ramp steps rather than alpha, and all three read as a sticker. glow grows its rings outward from the subject's silhouette, so a tall narrow flame gives a tall narrow egg with a hard elliptical boundary, and it paints at full opacity, so inside it the mortar joints and the block shading vanish into a smooth oval. Light brightens a surface. It does not erase it.

So the pool is the masonry moved up its own ramp, by however many steps the distance from the flame allows:

lift = round(POOL_GAIN * (1.0 - reach / POOL_RADIUS) ** 2)
target = min(step + lift, len(STONE) - 1)

Every pixel on that wall is already an exact ramp entry, so finding its step is a table lookup and lifting it is arithmetic on an integer. One get_pixels over the pool's bounding box, one draw_pixels back:

light pool: lifted 1503 wall pixels up their own ramp, 0 off-ramp and left alone

The joints lift too, which is exactly why the masonry survives inside the light. glow is still there, at radius=3, for the heat right at the flame, which is the job it is good at.

The sconce casts onto the wall it is bolted to, with light_angle=90 and a high light_height so the shadow falls straight down and short. It had none for three drafts, which is the single commonest reason a lit object reads as pasted on.

The floor recedes. Its courses grow taller and its stones grow wider down the frame, because flat equal courses read as a second wall lying down:

floor: course heights [5, 6, 7, 8], stone widths [17, 21, 26, 31], down the frame

Where it meets the wall there is a shorter, darker skirting course and then three rows of flagstone stepped down their own ramp, rather than the four flat full-width rows an earlier version put there. That did stop two surfaces of grey blocks reading as one wall, the way a letterbox bar stops a bad crop.

The chest's shadow is cast_shadow with ground_layer="floor", which clips it to the flagstones so it cannot run off the floor and hang in the air, and it uses the floor's ramp rather than the chest's, because a shadow is a darkening of what it lies on. The chest's own contact shadow had to move: contact_shadow takes the occluder's colour, and run after the brass pass that had already repainted the straps, only 3 pixels of the chest were still the colour it was given. It runs before that pass now and reports 102 darkened wood pixels, which the generator asserts is not zero.

Animate a palette, not the pixels

Every other animation here moves something. This one moves nothing: there is one drawn frame, and the lava flows because its indices rotate. cycle_palette generates the timeline from that single frame, and the twenty-four frames of the loop contain no new drawing at all.

The technique constrains the art rather than the other way round, and lava.py records the three drafts it took to learn how. A rotation can only translate a pattern that is monotone in index space, so the lava has to be painted as a sawtooth of consecutive indices laid across the direction of travel; a triangle would reflect instead of flowing. The run has to close, because a one-way dark to white ramp puts a bright-to-black seam at every wrap, which reads as a moving staircase. And it has to be long and weighted: with eight entries the bright one recurs every eight pixels, which is a bright line every eight pixels however the brightnesses are arranged, so the fall came out as a drill thread. This run is twenty-four entries of which twelve are crust that barely differ, built by three ramp_between calls joined at shared ends, and what travels is the crack.

The direction is a sign, and not the one you would reason to. step=1 puts frame two's row y where frame one's row y - 1 was, so the pattern travels down and the cataract falls. The first draft had it running uphill.

The cataract and the pool drift differently, and both come out of the same call: the fall is banded by row and the pool across the flow, so one rotation moves one down and the other sideways. Nothing in the generator says "move this down and that right".

The stone is the control, and the generator holds it to that: it reads the same rock window on all twenty-four frames and requires it unchanged, which is what separates "the colours rotated" from "the picture was redrawn". It also checks the flow by comparing two frames through a shifted window, which is how the backwards step was caught. Aseprite's Lua API exposes no per-frame palette (measured on 1.3.18.6 and written down in cycle_palette's own docstring), so the rotation is applied to the pixels' own indices and the result says which mechanism ran: method: "pixel_remap". On an indexed sprite the two are the same picture, and the move never routes a colour through a nearest-entry match, so the palette comes back byte for byte.

Scaffold a one-shot, and let the timing do the hitting

A one-shot is where a scaffolded animation goes wrong in three ways at once: the frame count is a guess, the frames are numbered instead of named, and the whole thing is tagged as a loop with uniform timing. scaffold_cycle(kind="attack") settles all three before a pixel is drawn, and attack.py is the drawing laid over what it built.

The timing is the part worth looking at, and it is not the timing you would guess. The curve puts the 24-millisecond frame on the swing, not on the impact:

phase

duration

why

anticipation

240 ms

the wind-up, held long enough to read as intent

swing

24 ms

one frame you barely see, which is what makes it a snap

impact

200 ms

held, because the hit has to land rather than flash past

recoil

80 ms

recover

80 ms

That ordering is the craft: the fast frame is the blur between poses, and the pose that has to be understood is the one that holds. Uniform timing at 80 ms would run the same five drawings in the same order and read as a shove. The generator pins the snap to frame two for exactly that reason, because "the shortest frame is the impact" is the plausible wrong answer and a test that only checked for non-uniformity would accept it.

Each phase gets a tag named for the pose (attack_anticipation through attack_recover, plus attack over the whole cycle), and every one is written with repeats=1 rather than left at 0, which means "play forever" in the file format. That field is what validate_loop reads, so a one-shot tagged as a loop makes the checker report a duplicated seam frame on an animation that has no seam. The per-phase tags matter as much as the whole-cycle one, since a single-frame tag left looping says "hold this pose forever".

validate_loop also found an art bug here, which is the kind of thing this server is for: it reported the drawn content's bottom row moving 4px across the phases, because the recover blade was swinging clean through the floor. Fixing the arc did not end it either, since the centreline then cleared the ground and the blade's own thickness still did not. The generator checks that directly now, because a background was added and the contact measurement stopped being able to say so.

Make fast movement read as speed, in colours the sprite already had

Two frames of something moving quickly are two frames of it being in two places, which the eye reads as teleportation. A smear is the frame an animator draws to fix that, and smear_frame takes the movement vector from the cels themselves, so there is nothing to keep in sync with the drawing. Top to bottom: the movement as it arrives, the stretch smear that elongates the subject back along its path, and the echo smear that draws it several times.

The trail is made of colours the sprite already had. Each pixel of it is the nearest ramp entry to the subject's own colour there, stepped toward the dark end and clamped, so the smear never invents a colour and palette_conformance stays at 1.0. smear.py asserts that directly: every colour in the trail is on the ramp it was given, the trail lies between the two positions, and the subject's own pixels are untouched because the trail goes behind it.

This piece is indexed on purpose, because smear_frame was the one ramp-taking tool with no reading of what its ramp becomes on a palette: it resolves the ramp in Python into a lookup table and never passes a ramp to Lua, so the harness that measures that had nothing to see. The reading exists now, and building this piece immediately taught three things the docstring does not say.

A stretch trail asks for one shift level per ramp entry, so it is as long as the ramp, and it measures its room by where the subject's lightest colour sits. Two drafts went into lengthening the ramp and shortening the movement before the message was read properly: what fixed it was giving the sphere a specular highlight, so a pixel finally sat on the ramp's top step. A highlight turned out to be load-bearing.

And on a shaded subject the reading then fires anyway, in both modes, because the darker pixels run out of ramp before the trail ends and clamp at the dark entry. That is not avoidable by drawing better: the only subject that cannot clamp is one painted in a single colour. The reading used to blame the palette for it and suggest adding colours, while its own numbers said the palette held every target exactly (#226). It now tells the two apart, a clamp being copies that wanted one colour and a short palette copies that wanted several, and gives each its own remedy: for a stretch, mode='echo'. The generator asserts on the sentence as well as on trail_on_palette's counts, and the "crushed palette" case it builds turned out to be clamps too: the two colours there that share a palette entry belong to different parts of the subject, so no copy merges because of the palette.

Scaffold a whole asset in one call

validate_sprite_for_game_export -> passed  (width, height, color_mode, min_frames, required_tags)
export_game_asset_bundle        -> hero.png, hero.gif, hero_sheet.png (+JSON), hero_idle.gif, manifest.json

sword   17 colours, from 4 ramps and nothing else
shield  19 colours, from 3 ramps and nothing else
helm    12 colours, from 2 ramps and nothing else
key      9 colours, from 1 ramp and nothing else
scroll  14 colours, from 3 ramps and nothing else

sword: blade is rows 0 to 26, 68% of its height
centres: sword=19.5  shield=19.0  helm=19.0  key=19.5  scroll=18.5   spread 1.0

Those checks earn their keep, and each of them was added after the thing it checks had already gone wrong.

The colour census: base_color scopes a shading pass by colour distance, and at the default tolerance of 24 every step of a gold ramp is within reach of a step of a brass one, so a pass meant for one item also matched art in a different cell and reshaded it. Nothing looked wrong, and three rounds went into redrawing the wrong thing before the colours were counted. That was #183, and it is fixed: both tools report region_components and region_bounds now, so a pass scoped to a 27px coin that comes back with a box spanning 200 pixels of canvas says so in its own result. The census here stays, because a script asserting what it needs is cheaper to read than one trusting that someone else asserted it.

The blade's share: a draft of this sword was 54% blade at a 1 to 2.3 aspect, which is a spearhead, and at inventory size it read as a crystal shard on a stick. 54% is not something anybody notices as a number, which is the whole reason for printing it.

The centre line: five items at five different heights read as five sprites from five games.

A fourth check, not shown here, asserts each glint's pixels are inside the part named for it. Two of the four used to be wrong: scoped to a whole 40px cell, specular_highlight built its normals from the entire compound object, and the sword's glint landed on its leather grip while the blade had none. It is worth knowing that check has a hole in it too, because the key passed it while still being wrong: it proves a glint is on the right part, not on the right side of it.


Requirements

  • Aseprite 1.3+ (the scripting API). The Steam and standalone builds both work.

  • Python 3.10+

  • uv (recommended), or any PEP 517 installer.

Install

git clone https://github.com/MalloyTheDev/aseprite-mcp.git
cd aseprite-mcp
uv sync

That creates a virtual environment and installs the aseprite-mcp package and its dependencies. The test suite comes in two tiers: the pure-Python tests always run, and the ones that drive a real Aseprite are opt-in behind --run-aseprite (and skip, saying so, when the flag is given and Aseprite cannot be found):

uv run pytest                  # pure-Python tests; no Aseprite needed
uv run pytest --run-aseprite   # plus the integration and golden-output tests

Configuration

Everything is configurable via environment variables (all optional):

Variable

Purpose

Default

ASEPRITE_PATH

Full path to Aseprite.exe / aseprite.

Auto-detected (Steam, standalone, PATH).

ASEPRITE_MCP_WORKSPACE

Folder where relative sprite paths are resolved.

<repo>/workspace from a source checkout, otherwise a per-user data directory.

ASEPRITE_MCP_TIMEOUT

Per-operation timeout in seconds (clamped to 1-3600).

90

ASEPRITE_MCP_ALLOW_ABSOLUTE

Allow absolute / workspace-escaping paths (1/true to enable).

off (sandboxed)

ASEPRITE_MCP_TRANSPORT

stdio, streamable-http, or sse. See the warning below before using an HTTP transport.

stdio

stdio is the right default: it is what desktop MCP clients launch, and it keeps the server reachable only by the process that started it. The HTTP transports exist for agents that cannot spawn a local process. Treat them as a deliberate exposure decision: this server's file access is scoped by a workspace directory, not by an identity, so binding it to a reachable port gives every caller that can reach it the same filesystem access the local user has. Bind to loopback, or put authentication in front of it.

On this machine Aseprite was detected at C:\Program Files (x86)\Steam\steamapps\common\Aseprite\Aseprite.exe, so ASEPRITE_PATH is not strictly required, but setting it explicitly is the most reliable.


Register with an MCP client

Using something other than Claude? docs/CLIENTS.md has a copy-paste config block per client format (Codex CLI's TOML, Continue's config.yaml, Zed's context_servers, Goose's extensions, and the mcpServers JSON that Claude Desktop, Cursor, Cline, Roo Code, Windsurf and LM Studio share), the config file path for each one, the launch form that avoids the Windows venv lock, and the strict-mode notes for OpenAI or Grok style function-calling bridges. The two quick starts below cover the common case.

Replace /ABSOLUTE/PATH/TO/aseprite-mcp below with the absolute path to your clone.

Claude Code (CLI)

claude mcp add aseprite -- uv --directory /ABSOLUTE/PATH/TO/aseprite-mcp run aseprite-mcp

To set the Aseprite path explicitly (recommended if auto-detection fails):

claude mcp add aseprite \
  --env ASEPRITE_PATH="/path/to/Aseprite.exe" \
  -- uv --directory /ABSOLUTE/PATH/TO/aseprite-mcp run aseprite-mcp

Claude Desktop / generic MCP client (JSON)

Add this to your client's MCP server config (e.g. claude_desktop_config.json). A ready-to-copy template lives in mcp-config.example.json (Windows-style paths shown; adjust for your OS):

{
  "mcpServers": {
    "aseprite": {
      "command": "uv",
      "args": ["--directory", "C:\\path\\to\\aseprite-mcp", "run", "aseprite-mcp"],
      "env": {
        "ASEPRITE_PATH": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Aseprite\\Aseprite.exe",
        "ASEPRITE_MCP_WORKSPACE": "C:\\path\\to\\aseprite-mcp\\workspace"
      }
    }
  }
}

Restart the client; the aseprite server and its full tool set will be available (the current count is at the top of docs/TOOLS.md). Ask the agent to run health_check to confirm Aseprite is wired up correctly, and see docs/CLIENTS.md for what the answer should look like.


High-level workflows

Beyond the low-level tools, a few workflow tools scaffold a whole asset in one call and return a manifest (created files, paths, frames, tags, dimensions, and suggested next steps) so an agent can keep going. They compose the low-level tools: deterministic scaffolding, no AI generation.

Tool

Description

create_character_sprite

Transparent canvas + body/details layers + a generated shading ramp + an outlined placeholder.

make_4_frame_idle_animation

Turn a 1-frame sprite into a 4-frame idle "bob" loop with a tag.

scaffold_cycle

Scaffold a named cycle (walk, run, idle, attack, hurt, death) at its conventional frame count, one tag per phase (walk_contactL, walk_downL, ...), durations shaped by a timing curve rather than uniform, and loop or one-shot set correctly: attack, hurt and death are one-shots.

create_tileset_project

Canvas + tilemap layer + a starter tileset (grass/dirt/water/stone, or your own).

create_icon_set

Grid sheet of icon cells, each a placeholder inside a named slice (icon_0, …).

create_rpg_item_sheet

Grid sheet with a named slice per item (sword/shield/potion/…).

make_8_direction_walk_template

8-direction walk template: frames + one tag per direction (N/NE/E/…).

export_game_asset_bundle

PNG + animated GIF + sprite sheet (+ JSON) + per-tag GIFs + manifest.json. Assesses every frame first and refuses on a measured defect (an absent keyline, or with ramp, a pixel off it) unless allow_defects=True; every other reading is listed in the manifest's assessment.

export_godot_spriteframes

Godot 4 SpriteFrames resource (.tres) + packed sheet; one animation per tag, timed from frame durations.

export_slice_metadata

Engine-agnostic <sprite>_slices.json: hitbox/hurtbox/collision/attach/9-slice/pivot from slice names or JSON data.

validate_sprite_for_game_export

Check a sprite is game-ready (dimensions/tile multiple, colour mode, frames, required tags, transparency, palette budget, exports exist) → pass/fail report.

validate_asset_spec / plan_asset_spec / build_asset_from_spec

Describe an asset once (aseprite_mcp.asset_spec.v1), then validate it, dry-run the plan, or build it (structure only, canvas/layers/frames/tags/slices/palette + exports; you draw the art).

validate_asset_against_spec

Closes the loop: does the sprite that got built actually match the spec it was built from. Canvas, layer names, frame count, tags, slices, palette capacity. Reports what it checked as well as what failed, so "nothing was wrong" and "nothing was checked" cannot be confused.

"Make me an idle-animated hero and a game-ready bundle."

  1. create_character_sprite("hero", 32, 32, base_color="#3878c8") builds layers, palette and a placeholder.

  2. Draw the character on the body / details layers (low-level tools).

  3. make_4_frame_idle_animation("hero.aseprite") makes a 4-frame loop tagged idle.

  4. validate_sprite_for_game_export("hero.aseprite", expected_width=32, required_tags=["idle"]) confirms it is game-ready.

  5. export_game_asset_bundle("hero.aseprite", scale=8) judges every frame, then writes PNG/GIF/sheet+JSON/manifest into hero_bundle/. A defect refuses the bundle with the frames and the fix named; the manifest's assessment lists the readings worth a look that do not block it.

Bring art in from elsewhere

Art made outside the server (a PixelPrep conversion, a downloaded sheet, a screenshot) comes in through two tools, and the rest of the toolset then works on it as on anything drawn here.

  1. import_image("scene.png", "scene.aseprite") for one picture. A PNG with an alpha channel, which is what PixelPrep writes, arrives as an ordinary layer; an opaque one without alpha, or an opaque indexed PNG, arrives as a Background, which Aseprite draws opaque everywhere.

  2. import_spritesheet("walk.aseprite", "walk_strip.png", 32, 48) for a strip, a column (layout="vertical") or a grid (layout="grid") of frames. A cell size that does not divide the sheet is refused before anything is launched, and spare grid cells come back as empty_frames.

  3. set_color_mode("scene.aseprite", "indexed") to limit the palette. An opaque scene keeps every pixel: one of its colours can land on the transparent index (in both scenes tried while building this it was the darkest), which a Background shows as a colour, and the readers and drawing tools treat it as one.

  4. assess_sprite and render_preview to look at it (a large scene previews at a scale that keeps the image within 2048 px), then edit it like any other sprite.

  5. For animation, export_motion_trail shows every frame of a motion in one image, so arcs and spacing can be judged before anything is exported.

Workflow manifest contract

Every workflow tool returns a standardized workflow_manifest.v1 object (defined in core/manifest.py) so the asset layer stays consistent as it grows. Always present: ok, schema_version, kind, created_files[], suggested_next_actions[], warnings[]. Included when relevant: sprite{}, exports[], palette{}, animation{}, tilemap{}, tiling{}, validation{}, operations[], plan[] and dry_run. File/export entries are {role, path, format, metadata_path?}.

A manifest also reports what it wrote, at the top level beside ok: pixels_written, pixels_clipped, pixels_skipped, pixels_outside_selection, selection_applied and linked_frames_also_changed. Top level rather than in a pixels section of their own, because the sections above each describe the product while these are a verdict on the call, and because every other result in this server reports them there: one rule reads them across all 163 tools. They are absent rather than zero, so a key that is present at all means there is something to read, and a tool that writes no pixels grows no 0 that reads as a claim about pixels. apply_operations used to drop them, which let a batch report status: applied for an op whose every pixel an active selection had refused.

{
  "ok": true,
  "schema_version": "workflow_manifest.v1",
  "kind": "character_sprite",
  "sprite": { "path": "...", "width": 32, "height": 32, "color_mode": "rgb",
              "frames": 1, "layers": ["body", "details"], "tags": [] },
  "created_files": [ { "role": "source_sprite", "path": "...", "format": "aseprite" } ],
  "palette": { "colors": ["#1b1f2a", "..."], "count": 5 },
  "pixels_written": 437,
  "suggested_next_actions": ["Draw the character on the 'body' layer", "..."],
  "warnings": []
}

Batch operations

apply_operations applies a list of edits to one sprite in a single Aseprite process, atomically: open once → run every op inside one transaction → save only if all succeed. This collapses multi-launch agent flows (add layer → draw → add frame → tag) into one fast, all-or-nothing call. Pass dry_run=true to validate the op list without launching Aseprite.

apply_operations("hero.aseprite", [
  {"op": "add_layer",      "args": {"name": "fg"}},
  {"op": "fill_layer",     "args": {"layer": "fg", "color": "#1d2b53"}},
  {"op": "draw_rectangle", "args": {"layer": "fg", "x": 2, "y": 2, "width": 12, "height": 8, "color": "#ff004d"}},
  {"op": "add_frame",      "args": {"copy_from": 1, "duration_ms": 120}},
  {"op": "add_tag",        "args": {"name": "idle", "from": 1, "to": 2}}
])

If any op fails, the whole batch rolls back and the error names the failing op index. v1 ops: layer add/rename/visible/opacity/remove · frame add/duplicate/remove/duration/all-durations · cel position/opacity/copy/delete · tag add/remove · draw set_pixel/pixels/line/rectangle/fill_rectangle/ellipse/fill_ellipse/fill_layer/clear_layer · slice add/remove · replace_color.


Tool catalogue

Relative filenames resolve inside the workspace (absolute paths require ASEPRITE_MCP_ALLOW_ABSOLUTE=1; see Security). Frames and palette-aware operations are 1-based for frames, 0-based for palette indices. Colours accept #RRGGBB, #RRGGBBAA, r,g,b, r,g,b,a, index:N, or a name (black, white, red, green, blue, yellow, cyan, magenta, transparent, …).

Sprite lifecycle

Tool

Description

create_sprite

Create & save a new sprite (rgb/indexed/gray, optional background; indexed starts with a usable palette).

save_sprite_as

Save a copy under a new path (optionally flattened).

set_color_mode

Convert between rgb / indexed / gray (with dithering); builds the palette from the art and refuses to drop pixels.

resize_canvas

Change canvas size without scaling art (top_left / center).

crop_sprite

Crop the canvas to a rectangle.

scale_sprite

Scale the whole sprite (by factor or to dimensions; nearest/bilinear).

flatten_sprite

Flatten all layers into one.

trim_sprite

Auto-crop the canvas to non-transparent content.

convert_layer_to_background · convert_background_to_layer

Toggle the opaque Background layer.

Inspection & preview

Tool

Description

get_sprite_info

Full structured state: size, mode, frames, layer tree, tags, palette.

render_preview

Render a frame to a PNG image you can view, scaled up for small sprites; a large one is fitted to 2048 px on its longer side. A frame the sprite does not have is refused. views shows it several ways side by side from the same render: color, value (greys of each colour's own lightness, for whether the forms read without hue), silhouette (black on white, for whether the shape reads and its parts have air between them) and actual (1x).

get_pixels

Read the pixel colours of a region, composited or from one named layer, as rows or as a compact symbol map (≤ 64×64 per call).

assess_sprite

Measure the drawing: colours and ramps, noise, jagged diagonals, how much of the canvas is used, centring, symmetry, palette conformance against a declared ramp, and tile seams. Each measurement worth acting on comes back with a line saying why.

diff_sprites

Compare two frames pixel for pixel: pixels added to or removed from the silhouette, repainted inside it, or changed in alpha alone, plus the colours involved and the box they sit in. Says so loudly when nothing changed, and takes expect= to turn the measurement into a pass or a fail.

list_sprites

List sprite/image files in the workspace.

Layers

Tool

Description

add_layer

Add a layer (optional group, opacity, blend mode, visibility).

add_group_layer

Add a group layer.

remove_layer · rename_layer

Delete / rename a layer.

set_layer_properties

Update opacity, blend mode, visibility, editability, name.

move_layer

Reorder a layer (1-based stack index, 1 = bottom).

duplicate_layer · merge_layer_down

Duplicate / merge a layer down.

Frames (animation)

Tool

Description

add_frame

Add a frame: empty at the end, or a copy right after the frame it copies.

duplicate_frame · remove_frame

Duplicate / delete a frame.

set_frame_duration · set_all_frame_durations

Set per-frame / uniform durations (ms).

reverse_frames · move_frame

Turn a run of frames round, or move one frame to another position. Cels on every layer, durations and cel links all travel with the frame.

Cels (a layer's image at a frame)

Tool

Description

get_cel

Inspect a cel (exists, position, bounds, opacity).

set_properties · get_properties

Read / write custom properties on a sprite, layer, cel, tag, slice or tile, stored inside the .aseprite file so game metadata travels with the art instead of in a sidecar.

set_cel_position · set_cel_opacity

Move / fade a cel.

copy_cel · delete_cel

Copy a cel between frames / delete it.

link_cels · unlink_cels

Share one image across frames (a held pose: editing any of them edits all, and the file stores it once) / give a frame its own copy back.

set_cel_z_index

Reorder one cel against its layer's neighbours, for a limb that is in front on one frame and behind on the next, without restructuring the layer stack.

Animation tags

Tool

Description

add_tag

Tag a frame range with a name, direction, colour, and a repeat count (0 means forever, which is how a cycle is marked).

set_tag · remove_tag

Edit / delete a tag.

Animation (motion, timing, checks)

Tool

Description

offset_cels

Move a drawn cel along a line or an arc across frames in one launch, spacing distributed so it reads as speed rather than as a limp.

tween_cels

Scale, turn and fade one drawn cel across frames in one launch: squash and stretch (the two axes go opposite ways), whole-degree rotation sampled nearest-neighbour so no colour is invented, and a fade that sets cel opacity rather than baking alpha. anchor="bottom" squashes onto the ground, which validate_loop's contact check then confirms.

smear_frame

Draw one frame's subject along its own movement, so fast motion reads as speed rather than as teleportation. stretch elongates it and thins to a point; echo draws it several times. The vector comes from the cels themselves, and with a ramp every trail pixel is a colour the sprite already had.

apply_timing_curve

Give a cycle a shape in time (hold_extremes, attack, ease_in, ease_out, flat), or hold and snap named poses. Sets durations and never duplicates a frame.

validate_loop

Measure a cycle instead of playing it: per-frame hashes, spacing, contact rows, durations, and the faults a still frame hides (a wrap frame repeating the first, duplicated poses, placeholder timing, a drifting contact edge).

Easing belongs in one of these at a time. Eased spacing plus an eased duration curve is the same curve applied twice, and reads as slow motion; apply_timing_curve measures the cels and says so rather than doing it quietly.

Drawing

Tool

Description

draw_pixels

Plot individual pixels (per-pixel or shared colour).

draw_pixel_map

Draw from a character grid, one character per pixel, with a legend of symbol to colour. The write side of get_pixels(format="map") and the same shape it returns, so a read, an edit and a write round-trip. A ragged map is refused rather than padded, and a character the legend does not define is refused rather than skipped: a typo in a grid would otherwise paint nothing and report success.

draw_line · draw_polyline

Line / connected segments; pixel_perfect & antialias options.

draw_curve

Quadratic Bézier curve.

draw_rectangle · draw_ellipse

Outline or filled rectangle / ellipse; ellipse has antialias.

draw_ellipse_in_box

An ellipse filling the same bounding box draw_rectangle takes, so an even diameter is possible and a circle can line up with a rectangle.

fill_area

Flood fill (paint bucket) from a point.

fill_layer · clear_layer

Fill the whole cel / erase it to transparent.

Brushes & symmetry

Tool

Description

draw_brush

Stamp a custom brush shape (ASCII mask) at many points.

stamp_pattern

Tile an image/sprite across a region (with spacing, opacity, blend).

mirror_layer

Reflect one half of a layer onto the other (build symmetric art).

draw_symmetric_pixels

Plot pixels with horizontal/vertical/4-way mirroring.

Shading & light

Tool

Description

shade_region_by_light

Shade a flat region as a lit form, from a ramp and a light direction.

shade_facets

Shade a form built from flat planes, one tone per plane, from a map whose legend names directions instead of colours. For anything hard: a crate, a helm, cut stone. shade_region_by_light reads its normals from the silhouette's distance field, so it rounds a form over and a block comes out a pillow.

gradient_map

Put every pixel on a ramp by its brightness, whatever it started as: the tool that brings imported or filtered art onto a palette at all. Optional ordered dithering.

shift_along_ramp

Move pixels along a colour ramp, keeping every one of them on the palette.

specular_highlight

Place a small glint where the light reflects at the viewer, never on an edge pixel. The ramp's top step, or a brighter colour for metal.

contact_shadow

Darken the pixels where one form meets another, along its ramp.

seam_occlusion

Darken the seam where two masses of the same material overlap, from a character map whose legend names the masses and says which is nearer the viewer. contact_shadow finds its occluder by colour, so it cannot see an arm against a torso cut from one stone. Falls off with distance, so the contact does not read as drawn brickwork.

surface_emission

Light an interior source onto the surface around it, up that surface's own ramp by distance. glow builds its halo on a layer below the art, so a core inside a silhouette gets nothing; this warms the stone instead, and two tones at one distance move together so the form survives.

outline_smart

Outline a shape in colours taken from its own ramp, not one flat colour.

dither_band

Dither the boundary between two adjacent ramp steps, widening the transition.

Selections

Tool

Description

select_region

Select a rectangle, ellipse, or polygon (replace/add/subtract/intersect).

select_by_color

Magic wand: select every pixel matching a colour.

modify_selection

Grow, shrink, or outline the current selection.

invert_selection · deselect

Swap selected for unselected / clear it.

get_selection

Report whether there is a selection and what it covers.

A selection is not stored in the .aseprite file, and every call here is its own Aseprite process, so it is kept in a .msk sidecar beside the sprite and loaded again on the next call. It scopes every later edit until deselect, which is how an image editor behaves, and every result that touched pixels reports selection_applied.

"Scopes every later edit" is now enforced rather than asserted. The mask is consulted in one function that every write goes through, and a test holds each write path to it separately, asserting the pixels outside the selection rather than a count. That is there because nine of them used to bypass it: the anti-aliased coverage write, the flood fill, every per-pixel effect pass, mirror_layer and the batch runner's replace op all edited the whole layer while the result still said selection_applied: true. A count can be satisfied by a tool that wrote the right number of pixels in the wrong places.

Slices (named regions / 9-patch)

Tool

Description

add_slice · set_slice · remove_slice · list_slices

Manage slices with optional 9-patch center, pivot, colour, and data.

Effects & colour adjustments

Tool

Description

fill_gradient

Linear/radial gradient, multi-stop, optional Bayer dithering.

fill_checkerboard

Two-colour checkerboard pattern.

add_outline

Pixel outline around art (outside/inside, 4/8-connectivity, thickness). With a light angle the weight tapers across the terminator, 2 then 1 then 0 over a band of edge, instead of switching per pixel and breaking the keyline into scraps.

add_drop_shadow

Hard drop shadow on a new layer beneath the art.

cast_shadow

A shadow on the ground, away from the light and foreshortened by its height, built of ramp steps and clipped to the surface it falls on.

glow

A halo of several rings, each a step further down a ramp, optionally dithered at the outer edge. Its own layer, so deleting it removes the effect, and one cel a frame, so one layer carries an animated one.

replace_color

Swap a colour (with per-channel tolerance).

remove_stray_pixels

Replace pixels with no neighbour of their own colour by the colour around them: the dirt a shading pass leaves, without touching a dither or introducing a colour.

normalize_edge_runs

Even out the run lengths along a silhouette's diagonals, which is the wander that reads as programmer art. Merges a stray one-row run into its neighbour and reports the jagged-corner count before and after; it only ever adds a pixel, so the extent cannot move, and it declines a 1:1 diagonal, a spike, a notch or a hairline by name.

invert_colors

Invert RGB (alpha preserved).

adjust_brightness_contrast · adjust_hue_saturation · desaturate

Colour grading.

Text

Tool

Description

draw_text

Render text (built-in bitmap font or a TrueType file) as crisp pixels.

Tilemaps (Aseprite 1.3+)

Tool

Description

create_tilemap_layer

Create a tilemap layer with a tile size + empty grid.

add_tile · fill_tile · paint_tile_pixels

Define/draw the tileset artwork.

set_tile · set_tiles · fill_tilemap

Place tiles on the grid.

get_tilemap

Read the grid of tile indices.

Image stamping

Tool

Description

stamp_file

Composite another image/sprite file onto a layer (opacity, blend mode).

draw_image_base64

Composite an inline base64 image onto a layer.

Palette

Tool

Description

get_palette · set_palette

Read / replace the whole palette.

set_palette_color · add_palette_color · resize_palette

Edit individual entries / size.

load_palette

Load a palette from .gpl/.pal/.png/.aseprite.

set_transparent_color

Set the transparent index (indexed sprites).

extract_palette

Collect the unique colours used in a sprite/image.

sort_palette

Sort by hue/luminance/saturation/value (remaps indexed pixels).

quantize_palette

Derive a palette from the artwork itself, reduced to at most N colours.

list_palette_usage

Which palette indices the art actually draws with, as runs of consecutive entries, so the run worth cycling is visible before you cycle it. Indexed sprites only, because an RGB pixel carries no index.

cycle_palette

Animate an indexed sprite by rotating a run of palette indices across new frames, the classic palette-cycling effect for water, fire and glows. Aseprite's Lua API exposes no per-frame palette, so the rotation is applied to the pixels' own indices and the result says so (method: "pixel_remap").

generate_ramp

Build a hue-shifted shading ramp from a base colour. Says how many steps came back distinct, since lightness clamps at both ends.

ramp_between

Build a ramp from its two ends, the cool shadow and the warm highlight, interpolated in Oklab so the middle is a blend rather than a hue rotation.

ramp_from_art

Recover the ramp a sprite is already painted with, ordered dark to light, with the share of the art each step covers.

Palette cycling is the one animation technique here that moves no pixels: rotate a run of indices and water flows, lava creeps, a portal turns. list_palette_usage is the step before it, because the run worth cycling is a property of the art rather than of the palette: an index the drawing never uses contributes nothing, and a run of two is a flicker rather than a flow. One measured limitation shapes the tool: Aseprite's Lua API exposes no per-frame palette, so the rotation is applied to the pixels' own indices instead and the result says which it did (method: "pixel_remap"). On an indexed sprite the two are the same picture, and the move is exact because it never resolves a colour to a nearest entry.

Transform & export

Tool

Description

flip_sprite · rotate_sprite

Flip (h/v) / rotate (90/180/270) the whole sprite.

export_png

Export one frame as a flattened PNG (scaled).

export_gif

Export the animation as an animated GIF.

export_tag_gif

Export only a named tag's frames as a GIF.

export_spritesheet

Pack frames into a sheet (+ JSON metadata; layer/tag filters & splits).

export_spritesheet_packed

Pack frames with extrude (the one-pixel border that stops texture bleeding in a game engine), merged duplicates and trim.

export_frames

Export each frame to its own file ({frame} pattern).

export_layer · export_layers

Export one layer / each layer to separate files.

export_tags

Export each animation tag's frames to separate files.

export_onion_skin

Render a frame with neighbouring frames ghosted behind it.

export_motion_trail

Every frame of a motion in one image, oldest faintest, so arcs and spacing can be judged at a glance.

import_image

Build an editable .aseprite from a flat image.

import_spritesheet

Slice a sprite sheet image into frames, one per cell: a strip, a column or a grid.

Minecraft resource packs

Tool

Description

export_minecraft_texture

Export a sprite into a resource pack at its correct texture path.

validate_minecraft_texture

Check a sprite against Minecraft's texture rules before it ships.

write_pack_mcmeta

Write pack.mcmeta, the file that makes a directory a resource pack.

write_texture_mcmeta

Write the <texture>.png.mcmeta sidecar for an animated texture.

Reference / rotoscope

Tool

Description

add_reference_layer

Add a dimmed, locked layer holding a reference image to trace over.

import_reference_sequence

Import a sequence of images as per-frame references (rotoscoping).

Batch operations

Tool

Description

apply_operations

Apply many edits to one sprite atomically in a single process (dry_run to validate only). See Batch operations.

GUI companion mode

Tool

Description

open_in_editor

Open a sprite in the live Aseprite GUI window (non-blocking) to watch edits.

gui_available

Report whether the Aseprite GUI can be launched.

Health & self-test

Tool

Description

health_check

Self-test: Aseprite found?, version, workspace, tool count, and a real create+export round-trip.


Live viewing (GUI companion mode)

The server edits files headlessly, but you can watch the work in the real Aseprite window. Call open_in_editor("sprite.aseprite") and Aseprite opens it in a normal, non-blocking window. As the agent keeps saving edits with the other tools, Aseprite detects the on-disk change and offers to reload (or reloads automatically, depending on your Aseprite preferences), so edits appear without re-opening.

What this is and isn't: Aseprite's Lua scripting sandbox has no networking or timers, so the server can't stream a live canvas into the GUI frame-by-frame. The companion view above (open once → headless edits → Aseprite reloads) is the robust, supported workflow. The agent's own "eyes" remain render_preview, which returns a PNG it can inspect directly.


Example agent workflow

"Make me a 32×32 walking-slime animation."

  1. create_sprite("slime.aseprite", 32, 32, "rgb")

  2. fill_layer the background, add_layer("slime.aseprite", "slime"), draw the body with draw_ellipse/fill_area/draw_pixels.

  3. add_frame("slime.aseprite", copy_from=1) a couple of times; nudge the body with set_cel_position to create a bounce.

  4. set_all_frame_durations("slime.aseprite", 120) and add_tag("slime.aseprite", "walk", 1, 3, "pingpong").

  5. render_preview to check it, iterate, then export_gif("walk.aseprite", "walk.gif", scale=8). Pass loop=False for a one-shot: an attack or a death is not a cycle, and a GIF declares that in its own metadata rather than in a caption.


How it works

client (any MCP client) ──MCP──> aseprite-mcp (MCPServer, Python)
                              │  builds a Lua body + ARG table
                              ▼
                         luagen.assemble_script  ──>  temp .lua
                              │   (prelude: JSON encoder, colour/pixel
                              │    helpers, drawing primitives, info)
                              ▼
                  Aseprite.exe -b --script temp.lua
                              │  prints  @@ASEMCP@@<json>  (or @@ASEMCP_ERR@@)
                              ▼
                         runner parses the sentinel  ──>  dict back to the client

Drawing primitives (line, rectangle, ellipse, flood fill) are implemented deterministically in Lua and operate on a full-canvas copy of the target cel, so coordinates are always in sprite space and results are identical across runs. Exports use the Aseprite CLI's native flags (--sheet, --scale, --data, …).

Project layout

src/aseprite_mcp/
  app.py          MCPServer instance, tool classification, portable schemas
  server.py       imports every tool module, picks the transport, main()
  core/           config (locate Aseprite, workspace, path sandbox), paths (output
                  paths + the no-clobber check), limits, errors, models, luagen
                  (Python->Lua + the shared PRELUDE), runner (run_lua / run_cli,
                  sentinel parsing), oplib (the batch op registry), manifest,
                  validation, asset_spec, minecraft, engines/ and slice_metadata
                  (engine export formats), ramps, indexed and lighting (colour
                  and light arithmetic), quality and spritediff (the measurements),
                  loopcheck, timing, frameops, motion and inbetween (animation maths)
  tools/          one module per domain: sprite, inspect, layers, frames, tags,
                  cels, animation, drawing, brushes, shading, selection, effects,
                  text, tilemap, image, palette, slices, transform, export,
                  export_presets, minecraft, reference, workflow, asset_spec,
                  batch, gui, health (+ common.py)
docs/TOOLS.md     full auto-generated tool reference, every registered tool
docs/CLIENTS.md   per-client setup, transports, and what to do when a client
                  mangles arguments
scripts/          gen_tool_docs.py (regenerates docs/TOOLS.md), quality_report.py,
                  release_gate.py, showcase/ (regenerates the images above)
tests/            pytest suite: the pure tests always run, the rest need
                  --run-aseprite

Security

This server hands an AI agent a file capability, so access is scoped by default:

  • Workspace-sandboxed paths. Relative filenames resolve under ASEPRITE_MCP_WORKSPACE, which defaults to <repo>/workspace from a source checkout and to a per-user data directory from an installed package, never to a path inside the Python installation. Absolute paths and paths that escape the workspace via .. (or a symlink that points outside it) are rejected unless you set ASEPRITE_MCP_ALLOW_ABSOLUTE=1.

  • No-clobber by default. Every output-writing tool (create_sprite, save_sprite_as, import_image, import_spritesheet, all export_*, export_game_asset_bundle) refuses to overwrite an existing file; pass overwrite=True to replace it on purpose. Multi-file exports validate every target up front, so they fail before writing anything if any target already exists. Pattern exports (frames/walk_{frame}.png) are expanded by Aseprite itself, so they are checked against everything the pattern could match.

  • Bounded work per call. A single call cannot exhaust the host: batch op-lists and pixel/tile/colour lists are capped, canvases are capped at 16384px per axis and 16,777,216 pixels of area (so two individually-legal axes can't add up to gigabytes), inline base64 images at 32 MB, and text rasterization is budgeted while it renders. An outside image whose header declares more than the canvas caps is refused before it is opened, an export's scale and a sheet's padding are held so the rendered image stays inside them, and render_preview fits a large sprite to 2048 px. ASEPRITE_MCP_TIMEOUT is clamped to 1-3600s so it can't be set to something that disables the timeout.

  • No shell, no injection. Aseprite is invoked with list-form arguments (never a shell), and every user value is passed into generated Lua through an escaped ARG table: user input is never concatenated into Lua source.

  • Bring your own Aseprite. The server only runs the Aseprite binary you point it at.

Run health_check to confirm the configuration (Aseprite path, workspace, sandbox state).

Notes & limitations

  • Each call is its own process. A tool call is an independent headless Aseprite run, so in-memory state (undo history, the "active" sprite) does not carry over, and operations take explicit coordinates rather than relying on what was open. The one piece of editor state that does survive is the selection: the selection tools keep it in a .msk sidecar beside the sprite and reload it on the next call, so it scopes later edits and deselect is a real step rather than a formality. A future live-GUI mode can layer on top of this without changing the tool API. docs/HEADLESS.md records what else batch mode takes away, which parts of the Aseprite API are unusable or unsafe under it, and why several tools are shaped the way they are.

  • Use a .aseprite/.ase extension to keep layers, frames, and tags editable. Saving to .png/.gif flattens.

  • get_pixels is capped at 4096 px (e.g. 64×64) per call; read in tiles for larger areas.

  • Anti-aliasing (antialias=True) only applies to RGB sprites; it's ignored on indexed/gray. Tilemaps and reference layers require Aseprite 1.3+.

  • Indexed sprites and the Background. On an ordinary layer the transparent palette index means "no pixel". On a Background Aseprite draws it as a colour, and so do get_pixels, assess_sprite, diff_sprites, the palette tools, trim_sprite, set_color_mode's conversion check, the drawing tools, and every effect and shading tool that reads the layer it is about to write (replace_color, the filters, the shading masks, remove_stray_pixels, normalize_edge_runs, fill_gradient with respect_alpha). The same scene behaves the same as an RGB or an indexed Background. add_outline refuses a Background of either kind, since nothing on one is empty.

  • Fills start from Aseprite's factory colours. Where a Background gains pixels (convert_layer_to_background, or growing its canvas with resize_canvas or crop_sprite) they are black, or the transparent index on an indexed sprite, whatever the editor's colour bar holds. A headless run used to inherit that colour bar.

Troubleshooting

  • "Could not locate Aseprite." Set ASEPRITE_PATH to the full executable path.

  • Nothing happens / permission denied on save. Ensure the workspace path is writable. Relative filenames go under ASEPRITE_MCP_WORKSPACE; health_check reports the directory files are actually landing in.

  • Timeouts on big operations: raise ASEPRITE_MCP_TIMEOUT (seconds).

  • A tool errors with a Lua message. The message is surfaced verbatim from Aseprite, it usually names the bad argument (e.g. a missing layer/frame).

  • Tests all skip. The Aseprite-driving tests are opt-in: run uv run pytest --run-aseprite. With the flag given and no Aseprite found they still skip, naming that as the reason, so set ASEPRITE_PATH as well.

Client-side problems (sprites landing in a venv directory, a text-only model that cannot see render_preview, the Windows lock on .venv\Scripts\aseprite-mcp.exe that blocks uv sync, a server that never appears) are covered in docs/CLIENTS.md.

Development

uv run pytest                              # pure-Python tests (no Aseprite needed)
uv run pytest --run-aseprite               # plus the integration and golden tests
uv run aseprite-mcp                        # run the server over stdio (manual debugging)
uv run python scripts/gen_tool_docs.py     # regenerate docs/TOOLS.md

See CONTRIBUTING.md for the architecture and how to add a tool, and CHANGELOG.md for release notes.

Contributing

Contributions are welcome! Please read CONTRIBUTING.md, add a test for your change, and regenerate the tool reference before opening a PR.

License

MIT © Brendan Malloy.

Disclaimer

This is an independent, unofficial project and is not affiliated with or endorsed by Aseprite or Igara Studio S.A. "Aseprite" is a trademark of its respective owner. You need your own licensed copy of Aseprite for this server to function.

Available Tools

156 tools
add_drop_shadowB

Add a hard drop shadow for a layer's artwork on a new layer placed beneath it.

Args:
    layer: The layer casting the shadow.
    offset_x, offset_y: Shadow offset in pixels.
    color: Shadow colour (often semi-transparent black, the default).
    opacity: Opacity (0-255) of the shadow layer.
    frame: Frame to build the shadow for.
ParametersJSON Schema
NameRequiredDescriptionDefault
colorNoDefault: "#00000080".#00000080
frameNoDefault: 1.
layerYes
opacityNoDefault: 255.
filenameYes
offset_xNoDefault: 1.
offset_yNoDefault: 1.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare a write operation (readOnlyHint=false) and closed-world scope, so safety is partly covered. The description adds useful side-effect context — a new layer is created beneath the source artwork — but says nothing about permissions, reversibility, or return value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence and the Args block is tightly scoped with no filler. The bulleted list could be slightly more economical but every line carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema, the description covers most parameters but omits the required filename and gives no guidance on frame/layer interaction or the resulting layer's naming. Adequate but leaving clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds genuine meaning the schema lacks: offset units (pixels), opacity range (0-255), and color being semi-transparent black by default. However, the required 'filename' parameter is never mentioned, and schema coverage sits at 71%, so the doc is not fully compensating.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a hard drop shadow') and clarifies the output is a new layer placed beneath the source. It does not, however, distinguish itself from close siblings like cast_shadow or contact_shadow, leaving the agent to infer which shadow tool applies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the shadow is but gives no when-to-use, when-not-to-use, or alternative guidance. With cast_shadow and contact_shadow sitting as siblings, the absence of any routing hint is a real gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_frameA

Add a frame: appended when it is empty, inserted when it copies another.

Args:
    duration_ms: Frame duration in milliseconds (default 100).
    copy_from: If given (1-based), duplicate the content of that frame; otherwise the
        new frame is empty and goes at the end. Must name an existing frame: an
        out-of-range number is rejected, not clamped. **A copy is inserted, not
        appended**, so every frame from that point on is renumbered: on a two-frame
        sprite, `copy_from=1` gives three frames whose second is the original first.
        Pass no `copy_from` and the sprite's existing frames keep their numbers.

Returns the new frame number and updated frame count. With `copy_from`, `newFrame` is
where the copy landed, which is also the number the frames after it shifted from.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
copy_fromNo
duration_msNoDefault: 100.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give a generic mutation/safety profile (readOnlyHint false, destructiveHint false). The description goes well beyond that by disclosing the frame-renumbering side effect of insertion, with a concrete two-frame worked example, plus the rejection-not-clamp behavior and the exact return contents (newFrame and updated frame count). This is exactly the kind of non-obvious behavioral context the description should carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core behavior in the opening line, then uses a clean Args structure. It is somewhat verbose and uses bolding for emphasis, but each sentence carries real semantic content (renumbering, rejection semantics, return values) rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description appropriately explains the return values, and for a mutating tool it covers the key side effect (renumbering) and error behavior. The only shortfall is the undocumented required filename parameter, which is left unexplained in both schema and description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% (just duration_ms's default), so the description must compensate, and it does for two of three params: duration_ms default, and copy_from's 1-based indexing, existence requirement, out-of-range rejection and renumbering effect. The required filename parameter is never mentioned in either the schema or the Args list, leaving a small gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a frame') and immediately characterizes the two operating modes: appended when empty, inserted when copying. Combined with the copy_from detail, an agent can distinguish this from siblings like duplicate_frame or move_frame without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly explains the two conditional modes (pass copy_from to duplicate content, omit it to append an empty frame) and warns that an out-of-range value is rejected rather than clamped. It stops short of naming an alternative sibling (e.g. duplicate_frame) for the copy case, so guidance is strong but not fully explicit about when to prefer another tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_group_layerA

Add a new (empty) group layer on top of the stack. Nest layers into it with add_layer(group=...) or move_layer(group=...).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
filenameYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=false, destructive=false, and openWorld=false, so the safety profile is covered. The description adds useful behavioral detail beyond that: the layer is created empty, it sits on top of the stack, and it acts as a nesting container for subsequent add_layer/move_layer calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the core action front-loaded ahead of the follow-up nesting hint. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter mutation whose safety profile is covered by annotations, the description is adequate to call the tool correctly, but the complete absence of filename/name semantics is a real gap and there is no output schema to lean on.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for both required parameters (filename, name), and the description says nothing about either. An agent gets no guidance on whether filename is the sprite file path or what name refers to, so the description fails to compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Add a new (empty) group layer') plus placement ('on top of the stack'). It distinguishes itself from the sibling add_layer by clarifying that this creates a container that other layers are nested into rather than a drawable layer.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear follow-up context by naming the exact sibling calls (add_layer(group=...) or move_layer(group=...)) used to populate the new group. It does not state when to prefer a group layer over other structuring approaches or any exclusions, so it falls short of full 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.

add_layerA

Add a new (empty) normal layer on top of the stack.

Args:
    name: Layer name.
    group: Optional name of an existing group layer to nest the new layer in.
    opacity: 0-255.
    blend_mode: normal, multiply, screen, overlay, darken, lighten,
        color_dodge, color_burn, hard_light, soft_light, difference,
        exclusion, hue, saturation, color, luminosity, addition, subtract, divide.
    visible: Initial visibility.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
groupNo
opacityNoDefault: 255.
visibleNoDefault: true.
filenameYes
blend_modeNoDefault: "normal".normal

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds useful context that the created layer is empty and placed at the top of the stack, but says nothing about what happens to the active selection, whether the layer becomes selected/current, or return behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence fully front-loads the action, and the Args block is terse. The long blend_mode list is the only bulk, and it is necessary information not available elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-param mutation with no output schema and annotations covering safety, the description covers nearly everything needed to invoke it correctly. The lone gap is the undocumented required 'filename' parameter, which forces the agent to guess which sprite file is targeted.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 50% schema coverage and zero schema enums, the description carries real weight: it enumerates all 18 legal blend_mode values (absent from the schema) and documents name, group, opacity and visible. Only 'filename' is left undocumented, which keeps it short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb+resource (add a layer) and narrows it with 'new (empty) normal layer on top of the stack', which distinguishes it from sibling operations like add_group_layer and duplicate_layer. It does not explicitly name those siblings, but the type and placement are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: 'on top of the stack' tells the agent where the layer lands, and 'normal layer' hints at the alternative of a group layer. There is no explicit when-to-use/when-not or routing to add_group_layer or add_reference_layer, so the agent must infer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_outlineB

Add a pixel outline around the artwork on a layer.

Args:
    color: Outline colour.
    thickness: Outline width in pixels (default 1).
    connectivity: 4 (orthogonal only) or 8 (includes diagonals, default).
    where: "outside" (grow into transparency, default) or "inside"
        (recolour the shape's border pixels).
ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerNo
whereNoDefault: "outside".outside
filenameYes
thicknessNoDefault: 1.
connectivityNoDefault: 8.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint false and openWorldHint false, establishing a local write operation. The description adds semantics for the where option (outside grows into transparency, inside recolours border) but does not state that the layer is modified in place or whether existing artwork is required.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose followed by a structured Args list. Concise and readable, though it repeats schema defaults for thickness, connectivity, and where.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema, the description covers the main operation and key parameters but leaves filename, layer, and frame undocumented. It also does not clarify which layer is modified if 'layer' is omitted.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 57% and the schema descriptions are only default values. The description provides meaningful semantics for color, thickness, connectivity, and where, but omits filename, layer, and frame. This adds substantial value for the core outline parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (add) and resource (pixel outline) plus target (artwork on a layer). It does not differentiate from the sibling tool outline_smart, so sibling differentiation is absent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance or alternatives are provided; the description only documents parameters. An agent must infer context from the tool name and siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_palette_colorC

Append a colour to the end of the palette.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
filenameYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=false, so the safety profile is covered; the description's 'append' is consistent with that but adds almost nothing beyond it. It omits any behavioral context such as palette size limits, whether the color is deduplicated, or error behavior when the palette is full.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single efficient sentence with the action and target front-loaded and no filler. It is not padded, though its brevity is partly under-specification rather than disciplined economy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating two-parameter tool with no output schema, zero schema description coverage, and only weak annotation support, the description leaves key call-time details unknown: what filename identifies, what color encoding is valid, and whether the operation can fail. It is too thin to call the tool correctly with confidence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description partially compensates only for 'color' by implying it is a palette colour. The accepted color format (hex, RGB, name) is never stated, and the required 'filename' parameter is not addressed at all, leaving half the input unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb ('Append') and resource ('colour') plus the insertion position ('to the end of the palette'), which implicitly distinguishes it from set_palette_color, which presumably overwrites an existing entry. It is clear what the tool does, though it never names the sibling it contrasts with.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this rather than set_palette_color, load_palette, or resize_palette, and no mention of prerequisites such as the palette needing to exist or the filename needing to resolve. The agent must infer usage entirely from the tool name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_reference_layerA

Add a dimmed, locked layer holding a reference image to trace over.

Args:
    image_file: The reference image/sprite.
    layer_name: Name for the new layer (default "reference").
    opacity: Layer opacity (0-255); dim it so your art stands out.
    scale_to_fit: Resize the reference to the canvas size (smooth).
    x, y: Placement when not scaling to fit.
    frame: Which existing frame to place the reference on (1-based). An
        out-of-range frame is rejected with the sprite's valid range.

Exclude this layer from exports with ignore_layer="<layer_name>".
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
frameNoDefault: 1.
opacityNoDefault: 128.
filenameYes
image_fileYes
layer_nameNoDefault: "reference".reference
scale_to_fitNoDefault: false.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare the mutation/safety profile (readOnly=false, destructive=false, openWorld=false), and the description adds real behavioral context beyond them: the layer is dimmed and locked, the frame argument is validated with an out-of-range rejection, and the layer can be excluded from exports. It stops short of describing return values or lock semantics fully, warranting a 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in the first sentence, followed by an arg list that maps cleanly to parameters. Slightly verbose in enumerating defaults, but every line carries useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with no output schema, the description covers behavior, most parameters, and a follow-up export note. The omission of the required 'filename' parameter keeps it from being fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, and the description adds genuine meaning: opacity range 0-255 with dimming intent, scale_to_fit as smooth resize, x/y as placement only when not scaling, and frame as 1-based with rejection behavior. Only the required 'filename' parameter is left undocumented, so it falls just short of full compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Add), resource (layer), and defining traits (dimmed, locked, holding a reference image to trace over). This clearly distinguishes it from generic siblings like add_layer or add_group_layer without needing to open any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'to trace over' implies the intended use case, and the closing note gives a follow-up action (exclude via ignore_layer). However, no alternative tool is named and there is no explicit when-to-use/when-not guidance versus add_layer or import_reference_sequence.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_sliceB

Create a slice (named region) at (x, y, width, height).

Args:
    center_*: Optional 9-patch center rectangle, **relative to the slice's
        top-left**. Provide all four to mark the stretchable middle.
    pivot_*: Optional pivot point (relative to the slice).
    color: Optional slice colour shown in the editor.
    data: Optional user data. A string is stored as it arrives; a dict or list is
        JSON-encoded, so {"type": "hitbox", "id": "body"} round-trips through
        export_slice_metadata, which derives the slice's type and id from it.
ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
dataNo
nameYes
colorNo
widthYes
heightYes
pivot_xNo
pivot_yNo
center_xNo
center_yNo
filenameYes
center_widthNo
center_heightNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-read-only, non-destructive, closed-world mutation, so the safety profile is covered. The description adds real behavioral value by explaining that dict/list data is JSON-encoded and round-trips through export_slice_metadata, but it says nothing about failure modes (e.g., overlapping slices, missing filename) or whether the sprite must already exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The one-line summary is front-loaded and the args list is tight, with conditional guidance folded into the relevant entries rather than repeated. Only the omission of filename and x/y semantics keeps it from being fully front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter mutation tool with zero schema descriptions and no output schema, the description covers the tricky optional params but leaves gaps: filename is undocumented, x/y origin is unspecified, and there is no indication of what happens if a slice already exists at that location.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% across 14 parameters, so the description carries the load and does so for the non-obvious ones: center_* is a 9-patch rect relative to the slice's top-left and all four must be supplied, pivot_* is a point relative to the slice, and data has special encoding rules. It omits filename and the coordinate origin for x/y, keeping it short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create a slice (named region)') plus the positional parameters, so the agent knows it adds a slice rather than modifying or removing one. It does not explicitly name the sibling alternatives (set_slice, remove_slice), but the create semantics are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no reference to alternatives such as set_slice for editing an existing slice or list_slices for inspection. The args section explains what fields mean, not when this tool is the right choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_tagA

Create an animation tag spanning frames [from_frame, to_frame] (1-based).

Both frames must already exist: an out-of-range number is rejected with the sprite's
valid range rather than clamped to it (which used to report a tag added while
creating it over a different range).

Args:
    direction: "forward" (default), "reverse", "pingpong", or "pingpong_reverse".
    color: Optional tag colour, shown in the timeline.
    repeats: How many times the tag plays. **0, the default, means forever**, which
        is how a cycle is marked in the file; 1 is a one-shot such as an attack, a
        hurt or a death. This is the sprite's own answer to whether these frames
        loop, and `validate_loop` reads it: a repeated last frame is an error for a
        cycle and only a warning for a one-shot.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
colorNo
repeatsNoDefault: 0.
filenameYes
to_frameYes
directionNoDefault: "forward".forward
from_frameYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the non-destructive mutation annotations, the description discloses real behavior: the strict out-of-range rejection and its history, the meaning of repeats=0 ('forever', the cycle marker), and the fact that validate_loop reads repeats and treats a repeated last frame as an error for a cycle versus a warning for a one-shot. That is substantive context an agent could not derive from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Core contract and the frames constraint are front-loaded, and the Args block is compact. The parenthetical about the previous clamping bug is historical trivia that does not help an agent invoke the tool, a minor bit of non-earning text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter, no-output-schema mutation tool it covers error behavior, the direction domain, and the important repeats default. It leaves name/filename semantics and whether names must be unique or an existing tag is overwritten unstated, which is the remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 29% and no enums are declared, so the description carries most of the load: it enumerates the four direction values, explains color is a timeline-displayed tag colour, and gives repeats' default and semantics in depth. It does not explain name or filename, so it is strong but not fully compensating.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Create an animation tag spanning frames [from_frame, to_frame]') and states the 1-based indexing, so the agent knows exactly what is being produced. It does not, however, distinguish itself from the sibling set_tag, leaving the boundary between creating and replacing a tag to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a precondition (both frames must already exist and out-of-range values are rejected rather than clamped), which implies usage context. But it never states when to reach for add_tag versus set_tag, remove_tag, or validate_loop, so routing guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_tileB

Add a new tile to the layer's tileset (optionally filled with a solid colour). Returns the new tile's index.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorNo
frameNoDefault: 1.
layerYes
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare this is a non-read-only, non-destructive, closed-world write, so the safety profile is covered. The description adds that the tile may be optionally filled and that the new index is returned, but says nothing about persistence, required layer type, or side effects on existing tiles.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero filler; the core action is front-loaded and the return value is appended compactly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with 25% schema coverage and no output schema, the description covers the return value but leaves 'filename' and 'frame' entirely unexplained and gives no guidance on the tileset/layer preconditions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, and the description mentions just the optional colour fill. The required 'filename' and the 'frame' parameter (with its default) remain undocumented in both description and schema, leaving half the parameters semantically opaque.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Add a new tile to the layer's tileset', with the optional solid-colour fill noted. It is distinguishable from mutation siblings like set_tile/set_tiles, though it does not explicitly contrast itself with fill_tile or create_tilemap_layer.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use this versus alternatives such as set_tile, fill_tile, or paint_tile_pixels, nor any prerequisite (e.g. layer must already be a tileset). Usage must be inferred from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

adjust_brightness_contrastB

Adjust brightness (-255..255, additive) and contrast (-255..255) of a layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
contrastNoDefault: 0.
filenameYes
brightnessNoDefault: 0.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=false, so the mutating, local nature is known. The description adds one genuinely useful behavioral trait - brightness is 'additive' - but says nothing about reversibility, whether changes are baked into pixels, or permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that names the operation, both adjustable dimensions, the valid range, the compositing mode, and the target scope. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter mutating tool with no output schema and only 60% schema coverage, the description covers the two numeric parameters well but leaves frame/layer/filename and the mutation's side effects unspecified. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% and the schema only documents defaults, so the description's ranges (-255..255) and the additive semantics for brightness do add meaning. However, frame, layer, and filename receive no semantic explanation in either place, leaving a partial gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Adjust') plus the exact resources (brightness and contrast) and the scope ('of a layer'), with valid ranges in parentheses. It does not differentiate itself from the sibling adjust_hue_saturation, but the operation itself is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus the other adjustment tools (adjust_hue_saturation, desaturate, gradient_map) or when not to. The agent must infer applicability from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

adjust_hue_saturationB

Shift hue (degrees) and scale saturation/lightness (percent, -100..100).

ParametersJSON Schema
NameRequiredDescriptionDefault
hueNoDefault: 0.
frameNoDefault: 1.
layerNo
filenameYes
lightnessNoDefault: 0.
saturationNoDefault: 0.

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, so the agent knows this is a mutating operation. However, the description does not disclose what exactly gets modified (e.g., a specific layer or frame in a file), whether changes are reversible, or any permission requirements. It adds only the units and range for the adjustment values, not the behavioral context of a mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that is appropriately sized and contains no filler. Every part, the operations and the units, earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 6 parameters (including required filename, plus layer and frame targeting) and no output schema, the description is too thin. It explains the adjustment values but not what object is being modified or how the target is selected, leaving significant gaps for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67%, and for the core adjustment parameters the schema only says 'Default: 0.' The description adds crucial meaning by specifying that hue is in degrees and saturation/lightness are percentages in the -100..100 range. It does not clarify the roles of filename, layer, or frame.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific operation: shifting hue and scaling saturation/lightness. It is clear about what adjustments are performed but does not differentiate this tool from close siblings like adjust_brightness_contrast or desaturate, nor does it mention the target resource (file, layer, frame).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided about when to use this tool versus alternatives such as desaturate or adjust_brightness_contrast. It gives no prerequisites or context for selection, leaving the agent to infer usage from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_operationsA
Destructive

Apply a list of edit operations to a sprite in one atomic, single-process batch.

Each operation is {"op": "<name>", "args": {...}}. Ops run in order against the same open sprite, so later ops see earlier ones (e.g. add a layer then draw on it). Arguments not listed for an op are rejected rather than ignored.

Atomic: if any op fails the whole batch is rolled back and nothing is saved; the error names the failing op index. dry_run=True validates the op list and returns the plan without launching Aseprite (shape checks only; runtime issues like a missing layer surface on a real run).

Frames are 1-based, and an arg=frame argument must name a frame that already exists: an out-of-range frame is rejected with the sprite's valid range rather than clamped, so a per-op summary always describes the frames actually touched.

Returns a workflow_manifest.v1 (kind "batch") with a per-op operations list, and, when the ops touched pixels, the same pixels_written / pixels_outside_selection / selection_applied fields every other tool reports: a batch run under an active selection is clipped to it, and these say how much the mask refused.

Operations and their arguments ('?' marks an optional argument): add_frame(duration_ms=int?, copy_from=frame?) add_layer(name=str, group=str?, opacity=int?, blend_mode=str?, visible=bool?) add_slice(name=str, x=int, y=int, width=int, height=int, color=color?) add_tag(name=str, from=frame, to=frame, direction=str?, color=color?) [also accepts from_frame for from, to_frame for to] clear_layer(layer=str?, frame=frame?) copy_cel(layer=str, from=frame, to=frame, to_layer=str?) [also accepts from_frame for from, to_frame for to] delete_cel(layer=str, frame=frame) draw_ellipse(layer=str?, frame=frame?, cx=int, cy=int, rx=int, ry=int, color=color) draw_line(layer=str?, frame=frame?, x1=int, y1=int, x2=int, y2=int, color=color) draw_pixels(layer=str?, frame=frame?, pixels=list, color=color?) draw_rectangle(layer=str?, frame=frame?, x=int, y=int, width=int, height=int, color=color) duplicate_frame(frame=frame) fill_ellipse(layer=str?, frame=frame?, cx=int, cy=int, rx=int, ry=int, color=color) fill_layer(layer=str?, frame=frame?, color=color) fill_rectangle(layer=str?, frame=frame?, x=int, y=int, width=int, height=int, color=color) remove_frame(frame=frame) remove_layer(layer=str) remove_slice(name=str) remove_tag(name=str) rename_layer(layer=str, new_name=str) replace_color(layer=str?, frame=frame?, from=color, to=color, tolerance=int?) [also accepts from_color for from, to_color for to] set_all_frame_durations(duration_ms=int) set_cel_opacity(layer=str, frame=frame, opacity=int) set_cel_position(layer=str, frame=frame, x=int, y=int) set_frame_duration(frame=frame, duration_ms=int) set_layer_opacity(layer=str, opacity=int) set_layer_visible(layer=str, visible=bool) set_pixel(layer=str?, frame=frame?, x=int, y=int, color=color)

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoDefault: false.
filenameYes
operationsYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, yet the description adds substantial behavior beyond that: full-batch rollback on any op failure, the error naming the failing op index, dry_run validating shape only ('runtime issues surface on a real run'), 1-based frame rejection rather than clamping, and selection clipping. This is rich, non-obvious disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Key semantics (atomicity, ordering, dry_run, frame numbering) are front-loaded before the long op catalog. The catalog is long but every line is functional reference an agent needs to construct valid operations, so no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description specifies the return value (workflow_manifest.v1 with a per-op operations list and pixels_written/pixels_outside_selection/selection_applied when pixels are touched). Combined with the destructiveness annotations, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% (filename and the operations array are opaque), so the description carries the burden and does so exhaustively: it enumerates every op with its argument names, marks optionals with '?', documents aliases (from_frame/to_frame, from_color/to_color), and states that unlisted args are rejected. This is far beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Apply a list of edit operations to a sprite') plus the key differentiator of 'atomic, single-process batch'. This clearly separates it from the many single-op siblings like draw_line, add_layer, and set_frame_duration that do one thing each.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the batching context well: ops run in order against the same open sprite, so later ops see earlier ones, and dry_run=True is recommended for validation before a real run. It does not explicitly name when to prefer this over calling individual op tools, so it stops short of full when/when-not/alternatives guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_timing_curveA

Give an animation a shape in time, by setting durations and never duplicating frames.

Uniform timing is the placeholder every animation starts with and almost none should
keep. A cycle holds its extremes two to four times as long as the poses it passes
through; an attack holds the anticipation, snaps through the strike in 20 to 40ms, and
holds the impact.

Args:
    curve: `hold_extremes` (the ends of a cycle are held, the passing frames are not),
        `attack` (anticipation, snap, impact, recovery), `ease_in` (starts slow),
        `ease_out` (ends slow), or `flat` (every frame the same, to start over).
    frames: The frames to time, in order. Defaults to a tag's frames, or all of them.
    tag: Time one tag's frames instead of naming them.
    base_ms: The duration of a passing frame. Everything else is a multiple of it.
    hold_frames: Frames to hold whatever the curve says, at three times `base_ms`.
    snap_frames: Frames to snap through, at the shortest duration that still registers.

A hold is a longer duration on one frame, never a repeated frame: duplicating costs a
frame, shifts every tag index, and hides the repeat from `validate_loop`. The returned
`frames_added` is always 0, and it is returned so that claim can be checked.

Easing here and easing the spacing elsewhere are the same curve applied twice, which
reads as slow motion rather than as weight. The cels are measured on the way through,
so asking for an eased curve over spacing that is already eased comes back with a
warning rather than quietly doing it.
ParametersJSON Schema
NameRequiredDescriptionDefault
tagNo
curveNoDefault: "hold_extremes".hold_extremes
framesNo
base_msNoDefault: 100.
filenameYes
hold_framesNo
snap_framesNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description carries the rest and does so richly: holds are durations not duplicated frames, duplicating shifts every tag index and hides the repeat from validate_loop, frames_added is always 0 and returned so the claim is checkable, and a double-ease request returns a warning rather than silently proceeding.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose sentence and structured into prose rationale followed by an Args list. The aphorism about uniform timing being a placeholder is mildly expendable, but the rest earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, yet the description explains the meaningful return value (frames_added always 0) and the warning path, which is more than required. The main omission is the required `filename` parameter, and the warning's exact shape is not spelled out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 29% and there are no enums, so the description does the heavy lifting: it enumerates and explains all five `curve` values, defines base_ms as the passing-frame duration with everything else a multiple of it, and clarifies hold_frames (3x base_ms) and snap_frames (shortest registrable duration). Only the required `filename` is left undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb+resource: 'Give an animation a shape in time, by setting durations.' The 'never duplicating frames' clause and the curve taxonomy distinguish it from generic siblings like set_frame_duration and set_all_frame_durations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete when-to-use guidance per curve ('a cycle holds its extremes two to four times as long as the poses it passes through', attack = anticipation/snap/impact), plus an explicit when-not-to-do-something warning about combining easing here with eased spacing. It stops short of naming sibling alternatives like set_frame_duration.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

assess_spriteA
Read-only

Measure the drawing itself and say what is worth fixing.

`get_sprite_info` says what a sprite contains and `render_preview` returns a picture
a text-only model cannot read. This answers the question in between: is the art any
good, in the ways that can be counted.

Reports how many colours are in use and roughly how many ramps they form, pixels with
no neighbour of their own colour (noise), jagged corners on diagonals, the drawn
bounding box, how much of the canvas it fills, whether it sits centred, and how far
the silhouette is from its own mirror. Each measurement that is worth acting on comes
back with a line saying why, so the numbers do not have to be interpreted.

Args:
    ramp: Declare the ramp the art should be on and the report adds palette
        conformance: the fraction of drawn pixels sitting exactly on it. This is the
        measurement that separates shading from filtering, and it is omitted rather
        than reported as a meaningless 1.0 when no ramp is given. On an **indexed**
        sprite the readings also say how much of the ramp the palette can actually
        hold, because conformance cannot see a ramp step that collapsed onto its
        neighbour: the colour it collapsed to is still on the ramp, so banded
        shading still scores 1.0.
    check_tiling: For a tile, also measure how much worse the wrapping edge looks
        than the interior, per axis. Near 1.0 wraps; much above 1.0 has a seam.
    layer: Measure one layer instead of the flattened frame.

Reads the whole frame in one Aseprite launch. None of the pixels are returned, only
the measurements, so this is cheap to call after every pass.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampNo
frameNoDefault: 1.
layerNo
filenameYes
check_tilingNoDefault: false.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint/openWorldHint; the description adds substantial context beyond them: it reads the whole frame in one Aseprite launch, returns no pixels (measurements only), is cheap, and explains the subtle indexed-palette limitation where ramp conformance can falsely read 1.0.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and the sibling contrast before detail. The prose is dense and occasionally elaborate, but nearly every clause carries information; the long ramp paragraph is the only place readability dips.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description enumerates what comes back (colour count, ramps, noise, jagged corners, bounding box, fill, centring, symmetry distance) and notes each actionable measurement is annotated with a reason. Enough for an agent to interpret results without a schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 40%, so the description carries the load and does so well for ramp, check_tiling, and layer, including when measurements are omitted vs reported. It never explains `frame` or `filename`, which keeps it off a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('measure the drawing itself') and explicitly positions itself between get_sprite_info and render_preview, naming both siblings. An agent can distinguish it from every neighbouring tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: get_sprite_info for contents, render_preview for a picture, this tool for countable quality. Closes with 'cheap to call after every pass', which tells the agent the cadence and cost of use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

build_asset_from_specA
Destructive

Build the asset described by an aseprite_mcp.asset_spec.v1 document.

Executes the (validated) plan by dispatching each step to an existing tool: scaffolds
the sprite for its `kind`, applies palette / extra layers / animation frames+tags /
slices, and runs the requested exports. **Structure only - no pixels are drawn;** the
returned manifest's `suggested_next_actions` hand the actual art back to you.

Args:
    overwrite: Passed to the export steps (replace existing export files). The sprite
        itself is created no-clobber, so building over an existing ``<name>.aseprite``
        raises - build to a new name or remove the old file.

Returns a ``workflow_manifest.v1`` (kind ``asset_spec``) with the created files, the
executed `plan`, and next actions. Raises ``ValidationFailed`` if the spec is invalid.
ParametersJSON Schema
NameRequiredDescriptionDefault
specYes
overwriteNoDefault: false.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description openly explains that the sprite itself is created no-clobber (raises on existing <name>.aseprite) while overwrite only affects export files. This is exactly the kind of nuance annotations alone cannot convey, though it doesn't cover all mutation boundaries or return format details in full.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is appropriately sized and front-loaded: a one-sentence summary, then a paragraph explaining execution flow, then Args and Returns sections. Every sentence carries information and nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description appropriately explains the return type (workflow_manifest.v1) and its contents. It covers the no-clobber behavior, the validation failure mode, and the suggested_next_actions mechanism. It could be slightly more complete by mentioning any constraints on the spec format or typical failure modes, but it is adequate for a complex orchestrator tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The spec param is a nested object with no schema description, but the description explains its role (drives scaffolding, palette, layers, animation, exports) and references a versioned document type. The overwrite parameter gets a full behavioral explanation (passed to export steps, no-clobber for sprite creation) that goes beyond the schema's 'Default: false.' This adds substantial meaning despite 50% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Build the asset described by a aseprite_mcp.asset_spec.v1 document.' It clearly identifies itself as a high-level orchestrator that dispatches to existing tools, distinguishing it from atomic siblings like draw_pixels or export_png. An agent can tell this composes a batch of operations based on a spec.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the description's emphasis on executing a validated plan and handing art back via suggested_next_actions, but it does not explicitly state when to use this vs plan_asset_spec or validate_asset_spec (siblings in the list). The overwrite arg behavior is explained, but there are no explicit when/when-not/alternatives statements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cast_shadowA

Lay a subject's shadow on the ground, away from the light and made of ramp steps.

`add_drop_shadow` offsets a copy of the artwork and tints it, which is a sticker of
the subject floating beside it. A cast shadow is a different thing: it falls on a
*surface*, away from the light, and flattens as it goes, so on the ground it is a
foreshortened ellipse under the subject rather than a second copy of its silhouette.

Built entirely of ramp steps, which is the point. A shadow made by multiplying alpha
lands every pixel of it between palette entries, and then `palette_conformance` drops
and nothing downstream holds together: indexed export, tileset reuse, a consistent
look between two sprites. The core is `ramp[0]` and each pixel of `softness` around it
is one step lighter, so the whole effect is ramp entries arranged in space.

Where it falls: the direction is away from `light_angle`, and the length comes from
`light_height` as the actual cotangent of the light's elevation. An overhead light
casts an ellipse straight underneath; a low light throws it far to one side.

Onto what: `ground_layer`. Name the layer holding the floor and the shadow is clipped
to it, so it cannot run off the edge of a platform and hang in the air, and if that
layer has nothing where the shadow would land the call is refused rather than drawing
a shadow onto nothing.

Args:
    layer: The layer casting the shadow. Its cel is never modified. A background
        layer is refused: it is opaque and covers the canvas, so it has no silhouette
        to cast. `convert_background_to_layer` first if the subject is one.
    ramp: Colours darkest first, normally the *ground's* ramp rather than the
        subject's, since the shadow is a darkening of the surface it lies on.
        Required, and deliberately so: a shadow built out of alpha instead is
        `add_drop_shadow`, which already exists.
    light_angle: Degrees. 0 is from the right, 90 from above, 135 from the upper left.
        The shadow falls the opposite way.
    light_height: The light's elevation, above 0 and up to 1. 1.0 is directly
        overhead and casts no length at all; small values are a low sun and throw a
        long shadow. This is the control that changes the shadow's length.
    ground_y: The row the shadow lies on. Defaults to the subject's own contact row,
        the lowest row it has a pixel on, which is the same measurement
        `validate_loop` reports as `contact_rows`. Refused if it sits above that row,
        because a floor running through the subject is not a floor.
    ground_layer: The layer holding the surface. When given, the shadow is clipped to
        that layer's pixels and the call is refused if there is nothing there to
        catch it. Consulted for its pixels, not for whether the picture shows them: a
        hidden layer, or one at a low opacity, still holds the pixels the clip asks
        about, so the shadow is drawn and the result reports what the floor actually
        is (see below) rather than the call being refused over it.
    softness: Pixels of penumbra around the core, each one ramp step lighter. 0 is a
        hard-edged shadow, 1 or 2 is the usual soft contact.
    opacity: The shadow *layer's* opacity, 0 to 255. Left at 255 the shadow's pixels
        are exactly ramp entries, which is what keeps conformance at 1.0; lowering it
        blends them with whatever is underneath and takes the composite off the ramp,
        so prefer a lighter ramp step over a lower opacity.
    new_layer: Name for the shadow's own layer, created directly below `layer`, or
        reused when a previous call of this tool made it and `frame` has no cel on it
        yet. That is how one shadow layer carries a whole walk cycle. A second call for
        the same layer *and* frame is refused, because two effects composited into one
        cel are a picture neither call describes, and so is a layer of that name this
        tool did not create.
    frame: Frame to build the shadow for, 1-based.

Returns the ellipse it used as `shadow_ellipse` (`[cx, cy, rx, ry]`), the
`contact_row` it measured, and `shadow_pixels`. A shadow that landed entirely off the
canvas is refused rather than reported as a success that drew nothing.

With a `ground_layer` the result also says what that floor is: `ground_layer_visible`,
`ground_layer_opacity`, and `ground_layer_hidden` naming the layer and any group whose
flag is off, which is present only when something is. A floor the picture does not
show, or shows faintly, is reported in `warnings` as well, because a crisp shadow on
an invisible surface is usually a layer named by mistake rather than an intent.

`clipped_pixels` is routinely large next to `shadow_pixels` when `ground_layer` is a
thin floor, and that is arithmetic rather than a fault: the ellipse is centred on the
contact row and so half of it lies above the floor's top edge, where there is no
surface. Pass `ground_y` at the floor's own top row to push it down, or leave
`ground_layer` out and let the subject hide the upper half.

A shadow is refused when rasterising it would allocate more points than the limit,
which is reachable from legal arguments on a large canvas: the ellipse's radii grow
with the subject's size and with how low the light sits, and the point list is built
in full before any pixel is drawn, so that cost is memory rather than patience. The
message names both radii and the remedy. `ellipse_points` in the result says how close
an accepted shadow came.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampYes
frameNoDefault: 1.
layerYes
opacityNoDefault: 255.
filenameYes
ground_yNo
softnessNoDefault: 1.
new_layerNoDefault: "shadow".shadow
light_angleNoDefault: 135.0.
ground_layerNo
light_heightNoDefault: 0.6.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description carries far more: the source cel is never modified, the new layer is created directly below `layer` and reused across frames, a second call for the same layer+frame is refused, a foreign layer of the same name is refused, and opacity below 255 breaks palette conformance. It also discloses the point-allocation limit and that the point list is built in full before drawing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and sibling differentiation before the mechanism and per-argument detail. Given 11 parameters and several non-obvious refusal rules, the length is largely justified, though several passages are rhetorically padded ('which is the point', 'a picture neither call describes') and could be tightened without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by documenting the return fields (shadow_ellipse, contact_row, shadow_pixels, clipped_pixels, ellipse_points) and the conditional ground_layer_visible/opacity/hidden warnings. Return semantics, refusal semantics, and argument interactions are all present, leaving little an agent needs that is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 55%, but the description compensates heavily: ramp ordering (darkest first, ground's ramp), light_angle's degree convention, light_height as cotangent of elevation, ground_y default and refusal rule, ground_layer's clip semantics (including that hidden/low-opacity layers still hold pixels), softness as ramp steps lighter, and opacity's conformance tradeoff. `filename` is left implicit, but the semantic gaps are otherwise well covered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (lay a subject's shadow on the ground) plus the mechanism (made of ramp steps), and explicitly contrasts itself with `add_drop_shadow`, naming that sibling and explaining how the two effects differ. An agent can distinguish this from every other shadow/palette tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing to `add_drop_shadow` for alpha-based shadows, plus named prerequisites (`convert_background_to_layer` for background subjects), refusal conditions (background layer, ground_y above contact row, empty ground_layer, duplicate call on same layer+frame), and the offered remedy for large clipped_pixels. When-to-use and when-refused are both spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clear_layerB
Destructive

Erase the target layer/frame cel to full transparency.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutating, destructive nature is covered. The description adds meaningful context by clarifying the result is full transparency rather than deletion, distinguishing it from delete_cel. It does not state reversibility, permissions, or whether off-target cels are affected.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence, front-loaded with the action and outcome. No wasted words, though it is terse enough to leave gaps rather than being over-long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, the description conveys the core effect but leaves parameter behavior underspecified and offers no guidance on siblings. It is minimally adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% and the layer and filename parameters have no descriptions. The phrase "target layer/frame cel" loosely gestures at the layer and frame params but adds no semantics for defaults, required filename, or what frame omission means.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource plus the outcome: "Erase the target layer/frame cel to full transparency." An agent can tell this empties a cel rather than deleting it. However, it does not distinguish itself from close siblings like fill_layer, remove_layer, or delete_cel.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance and no named alternatives, despite several overlapping siblings (fill_layer, delete_cel, remove_layer). The agent must infer the use case from the purpose alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contact_shadowA

Darken the pixels where one form meets another, along its ramp.

Ambient occlusion as pixel artists actually draw it: a line one or two steps darker
where two shapes touch. It is what stops a shaded object looking like it is floating
in front of the thing it is standing on.

Args:
    ramp: Colours darkest first. Darkened pixels stay on this ramp.
    occluder_color: The colour of the form casting the occlusion, for example the
        ground a character stands on, or the blade a crossguard meets.
    radius: How far the darkening reaches from the occluder, in pixels. 1 or 2 is
        usually right; beyond that it reads as a drop shadow rather than contact.
    depth: How many ramp steps darker, at the contact line. 1 is the common choice.
    direction: Degrees, restricting occlusion to one side. Omit for all directions,
        which is what you want for a contact line; set it when only one side of the
        form is actually touching something.
    tolerance: How close a pixel must be to a ramp entry to be darkened. Pixels
        further away are left alone, so this does not spill onto other materials.
    occluder_tolerance: How close a pixel must be to `occluder_color` to count as the
        occluder, as a weighted RGB distance. Defaults to `tolerance`, which is what
        this did before it was a separate argument. It wants to be **tight**: the
        occluder is a flat fill you named, while `tolerance` has to stay loose enough
        for shaded art that varies, and one number cannot be both. At the shared
        default of 24 a ground colour within 24 of the subject's own ramp makes the
        subject its own occluder: measured on a 24x24 sprite with a subject painted
        `#5a5a7a` and ground `#60607e`, `occluder_pixels` came back as 312 (the 144
        ground pixels plus all 168 of the subject) and nothing was darkened at all.
        The result carries a warning naming any ramp entry this cannot be told apart
        from, because that overlap is invisible otherwise.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

Refuses a pass that darkened nothing rather than reporting `darkened_pixels: 0` as a
success, and the refusal carries the three counts that say which of the possible
causes it was. A contact shadow that changed no pixel is not a contact shadow.

Run this **before** the passes that repaint the occluder, not after. The occluder is
found by colour, so a `shade_region_by_light` or `shift_along_ramp` that has already
moved the ground off `occluder_color` leaves this matching a handful of pixels and
reporting the handful as a success.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampYes
depthNoDefault: 1.
frameNoDefault: 1.
layerNo
radiusNoDefault: 1.
filenameYes
directionNo
toleranceNoDefault: 24.0.
occluder_colorYes
occluder_toleranceNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false (a write operation) but the description goes far beyond: it explains the tool's refusal behavior ('Refuses a pass that darkened nothing... the refusal carries the three counts'), it explains the warning about ambiguous ramp entries, and it describes the exact failure mode when occluder_tolerance is too loose (with a concrete example and numbers). This is exceptional transparency for a mutation tool, adding significant value beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear opening statement, parameter-by-parameter explanations, and a final usage-ordering rule. However, it is quite long and the occluder_tolerance paragraph is dense and somewhat rambling. It remains front-loaded with the core purpose, but the length and detail level, while useful, could be trimmed slightly without losing value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 10 parameters, low schema coverage, no output schema, and the tool's mutation nature, the description covers everything an agent needs: purpose, parameter semantics, behavioral quirks (refusal, warning), and ordering constraints. There are no significant gaps for correct invocation. It is complete and self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 40% (many parameters lack schema descriptions), so the description must carry the burden. It does so thoroughly: it explains each parameter's meaning, provides guidance for values (radius: '1 or 2 is usually right'), explains defaults and interactions (occluder_tolerance defaults to tolerance and why it should be tight), and gives a concrete example of misconfiguration. This fully compensates for the sparse schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and effect ('Darken the pixels where one form meets another, along its ramp') and elaborates with an analogy that leaves no ambiguity about what the tool does. Sibling tools include cast_shadow, glow, and add_drop_shadow, and the description explicitly distinguishes contact shadow from drop shadow ('beyond that it reads as a drop shadow rather than contact'). An agent can select this tool with confidence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use the tool ('Run this before the passes that repaint the occluder') and what not to do ('not after'). It also explains the failure mode of using it after other passes. It distinguishes the tool from related operations by warning about ordering relative to shade_region_by_light and shift_along_ramp. This is as good as it gets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

convert_background_to_layerB

Convert the Background layer back into a normal (transparent-capable) layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=false, so the agent knows this mutates state. The description adds useful semantic context by identifying that the Background layer is changed into a normal transparent-capable layer, but says nothing about reversibility, permissions, or side effects on existing content.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no redundant wording. The key action and result are stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation tool with readOnlyHint=false and no output schema, the core effect is covered. However, with 0% schema description coverage and no parameter explanation, the definition remains incomplete regarding which file the operation targets and what error or edge conditions exist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for the single required 'filename' parameter, and the description adds no explanation of it. The agent can infer it refers to a file, but the description does not compensate for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Convert back') and resource ('the Background layer') with the exact resulting state ('normal (transparent-capable) layer'). This clearly distinguishes it from the inverse sibling convert_layer_to_background.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use guidance, prerequisites, or alternatives are given. It implies the operation is needed when a transparent-capable layer is desired, but does not say when to choose this over other layer operations or what conditions must hold.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

convert_layer_to_backgroundC

Convert a normal layer into the sprite's opaque Background layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, which tell the agent this mutates state; the description adds that the resulting layer is opaque but says nothing about whether the original layer is replaced, what happens to an existing background layer, or whether the operation is reversible. No destructiveHint is declared and the description does not compensate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with no wasted words, front-loading the verb and the target resource.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating, non-read-only tool with no output schema and undocumented parameters, the description should state preconditions (e.g., only one background layer allowed) and the effect on existing content. None of that is present, leaving the definition inadequate for its complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for both required parameters (filename, layer), and the description never mentions them. It does not clarify how the layer is identified (name vs. index) or what filename refers to, so the agent must guess at parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb (convert) and resource (a normal layer) and states the transformation target (the sprite's opaque Background layer). It is distinguishable in intent, though it does not explicitly name the reverse sibling convert_background_to_layer, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use or when-not-to-use guidance, and does not mention the natural alternative convert_background_to_layer. An agent must infer the correct context from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

copy_celB

Copy a cel's image (and position) from one frame to another on the same layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes
to_frameYes
from_frameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=false, so the agent knows this is a mutation. The description adds that the copied data includes image and position, but it omits whether the destination cel is overwritten, what happens if the cel is missing, or any permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence, front-loaded with the core operation and containing no filler. It is appropriately sized for the amount of information it chooses to convey.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter mutation tool with no schema descriptions and no output schema, the description is too sparse. It does not explain how filename identifies the sprite, what happens to an existing destination cel, or any error conditions, leaving the agent under-informed for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for four required parameters. The description implies meanings for from_frame, to_frame, and layer, but it never names them and completely omits the filename parameter, so it fails to compensate for the undocumented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb+resource ('Copy a cel's image') and clarifies scope ('from one frame to another on the same layer'). It is clear what the tool does, but it does not name a sibling alternative to distinguish it from tools like link_cels or duplicate_frame.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus alternatives such as link_cels, offset_cels, or tween_cels. The description only states the operation, leaving usage context to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_character_spriteA

Scaffold a character sprite project: a transparent canvas with a tidy layer stack (body + details), an auto-generated shading palette ramp from base_color, and (optionally) an outlined placeholder body to draw over.

Returns a ``workflow_manifest.v1`` manifest (sprite summary, created files,
palette, and suggested next actions), plus `pixels_written` for the placeholder it
drew. With `with_placeholder=False` nothing is drawn and the field is absent.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
widthNoDefault: 32.
heightNoDefault: 32.
base_colorNoDefault: "#3878c8".#3878c8
with_placeholderNoDefault: true.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false. The description adds real context beyond that: it lists the created files, describes the auto-generated palette ramp, and specifies the conditional behavior of with_placeholder=False (nothing drawn, pixels_written absent). It stops short of noting overwrite/collision or permission requirements for a write tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the primary action and artifact list, then a second paragraph on the return contract. Both sentences carry weight; nothing is padded, though the return detail could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description rightly covers the workflow_manifest.v1 return and the conditional pixels_written field. Combined with the artifact enumeration, an agent has what it needs to call this correctly; only edge cases like existing-name conflicts are unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 80%, so most params are self-documented and the baseline would be 3. The description earns above baseline by explaining what base_color actually drives (an auto-generated shading ramp) and the effect of with_placeholder, meaning not captured in the schema. name/width/height remain unelaborated in the text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('scaffold a character sprite project') and enumerates the concrete artifacts produced: transparent canvas, body+details layer stack, palette ramp, optional placeholder. The agent can distinguish it from the generic 'create_sprite' sibling by the scaffolding behavior, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the scaffolding framing and the with_placeholder toggle, but there is no explicit when-to-use/when-not guidance nor any pointer to alternatives like create_sprite or create_icon_set. The agent must infer that this is a project-start helper.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_icon_setB

Scaffold an icon set: a grid sheet with count icon cells, each a placeholder inside a named slice (icon_0, icon_1, …) for easy atlas export.

Returns a ``workflow_manifest.v1`` manifest (kind "icon_set"); the per-icon regions
appear as slices under `sprite.slices`.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
countNoDefault: 4.
columnsNo
icon_sizeNoDefault: 16.

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the mutation hint is covered, but the description adds real value by disclosing the return artifact: a `workflow_manifest.v1` manifest of kind "icon_set" with per-icon regions exposed as slices under `sprite.slices`. That return contract matters since no output schema exists. It does not state persistence behavior or whether an existing set is overwritten.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the scaffolding behavior and cell naming come first, the return shape second. Nothing is padded. The phrase 'for easy atlas export' earns its place as rationale, though it is not strictly required.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a creation tool with no output schema, explaining the returned manifest is genuinely helpful and largely closes the return-value gap. What remains missing is the semantics of `columns` and `icon_size` (grid layout and cell pixel dimensions), plus whether the scaffold writes to a sprite file on disk. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50%, and the description compensates for `count` by describing cells and their naming scheme (icon_0, icon_1, …), matched to slices. However, `columns` and `icon_size` are left entirely to the schema, whose only descriptions are 'Default: 16.' — no meaning or units are added.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (scaffold) and resource (icon set) with concrete structure: a grid sheet of `count` cells, each a named placeholder slice. This clearly distinguishes it from siblings like create_sprite or create_tileset_project. It stops short of naming an alternative, but the purpose itself is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, prerequisites, or comparison to alternatives anywhere in the text. It does not tell the agent when scaffolding an icon set is preferable to creating a sprite and adding slices manually via add_slice. Usage must be inferred from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_rpg_item_sheetB

Scaffold an RPG item sheet: a grid sheet with one named slice per item (default sword/shield/potion/coin/key/gem), each with a placeholder.

Returns a ``workflow_manifest.v1`` manifest (kind "rpg_item_sheet"); item regions
appear as slices (named after each item) under `sprite.slices`.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
itemsNo
columnsNo
item_sizeNoDefault: 16.

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is not read-only and not open-world. The description adds some behavioral context by disclosing the return manifest kind and slice structure, but it does not say whether it overwrites existing data, what permissions are needed, or what side effects occur.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact, front-loaded sections: what it scaffolds first, then return details. Every sentence earns its place, with no redundant or filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a composite creation tool with low schema coverage and no output schema, the description covers purpose and return format adequately. However, it omits parameter explanations, side effects, prerequisites, and usage context, leaving meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, so the description must compensate. It partly explains the items parameter via default item names and the slice mapping, but does not explain name or columns, and item_size is only documented in the schema with a default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Scaffold") and resource ("RPG item sheet"), and describes the output: a grid sheet with one named slice per item and default items. It is clear but does not explicitly distinguish itself from sibling creation tools like create_sprite or create_character_sprite.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives no when-to-use guidance, no prerequisites, and no alternatives. The purpose implies a scaffolding scenario, but there is no explicit instruction about when to choose this over other creation tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_spriteA
Destructive

Create a new sprite file and save it.

Args:
    filename: Output path. Relative paths go in the workspace. Use a
        .aseprite/.ase extension to keep layers & frames editable.
    width, height: Canvas size in pixels. Each axis is capped at 16384px
        and the total area at 16,777,216 pixels (e.g. 4096x4096).
    color_mode: "rgb" (default), "indexed", or "gray".
    background: Optional fill colour for the first layer (e.g. "#1d2b53").
        Omit for a transparent canvas.
    overwrite: Replace `filename` if it already exists (default False = no-clobber).

An **indexed** sprite is created with a usable 33-colour palette: a transparent
entry at index 0 (the index that means "no pixel here"), then the 32 colours
Aseprite ships as its default. Aseprite's own new indexed sprite has 256 entries of
identical black instead, which made every colour equidistant from every entry, so
every draw resolved to index 0 and was invisible while reporting success. A
`background` colour that the default palette does not contain is appended to it, so
the background is the exact colour asked for rather than the nearest one available.
Replace the whole palette with `set_palette` when you have one in mind.

Returns the new sprite's structured info.
ParametersJSON Schema
NameRequiredDescriptionDefault
widthYes
heightYes
filenameYes
overwriteNoDefault: false.
backgroundNo
color_modeNoDefault: "rgb".rgb

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds substantial behavior the schema cannot convey: no-clobber default on `overwrite`, the 16384px per-axis / 16,777,216px area caps, and a detailed disclosure of how indexed sprites differ from Aseprite's own black-256-entry default and how an unmatched `background` colour is appended rather than snapped.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action, then parameter guidance, then the palette caveat. The indexed-palette paragraph is long and partially defensive in tone, but it carries real decision-relevant information and is not duplicative; still, it could be tightened by a sentence or two.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter creation tool with no output schema, the description covers defaults, limits, overwrite risk, extension choice, and returns ('Returns the new sprite's structured info'). With no output schema, the description notes the return shape adequately, and nothing needed to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (just the two defaults), yet the description documents all six parameters: filename path/extension rules, per-axis and total-area pixel caps, the three color_mode values (the schema has no enum), background fill syntax and omit-for-transparent semantics, and overwrite's no-clobber default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line states a specific verb+resource ('Create a new sprite file and save it') and the body goes on to distinguish the creation behavior from the palette-editing sibling by name ('Replace the whole palette with set_palette'). An agent can tell this apart from save_sprite_as, list_sprites, and set_color_mode without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete when-to-use guidance: pick a .aseprite/.ase extension when layers & frames must stay editable, omit `background` for transparency, and defer to `set_palette` when a specific palette is in mind. It does not state when creation should be avoided entirely (e.g., use save_sprite_as on an existing sprite), so it falls just short of explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_tilemap_layerB

Create a tilemap layer with an empty grid.

Args:
    name: Layer name.
    tile_width, tile_height: Tile size in pixels (sets the sprite grid).
    columns, rows: Grid size in tiles (default: enough to cover the canvas).
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
rowsNo
frameNoDefault: 1.
columnsNo
filenameYes
tile_widthNoDefault: 16.
tile_heightNoDefault: 16.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool is a non-read-only, non-destructive, closed-world mutation. The description adds that the layer starts with an 'empty grid' and that tile size sets the sprite grid, which is useful. It omits that the operation writes to a file (required 'filename') or any permission/persistence behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, followed by a tight Args list. No wasted prose, appropriate size for a creation tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema, the description explains most grid parameters but leaves the required 'filename' undocumented, leaving the agent unsure where the layer is created. Adequate but with a clear gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 43%, so the description should compensate. It documents name, tile_width, tile_height, columns, and rows, but omits the required 'filename' parameter entirely and never mentions 'frame'. Partial compensation for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'Create a tilemap layer with an empty grid.' This is clear and distinguishable from generic sibling tools like add_layer, though it doesn't explicitly differentiate from similar creation tools such as create_tileset_project.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus alternatives like add_layer or create_tileset_project, and no prerequisites. Usage context is only implied by the phrase 'tilemap layer'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_tileset_projectA

Scaffold a tilemap project: a canvas sized columns×rows tiles, a tilemap layer, and a starter tileset (grass/dirt/water/stone by default, or your own [{"name","color"}] list). The grid is filled with the first tile to start.

Returns a ``workflow_manifest.v1`` manifest with a tilemap block mapping tile
names to their tileset indices.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
rowsNoDefault: 4.
tilesNo
columnsNoDefault: 4.
tile_sizeNoDefault: 16.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the mutation and closed-world profile is already known. The description adds real behavioral context beyond that: the grid is pre-filled with the first tile, and a workflow_manifest.v1 is returned with a tilemap block. It doesn't say whether an existing project is overwritten, but this is solid added value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then scope, then return value in three tight sentences. The default-tileset aside is parenthetically compact. Slightly dense but no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers what is created, the pre-fill behavior, and the returned manifest shape. The only notable omission is overwrite/idempotency behavior, but nothing critical to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60%, with rows/columns/tile_size only carrying defaults and the 'tiles' array undocumented. The description compensates by explaining that columns×rows defines canvas size in tiles and that 'tiles' accepts either the default grass/dirt/water/stone set or a custom [{"name","color"}] list, giving the otherwise-bare parameter real meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Scaffold') and resource ('tilemap project'), then enumerates exactly what gets created: canvas, tilemap layer, starter tileset. This distinguishes it from siblings like create_tilemap_layer or create_sprite, which build only one component.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the scaffold framing (start a new tilemap project), but there is no explicit when-to-use versus alternatives such as create_tilemap_layer or create_sprite, and no mention of prerequisites or when-not to use it. Adequate but with clear gaps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

crop_spriteB
Destructive

Crop the canvas to the rectangle (x, y, width, height).

The resulting canvas is subject to the same dimension/area caps as `create_sprite`
(a "crop" to a larger rectangle grows the canvas).
ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
widthYes
heightYes
filenameYes

TDQS

B3.3/5.0
Behavior4/5

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 covered. The description adds genuinely useful behavior beyond that: the resulting canvas inherits create_sprite's dimension/area caps, and a crop to a larger rectangle GROWS the canvas rather than failing — a counterintuitive trait worth surfacing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the core action front-loaded and the surprising edge-case behavior immediately after. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive 5-parameter mutation with no output schema and zero schema description coverage, the description covers crop semantics well but omits the filename parameter, origin convention, and out-of-bounds/clamping behavior. Annotations cover the safety profile, so the remaining gap is moderate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and none of the five parameters are documented in the schema. The description names x, y, width, height but never says x/y are the top-left corner or how out-of-bounds values behave, and the required `filename` parameter is not mentioned at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (crop) and resource (canvas) and identifies the exact parameters that define the rectangle. It doesn't explicitly differentiate itself from adjacent transforms like trim_sprite, resize_canvas, or scale_sprite, though the parenthetical clarifies its unusual grow-on-larger-rectangle semantics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance is given and no alternatives are named, despite siblings like trim_sprite and resize_canvas that overlap conceptually. The note about area caps implies constraints but does not tell the agent when to prefer this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cycle_paletteA

Animate a sprite by cycling a run of palette colours, the oldest trick in the medium: the pixels do not move, the colours do, and water flows.

**What this ships, and why.** Aseprite's file format carries a palette per frame, but
its Lua API does not expose one, so the real thing cannot be authored from here.
Measured on 1.3.18.6: `#spr.palettes` is 1 and stays 1, the collection is read-only
(`spr.palettes[2] = ...` and `table.insert` both raise "attempt to index a nil value
(field '__setters')"), `Palette` has no `frame` property, `Sprite:newPalette` does not
exist, and `Sprite:setPalette` replaces the single sprite-wide palette no matter which
frame `app.frame` is on, as does `app.command.LoadPalette`. So this is the fallback:
the frames are generated, it costs one frame of storage each, and it works everywhere
a frame does, including in a GIF or a PNG sequence.

What rotates is the pixels' own indices, not the palette. On an indexed sprite those
are the same picture, and the index move is exact: no colour matching, nothing routed
through `nearest_index`, and the palette comes back byte for byte as it went in, so
`get_palette` still shows the ramp that was authored.

Args:
    indices: The palette indices to rotate, **in the order the colours travel**. At
        least two, distinct, each one in the palette, and none of them an entry that
        cannot draw (the sprite's transparent index, or an entry whose alpha is 0):
        rotating one of those through the cycle would make drawn pixels vanish.
        `list_palette_usage` reports the contiguous runs worth passing here.
    frame_count: How many frames the cycle occupies. Defaults to `len(indices)`, which
        is one frame per colour, and is capped there: past that the rotation repeats a
        frame already written, so the extra frames cost storage and show nothing new.
    step: How far the colours travel per frame. Positive moves them forward along
        `indices`; negative moves them back. A multiple of `len(indices)` is refused
        rather than silently producing identical frames.
    layer: Cycle only this layer's pixels. Default: every pixel layer.

The sprite must have exactly one frame. A cycle generates the whole timeline from the
one drawn frame, so a sprite that already animates would have its timeline redefined,
and that is refused rather than guessed at: `duplicate_frame` the pose into a sprite
of its own first.

Refuses, before anything is written, an index outside the palette (it names the size),
an index that cannot draw, a repeated index, a step that is a whole number of laps, and
a cycle none of whose indices appear in the art, which would write identical frames and
animate nothing. That last refusal names the indices the art *is* drawn with.

Returns the frames it wrote and how many pixels moved on each, `closes` (whether the
rotation returns to where it started at the wrap), and `warnings` when the cycle does
not close, or when an index in it has no pixels to travel through. `warnings` is
absent rather than empty when there is nothing to say.
ParametersJSON Schema
NameRequiredDescriptionDefault
stepNoDefault: 1.
layerNo
indicesYes
filenameYes
frame_countNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description goes far beyond them, disclosing that it rewrites the entire timeline, costs one frame of storage per colour, rotates index data rather than palette entries, and enumerates every refusal (out-of-palette index, non-drawing index, repeats, whole-lap step, no-op cycles) before listing what the return payload contains.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and the Args section is well structured, but the middle paragraph justifying the fallback against Aseprite 1.3.18.6 internals is dense and only partly load-bearing for an agent. Most sentences still earn their place given the tool's non-obvious semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description fully covers what comes back (frames written, per-frame pixel movement, closes, and warnings that are absent rather than empty). Combined with the refusal list and preconditions, an agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 20% (just step's default), and the description compensates thoroughly for indices (order, distinctness, palette membership, alpha-0 exclusion), frame_count (default and cap logic), step (direction and whole-lap refusal) and layer (default scope). The required filename parameter is left undocumented in both schema and description, a small remaining gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Animate a sprite by cycling a run of palette colours") and immediately disambiguates from related tools by insisting the pixels don't move, the colours do. An agent can distinguish this from set_palette, get_palette, generate_ramp and shift_along_ramp without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit prerequisites and when-not conditions: the sprite must have exactly one frame, and a sprite that already animates is refused with a named workaround (duplicate_frame into its own sprite). It also routes the agent to list_palette_usage for finding the runs worth passing, and explains the fallback context versus per-frame palettes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_celB
Destructive

Delete a cel (the layer becomes empty at that frame).

ParametersJSON Schema
NameRequiredDescriptionDefault
frameYes
layerYes
filenameYes

TDQS

B3.1/5.0
Behavior3/5

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 covered. The description adds the meaningful consequence that the layer itself survives and only becomes empty at that frame, but says nothing about reversibility or side effects on linked cels.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the verb-resource pair front-loaded and the clarifying consequence in a parenthetical. Nothing is redundant or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema and zero parameter documentation, the description conveys the core effect but omits error behavior, whether the cel can be restored, and how the filename/layer/frame arguments are validated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and all three parameters (filename, layer, frame) are required and undocumented. The description adds no parameter detail at all, so it fails to compensate for the coverage gap even though the names are largely self-explanatory.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Delete) and resource (cel) and adds the effect 'the layer becomes empty at that frame,' which usefully separates this from clear_layer/remove_layer semantics. It doesn't name a sibling tool explicitly, so an agent must still infer the distinction from context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance and no named alternative such as clear_layer, remove_layer, or remove_frame. Usage is only implied by the parenthetical about the resulting empty layer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

desaturateB

Desaturate toward grayscale by amount percent (0-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
amountNoDefault: 100.
filenameYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, confirming this is a mutation. The description adds the amount range (0-100) and direction (toward grayscale), which is useful context, but does not disclose what exactly gets modified (layer, frame) or whether changes are reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with zero waste. Every word contributes to stating the operation and its degree.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with four parameters and no output schema, the description is too thin. It omits which sprite/layer/frame is affected and leaves required 'filename' and optional 'layer' unexplained, so an agent cannot fully predict the tool's effect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%. The description adds meaning for 'amount' (percent toward grayscale, 0-100), which goes beyond the schema's bare 'Default: 100.' However, it does not explain the required 'filename' or the optional 'layer' and 'frame' parameters, so partial compensation only.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Desaturate') and the effect ('toward grayscale by amount percent'), so the agent knows the operation. It does not differentiate from sibling tools like adjust_hue_saturation or invert_colors, but the core purpose is clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, prerequisites, or mention of alternatives. The description only states what the tool does, leaving the agent to infer when to select it over sibling color operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

deselectA

Clear the selection, so edits affect the whole layer again.

A real step, not a formality: the selection lives in a sidecar beside the sprite and
persists across calls, so leaving one active will silently scope every later edit.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=false and openWorldHint=false; the description adds crucial behavioral context beyond that: the selection persists across calls in a sidecar and can silently scope future edits, making this a necessary state-clearing operation rather than a formality. This is exactly the kind of hidden-state disclosure that annotations cannot provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action and effect, followed by a compact rationale. Every sentence earns its place and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple state-clearing tool with one parameter and no output schema, the description provides adequate context: it explains what is cleared and why it matters. The lack of any mention of the filename parameter or return value is a minor gap, but not critical given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has a single required 'filename' parameter with 0% schema description coverage. The description does not explain the filename parameter at all. However, with only one parameter (baseline 4 for 0 params, but here 1 param with no description), the baseline is adjusted: the description's silence on the parameter is a gap, but not severe since the parameter is self-evident from context (the sprite file). A score of 3 reflects that the description adds no parameter-specific meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Clear') and resource ('the selection'), and immediately explains the effect: 'edits affect the whole layer again.' It is easily distinguished from siblings like modify_selection, invert_selection, and select_region, which create or alter selection rather than clear it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly implies when to use it by warning that leaving a selection active will 'silently scope every later edit,' effectively guiding the agent to call deselect before doing layer-wide edits. It does not explicitly name alternatives or state a when-not-to-use condition, so it falls 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.

diff_spritesA
Read-only

Compare two frames pixel for pixel and say what changed.

This is the tool for the question an editing agent cannot otherwise answer: *did my
last call do what I meant?* `assess_sprite` judges one frame on its own and
`render_preview` returns a picture a text-only model cannot read. This reports the
difference between two frames as counts, which is the only form in which "the shading
pass moved the outline" is visible without eyes.

**Nothing changed is the loudest result, not the quiet one.** An edit that silently
went nowhere, to the wrong layer, inside a stale selection, off the canvas, looks
exactly like an edit that was not needed. When the two frames are identical this says
so first and names the usual causes.

A difference is never reported as a fault, because different is not wrong. Pass
`expect` to turn the measurement into a check.

Args:
    filename: The sprite to compare, and the "before" side of the report.
    frame: Which frame of it (1-based).
    layer: Compare this layer alone instead of the composite, on both sides unless
        `other_layer` says otherwise. Worth reaching for: drawing tools write to ONE
        layer, so a composite diff can show nothing while the layer underneath
        changed completely, and the reverse.
    other: The sprite to compare against. Defaults to `filename`, which is what makes
        a frame-to-frame diff inside one animation this same call.
    other_frame: Which frame of `other` (1-based).
    other_layer: The layer to read on the `other` side, when it is named differently.
    expect: What the change should be: "identical", "silhouette", "interior",
        "coverage" or "mixed". Adds a verdict block with a pass or a fail, and is
        omitted rather than guessed at.

Returns counts in four buckets that add up to `changed_pixels`, so a change is never
reported as a single number that could mean two different things:

* `silhouette_added` / `silhouette_removed`: pixels that entered or left the shape.
  These are the ones that move a collision box, an outline and a trimmed export box.
* `interior_changed`: pixels that were visible before and after and changed colour.
* `coverage_changed`: pixels that kept their colour and changed only their alpha,
  which is an opacity or anti-aliasing change rather than a repaint.

Both frames must be the same size; a mismatch is refused with both canvas sizes and
both content boxes, because a diff of differently sized frames is an offset question
in disguise. Different colour modes compare fine: both sides are read as RGBA, so an
indexed sprite and its RGB export can be checked against each other.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
otherNo
expectNo
filenameYes
other_frameNoDefault: 1.
other_layerNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say read-only and closed-world. The description adds substantial behavior: identical frames are reported first with probable causes, differences are never framed as faults, the four output buckets that sum to changed_pixels, size mismatch is refused with canvas sizes and content boxes, and cross-color-mode comparison is allowed. That is well beyond what readOnlyHint conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then use-case, then args, then return shape, then edge cases. It is longer than most definitions but nearly every sentence adds decision-relevant detail. Slightly more prose than strictly necessary in the framing paragraphs, but it earns its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description documents the return shape explicitly (four buckets summing to changed_pixels). Combined with the expect verdict, the mismatch refusal, and the color-mode note, an agent has everything needed to invoke and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 29% and the description fully compensates: it defines each of the 7 params (defaults for frame/other_frame, the layer/other_layer relationship, other defaulting to filename for intra-animation diffs, and the enum values for expect plus its pass/fail verdict block). This is the rare case where the description carries parameter meaning the schema omits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (compare pixel for pixel) and names what it returns (what changed). Explicitly contrasts with siblings assess_sprite (judges one frame) and render_preview (returns a picture), so the agent can position this tool without opening other schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the exact question this tool answers ('did my last call do what I meant?') and names the two alternatives it is not. The layer arg even explains when to reach for composite vs layer diffing, which is a when-to-use distinction inside a parameter.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

dither_bandA

Dither the boundary between two adjacent ramp steps, widening the transition.

Dithering in pixel art is a limited-palette necessity rather than a style: it buys
an apparent extra shade between two you already have. It reads as dated when applied
globally, which is why this is scoped to one boundary rather than offered as a
filter over the whole sprite.

Args:
    ramp: Colours darkest first.
    from_step, to_step: 1-based indices into `ramp`, and they must be adjacent.
        Dithering between distant steps produces visible noise, not a gradient.
        **1-based, while `ramp` is a list the caller indexes from 0**, so the pair
        that dithers `ramp[3]` against `ramp[4]` is `from_step=4, to_step=5`. The two
        conventions usually sit a line apart:

            shade_region_by_light(f, GOLD, base_color=GOLD[4], ...)
            dither_band(f, GOLD, from_step=5, to_step=6, ...)   # GOLD[4], GOLD[5]

        Off by one still names an adjacent pair, so the call succeeds and dithers the
        wrong boundary. The result reports `from_color` and `to_color` for that
        reason: it is the only way to check the intent from the output.
    pattern: "bayer4" (finest, the usual choice), "bayer2" (chunkier) or "checker"
        (a hard 50/50 that suits a sharp material change).
    width: How far the dithered zone reaches into each band, in pixels. This is what
        widens the transition, which is the point of dithering: at width=1 only the
        seam itself alternates, and every pattern collapses to the same result
        because a one-pixel-deep band can only alternate.
    tolerance: How close a pixel must be to one of the two colours to take part.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

Only pixels of the two named colours that border each other are touched, so the
rest of the sprite is untouched even where it uses the same ramp.

Returns `dithered_pixels`, and `from_color`/`to_color`, the two colours the steps
actually resolved to.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampYes
frameNoDefault: 1.
layerNo
widthNoDefault: 2.
patternNoDefault: "bayer4".bayer4
to_stepYes
filenameYes
from_stepYes
toleranceNoDefault: 24.0.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnlyHint=false and openWorldHint=false, so the description carries most of the burden and does so well: it discloses that only pixels of the two named colours that border each other are touched, that the rest of the sprite is untouched, and that the result reports from_color/to_color. It does not explicitly state persistence/undo behavior, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then organized into a rationale block and an Args block. The indexing explanation is lengthy but earns its place given the documented off-by-one hazard. Slightly verbose, but no clearly wasted sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation tool with no output schema and low schema coverage, the description supplies the missing behavioural and parameter context, including return fields, scope of effect, and the indexing convention. Nothing an agent needs to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 44%, yet the description documents nearly every parameter with meaning beyond the schema: 1-based from_step/to_step semantics with a worked off-by-one example, the three pattern choices and their trade-offs, width's effect (and that width=1 collapses all patterns), tolerance, layer and frame. This fully compensates for the sparse schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (dither) and resource (the boundary between two adjacent ramp steps) plus the effect (widening the transition). It is immediately distinguishable from ramp-generation siblings like generate_ramp/ramp_between and from shade_region_by_light, which the description itself contrasts against.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the context for use (limited-palette necessity, buys an extra apparent shade) and why it is deliberately scoped to one boundary rather than a global filter. It also states the adjacency constraint. However, it never explicitly routes the agent to a named alternative tool for the global case, so it stops just 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.

draw_brushB

Stamp a custom brush shape at a list of points.

Args:
    brush: The brush as rows of characters. Any character other than space,
        '.', or '0' is a filled cell. e.g. a plus brush: ["010", "111", "010"].
    points: Positions to stamp at, list of {"x": int, "y": int}.
    color: Colour to stamp the brush in.
    anchor: "center" (default) or "topleft", where each point sits in the brush.
ParametersJSON Schema
NameRequiredDescriptionDefault
brushYes
colorYes
frameNoDefault: 1.
layerNo
anchorNoDefault: "center".center
pointsYes
filenameYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the agent already knows this mutates local state. The description adds meaningful input semantics (brush character encoding, anchor placement) but never says which file/layer/frame is affected, that it is destructive to existing pixels, or that 'filename' is required – gaps the annotations alone do not close.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line purpose followed by a compact Args block; every line earns its place and there is no filler. The only minor cost is the verbose brush example, which is nonetheless useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema and low schema coverage, the description covers the novel brush/point semantics but omits required-parameter guidance (filename) and the frame/layer targeting behavior, leaving an agent to infer how the stamp is scoped.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 29%, so the description carries real weight, and it does document brush, points, color, and anchor well (including the character-fill rule and the center/topleft values). However, three parameters – filename, frame, and layer – are undocumented in both schema and description, leaving the coverage gap only partly filled.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line gives a specific verb (stamp) and resource (custom brush shape) plus the target (a list of points), which is clear enough to distinguish it from pixel- or line-drawing siblings. It does not explicitly contrast itself with the closest alternatives like stamp_pattern or draw_pixel_map, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to reach for this tool versus stamp_pattern, draw_pixel_map, or draw_pixels, nor any prerequisites (e.g. an open sprite, valid layer/frame). The Args block documents inputs but never states the usage context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_curveA

Draw a quadratic Bézier curve from (x0,y0) to (x1,y1) bending toward the control point (control_x, control_y). steps controls smoothness.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
x0Yes
x1Yes
y0Yes
y1Yes
colorYes
frameNoDefault: 1.
layerNo
stepsNoDefault: 32.
filenameYes
control_xYes
control_yYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnlyHint=false and openWorldHint=false. The description adds genuine behavioral context beyond that: out-of-canvas writes are silently dropped rather than raising, every drawing call returns pixels_written and pixels_clipped, and the agent is told not to trust `ok` alone. It does not state whether the call needs an open sprite or which cel/layer is mutated, so it is not a full 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded correctly, but the bulk of the text is a shared drawing-convention preamble about draw_rectangle, draw_ellipse, draw_ellipse_in_box, and draw_symmetric_pixels — tools other than this one. It is dense rather than padded, yet a large fraction of the content does not earn its place in a curve-specific definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly steps in to describe the return payload (pixels_written, pixels_clipped) and the coordinate system and clipping policy, which is what an agent needs to call and verify this draw op. What remains missing — layer/frame targeting and preconditions — is secondary for a single-primitive draw call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 18% (basically just the two defaults), so the description has to carry the load. It explains the six geometric coordinates and gives `steps` a meaning ('controls smoothness'), but leaves frame, layer, and filename semantically undocumented. Partial compensation for a low-coverage schema lands at the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource — 'Draw a quadratic Bézier curve' — and enumerates the exact anchor and control points plus the `steps` parameter that governs it. That is precise enough to separate it from draw_line, draw_polyline, and the other drawing siblings without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The centring section gives real routing advice (use draw_ellipse_in_box for even diameters, etc.), but it tells the agent when to prefer OTHER primitives, not when to reach for draw_curve over draw_line or draw_polyline. Usage of this tool itself is only implied by the name and the Bézier phrasing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_ellipseA

Draw an ellipse centred at (center_x, center_y) with the given radii.

For a circle, use the same value for radius_x and radius_y. filled=False draws a 1px outline, and a filled ellipse is exactly that outline with its interior: the two are one shape rendered two ways, so a fill and an outline of the same call line up. antialias smooths a filled ellipse with sub-pixel coverage (RGB sprites only; ignored otherwise).

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerNo
filledNoDefault: false.
center_xYes
center_yYes
filenameYes
radius_xYes
radius_yYes
antialiasNoDefault: false.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark this as a non-read-only, closed-world write. The description adds real behavioral context: filled=False gives a 1px outline that lines up exactly with the filled version, antialias applies only to filled RGB sprites, out-of-canvas writes are dropped rather than raising, and pixels_written/pixels_clipped should be compared against intent instead of trusting ok.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the fill/antialias semantics are front-loaded, and the coordinate and centring details are grouped into scannable bullets. It is somewhat long for a single drawing primitive, but nearly every line carries non-obvious information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description covers the coordinate system, clipping behavior, and the keys returned (pixels_written, pixels_clipped), so return-shape handling is addressed. The main omission is format/meaning for color, layer, and frame, which a caller still has to infer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 30%, so the description must compensate. It gives strong meaning for center, radius, filled, and antialias (odd 2*radius+1 span, whole-pixel centring, fill/outline equivalence), but leaves color, layer, frame, and filename entirely unexplained - roughly half the parameters remain undocumented in either place.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource with the exact anchoring parameters (center_x, center_y, radii). It also distinguishes this primitive from draw_ellipse_in_box, draw_rectangle, and draw_symmetric_pixels via the centring bullet list, so an agent can select it without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing guidance: use this for a circle (radius_x == radius_y) and for pixel-centred spans, and switch to draw_ellipse_in_box for even diameters, discs on even canvases, or circles that must align with a rectangle. The when-to-use-vs-sibling condition is spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_ellipse_in_boxA

Draw an ellipse that fills the given bounding box exactly.

Takes the same box as draw_rectangle, so the two share a centre and an extent: this is how to draw a disc centred on an even canvas, or a circle that lines up with a rectangle. draw_ellipse takes a centre and radii instead, which can only ever be an odd 2*radius+1 across.

An even side is drawn the way it is drawn by hand: the odd ellipse one pixel smaller, with its middle row or column repeated. Give an odd width and height and the result is pixel for pixel what draw_ellipse produces for the same shape, because both use the same geometry.

filled=False draws a 1px outline. antialias smooths a filled ellipse with sub-pixel coverage (RGB sprites only; ignored otherwise).

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
colorYes
frameNoDefault: 1.
layerNo
widthYes
filledNoDefault: false.
heightYes
filenameYes
antialiasNoDefault: false.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only state readOnlyHint=false and openWorldHint=false. The description adds substantial behavioral detail beyond that: out-of-canvas writes are dropped rather than raising, results are reported via pixels_written/pixels_clipped that should be checked instead of trusting ok, and antialias applies only to filled RGB sprites. This is rich context the annotations do not carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then structured into geometry, centring comparison, and clipping notes. It is long, but nearly every sentence carries distinct information (odd/even parity, layout alignment, clip reporting); the bulleted centring section is the only part that could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter mutation tool with no output schema, it covers the critical drawing semantics, coordinate convention, and return-field behavior. It leaves color format and the frame/layer parameters unexplained, so it is strong but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 30% schema coverage, the description must compensate and largely does: it defines the box semantics of x/y/width/height ('x .. x + width - 1, so width is a count of pixels, not an offset'), explains filled=False as a 1px outline, and clarifies antialias behavior. Gaps remain for color, layer, and frame, which are undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a precise verb+resource+scope: draw an ellipse that fills the given bounding box exactly. It explicitly distinguishes itself from draw_ellipse (centre+radii, odd sizes), draw_rectangle (shares the box), and draw_symmetric_pixels, so an agent can pick correctly without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States explicitly when to use this tool ('the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle') and pins the comparison against named alternatives, including the odd-vs-even size distinction versus draw_ellipse.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_image_base64A

Composite an inline base64-encoded PNG (or other image) onto a layer at (x, y).

Useful for pasting externally generated artwork. `image_base64` may include a
`data:image/png;base64,` prefix. The decoded image is capped at 32 MB; for
anything larger, write the file into the workspace and use `stamp_file`.
ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
frameNoDefault: 1.
layerNo
opacityNoDefault: 255.
filenameYes
blend_modeNoDefault: "normal".normal
image_base64Yes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only state readOnlyHint=false and openWorldHint=false, which already imply a local mutating operation. The description adds real context beyond that: the 32 MB decoded-size cap, tolerance for a data: URI prefix, and the fallback path for oversized images. It does not describe how existing layer content is affected by compositing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the use case, then the base64/size caveats and fallback. No filler; every sentence carries operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so return values needn't be explained. The call-critical details (base64 prefix, size cap, preference for stamp_file on large inputs) are present, though unaddressed parameters like blend_mode and opacity leave some gaps for a compositing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 38% for 8 parameters. The description clarifies image_base64 format (optional data: URI prefix) and implies x/y placement, which does add meaning. However, layer, opacity, blend_mode, and frame are undocumented in both schema and description, so it only partially compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (composite) plus resource (inline base64-encoded image) and the destination (a layer at (x, y)). It is immediately distinguishable from the sibling stamp_file, which is file-based, and from draw_pixels/draw_pixel_map which draw pixel data rather than images.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a use case ('pasting externally generated artwork') and explicitly names the alternative stamp_file with the condition that selects it (>32 MB). No explicit when-not beyond the size threshold, but the routing guidance is concrete and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_lineA

Draw a straight line from (x1,y1) to (x2,y2).

Args: pixel_perfect: Remove L-shaped corner pixels for a clean 1px pixel-art line. antialias: Smooth (Xiaolin Wu) line with alpha blending, RGB sprites only; ignored on indexed/gray. Takes precedence over pixel_perfect.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
x1Yes
x2Yes
y1Yes
y2Yes
colorYes
frameNoDefault: 1.
layerNo
filenameYes
antialiasNoDefault: false.
pixel_perfectNoDefault: false.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide readOnlyHint=false and openWorldHint=false. The description adds substantial behavioral context: out-of-canvas writes are dropped rather than raising, and reports pixels_written/pixels_clipped so the agent should compare against expectations rather than trusting 'ok'. This is exactly the kind of non-obvious behavior annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and args, then provides useful coordinate/centring reference material. The centring section is lengthy and somewhat tangential to drawing a line, but it is structured and earns its place for alignment work. Slightly verbose but well organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a drawing primitive with no output schema and low schema coverage, the description covers coordinate conventions, mode interactions, clipping behavior, and sibling primitive distinctions. An agent has everything needed to call it correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 30%, so the description must compensate. It explains pixel_perfect and antialias semantics, and critically defines the coordinate system ((0,0) top-left, y grows down, span = x..x+width-1). It does not explain frame, layer, or color parameters, leaving some gaps, but adds meaningful value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Draw a straight line') with exact endpoint syntax '(x1,y1) to (x2,y2)'. Distinguishes itself from sibling primitives like draw_rectangle, draw_ellipse, and draw_polyline by naming them and clarifying their differing centring conventions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly explains the alternative modes (pixel_perfect vs antialias) and when antialias applies (RGB only, ignored on indexed/gray, takes precedence over pixel_perfect). Does not give an explicit when-to-use-this-tool-instead-of-siblings directive, but the centring comparisons guide the agent toward the right primitive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_pixel_mapA

Draw from a character grid, one character per pixel: the way pixel art is authored.

This is the write side of get_pixels(format="map") and takes exactly the shape that returns, a legend plus one string per row, so a read, an edit and a write round-trip. Until this existed the server could show a caller per-pixel intent and could not receive it: the only way to author a figure was a list of {"x", "y", "color"} dictionaries, one per pixel.

That asymmetry shaped the art it produced, which is the real reason this is here. A caller reaching for a thousand-entry dictionary list does not write a thousand considered pixels, it writes a formula that emits them, and a formula produces smooth monotone surfaces. Hand-placed pixel art is the opposite of that: a highlight nudged two pixels off the geometric centre, an outline that thickens on the shadow side, three pixels clustered to imply a chip in the stone. A grid is the notation those decisions can be written in, and it is about a tenth the size: a 16x16 of three colours is roughly 3,400 characters as dictionaries and 350 as a map.

Args: rows: One string per row, one character per pixel, every row the same length. A ragged map is refused rather than padded, because padding would shift every pixel after the short row. legend: Symbol to colour, as {"a": "#1b2b4a", "b": "red"}. "." means leave that pixel alone and needs no entry; any other character can say the same with the value "transparent", which is what the read side emits. A character the legend does not define is refused, not skipped: a typo in a grid would otherwise paint nothing and report success. x, y: Where the map's top-left corner lands on the canvas. Defaults to the canvas origin. layer: Target layer name or 1-based index (default: top layer). frame: Target frame, 1-based (default 1).

Transparent cells are left untouched rather than erased, so a map can be stamped over existing art; clear the layer first if you want the map to be the whole of it.

Returns the usual write counters plus map_width, map_height, pixels_transparent (cells deliberately left alone) and colors_used.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
rowsYes
frameNoDefault: 1.
layerNo
legendYes
filenameYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare `readOnlyHint=false` and `openWorldHint=false`; the description adds substantial behavioral detail beyond that: ragged maps are refused rather than padded, undefined legend characters are refused rather than skipped, transparent cells are left untouched so maps can be stamped over existing art, and out-of-bounds writes are dropped with `pixels_clipped` reported. This is rich disclosure of failure modes and side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections for args, returns, coordinates, and centering, but it is long and includes extended rationale about the asymmetry of prior APIs and the nature of hand-placed pixel art. Some of that narrative is justification rather than actionable guidance, so it is not as concise as it could be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description explains the returned counters (`map_width`, `map_height`, `pixels_transparent`, `colors_used`) and the general write counters, along with clipping behavior, coordinate conventions, and centering differences among related primitives. For a complex 7-parameter write tool with minimal annotations, this is complete enough to invoke correctly, with only the trivial omission of `filename`.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 43% schema description coverage, the description carries most parameter meaning: it explains `rows` (one string per row, equal lengths, ragged refused), `legend` (symbol-to-color mapping, `.` and `transparent` semantics, undefined characters refused), `x`/`y` (top-left placement), `layer` (name or 1-based index, default top), and `frame` (1-based, default 1). It does not mention the required `filename` parameter, leaving a small gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Draw from a character grid, one character per pixel') and explicitly positions itself as the write side of `get_pixels(format="map")`, distinguishing it from dictionary-list pixel writing and from sibling drawing tools. An agent can identify exactly what it does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context: it round-trips with `get_pixels(format="map")` and is the notation for hand-placed pixel art, contrasted with formula-generated dictionary lists. However, it does not explicitly state when to choose this over `draw_pixels`, `draw_line`, or other drawing primitives, nor does it give exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_pixelsA

Plot individual pixels.

Args: pixels: List of {"x": int, "y": int, "color": "#hex"?}. If a pixel omits "color", the shared color argument is used. color: Default colour for pixels that don't specify their own. layer: Target layer name or 1-based index (default: top layer). frame: Target frame, 1-based (default 1).

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorNo
frameNoDefault: 1.
layerNo
pixelsYes
filenameYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnlyHint=false, openWorldHint=false) by disclosing that out-of-canvas writes are silently dropped rather than raising, that pixels_written/pixels_clipped are reported, and advising the agent not to trust `ok`. These are exactly the failure-mode details an agent needs before calling a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and the args block, then the coordinate and centring conventions. The centring bullets lean toward sibling-tool documentation, but each carries useful alignment information and nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by naming the returned counters (pixels_written, pixels_clipped) and their clipping semantics, plus the coordinate origin and drop-outside-canvas rule. The main gap is that `filename` is never tied to a canvas/sprite concept.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 20% schema description coverage, the description carries the load well: it documents the pixel object shape ({x, y, color?}), the fallback `color`, `layer` accepting a name or 1-based index with a default of top layer, and `frame` being 1-based with default 1. Only the required `filename` parameter is left unexplained anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: "Plot individual pixels" with a per-pixel list contract. It is clearly a raster-primitive tool, though it never explicitly distinguishes itself from the nearby sibling draw_pixel_map or draw_brush, leaving the agent to infer the difference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied rather than stated: the centring section tells the agent which primitive to pick for even vs odd diameters, but that is guidance about sibling tools. There is no explicit "use draw_pixels when... / prefer draw_pixel_map when..." routing for this tool itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_polylineA

Draw connected line segments through a list of points.

points: list of {"x": int, "y": int}. Set closed=True to connect the last point back to the first (outline a polygon). pixel_perfect removes L-corner pixels across the whole path for a clean pixel-art outline.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerNo
closedNoDefault: false.
pointsYes
filenameYes
pixel_perfectNoDefault: false.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the description carries the behavioral burden and does so well: out-of-canvas writes are silently dropped rather than raising, and every drawing tool reports pixels_written/pixels_clipped, with the explicit warning to compare those rather than trusting 'ok'. That is exactly the failure-mode context an agent needs before a write.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, followed by parameter semantics, then coordinate conventions and clipping behavior; each block earns its place. The multi-bullet centring comparison is tangential to this specific tool and could be relegated elsewhere, which keeps it from a full 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description steps in to describe the returned pixels_written/pixels_clipped counters and the clipping failure mode, plus the coordinate system and centring conventions. The only remaining gap is the semantics of color, frame and layer, which an agent must infer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 43%, so the description must compensate, and it does for the non-obvious parameters: points is defined as a list of {x:int, y:int}, closed is explained as connecting last point to first, and pixel_perfect removes L-corner pixels. color, frame, layer and filename remain undocumented in both schema and description, which keeps it short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource — 'Draw connected line segments through a list of points' — which is clearly distinct from siblings like draw_line, draw_curve, draw_rectangle and draw_ellipse. An agent can identify the tool's job without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It hints that closed=True produces a polygon outline, but it never states when to prefer draw_polyline over draw_line or draw_curve. The comparative guidance it does give (draw_ellipse_in_box vs draw_rectangle centring) is about other primitives rather than about selecting this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_rectangleA

Draw a rectangle. filled=False draws a 1px outline, True fills it.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
colorYes
frameNoDefault: 1.
layerNo
widthYes
filledNoDefault: false.
heightYes
filenameYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give readOnlyHint=false and openWorldHint=false, so the description carries the behavioural load and does so: out-of-canvas writes are dropped rather than raising, and the tool returns pixels_written/pixels_clipped which should be compared against intent rather than trusting 'ok'. That is exactly the kind of trait an agent needs and cannot get from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core behaviour, then the coordinate/centring detail. Every bullet carries real information an agent needs for alignment, though the centring section is long enough that a shorter phrasing could convey the same rule.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description closes the biggest gaps by naming the returned counters (pixels_written, pixels_clipped) and the clipping policy. It is not fully complete because four of nine parameters (filename, color, layer, frame) get no explanation anywhere.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 22%, so the description must compensate, and it does for the geometric core: it defines the origin, growth direction, the x..x+width-1 span rule, and the filled flag. However, filename, color, layer and frame are left entirely undocumented in both schema and prose, so the compensation is substantial but incomplete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Draw a rectangle') and immediately pins down the filled flag's meaning. It also explicitly distinguishes itself from near-siblings (draw_ellipse, draw_ellipse_in_box, draw_symmetric_pixels), so an agent can route correctly without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use-which guidance: pick draw_ellipse_in_box for even diameters, a disc centred on an even canvas, or a circle that must line up with a rectangle, and notes draw_symmetric_pixels mirrors about the canvas. It also states the alignment/centring condition that governs the choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_symmetric_pixelsB

Plot pixels together with their mirror image(s).

mode: "horizontal" (mirror across vertical axis_x), "vertical" (across axis_y),
or "both" (4-way radial symmetry). Axes default to the canvas centre.
ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoDefault: "horizontal".horizontal
colorYes
frameNoDefault: 1.
layerNo
axis_xNo
axis_yNo
pixelsYes
filenameYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the agent knows this is a local mutation. The description usefully adds the mirroring behavior and axis defaults, but says nothing about whether it overwrites or blends existing pixels, which layer/frame it targets, or any return value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the core purpose front-loaded and no filler. The mode enumeration is compact, though the parenthetical phrasing ("across vertical axis_x") is slightly terse and could be misread.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 8 parameters, 25% schema coverage, and no output schema, the description covers the symmetry concept and axis defaults but omits the pixels payload shape, color format, and frame/layer targeting. An agent can grasp intent but lacks enough detail to call it correctly without inspecting the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, so the description must carry weight; it does explain the mode enum values and that axis_x/axis_y default to the canvas centre. However, the required parameters (filename, pixels, color) and the format of the pixels array (objects with additionalProperties) remain undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Plot pixels together with their mirror image(s)" gives a specific verb (plot/draw), resource (pixels), and the distinguishing feature (mirror symmetry) that separates it from the sibling draw_pixels. It does not explicitly name an alternative, but the symmetry concept makes the tool's niche clear without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the mode values (horizontal/vertical/both) but never states when to choose this tool over draw_pixels or mirror_layer. Usage is only implied by the mode semantics, with no when-to-use or when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

draw_textA

Draw text onto a layer at (x, y) in a single colour.

Args:
    text: The string (supports "\n" for multiple lines).
    x, y: Top-left position of the text.
    color: Text colour.
    scale: Integer pixel-scaling of the rendered glyphs (default 1).
    font_path: Optional path to a .ttf/.otf font. If omitted, a built-in
        bitmap font is used (best for tiny pixel text).
    font_size: Point size when a TrueType font_path is given.
    spacing: Extra pixels between lines.
    threshold: 0-255 cutoff; pixels brighter than this are drawn (lower =
        heavier text). Keeps glyphs crisp (no anti-aliasing artefacts).

scale is capped at 64, font_size at 512, and the rendered text at 200,000
pixels; the pixel budget is enforced while rasterizing, not afterwards.

Returns the standard draw result plus the rendered text's pixel size.
ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
textYes
colorYes
frameNoDefault: 1.
layerNo
scaleNoDefault: 1.
spacingNoDefault: 1.
filenameYes
font_pathNo
font_sizeNoDefault: 16.
thresholdNoDefault: 128.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the mutating, local nature is already known. The description adds value beyond that: the scale=64, font_size=512, and 200,000-pixel caps, the fact that the pixel budget is enforced during rasterization (not afterwards, implying no silent retro-crop), and the threshold's crisp anti-aliasing behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the one-line purpose, then an Args block, then caps explanation, then return note. Every sentence carries information, though the return sentence is somewhat redundant given output schema absence is answered anywhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-param draw tool with no output schema and partial schema coverage, the description covers the majority of parameters plus hard limits and return shape. Missing only minor details like frame/layer targeting and spacing units beyond lines, but the important behavioral limits are present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 42% schema description coverage and 12 parameters, the schema leaves many parameters with only default values. The description explains text (supports \n), x/y as top-left, color, scale limits, font_path fallback behavior, font_size context, spacing meaning, and threshold 0-255 semantics, substantially compensating for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (draw) and resource (text) with precise location semantics (top-left x,y). Distinct from sibling raster tools like draw_line or fill_area, and from stamp_file/draw_image_base64, which place images not glyphs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage (drawing glyph strings onto a layer) and offers a hint via font_path semantics – omit it for built-in bitmap text, provide a .ttf/.otf for TrueType. However, there is no explicit when-to-use vs when-not-to-use guidance relative to sibling text-ish or image-drawing tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

duplicate_frameA

Duplicate an existing frame (1-based); the copy is inserted after it.

`frame` must already exist: an out-of-range number is rejected with the sprite's
valid range rather than clamped to it.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameYes
filenameYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false, so the mutation/safety profile is already covered; the description goes beyond that by disclosing error semantics (rejection with the sprite's valid range instead of silent clamping) and 1-based indexing. It stops short of saying what is returned or whether the change is persisted to `filename`.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loading the verb+resource and the insertion position, with the precondition detail following. No filler; each clause adds usable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description should clarify the return value (new frame index?) and whether `filename` identifies the file being mutated on disk. Those gaps plus the undocumented `filename` parameter leave an agent short of a fully confident call, despite solid coverage of the frame argument.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden and it only partially delivers: `frame` is well specified (1-based, must exist, error behavior on out-of-range), but `filename` — the required target file — is never mentioned or explained. Half the parameter surface is still undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (duplicate an existing frame) and adds the key behavioral detail that the copy lands immediately after the source. It is implicitly distinguishable from siblings like add_frame, remove_frame and move_frame, but never names or contrasts them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a real precondition — the target frame must already exist and out-of-range values are rejected with the valid range rather than clamped — which tells the agent when this call is legal. However, it offers no routing guidance among alternatives such as add_frame (for a blank frame) or copy_cel/duplicate_layer, leaving the choice of tool to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

duplicate_layerB

Duplicate a layer (including its cels) as a new layer on top.

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds real behavioral value by specifying that cels are included and the new layer is placed on top, but says nothing about whether the original is untouched, naming, or what identifies the new layer afterwards.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence, front-loaded with the verb and the key behavioral caveat (cels included, placed on top). No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With two undocumented required parameters and no output schema, the description should at least clarify how the layer is addressed and what is returned. It omits both, leaving the agent to guess at identification semantics for a tool that creates a new object.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden and fails it: neither 'filename' (which sprite file?) nor 'layer' (name, index, or id?) is explained. Both are required, so ambiguity in 'layer' is a genuine invocation risk.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (duplicate) and resource (layer), plus a meaningful detail: cels are copied and the copy lands on top. This distinguishes it from add_layer (empty layer) and duplicate_frame (frame-level sibling). It does not explicitly name a sibling, so it stops short of 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use context, no prerequisites, and no routing to alternatives such as add_layer or copy_cel when only part of the layer is wanted. The agent must infer that this is for whole-layer copies from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_framesA
Destructive

Export each frame to its own image file.

output_pattern must contain "{frame}" (and optionally "{tag}", "{layer}"),
e.g. "frames/walk_{frame}.png". Aseprite substitutes the values.

overwrite: Replace files the pattern would expand onto (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
filenameYes
overwriteNoDefault: false.
output_patternYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, giving the safety profile. The description adds the important no-clobber default behavior and the overwrite semantics, which is useful beyond annotations. However, it doesn't state where files are written, whether parent directories are created, or the interaction between destructiveness and the no-clobber default.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight, front-loaded sentences. The key constraint (output_pattern must contain {frame}) follows immediately after the purpose statement, and the overwrite clarification is appended without waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate for a 4-param mutation tool with annotations and no output schema. It covers the pattern DSL and overwrite behavior, but omits output location context, directory creation, and how scale interacts with each export.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%; the description explains output_pattern placeholder syntax ({frame}, {tag}, {layer}) and overwrite semantics, compensating for the schema's bareness on those two. The other two parameters (scale, filename) get no description elaboration beyond what the schema shows.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (export) and resource (each frame to its own image file) with explicit granularity. This clearly distinguishes it from export_png (single image), export_spritesheet (packed sheet), and export_gif (animation).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage is clear from the purpose (per-frame image export), but there's no explicit guidance on when to choose this over export_layer or export_layers, nor any stated prerequisites. No when-not-to-use or alternative routing is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_game_asset_bundleA
Destructive

Export a sprite into a game-ready bundle directory: a flattened PNG, an animated GIF, a packed sprite sheet (+ JSON data), a GIF per animation tag, and a manifest.json describing everything.

Args:
    overwrite: Replace existing bundle files (default False = no-clobber). Every
        planned output is checked up front, so the bundle fails before writing any
        file if a target already exists.

Returns a ``workflow_manifest.v1`` manifest (the same object is also written to
disk as manifest.json inside the bundle).
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
filenameYes
overwriteNoDefault: false.
bundle_nameNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag this as non-read-only and destructive, and the description adds genuinely useful behavior: no-clobber default, an up-front check of every planned output, and fail-before-writing semantics. It could still say more about permissions or clobber risk per file, but it meaningfully exceeds the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the artifact list, then a focused Args block on the one parameter that needs explanation, then a tight Returns sentence. Only minor redundancy in restating that the manifest is both returned and written as manifest.json.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema, and the description correctly fills that gap by naming the returned workflow_manifest.v1 and its on-disk counterpart. Mutation semantics and the overwrite flag are covered, though scale/bundle_name remain unaddressed for a 4-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 50% (filename and bundle_name have no descriptions; scale/overwrite only carry boilerplate defaults). The description thoroughly explains overwrite's no-clobber behavior, but adds nothing for scale, bundle_name, or filename, so it only partially compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Export) and resource (sprite into a game-ready bundle directory), then enumerates the exact artifacts produced: flattened PNG, animated GIF, packed sprite sheet + JSON, per-tag GIFs, and manifest.json. This clearly distinguishes it from the single-purpose siblings export_png, export_gif, and export_spritesheet_packed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the artifact list (use this instead of calling the individual export tools when you want everything at once), but the description never explicitly says when to choose this over export_png/export_gif/export_spritesheet or what prerequisites exist. The reader must infer the routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_gifA
Destructive

Export the full animation as an animated GIF (honours frame durations).

Tag *ranges* are honoured, but a tag's playback direction is not: a GIF is a flat
frame sequence. A ping-pong tag exports forward, and the result says so in
`warnings` rather than letting the caller find out in-engine.

overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
outputYes
filenameYes
overwriteNoDefault: false.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real context beyond the annotations: GIFs are flat frame sequences, ping-pong tags silently export forward and the loss is surfaced in `warnings`, and overwrite defaults to no-clobber. The no-clobber/overwrite disclosure is valuable for a destructiveHint=true tool, though permission requirements and error behavior remain unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then the important tag-direction caveat, then the overwrite note. Each block earns its place, though the phrasing is slightly loose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description usefully names the `warnings` channel where downgraded playback direction is reported. With a destructive write and 4 params, it covers the main behavioral traps, though the required path params and scale remain unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, with `output` and `filename` carrying no descriptions. The description explains `overwrite` semantics well (replace if exists, default False), but adds nothing for `scale` or the two required path parameters, so it only partially compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Export) and resource (the full animation as an animated GIF), and the phrase 'full animation' implicitly distinguishes it from the tag-scoped sibling export_tag_gif. It stops short of explicitly naming that alternative, so the distinction requires inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: 'Export the full animation' suggests this is the whole-sprite exporter versus export_tag_gif, but no explicit when-to-use or when-not guidance is given. The tag-range caveat is behavioral rather than a selection cue.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_godot_spriteframesA
Destructive

Export a sprite as a Godot 4 SpriteFrames resource (.tres) + a packed sheet.

Produces three files: a packed PNG sprite sheet, its JSON frame/tag metadata, and a
``SpriteFrames`` .tres that references the sheet via ``AtlasTexture`` regions, one
Godot animation per Aseprite tag (or a single ``default`` animation if untagged), with
per-frame timing taken from Aseprite frame durations.

v1 emits ``SpriteFrames`` only (no pivot/origin/hitbox/9-slice). Aseprite tag direction
isn't represented (Godot animations only loop or not); ``default_loop`` is applied to all.

Args:
    output: Destination .tres path (workspace-relative).
    sheet_output: Sheet PNG path. Defaults to ``<output stem>.png`` beside the .tres.
    scale: Integer upscaling factor for the sheet.
    texture_res_path: The ``res://`` path of the sheet inside your Godot project (the
        AtlasTexture atlas). Defaults to ``res://<sheet filename>`` (same-folder import).
    default_loop: ``loop`` flag for every generated animation (default True).
    overwrite: Replace existing outputs (default False = no-clobber). All three targets
        are validated up front, so nothing is written if any already exists.

Returns a ``workflow_manifest.v1`` manifest (kind ``engine_preset``).
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
outputYes
filenameYes
overwriteNoDefault: false.
default_loopNoDefault: true.
sheet_outputNo
texture_res_pathNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, but the description adds substantial context beyond them: no-clobber default, up-front validation of all three targets ('nothing is written if any already exists'), and v1 limitations (no pivot/origin/hitbox/9-slice, tag direction not represented, default_loop applied to all). This materially mitigates and elaborates the destructive profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and outputs are front-loaded, followed by an Args block and a concise return line; every sentence carries information. It is somewhat long, but no sentence is filler given the mutation and v1 caveats it must convey.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, it discloses the return type (workflow_manifest.v1, kind engine_preset), side effects, no-clobber semantics, and scope limitations. The only meaningful omission is the required filename parameter, which is undocumented in both description and schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 43% (most params carry just a 'Default:' string), so the description compensates well: it explains output, sheet_output's derivation from output stem, scale's meaning as upscaling factor, texture_res_path's res:// role and default, plus default_loop and overwrite semantics. The required 'filename' param remains unexplained, so it falls short of full compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Export a sprite as a Godot 4 SpriteFrames resource (.tres) + packed sheet') and enumerates the three concrete artifacts produced. This distinguishes it from siblings like export_spritesheet, export_gif, and export_game_asset_bundle without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the Godot-4 engine target and the v1 scope note, but the description never names an alternative export tool or states when to prefer this over export_spritesheet/export_game_asset_bundle. No explicit when/when-not routing is provided, leaving selection to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_layerB
Destructive

Export a single layer of one frame as a PNG (others excluded).

overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerYes
scaleNoDefault: 1.
outputYes
filenameYes
overwriteNoDefault: false.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description adds useful non-clobber context: overwrite defaults to False so an existing `output` is preserved unless opted in. It does not, however, clarify whether the export writes files to disk, what happens on path conflicts beyond the overwrite flag, or any auth constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short lines, front-loaded with the purpose and followed by the one non-obvious parameter's behavior. No filler or repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, six-parameter write tool with no output schema, the definition covers the core action and the overwrite semantics but is thin on the remaining parameters and on side effects. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50% and six parameters exist, so the schema does only part of the work. The description adds real meaning for `overwrite` (no-clobber default), but says nothing about `filename` vs `output`, `scale`, or `frame`, leaving half the parameters ambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (export), resource (single layer of one frame), format (PNG), and scope (others excluded), which meaningfully distinguishes it from export_png and export_layers. It stops short of naming those siblings explicitly, so an agent must infer the routing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'others excluded' implies this is the narrow per-layer variant, but the description never says when to prefer it over export_png, export_layers, export_frames, or export_spritesheet. No prerequisites or alternatives are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_layersA
Destructive

Export each layer to its own image file.

output_pattern must contain "{layer}" (e.g. "layers/{layer}.png"); add
"{frame}" too for animations. include_hidden also exports hidden layers.

overwrite: Replace files the pattern would expand onto (default False =
no-clobber). Aseprite expands the placeholders, so the check refuses when any
file matching the pattern already exists.
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
filenameYes
overwriteNoDefault: false.
include_hiddenNoDefault: false.
output_patternYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true, and the description goes further by explaining exactly what the destruction means: the default is no-clobber, and the check refuses when any file matching the expanded pattern already exists. It stops short of describing the return payload, partial-write behavior, or whether directories are auto-created.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action is front-loaded and each subsequent sentence maps to a distinct parameter concern with no filler. The final sentence on Aseprite's placeholder expansion is dense but earns its place by explaining why the existence check works the way it does.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter, destructive, no-output-schema tool, the description covers the highest-risk parts: output path templating, hidden-layer inclusion, and clobber protection. It omits only secondary concerns like scale behavior and what the call returns, which are minor against the covered risk surface.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% and the description meaningfully lifts three of the bare parameters: it documents output_pattern placeholder syntax and the '{frame}' variant, explains include_hidden's effect, and details overwrite's no-clobber semantics. 'scale' and 'filename' remain undocumented in both places, which is the remaining gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and scope: 'Export each layer to its own image file,' which distinguishes it from bulk exporters like export_png and from the singular export_layer. It never names those siblings as alternatives, so the differentiation is implied rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage conditions are implied through the required '{layer}' placeholder and the note about adding '{frame}' for animations, which tells the agent when the tool applies. There is no explicit when-not guidance or pointer to export_layer for single-layer output, leaving sibling routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_minecraft_textureA
Destructive

Export a sprite into a resource pack at its correct texture path.

A single-frame sprite exports as a plain PNG. A multi-frame sprite exports as a
**vertical strip** (frame 1 on top, no padding) and gets a ``.png.mcmeta`` sidecar -
that pairing is what the game reads as an animation, and either half alone is broken.

Args:
    pack_root: The resource-pack directory (its ``assets/`` tree is written under this).
    namespace: Your mod/pack id. Defaults to "minecraft", which overrides vanilla.
    category: Texture subdirectory - block, item, entity, gui, particle, ...
    texture_name: In-pack texture name, ``/`` allowed for subdirectories. Defaults to
        the sprite's filename stem.
    frametime: Ticks per frame for the animation sidecar (1 tick = 50 ms).
    interpolate: Blend between animation frames.
    frame_order: Optional playback order (see ``write_texture_mcmeta``).
    overwrite: Replace existing files (default False = no-clobber).

Returns a ``workflow_manifest.v1`` manifest (kind ``minecraft_texture``).
ParametersJSON Schema
NameRequiredDescriptionDefault
categoryNoDefault: "block".block
filenameYes
frametimeNoDefault: 1.
namespaceNoDefault: "minecraft".minecraft
overwriteNoDefault: false.
pack_rootYes
frame_orderNo
interpolateNoDefault: false.
texture_nameNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, and the description adds concrete value beyond them: the no-clobber default for overwrite, the requirement that the .png.mcmeta sidecar and the vertical-strip PNG must be written together, and the fact that assets/ is written under pack_root. It does not discuss permissions or rate limits, but for a local file-writing tool that is minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical behavioral distinction (PNG vs vertical strip + mcmeta) is front-loaded before the Args block, and the Args block is compact. It runs slightly long, but nearly every line carries information an agent needs to call the tool correctly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation tool with no output schema, the description covers behavior, parameter meaning, side effects, and the return value ('workflow_manifest.v1' manifest, kind 'minecraft_texture'). Nothing essential to a correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 56% (mostly bare defaults), yet the description documents essentially every parameter meaningfully: pack_root's assets/ tree, namespace's vanilla-override semantics, category values, texture_name's '/'-based subdirectories, frametime in ticks (1 tick = 50 ms), interpolate blending, and overwrite's no-clobber default. This is strong compensation for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('Export a sprite into a resource pack at its correct texture path') and immediately distinguishes this tool from the many sibling export_* tools by specifying the Minecraft resource-pack target. The single-frame vs multi-frame behavior further pins down what it produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states the condition that changes behavior (single-frame vs multi-frame) and routes frame_order to the sibling write_texture_mcmeta. It does not, however, explicitly say when to prefer this over export_png or validate_minecraft_texture, so routing is implied rather than fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_onion_skinA
Destructive

Export a frame with neighbouring frames ghosted behind it (onion skin).

Args:
    frame: The in-focus frame (drawn fully opaque), 1-based.
    previous, next: How many earlier/later frames to ghost.
    ghost_opacity: Max opacity (0-255) of the nearest ghost; further frames fade.
    scale: Integer upscaling factor for the output PNG.
    overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
nextNoDefault: 0.
frameYes
scaleNoDefault: 4.
outputYes
filenameYes
previousNoDefault: 2.
overwriteNoDefault: false.
ghost_opacityNoDefault: 80.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag the tool as a non-read-only, destructive write (destructiveHint=true), so the no-clobber behaviour needs credit only for the added detail: 'overwrite: Replace output if it already exists (default False = no-clobber)'. That is a genuinely useful behavioural fact beyond the annotation. However, other behaviours an agent needs—output format/bit depth beyond PNG, failure behaviour when the frame is out of range, and whether neighbouring frames are silently clipped at sequence bounds—are absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The front-loaded one-sentence summary is strong and the per-argument list is tight; each line earns its place. The Google-style 'Args:' block formatting is slightly awkward embedded in a description field but does not waste words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter destructive export with no output schema, the description covers the fusion/ghost semantics and the clobber flag but leaves filename/output semantics and error/boundary behaviour unspecified. Adequate, not complete."

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

At 63% schema coverage, several params carry only a 'Default: N' stub. The description compensates well for the semantically important ones: frame is 'the in-focus frame (drawn fully opaque), 1-based', previous/next are 'how many earlier/later frames to ghost', ghost_opacity is 'max opacity (0-255) of the nearest ghost; further frames fade', and scale is 'integer upscaling factor'. The 1-based indexing and fade semantics are real added meaning. Only filename and output remain unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (export) and resource (a frame with ghosted neighbouring frames), and the parenthetical '(onion skin)' names the exact technique. Among a large set of export_* siblings, this is clearly distinguishable as the onion-skin renderer.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by defining what onion skinning is, but never states when to choose this over the neighbouring export_frames, export_layer, or render_preview siblings, nor any prerequisite. Usage is inferred from the technique name rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_pngA
Destructive

Export one frame as a flattened PNG.

Args:
    output: Destination .png path.
    frame: Frame to export, 1-based (default 1).
    scale: Integer upscaling factor (default 1).
    overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
scaleNoDefault: 1.
outputYes
filenameYes
overwriteNoDefault: false.

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, and the description adds concrete behavioral context that annotations don't: overwrite defaults to no-clobber ('Replace output if it already exists') and output is flattened. This clarifies exactly what the destructive flag governs. It doesn't cover error behavior or rate limits, but the no-clobber disclosure is genuinely useful.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by a tight args list, with zero filler. Each line earns its place. The structure is standard and readable, though the args block could be folded more compactly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an export tool with no output schema, the destination-path and overwrite semantics are covered, but the required 'filename' parameter is undocumented in both schema and description, leaving a real gap for correct invocation. Return/error behavior is also unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% (frame/scale/overwrite only carry 'Default: X'), and the description meaningfully extends this: frame is 1-based, scale is an integer upscaling factor, and overwrite's no-clobber default is spelled out. The required 'filename' parameter is never explained in either the schema or the description, which caps the score below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Export one frame as a flattened PNG.' The phrase 'one frame' implicitly distinguishes it from siblings like export_frames and export_spritesheet, so an agent can route reasonably. It stops short of explicitly naming those alternatives, but the 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.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance relative to the many export siblings (export_gif, export_frames, export_layer, export_spritesheet). The 'one frame' scoping implies a single-frame use case but leaves the agent to infer it against alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_slice_metadataA
Destructive

Export every slice as engine-agnostic JSON (aseprite_mcp.slice_metadata.v1).

Each slice becomes ``{name, type, id, bounds, pivot, nine_slice, color, data,
raw_data}``. **Type detection:** a slice's user-data JSON ``type`` wins; otherwise the
name convention ``<type>:<id>`` (recognized types: hitbox, hurtbox, collision, interact,
pivot, origin, attach, spawn, nine_slice; anything else becomes ``"custom"``, never an
error). ``id`` comes from the data ``id`` or the name's ``:<id>`` suffix. ``nine_slice``
(Aseprite's 9-patch center) and ``pivot`` are emitted whenever the slice has them. Slice
user-data that is valid JSON is parsed into ``data``; the raw string is kept in ``raw_data``.

Args:
    output: Destination .json path. Defaults to ``<sprite>_slices.json`` beside the sprite.
    overwrite: Replace an existing file (default False = no-clobber).

Returns a ``workflow_manifest.v1`` manifest (kind ``engine_metadata``).
ParametersJSON Schema
NameRequiredDescriptionDefault
outputNo
filenameYes
overwriteNoDefault: false.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations mark it destructive/not-read-only, and the description earns its keep by disclosing the no-clobber default, the overwrite flag semantics, and the default output path — concrete write-behavior context beyond the annotations. It stops short of stating permissions or failure modes, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose and output format, then type-detection rules, args, and return. It is dense but every section (type precedence, id derivation, raw_data retention) carries information an agent would otherwise have to guess.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description describes the returned workflow_manifest.v1 manifest (kind engine_metadata) and the emitted slice object shape, so the agent knows both what is written and what comes back. Minor gaps around permissions/failures remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33%, but the description documents both output (destination .json path with default) and overwrite (replace existing, default False), adding real meaning. The required filename param is left unexplained, keeping it from a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Export every slice as engine-agnostic JSON') and names the exact format schema (aseprite_mcp.slice_metadata.v1), which cleanly separates it from siblings like list_slices or export_spritesheet.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the described output format (engine-agnostic JSON for downstream consumption) but there is no explicit 'use this when / not when' or named alternative. The agent must infer when this beats list_slices or export_game_asset_bundle.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_spritesheetA
Destructive

Export frames into a single sprite-sheet image.

Args:
    output: Destination sheet image (.png).
    sheet_type: one of horizontal, vertical, rows, columns, packed.
    scale: Integer upscaling factor.
    data_output: Optional .json path to also write frame/tag/slice metadata
        (JSON-array format) describing each frame's rectangle in the sheet.
    padding: Pixels of padding around/between frames.
    layer: Only include this layer.
    ignore_layer: Exclude this layer (e.g. a "reference" layer).
    split_layers: Lay out each layer as separate cels in the sheet.
    split_tags: Treat each tag as a separate set in the sheet.
    overwrite: Replace existing output(s) (default False = no-clobber). When
        data_output is given, both files are checked before anything is written.
ParametersJSON Schema
NameRequiredDescriptionDefault
layerNo
scaleNoDefault: 1.
outputYes
paddingNoDefault: 0.
filenameYes
overwriteNoDefault: false.
sheet_typeNoDefault: "packed".packed
split_tagsNoDefault: false.
data_outputNo
ignore_layerNo
split_layersNoDefault: false.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the description carries less burden. It still adds real value beyond them: the no-clobber default (overwrite=False), and the guarantee that when data_output is given 'both files are checked before anything is written,' which is meaningful write-safety context not expressible in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose in one sentence, then organizes per-argument notes in a consistent docstring style. Essentially every line carries information; only a little verbosity in the overwrite/split entries, but nothing wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter, destructive export tool with no output schema, the description covers nearly all parameters plus the write-safety semantics. It could still note the return value (paths written) or interaction with split_layers/split_tags and data_output, but it is close to complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 55%, but the description compensates: it enumerates the valid sheet_type values (horizontal, vertical, rows, columns, packed) that the schema lacks as an enum, explains the data_output JSON-array format, and gives an example for ignore_layer. Only filename goes undocumented, a minor gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Export frames into a single sprite-sheet image.' That is clear and unambiguous. However, it never distinguishes this tool from close siblings like export_spritesheet_packed, export_frames, or export_png, so an agent cannot route between them on the description alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description is purely mechanical (what each arg does); it gives no when-to-use context, no prerequisites, and no mention of alternatives despite several overlapping export siblings. An agent gets no help deciding when this tool is the right choice versus export_spritesheet_packed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_spritesheet_packedA
Destructive

Export a sprite sheet with the controls a game engine needs: extrude, dedupe, trim.

The sibling of `export_spritesheet`, which goes through the Aseprite CLI. This one
drives the editor's own export command, which the CLI flags do not fully reach, and
adds three things that matter when the sheet is going into an engine rather than into
a preview:

Args:
    output: Destination sheet image (.png).
    sheet_type: one of horizontal, vertical, rows, columns, packed (the default).
    trim: Trim each frame to its drawn pixels before packing, so empty margins cost
        no sheet space. The frame rectangles in the data file say where each frame
        went and how much was trimmed, so an engine can still place it correctly.
    extrude: Duplicate each frame's edge pixels one pixel outwards around its cell.
        This is the fix for the thin seam or transparent line that appears between
        tiles in Unity, Godot or a shader at non-integer zoom: the sampler reads
        half a texel past the frame's edge, and without extrude that is whatever the
        neighbouring frame or empty space holds. The frame rectangle in the data file
        still names the frame itself, not the border.
    merge_duplicates: Give identical frames one rectangle in the sheet instead of a
        copy each, which is what shrinks a sheet full of held poses. Identical by
        pixels, so it catches both a duplicated frame and a linked cel. A packed
        sheet does this anyway and the result says so.
    padding: Pixels of padding around and between frames, as `export_spritesheet`.
        Padding separates frames; extrude fills the gap at the frame's own edge.
        They solve different halves of the same bleeding problem and compose.
    data_output: Optional .json path for the sheet metadata, which also carries the
        layer, tag and slice lists.
    data_format: "json-array" (the default when `data_output` is given) or
        "json-hash". The array form lists frames in order, which an engine indexing
        by frame number wants; the hash form keys them by name, which a loader
        looking frames up by name wants. The tag section is called `frameTags` in
        both.
    overwrite: Replace existing output(s) (default False = no-clobber). When
        `data_output` is given, both files are checked before anything is written.

The source sprite is not modified: verified, the file's bytes and frame count are the
same afterwards, including with trim and extrude set.
ParametersJSON Schema
NameRequiredDescriptionDefault
trimNoDefault: false.
outputYes
extrudeNoDefault: false.
paddingNoDefault: 0.
filenameYes
overwriteNoDefault: false.
sheet_typeNoDefault: "packed".packed
data_formatNo
data_outputNo
merge_duplicatesNoDefault: false.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, but the description directly addresses this: 'The source sprite is not modified: verified, the file's bytes and frame count are the same afterwards, including with trim and extrude set.' This casts the mutation as output-file-only, which is valuable context beyond annotations. It also explains overwrite's no-clobber default and that both files are checked before writing. Slight tension with destructiveHint is resolved rather than contradicted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and the sibling distinction in the first paragraph, which is good. But the argument section is very long and partly prose-essay (Unity sampler half-texel explanation), which is thorough yet heavy for a tool description. Earns its place mostly, but less economical than ideal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers a 10-parameter export tool with no output schema: what each control does, the default sheet_type, data_format behavior, no-clobber semantics, and even a non-modification guarantee. Return values aren't described, but metadata is captured via data_output. Nearly complete for the complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60%, so the description must carry the rest and largely does. It explains the meaning and purpose of trim, extrude, merge_duplicates, padding, data_output, data_format (including the json-array vs json-hash choice and frameTags), and overwrite. It even clarifies how padding and extrude compose. Only sheet_type enum values are fully enumerated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Export a sprite sheet') and immediately names its scope ('with the controls a game engine needs'). It explicitly distinguishes itself from the sibling export_spritesheet: 'The sibling of export_spritesheet, which goes through the Aseprite CLI. This one drives the editor's own export command, which the CLI flags do not fully reach.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (export_spritesheet) and the condition selecting this tool: it drives the editor's own export and reaches flags the CLI doesn't. Also frames the whole tool as for 'sheet going into an engine rather than into a preview,' an explicit use case boundary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_tag_gifB
Destructive

Export only the frames of a named animation tag as an animated GIF.

overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
scaleNoDefault: 1.
outputYes
filenameYes
overwriteNoDefault: false.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and readOnlyHint=false; the description usefully explains the no-clobber default and that overwrite replaces `output`, which accounts for the destructive trait. However, it omits what gets written on disk (paths, frame-duration handling) and any error behavior when a tag is missing, so it adds only moderate context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight stanzas, front-loaded with the core action before the overwrite note. No filler sentences, though the overwrite line is formatted as a stray note rather than integrated prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and a write operation, the description is adequate but thin: it never explains how scale affects output, where the file lands, or how multiple tagged frames become a GIF. It covers the essentials for a straightforward export but leaves meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 40% (just terse 'Default:' notes on scale and overwrite). The description meaningfully explains `overwrite` and references `output` and `tag`, but leaves `filename` and `scale` entirely undefined, so it only partly compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Export), resource (animation tag frames), and format (animated GIF), with the scope qualifier 'only the frames of a named animation tag' that separates it from generic export_gif/export_frames siblings. It never names a sibling explicitly, but the scoping does the disambiguation work.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use vs when-not guidance. Given the dense sibling cluster (export_gif, export_frames, export_tags, export_spritesheet), the description should say when tag-scoped GIF export is preferred over the alternatives, but it leaves that entirely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_tagsA
Destructive

Export each animation tag's frames to their own files.

output_pattern must contain "{tag}" (and usually "{frame}"),
e.g. "anim/{tag}_{frame}.png".

overwrite: Replace files the pattern would expand onto (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
scaleNoDefault: 1.
filenameYes
overwriteNoDefault: false.
output_patternYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false; the description usefully clarifies the actual behavior that drives that flag - overwrite replaces existing files and defaults to no-clobber. This adds real value beyond the annotation by explaining the clobber semantics rather than just flagging destructiveness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by two short, high-value constraint bullets (pattern tokens, overwrite semantics). No filler, though the formatting as loose lines is slightly ragged.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no output schema and only 50% parameter coverage, the description covers the two most important parameters but omits scale and filename entirely and never states the return value or whether the operation can be partially applied.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, with filename and output_pattern undescribed in the schema. The description compensates well for output_pattern by documenting the required "{tag}"/"{frame}" placeholders and for overwrite by giving its default behavior, but filename and scale remain unexplained in both places.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (export) and resource (each animation tag's frames) with clear scope: one file per frame per tag. It does not, however, distinguish itself from close siblings like export_frames, export_png, or export_tag_gif, which an agent must resolve on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by specifying that output_pattern must contain "{tag}" and usually "{frame}", which is actionable but framed as a constraint rather than a when-to-use rule. There is no guidance on when to pick this over export_frames or export_tag_gif, and no prerequisites named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

extract_paletteA

Extract the unique colours used in a sprite (or another image).

Args:
    from_image: Optional image/sprite to scan instead of `filename`.
    set_as_palette: Apply the extracted colours as `filename`'s palette.
    include_alpha: Treat differing alpha as distinct colours (default off).
    max_colors: Error out if more unique colours than this are found.

Returns the list of "#RRGGBBAA" colours found.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
from_imageNo
max_colorsNoDefault: 256.
include_alphaNoDefault: false.
set_as_paletteNoDefault: true.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, and the description corroborates this by explaining that set_as_palette (default true) writes the extracted colours into filename's palette — so the mutating behavior is disclosed rather than hidden. It also documents the error path for max_colors, though it says nothing about permissions or how a failure leaves the palette.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One framing sentence, a tight per-argument list, and a return-type line. It is front-loaded and every line earns its place, with only minor redundancy between the arg list and the schema defaults.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter tool with no output schema, the description covers the optional arguments, the mutation semantics, the error condition, and the return format ('#RRGGBBAA' list). Its one substantive gap is routing guidance against the cluster of palette siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 60% and the schema descriptions are boilerplate ('Default: 256.'), so the description does real work: it explains from_image as an override for filename, include_alpha as treating differing alpha as distinct colours, and max_colors as an error threshold. Only filename itself is left without explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Extract the unique colours used in a sprite (or another image)'. That is clear enough to identify the operation, but it never distinguishes itself from nearby siblings like get_palette, quantize_palette, or list_palette_usage, which an agent must sort out on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the from_image and set_as_palette arguments hint at the two modes (scan an external image vs. re-palette the target file), but there is no explicit when-to-use or when-not statement. No alternative tool is named despite get_palette/set_palette/quantize_palette sitting right beside it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_areaA

Flood fill (paint bucket): replace the contiguous region of matching colour starting at (x,y) on the target layer with color.

Coordinates: (0, 0) is the top-left pixel. x grows right, y grows DOWN. A span given as position plus size covers x .. x + width - 1, so width is a count of pixels, not an offset to the far edge.

Centring differs between primitives, so check this when aligning two shapes:

  • draw_rectangle(x, width) spans x .. x+width-1, centred on x + (width-1)/2. An even width therefore centres on a half pixel.

  • draw_ellipse(center, radius) spans center-radius .. center+radius, which is always an ODD 2*radius+1 pixels wide and always centred on a whole pixel.

  • draw_ellipse_in_box(x, y, width, height) takes the same bounding box as draw_rectangle and fills it exactly, so it is the one to use for an even diameter, a disc centred on an even canvas, or a circle that has to line up with a rectangle.

  • draw_symmetric_pixels mirrors about the canvas, not about either of the above.

Writes falling outside the canvas are dropped rather than raising. Every drawing tool reports pixels_written, and pixels_clipped when anything was dropped, so compare those against what you asked for rather than trusting ok.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
colorYes
frameNoDefault: 1.
layerNo
filenameYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the bare annotations (readOnlyHint false, openWorldHint false), it discloses that out-of-canvas writes are silently dropped and that results expose pixels_written/pixels_clipped, advising the agent to verify counts rather than trust 'ok'. That is meaningful behavioral context for a mutation tool with no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence is precise and front-loaded, but roughly two-thirds of the text is a digression into centring rules for draw_rectangle, draw_ellipse, draw_ellipse_in_box and draw_symmetric_pixels, which are largely irrelevant to a flood-fill start point and dilute the core instruction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with minimal annotations and no output schema, the description covers clipping behaviour and return fields well, but it omits the meaning of `frame`/`filename`, any failure modes beyond canvas clipping, and guidance on layer targeting versus the whole-canvas default.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17%, so the description must compensate, and it partially does: it defines the coordinate origin/direction for x and y and ties colour and 'target layer' to their roles. It says nothing about `frame` or `filename`, leaving two of six parameters undocumented in both places.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and mechanism: 'Flood fill (paint bucket): replace the contiguous region of matching colour starting at (x,y) on the target layer with color.' It names the exact semantics (contiguous, colour-matching, start point, target layer), which cleanly separates it from whole-layer operations like fill_layer and from the draw_* primitives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The flood-fill semantics imply when it applies, but the description never states when to choose it over siblings such as fill_layer, select_by_color, or draw_brush. The centring guidance mentions conditions for aligning shapes but does not route the agent between competing tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_checkerboardC

Fill a region with a 2-colour checkerboard of size-pixel squares.

ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
sizeNoDefault: 1.
frameNoDefault: 1.
layerNo
widthNo
color1Yes
color2Yes
heightNo
filenameYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the agent knows this mutates a closed-world resource. The description adds no further behavioral context: it does not say whether existing pixels are overwritten, how the region is bounded, whether a selection or layer is required, or what side effects occur.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no filler. It is efficient, though notably sparse for a 10-parameter tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 10 parameters, no output schema, and only minimal annotations, the description is too thin. It omits how the region is defined, which parameters are required, what layer or file is affected, and what happens to existing content.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 40%, with only default-value notes for x, y, size, and frame. The description only clarifies that `size` is in pixels; it does not explain the coordinate/region parameters, width, height, layer, filename, or color1/color2, so it does not compensate for the low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fill') and resource ('region') plus the distinguishing checkerboard pattern and square size. It does not explicitly differentiate itself from siblings like fill_area, fill_layer, or stamp_pattern, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides no guidance about when to use this tool instead of related fill or pattern tools such as fill_area, fill_layer, or stamp_pattern. It only describes the operation, leaving the agent to infer usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_gradientA

Fill a region with a gradient, by default only where pixels already exist.

Args:
    colors: 2+ colour stops, e.g. ["#000000", "#ff004d", "#ffec27"], spread
        evenly. For dither=True, provide exactly 2 colours.
    gradient_type: "linear" or "radial".
    angle: Direction in degrees for linear gradients (0 = left->right).
    dither: Ordered (Bayer 4x4) dithering between 2 colours instead of smooth
        interpolation, great for limited palettes / retro looks.
    x, y, width, height: Region (defaults to the whole canvas).
    respect_alpha: Leave transparent pixels transparent (default). The gradient
        then shades the artwork inside the region rather than filling the region.
        Pass False to paint the whole rectangle, background included.

Returns `pixels_written` and `pixels_skipped` so the caller can tell how much of
the region was actually covered.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
angleNoDefault: 0.0.
frameNoDefault: 1.
layerNo
widthNo
colorsYes
ditherNoDefault: false.
heightNo
filenameYes
gradient_typeNoDefault: "linear".linear
respect_alphaNoDefault: true.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description goes further by explaining that respect_alpha=True shades existing artwork while False paints the whole rectangle including background, and that the call reports pixels_written/pixels_skipped. It does not mention permissions or layer targeting limits across the 12 params.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line summary followed by a tight Args list where each entry adds distinct information; the closing sentence about return values is one line. Slightly long but essentially no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter mutation tool with no output schema and thin annotations, the description supplies the missing alpha/dither semantics and even explains the return payload, which compensates for the absent output schema. Only the frame/layer parameters are left unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 58% and most schema descriptions are bare 'Default: X', so the description carries real weight: it gives the colors array format with an example, the dither=exactly-2-colours constraint, angle's 0=left->right convention, and the region defaults. It leaves filename, frame, and layer undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fill a region with a gradient') and immediately narrows scope with 'by default only where pixels already exist.' An agent can distinguish this from solid fill_area or palette-gradient gradient_map by the region+gradient framing, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Offers contextual guidance for options ('dither ... great for limited palettes / retro looks') and explains the default alpha behavior, but never states when to prefer this tool over the many neighboring fill/gradient tools (fill_area, gradient_map, dither_band). Usage is implied rather than routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_layerB
Destructive

Fill the entire target layer/frame cel with a solid colour.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerNo
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=true, so the safety profile is covered. The description contributes the fact that the WHOLE layer/cel is overwritten with a single colour, which corroborates destructiveness, but says nothing about whether the file is saved, whether existing pixels are irrecoverably lost, or what is returned. Adequate but thin given the mutation/destructive nature.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with no filler, front-loading the verb and scope. Nothing to trim.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, 4 parameters at 25% description coverage, and many sibling fill/clear tools, the description is too spare. It omits save semantics, colour format, error cases, and any disambiguation from adjacent fill/clear operations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 25% and the description adds little: it signals that layer, frame, and color are involved but gives no colour format (hex? named? alpha?), no explanation of which cel on the layer/frame is targeted, and says nothing about the required filename parameter. Low coverage means the description should compensate more than it does.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description pairs a specific verb ("Fill") with a clear resource ("the entire target layer/frame cel") and the fill material ("solid colour"). It is distinguishable from fill_area (region) and fill_gradient/checkerboard, though it never names those siblings explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to choose this over fill_area, clear_layer, or fill_tile, nor any prerequisite (e.g., layer must exist, file must be loaded). Usage must be inferred from the word "entire".

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_tileB

Fill an existing tile's artwork with a solid colour.

Returns `pixels` (the tile's area, all of which is written) so the result says the fill
reached the tile rather than only that the call returned.
ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerYes
filenameYes
tile_indexYes

TDQS

B3.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is not a read-only operation and is not open-world. The description adds meaningful context by stating that all of the tile's area is written and that the return value reports the filled pixels rather than merely call success.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loads the purpose in the first sentence. The second sentence explains the return value and is useful, though slightly more verbose than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does provide some return-value context. However, for a five-parameter mutation tool with only 20% schema description coverage, it leaves most parameter semantics unexplained and is not complete enough for reliable invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 20%, with just the frame parameter documented. The description implies color is a solid colour and that tile_index identifies the existing tile, but it does not explain filename, layer, tile_index, or frame semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Fill an existing tile's artwork with a solid colour.' This distinguishes it from layer-level or tilemap-level fills, though it does not explicitly name the sibling tools it differs from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, no prerequisites, and no comparison to alternatives such as fill_layer, fill_tilemap, or paint_tile_pixels. It only implies that the tile must already exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fill_tilemapB

Fill the entire tilemap grid with a single tile index.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerYes
filenameYes
tile_indexYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the agent already knows this is a write operation. The description adds that it affects the entire tilemap grid, which usefully signals a bulk overwrite, but it does not disclose whether existing tiles are irreversibly replaced, what permissions are required, or how the optional frame parameter affects scope.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no redundant or filler content. It efficiently communicates the core bulk-fill action without repeating schema details or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter mutation tool with low schema description coverage and no output schema, the description is too thin. It does not explain what filename or layer identify, how frame behaves, or what happens to existing tile data, so an agent lacks enough context to invoke it safely and correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, and the description mentions only the concept of a single tile index, which maps weakly to the tile_index parameter. It provides no meaning for filename, layer, or frame, leaving three of four parameters semantically unexplained in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Fill') and resource ('entire tilemap grid') with the tile index constraint, so the core action is clear. However, it does not distinguish this operation from close siblings like fill_layer, fill_tile, set_tile, or set_tiles, leaving an agent to infer the difference from the name alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives such as fill_layer, fill_tile, set_tile, or set_tiles. The description implies a bulk fill operation but does not state prerequisites, exclusions, or selection criteria for the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

flatten_spriteB
Destructive

Flatten all layers into a single layer (in place).

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, and openWorldHint=false, so the mutation/safety profile is covered structurally. The description adds the useful '(in place)' detail meaning it overwrites the existing sprite rather than producing a new file, but it does not say what is lost (layer structure, groups, blend semantics) or whether the operation is undoable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the core action front-loaded and no filler. Nothing could be removed without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, no-output-schema mutation the description covers the basic effect and the in-place nature, and annotations carry the destructiveness flag. It remains thin on what the destination layer is, how groups/background layers are handled, and how the filename argument should be supplied.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is one parameter, filename, with 0% schema description coverage, and the description never mentions it. With coverage this low the description is expected to compensate, but it does not say whether filename is a path, a sprite name, or whether it must reference an already-open document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (flatten) and resource (all layers) plus the scope (in place), which is clearly distinct from a partial merge. It does not, however, name or contrast with the closest sibling, merge_layer_down, so the agent must infer the difference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use this versus merge_layer_down, convert_layer_to_background, or other layer-collapsing siblings, and no prerequisites are given. Usage is only implied by the tool name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

flip_spriteB

Flip the entire sprite. direction: "horizontal" or "vertical".

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
directionNoDefault: "horizontal".horizontal

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=false and openWorldHint=false, so the write nature is known. The description does not add behavioral context such as whether the change is saved automatically, whether the sprite file must exist, or whether the operation is reversible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with the core action and followed by the key parameter constraint. It is appropriately sized and contains no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation tool with no output schema, the description covers the operation and direction values. It omits file-handling details such as whether the filename refers to an existing sprite or how the result is persisted, which leaves relevant context gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50%. The description supplies the allowed direction values ('horizontal' or 'vertical'), which the schema only partially indicates through a default. The required filename parameter is not described in either place, so the description only partially compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb (Flip) and resource (entire sprite), and the direction parameter indicates the operation's axis. It does not explicitly distinguish itself from similarly named siblings such as mirror_layer or rotate_sprite, so it falls short of the top score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus alternatives like rotate_sprite or mirror_layer. The implied usage is obvious but not stated explicitly, leaving the agent to infer context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_rampA

Generate a shading ramp from a base colour (dark -> light).

Produces `steps` colours by varying lightness across `light_range`, optionally
rotating hue by `hue_shift` total degrees across the ramp (classic pixel-art
hue shifting: cool shadows / warm highlights) and scaling saturation by
`saturation_shift` percent across the ramp.

Args:
    filename: If set with apply, write the ramp into that sprite's palette.
    apply: "none" (just return), "append" (add to palette), or "replace".

Returns the ramp as a list of "#RRGGBB" colours (darkest first), with `distinct`, how
many of them are different from each other.

**`distinct` is not always `steps`.** Lightness is clamped at both ends, so a base
already near white or near black spends its outermost steps on the same colour: nine
steps in, eight colours out. The ramp is still returned, because clamping is the honest
result of the inputs and a caller may not care, but `warnings` then names which end
collapsed and the nearest `light_range` that would not.

It is worth caring about at least once. `specular_highlight` needs the ramp's top step
to be brighter than what `shade_region_by_light` spread across the lit side, so a ramp
whose top two entries are both `#ffffff` makes that call refuse, with a message about
the shading pass. The cause is two calls earlier, in this one, which used to report
success either way.
ParametersJSON Schema
NameRequiredDescriptionDefault
applyNoDefault: "none".none
stepsNoDefault: 5.
easingNoDefault: "linear".linear
filenameNo
hue_shiftNoDefault: 0.0.
light_hueNo
sat_curveNoDefault: "linear".linear
base_colorYes
shadow_hueNo
light_rangeNoDefault: 0.6.
saturation_shiftNoDefault: 0.0.

TDQS

A3.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only readOnlyHint=false and openWorldHint=false available, the description carries the full burden and does so well: it discloses that apply mutates a sprite palette, that lightness clamping can make distinct < steps, that warnings name the collapsed end plus a corrective light_range, and that a degenerate top step makes specular_highlight refuse downstream. That is exactly the non-obvious behavior an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose and Args block are fine, but the final three paragraphs are discursive and repeat the distinct/steps point multiple times ('It is worth caring about at least once...'). The Args section also partly restates schema fields. Informative, but not tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description correctly documents the return value (list of '#RRGGBB', darkest first) plus distinct and warnings. For an 11-parameter mutating tool this is nearly sufficient, with the main gap being the unexplained easing, sat_curve, light_hue, and shadow_hue parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 64% and the schema's own parameter descriptions are near-useless (mostly just restated defaults). The prose compensates by explaining steps, light_range, hue_shift, saturation_shift, base_color, apply, and filename semantics — 7 of 11. easing, sat_curve, light_hue, and shadow_hue remain undocumented in both places, keeping it short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Generate a shading ramp from a base colour (dark -> light).' An agent immediately knows the operation and the direction convention. It does not, however, distinguish itself from close siblings like ramp_between, ramp_from_art, or shift_along_ramp, so sibling selection still requires inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clarifies the three apply modes (none/append/replace) and filename pairing, and gives a strong downstream caveat about when to care about collapsed ramps feeding specular_highlight. But it never states when to choose this tool over ramp_between or ramp_from_art, so alternative-routing guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_celA
Read-only

Inspect a cel: whether it exists, its position, bounds, opacity, and links.

`linked_with` lists the other frames sharing this cel's image, so a held pose is
visible as what it is. An edit to any of them changes all of them.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerYes
filenameYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds valuable behavioral context: it lists the returned properties and explains that linked_with reveals shared-image cels, where editing any one changes all of them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loaded, and free of filler. Every sentence adds useful information, and the linked-cel caveat is placed immediately after the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description adequately covers the read-only inspection purpose and return properties, and it explains the important linked_with semantics. However, with no output schema and only 33% schema parameter coverage, it should do more to explain the filename, layer, and frame parameters needed to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33%, with filename and layer required but undocumented. The description does not explain filename, layer, or frame, so it fails to compensate for the low schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb (Inspect) and resource (a cel), then enumerates what is returned: existence, position, bounds, opacity, and links. This clearly distinguishes get_cel from mutation siblings such as set_cel_position, set_cel_opacity, and delete_cel.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by naming the inspection operation and explaining linked cels, but it does not explicitly say when to use get_cel versus alternatives like get_pixels, get_sprite_info, or list_sprites. No when-not conditions are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_paletteB
Read-only

Return the sprite's palette as a list of "#RRGGBBAA" colours.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds the output format (list of '#RRGGBBAA' colors), which is useful behavioral context, but does not mention ordering, empty palettes, error cases, or other operational details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no wasted words. It states the action, the resource, and the return format efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one parameter and no output schema, the description adequately states what is returned. However, it leaves the sole parameter undocumented and provides no usage context relative to the many sibling palette tools, so an agent still lacks important operationally relevant details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single parameter 'filename' is not explained at all in the description. The phrase 'the sprite's palette' hints that filename identifies a sprite, but no format, path, or naming convention is provided to compensate for the missing schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb ('Return') and resource ('the sprite's palette'), and specifies the return format as a list of '#RRGGBBAA' colors. This clearly distinguishes it from sibling palette-mutation tools like set_palette or add_palette_color.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance about when to use this tool versus alternatives (e.g., list_palette_usage, extract_palette, set_palette). Usage is only inferred from the tool name and description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pixelsA
Read-only

Read the pixel colours of a region.

Args:
    layer: Read this layer alone instead of the composite. This matters more than
        it sounds: drawing tools write to ONE layer, so the composite is not the
        surface your next edit will act on. A fill whose boundary is drawn on a
        different layer will flood the whole canvas while the composite looks as
        though it should have stopped.
    format: "rows" (default) gives rows of "#RRGGBBAA" strings. "map" gives a
        `legend` of symbol to colour plus one string per row, which is around a
        tenth the size: a 16x16 icon of three colours costs roughly 3,400
        characters as rows and 350 as a map, and defects like a one-pixel offset
        are visible in it at a glance.

The region is capped at 64x64 (4096 pixels) per call to keep responses small, so
read in tiles for bigger areas.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
frameNoDefault: 1.
layerNo
widthNo
formatNoDefault: "rows".rows
heightNo
filenameYes

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=true and openWorldHint=false; the description adds the hard 64x64/4096-pixel cap, the composite-vs-layer behavioral trap, and the output-format size tradeoff. These are non-obvious behavioral traits beyond what the structured fields declare.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with a one-line purpose, then focused arg guidance; the length is largely justified by the layer and format explanations. The layer passage is slightly discursive, keeping it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-param read tool with no output schema and minimal annotations, it explains the output shapes (rows vs map) and the region cap, which is what an agent most needs. It omits any mention of 'frame' semantics, which is a minor but real gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, and the description compensates well for the two semantically tricky params (layer, format) with usage meaning and concrete size examples. It leaves 'frame', x/y, and width/height entirely to the bare schema defaults, so it does not fully close the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read the pixel colours of a region'), which is enough for an agent to distinguish it from get_palette, get_cel, or get_sprite_info at a glance. It does not explicitly name or contrast a sibling, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives real decision guidance for two parameters: when to pass 'layer' (because drawing tools write to one layer, so the composite misleads edits) and when to choose 'format: map' (size and defect visibility). It also tells the agent to tile for regions over 64x64. No explicit when-not or alternative-tool routing, so not a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_propertiesA
Read-only

Read the custom properties stored on one object inside the sprite.

The counterpart to `set_properties`, and the only way to read that metadata back:
neither `get_sprite_info` nor the sprite-sheet export reports custom properties.

Args:
    target, layer, frame, name, tile: Which object, exactly as `set_properties`
        takes them.
    namespace: Read a named group instead of the unnamed one. Aseprite offers no way
        to list the namespaces an object has, so a group can only be read by a caller
        who knows its name; an unknown name reads as empty rather than as an error.

Returns `properties` as an object of key to value, each value in the type it was
stored as. A value of a type JSON cannot describe (the editor can store a point or a
rectangle) is reported as text rather than dropped.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
tileNo
frameNo
layerNo
targetYes
filenameYes
namespaceNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations give readOnlyHint=true and openWorldHint=false, so safety is covered. The description goes further with non-obvious edge cases: an unknown namespace reads as empty rather than erroring, and values of types JSON cannot describe (point, rectangle) are returned as text rather than dropped. It does not cover failure behavior for a bad filename/target, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose, then uses an Args block and a Returns sentence with no filler. Each part earns its place, though the 'counterpart to set_properties' framing repeats the scope point already made in sentence one.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly supplies the return shape (key-to-value object, types preserved, unrepresentable types as text) and discloses the namespace-enumeration limitation. Only the required filename parameter and error conditions remain unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 7 params, so the description must carry the load, and it does: target/layer/frame/name/tile are grouped as the object locator, and namespace gets a full explanation of its grouping semantics and failure mode. The required 'filename' parameter is never explained, and it defers locator semantics to set_properties, so it falls short of full compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope ('custom properties stored on one object inside the sprite') and distinguishes itself from siblings by naming both its counterpart set_properties and the tools that do NOT surface this data (get_sprite_info, sprite-sheet export). An agent can identify it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames itself as the counterpart to set_properties and the only way to read that metadata back, and warns that namespaces cannot be enumerated, so a group can only be read by a caller who already knows its name. That is exactly the when/when-not guidance needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_selectionA
Read-only

Describe the current selection: whether there is one, and what it covers.

Returns `bounds`, the pixel `area` actually inside the selection, and a `map` of
the selected region using `#` for selected and `.` for not, in the same shape
`get_pixels(format="map")` uses. The map is capped, and omitted for a selection
larger than the cap, since a wall of characters is not feedback.

Worth calling before a large edit: a selection you forgot about is the difference
between changing what you meant and changing a corner of it.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and closed-world, so safety is covered. The description adds real behavioral value beyond that by disclosing the returned fields (bounds, area, map), the map character encoding, and the caps/omission behavior for large selections.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose followed by return details and a rationale. Generally efficient, though the final motivational sentence is slightly padded rather than strictly informational.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full burden of explaining returns and does so thoroughly, including the map format and its cap behavior. For a simple single-parameter read tool, nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description never mentions the sole 'filename' parameter, though its meaning is largely self-evident. The baseline 3 applies since the description adds no parameter semantics the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (describe) and resource (the current selection), and clarifies scope as 'whether there is one, and what it covers'. This clearly distinguishes it from siblings like modify_selection, invert_selection, and deselect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a concrete usage trigger: 'Worth calling before a large edit'. It explains why it matters but does not explicitly name or exclude alternatives (e.g., contrast with modify_selection or get_pixels), so it stays short of full 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.

get_sprite_infoB
Read-only

Return structured info about a sprite: size, colour mode, frames (with durations), the full layer tree (names, opacity, blend mode, visibility), animation tags, and palette size.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only, local safety profile is covered. The description adds useful context about the breadth of returned data (e.g. 'the full layer tree'), but says nothing about error behavior, missing files, or performance. With annotations carrying the safety profile, 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence that opens with the action and then lists returned fields with no filler or repetition. Every clause earns its place by describing the output shape.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the burden of describing returns, and it does so thoroughly with an explicit field list. Read-only annotations cover safety and the lone parameter is obvious, leaving only usage guidance as the notable gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'filename' has 0% schema description coverage, and the description never mentions it or clarifies whether it is a path, bare name, or extension. The parameter name is self-evident, but the description contributes no additional meaning to compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Return structured info about a sprite') and enumerates the exact fields returned (size, colour mode, frames, layer tree, tags, palette size), so the agent knows precisely what this produces. It does not, however, differentiate itself from related inspection siblings such as get_pixels, get_properties, or assess_sprite.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no indication of when to use this tool versus get_pixels, get_properties, get_cel, or assess_sprite, and no prerequisites or exclusions. Usage is only weakly implied by the fact that it returns metadata rather than pixel data.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_tilemapB
Read-only

Read the tilemap as a 2D grid of tile indices, plus tile size and count.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerYes
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful context that the return is a 2D grid of tile indices plus tile size and count, but it says nothing about the layer/frame scoping behavior or error cases for a missing layer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no wasted words. It is well-sized, though it spends its payload on the return shape rather than the arguments the caller must supply.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool whose annotations carry the safety profile, the description is adequate on the output side but thin on the input side: two required parameters (filename, layer) are unexplained and there is no output schema to fall back on. It leaves a meaningful gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33%: filename and layer — both required — have no descriptions, and only frame ('Default: 1') is documented. The description adds no meaning for any parameter, so it fails to compensate for the undocumented required inputs. An agent cannot tell what a valid 'layer' value is.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (read) and resource (tilemap), and even describes the shape of the result: a 2D grid of tile indices plus tile size and count. It is clearly a read operation, distinguishing it implicitly from write-oriented siblings like set_tile or fill_tilemap, though it never names an alternative explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance is given. The description does not state when an agent should call get_tilemap versus related tools (get_pixels, get_cel, list_slices) or what prerequisites apply. Usage is only implied by the word 'read'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

glowA

Halo a shape in rings of ramp steps, so it glows without leaving the palette.

`add_outline` gives one flat ring, which reads as a sticker. A glow is several rings,
each a step further down a ramp: hottest against the artwork, fading outward, with the
outer ring optionally dithered so it ends in something softer than a hard edge.

The ramp is what makes this different from a glow in an image editor. A halo made of
alpha, or of colours interpolated between two others, takes the art off its palette,
and then `palette_conformance` drops and the sprite no longer exports to an indexed
format, reuses a tileset, or matches the sprite beside it. Every pixel this writes is
exactly one of the colours you passed in.

The glow goes on its own layer below the artwork, so the subject's cel is untouched
and deleting one layer removes the effect.

Args:
    ramp: Colours darkest first. Ring 1, touching the artwork, takes the top step and
        the outermost ring takes `ramp[0]`, so a longer ramp fades more finely. For a
        glow that reads as light rather than as a coloured border this usually wants
        its own bright ramp (a gem's or a flame's), not the subject's body ramp.
    radius: How many rings, in pixels. 2 or 3 reads as a glow; much more reads as fog.
    falloff: "linear" spaces the steps evenly. "quadratic" drops away faster, keeping
        a hotter core and a dimmer skirt, which is the one that reads as a light
        source rather than as an outline.
    dither_edge: Dither the outermost ring, so the glow ends in a half-density
        scatter instead of a hard line. This is binary coverage, a pixel either drawn
        or not, rather than a partial alpha, so every drawn pixel is still exactly a
        ramp step and conformance stays at 1.0.
    base_color: Glow only around pixels near this colour, which is how a gem glows
        while the hand holding it does not. Distance is measured out from those
        pixels, but the glow is never painted over any part of the subject layer, so
        a body blocks the halo of a gem inside it.
    tolerance: How close a pixel must be to `base_color` to be treated as a source,
        as a weighted RGB distance. Ignored when `base_color` is omitted.
    new_layer: Name for the glow's own layer, created directly below `layer`, or
        reused when a previous call of this tool made it and `frame` has no cel on it
        yet. That is how one glow layer carries a flickering torch across four frames
        rather than needing four layers with one cel each. A second call for the same
        layer *and* frame is refused, because two halos composited into one cel are a
        picture neither call describes, and so is a layer of that name this tool did
        not create.
    layer: The layer to glow around (default: top layer). Its cel is never modified.
    frame: Target frame, 1-based.

Refuses rather than drawing nothing: no pixel matching `base_color` is an error, and
so is a subject that leaves the glow nowhere to go.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampYes
frameNoDefault: 1.
layerNo
radiusNoDefault: 3.
falloffNoDefault: "linear".linear
filenameYes
new_layerNoDefault: "glow".glow
toleranceNoDefault: 24.0.
base_colorNo
dither_edgeNoDefault: true.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare only readOnlyHint=false and openWorldHint=false, so the description carries the rest and delivers: it writes to a new layer below the artwork, the subject cel is untouched, deleting one layer removes the effect, palette conformance stays at 1.0, layer reuse across frames is allowed but a duplicate layer+frame call is refused, and specific refusal conditions are enumerated. This is unusually rich behavioral disclosure for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with a one-sentence summary followed by rationale and a dense but well-organized Args section; nearly every sentence carries non-redundant information. It is long for a tool description, but the length is largely earned by the ten parameters and the refusal semantics, with only mild room for trimming in the palette-conformance rationale paragraph.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter mutation tool with no output schema and only two annotation hints, the description covers layer side effects, error/refusal behavior, cross-frame reuse, and palette guarantees. Nothing an agent needs to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% and the schema only supplies defaults, yet the description adds genuine meaning for every parameter: ramp ordering and why a separate bright ramp is wanted, radius-as-ring-count, the two falloff modes, dither_edge's binary-coverage semantics, base_color's distance measurement and subject-layer blocking, tolerance's weighted RGB distance and its interaction with base_color, and new_layer's reuse rule. The enum-less falloff string is disambiguated purely by prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line states a specific verb+resource ('halo a shape in rings of ramp steps') and immediately distinguishes the tool from its closest sibling by contrasting with `add_outline`'s single flat ring. An agent can tell this apart from add_outline, add_drop_shadow, and cast_shadow without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative (`add_outline`) and the condition that separates them, plus contrasts with image-editor glow techniques and explains when falloff='quadratic' vs 'linear' is appropriate and what radius values read as glow vs fog. The when-not case (image-editor alpha interpolation) is also stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gradient_mapA

Put every pixel on a ramp by its brightness, whatever it started as.

The other shading tools all begin with art that is *already* on a ramp:
`shift_along_ramp` moves pixels between steps they already belong to, and
`shade_region_by_light` shades a flat region painted in one of the ramp's colours.
This is the one that brings art onto a ramp in the first place, which is what an
imported image, a photo traced over, or a gradient fill actually needs.

Each pixel's luminance decides its step: darkest to `ramp[0]`, lightest to the last
entry, the rest in between. Afterwards the art uses the ramp's colours and nothing
else, so `assess_sprite(..., ramp=...)` reports a palette conformance of 1.0.

Args:
    ramp: The ramp, darkest first. Order is the mapping, so a reversed ramp inverts
        the image.
    contrast: Stretch the mapping around mid-grey. Above 1.0 pushes pixels toward
        the ends of the ramp and drops the middle steps; below 1.0 crowds everything
        into the middle. The interesting control is not which colours are used but
        how much of the art each step takes.
    bias: Shift the whole mapping after contrast, from -1.0 to 1.0. Positive is
        lighter. Use it when an image maps too dark to read.
    dither: "bayer4", "bayer2" or "checker" to break the bands. A pixel landing
        between two steps takes the darker or the lighter one by an ordered pattern,
        which reads as a gradient without adding a colour.
    x, y, width, height: Restrict the change to a region.

Luminance is weighted 0.299/0.587/0.114, the same weighting the ramp matching uses,
so a saturated red and a dull red of the same weight land on the same step. Alpha is
carried through untouched, so the silhouette does not move and anti-aliased edges
keep their coverage, even though their colour is now a ramp entry.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
biasNoDefault: 0.0.
rampYes
frameNoDefault: 1.
layerNo
widthNo
ditherNo
heightNo
contrastNoDefault: 1.0.
filenameYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description goes far beyond by disclosing the luminance weighting (0.299/0.587/0.114), that alpha is preserved so silhouettes and anti-aliasing are unaffected, that the result yields palette conformance of 1.0, and exactly how contrast/bias/dither manipulate the mapping.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the sibling differentiation, then structured into a clear Args block plus a behavior note. Some stylistic prose ('The interesting control is not which colours are used...') is slightly verbose, but almost every sentence carries usable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter mutation tool with no output schema, the description is unusually complete on the mapping, region, and alpha behavior. The gaps are the unaddressed frame/layer targeting and return-value expectations, but nothing critical for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 45% and the schema descriptions are bare defaults, so the prose carries real weight: it explains ramp ordering and reversal, contrast's effect on step distribution, bias direction, dither modes (bayer4/bayer2/checker), and region restriction for x/y/width/height. It leaves frame, layer, and filename unexplained, which keeps it from a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (map every pixel onto a ramp by luminance) and explicitly distinguishes itself from shift_along_ramp and shade_region_by_light, explaining that those assume art already on a ramp while this one brings art onto a ramp. An agent can pick it out of the sibling list without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete when-to-use cases (imported image, traced photo, gradient fill) and names the alternative tools with the condition that selects them. This is essentially explicit routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gui_availableA
Read-only

Check whether the Aseprite GUI can be launched (executable resolvable).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish this is a read-only, closed-world probe, so the safety profile is covered. The description adds real value by clarifying that 'available' means the executable is resolvable, but it does not say what the tool returns (boolean? status string?) or what the agent should do when it reports unavailable. With no output schema, that gap matters.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with the parenthetical clarifying the criterion. Every word earns its place, and the key information leads.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a trivial no-argument probe, the description is nearly sufficient: it defines the condition being tested. The only shortfall is the absence of any return-value information, which is not covered by an output schema, so an agent cannot know the result shape in advance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-parameter tool is 4. Nothing in the text misrepresents the input contract.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (check) and a specific subject (whether the Aseprite GUI can be launched), and even defines the check as 'executable resolvable', which removes ambiguity about what 'available' means. It does not differentiate itself from the sibling health_check tool, which is the main gap keeping it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to call this versus alternatives — notably the sibling health_check, which sounds like an overlapping diagnostic. The pre-flight use case is only implied by the word 'check'. No exclusions or prerequisites are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

health_checkA
Read-only

Run a self-test of the server and its Aseprite integration.

Returns whether Aseprite was found, its version, the workspace, the number of
registered tools, and whether a real create-sprite plus export-PNG round-trip
succeeds. `ok` is True only if the round-trip works and the workspace is usable.

`workspace` is the **resolved** path, which is where files land and what every other
tool reports, because paths are canonicalised before the containment check that keeps
them inside the workspace. When the configured value spells the same directory
differently, which is what a junction or a symlink does, it is reported alongside as
`workspace_configured` with a note; the two are one place, not two.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description goes further and discloses the return payload (Aseprite found, version, workspace, tool count, round-trip result) and defines the semantics of `ok` — that it is true only when both the round-trip and workspace usability hold. It also explains the workspace canonicalisation behavior. It stops short of saying whether the self-test is cheap or slow.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then the return breakdown, then the workspace nuance — a sensible order. The final sentence ('the two are one place, not two') restates what the preceding clause already conveyed about workspace vs workspace_configured, adding mild redundancy, but the overall size is defensible given no output schema exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no input parameters and no output schema, the description carries the full burden of describing the return payload, and it does so — fields, the `ok` condition, and the workspace/workspace_configured relationship. Nothing an agent needs to interpret a health_check result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so per the rubric the baseline is 4. No parameter explanation is needed or given, which is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Run a self-test of the server and its Aseprite integration.' It is immediately distinguishable from roughly 90 sibling tools, including the superficially related gui_available, because it is framed as a server-level diagnostic rather than an editor capability probe.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The diagnostic intent implies when to call it (before/after operations to verify the integration is live), but there is no explicit statement of when to use this versus alternatives such as gui_available, nor any mention of cost or side effects of the self-test. Usage is inferable but not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_imageA
Destructive

Create an editable .aseprite sprite from a flat image (.png/.bmp/.jpg/...).

Args:
    input_image: Source raster image.
    output: Destination .aseprite path.
    overwrite: Replace `output` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
outputYes
overwriteNoDefault: false.
input_imageYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations flag destructiveHint=true and readOnlyHint=false, and the description usefully qualifies that this destruction only occurs when overwrite is true, since the default is no-clobber. That is real added value beyond the flat annotation, though it never says what happens on a no-clobber collision (error vs. skip) or what is returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded purpose sentence plus a tight three-line args block; nothing is padded and the most important constraint (output must be .aseprite) appears first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity 3-parameter file-conversion tool with no output schema, the description covers the purpose, both required inputs, formats, and overwrite semantics. The only gap is undefined error behavior when output already exists and overwrite is false, plus no hint about what the call returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (just 'Default: false.' on overwrite), so the description must compensate, and it does: it defines input_image as the source raster, output as the destination .aseprite path, and overwrite as the replace-existing flag with its default. The .aseprite constraint on output is information the schema does not carry.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create an editable .aseprite sprite from a flat image') and enumerates accepted source formats, so the conversion direction is unambiguous and distinguishable from create_sprite or import_reference_sequence. It stops short of naming a sibling tool explicitly, which keeps it out of the top band.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use statement, nor any named alternative among the many sprite/import siblings. Usage is only implied by the accepted file formats and the no-clobber note, which is the level the rubric defines as 'implied usage'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_reference_sequenceA

Import a sequence of images as per-frame references for rotoscoping.

Each image is placed on its own frame in a single dimmed, locked layer
(frames are created as needed, so `start_frame` may sit past the end). Draw your
animation on a layer above, then exclude this layer at export with
ignore_layer="<layer_name>".
ParametersJSON Schema
NameRequiredDescriptionDefault
imagesYes
opacityNoDefault: 128.
filenameYes
layer_nameNoDefault: "rotoscope".rotoscope
start_frameNoDefault: 1.
scale_to_fitNoDefault: false.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already disclose readOnlyHint=false (a mutation), and the description adds substantial side-effect context: each image goes on its own frame in a single dimmed, locked layer, frames are created as needed, and start_frame may extend past the current end. It does not cover error behavior or layer-name conflicts, but it is well beyond the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, then adds just enough behavioral and workflow detail in three compact sentences. Every sentence earns its place, and the backtick usage aids scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter mutation tool with no output schema, the description covers purpose, side effects, and pipeline integration well. However, it omits required-parameter semantics for images and filename and does not describe the return value, leaving meaningful gaps for an agent invoking it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, but descriptions mostly repeat defaults. The tool description adds meaning for start_frame (frames are created as needed) and layer_name (usable for export exclusion), yet it leaves required parameters images and filename undocumented, and does not clarify opacity or scale_to_fit beyond their schema defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Import a sequence of images') and scopes it to per-frame references for rotoscoping. It implicitly distinguishes from single-image siblings like import_image, but never names an alternative tool explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the rotoscoping use case and outlines a workflow (draw animation above, exclude at export), which implies when to use it. However, it does not name or contrast alternatives such as import_image or add_reference_layer, nor does it state when not to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

invert_colorsB

Invert the RGB colours of a layer's pixels (alpha preserved).

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
filenameYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the safety profile is thin. The description usefully discloses that only RGB is inverted while alpha is preserved, which is real behavioral information, but it does not say whether the change applies to a single layer or all layers, whether it is reversible, or how it interacts with an active selection.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with the operation front-loaded and the alpha-preservation caveat parenthetically placed. Zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description should carry more weight. For a mutation tool with an optional layer parameter, it fails to explain the effect's scope (single layer vs. whole sprite), whether the operation can be undone, or how it differs from related color tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (frame has a trivial 'Default: 1.' note, while layer and filename are undocumented). The description gestures at the layer concept with 'a layer's pixels' but never explains what happens when layer is omitted, which is a meaningful ambiguity given only filename is required.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Invert the RGB colours of a layer's pixels') and adds the scope detail that alpha is preserved. It is clearly distinguishable from the neighboring invert_selection, though the description never names that sibling to close the loop.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no exclusions, and no alternatives are offered. With siblings like adjust_hue_saturation, desaturate, and invert_selection, the agent gets no help deciding when color inversion is the right operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

invert_selectionB

Swap what is selected for what is not.

Selecting a character's silhouette and inverting gives the background, which is usually easier than describing the background directly.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, indicating a local state-changing operation. The description restates the action but adds no further behavioral details such as prerequisites (e.g., must have an active selection) or side effects, so it adds limited value beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the core action and followed by a brief rationale. Every sentence earns its place with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple selection-inversion tool with no output schema, the description covers the action and a use case. However, it omits any explanation of the required 'filename' parameter and does not state whether an existing selection is a prerequisite, leaving gaps for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description makes no mention of the sole 'filename' parameter. It does not clarify what the filename refers to (e.g., the sprite file) or that it is required, leaving the parameter entirely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Swap what is selected for what is not.' This clearly conveys the action of inverting a selection. It does not explicitly differentiate from siblings like modify_selection or deselect, but the action itself is distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence provides a concrete use case: 'Selecting a character's silhouette and inverting gives the background, which is usually easier than describing the background directly.' This gives clear context for when to use the tool, though it does not name alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_palette_usageA
Read-only

Which palette indices the art is drawn with, how many pixels each covers, and which runs of them are worth cycling.

Indexed sprites only: an RGB or grayscale pixel carries its own colour rather than an
offset into a palette, so there is no index to count. `extract_palette` lists the
colours such a sprite uses and `assess_sprite` counts them.

The answer `cycle_palette` needs and the answer `get_palette` cannot give. A palette
says what colours exist; this says which of them the picture actually uses, so a
256-entry palette on a sprite painted in nine colours stops being a wall of hex. The
only way to work this out before was to read every pixel through `get_pixels` and
count them by hand.

Args:
    frame: Count only this frame. Default: every frame.
    layer: Count only this layer. Default: every pixel layer, groups walked through.
        Tilemap layers are skipped, because the numbers in their cels are tile
        references rather than palette offsets.

Returns `used` (index, colour and pixel count, most pixels first), `unused`, `runs`
(the contiguous spans of used indices, longest first, which is what a cycle rotates),
the transparent index and how many pixels sit on it, and `out_of_range`: pixels
carrying an index past the end of the palette, which is what a palette resized
smaller than its art leaves behind and which no colour can be read for at all.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNo
layerNo
filenameYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint/openWorldHint annotations, the description discloses real behavior: tilemap layers are skipped because their cels hold tile references, defaults apply to frame and layer, and out-of-range indices are reported because no colour can be read for them. That is substantive operational context an agent could not infer from 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and the Args/Returns structure is easy to scan, but the rhetorical asides ('stops being a wall of hex', 'count them by hand') add length without adding selection value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by enumerating every returned field (used, unused, runs, transparent index and its pixel count, out_of_range) with ordering semantics. Nothing needed to call or interpret the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the parameter burden and does: frame and layer both get default behavior (every frame, every pixel layer with groups walked through) plus the tilemap-skip rule. filename is left undocumented, but its meaning as the target sprite is self-evident from context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names the exact resource and the three outputs (used indices, pixel counts, cycleable runs) in a specific verb+resource form. It is immediately distinguishable from get_palette, extract_palette and get_pixels, each of which is named and contrasted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly scopes the tool to indexed sprites and tells the agent what to use instead for RGB/grayscale art (extract_palette for colours, assess_sprite for counts). It also frames itself against get_palette and get_pixels, so the when/when-not decision is fully specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_slicesA
Read-only

List every slice with its bounds, center, pivot, colour and user-data.

User-data comes back two ways, because it is one string that is sometimes a document.
`data` is the string exactly as Aseprite stores it, so it round-trips through
`set_slice` unchanged. `data_parsed` is added only when that string is valid JSON,
which is the shape worth sending: `{"type": "hitbox", "id": "body"}` is what
`export_slice_metadata` reads a slice's type and id from, and what
`build_asset_from_spec` writes. A slice with no user-data has neither field, so "set
and forgot" and "never set" are now distinguishable, which they were not while this
tool reported the same thing for both.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint, so the description carries the return-shape burden and does so well: it explains that `data` is the raw stored string, that `data_parsed` is conditionally present only for valid JSON, and that a slice with no user-data has neither field. This 'set and forgot vs never set' distinction is real behavioral context an agent cannot get from the annotations or schema, though ordering/other field formats remain undisclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the one-line purpose before any elaboration, and the JSON example earns its place by making the expected payload concrete. The closing clause about prior behavior ('which they were not while this tool reported the same thing for both') is mildly editorial and could be trimmed, but the overall length is justified by the subtle return semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotation detail, the description must explain the return value, and it thoroughly covers the hardest part (the two forms of user-data and their conditional presence). It stops short of describing the format of the other returned fields (bounds, center, pivot, colour) or any ordering/pagination, which leaves a small but real gap for a list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter is a bare `filename: string` with 0% schema description coverage, and the description adds nothing about it (e.g. whether it is a path, an open sprite, or a project-relative name). The parameter is trivially inferable from sibling conventions, so this is adequate but leaves a real gap given the description otherwise has room to say more.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb ('List'), an explicit scope ('every slice'), and enumerates the returned fields (bounds, center, pivot, colour, user-data). This is unmistakably distinct from siblings such as list_sprites or get_sprite_info, and it names the companion tools (set_slice, export_slice_metadata, build_asset_from_spec) that consume the data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by explaining that `data` round-trips through `set_slice` and that `data_parsed` is 'the shape worth sending' to `export_slice_metadata`/`build_asset_from_spec', which hints at inspecting slices before exporting. However, it never states an explicit when-to-use or when-not-to-use rule, nor does it point to an alternative inspection tool, so the guidance remains inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_spritesA
Read-only

List sprite/image files in the workspace directory.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered and the bar is lower. The description adds the useful scoping detail that results come from the workspace directory, but says nothing about what is returned (names vs. paths) or whether results are recursive or filtered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler, preamble, or redundancy. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list with no parameters, the description is nearly sufficient, but since there is no output schema it omits what the listing actually contains (filenames, paths, extensions) and whether the scan is recursive. That gap keeps it at minimum-viable rather than complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters and schema coverage is 100%, so there is nothing for the description to disambiguate. A 4 is the baseline for a parameterless tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

It states a specific verb (List) and resource (sprite/image files) plus a scope (workspace directory), so the agent knows this is a filesystem enumeration of sprites rather than a sprite-object query like get_sprite_info. It does not explicitly contrast itself with sibling listing tools (e.g., list_slices, list_palette_usage), so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the agent can infer it should call this to discover what sprite files exist before operating on them. There is no explicit when-to-use, no exclusion, and no named alternative such as get_sprite_info for metadata on a known sprite.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

load_paletteC
Destructive

Load a palette from a file (.gpl, .pal, .aseprite, .png, ...) and apply it.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
palette_fileYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations flag destructiveHint=true and readOnlyHint=false, but the description never discloses what the operation destroys or replaces (e.g., the existing palette) or which document is affected. 'Apply it' vaguely implies mutation but adds no real behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler or redundancy. It is terse, but every word contributes to the action being described.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema and 0% parameter coverage, the description omits the essential facts: which object is modified, whether the existing palette is replaced, and what 'filename' refers to. It is under-specified for the risk level implied by the annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and neither required parameter is explained. The description clarifies 'palette_file' only by listing example extensions, while 'filename' is left completely unexplained, so the agent cannot tell whether it names the target sprite or something else.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb+resource ('load a palette from a file') and even enumerates supported formats. It does not distinguish itself from palette siblings such as set_palette, extract_palette, or quantize_palette, and 'apply it' leaves the target of the application implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to prefer this over set_palette or extract_palette, no statement of prerequisites, and no indication of what 'apply' affects. The agent must infer usage entirely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

make_4_frame_idle_animationA

Turn a single-frame sprite into a 4-frame idle "bob" loop.

Duplicates frame 1 to 4 frames, nudges `layer` down by `bob_pixels` on frames 2
and 4 for a subtle bob, sets uniform durations, and adds a looping tag.

Returns a ``workflow_manifest.v1`` manifest (sprite summary + animation block).
ParametersJSON Schema
NameRequiredDescriptionDefault
layerNoDefault: "body".body
filenameYes
tag_nameNoDefault: "idle".idle
bob_pixelsNoDefault: 1.
frame_duration_msNoDefault: 150.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the description carries the behavioral burden and does so well: it enumerates the exact mutations (duplicates frame 1 to 4 frames, nudges `layer` down by `bob_pixels` on frames 2 and 4, sets uniform durations, adds a looping tag). It also discloses the return type (workflow_manifest.v1). It stops short of stating what happens to pre-existing frames or whether the operation is reversible/overwriting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by the mechanics and the return value. Every sentence earns its place with no filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with no output schema, the description supplies the transformation steps, the touched parameters, and the return shape, which is enough to call it correctly. A note on interaction with pre-existing frames (overwrite vs. append) would close the remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 80% (defaults documented for layer, tag_name, bob_pixels, frame_duration_ms), so baseline is 3. The description adds genuine meaning by tying parameters to behavior: `layer` is the layer that gets nudged, `bob_pixels` is the downward offset amount, and frame_duration_ms maps to the 'uniform durations'. Only `filename` (and the exact effect of tag_name) is left unelaborated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource+outcome: 'Turn a single-frame sprite into a 4-frame idle "bob" loop.' This is clearly distinguishable from generic siblings like add_frame, duplicate_frame, tween_cels, and smear_frame, which do not perform this specific one-shot idle-animation construction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The use case (single-frame sprite → idle bob loop) is implied clearly by the first sentence, so an agent can infer when it applies. However, no alternatives are named and no when-not guidance is given (e.g., what to do if the sprite already has frames, or how it differs from add_frame/duplicate_frame).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

make_8_direction_walk_templateA

Scaffold an 8-direction walk-cycle template on an existing sprite: enough frames for frames_per_direction per direction, with one animation tag per direction (N, NE, E, SE, S, SW, W, NW by default).

Args:
    frames_per_direction: 8 is the convention for a walk, and it is what this
        defaults to: contact, down, pass, up for each leg. 6 is the budget option and
        4 only reads as a walk mirrored on a side view, which an 8-direction sheet by
        definition is not. The default was 4 until this was fixed (#91), so a sprite
        scaffolded before then has half the frames a walk needs.
    frame_duration_ms: Set on every frame. Shape the timing afterwards with
        `apply_timing_curve`: a walk holds its contacts.
    directions: Override the eight compass tags.

Frames are placeholders to draw over. Returns a ``workflow_manifest.v1`` manifest
(kind "walk_template") with an animation block listing the directions/tags.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
directionsNo
frame_duration_msNoDefault: 120.
frames_per_directionNoDefault: 8.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark it as non-read-only and closed-world, so the description carries the useful extra detail: frames are empty placeholders to draw over, timing is set on every frame and should be refined with apply_timing_curve, and it returns a workflow_manifest.v1 (kind "walk_template"). It also discloses the historical default change (#91), which explains why older sprites may lack frames.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Leading sentence front-loads purpose and output shape, and the Args block is scannable. The #91 changelog aside is interesting but not essential for an agent deciding to call the tool, making it slightly longer than it needs to be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating scaffolding tool with no output schema, the description covers what is created (placeholders plus tags), the manifest kind it emits, and per-parameter meaning. It lacks any note on prerequisites (sprite size/layer expectations) or what happens if the sprite already has frames or tags of the same name.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% and the two schema-described params only restate their defaults, so the prose does the real work: it explains why 8 is the walk convention, why 6 and 4 are inferior for an 8-direction sheet, what frame_duration_ms applies to, and that directions overrides the default compass tags. The required filename param is never described anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb (scaffold) and resource (8-direction walk-cycle template on an existing sprite) plus the delivered output (a frame per direction with one tag per direction). It is clear enough to separate from siblings like make_4_frame_idle_animation, but it never names or contrasts an alternative such as scaffold_cycle.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: it is for a sprite that needs a walk cycle in all eight compass directions, and it operates on an existing sprite. There is no explicit when-to-use / when-not-to-use rule and no routing to scaffold_cycle or add_frame alternatives, so the agent must infer the context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_layer_downA
Destructive

Merge a layer down into the layer directly beneath it.

Refuses rather than doing nothing when there is nothing to merge into. Aseprite's
`MergeDownLayer` is a no-op in five cases, and it raises in none of them, so this used
to report a result indistinguishable from a merge that happened. Measured, naming the
layer stack before and after:

    bottom layer of the sprite        ['only']                   -> ['only']
    lowest layer inside a group       ['Layer 1', 'grp/a', 'b']  -> unchanged
    the layer below is a group        ['Layer 1', 'grp', 'a']    -> unchanged
    the layer named is a group        ['Layer 1', 'grp/a']       -> unchanged
    the layer below is a tilemap      ['Layer 1', 'tiles', 'px'] -> unchanged

All five returned sprite info describing the stack they had failed to change, which is
the same shape a successful merge returns. Only the ordinary case worked, so an agent
flattening a stack by merging downward in a loop was told the loop had finished when it
had stopped.

Returns `merged_into`, the name of the layer the artwork went into, so the result says
what happened rather than only what the sprite now looks like.
ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds rich behavioral context beyond that: it explains the refusal behavior, lists five no-op cases with measured layer-stack examples, and describes the returned merged_into field. This is exactly the kind of disclosure that helps an agent trust and correctly interpret the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence front-loads the core operation clearly. The remaining detail is useful for behavioral transparency, though the measured table and extended explanation are somewhat lengthy. Most sentences earn their place, but the definition could be tightened without losing essential meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with no output schema, the description does well by explaining failure modes and the merged_into return value. However, it leaves the two required parameters essentially undocumented despite 0% schema coverage, which is a notable gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for two required parameters (filename and layer). The description discusses the concept of a layer but never explains parameter syntax, accepted layer identifiers, filename format, or any constraints. It does not compensate for the schema's complete lack of parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb, resource, and direction: 'Merge a layer down into the layer directly beneath it.' This is unambiguous and distinguishes the operation from sibling tools like flatten_sprite or duplicate_layer without needing to name them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear when-not guidance by listing five cases where Aseprite's MergeDownLayer is a no-op and explaining that this tool refuses instead. However, it does not explicitly name alternative tools or conditions for choosing them, so it falls short of full when/when-not/alternatives guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mirror_layerB

Mirror one half of a layer onto the other (build symmetric artwork).

Args:
    direction: "horizontal" (reflect left<->right) or "vertical" (top<->bottom).
    source_side: which half is copied: "first" (left/top) or "second" (right/bottom).
    axis: mirror line position (x for horizontal, y for vertical); default = centre.
ParametersJSON Schema
NameRequiredDescriptionDefault
axisNo
frameNoDefault: 1.
layerYes
filenameYes
directionNoDefault: "horizontal".horizontal
source_sideNoDefault: "first".first

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=false, so the agent knows this mutates local state. The description implies the opposite half is overwritten by 'mirror onto the other', but doesn't state what happens to existing pixels on the target side or whether the operation is reversible. Adds some semantic context but not substantially more than the 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One-line summary followed by a compact Args block; the operation is front-loaded and every line earns its place. Slightly verbose in restating default values that the schema already carries.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter mutation tool with no output schema, the description covers the operation and the tricky cosmetic parameters well, but omits frame and the two required params (filename, layer) entirely. Adequate but with a visible gap an agent would want filled.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50% and the schema provides no value semantics for direction/source_side/axis (just types and defaults). The description supplies the missing meaning: 'horizontal' = left<->right, 'vertical' = top<->bottom, 'first' = left/top, 'second' = right/bottom, and axis = mirror line position. That is real added value over the schema, though filename and layer are undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Mirror one half of a layer onto the other') plus the goal (build symmetric artwork), which is clearly distinct from flip_sprite (whole-sprite flip) and draw_symmetric_pixels (pixel drawing). However it never names an alternative explicitly to route the agent, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance, no when-not-to-use, and no reference to siblings like flip_sprite or draw_symmetric_pixels. The parenthetical '(build symmetric artwork)' is the only hint of intent, leaving selection to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modify_selectionB

Grow, shrink, or outline the current selection.

Args:
    op: "expand" grows by `quantity` pixels, "contract" shrinks, "border" replaces
        the selection with a band of that width around its edge. A border selection
        is how you scope an outline or a contact shadow to where two forms meet.
    quantity: How many pixels, at least 1.
ParametersJSON Schema
NameRequiredDescriptionDefault
opYes
filenameYes
quantityNoDefault: 1.

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only readOnlyHint=false and openWorldHint=false. The description does not state what happens to the prior selection, whether the operation is destructive/irreversible, error conditions (e.g., no active selection), or permission requirements. For a mutating tool, this leaves substantial behavioral gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by per-parameter explanation; efficient and organized. The 'Args:' block formatting is slightly verbose but every line carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and thin annotations, the description covers op and quantity adequately but omits filename entirely and says nothing about mutation semantics or post-conditions. It's adequate to invoke the tool but not complete for a mutation on shared state.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (only quantity has a description), so the description must compensate. It does add real meaning: explains that op takes one of three named values and what each does, and that quantity is in pixels with a minimum of 1. It does not document the filename parameter at all, leaving one gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (grow, shrink, outline) and resource (current selection), and the op semantics are spelled out precisely. It doesn't explicitly differentiate from siblings like select_region, invert_selection, or deselect, but the operation on an existing selection is reasonably distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool operates on an existing selection ("the current selection") but gives no when-to-use guidance, prerequisites, or alternatives. The note that a border selection 'is how you scope an outline or a contact shadow' hints at usage context without naming or contrasting sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_frameA

Move one frame to another position, taking its cels and its duration with it.

Fixing an ordering mistake otherwise means deleting and redrawing. Nothing is copied:
the frame keeps its identity, so linked cels stay linked.

Args:
    frame: The frame to move, 1-based.
    to: Where it should end up, 1-based, in the numbering *after* the move. Moving
        frame 2 to 5 on a six-frame sprite gives 1, 3, 4, 5, 2, 6.

**Tags mark positions, not pictures.** A tag between the two positions keeps its own
range and now covers a different set of drawings. The result names every tag that
overlapped the frames in between, because that is the part worth checking and it is
invisible in the frame count.
ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
frameYes
filenameYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnlyHint=false annotation by disclosing that nothing is copied, the frame keeps its identity so linked cels stay linked, and that tags mark positions rather than pictures so their ranges shift. It also describes the return behavior (naming every tag that overlapped). This is exactly the mutation-side-effect context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then parameter docs, then the tag caveat ordered by importance. Slightly long, and the worked numbering example plus the bolded tag aside push it past the minimum, but each sentence carries information the agent cannot get from the 0%-covered schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with no output schema and no schema descriptions, the description covers the action, the identity/link preservation, the tag-range side effect, and what the result reports. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, yet the description fully compensates: frame and to are documented as 1-based, and crucially 'to' is defined in the post-move numbering with a worked example (moving 2 to 5 on six frames gives 1,3,4,5,2,6). Only filename is left implicit, and that is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Move one frame to another position') and immediately qualifies the scope ('taking its cels and its duration with it'). This cleanly separates it from add_frame, duplicate_frame, remove_frame, and reverse_frames in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear use context: fixing an ordering mistake that would otherwise require deleting and redrawing. It contrasts against the delete-and-redraw workflow rather than naming a sibling tool, so it stops short of explicit when-to-use-this-vs-that routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_layerB

Reorder a layer to a new 1-based stack index (1 = bottom-most).

Note: moves within the layer's current parent group.
ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes
to_indexYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=false, so the mutation and closed-world nature are known. The description adds useful context about the 1-based indexing and parent-group restriction, but does not cover side effects, error conditions, or required permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no wasted words, and the key behavioral detail (index base) is front-loaded before the parent-group note.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation with annotations covering safety, the description gives enough to understand the core operation, but it omits parameter semantics for filename and layer, and does not describe what happens on invalid indices or missing layers.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for all three required parameters. The description explains the meaning of to_index (1-based, bottom-most) but leaves filename and layer entirely undocumented, so it only partially compensates for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Reorder') and resource ('a layer') and clarifies the target index convention. It is clearly distinct from most siblings, but it does not explicitly differentiate itself from related ordering tools like set_cel_z_index or move_frame.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The note that the move occurs within the layer's current parent group provides a usage constraint, but there is no explicit guidance on when to use this tool versus alternatives such as set_cel_z_index or set_layer_properties.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

offset_celsA

Move one layer's drawn cel along a path across frames, in one Aseprite launch.

The cel on the first listed frame stays where it is; every later frame is placed
along the way to `(dx, dy)` from it, and the last frame lands exactly there. This is
the same work as one `set_cel_position` per frame, minus the launches and minus
computing the intermediate positions by hand.

Args:
    frames: The frames to place, in the order the movement passes through them.
    dx, dy: The whole movement, in pixels, from the first frame to the last.
    ease: How the movement is *spaced*: `linear`, `ease_in` (starts slow),
        `ease_out` (arrives slow), `ease_in_out`, or `gravity` (horizontal speed
        stays even while the vertical accelerates, as a thrown object does).
    arc_height: Bend the path into an arc this many pixels high at its midpoint,
        perpendicular to the straight line between the ends. A jump or a thrown
        object needs this; a slide does not.

Easing belongs here, in the spacing, and not in the frame durations. Applying a curve
to both applies it twice, and the result reads as slow motion rather than as weight.

Positions are whole pixels, so it is the running position that gets rounded and not
each step: the leftover fraction carries forward instead of being reintroduced every
frame, which is the difference between spacing that reads as speed and spacing that
reads as a limp. The returned `deltas` are the spacing a viewer actually sees, and
`max_error_px` is how far the furthest frame sits from the ideal curve, which stays
below one pixel.
ParametersJSON Schema
NameRequiredDescriptionDefault
dxNoDefault: 0.
dyNoDefault: 0.
easeNoDefault: "linear".linear
layerYes
framesYes
filenameYes
arc_heightNoDefault: 0.0.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only declaring readOnlyHint=false and openWorldHint=false, the description carries real load: it discloses that the first frame is anchored, intermediate positions are rounded via carried-forward fractions, and it describes the returned `deltas` and `max_error_px` bound despite there being no output schema. This is genuine behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action first, then args, then two short craft notes; each paragraph does work. Slightly verbose in the explanatory asides, but nothing is truly wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-param mutation tool with no output schema and partial schema coverage, the description covers the mechanics, the easing/rounding subtleties, and the return values. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 57% and the description compensates well, defining the frames ordering, the meaning of dx/dy as the total movement, the ease options (linear, ease_in, ease_out, ease_in_out, gravity) that the schema lacks an enum for, and arc_height's perpendicular-midpoint semantics. Only filename and layer are left unexplained in prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a precise verb+resource+scope: moving one layer's cel along a path across frames, and pins it as a single-launch operation. It implicitly distinguishes itself from the sibling set_cel_position by describing itself as the batched equivalent, so an agent can tell them apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context ('the same work as one set_cel_position per frame, minus the launches') and a specific rule for where easing belongs (spacing, not frame durations). However it never explicitly names or excludes the closest siblings, tween_cels and apply_timing_curve, leaving the agent to infer which movement tool to pick.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_in_editorA

Open a sprite in the Aseprite GUI window (non-blocking) for live viewing.

The window stays open and runs independently of this server. Keep editing the file with the other tools; Aseprite detects the on-disk change and prompts to reload (or reloads automatically, depending on your Aseprite preferences), so you can watch edits land without re-opening.

Returns the launched process id. To stop watching, just close the Aseprite window yourself.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial context beyond the annotations: the operation is non-blocking, the window runs independently of the server, on-disk edits are auto-detected and reloaded, the return value is the launched process id, and stopping is done by closing the window. Annotations only give the safety profile, so this is a rich, valuable disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, front-loaded sentences: purpose first, then lifecycle behavior, then return value and stopping instructions. Every sentence earns its place and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a GUI-launching tool with no output schema, the description covers what is needed: non-blocking behavior, process independence, reload semantics, the returned process id, and how to terminate watching. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description never discusses the single 'filename' parameter, its format, or whether paths are relative or absolute. 'Open a sprite' hints that the string should be a sprite file, but this is minimal compensation for a fully undocumented parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (open a sprite in the Aseprite GUI window) plus the key distinguishing mode (non-blocking, live viewing). This clearly separates it from headless export/render siblings like render_preview or export_png, so an agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear context for use: live viewing while continuing to edit with other tools, with the reload behavior explained. It does not explicitly name an alternative (e.g., render_preview) or a when-not-to-use condition, so it falls 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.

outline_smartA

Outline a shape in colours drawn from its own ramp, not one flat colour.

`add_outline` paints a single colour all the way round, which reads as a sticker.
Pixel artists vary the outline: darker where the form turns away from the light,
and often dropped entirely on the lit side so the shape breathes.

Args:
    ramp: Colours darkest first. Outline pixels come from here.
    mode: "colormatched" takes each outline pixel from the adjacent interior colour
        shifted `darken_steps` down the ramp. "selective" does the same but leaves
        the lit side unoutlined, which needs `light_angle`. "single" uses the
        darkest ramp entry all round, the classic look.
    darken_steps: How many ramp steps below the neighbouring interior colour.
    light_angle: Degrees, required for "selective". 135 is the usual key light.
    tolerance: How close an interior pixel must be to a ramp entry to be used as
        the source for its outline pixel.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

The outline is drawn outside the silhouette, into transparency, so it never eats
into the artwork.
ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoDefault: "colormatched".colormatched
rampYes
frameNoDefault: 1.
layerNo
filenameYes
toleranceNoDefault: 32.0.
light_angleNo
darken_stepsNoDefault: 2.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description adds the operationally important fact that the outline is drawn outside the silhouette into transparency 'so it never eats into the artwork' — key for predicting side effects. It still doesn't say whether the operation is destructive to existing outlines or requires an existing ramp/palette on the sprite.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, followed by a useful contrast sentence and an Args block; every line carries substance. Slightly long, but no filler that could be cut without losing parameter or behavioral meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and thin annotations, the description covers what it does, all parameter meanings, and a key side-effect (draws outside silhouette). Missing only return/error behavior and whether it overwrites existing outlines, which keeps it from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 50%, and the description fully compensates: it defines ramp ordering ('darkest first'), explains all three mode values with their behavior and the interaction with light_angle, and clarifies darken_steps, light_angle, tolerance, layer default, and frame indexing. This is meaning well beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (outline) and a precise, unusual scope: colours drawn from the shape's own ramp rather than one flat colour. It explicitly names and contrasts with the sibling add_outline ('paints a single colour all the way round, which reads as a sticker'), so an agent can distinguish the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Strong contextual routing: it explains the pixel-art rationale for varying the outline and when the lit side should be left unoutlined, which effectively tells the agent when to pick each mode. It lacks an explicit 'use this instead of X when Y' statement or prerequisite/permission notes, so it stops short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

paint_tile_pixelsB

Draw individual pixels into a tile's artwork (tile-local coordinates).

pixels: list of {"x", "y", "color"?}; falls back to the shared `color`.
ParametersJSON Schema
NameRequiredDescriptionDefault
colorNo
frameNoDefault: 1.
layerYes
pixelsYes
filenameYes
tile_indexYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations supply readOnlyHint=false, so the agent already knows this is a mutating operation, and the description adds the tile-local coordinate semantics plus a color fallback rule. However, it says nothing about preconditions (must the tile already exist?), overwrite behavior, or undo/irreversibility that a paint operation would benefit from.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded segments with no filler; the core purpose leads and the nested pixels detail follows. Efficient and easy to scan, though it leans heavily on terseness rather than elaboration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and low parameter coverage, the description is only marginally sufficient for a mutating tile-paint operation. It covers the nested pixel payload well but omits preconditions, return behavior, and several parameter meanings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 17%, so the description carries real weight and does explain the pixels item shape ({x, y, color?}) and the shared color fallback. But filename, layer, tile_index, and frame remain undocumented in both places, leaving a meaningful gap for a 6-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Draw individual pixels into a tile's artwork') and adds a scoping qualifier ('tile-local coordinates') that helps distinguish it from the canvas-level draw_pixels sibling. It doesn't explicitly name alternatives, but the tile-scoped framing is clear enough to infer intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no statement of prerequisites, and no named alternative (e.g., draw_pixels, set_tile, fill_tile). The tile-local coordinate note implies the use case but the description never tells the agent when this tool is the right choice versus its many drawing/tile siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plan_asset_specA
Read-only

Return the ordered build steps for an asset spec without launching Aseprite.

The pure dry-run: each step is ``{tool, args, purpose}`` naming the existing tool that
`build_asset_from_spec` would call. Returns a ``workflow_manifest.v1`` (kind
``asset_spec``) with the steps under `plan` and `dry_run=true`. If the spec is invalid,
returns the validation report instead.
ParametersJSON Schema
NameRequiredDescriptionDefault
specYes

TDQS

A3.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-open-world behavior, but the description adds significant detail beyond them: no Aseprite launch, pure dry-run execution, each step's shape as {tool, args, purpose}, the returned workflow_manifest.v1 kind with plan and dry_run=true, and the invalid-spec fallback to a validation report.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the tool's core purpose and dry-run behavior, followed by return and fallback details. It is compact and every sentence adds useful information, though the opening and second sentence overlap slightly in restating the dry-run idea.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully explains the returned manifest shape and invalid-spec behavior. However, for a tool whose only parameter is an opaque nested object with 0% schema coverage, the definition remains incomplete because an agent cannot determine how to construct a valid spec from this description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the single nested spec parameter is documented only by the schema type. The description calls it an 'asset spec' but does not describe its accepted fields, expected structure, or format, so it fails to compensate for the absent parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: returning ordered build steps for an asset spec. It explicitly scopes the behavior as a dry-run without launching Aseprite and names build_asset_from_spec as the tool whose calls are being previewed, clearly distinguishing it from build_asset_from_spec.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The dry-run framing strongly implies the tool is used to preview build steps before invoking build_asset_from_spec, and it notes that invalid specs return a validation report. However, it does not explicitly state when to choose this tool over validate_asset_spec or when not to use it, so usage is implied rather than directly prescribed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

quantize_paletteA
Destructive

Derive a palette from the art, reduced to at most max_colors entries.

The step between a picture and pixel art. `extract_palette` lists the colours a
sprite already uses but cannot reduce them to a budget, and `set_color_mode` maps art
onto a palette but cannot decide what the palette should be. This asks the editor's
own quantizer for the best `max_colors` colours for this art and installs them, which
is what to do before `set_color_mode("indexed", palette_source="keep")`.

One entry is spent on transparency, at index 0, which is what an indexed sprite needs
there: an opaque colour at the transparent index is in the palette and can never be
drawn.

**`max_colors` is a ceiling and nothing more, and it has a cliff in it.** The
reduction merges whole levels of colour space at a time, so it can stop well short of
what was asked for: measured, four distinct colours with `max_colors=4` came back as
one mid-grey that was the average of all four, while `max_colors=5` on the same art
returned all four exactly. The result therefore reports how many colours the art has,
how many of them the new palette holds exactly, and how many entries can draw at all,
and says in `warnings` when the palette cannot hold the art. Raising `max_colors` by
a little is usually what fixes it.

Refuses an indexed sprite. There a pixel is an offset into the palette rather than a
colour, so replacing the palette changes what every pixel means without touching a
pixel; the error says how to do it in that case.

Past a million pixels the art is not scanned, the palette is still derived, and the
result says the comparison was skipped rather than implying the art is blank.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
max_colorsNoDefault: 256.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark it destructive/non-readOnly; the description adds substantial beyond that: it installs the palette, spends index 0 on transparency, refuses indexed sprites with a remediation hint, skips pixel comparison past a million pixels, and surfaces 'warnings' when the palette cannot hold the art. This is rich mutation-behavior disclosure that the annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and sibling differentiation, then grouped into scannable paragraphs on atomicity, parameter cliffs, refusal, and degradation. Dense and informative, though the transparency-index aside and stylistic phrasing make it longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description covers what an agent needs: the mutation performed, refusal conditions, scale limits, and what the result reports (color count, exact-match count, drawable entries, warnings). Nothing essential to calling or interpreting it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50% ('max_colors' merely says 'Default: 256'), yet the description explains max_colors as a ceiling with a non-obvious quantization cliff, including a concrete measured example (four colors collapsing to one mid-grey at 4, preserved at 5). This meaningfully compensates for the schema gap; 'filename' is self-evident from context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Derive a palette from the art, reduced to at most max_colors entries') and explicitly distinguishes itself from 'extract_palette' (lists colors, cannot reduce) and 'set_color_mode' (maps onto a palette, cannot decide it). An agent can identify the tool's unique role without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('what to do before set_color_mode("indexed", palette_source="keep")'), when-not-to-use (refuses an indexed sprite), failure remedy ('raising max_colors by a little is usually what fixes it'), and the large-image degradation case. Rival tools are named and routed away from.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ramp_betweenA

Build a ramp from its two ends, which is how a ramp is usually decided.

`generate_ramp` grows a ramp outward from one base colour, so reaching a particular
shadow and a particular highlight means guessing at `hue_shift` until the ends land
near what was wanted. This takes the ends directly: pick the cool shadow and the warm
highlight, and the middle is interpolated between them.

Both ends come back **exactly** as given. They were chosen, and a ramp whose endpoints
are approximations of the caller's own colours is not the ramp that was asked for.

Args:
    easing: "perceptual" (the default) walks the straight line between the ends in
        Oklab, so the middle steps are evenly spaced to the eye and the ramp keeps its
        hue. "linear" is the naive sRGB blend, which darkens and greys the middle.
    filename, apply: As `generate_ramp`. "append" or "replace" writes the ramp into
        that sprite's palette.

Neither mode rotates hue. Interpolating hue between distant colours is what turns a
blue-to-cream ramp magenta in the middle: at that distance both ways round the wheel
are equally short, and neither is the blend anybody wanted.
ParametersJSON Schema
NameRequiredDescriptionDefault
applyNoDefault: "none".none
stepsNoDefault: 5.
easingNoDefault: "perceptual".perceptual
filenameNo
light_colorYes
shadow_colorYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the description carries the real burden. It adds meaningful disclosure: endpoints are returned exactly as given, easing choices change the middle's brightness/greyness, neither mode rotates hue, and append/replace writes into the sprite palette. It slightly defers by saying filename/apply behave 'As generate_ramp', and it doesn't clarify what apply='none' (the default) does with the built ramp.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and the sibling comparison before the Args block, which is the right order. It is slightly verbose — the endpoint-preservation paragraph and the hue-rotation aside both lean on emphasis but each still carries a distinct behavioral point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with no output schema and only safety annotations, the description covers purpose, differentiation, key behavior, and most arguments. Remaining gaps are small: the unaddressed 'steps' semantics and the fact that the return value is only implied ('both ends come back').

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%, so the description must compensate; it explains easing thoroughly (Oklab 'perceptual' vs naive sRGB 'linear') and partially covers apply ('append'/'replace' writes to palette). However, shadow_color/light_color are only described conceptually and the 'steps' parameter is never addressed anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Build a ramp from its two ends') and immediately frames the decision model. It draws an explicit contrast with the sibling generate_ramp, so an agent can distinguish the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (generate_ramp) and the condition that selects this tool: when you want to pin both a specific shadow and highlight rather than guessing hue_shift. This is explicit when-to-use guidance against a real sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ramp_from_artA

Recover the ramp an existing sprite is painted with.

`extract_palette` reports the colours a sprite uses as a set. A set is not a ramp: the
shading tools need them ordered dark to light, and an agent asked to add to somebody
else's sprite has no way to get that order today.

The colours are grouped by luminance into `steps` bands, and each band is represented
by the colour most of its pixels use, so every entry is a colour that is actually in
the art and can be matched against it. `coverage` says what share of the drawn pixels
each step covers, which is how to tell a real ramp from one step plus four stragglers.

Says so when the colours are not a ramp: art spanning many hues is several materials
sharing a sprite, and comes back with a warning rather than with a plausible-looking
five colours. Scope the read with `layer` when that happens.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
stepsNoDefault: 5.
filenameYes

TDQS

A4.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description is unusually rich about behaviour — luminance banding into `steps`, the modal-colour-per-band rule, the `coverage` share, and an explicit warning when the art is not a ramp. However, it frames the whole operation as a read ('Recover', 'scope the read'), while the annotation declares readOnlyHint=false, so the description's read/write framing conflicts with the supplied hint. That mismatch is the main transparency problem; mild credit is retained for the otherwise substantive disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs, front-loaded with the core action and then rationale. The digression about agents 'adding to somebody else's sprite' is slightly wordy but earns its place by motivating the tool. Nothing is buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the return-value burden itself and does so: `steps` bands, per-step `coverage`, and a warning path instead of a plausible-looking five-colour answer. Only the unexplained `frame` parameter and absence of any error/permission detail keep it from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%, so the prose has to compensate. It does meaningfully for `steps` (luminance bands, each represented by its dominant colour) and `layer` (scope the read when a warning fires). `filename` is self-evident; `frame` (default 1) is never explained, which is the only real gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Recover the ramp an existing sprite is painted with') and immediately distinguishes itself from the sibling `extract_palette`, explaining that a colour set is not an ordered ramp. An agent can pick this tool over the palette tools without inspecting either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (you need colours ordered dark-to-light for the shading tools, or you're adding to someone else's sprite) and names the alternative it supersedes (`extract_palette`, which only reports a set). It also says what to do in the failure case: when the warning about multi-hue art fires, re-run scoped with `layer`.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_frameA
Destructive

Delete a frame (1-based). The sprite must have more than one frame.

`frame` must already exist: an out-of-range number is rejected with the sprite's
valid range rather than clamped to it (which used to delete a different frame).
ParametersJSON Schema
NameRequiredDescriptionDefault
frameYes
filenameYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds important behavioral detail: frame indexing is 1-based, out-of-range input is rejected with the valid range rather than clamped, and this prevents accidentally deleting a different frame. This goes well beyond the annotation-level safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loaded with the action, and every sentence earns its place. The parenthetical about the old clamping behavior directly explains the validation behavior rather than adding trivia.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity deletion tool with annotations covering destructiveness, the description covers indexing, preconditions, and error behavior well. Minor gaps remain around the `filename` parameter and any downstream effects on tags or cels, but these are not central for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It thoroughly explains the `frame` parameter as 1-based, required, and validated against the existing range, though it does not clarify the `filename` parameter beyond the obvious string name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Delete a frame (1-based).' It clearly distinguishes the operation from sibling tools like add_frame, duplicate_frame, and move_frame, and states the key precondition that the sprite must have more than one frame.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear conditions for use: the sprite must have more than one frame, and the target frame must already exist. It does not explicitly name alternatives, but the deletion context and prerequisites are sufficient to guide correct invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_layerA
Destructive

Delete a layer (or group, including its children) by name or 1-based index.

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes

TDQS

A3.5/5.0
Behavior4/5

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 covered. The description earns credit by extending that: it discloses destructive *scope* — deleting a group also deletes its children — which annotations cannot express. It does not say what happens on a missing/ambiguous layer name, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single well-formed sentence with the operation front-loaded, the group/children caveat close behind, and zero filler. Nothing could be trimmed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description needn't explain returns, and annotations supply the destructive/safe-read profile. Still, for a destructive two-parameter tool it omits error behavior, index basis, and what 'filename' refers to — enough gaps that an agent may guess on edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry the load. It does clarify accepted formats for 'layer' (name or 1-based index), which is meaningful. However, 'filename' is never addressed, and it does not say whether the index counts all layers, top-level layers only, or respects ordering — leaving half the params undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb (Delete) and resource (layer) and immediately resolves the layer-vs-group ambiguity by noting groups and their children go too. That scope distinction separates it from sibling mutations like delete_cel, remove_frame, and remove_tag. It does not explicitly name a sibling, so it lands just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance, no note on prerequisites (e.g. whether the layer must exist or be unlocked), and no pointer to alternatives such as clear_layer. The purpose is inferable from the name, but the description itself provides no routing information.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_sliceC
Destructive

Delete a slice by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
filenameYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, so the write/destructive nature is already known. The description adds nothing beyond 'delete', failing to disclose what deletion entails (permanent? affects file? warnings? error if not found?). With annotations covering the safety profile, the bar is lower, but this still adds no behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, front-loaded verb+resource. Very efficient, though perhaps too terse for the scope.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with 2 undocumented parameters and no output schema, the description is inadequate. It doesn't explain what a slice is, how to reference it, or consequences of deletion.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and both parameters (name, filename) lack descriptions. The description only implies a 'name' parameter but does not explain what it identifies, how 'filename' relates (which file contains the slice?), or the relationship between them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb+resource: deletes a slice by name. Distinct from siblings like add_slice, set_slice, list_slices. But doesn't identify the 'slice' context (e.g., sprite) or how it's identified.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus set_slice, add_slice, or other slice operations. No prerequisites or context beyond the verb.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_stray_pixelsA

Replace pixels that have no neighbour of their own colour with the colour around them.

A stray pixel is one whose eight neighbours are all a different colour. They are what
a shading pass leaves behind at a band boundary, and at any zoom they read as dirt
rather than as texture. `assess_sprite` counts them as `isolated_pixels`; this is what
to do about the count.

Each stray takes the most common colour among its opaque neighbours, so **no new
colour can appear**: the result uses a subset of the colours already there, and art on
a ramp stays on it. Transparent pixels are left alone, so the silhouette does not
change.

A stray with no opaque neighbour at all has no colour to take, so by default it is
skipped: inventing one would be drawing rather than cleaning. That is the right answer
inside the art and the wrong one for the commonest dirt an effects pass leaves, which
is a lone pixel *outside* the art on empty canvas. `erase_isolated` is for that.

Args:
    protect: Colours never to replace. A one-pixel eye highlight or a specular dot is
        a stray by this definition and is meant to be there, so name its colour. Also
        keeps a cluster `erase_isolated` would otherwise erase, if the colour is in it.
    erase_isolated: Erase a cluster that stands clear of everything else instead of
        skipping it. **Opt-in, because this changes the silhouette**, which is the one
        thing the tool otherwise never does: a one-pixel spark, a floating highlight,
        the dot of an "i" drawn as its own element and a dither sparser than a
        checkerboard are all clusters by this rule and are all meant to be there. What
        it erases is reported as `erased`, apart from `replaced`, for the same reason.
    min_cluster: How many pixels a detached cluster may have and still count as dirt.
        1, the default, is a lone pixel, which is all "isolated" means by itself; 2
        catches the two-pixel speck these passes usually leave, where neither pixel is
        isolated because each has the other for company. Capped low, and the refusal
        names the cap: past a handful of pixels a thing standing clear of the artwork
        is a mark somebody drew. Only means anything with `erase_isolated`, and is
        refused without it rather than ignored.

Erasure is decided over clusters of **opaque** pixels, connected in all eight
directions, that have nothing but transparency around them. That is what makes it safe
at any `min_cluster`: the artwork is connected to itself, so it is never a cluster, and
only something standing clear of it can go. It is also why the two halves of this tool
barely meet: a cluster touches no other opaque pixel, so nothing else's replacement can
be reading a colour off one. Where they do meet, erasing wins, since recolouring dirt
on its way out is work with no result.

A pixel whose only same-colour neighbour is **diagonal** is part of a dither pattern,
not dirt, and is left alone. `assess_sprite` counts isolation orthogonally, which is
the stricter reading, so a dithered sprite still reports some `isolated_pixels` after
this has run and that count is the dithering rather than anything to fix.

This is not Aseprite's own Despeckle, which is a median filter: that one averages
neighbourhoods, introduces colours that were not in the palette, and on a measured
test left *more* stray pixels than it found. This changes only the pixels that are
strays, and only to colours already next to them.

Returns how many were replaced, so a second call can be skipped when it says 0. With
`erase_isolated` it also returns `erased` and `erased_clusters`, which are absent
otherwise: a count of work nobody asked for reads as a finding.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
protectNo
filenameYes
min_clusterNoDefault: 1.
erase_isolatedNoDefault: false.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes far beyond the readOnlyHint=false/openWorldHint=false annotations: it discloses that no new colour can appear, that transparent pixels and the silhouette are untouched by default, that erase_isolated DOES change the silhouette (the one destructive behavior), how clusters are defined (8-connected, opaque, surrounded by transparency), that diagonal-only neighbours are dithering and left alone, and why erased/erased_clusters are reported separately. This is exactly the behavioral context an agent needs for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and well-organized (opening sentence defines the action, then Args, then edge cases, then return values), but the description is very long — several paragraphs with repeated threading of protect/erase_isolated/min_cluster and multiple parenthetical justifications. It is thorough rather than concise; an agent gets the answer but pays a token cost. Structure is good, size is excessive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers operation semantics, destructive boundaries, cluster definitions, sibling routing, defaults, refusal behavior, and return values (replaced, and conditioned erased/erased_clusters). Nothing an agent needs to invoke this correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% (frame and layer have no descriptions; filename none either), so the description must compensate. It richly explains protect, erase_isolated, and min_cluster — their meaning, defaults, interactions, and even refusal conditions ('Capped low, and the refusal names the cap'; 'refused without it rather than ignored'). It does not cover frame/layer/filename, so not a 5, but the semantically tricky parameters are fully illuminated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a precise verb and operation ('replace pixels that have no neighbour of their own colour with the colour around them'), defines 'stray pixel' operationally, and distinguishes from siblings by naming assess_sprite (which counts them) and erase_isolated (for the outside-canvas case). An agent can tell exactly what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it (cleaning dirt left by shading passes at band boundaries), when it's the wrong answer (lone pixels outside the art on empty canvas — use erase_isolated), and the protect/erase_isolated interaction. It also distinguishes itself from a plausible alternative ('This is not Aseprite's own Despeckle'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_tagC
Destructive

Delete an animation tag by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
filenameYes

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare this as destructive and not read-only, so the safety profile is covered. The description adds nothing beyond the action itself — it does not state whether deletion is reversible, what happens to frames or cels associated with the tag, or any permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted words. It conveys the core action efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with two required parameters and no schema descriptions or output schema, the description is insufficient. It omits the meaning of 'filename', any behavioral consequences of deletion, and usage context, leaving significant gaps 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.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains the 'name' parameter indirectly ('by name'), but the 'filename' parameter is never mentioned or clarified, leaving half the required inputs undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Delete') and resource ('animation tag') with a clear scope ('by name'). This is unambiguous on its own, though it does not explicitly distinguish itself from sibling tools like add_tag or set_tag.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no when-to-use guidance, no prerequisites, and no alternatives. It only states what the tool does, leaving the agent to infer when deletion is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_layerC

Rename a layer.

ParametersJSON Schema
NameRequiredDescriptionDefault
layerYes
filenameYes
new_nameYes

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already disclose readOnlyHint=false and openWorldHint=false, so the mutation nature is covered structurally. The description adds nothing beyond that: it does not say what happens on name collision, whether the old name is preserved, or what errors can occur. For a mutating tool, this leaves the behavioral profile thin.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with zero waste and the action front-loaded, but the brevity reflects under-specification rather than efficient conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation tool with no output schema and zero parameter documentation, the description is too thin to be complete. It should at least clarify parameter roles, uniqueness/error behavior, or prerequisites.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All three parameters (filename, layer, new_name) have 0% schema description coverage, so the schema carries no semantics and the description must compensate — but it provides none. The names are largely self-explanatory, which keeps this above a 1, but there is no explanation of format or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (rename) and resource (layer), so the agent knows exactly what operation this performs. However, it offers no differentiation from near-siblings like set_layer_properties or move_layer, which also alter layer metadata.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no indication of when to use this tool versus alternatives such as set_layer_properties, nor any preconditions (e.g., layer must exist, name must be unique). Usage is left entirely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_previewA
Read-only

Render a single frame to a PNG and return it as an image you can view.

Use this to *see* your work. frame is 1-based; scale enlarges small sprites
(default 8x) so individual pixels are visible.
ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
scaleNoDefault: 8.
filenameYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond that: the 1-based frame indexing and the fact that scale enlarges small sprites so pixels are visible, which tells the agent what output quality to expect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, zero filler, and the core action leads immediately ahead of the parameter notes. Every sentence carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly states the return is a viewable image, and it covers the two non-obvious parameters. Minor gaps remain (no mention of error behavior for an out-of-range frame or whether a sprite must be loaded), but nothing essential is missing for a low-complexity preview tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67% and the schema's own descriptions are content-free ('Default: 1.', 'Default: 8.'). The description compensates by explaining that frame is 1-based and that scale magnifies sprites (default 8x), adding real meaning the schema lacks; only filename is left unexplained, though it is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Render a single frame to a PNG') plus the delivery mode ('return it as an image you can view'), which cleanly separates it from the export_* siblings that write files. An agent can identify this as the visual-inspection tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this to *see* your work' gives a clear condition for selection, implicitly contrasting with export tools. It stops short of naming an explicit alternative (e.g. export_png) or a when-not case, so it is clear context rather than full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

replace_colorB
Destructive

Replace every pixel matching from_color (within tolerance per channel) with to_color, on the chosen layer + frame.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerNo
filenameYes
to_colorYes
toleranceNoDefault: 0.
from_colorYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the write/mutation profile is covered. The description adds the useful scope detail that all matching pixels across the layer/frame are rewritten, but it does not state whether the change is reversible, whether it operates on a saved file or in-memory sprite, or what happens on no matches. Given annotation coverage, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single tight sentence with the operation front-loaded and the scope qualifier appended. No waste, though it sacrifices completeness for brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A destructive mutation tool with no output schema, 33% schema coverage, and an undocumented required filename parameter. The description does not cover color format, filename semantics, or the irreversible nature of the pixel rewrite. It should do more given the tool's complexity and destructive annotation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 33% – only frame and tolerance have descriptions (defaults). The description names from_color, to_color, tolerance, layer, and frame, giving semantic meaning to the color pair and tolerance that the schema lacks. However, it omits the required filename parameter entirely and gives no format for colors (hex? named? RGBA?), so it only partially compensates for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Replace) and resource (every pixel matching from_color), plus the exact scope (chosen layer + frame). An agent can distinguish this from select_by_color, fill_area, or recoloring operations without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no mention of alternatives (e.g., select_by_color + fill_area, or how it differs from invert_colors). The description is purely mechanical and does not route the agent to or away from sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resize_canvasA
Destructive

Resize the canvas WITHOUT scaling the artwork (adds or trims space).

anchor controls where existing content sits in the new canvas:
"top_left" (default) or "center". The new canvas is subject to the same
dimension/area caps as `create_sprite`.
ParametersJSON Schema
NameRequiredDescriptionDefault
widthYes
anchorNoDefault: "top_left".top_left
heightYes
filenameYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description consistently adds real behavioral context: that space is added or trimmed, and that the new canvas is bound by the same dimension/area caps as create_sprite. It does not state effects on existing layers/cels or failure modes, keeping it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, front-loaded sentences; the critical no-scaling constraint and the anchor semantics come first, with no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema this covers the core intent and one constraint, but omits what happens to existing cels/layer positions, whether changes are reversible, and error behavior for missing files — relevant gaps an agent would want.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 25%, so the description must compensate and it does so for anchor, explaining the meaning and values (top_left/center) beyond the schema's bare default note. width, height and filename receive no semantic detail (units, whether the file must exist), so the low-coverage burden is only partly met.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (resize) and resource (canvas) and immediately scopes it with 'WITHOUT scaling the artwork (adds or trims space),' which distinguishes it from scale_sprite and crop_sprite without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'without scaling' clause gives clear context for when this tool is the right choice versus scaling siblings, and anchor is explained. It stops short of naming the alternative tool or stating when-not (e.g. use scale_sprite to change artwork size).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resize_paletteB
Destructive

Resize the palette to size entries (new entries are black).

ParametersJSON Schema
NameRequiredDescriptionDefault
sizeYes
filenameYes

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the risk profile is carried by structured data. The description adds genuinely useful behavior for growth ('new entries are black'), but says nothing about the shrink case — whether colors are truncated, remapped, or an error is raised — which is exactly the destructive scenario the annotation warns about.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence, front-loaded with the verb and target, with the parenthetical default placed last. Efficient, though the extreme brevity leaves the destructive/shrink behavior unaddressed rather than deliberately trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a destructive mutation with no output schema and zero schema documentation, so the description carries the full burden. It covers growth only; an agent cannot tell what happens to existing palette entries on shrink, whether indices in existing artwork are remapped, or what the call returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for both parameters, so the description must compensate. It explains that `size` is a count of palette entries and how added entries are initialized, which is real value, but `filename` is left entirely unexplained in both schema and description, leaving half the surface undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Resize the palette') plus the target dimension (`size` entries), which is enough for an agent to distinguish it from siblings like set_palette, quantize_palette, or sort_palette. It stops short of explicitly contrasting itself with those palette siblings, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use this versus the many adjacent palette tools (quantize_palette, set_palette, extract_palette, add_palette_color). No prerequisites, no conditions, no exclusions are given; usage must be inferred entirely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reverse_framesA

Reverse the order of a run of frames, keeping their timing with them.

Reversing a walk to get its mirror, or a grow to get a shrink, is a normal move and
otherwise means re-authoring the whole thing. Whole frames move: every layer's cel
travels together, and each frame keeps its own duration.

Args:
    tag: Reverse one tag's frames.
    frames: Reverse these frames instead. They must be one unbroken run, because
        Aseprite reverses everything between the first and the last: a gapped list
        would silently take in the frames in between.

Defaults to the whole sprite when neither is given.

**Tags mark positions, not pictures.** A tag over the reversed frames keeps its own
range and now covers them in their new order, which is usually what was wanted for a
tag that spans the whole run and rarely what was wanted for one that spans part of
it. The result lists every tag that overlapped, so the ones worth revisiting are
named rather than left to be discovered later.
ParametersJSON Schema
NameRequiredDescriptionDefault
tagNo
framesNo
filenameYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only readOnlyHint=false and openWorldHint=false available, the description carries the load and does so well: it discloses that whole frames move as units, that each frame keeps its own duration, that a gapped frame list silently absorbs the frames in between, how tags behave (they mark positions, not pictures), and that the result lists every overlapping tag.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then structured into args and a caveat block. Mostly earns its place, though the aside 'otherwise means re-authoring the whole thing' and the tag paragraph are slightly verbose for the payload they carry.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers input semantics, the gapped-list hazard, tag side effects, and even what the result reports. Remaining gaps are minor: no mention of error conditions or whether changes are undoable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains what 'tag' targets, what 'frames' means, the unbroken-run constraint and why it matters, and the no-argument default. Only 'filename' is left undocumented, though it is self-evident as the required target.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a precise verb+resource+scope: 'Reverse the order of a run of frames, keeping their timing with them.' This clearly separates it from siblings like move_frame, duplicate_frame, or flip_sprite, which do not reorder a run while preserving per-frame durations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete motivating use cases ('reversing a walk to get its mirror, or a grow to get a shrink') and states the default (whole sprite when neither tag nor frames is given). It does not explicitly name alternative tools for those goals, so it stops short of a 5, but the when-to-use context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rotate_spriteB

Rotate the entire sprite by 90, 180, or 270 degrees (clockwise).

ParametersJSON Schema
NameRequiredDescriptionDefault
angleYes
filenameYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the mutation nature is already known. The description adds useful scope information ('entire sprite', clockwise direction), but omits whether rotation is in place or saved to a file, and whether 90/270 rotation resizes the canvas.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no waste. Purpose, scope, and accepted values are all in one clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 2-param mutation with no output schema, this covers the essentials. However, it says nothing about whether rotation applies across all cels/frames, whether the canvas is resized for 90/270, or whether results persist — relevant for a write tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the param burden. It usefully constrains 'angle' to 90/180/270 clockwise when the schema only says 'integer' with no enum — a real gap filled. 'filename' is undocumented but self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Rotate the entire sprite') and adds scope ('entire sprite') plus the accepted angles. This distinguishes it from per-cel operations, though it doesn't explicitly contrast with flip_sprite or offset_cels, which are the nearest siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance. It never mentions flip_sprite, offset_cels, or scale_sprite as alternatives, so the agent must infer that this is the dedicated rotation tool from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_sprite_asA
Destructive

Save a copy of a sprite under a new path (optionally flattened).

The original file is left untouched. Useful for exporting an editable
.aseprite to another .aseprite, or snapshotting a version.

overwrite: Replace `new_filename` if it already exists (default False = no-clobber).
ParametersJSON Schema
NameRequiredDescriptionDefault
flattenNoDefault: false.
filenameYes
overwriteNoDefault: false.
new_filenameYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, and the description adds meaningful context that reduces ambiguity: the original file is never modified, and the destructive path is opt-in via overwrite with a no-clobber default. It does not explain what flatten actually strips or what is returned, and it never reconciles the 'untouched original' claim with the destructive annotation explicitly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the key non-destructive guarantee are front-loaded, and the sentences are short and mostly free of filler. The trailing standalone overwrite note and the hard line wrapping make it slightly less tight than it could be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and a mutation-ish operation, the description omits what happens on failure and what the result is (e.g., the written path), and leaves flatten undefined. The safety-critical behavior is covered, so it is functional but not complete for a 4-parameter file-writing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 50% (flatten and overwrite only carry 'Default: false.'), so the description must compensate. It does explain overwrite ('Replace new_filename if it already exists') and gestures at flatten ('optionally flattened'), but never defines what flattening does, and filename/new_filename get no path-format or source-sprite guidance. Adequate but incomplete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Save a copy of a sprite under a new path') plus the optional transformation (flatten), and the two use cases (editable .aseprite to another .aseprite, snapshotting a version) separate it from the export_png/export_* siblings that produce different formats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage context ('exporting an editable .aseprite to another .aseprite, or snapshotting a version'), which tells the agent when this is the right tool versus the format-conversion exporters. There are no explicit when-not rules or named alternatives, 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.

scaffold_cycleA

Scaffold one animation cycle: its frames, a tag per phase, and a shaped timing curve.

`kind` is `walk`, `run`, `idle`, `attack`, `hurt` or `death`, and it settles the four
things a scaffolded animation otherwise gets wrong:

* **The frame count.** walk 8 (6 is the budget option, and 4 only reads as a walk
  mirrored on a side view), run 6, idle 4, attack 5, hurt 2, death 6. A count outside
  the kind's conventional range is accepted with a warning rather than refused.
* **A tag per phase, named for the pose rather than numbered.** An 8-frame walk gets
  `walk_contactL`, `walk_downL`, `walk_passL`, `walk_upL` and the same four for the
  right step, plus a `walk` tag over the whole cycle, so the frame you are drawing on
  says what it is meant to be.
* **Non-uniform durations from the start**, via `apply_timing_curve`: a cycle holds
  its extremes, an attack snaps through the strike, a hurt flashes and then holds the
  recovery, a death slows to a stop on a held last pose. Uniform timing is the
  placeholder every animation starts with and almost none should keep.
* **Loop versus one-shot.** An attack, a hurt and a death do not wrap, so every tag
  they get is written with `repeats=1` instead of being left at 0 ("play forever").
  That field is what `validate_loop` reads, so a one-shot tagged as a loop makes the
  checker report a duplicated seam frame on an animation that has no seam.

Frames are copies of frame 1, there to draw over. Nothing already in the sprite is
deleted, but Aseprite inserts a copied frame rather than appending it, so on a sprite
that already has several frames the new ones land at the front and the existing ones
end up at the end of the cycle; the manifest warns when that happens. Frames past the
cycle are left untagged and untimed, with a warning saying which.

Args:
    kind: walk | run | idle | attack | hurt | death.
    frames: Override the kind's default frame count.
    base_ms: The duration of a passing frame; every other duration is a multiple of
        it. Defaults per kind, because a run passes through its poses faster than an
        idle breathes.

Returns a ``workflow_manifest.v1`` manifest (kind ``animation_cycle``) whose
`animation` section lists every phase with the frame, tag, duration, timing role and
repeat count it ended up with, read back off the saved sprite rather than restated
from what was asked for.
ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes
framesNo
base_msNo
filenameYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare mutation (readOnlyHint=false) and openWorldHint=false; the description adds substantial behavior: frames are copies of frame 1, nothing existing is deleted, Aseprite inserts copies at the front so existing frames shift to the end, warnings are emitted for odd frame counts and untagged tail frames, and out-of-range counts are accepted with a warning rather than refused.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line summary followed by four tight bullets that each cover a distinct behavioral dimension, with args and returns clearly demarcated. It is long, but for a tool that mints frames, tags, timing and loop flags in one call, nearly every sentence carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description explains the return value (a workflow_manifest.v1 with kind animation_cycle, listing phase, frame, tag, duration, timing role and repeat count read back off the saved sprite). Combined with the mutation behavior and warning disclosures, an agent has everything needed to invoke and interpret it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry parameter meaning. It does: enumerates the six valid kind values, explains frames as an override of the kind's default count, and explains base_ms as the duration of a passing frame with per-kind defaults. Only filename is undocumented, which is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Scaffold one animation cycle: its frames, a tag per phase, and a shaped timing curve.' This distinguishes it clearly from narrow siblings like add_frame, add_tag, and apply_timing_curve, which each do only one of the three things this tool bundles.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives strong context on when each kind applies and which defaults are conventional, and explains the interaction with validate_loop (tagging one-shots with repeats=1 so the checker doesn't report a duplicated seam). It doesn't explicitly say when to prefer this over manually calling add_frame/add_tag/apply_timing_curve, so it stops short of full when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scale_spriteA
Destructive

Scale the whole sprite (artwork included).

Provide either `factor` (e.g. 2.0 to double) OR explicit `width`/`height`.
method: "nearest" (crisp pixels, default) or "bilinear" (smooth).

The scaled canvas is subject to the same dimension/area caps as `create_sprite`.
With `factor` the result depends on the sprite's current size, so that check runs
inside Aseprite and reports the size it would have produced.
ParametersJSON Schema
NameRequiredDescriptionDefault
widthNo
factorNo
heightNo
methodNoDefault: "nearest".nearest
filenameYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With destructiveHint=true already declared, the description adds real context: the scaled canvas is subject to the same dimension/area caps as `create_sprite`, and with `factor` the check runs inside Aseprite and reports the resulting size. That explains a non-obvious failure mode, which is valuable beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then parameter guidance, then caveats. Four short lines with no repetition, though the closing sentence about the cap check is slightly longer than needed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter mutation tool with no output schema and sparse schema descriptions, the definition covers purpose, parameter alternatives, method semantics, and the size-cap constraint. It does not describe the return payload other than the size report, but that is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 20% (just `method`), so the description must compensate, and it does: it explains `factor` semantics (2.0 = double), the width/height alternative, mutual exclusivity, and the meaning of 'nearest' vs 'bilinear'. Only the `filename` parameter goes unexplained, which is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Scale the whole sprite') and clarifies scope with '(artwork included)', which implicitly separates it from resize_canvas. It doesn't name resize_canvas or flip_sprite/rotate_sprite explicitly, so the differentiation from siblings is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operating context: use either `factor` OR explicit `width`/`height`, and explains the two `method` choices. It doesn't state when to prefer this over resize_canvas or when scaling is inappropriate, but the invocation conditions are unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

select_by_colorA

Select every pixel of one layer matching a colour, the magic-wand selection.

The usual way to scope an edit to one material: select the armour's base colour and
every later operation touches only the armour. Pair it with `shift_along_ramp` to
shade one material without disturbing its neighbours.

Args:
    color: The colour to match.
    tolerance: 0 matches exactly. Higher values also catch nearby colours, which is
        useful on artwork that was anti-aliased or converted from a photo.
    frame: Which frame to sample, 1-based.
    layer: Which layer to match on. Defaults to the top layer, which is the layer the
        drawing and shading tools also default to, so a selection made here scopes
        the call that follows it.

**One layer, not the composite**, and that is deliberate for the same reason
`get_pixels` takes a layer: the tools this selection is for write to one layer, so a
pixel selected on a different one is selected and unreachable. Select on the layer you
are about to edit.

This used to run Aseprite's `MaskByColor` without saying which layer it meant, and the
layer it got was whichever one Aseprite made active on opening the file, which is the
*bottom* one. Measured on an 8x8 sprite with red on the bottom layer and an opaque
blue square over half of it on the layer above: matching red selected all 64 pixels,
including the 32 nothing can see, and matching blue (32 pixels, plainly visible, and
on the layer every drawing tool writes to) selected nothing at all.

Refuses when no pixel matches, rather than reporting a success with no selection. The
old behaviour cleared the sidecar on the way through, so a mistyped colour silently
unscoped every edit that followed it, which is the opposite of what asking for a
selection means. A refusal leaves the previous selection as it was.
ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
frameNoDefault: 1.
layerNo
filenameYes
toleranceNoDefault: 0.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description goes well beyond that, disclosing that the tool refuses rather than reporting a false success, that a refusal preserves the previous selection, and the exact layer-defaulting behavior (top layer, matching drawing tools) with an explicit account of the legacy MaskByColor bug. For a state-mutating selection tool this is unusually complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and clearly sectioned (summary, Args, rationale), so structure is good, but the two final paragraphs are lengthy historical narration about the old MaskByColor behavior. That detail explains a real behavioral change, yet it is duplicated across the 'One layer, not the composite' paragraph and the bug story, costing more words than the agent needs to invoke the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, no annotations covering mutation semantics, and 5 parameters, the description carries most of the burden and does so competently: it covers selection scope, refusal semantics, layer defaults, and side effects on prior selections. It does not say what is returned on success (e.g. whether selection bounds or a count comes back), which is the main remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 40% (frame and tolerance carry just a default; color/filename have none). The description compensates by explaining color, the tolerance scale including the anti-aliasing/photo rationale for higher values, the 1-based frame, and the layer default plus why it matters. Only `filename` is left unmentioned, which is self-evident, so the gap is nearly closed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb+resource+scope: 'Select every pixel of one layer matching a colour, the magic-wand selection.' This is immediately distinguishable from siblings like select_region, modify_selection, and invert_selection, and even names the conceptual analogue (magic wand).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states a concrete use case (scoping an edit to one material) and names a companion tool (`shift_along_ramp`) for the follow-up operation, plus an operational rule ('Select on the layer you are about to edit'). It gives no explicit comparison to select_region or get_selection, so it stops short of full when-not-to-use routing, but the guidance is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

select_regionA

Select a region, so later edits only affect that area.

The selection persists until `deselect`, and every pixel-writing tool honours it.
There is no per-call override: to draw outside the selection, clear it first. Tools
that wrote fewer pixels than asked report `selection_applied` and
`pixels_outside_selection`, so a forgotten selection shows up in the result rather
than as a mysteriously incomplete edit.

Args:
    shape: "rect", "ellipse" (both use x/y/width/height) or "polygon" (uses points).
    x, y, width, height: The region. width/height default to the rest of the canvas.
    points: For "polygon", a list of {"x": int, "y": int}, at least 3.
    mode: "replace" the selection, or "add"/"subtract"/"intersect" with the current
        one. Building a selection from several shapes is how you scope an edit to
        an awkward area, such as everything except a character's eyes.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
modeNoDefault: "replace".replace
shapeNoDefault: "rect".rect
widthNo
heightNo
pointsNo
filenameYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the description carries the real burden and delivers: selection persistence, cross-tool effect on every pixel-writing tool, no per-call override, and self-reporting via selection_applied/pixels_outside_selection so a stale selection is visible rather than silent. This is exactly the behavioral context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and persistence semantics, then a structured Args block. Every sentence adds information (override behavior, failure reporting, composition motivation); no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by naming the result fields (selection_applied, pixels_outside_selection) returned by affected tools. Combined with full coverage of selection lifecycle and modes, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% and its descriptions are trivial ('Default: 0'), so the description does the heavy lifting: it maps shape values to their coordinate requirements ('polygon' uses points), explains that width/height default to the rest of the canvas, and defines what mode does. The required 'filename' parameter is never mentioned, a minor gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Select a region') plus its scope consequence ('so later edits only affect that area'), which cleanly separates it from siblings like modify_selection, invert_selection, and deselect. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly explains persistence ('until deselect'), the absence of a per-call override, and the corrective action ('clear it first'). It also names the mode values and describes the composition workflow (add/subtract/intersect) with a concrete motivating example.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_all_frame_durationsA

Set every frame's duration in milliseconds (uniform animation speed).

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
duration_msYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=false, openWorldHint=false) already tell the agent this is a local mutation, so the bar is lower. The description adds the semantic rationale ('uniform animation speed'), but omits that it overwrites all existing per-frame delays and does not say whether the change is persisted to disk or only to the in-memory sprite.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the scope, unit, and intended effect, and no filler. Nothing can be trimmed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-param mutation tool with no output schema this is minimally sufficient, but the filename argument is undocumented, the overwrite semantics are unstated, and the relationship to the single-frame sibling is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the schema only types duration_ms as an integer, so the description's disclosure of the millisecond unit is genuinely additive. The required 'filename' parameter, however, has no explanation in either the schema or the description, leaving the compensation incomplete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (set) and resource (every frame's duration) with an explicit scope qualifier ('every frame') that implicitly distinguishes it from the sibling set_frame_duration. However, it never names that sibling, so the differentiation relies on the agent noticing the singular/plural contrast on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the 'every frame' wording suggests bulk application versus the single-frame variant, but there is no explicit guidance on when to prefer this over set_frame_duration or whether it belongs to a specific animation workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_cel_opacityC

Set a cel's opacity (0-255).

ParametersJSON Schema
NameRequiredDescriptionDefault
frameYes
layerYes
opacityYes
filenameYes

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare it's a non-read-only, closed-world mutation. The description adds the 0-255 range constraint, which is useful behavioral context beyond annotations, but doesn't explain effects on linked cels, clamping, or persistence.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with no wasted words. For a simple setter, this is concise, though it could arguably afford a bit more detail on parameters without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation with no schema descriptions and no output schema, the description is far too sparse. It identifies the operation and one parameter range but leaves the agent without necessary context on how to identify the target cel or interpret the other parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It only clarifies the 'opacity' parameter's range (0-255), leaving filename, layer, and frame completely undocumented—the agent has no semantic guidance for three of four required parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Set') and resource ('cel's opacity'), clearly distinguishing it from sibling setters like set_cel_position or set_cel_z_index by naming the property. It stops short of 5 because it doesn't explicitly reference alternatives or scope (e.g., which cel).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives such as set_properties or set_cel_position, nor any prerequisites. The simple setter nature implies usage, but no explicit context is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_cel_positionC

Move a cel's image to position (x, y) within the canvas.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
frameYes
layerYes
filenameYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations establish this is a write operation (readOnlyHint=false) in a closed world, so the safety profile is partly covered. Beyond that the description says nothing: it does not reveal whether the position is relative to the layer, canvas, or tilemap origin, what happens to pixels pushed past the canvas edge, or whether linked cels are affected.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with the action front-loaded and no filler. It is efficient, though it is efficient partly because it omits necessary content rather than by trimming redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a mutation tool with no output schema, 0% parameter documentation, and only two terse annotations. The description leaves the coordinate frame, cel identification (filename/layer/frame), and out-of-bounds behavior entirely unaddressed, which is inadequate for a 5-required-parameter write operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 5 parameters, so the description carries the full burden. It only surfaces x and y (implicitly, as the positional pair) and says nothing about filename, layer, or frame, leaving three of five required parameters with no semantic explanation anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Move') and resource ("a cel's image") with a clear positional target, so the core action is unambiguous. It does not differentiate itself from neighboring tools such as offset_cels, move_layer, or set_cel_z_index, which all involve repositioning, so an agent gets no help disambiguating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no mention of prerequisites (a cel must already exist given filename/layer/frame), and no named alternative. The reader must infer from the name alone that this is a direct absolute-position setter rather than a relative offset.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_cel_z_indexA

Reorder one cel against the other cels in its frame, without moving any layer.

This is the fix for "the arm is in front of the body this frame and behind it the
next". The alternatives are to restructure the layer stack, which changes every other
frame too, or to duplicate the arm onto a second layer and hide one of them per
frame; a z-index is per cel, so it says exactly what it means and only where it
applies.

`z` is an offset, not a position: 0 (the default for every cel) means "wherever this
cel's layer sits in the stack", a positive number moves the cel towards the front and
a negative one towards the back. A cel draws at its layer's stack position plus `z`,
and when two cels land on the same number the one with the larger `z` draws in front.
So `z=1` on a cel one layer below another is enough to put it in front of that one.

The ordering is scoped to the layer's siblings: a layer inside a group is ordered
against that group's other layers, and the group as a whole keeps its place. Returns
`order`, the frame's competing cels back to front, which is the part a caller cannot
see for themselves.

A z-index is per cel even when the cel is linked: two frames sharing one image share
their opacity and their properties, and do not share this. Verified against the
editor, because the opposite is the reasonable guess.

`z` must be between -32768 and 32767. The editor accepts a larger number in memory
and then stores it in a 16-bit field, so saving and reopening would silently turn it
into a different one, usually of the opposite sign.
ParametersJSON Schema
NameRequiredDescriptionDefault
zYes
frameYes
layerYes
filenameYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark it as a mutation (readOnlyHint=false). The description adds crucial behavioral depth: z is an offset not a position, default 0, positive/negative movement, tie-breaking rule, scoping to sibling layers, per-cel behavior even when linked, the exact numeric range -32768 to 32767, and why larger values cause silent corruption on save. This is far beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and alternatives, then systematically explains z semantics, scoping, and edge cases. Every sentence adds value, though the overall length is substantial; it could be trimmed slightly without losing critical information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a mutation tool with four required parameters, no output schema, and minimal annotations, the description covers the tool's behavior, constraints, return value (`order`), and scoping rules in full. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the full load. It thoroughly explains the `z` parameter (meaning, range, tie-breaking) but leaves `filename`, `layer`, and `frame` without explicit definition, relying on the reader's inference from context. This is adequate for an expert but leaves clear gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb+resource: 'Reorder one cel against the other cels in its frame, without moving any layer.' It distinguishes from sibling tools by explaining the exact problem it solves and why alternative approaches (restructuring layers, duplicating cels) are inferior.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool ('the fix for the arm in front of the body this frame and behind it the next') and names the concrete alternatives (restructure layer stack, duplicate layer) along with their downsides. The agent can confidently select this tool over the alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_color_modeA
Destructive

Convert a sprite between colour modes ("rgb", "indexed", "gray").

Converting **to indexed** builds the palette from the sprite's own colours first,
which is what the editor does and what makes the art survive. Mapping art against
whatever palette the sprite happened to carry is how this tool used to empty a
sprite: a saved RGB sprite carries a single transparent entry, so every pixel
resolved to it and the whole image became transparent while the call reported ok.

Args:
    color_mode: "rgb", "indexed", or "gray".
    dithering: "none" (default), "ordered", or "old". How a colour between two
        palette entries is resolved. Indexed conversions only.
    palette_source: "from_art" (default) quantizes the sprite's colours into a new
        palette and maps onto that, so flat colours convert exactly. "keep" maps
        against the palette the sprite already has, for when you loaded or built one
        deliberately; snapping the art to that palette is the point, so expect
        colours to shift, and expect two art colours to merge where the palette has
        only one entry near them. Indexed conversions only; the other modes have no
        palette to choose.

**Refuses** a conversion to indexed that would make drawn pixels disappear, naming
how many, and leaves the file untouched when it does. Losing colour accuracy is what
indexed mode is for and is allowed; losing pixels is not recoverable and is the one
thing a mode change must never do quietly. `set_palette` or `add_palette_color` fix a
palette that has nothing to draw with.

That check counts every pixel of every frame, twice. Past `MAX_VERIFY_PIXELS` the
conversion still runs and reports `verified: false` with the reason, rather than
being refused: a capability that declines to work on a large sheet because the check
is unaffordable is worse than one that works and says what it did not check.
`diff_sprites` against a copy taken beforehand answers the same question by hand.

Returns the sprite's structured info, plus `drawn_pixels` and `verified` (whether
that count was actually compared across the conversion) and the `palette_source`
used, for indexed targets.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
ditheringNoDefault: "none".none
color_modeYes
palette_sourceNoDefault: "from_art".from_art

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description goes well beyond that: it documents the refusal precondition (indexed conversions that would erase drawn pixels, with a count reported and the file left untouched), the large-sheet fallback where MAX_VERIFY_PIXELS is exceeded and the call proceeds with verified:false, and the historical failure mode that motivates the check. This is exactly the kind of behavioral context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the conversion itself and then uses a clear Args block, so structure is good. It runs long, however, and the aside about how the tool 'used to empty a sprite' plus the doubled pixel-count detail could be trimmed without losing the operational guarantee.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description still specifies the return payload (structured sprite info plus drawn_pixels, verified, palette_source for indexed targets) and covers the refusal path, the unverified-large-sheet path, and the palette_source default. Nothing an agent needs to call it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% - filename and color_mode have no schema descriptions and dithering/palette_source only carry a default string. The description compensates fully, documenting each value of color_mode, the three dithering behaviours and their indexed-only scope, and the two palette_source strategies including when colours will shift or merge.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb (Convert) and resource (a sprite between colour modes) and enumerates the three target modes, which pins the operation precisely against palette-oriented siblings like set_palette, quantize_palette and cycle_palette. An agent can tell what changes and what the input domain is without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives real guidance on option selection - dithering applies to indexed only, palette_source=from_art vs keep with the consequences of each - and routes agents to set_palette/add_palette_color when a palette is unusable and to diff_sprites for manual verification. It never states explicitly when to choose this tool over a sibling conversion/quantization tool, so it stops short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_frame_durationA

Set a single frame's duration in milliseconds (1-based frame).

`frame` must already exist: an out-of-range number is rejected with the sprite's
valid range rather than clamped to it (which used to report the requested number
while changing frame 1).
ParametersJSON Schema
NameRequiredDescriptionDefault
frameYes
filenameYes
duration_msYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say it is not read-only and not open-world. The description adds meaningful behavioral detail: out-of-range frames are rejected with the valid range rather than clamped, and the historical bug is called out so the agent understands the current contract.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loads the operation, and keeps the key precondition in the first sentence. The parenthetical historical note is useful but slightly more detail than strictly needed for selection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter mutation tool with no output schema and minimal annotations, the description covers indexing, units, existence constraint, and error behavior. It is nearly complete, though filename semantics and whether changes are persisted remain implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explains that duration is in milliseconds and that frame is 1-based and must already exist, but it says nothing about the filename parameter, leaving one of three required parameters semantically undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource: set a single frame's duration, with units and indexing. The word 'single' distinguishes it from the sibling set_all_frame_durations without requiring the schema to be opened.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an important precondition ('frame' must already exist) and error behavior, but does not explicitly say when to choose this tool over set_all_frame_durations or other frame-duration tools. Usage is implied by the single-frame scope rather than stated as routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_layer_propertiesC

Update one or more layer properties. Only the arguments you pass are changed.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
layerYes
opacityNo
visibleNo
editableNo
filenameYes
blend_modeNo

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, so the agent knows this is a mutation, and the description usefully adds that unset properties are left untouched. It is silent on permissions, behavior when the layer or filename is invalid, and whether failing mid-update rolls back, which matters for a multi-field writer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with zero padding, and the primary action is front-loaded. It is efficient but verges on under-specification rather than dense information delivery.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter write tool with no output schema and only minimal annotations, the description is far too thin. An agent still cannot tell which properties are settable, what values blend_mode accepts, or what happens on partial failure, so key operational knowledge is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 7 parameters, and the description contributes no meaning for any of them. It never maps the verb 'properties' to the fields name, opacity, visible, editable, or blend_mode, nor explains that filename/layer are the addressing keys, leaving the agent to guess from bare names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update one or more layer properties'), so the core action is unambiguous. However, it fails to distinguish itself from overlapping siblings like rename_layer and move_layer, which also mutate per-layer attributes, and it never clarifies which properties are in scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence ('Only the arguments you pass are changed') describes partial-update semantics rather than when to choose this tool. There is no guidance on when to use it versus rename_layer, move_layer, or set_properties, nor any prerequisites such as the file needing to be open or the layer existing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_paletteC
Destructive

Replace the entire palette with the given list of colours.

colors: list of colour strings, e.g. ["#000000", "#ffffff", "255,0,0"].
ParametersJSON Schema
NameRequiredDescriptionDefault
colorsYes
filenameYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, and the description's 'Replace the entire palette' largely restates that rather than adding context. It says nothing about what 'filename' scopes to (which sprite/palette file), whether the previous palette is recoverable, or what happens to palette indices already in use.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short lines, front-loaded with the destructive action and then the one non-obvious parameter format. The trailing fragment 'colors: ...' is slightly terse but not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, file-scoped mutation with no output schema, the description is minimally adequate: it conveys the overwrite semantics and the colour format. It omits what 'filename' refers to and any recoverability/permission note, which matters given destructiveHint=true.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It does document the 'colors' parameter with concrete format examples (hex and 'r,g,b' strings), which is genuinely useful, but the required 'filename' parameter is never explained, leaving half the inputs ambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Replace') plus resource ('palette') and scope ('entire'), which distinguishes it from partial mutators like add_palette_color or set_palette_color. It does not explicitly name those siblings, but the scoping word 'entire' carries the differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance and no mention of alternatives, despite a dense sibling cluster (set_palette_color, add_palette_color, resize_palette, load_palette, quantize_palette). The agent is left to infer that this is the whole-palette overwrite variant.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_palette_colorA

Set a single palette entry by index (0-based). Grows the palette if needed.

The index is bounded by the palette ceiling: the Lua below resizes the palette to
`index + 1`, so the index *is* a palette size.
ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
indexYes
filenameYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false, so the description carries real weight by disclosing that the palette grows if the index exceeds its size — a mutation side-effect the agent would otherwise not anticipate. It does not explain return values, error behavior, or whether color must be a specific format, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and two sentences of genuinely relevant constraint, with no filler. The dangling reference to 'the Lua below' is a minor structural flaw since no such code is present in the visible definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and thin annotations, the description covers the mutation and index semantics but leaves the color encoding and filename target unspecified. It is adequate to call the tool safely but not fully self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate for three parameters. It usefully clarifies that index is 0-based and effectively defines the resulting palette size, but it says nothing about the color string format or the filename parameter's role, leaving meaningful gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (set a single palette entry) and scope (by index, one entry at a time), which distinguishes it from bulk siblings like set_palette and resize_palette. It never names an alternative explicitly, so it falls short of a 5 but the operation is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is for writing one entry rather than the whole palette or appending a new one, but the description never states when to prefer it over add_palette_color, set_palette, or resize_palette. The growth note hints at a use case but no explicit routing guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_propertiesA
Destructive

Store a custom property on an object inside the sprite, in the .aseprite file.

This is where game metadata belongs: a hitbox on a slice, an anchor point on a layer,
"this frame deals damage" on a cel, a surface kind on a tile. It travels with the art
instead of living in a sidecar file that the next edit desynchronises, and the editor
shows it and keeps it.

Args:
    target: Which kind of object: "sprite", "layer", "cel", "tag", "slice" or "tile".
    key: The property name, e.g. "hitbox".
    value: What to store. Text by default, so value="7" stores the two-character
        string "7". Pass as_json=True to store a number, a boolean or a structure:
        then "7" stores the number 7, "true" stores a boolean, and
        '{"x": 8, "y": 15}' stores a table. A value that begins like a JSON object or
        array is read as JSON either way, since there is no other reading of one.
    layer: The layer's name. Needed for target "layer", "cel" and "tile".
    frame: 1-based frame number, for target "cel" (default: the first frame).
    name: The tag's or slice's name, for target "tag" and "slice".
    tile: An index into the layer's tileset, for target "tile". 0 is the empty tile.
    namespace: Keep the property in a named group rather than in the unnamed one the
        editor's own property panel uses. Two tools can then both use the key
        "anchor" without colliding. Namespaces cannot be listed back, so a caller has
        to know the name to read one again.
    as_json: Parse `value` as JSON before storing it (see `value`).
    delete: Remove the property instead of setting it. `value` is then ignored, and
        removing a key that was not there is not an error.

A selector the target does not use is refused rather than ignored, because the
property would otherwise land on a different object than the one that was named.

Properties live on the record that linked cels share, so setting one on a held pose
sets it on every frame of the hold. The result says which frames those were.

Returns the whole property group after the write, so the stored value is visible as
the type it was stored as.
ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes
nameNo
tileNo
frameNo
layerNo
valueNo
deleteNoDefault: false.
targetYes
as_jsonNoDefault: false.
filenameYes
namespaceNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past the annotations: discloses that unused selectors are refused rather than ignored, that properties live on shared cel records so a held pose sets every frame, that namespaces prevent key collisions but cannot be listed back, and that deleting a nonexistent key is not an error. These are precisely the behaviors an agent cannot derive from destructiveHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose before the Args block, and every sentence carries information. It is long, but the length is justified by the 11-parameter surface and the storage-type subtleties; little could be cut without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, it describes the return (the whole property group after the write, so the stored value is visible as the type it was stored as) and notes the result identifies which frames were affected. Complete for a destructive multi-parameter mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 18%, so the description carries the load, and it does: every meaningful parameter (target, key, value, layer, frame, name, tile, namespace, as_json, delete) is explained with types and defaults. The value/as_json interaction ("7" vs 7, JSON-shaped strings parsed either way) is documented far beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (store) and resource (custom property on an object in the .aseprite file) and immediately scopes the intent with a concrete example list (hitbox on a slice, anchor on a layer). An agent can distinguish this from the sibling get_properties, which is the read counterpart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when this is the right tool (game metadata that should travel with the art rather than a sidecar file) and covers the delete case explicitly. It never names the sibling get_properties as the read path, so an agent must infer the read/write split.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_sliceB

Update an existing slice's bounds, name, colour, or data.

data: a string is stored as it arrives; a dict or list is JSON-encoded, so structured
user-data round-trips through export_slice_metadata.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNo
yNo
dataNo
nameYes
colorNo
widthNo
heightNo
filenameYes
new_nameNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, confirming this is a mutation on closed local data. The description adds useful detail on data encoding behavior (strings pass through, dicts/lists are JSON-encoded and round-trip via export_slice_metadata) which goes beyond annotations. However, it doesn't say whether undefined fields are left alone or cleared, whether the name change via new_name vs name behaves how, or what happens if the slice doesn't exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short paragraphs; the first sentence front-loads purpose and the second adds targeted detail on the data param. No wasted words, though the encoding note could be trimmed slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

9 parameters with 0% schema coverage, no output schema, no annotations beyond safety flags, and description only covers one parameter's behavior. For a 9-param mutation tool the description leaves substantial gaps — how bounds interact, what new_name vs name does, and error behavior are all unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% — no parameter is documented in the schema. The description explains data encoding semantics for the 'data' param but says nothing about x/y/width/height/fileName semantic constraints, nor the difference between 'name' (required) and 'new_name'. Partial compensation at baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Update an existing slice's bounds, name, colour, or data' — specific verb (update) plus resource (slice) plus enumerable fields. Distinguishes itself from siblings add_slice/remove_slice/list_slices, though it doesn't explicitly name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance about when to use this vs add_slice or remove_slice, no mention of prerequisites like whether the slice must already exist, and no exclusions. The 'existing' implies the slice must pre-exist but this is only weakly inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_tagA

Update an existing tag. Only the arguments you pass are changed.

Note: changing from_frame/to_frame recreates the tag in place to update its
range reliably across Aseprite versions. A frame that does not exist is rejected
with the sprite's valid range rather than clamped into it.

`repeats` is how many times the tag plays, with 0 meaning forever. It survives the
recreate above along with the name, direction and colour.
ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
colorNo
repeatsNo
filenameYes
new_nameNo
to_frameNo
directionNo
from_frameNo

TDQS

A3.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=false, so the description carries the disclosure burden and does it well: it warns that changing from_frame/to_frame recreates the tag in place, that an out-of-range frame is rejected with the sprite's valid range rather than clamped, that repeats=0 means forever, and that name/direction/colour survive the recreate. These are non-obvious, operationally important behaviours an agent could not infer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, followed by a scoped note block; every sentence carries information. Slightly over-fragmented with the mid-sentence line breaks and the parenthetical aside about Aseprite versions, but no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema and minimal annotations mean the description is the main source of truth. It covers the tricky behavioural cases well, but for an 8-parameter, 0%-coverage mutation tool it leaves direction (an enum-less string with no hint of forward/reverse/pingpong), colour format, and the identifier-vs-rename roles of name/new_name undocumented.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% across 8 parameters, so the description must compensate. It adds real meaning for repeats (0 = forever) and for from_frame/to_frame (recreation and validation), and generalises partial-update semantics, but it says nothing about the name vs new_name distinction, the colour format, or the legal values for direction.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Update an existing tag" is a specific verb+resource and clearly scopes it to mutation of a tag that already exists, distinguishing it in spirit from add_tag and remove_tag in the sibling list. It does not name those siblings explicitly, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Only the arguments you pass are changed" implies partial-update usage and the phrase "Update an existing tag" implies it is not the tool for creating a tag, but no alternative (add_tag) is named and no conditions or exclusions are given. Usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_tileC

Place a tile (by tileset index, 0 = empty) at grid cell (column, row).

ParametersJSON Schema
NameRequiredDescriptionDefault
rowYes
frameNoDefault: 1.
layerYes
columnYes
filenameYes
tile_indexYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=false, so the agent knows this mutates local state. The description adds only the "0 = empty" clearing behavior; it says nothing about whether the tileset/file must already exist, whether the change persists, or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with the key index semantics parenthesized inline; nothing is wasted and the operation is front-loaded. It is efficient, though very sparse for a 5-required-parameter mutation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter mutation tool with no output schema and 17% schema coverage, the definition is too thin: filename/layer semantics, save behavior, and failure modes are all unaddressed, so an agent cannot reliably call it without guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17%, so the description carries heavy burden. It usefully explains tile_index (tileset index, 0 = empty) and maps column/row to a grid cell, but leaves the required filename, layer, and the optional frame parameter completely unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("Place a tile") and a precise target ("grid cell (column, row)"), and clarifies tile_index semantics ("0 = empty"). However, it does not distinguish itself from the cluster of highly similar siblings (add_tile, set_tiles, fill_tile, paint_tile_pixels), leaving the agent to infer the difference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no mention of the near-identical tile siblings. With add_tile, set_tiles, fill_tile and fill_tilemap all in scope, the absence of any routing guidance is a clear gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_tilesC

Place many tiles at once. tiles: list of {"column", "row", "index"}.

ParametersJSON Schema
NameRequiredDescriptionDefault
frameNoDefault: 1.
layerYes
tilesYes
filenameYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the write nature is already covered. The description adds nothing beyond that: it doesn't say whether existing tiles are overwritten, whether 'index' refers to a tileset index or -1 for empty, or whether filename/layer must pre-exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and followed by the payload shape, with no filler. It is lean almost to the point of being terse, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A mutation tool on a tilemap layer with four parameters, 25% schema coverage, no output schema, and dense tile siblings — the description should do much more. It omits what the operation mutates, overwrite behavior, and how it differs from the other tile tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 25% (only 'frame' is documented), so the description must compensate. It partially does by disclosing the tile object shape {column, row, index}, which is genuinely useful since the schema types 'tiles' items as an opaque object. But filename, layer, and frame semantics remain unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Place many tiles at once'), and the plural quantity implicitly distinguishes it from the singular set_tile. However, it never names or contrasts with the nearby siblings set_tile, add_tile, fill_tile, or fill_tilemap, leaving the agent to infer which tile-writing tool applies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no exclusions, and no alternatives named, despite four tile-manipulation siblings (set_tile, add_tile, fill_tile, fill_tilemap) whose boundaries an agent needs resolved. The agent gets no signal about batch-vs-single or paint-vs-place selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_transparent_colorB

Set which palette index is treated as transparent (indexed sprites only).

ParametersJSON Schema
NameRequiredDescriptionDefault
indexYes
filenameYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false (mutation) and openWorldHint=false, consistent with the 'Set' wording, so no contradiction. The description adds the meaningful constraint that this applies only to indexed sprites, but does not explain what happens to the previously transparent index, validation of the index, or reversibility.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with the scope qualifier front-loaded and zero filler; every element earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a narrow mutation tool with no output schema, the scope constraint plus annotation-driven safety profile is minimally sufficient. Missing prerequisites (indexed mode check) and error behavior keep it from being fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description carries the full burden. It clarifies that 'index' refers to a palette index, but gives no detail on the 'filename' parameter or valid index ranges, leaving half the parameters effectively undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: sets which palette index is treated as transparent, and clarifies scope with '(indexed sprites only)'. An agent can distinguish it from color-editing siblings like set_palette_color, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'indexed sprites only' implies a precondition (sprite must be in indexed color mode), giving implied usage context. However, it offers no when-to-use framing, no alternatives, and no explanation of behavior on non-indexed sprites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

shade_region_by_lightA

Shade a flat region as a lit form, using a ramp and a light direction.

Turns a flat fill into a shaded one: an asymmetric terminator, a darker core away
from the light, and optional rim light. Every output pixel comes from `ramp`.

Scope this to one material. Shading a whole layer flattens materials together: a
sword shaded in one pass turns steel, brass and leather into the same colours, where
three scoped calls keep all three. Scope it by passing `base_color`, by making a
selection first (`select_by_color` is the usual way), or both.

What it cannot do: a distance field measures depth inside a silhouette, so it cannot
invent form boundaries that are not in the outline. An overlapping head and torso
drawn as one flat shape become one mass. Shade them as separate regions.

Args:
    ramp: Colours darkest first, as from `generate_ramp`. Output uses only these.
    base_color: Only shade pixels near this colour. Defaults to every opaque pixel
        in scope, which is usually what you want once a selection is active.
    light_angle: Degrees. 0 is from the right, 90 from above, 135 from the upper
        left, which is the conventional pixel-art key light.
    light_z: How much the light comes from the viewer, 0 to 1. Higher flattens the
        terminator and lights more of the form.
    bulge: How rounded the form reads. 1.0 is sphere-like; lower is flatter, which
        suits cloth and flat panels; higher exaggerates the curvature.
    ambient: Floor brightness in shadow, 0 to 1. Pixel art rarely wants true black
        in shadow, so this sits well above zero by default.
    rim: Light wrapping the edge away from the key, 0 to 1. A little reads as a
        bounce; a lot reads as backlight.
    bias: Shift the whole result along the ramp, in steps. Use this when the result
        is uniformly a shade too dark or light, rather than re-tuning the lighting.
    fill_angle: Degrees, a second light. Omitted by default, which leaves the result
        exactly as it was before this argument existed. Set it opposite `light_angle`
        for the fill or bounce light that keeps a shadow side readable instead of
        letting it go flat dark: the shadow side is where a sprite stops describing
        its form, and one light can only ever leave it at `ambient`.
    fill_strength: How strong the fill is next to the key, 0 to 1 and capped below 1.
        A fill that matches the key cancels the form entirely, because the two
        terminators land on opposite sides of the same shape and sum to a flat fill,
        so the cap refuses the value that destroys what the tool is for. A third to a
        half is the conventional choice.
    tolerance: How close a pixel must be to `base_color` to count as part of the
        region, as a weighted RGB distance. Ignored when `base_color` is omitted.
        **A distance between colours, not between materials.** Two ramps of different
        materials are routinely closer than the default 24: every step of a gold ramp
        generated by `generate_ramp` is within 24 of a step of a brass one, so a pass
        scoped to the brass matched the gold as readily. Art whose fills came from
        `generate_ramp` is exact, so scope it with a tolerance near zero and keep the
        wide default for hand-drawn art that varies.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

The two lights are summed and clamped, not averaged: averaging would dim the key side
as the fill came up, so adding a fill light would make the whole sprite darker and
quietly cost the ramp's top step. Clamping leaves the key side as it was and lightens
only what the key did not reach, which is what a fill light is.

`per_step` in the result counts pixels per ramp entry, which is how to check a fill
actually lightened the shadow side rather than trusting that it did.

`region_components` and `region_bounds` say whether the pass went where it was meant
to, which `region_pixels` cannot: it counts matches without saying whether they are in
one place or four. A call scoped to a 27px coin that comes back with a box spanning 200
pixels of canvas has matched something else as well, and that is the mistake
`tolerance` invites.

Refuses a region with no interior to shade: below roughly 6px across, the distance
field never exceeds a pixel and there is no form to describe. The honest answer
there is two hand-placed pixels, which `draw_pixels` already does.
ParametersJSON Schema
NameRequiredDescriptionDefault
rimNoDefault: 0.0.
biasNoDefault: 0.0.
rampYes
bulgeNoDefault: 1.0.
frameNoDefault: 1.
layerNo
ambientNoDefault: 0.35.
light_zNoDefault: 0.45.
filenameYes
toleranceNoDefault: 24.0.
base_colorNo
fill_angleNo
light_angleNoDefault: 135.0.
fill_strengthNoDefault: 0.35.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say it is a mutating, non-open-world call. The description goes well beyond: it refuses regions below ~6px, caps fill_strength below 1 and explains why, explains that the two lights are summed and clamped rather than averaged, and describes result fields (per_step, region_components, region_bounds) that reveal intent failures. Rich disclosure for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and every section carries real decision-relevant content, but the prose is unusually long for a tool description and a few sentences restate a point already made ('which is what a fill light is'). Dense rather than padded, yet trimming would help scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by explaining what the result fields mean and how to use them to verify the pass. It also covers refusal conditions and multi-light interaction. For a 14-parameter mutation tool, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

At 64% schema coverage the schema itself only supplies defaults. The prose documents all 14 parameters with units, ranges, defaults, and intent — light_angle's degree convention, light_z's flattening effect, bulge's per-material guidance, the tolerance warning about gold vs brass ramps, and fill_angle's omission semantics. This far exceeds what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+mechanism: 'Shade a flat region as a lit form, using a ramp and a light direction.' It then names the resulting visual artifacts (asymmetric terminator, darker core, rim light) and constrains the output palette, which separates it from neighbours like gradient_map, specular_highlight and shift_along_ramp.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit scope guidance ('Scope this to one material') with a concrete failure mode (sword/steel/brass/leather flattening), three named ways to scope (base_color, making a selection, naming select_by_color as the usual route, or both), an explicit 'What it cannot do' section, and an alternative for the refused case (draw_pixels). This is close to ideal when/when-not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

shift_along_rampA

Move pixels along a colour ramp, keeping every one of them on the palette.

This is the operation to use for "put this in shadow", "make the night variant" or
"deepen the shadow side". Each pixel is matched to its nearest ramp entry, moved
`steps` along the ramp, and clamped at the ends, so the result uses only colours
that were already on the ramp.

Prefer this over `adjust_brightness_contrast` for anything that should still look
like pixel art: that tool does colour arithmetic and lands almost every pixel
between palette entries.

Args:
    ramp: The ramp, darkest first, as produced by `generate_ramp`. Order matters:
        negative `steps` moves toward the front of this list.
    steps: How far to move. Negative darkens (toward the front of `ramp`), positive
        lightens. Pixels already at an end stay there rather than wrapping.
    x, y, width, height: Restrict the change to a region. Defaults to the whole
        canvas. Scope this when a sprite has several materials: one ramp applied to
        everything flattens steel, brass and leather into the same colours.
    tolerance: How far a pixel may be from a ramp entry and still be treated as
        belonging to it, as a weighted RGB distance. Pixels further away than this
        are left alone and counted in `pixels_skipped`, so shading one material does
        not disturb its neighbours.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

Returns `pixels_written` and `pixels_skipped`. A high skip count usually means the
ramp does not match the artwork, not that the sprite was already correct.

`pixels_matched` counts the pixels that both matched the ramp and were written, so it
agrees with `pixels_written` rather than counting matches an active selection then
refused.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
rampYes
frameNoDefault: 1.
layerNo
stepsYes
widthNo
heightNo
filenameYes
toleranceNoDefault: 48.0.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnlyHint=false and openWorldHint=false, so the description carries most of the load. It discloses real behavior beyond the safety profile: per-pixel nearest-entry matching, clamping at ramp ends rather than wrapping, the tolerance-based skip rule, that skipped pixels are left untouched and counted, and the default target (top layer, whole canvas). The note that a high skip count usually signals a ramp mismatch rather than correct artwork is genuinely useful diagnostic context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and the alternative-tool guidance are front-loaded before the Args block, which is the right order. The final paragraph on pixels_matched is convoluted — it introduces a third return field not listed in the preceding 'Returns' sentence and references 'an active selection', a concept not otherwise raised. Minor redundancy costs it a point, but the rest is dense and earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description takes on return-value documentation (pixels_written, pixels_skipped, pixels_matched) and does so adequately, and it covers the region/tolerance semantics that the thin schema omits. For a 10-parameter mutation tool at 40% schema coverage this is close to sufficient; only the persistence target implied by filename and any undo/permission behavior go unmentioned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 40% (10 params, mostly undocumented in the schema), so the description must compensate and largely does: ramp ordering and its effect on negative steps, the sign convention for steps with clamp-at-end semantics, region scoping for x/y/width/height, tolerance as a weighted RGB distance with its skip consequence, layer default (top layer), and frame being 1-based. Only filename is left implicit, which is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb and resource ('Move pixels along a colour ramp, keeping every one of them on the palette') and immediately names the sibling it is not: 'Prefer this over `adjust_brightness_contrast`'. An agent can distinguish this from the many other colour/ramp tools (generate_ramp, ramp_between, ramp_from_art) without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete use-case triggers ('put this in shadow', 'make the night variant', 'deepen the shadow side') and an explicit when-not with a named alternative ('anything that should still look like pixel art' → use this, not adjust_brightness_contrast, because that tool lands pixels between palette entries). It also advises scoping x/y/width/height when a sprite has multiple materials.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

smear_frameA

Draw one frame's subject along its own path, so fast movement reads as speed.

Between two frames of a fast movement the eye expects a **smear**: one frame where the
subject is stretched along where it came from, or drawn several times faintly, so the
movement reads as speed rather than as teleportation. `offset_cels` produces the
movement; this describes one frame of it.

The movement vector is taken from the sprite rather than restated by the caller: it is
the shift between the centre of the drawn content on `from_frame` and on `frame`. The
*content* box, not `cel.position`, because any tool here that writes a whole canvas
back leaves the position at (0, 0) on every frame, and a position diff would then read
zero while the drawing plainly moved.

Args:
    frame: The frame to smear. Its own cel is the subject and stays on top, unchanged;
        the trail is drawn behind it. Only this frame is written.
    from_frame: The frame the movement came from. Defaults to the one before `frame`.
    mode: `stretch` draws the subject once, elongated back along the vector and
        thinning to a single pixel at the tip, which is the classic one-frame smear.
        `echo` draws it `steps` times along the vector, each copy a step further down
        the ramp, which is the multiple-exposure smear.
    strength: How far back the smear reaches, as a fraction of the movement. 0.6 is a
        trail that clearly trails; 1.0 reaches all the way to the previous position;
        above 1 it overshoots, which is a real choice an animator makes.
    steps: How many copies `echo` draws. Defaults to 3, and is refused with
        `mode="stretch"` rather than silently ignored.
    ramp: The colours, darkest first, the trail is allowed to use, as `generate_ramp`
        returns them. **Pass this.** Each pixel of the trail is the nearest ramp entry
        to the subject's own colour there, stepped toward the dark end and clamped
        (never wrapped), so `palette_conformance` stays at 1.0, which is the property
        every shading tool here holds to and what a pixel artist actually draws.
        Without it the fallback is opacity, and the fallback **leaves the palette**:
        the trail is then made of colours that are not in the sprite, which is motion
        blur rather than a smear. On an *indexed* sprite the ramp is required rather
        than preferred, and the call is refused without one: an indexed pixel is an
        offset into a palette and carries no alpha, so the fallback would snap every
        copy back to the subject's own colour and draw a solid blob.

Refuses rather than producing a blur of nothing: a frame with no movement to smear
(the two content boxes sit at the same place, and the message says where they are), a
movement too short to smear at this strength (it names the pixels and the length that
would result), `frame` 1 with no earlier frame, `from_frame` equal to `frame`, either
frame undrawn, a group or tilemap layer, a ramp of fewer than two colours or one given
as palette indices, `steps` with `stretch`, and a frame that shares its image with
another frame, since a linked cel would put the smear on every frame in the group and
the whole point is that the unsmeared frames are untouched.

Returns the vector it measured and where it came from, the plots it drew, and the
cel's bounds before and after, so the claim that the smear lies along the movement can
be checked. On an indexed sprite it also returns `trail_on_palette`: what the trail's
own target colours resolve to on this palette, and a warning naming the copies that
will come out the same colour because two of those targets landed on one entry. That
is a different finding from the ramp headroom one above it, which measures the art.
`validate_loop` will now report this frame as breaking the spacing series, which is
correct: a smear frame is one that legitimately does.
ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoDefault: "stretch".stretch
rampNo
frameYes
layerYes
stepsNo
filenameYes
strengthNoDefault: 0.6.
from_frameNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are sparse (readOnlyHint=false, openWorldHint=false), so the description must carry behavioral detail, and it does: it discloses the fallback behavior (opacity leaves the palette), the indexed-sprite refusal, the non-destructive nature (only this frame is written, unsmeared frames untouched), linked-cel refusal, and the return contents. This is far richer than the annotations. No contradiction with readOnlyHint=false (it writes).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well structured and front-loaded with the core purpose, then Args, refusals, and returns. It is long but the length is earned by the number of semantic traps (ramp requirement, indexed sprites, refusals). Some repetition exists but it is largely informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 8 params, no output schema, and sparse annotations, the description covers purpose, modes, required args, fallback behavior, refusals, return contents, and interaction with validate_loop. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, so the description must compensate, and it does for mode, strength, steps, and ramp, explaining semantics and edge cases (steps refused with stretch, ramp required on indexed sprites). It also explains how the vector is derived (content box, not cel.position). However, filename and layer are not addressed, and the frame/from_frame descriptions are brief.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the verb and resource ("Draw one frame's subject along its own path") and distinguishes this tool from its closest sibling: ``offset_cels`` produces the movement; this describes one frame of it. An agent can tell immediately this is a smear-frame tool, not a movement tool, and it references the sibling that creates the movement being smeared.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description names the alternative (`offset_cels`) and distinguishes its role, states which mode to use when (`stretch` vs `echo`), requires a ramp, and describes refusal conditions that effectively serve as when-not-to-use guidance. It explicitly calls out the indexed-sprite case. Usage conditions are well specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sort_paletteA

Sort the palette by "hue", "luminance" (default), "saturation", or "value".

For indexed sprites the pixel indices are remapped so the image looks identical.

ParametersJSON Schema
NameRequiredDescriptionDefault
byNoDefault: "luminance".luminance
reverseNoDefault: false.
filenameYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint=false signalling a mutation, the description adds a genuinely useful behavioral detail beyond annotations: indexed sprites have pixel indices remapped so the image appearance is preserved. It does not say whether the file is modified in place or what happens on non-indexed sprites, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences; the sort keys and default are front-loaded, and the indexed-sprite caveat follows with zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the description covers the options and the key side effect. It leaves minor ambiguity about mutation target/in-place behavior, but is otherwise complete enough to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67% and the schema's 'by' field only states the default. The description supplies the actual valid values (hue, luminance, saturation, value), adding real meaning beyond the schema. 'reverse' remains undocumented in both, so not quite a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (sort) and resource (the palette) plus the sort keys available. It is clearly distinct from siblings like resize_palette, cycle_palette, or load_palette, though it does not explicitly name any alternative for contrast.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description lists valid sort modes and the default, implying the operation's context, but gives no guidance on when to use it versus sibling palette tools or any prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

specular_highlightA

Place a small specular highlight where the light actually reflects at the viewer.

`shade_region_by_light` spreads the ramp's top step over the whole lit side, which is
what a matte surface does and why its output reads as plastic. A specular is the other
thing at the top of the ramp: a two or three pixel glint on the one part of the form
whose normal sends the light straight back at you. It is the difference between a
stone and a gem, and it is small by definition.

Run this **after** `shade_region_by_light`, on the same region and the same light: it
reuses that tool's region mask, distance field and surface normals, so the glint lands
inside the highlight rather than beside it.

**Reserve the top step for it.** Shade the form with the ramp *minus its last entry*
and then call this with the whole ramp:

    shade_region_by_light(f, ramp[:-1], light_angle=135)
    specular_highlight(f, ramp, light_angle=135, size=2)

Shading with the full ramp spreads its top step over the entire lit side, which leaves
nothing above it for a glint to be: the specular then paints pixels the colour they
already are, and that call is refused rather than reported as a success that changed
nothing. The refusal says this and names the way out, so it is a reminder rather than
a puzzle.

Where it goes: on the normal closest to the half-vector between the light and the
viewer, not on the normal closest to the light. That offset toward the viewer is what
makes a specular sit inside the lit side instead of out on its shoulder, and it is the
whole reason this is a separate tool rather than a brighter `bias`.

What it will not do: touch an edge pixel. A specular on the silhouette's border reads
as a hole punched in the form rather than as a shine, so only pixels with all eight
neighbours inside the region are candidates. On a region with no such pixel there is
nothing to put a glint on, and the call is refused with the same message
`shade_region_by_light` gives for a region too thin to shade.

Args:
    ramp: Colours darkest first, the same ramp the form was shaded with.
    light_angle: Degrees, and it must match the shading pass or the glint contradicts
        the form. 0 is from the right, 90 from above, 135 from the upper left.
    light_z: How much the light comes from the viewer, 0 to 1. Match the shading pass.
    size: How many pixels the glint covers. A count, not a radius: a specular is two
        or three pixels on most sprites, and the point of this tool is that it stays
        that small. The pixels are grown outward from the brightest one and stay
        touching, so the result is one glint rather than scattered dots.
    tightness: How narrowly the surface has to face the reflection to count, 0 to 1,
        as a threshold on the normal against the half-vector. High is a tiny hard
        glint on a polished surface; low lets a broader shoulder qualify, from which
        `size` still takes only the best pixels. If nothing clears it the call is
        refused and the message names the best alignment the form actually offers, so
        the number to lower it to is in the error rather than a guess.
    bulge: How rounded the form reads. Match the shading pass, or the normals this
        works from are not the normals the shading used.
    highlight_color: The glint's colour, defaulting to the ramp's top step so
        `palette_conformance` stays at 1.0. This is the flag for metal, which is the
        one material whose specular is genuinely brighter than its own ramp: name a
        near-white there. A colour that is not on `ramp` will drop conformance against
        that ramp, which is the honest trade rather than a bug, and the result says
        whether it happened.
    base_color: Only consider pixels near this colour, as for `shade_region_by_light`.
        Scope it the same way you scoped the shading.
    tolerance: How close a pixel must be to `base_color` to count as part of the
        region. Ignored when `base_color` is omitted.
    layer: Target layer (default: top layer).
    frame: Target frame, 1-based.

Returns `specular_pixels` (how many were placed, which is below `size` when the
eligible area is smaller than the budget), `pixels` (where they went, so a later
`remove_stray_pixels` can be told to protect them), `pixels_changed` (how many were
not already that colour) and `peak_alignment`, the best normal against the
half-vector found anywhere in the region.

Also `region_components` and `region_bounds`, which say whether the region is where it
was meant to be. Worth reading on this tool in particular: the normals come from the
*whole* region, so scoping a glint to a compound object rather than to one of its parts
puts it wherever that object's overall mass bulges. A sword scoped by its whole cell
got its only glint on the leather grip, with none on the blade, and
`specular_pixels: 2` said nothing about that.
ParametersJSON Schema
NameRequiredDescriptionDefault
rampYes
sizeNoDefault: 2.
bulgeNoDefault: 1.0.
frameNoDefault: 1.
layerNo
light_zNoDefault: 0.45.
filenameYes
tightnessNoDefault: 0.7.
toleranceNoDefault: 24.0.
base_colorNo
light_angleNoDefault: 135.0.
highlight_colorNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and openWorldHint=false; the description carries the rest richly — pixel-mutating behavior, refusal semantics for full-ramp and thin-region cases, the no-edge-pixel rule, and palette-conformance tradeoffs. This is far more behavioral context than the annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and structured with headers, code example, and a param list, so it is navigable. It is nonetheless very long (~700 words) for a single tool; some prose, such as the stone/gem and sword anecdotes, could be trimmed without losing actionable guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description fully documents return keys (`specular_pixels`, `pixels`, `pixels_changed`, `peak_alignment`, `region_components`, `region_bounds`) and warns about the compound-object scoping pitfall. An agent has everything needed to call and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 58% and most schema entries are bare defaults, so the description compensates by defining every parameter — units (degrees), ranges (0 to 1), matching requirements against the shading pass, count-vs-radius for `size`, and how `base_color`/`tolerance` interact. This adds substantial meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Place a small specular highlight') and immediately distinguishes itself from the sibling `shade_region_by_light` and from `bias`. An agent can tell exactly what this tool does and what it is not, without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit ordering rule ('Run this **after** `shade_region_by_light`, on the same region and the same light'), prerequisites (reserve the top step of the ramp), and named alternatives. It also routes failure cases clearly, telling the agent when the call is refused and why.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stamp_fileB

Composite another image/sprite file onto a layer at (x, y).

Args:
    source: Path to a .aseprite/.png/.bmp/... to stamp in.
    x, y: Top-left placement on the target canvas.
    source_frame: Which frame of the source to use (1-based).
    opacity: 0-255.
    blend_mode: Blend mode for compositing (normal, multiply, …).
ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
frameNoDefault: 1.
layerNo
sourceYes
opacityNoDefault: 255.
filenameYes
blend_modeNoDefault: "normal".normal
source_frameNoDefault: 1.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=false, so the mutation profile is partly covered, and the description confirms it composites onto a layer. It adds useful detail (opacity 0-255, blend_mode options) but never says whether existing pixels are overwritten or blended, nor whether the target layer must exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence is front-loaded and the Args block is compact, with every line earning its place. Minor redundancy in listing x, y and source_frame that the schema exposes, but overall efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutating tool with no output schema, the description should explain the layer/filename targets and the source_frame vs frame distinction. It covers most compositing knobs but leaves enough gaps that an agent could call it incorrectly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 44%, and the description compensates by explaining x/y as top-left placement and giving opacity range and blend_mode examples. However, it omits the role of filename, layer, and frame, and it documents source_frame without clarifying its relation to the also-present frame parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (composite/stamp) and resource (another image/sprite file onto a layer at x,y), which clearly differentiates it from siblings like import_image and draw_image_base64. It is clear what the tool does, though it doesn't explicitly name the nearest sibling (stamp_pattern).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus alternatives such as stamp_pattern, draw_image_base64, import_image, or add_reference_layer, nor any prerequisites. The agent must infer usage from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stamp_patternB

Tile an image/sprite across a region to fill it with a repeating pattern.

Args:
    source: Image/sprite to tile.
    x, y, width, height: Region to fill (defaults to the whole canvas).
    spacing_x, spacing_y: Gap between tiles.
    opacity, blend_mode: Compositing of each tile.
ParametersJSON Schema
NameRequiredDescriptionDefault
xNoDefault: 0.
yNoDefault: 0.
frameNoDefault: 1.
layerNo
widthNo
heightNo
sourceYes
opacityNoDefault: 255.
filenameYes
spacing_xNoDefault: 0.
spacing_yNoDefault: 0.
blend_modeNoDefault: "normal".normal

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnlyHint=false and openWorldHint=false. The description does not disclose that existing pixels in the region are overwritten, that it operates on a specific file/layer/frame context (three params it never mentions), or how compositing accumulations behave. It adds little beyond the write hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose sentence is front-loaded and the arg list is compact with no wasted prose. Structure is clean, though the args block reads more like a schema echo than value-adding guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-param mutation tool with no output schema, the description covers most parameters and the core behavior, but leaves the file/layer/frame targeting context and the overwrite semantics unaddressed. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 58% and much of it is trivial ('Default: 0.'), so the description carries real weight here: it explains source, the region defaults, spacing, and per-tile opacity/blend. It still omits filename, layer, and frame, which are inferred rather than explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('tile') and resource ('image/sprite'), and clarifies the result ('fill it with a repeating pattern'). This broadly distinguishes it from stamp_file, but it never explicitly contrasts the two (single vs repeating stamp), so differentiation relies on inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description lists arguments but gives no when-to-use guidance, no when-not-to-use conditions, and no pointer to alternatives like stamp_file, fill_area, or fill_checkerboard. An agent must guess which fill/tiling sibling to pick.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

trim_spriteB
Destructive

Auto-crop the canvas to the bounding box of all non-transparent content (across every frame).

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, so the safety profile is already covered by structured data. The description adds real behavioral context by specifying that trimming spans every frame and is driven by non-transparent content, but it omits the critical consequence for a destructive op: that cropped-away pixels and canvas regions are discarded and any frame offsets shift.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the core verb first and the parenthetical scope qualifier second; no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, single-parameter mutation with no output schema, the description covers the operation and its frame-wide scope adequately but leaves out the consequences of the destructive annotation (data loss, positional shifts) and any hint about the filename argument. Adequate but with visible gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one parameter at 0% schema description coverage, the description carries the burden but says nothing about 'filename' — not whether it is a path, a sprite name, or relative to the loaded document. The parameter is conventional enough to be guessed, so this is a gap rather than a failure.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Auto-crop the canvas to the bounding box of all non-transparent content') with a clear scope qualifier ('across every frame'), so the effect is unambiguous. It implicitly differentiates from the sibling crop_sprite by being automatic rather than manual, but never names or contrasts that alternative explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does but gives no guidance on when to use it versus crop_sprite or resize_canvas, no prerequisites, and no exclusions. An agent must infer the use case entirely from the mechanism described.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tween_celsA
Destructive

Scale, turn and fade one drawn cel across frames, in one Aseprite launch.

`offset_cels` moves a cel along a path, which is one of the four things an inbetween
does. This is the other three. The cel on the **first listed frame is the source**,
and every listed frame becomes that one drawing resampled by its share of the change:
frame nine is sampled from the original and not from frame eight, so the rounding
never compounds.

**It interpolates a transform, not pixels.** Blending two different drawings gives a
double exposure, two silhouettes at half strength, which reads as a mistake rather
than as motion. So this takes one drawing, and when two cels genuinely differ in shape
there is no honest automatic inbetween: draw the second pose and tween each one out
from its own extreme, or express the difference as a scale and a turn, which most of
them are.

Args:
    frames: The frames to write, in the order the change passes through them. The
        first is the source, and it is rewritten too when `scale_from`, `rotate_from`
        or `opacity_from` is not the identity.
    scale_from, scale_to: The scale at the first and last frame, on both axes.
    scale_y_from, scale_y_to: Override the vertical scale, for squash and stretch,
        where the two axes go opposite ways (0.7 tall against 1.25 wide is a squash
        that keeps its volume). Unset means the same as the horizontal, which is a
        zoom and not a squash.
    rotate_from, rotate_to: Clockwise degrees at the first and last frame, snapped to
        whole degrees. Quarter turns are exact and lose nothing; sampling within about
        15 degrees of one shuffles the edge pixels rather than turning the shape, and
        the result says so in `warnings` instead of pretending otherwise.
    opacity_from, opacity_to: Cel opacity, 0 to 255. This sets the cel's own opacity
        and never bakes alpha into the pixels: a baked fade invents colours that are
        not on the palette. It is the per-frame `set_cel_opacity` done in one call.
    ease: How the change is *spaced*: `linear`, `ease_in` (starts slow), `ease_out`
        (arrives slow), `ease_in_out`, or `gravity` (accelerating, as a falling object
        does). Easing belongs in one place at a time, and `apply_timing_curve` carries
        the durations.
    anchor: The point the transform holds still, taken from the cel's own drawn
        bounds: `center`, `top`, `bottom`, `left` or `right`. This matters more than it
        looks. A scale about the centre makes a ball grow in every direction; a scale
        about `bottom` makes it squash *onto the ground*, which is the one that reads
        as weight, and `validate_loop`'s contact-edge check then confirms that the
        contact row did not move.

Refuses rather than doing something approximate: fewer than two frames, a frame listed
twice, a from and to that are identical on every channel (each frame would be
rewritten with the drawing the source already holds), a scale of zero or below, a
group or tilemap layer, a source frame with no cel or nothing drawn on it, a frame
whose transform lands entirely off the canvas, and any frame that shares its image
with another frame. That last one is the sharp edge: linked cels share one image, one
position and one opacity, so a tween written into a link group would change every
frame in it. The refusal names the frames and points at `unlink_cels`.

Every listed frame after the first is **overwritten** with the transformed source
rather than blended with what was there. `steps[].bounds` is the written cel's own
content box, so a scale series can be checked instead of trusted: `rendered_monotone`
is that check, and it is omitted while the cel is also rotating, because a turning
shape's bounding box oscillates by design. `steps[].drawn_pixels` is how many opaque
samples that frame took; `pixels_written` is what landed, and the two differ only when
an active selection masked part of it, which `pixels_outside_selection` then reports.

Sampling is nearest-neighbour and copies the source pixel whole, so no colour appears
that the drawing did not already contain and `palette_conformance` is unchanged.
ParametersJSON Schema
NameRequiredDescriptionDefault
easeNoDefault: "linear".linear
layerYes
anchorNoDefault: "center".center
framesYes
filenameYes
scale_toNoDefault: 1.0.
rotate_toNoDefault: 0.0.
opacity_toNoDefault: 255.
scale_fromNoDefault: 1.0.
scale_y_toNo
rotate_fromNoDefault: 0.0.
opacity_fromNoDefault: 255.
scale_y_fromNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnly=false, and the description substantiates the mutation profile in depth: every listed frame after the first is overwritten, the source frame is rewritten when the from-values are non-identity, and a long list of refusal conditions is given (fewer than two frames, duplicate frames, identical from/to, zero scale, group/tilemap layer, linked cels sharing one image, off-canvas transforms). It even discloses backward-looking behavior like warnings on near-quarter rotations and palette_conformance being unchanged. Far beyond what annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose before the args, and the parentheticals (squash example, contact-edge reference) earn their space. It is long, but the length is largely justified by 13 parameters with non-obvious transform semantics and a large refusal surface; a few clauses could be tightened without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the full return burden and does: steps[].bounds, rendered_monotone (and why it is omitted while rotating), drawn_pixels vs pixels_written, and pixels_outside_selection. Combined with the refusal list and mutation semantics, an agent has everything needed to call and interpret it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 62% schema coverage and 13 parameters, the description compensates heavily: it defines frames ordering and source semantics, the scale_y_from/to override for squash-and-stretch, rotate snapping behavior, opacity as per-cel non-baked alpha, the ease enumeration with meanings, and anchor with the bottom-anchor weight argument. This adds substantial meaning the bare 'Default: 1.0' schema entries do not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb triple (scale, turn, fade) on a specific resource (one drawn cel) across frames, and explicitly positions itself against the sibling offset_cels ('this is the other three' inbetweens). An agent can distinguish this from offset_cels, set_cel_opacity, and apply_timing_curve without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Not only says when to use it but when NOT to: interpolating two genuinely different drawings is refused because it produces a double exposure, and the description routes the agent to draw the second pose or express the delta as scale/turn. It also names the boundary with apply_timing_curve (easing vs durations) and offset_cels explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_asset_specA
Read-only

Validate an aseprite_mcp.asset_spec.v1 document (does the spec make sense?).

Checks the schema, kind, canvas, per-kind fields, palette, layers, animations
(`frame_count`, not `frames`), slices, export formats, and that the work the plan
would produce fits one build. `name` may already carry a `.aseprite`/`.ase`
extension: it is normalised, not doubled, so `hero` and `hero.aseprite` name the same
file. Returns a ``workflow_manifest.v1`` (kind ``asset_spec``) with a `validation` block
`{passed, checks, errors, warnings}`. This does **not** check a finished sprite against
the spec - that's a separate future tool.
ParametersJSON Schema
NameRequiredDescriptionDefault
specYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the side-effect profile is covered. The description adds real value beyond that: it names the return artifact (workflow_manifest.v1 with a {passed, checks, errors, warnings} block) and the filename normalisation rule for `.aseprite`/`.ase` extensions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the parenthetical 'does the spec make sense?' anchors intent immediately, followed by the check list, return shape, and the exclusion. It is dense but each clause carries information; the parenthetical is the only mildly expendable element.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only validation tool with a generic nested object parameter and no output schema, the description supplies both the checks performed and the return structure. The only gap is how errors are surfaced (returned in the validation block vs raised), which an agent invoking on invalid input might want to know.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single `spec` parameter is an unrestricted nested object, so the description must carry the burden - and it does, enumerating the spec's constituent parts (schema, kind, canvas, per-kind fields, palette, layers, animations, slices, export formats). It could still be clearer on the frame_count vs frames nuance as an input field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (validate) and resource (aseprite_mcp.asset_spec.v1 document) plus the concrete scope of checks performed. It also distinguishes itself from adjacent tools like plan_asset_spec/build_asset_from_spec and explicitly excludes the 'validate a finished sprite' case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The closing sentence draws a clear boundary ('does not check a finished sprite against the spec - that's a separate future tool'), giving useful when-not guidance. However, it never routes the agent among existing siblings such as validate_sprite_for_game_export or validate_loop, so context is clear but alternatives are not fully enumerated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_loopA
Read-only

Measure an animation and report what is wrong with it, without playing it.

Renders each frame once (one Aseprite launch), then reports per-frame hashes, content
bounding boxes, centroids, the bottom row of the drawn content, the spacing series
between frames, and the durations. On top of the numbers it checks for: a last frame
identical to the first (a loop's wrap showing one image twice), identical adjacent
frames (a pose held by repeating a frame instead of lengthening one), uniform frame
durations, a spacing series that wobbles rather than eases, a contact edge that moves,
and frames with nothing drawn on them.

Args:
    tag: Limit the check to one animation tag's frames. Its repeat setting also
        decides whether the seam is treated as a loop's wrap.
    layer: Measure one layer's cels instead of the flattened frame, so a moving
        character can be measured without the background it sits on.
    loops: Override whether these frames are a cycle. One-shots (attack, hurt, death)
        do not wrap, so a repeated last frame is only a warning for them.
    jitter_tolerance: Pixels of spacing wobble to ignore. Integer cel positions make
        1px unavoidable, so that is the default; pass 0 to see every reversal.

Returns a ``workflow_manifest.v1`` manifest (kind "validation") whose `validation`
section is `{passed, checks[], errors[], warnings[]}` and whose `animation` section
carries every measurement. `validation.passed` is the verdict and is false only for
faults that are wrong whatever the animation is doing; the rest are warnings, because
a bouncing ball is meant to leave the ground and a flicker is meant to go blank.
ParametersJSON Schema
NameRequiredDescriptionDefault
tagNo
layerNo
loopsNo
filenameYes
jitter_toleranceNoDefault: 1.0.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint=false, but the description adds substantial behavioral detail: it renders each frame once via a single Aseprite launch, enumerates the measurement series produced, and critically explains the pass/warning verdict semantics ('passed is false only for faults that are wrong whatever the animation is doing'). This is exactly the context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the purpose and cleanly sectioned into behavior, Args, and Returns. The prose is dense but each sentence (measurements listed, checks listed, verdict rule) earns its place; a slight trim of the enumeration would tighten it further.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description compensates by specifying the returned workflow_manifest.v1 shape and its validation.animation/validation sections in detail. Combined with the arg semantics and check list, an agent has everything needed to call and interpret the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 20% schema coverage, the description does the heavy lifting: tag (frame subset plus seam semantics), layer (isolate cels from background), loops (cycle override), and jitter_tolerance (1px default rationale) all get meaningful explanation beyond the schema. Only filename is left implicit, but it is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Measure an animation and report what is wrong with it, without playing it') and enumerates the concrete faults it detects (duplicate last frame, held frames, uniform durations, wobbling spacing, moving contact edge, empty frames). This distinguishes it clearly from generic siblings like validate_asset_spec or assess_sprite without needing to open any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for the args (when to pass a tag, when to measure a layer, when loops should be overridden) and notes that one-shot animations turn some faults into warnings. However, it never names an alternative tool or states explicit when-not-to-use conditions relative to the many other validate_/assess_ siblings, so usage is implied rather than routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_minecraft_textureA
Read-only

Check a sprite against Minecraft's texture rules before it ships.

Always checks that frames are square and power-of-two. Optionally checks the declared
size, frame count and palette budget; if `tiling` is set, measures the wrap-around
seams of every frame; if `pack_root` is given, confirms an animated texture has its
``.png.mcmeta`` sidecar.

**The seam check** does not require the first and last columns to match - that is only
true of a texture with no variation, and would reject most real block art. It compares
the wrap transition against the texture's own interior column-to-column transitions and
reports the ratio, so a borderline verdict can be judged rather than taken on faith.
`warn_ratio` / `error_ratio` set where "suspect" and "seam" begin.

Returns a ``workflow_manifest.v1`` manifest (kind ``validation``) whose `validation`
block is ``{passed, checks, errors, warnings}``, plus per-frame seam measurements
under `tiling` when the seam check ran.
ParametersJSON Schema
NameRequiredDescriptionDefault
tilingNoDefault: false.
categoryNo
filenameYes
namespaceNoDefault: "minecraft".minecraft
pack_rootNo
warn_ratioNoDefault: 2.0.
error_ratioNoDefault: 4.0.
texture_nameNo
texture_sizeNo
expected_framesNo
max_palette_sizeNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this a safe read (readOnlyHint true, openWorldHint false), so the bar is low, and the description still adds substantial behavioral context: it explains the seam-check methodology, why a naive first/last column match is wrong, how warn_ratio/error_ratio thresholds are interpreted, and what the returned manifest contains. This is unusually rich disclosure for a read-only tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The content is front-loaded with the core purpose, then a compact list of always-on versus optional checks, then a focused explanation of the seam metric. The bolded seam paragraph is longer than strictly necessary but each sentence carries behavioral weight, so little is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and 11 parameters, the description carries heavy burden and does describe the return manifest shape ('validation' block with passed/checks/errors/warnings, plus per-frame seam measurements). It is nearly complete, missing only semantics for the identity/scope params (filename, category, namespace, texture_name).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 36%, so the description must compensate, and it does for the most consequential params: the declared size, frame count and palette budget (texture_size, expected_frames, max_palette_size), tiling, pack_root, and the two ratio thresholds. It leaves filename, category, namespace and texture_name undocumented, so it is not fully complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Check a sprite against Minecraft's texture rules') and enumerates the exact invariants enforced (square power-of-two frames, declared size, frame count, palette budget, tiling seams, .mcmeta sidecar). This clearly separates it from sibling validators like validate_loop or validate_sprite_for_game_export, which target different rule sets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives context ('before it ships') and states precisely when each optional check activates: 'if `tiling` is set', 'if `pack_root` is given', and which checks are always-on versus conditional. It does not name an alternative validator to use instead, so it stops short of full when/when-not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_sprite_for_game_exportA
Read-only

Check whether a sprite is game-ready against the criteria you specify.

Runs a series of checks: does the file open, do dimensions match (exactly or as
a tile multiple), is the colour mode allowed, are frame counts / required animation
tags present, is the background transparent, is the palette within budget, do
expected export files exist, and is sprite-sheet metadata readable, plus soft
warnings for oversized canvases, missing tags, and default/blank layer names.

All criteria are optional; only the ones you pass are enforced. Returns a
``workflow_manifest.v1`` manifest (kind "validation") with a `validation` section
`{passed, checks[], errors[], warnings[]}`. `validation.passed` is the verdict;
`ok` just means the check ran.
ParametersJSON Schema
NameRequiredDescriptionDefault
filenameYes
max_framesNo
min_framesNo
required_tagsNo
tile_multipleNo
expected_widthNo
expected_heightNo
expected_exportsNo
max_palette_sizeNo
spritesheet_dataNo
allowed_color_modesNo
require_transparent_backgroundNoDefault: false.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered, yet the description goes further by enumerating the actual checks performed, noting which produce hard errors versus 'soft warnings', and clarifying that `ok` means the check ran while `validation.passed` is the real verdict. That is meaningful behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two paragraphs, front-loaded with the purpose before the checklist, and the verdict semantics are stated at the end where the reader needs them. It is somewhat dense with the check list, but every item describes a real behavior rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by describing the returned workflow_manifest.v1 structure (kind 'validation', a validation section with passed/checks/errors/warnings) and disambiguating `ok` from `passed`. Combined with the check enumeration and optional-criteria rule, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 8% schema description coverage across 12 parameters, the description carries most of the semantic load, and it does: dimensions (exact or tile multiple), colour mode, frame counts, required tags, transparency, palette budget, expected exports, and spritesheet metadata are all described in prose. It compensates well for the schema gap, though it does not map each check to a specific parameter name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Check') plus resource ('sprite') and scope ('game-ready against the criteria you specify'), and the enumerated checklist pins down exactly what 'validate' means here. It is clearly distinguishable from neighboring validators like validate_minecraft_texture or validate_asset_spec, which have narrower or different targets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clarifies that all criteria are optional and only supplied ones are enforced, which is useful calling guidance, but it never states when to choose this over validate_asset_spec, validate_minecraft_texture, or assess_sprite. Usage is implied by the 'game export' framing rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_pack_mcmetaA
Destructive

Write <pack_root>/pack.mcmeta - the file that makes a directory a resource pack.

Args:
    pack_root: Directory to become the pack root (created if needed).
    mc_version: A known Minecraft version (e.g. "1.21.1") to look the format up from.
        Defaults to 1.21.1.
    pack_format: The format number, overriding `mc_version`. Required for versions
        outside the known table - an unverified guess produces a pack the game
        rejects as incompatible, so it is refused rather than guessed.
    supported_min, supported_max: Optional inclusive `supported_formats` range,
        letting one pack load across several game versions.

Returns a ``workflow_manifest.v1`` manifest (kind ``minecraft_pack``).
ParametersJSON Schema
NameRequiredDescriptionDefault
overwriteNoDefault: false.
pack_rootYes
mc_versionNo
descriptionNoDefault: "Generated by aseprite-mcp".Generated by aseprite-mcp
pack_formatNo
supported_maxNo
supported_minNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, openWorldHint=false. The description adds context beyond that: the directory is created if needed, an unverified format guess is refused rather than written, and the return is a `workflow_manifest.v1` (kind `minecraft_pack`). It stops short of describing overwrite behavior for an existing pack.mcmeta, which is the main gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then a clean Args block and a return note. The 'unverified guess... rejected as incompatible... refused rather than guessed' clause is slightly verbose but carries real behavioral weight, so most sentences earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive file-writing tool with no output schema, the description covers creation side effects, the format-resolution failure mode, cross-version support, and the return manifest. The only meaningful omission is the `overwrite` and `description` parameters, leaving the truncation story incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 29% schema coverage the description must compensate, and it does for 5 of 7 params: pack_root (created if needed), mc_version (a known version, defaults to 1.21.1), pack_format (overrides mc_version, required outside the known table and why), and supported_min/max (inclusive supported_formats range with its effect on cross-version loading). It omits any mention of `overwrite` and `description`, which is why it isn't a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (write) and exact artifact (`<pack_root>/pack.mcmeta`), then explains what that artifact does ('makes a directory a resource pack'). This lets an agent distinguish it from the sibling write_texture_mcmeta and the other mcmeta tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is partial conditional guidance ('pack_format required for versions outside the known table'), but no explicit when-to-use vs alternatives, no mention of when to prefer write_texture_mcmeta, and no prerequisites or exclusions. Usage is largely implied by the mount path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_texture_mcmetaA
Destructive

Write the <texture>.png.mcmeta sidecar for an animated texture.

``export_minecraft_texture`` writes this automatically for a multi-frame sprite; use
this to add or repair one beside a PNG that already exists.

Args:
    texture_path: Path to the ``.png`` (the sidecar goes beside it, same name + .mcmeta).
    frametime: Ticks each frame is shown for (1 tick = 50 ms).
    interpolate: Blend between frames - smooth for gradients, blurry for pixel art.
    frame_order: Optional playback order: frame indices (0-based) or
        ``{"index": i, "time": t}`` objects to hold individual frames longer.
    frame_width, frame_height: Only for non-square frames, which the game otherwise
        infers from the strip's width.

Returns a ``workflow_manifest.v1`` manifest (kind ``minecraft_texture``).
ParametersJSON Schema
NameRequiredDescriptionDefault
frametimeNoDefault: 1.
overwriteNoDefault: false.
frame_orderNo
frame_widthNo
interpolateNoDefault: false.
frame_heightNo
texture_pathYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and destructiveHint=true, so the write/destructive profile is covered. The description adds useful behavior: the file lands beside the PNG with a derived name, and it returns a workflow_manifest.v1. It does not explain the ``overwrite`` behavior that makes the call destructive, which is the one meaningful omission.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose, then a routing sentence pointing at the alternative, then structured Args. The per-argument lines all add semantic value rather than restating names; slightly long but no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by stating the return type (workflow_manifest.v1, kind minecraft_texture). Destination file naming and parameter semantics are complete; the only gap is the unmentioned ``overwrite`` flag, which matters given destructiveHint=true.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 43% schema coverage, the description carries the load well: it explains frametime units (1 tick = 50 ms), the practical meaning of interpolate (smooth gradients vs. blurry pixel art), the ``frame_order`` format including 0-based indices and {"index", "time"} hold objects, and that frame_width/height are only needed for non-square frames. Only ``overwrite`` goes undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and artifact: write the ``<texture>.png.mcmeta`` sidecar for an animated texture. It explicitly distinguishes itself from ``export_minecraft_texture`` (which writes it automatically for multi-frame sprites) and from the sibling ``write_pack_mcmeta`` by naming the texture-level sidecar.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use: 'add or repair one beside a PNG that already exists,' and names the alternative tool that already does this automatically. The condition that selects this tool over export_minecraft_texture is unambiguous.

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.

  1. 156 tool updatesv0.10.0
    • Changedadd_drop_shadow13 fields changed
      • addedInput schema / properties / color / description
        Added value: +"Default: \"#00000080\"."
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / offset_x / description
        Added value: +"Default: 1."
      • removedInput schema / properties / offset_x / title
        Removed value: -"Offset X"
      • addedInput schema / properties / offset_y / description
        Added value: +"Default: 1."
      • removedInput schema / properties / offset_y / title
        Removed value: -"Offset Y"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 255."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • removedInput schema / title
        Removed value: -"add_drop_shadowArguments"
    • Changedadd_frame8 fields changed
      • removedInput schema / properties / copy_from / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / copy_from / default
        Removed value: -null
      • removedInput schema / properties / copy_from / title
        Removed value: -"Copy From"
      • addedInput schema / properties / copy_from / type
        Added value: +"integer"
      • addedInput schema / properties / duration_ms / description
        Added value: +"Default: 100."
      • removedInput schema / properties / duration_ms / title
        Removed value: -"Duration Ms"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"add_frameArguments"
    • Changedadd_group_layer3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / title
        Removed value: -"add_group_layerArguments"
    • Changedadd_layer13 fields changed
      • addedInput schema / properties / blend_mode / description
        Added value: +"Default: \"normal\"."
      • removedInput schema / properties / blend_mode / title
        Removed value: -"Blend Mode"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / group / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / group / default
        Removed value: -null
      • removedInput schema / properties / group / title
        Removed value: -"Group"
      • addedInput schema / properties / group / type
        Added value: +"string"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 255."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • addedInput schema / properties / visible / description
        Added value: +"Default: true."
      • removedInput schema / properties / visible / title
        Removed value: -"Visible"
      • removedInput schema / title
        Removed value: -"add_layerArguments"
    • Changedadd_outline15 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / connectivity / description
        Added value: +"Default: 8."
      • removedInput schema / properties / connectivity / title
        Removed value: -"Connectivity"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / thickness / description
        Added value: +"Default: 1."
      • removedInput schema / properties / thickness / title
        Removed value: -"Thickness"
      • addedInput schema / properties / where / description
        Added value: +"Default: \"outside\"."
      • removedInput schema / properties / where / title
        Removed value: -"Where"
      • removedInput schema / title
        Removed value: -"add_outlineArguments"
    • Changedadd_palette_color3 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"add_palette_colorArguments"
    • Changedadd_reference_layer15 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / image_file / title
        Removed value: -"Image File"
      • addedInput schema / properties / layer_name / description
        Added value: +"Default: \"reference\"."
      • removedInput schema / properties / layer_name / title
        Removed value: -"Layer Name"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 128."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • addedInput schema / properties / scale_to_fit / description
        Added value: +"Default: false."
      • removedInput schema / properties / scale_to_fit / title
        Removed value: -"Scale To Fit"
      • addedInput schema / properties / x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"add_reference_layerArguments"
    • Changedadd_slice39 fields changed
      • removedInput schema / properties / center_height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / center_height / default
        Removed value: -null
      • removedInput schema / properties / center_height / title
        Removed value: -"Center Height"
      • addedInput schema / properties / center_height / type
        Added value: +"integer"
      • removedInput schema / properties / center_width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / center_width / default
        Removed value: -null
      • removedInput schema / properties / center_width / title
        Removed value: -"Center Width"
      • addedInput schema / properties / center_width / type
        Added value: +"integer"
      • removedInput schema / properties / center_x / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / center_x / default
        Removed value: -null
      • removedInput schema / properties / center_x / title
        Removed value: -"Center X"
      • addedInput schema / properties / center_x / type
        Added value: +"integer"
      • removedInput schema / properties / center_y / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / center_y / default
        Removed value: -null
      • removedInput schema / properties / center_y / title
        Removed value: -"Center Y"
      • addedInput schema / properties / center_y / type
        Added value: +"integer"
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / data / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / data / default
        Removed value: -null
      • removedInput schema / properties / data / title
        Removed value: -"Data"
      • addedInput schema / properties / data / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / properties / pivot_x / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / pivot_x / default
        Removed value: -null
      • removedInput schema / properties / pivot_x / title
        Removed value: -"Pivot X"
      • addedInput schema / properties / pivot_x / type
        Added value: +"integer"
      • removedInput schema / properties / pivot_y / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / pivot_y / default
        Removed value: -null
      • removedInput schema / properties / pivot_y / title
        Removed value: -"Pivot Y"
      • addedInput schema / properties / pivot_y / type
        Added value: +"integer"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"add_sliceArguments"
    • Changedadd_tag12 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • addedInput schema / properties / direction / description
        Added value: +"Default: \"forward\"."
      • removedInput schema / properties / direction / title
        Removed value: -"Direction"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / from_frame / title
        Removed value: -"From Frame"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • addedInput schema / properties / repeats
        Added value: +{
        +  "default": 0,
        +  "description": "Default: 0.",
        +  "type": "integer"
        +}
      • removedInput schema / properties / to_frame / title
        Removed value: -"To Frame"
      • removedInput schema / title
        Removed value: -"add_tagArguments"
    • Changedadd_tile9 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"add_tileArguments"
    • Changedadjust_brightness_contrast12 fields changed
      • addedInput schema / properties / brightness / description
        Added value: +"Default: 0."
      • removedInput schema / properties / brightness / title
        Removed value: -"Brightness"
      • addedInput schema / properties / contrast / description
        Added value: +"Default: 0."
      • removedInput schema / properties / contrast / title
        Removed value: -"Contrast"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"adjust_brightness_contrastArguments"
    • Changedadjust_hue_saturation14 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • addedInput schema / properties / hue / description
        Added value: +"Default: 0."
      • removedInput schema / properties / hue / title
        Removed value: -"Hue"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / lightness / description
        Added value: +"Default: 0."
      • removedInput schema / properties / lightness / title
        Removed value: -"Lightness"
      • addedInput schema / properties / saturation / description
        Added value: +"Default: 0."
      • removedInput schema / properties / saturation / title
        Removed value: -"Saturation"
      • removedInput schema / title
        Removed value: -"adjust_hue_saturationArguments"
    • Changedapply_operations5 fields changed
      • addedInput schema / properties / dry_run / description
        Added value: +"Default: false."
      • removedInput schema / properties / dry_run / title
        Removed value: -"Dry Run"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / operations / title
        Removed value: -"Operations"
      • removedInput schema / title
        Removed value: -"apply_operationsArguments"
    • Addedapply_timing_curve
    • Addedassess_sprite
    • Changedbuild_asset_from_spec4 fields changed
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • removedInput schema / properties / spec / title
        Removed value: -"Spec"
      • removedInput schema / title
        Removed value: -"build_asset_from_specArguments"
    • Addedcast_shadow
    • Changedclear_layer8 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"clear_layerArguments"
    • Addedcontact_shadow
    • Changedconvert_background_to_layer2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"convert_background_to_layerArguments"
    • Changedconvert_layer_to_background3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"convert_layer_to_backgroundArguments"
    • Changedcopy_cel5 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / from_frame / title
        Removed value: -"From Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / to_frame / title
        Removed value: -"To Frame"
      • removedInput schema / title
        Removed value: -"copy_celArguments"
    • Changedcreate_character_sprite10 fields changed
      • addedInput schema / properties / base_color / description
        Added value: +"Default: \"#3878c8\"."
      • removedInput schema / properties / base_color / title
        Removed value: -"Base Color"
      • addedInput schema / properties / height / description
        Added value: +"Default: 32."
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • addedInput schema / properties / width / description
        Added value: +"Default: 32."
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / with_placeholder / description
        Added value: +"Default: true."
      • removedInput schema / properties / with_placeholder / title
        Removed value: -"With Placeholder"
      • removedInput schema / title
        Removed value: -"create_character_spriteArguments"
    • Changedcreate_icon_set10 fields changed
      • removedInput schema / properties / columns / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / columns / default
        Removed value: -null
      • removedInput schema / properties / columns / title
        Removed value: -"Columns"
      • addedInput schema / properties / columns / type
        Added value: +"integer"
      • addedInput schema / properties / count / description
        Added value: +"Default: 4."
      • removedInput schema / properties / count / title
        Removed value: -"Count"
      • addedInput schema / properties / icon_size / description
        Added value: +"Default: 16."
      • removedInput schema / properties / icon_size / title
        Removed value: -"Icon Size"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / title
        Removed value: -"create_icon_setArguments"
    • Changedcreate_rpg_item_sheet13 fields changed
      • removedInput schema / properties / columns / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / columns / default
        Removed value: -null
      • removedInput schema / properties / columns / title
        Removed value: -"Columns"
      • addedInput schema / properties / columns / type
        Added value: +"integer"
      • addedInput schema / properties / item_size / description
        Added value: +"Default: 16."
      • removedInput schema / properties / item_size / title
        Removed value: -"Item Size"
      • removedInput schema / properties / items / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / items / default
        Removed value: -null
      • addedInput schema / properties / items / items
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / items / title
        Removed value: -"Items"
      • addedInput schema / properties / items / type
        Added value: +"array"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / title
        Removed value: -"create_rpg_item_sheetArguments"
    • Changedcreate_sprite12 fields changed
      • removedInput schema / properties / background / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / background / default
        Removed value: -null
      • removedInput schema / properties / background / title
        Removed value: -"Background"
      • addedInput schema / properties / background / type
        Added value: +"string"
      • addedInput schema / properties / color_mode / description
        Added value: +"Default: \"rgb\"."
      • removedInput schema / properties / color_mode / title
        Removed value: -"Color Mode"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / title
        Removed value: -"create_spriteArguments"
    • Changedcreate_tilemap_layer17 fields changed
      • removedInput schema / properties / columns / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / columns / default
        Removed value: -null
      • removedInput schema / properties / columns / title
        Removed value: -"Columns"
      • addedInput schema / properties / columns / type
        Added value: +"integer"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / properties / rows / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / rows / default
        Removed value: -null
      • removedInput schema / properties / rows / title
        Removed value: -"Rows"
      • addedInput schema / properties / rows / type
        Added value: +"integer"
      • addedInput schema / properties / tile_height / description
        Added value: +"Default: 16."
      • removedInput schema / properties / tile_height / title
        Removed value: -"Tile Height"
      • addedInput schema / properties / tile_width / description
        Added value: +"Default: 16."
      • removedInput schema / properties / tile_width / title
        Removed value: -"Tile Width"
      • removedInput schema / title
        Removed value: -"create_tilemap_layerArguments"
    • Changedcreate_tileset_project13 fields changed
      • addedInput schema / properties / columns / description
        Added value: +"Default: 4."
      • removedInput schema / properties / columns / title
        Removed value: -"Columns"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • addedInput schema / properties / rows / description
        Added value: +"Default: 4."
      • removedInput schema / properties / rows / title
        Removed value: -"Rows"
      • addedInput schema / properties / tile_size / description
        Added value: +"Default: 16."
      • removedInput schema / properties / tile_size / title
        Removed value: -"Tile Size"
      • removedInput schema / properties / tiles / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "additionalProperties": true,
        -      "type": "object"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / tiles / default
        Removed value: -null
      • addedInput schema / properties / tiles / items
        Added value: +{
        +  "additionalProperties": true,
        +  "type": "object"
        +}
      • removedInput schema / properties / tiles / title
        Removed value: -"Tiles"
      • addedInput schema / properties / tiles / type
        Added value: +"array"
      • removedInput schema / title
        Removed value: -"create_tileset_projectArguments"
    • Changedcrop_sprite6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"crop_spriteArguments"
    • Addedcycle_palette
    • Changeddelete_cel4 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"delete_celArguments"
    • Changeddesaturate10 fields changed
      • addedInput schema / properties / amount / description
        Added value: +"Default: 100."
      • removedInput schema / properties / amount / title
        Removed value: -"Amount"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"desaturateArguments"
    • Addeddeselect
    • Addeddiff_sprites
    • Addeddither_band
    • Changeddraw_brush13 fields changed
      • addedInput schema / properties / anchor / description
        Added value: +"Default: \"center\"."
      • removedInput schema / properties / anchor / title
        Removed value: -"Anchor"
      • removedInput schema / properties / brush / title
        Removed value: -"Brush"
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / points / title
        Removed value: -"Points"
      • removedInput schema / title
        Removed value: -"draw_brushArguments"
    • Changeddraw_curve17 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / control_x / title
        Removed value: -"Control X"
      • removedInput schema / properties / control_y / title
        Removed value: -"Control Y"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / steps / description
        Added value: +"Default: 32."
      • removedInput schema / properties / steps / title
        Removed value: -"Steps"
      • removedInput schema / properties / x0 / title
        Removed value: -"X0"
      • removedInput schema / properties / x1 / title
        Removed value: -"X1"
      • removedInput schema / properties / y0 / title
        Removed value: -"Y0"
      • removedInput schema / properties / y1 / title
        Removed value: -"Y1"
      • removedInput schema / title
        Removed value: -"draw_curveArguments"
    • Changeddraw_ellipse17 fields changed
      • addedInput schema / properties / antialias / description
        Added value: +"Default: false."
      • removedInput schema / properties / antialias / title
        Removed value: -"Antialias"
      • removedInput schema / properties / center_x / title
        Removed value: -"Center X"
      • removedInput schema / properties / center_y / title
        Removed value: -"Center Y"
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / filled / description
        Added value: +"Default: false."
      • removedInput schema / properties / filled / title
        Removed value: -"Filled"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / radius_x / title
        Removed value: -"Radius X"
      • removedInput schema / properties / radius_y / title
        Removed value: -"Radius Y"
      • removedInput schema / title
        Removed value: -"draw_ellipseArguments"
    • Addeddraw_ellipse_in_box
    • Changeddraw_image_base6415 fields changed
      • addedInput schema / properties / blend_mode / description
        Added value: +"Default: \"normal\"."
      • removedInput schema / properties / blend_mode / title
        Removed value: -"Blend Mode"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / image_base64 / title
        Removed value: -"Image Base64"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 255."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"draw_image_base64Arguments"
    • Changeddraw_line17 fields changed
      • addedInput schema / properties / antialias / description
        Added value: +"Default: false."
      • removedInput schema / properties / antialias / title
        Removed value: -"Antialias"
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / pixel_perfect / description
        Added value: +"Default: false."
      • removedInput schema / properties / pixel_perfect / title
        Removed value: -"Pixel Perfect"
      • removedInput schema / properties / x1 / title
        Removed value: -"X1"
      • removedInput schema / properties / x2 / title
        Removed value: -"X2"
      • removedInput schema / properties / y1 / title
        Removed value: -"Y1"
      • removedInput schema / properties / y2 / title
        Removed value: -"Y2"
      • removedInput schema / title
        Removed value: -"draw_lineArguments"
    • Addeddraw_pixel_map
    • Changeddraw_pixels13 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / pixels / title
        Removed value: -"Pixels"
      • removedInput schema / title
        Removed value: -"draw_pixelsArguments"
    • Changeddraw_polyline14 fields changed
      • addedInput schema / properties / closed / description
        Added value: +"Default: false."
      • removedInput schema / properties / closed / title
        Removed value: -"Closed"
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / pixel_perfect / description
        Added value: +"Default: false."
      • removedInput schema / properties / pixel_perfect / title
        Removed value: -"Pixel Perfect"
      • removedInput schema / properties / points / title
        Removed value: -"Points"
      • removedInput schema / title
        Removed value: -"draw_polylineArguments"
    • Changeddraw_rectangle15 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / filled / description
        Added value: +"Default: false."
      • removedInput schema / properties / filled / title
        Removed value: -"Filled"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"draw_rectangleArguments"
    • Changeddraw_symmetric_pixels20 fields changed
      • removedInput schema / properties / axis_x / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / axis_x / default
        Removed value: -null
      • removedInput schema / properties / axis_x / title
        Removed value: -"Axis X"
      • addedInput schema / properties / axis_x / type
        Added value: +"integer"
      • removedInput schema / properties / axis_y / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / axis_y / default
        Removed value: -null
      • removedInput schema / properties / axis_y / title
        Removed value: -"Axis Y"
      • addedInput schema / properties / axis_y / type
        Added value: +"integer"
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / mode / description
        Added value: +"Default: \"horizontal\"."
      • removedInput schema / properties / mode / title
        Removed value: -"Mode"
      • removedInput schema / properties / pixels / title
        Removed value: -"Pixels"
      • removedInput schema / title
        Removed value: -"draw_symmetric_pixelsArguments"
    • Changeddraw_text24 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / font_path / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / font_path / default
        Removed value: -null
      • removedInput schema / properties / font_path / title
        Removed value: -"Font Path"
      • addedInput schema / properties / font_path / type
        Added value: +"string"
      • addedInput schema / properties / font_size / description
        Added value: +"Default: 16."
      • removedInput schema / properties / font_size / title
        Removed value: -"Font Size"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • addedInput schema / properties / spacing / description
        Added value: +"Default: 1."
      • removedInput schema / properties / spacing / title
        Removed value: -"Spacing"
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • addedInput schema / properties / threshold / description
        Added value: +"Default: 128."
      • removedInput schema / properties / threshold / title
        Removed value: -"Threshold"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"draw_textArguments"
    • Changedduplicate_frame3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / title
        Removed value: -"duplicate_frameArguments"
    • Changedduplicate_layer3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"duplicate_layerArguments"
    • Changedexport_frames6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output_pattern / title
        Removed value: -"Output Pattern"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_framesArguments"
    • Changedexport_game_asset_bundle10 fields changed
      • removedInput schema / properties / bundle_name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / bundle_name / default
        Removed value: -null
      • removedInput schema / properties / bundle_name / title
        Removed value: -"Bundle Name"
      • addedInput schema / properties / bundle_name / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_game_asset_bundleArguments"
    • Changedexport_gif7 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_gifArguments"
    • Changedexport_godot_spriteframes17 fields changed
      • addedInput schema / properties / default_loop / description
        Added value: +"Default: true."
      • removedInput schema / properties / default_loop / title
        Removed value: -"Default Loop"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / properties / sheet_output / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / sheet_output / default
        Removed value: -null
      • removedInput schema / properties / sheet_output / title
        Removed value: -"Sheet Output"
      • addedInput schema / properties / sheet_output / type
        Added value: +"string"
      • removedInput schema / properties / texture_res_path / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / texture_res_path / default
        Removed value: -null
      • removedInput schema / properties / texture_res_path / title
        Removed value: -"Texture Res Path"
      • addedInput schema / properties / texture_res_path / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"export_godot_spriteframesArguments"
    • Changedexport_layer9 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_layerArguments"
    • Changedexport_layers8 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / include_hidden / description
        Added value: +"Default: false."
      • removedInput schema / properties / include_hidden / title
        Removed value: -"Include Hidden"
      • removedInput schema / properties / output_pattern / title
        Removed value: -"Output Pattern"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_layersArguments"
    • Addedexport_minecraft_texture
    • Changedexport_onion_skin13 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • addedInput schema / properties / ghost_opacity / description
        Added value: +"Default: 80."
      • removedInput schema / properties / ghost_opacity / title
        Removed value: -"Ghost Opacity"
      • addedInput schema / properties / next / description
        Added value: +"Default: 0."
      • removedInput schema / properties / next / title
        Removed value: -"Next"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / previous / description
        Added value: +"Default: 2."
      • removedInput schema / properties / previous / title
        Removed value: -"Previous"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 4."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_onion_skinArguments"
    • Changedexport_png9 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_pngArguments"
    • Changedexport_slice_metadata8 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / output / default
        Removed value: -null
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / output / type
        Added value: +"string"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • removedInput schema / title
        Removed value: -"export_slice_metadataArguments"
    • Changedexport_spritesheet27 fields changed
      • removedInput schema / properties / data_output / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / data_output / default
        Removed value: -null
      • removedInput schema / properties / data_output / title
        Removed value: -"Data Output"
      • addedInput schema / properties / data_output / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / ignore_layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / ignore_layer / default
        Removed value: -null
      • removedInput schema / properties / ignore_layer / title
        Removed value: -"Ignore Layer"
      • addedInput schema / properties / ignore_layer / type
        Added value: +"string"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / padding / description
        Added value: +"Default: 0."
      • removedInput schema / properties / padding / title
        Removed value: -"Padding"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • addedInput schema / properties / sheet_type / description
        Added value: +"Default: \"packed\"."
      • removedInput schema / properties / sheet_type / title
        Removed value: -"Sheet Type"
      • addedInput schema / properties / split_layers / description
        Added value: +"Default: false."
      • removedInput schema / properties / split_layers / title
        Removed value: -"Split Layers"
      • addedInput schema / properties / split_tags / description
        Added value: +"Default: false."
      • removedInput schema / properties / split_tags / title
        Removed value: -"Split Tags"
      • removedInput schema / title
        Removed value: -"export_spritesheetArguments"
    • Addedexport_spritesheet_packed
    • Changedexport_tag_gif8 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / properties / tag / title
        Removed value: -"Tag"
      • removedInput schema / title
        Removed value: -"export_tag_gifArguments"
    • Changedexport_tags6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / output_pattern / title
        Removed value: -"Output Pattern"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / scale / description
        Added value: +"Default: 1."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"export_tagsArguments"
    • Changedextract_palette12 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / from_image / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / from_image / default
        Removed value: -null
      • removedInput schema / properties / from_image / title
        Removed value: -"From Image"
      • addedInput schema / properties / from_image / type
        Added value: +"string"
      • addedInput schema / properties / include_alpha / description
        Added value: +"Default: false."
      • removedInput schema / properties / include_alpha / title
        Removed value: -"Include Alpha"
      • addedInput schema / properties / max_colors / description
        Added value: +"Default: 256."
      • removedInput schema / properties / max_colors / title
        Removed value: -"Max Colors"
      • addedInput schema / properties / set_as_palette / description
        Added value: +"Default: true."
      • removedInput schema / properties / set_as_palette / title
        Removed value: -"Set As Palette"
      • removedInput schema / title
        Removed value: -"extract_paletteArguments"
    • Changedfill_area11 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"fill_areaArguments"
    • Changedfill_checkerboard24 fields changed
      • removedInput schema / properties / color1 / title
        Removed value: -"Color1"
      • removedInput schema / properties / color2 / title
        Removed value: -"Color2"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / size / description
        Added value: +"Default: 1."
      • removedInput schema / properties / size / title
        Removed value: -"Size"
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • addedInput schema / properties / x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"fill_checkerboardArguments"
    • Changedfill_gradient28 fields changed
      • addedInput schema / properties / angle / description
        Added value: +"Default: 0.0."
      • removedInput schema / properties / angle / title
        Removed value: -"Angle"
      • removedInput schema / properties / colors / title
        Removed value: -"Colors"
      • addedInput schema / properties / dither / description
        Added value: +"Default: false."
      • removedInput schema / properties / dither / title
        Removed value: -"Dither"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • addedInput schema / properties / gradient_type / description
        Added value: +"Default: \"linear\"."
      • removedInput schema / properties / gradient_type / title
        Removed value: -"Gradient Type"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / respect_alpha
        Added value: +{
        +  "default": true,
        +  "description": "Default: true.",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • addedInput schema / properties / x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"fill_gradientArguments"
    • Changedfill_layer9 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"fill_layerArguments"
    • Changedfill_tile7 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / tile_index / title
        Removed value: -"Tile Index"
      • removedInput schema / title
        Removed value: -"fill_tileArguments"
    • Changedfill_tilemap6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / tile_index / title
        Removed value: -"Tile Index"
      • removedInput schema / title
        Removed value: -"fill_tilemapArguments"
    • Changedflatten_sprite2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"flatten_spriteArguments"
    • Changedflip_sprite4 fields changed
      • addedInput schema / properties / direction / description
        Added value: +"Default: \"horizontal\"."
      • removedInput schema / properties / direction / title
        Removed value: -"Direction"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"flip_spriteArguments"
    • Changedgenerate_ramp20 fields changed
      • addedInput schema / properties / apply / description
        Added value: +"Default: \"none\"."
      • removedInput schema / properties / apply / title
        Removed value: -"Apply"
      • removedInput schema / properties / base_color / title
        Removed value: -"Base Color"
      • addedInput schema / properties / easing
        Added value: +{
        +  "default": "linear",
        +  "description": "Default: \"linear\".",
        +  "type": "string"
        +}
      • removedInput schema / properties / filename / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / filename / default
        Removed value: -null
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / filename / type
        Added value: +"string"
      • addedInput schema / properties / hue_shift / description
        Added value: +"Default: 0.0."
      • removedInput schema / properties / hue_shift / title
        Removed value: -"Hue Shift"
      • addedInput schema / properties / light_hue
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / light_range / description
        Added value: +"Default: 0.6."
      • removedInput schema / properties / light_range / title
        Removed value: -"Light Range"
      • addedInput schema / properties / sat_curve
        Added value: +{
        +  "default": "linear",
        +  "description": "Default: \"linear\".",
        +  "type": "string"
        +}
      • addedInput schema / properties / saturation_shift / description
        Added value: +"Default: 0.0."
      • removedInput schema / properties / saturation_shift / title
        Removed value: -"Saturation Shift"
      • addedInput schema / properties / shadow_hue
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / steps / description
        Added value: +"Default: 5."
      • removedInput schema / properties / steps / title
        Removed value: -"Steps"
      • removedInput schema / title
        Removed value: -"generate_rampArguments"
    • Changedget_cel5 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"get_celArguments"
    • Changedget_palette2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"get_paletteArguments"
    • Changedget_pixels18 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / format
        Added value: +{
        +  "default": "rows",
        +  "description": "Default: \"rows\".",
        +  "type": "string"
        +}
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • addedInput schema / properties / layer
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • addedInput schema / properties / x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"get_pixelsArguments"
    • Addedget_properties
    • Addedget_selection
    • Changedget_sprite_info2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"get_sprite_infoArguments"
    • Changedget_tilemap5 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"get_tilemapArguments"
    • Addedglow
    • Addedgradient_map
    • Changedgui_available1 field changed
      • removedInput schema / title
        Removed value: -"gui_availableArguments"
    • Changedhealth_check1 field changed
      • removedInput schema / title
        Removed value: -"health_checkArguments"
    • Changedimport_image4 fields changed
      • removedInput schema / properties / input_image / title
        Removed value: -"Input Image"
      • removedInput schema / properties / output / title
        Removed value: -"Output"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Default: false.",
        +  "type": "boolean"
        +}
      • removedInput schema / title
        Removed value: -"import_imageArguments"
    • Changedimport_reference_sequence11 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / images / title
        Removed value: -"Images"
      • addedInput schema / properties / layer_name / description
        Added value: +"Default: \"rotoscope\"."
      • removedInput schema / properties / layer_name / title
        Removed value: -"Layer Name"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 128."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • addedInput schema / properties / scale_to_fit / description
        Added value: +"Default: false."
      • removedInput schema / properties / scale_to_fit / title
        Removed value: -"Scale To Fit"
      • addedInput schema / properties / start_frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / start_frame / title
        Removed value: -"Start Frame"
      • removedInput schema / title
        Removed value: -"import_reference_sequenceArguments"
    • Changedinvert_colors8 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / title
        Removed value: -"invert_colorsArguments"
    • Addedinvert_selection
    • Addedlink_cels
    • Addedlist_palette_usage
    • Changedlist_slices2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"list_slicesArguments"
    • Changedlist_sprites1 field changed
      • removedInput schema / title
        Removed value: -"list_spritesArguments"
    • Changedload_palette3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / palette_file / title
        Removed value: -"Palette File"
      • removedInput schema / title
        Removed value: -"load_paletteArguments"
    • Changedmake_4_frame_idle_animation10 fields changed
      • addedInput schema / properties / bob_pixels / description
        Added value: +"Default: 1."
      • removedInput schema / properties / bob_pixels / title
        Removed value: -"Bob Pixels"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame_duration_ms / description
        Added value: +"Default: 150."
      • removedInput schema / properties / frame_duration_ms / title
        Removed value: -"Frame Duration Ms"
      • addedInput schema / properties / layer / description
        Added value: +"Default: \"body\"."
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / tag_name / description
        Added value: +"Default: \"idle\"."
      • removedInput schema / properties / tag_name / title
        Removed value: -"Tag Name"
      • removedInput schema / title
        Removed value: -"make_4_frame_idle_animationArguments"
    • Changedmake_8_direction_walk_template12 fields changed
      • removedInput schema / properties / directions / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / directions / default
        Removed value: -null
      • addedInput schema / properties / directions / items
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / directions / title
        Removed value: -"Directions"
      • addedInput schema / properties / directions / type
        Added value: +"array"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame_duration_ms / description
        Added value: +"Default: 120."
      • removedInput schema / properties / frame_duration_ms / title
        Removed value: -"Frame Duration Ms"
      • changedInput schema / properties / frames_per_direction / default
        Previous value: -4New value: +8
      • addedInput schema / properties / frames_per_direction / description
        Added value: +"Default: 8."
      • removedInput schema / properties / frames_per_direction / title
        Removed value: -"Frames Per Direction"
      • removedInput schema / title
        Removed value: -"make_8_direction_walk_templateArguments"
    • Changedmerge_layer_down3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"merge_layer_downArguments"
    • Changedmirror_layer13 fields changed
      • removedInput schema / properties / axis / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / axis / default
        Removed value: -null
      • removedInput schema / properties / axis / title
        Removed value: -"Axis"
      • addedInput schema / properties / axis / type
        Added value: +"integer"
      • addedInput schema / properties / direction / description
        Added value: +"Default: \"horizontal\"."
      • removedInput schema / properties / direction / title
        Removed value: -"Direction"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / source_side / description
        Added value: +"Default: \"first\"."
      • removedInput schema / properties / source_side / title
        Removed value: -"Source Side"
      • removedInput schema / title
        Removed value: -"mirror_layerArguments"
    • Addedmodify_selection
    • Addedmove_frame
    • Changedmove_layer4 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / to_index / title
        Removed value: -"To Index"
      • removedInput schema / title
        Removed value: -"move_layerArguments"
    • Addedoffset_cels
    • Changedopen_in_editor2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"open_in_editorArguments"
    • Addedoutline_smart
    • Changedpaint_tile_pixels11 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / pixels / title
        Removed value: -"Pixels"
      • removedInput schema / properties / tile_index / title
        Removed value: -"Tile Index"
      • removedInput schema / title
        Removed value: -"paint_tile_pixelsArguments"
    • Changedplan_asset_spec2 fields changed
      • removedInput schema / properties / spec / title
        Removed value: -"Spec"
      • removedInput schema / title
        Removed value: -"plan_asset_specArguments"
    • Addedquantize_palette
    • Addedramp_between
    • Addedramp_from_art
    • Changedremove_frame3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / title
        Removed value: -"remove_frameArguments"
    • Changedremove_layer3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / title
        Removed value: -"remove_layerArguments"
    • Changedremove_slice3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / title
        Removed value: -"remove_sliceArguments"
    • Addedremove_stray_pixels
    • Changedremove_tag3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / title
        Removed value: -"remove_tagArguments"
    • Changedrename_layer4 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / new_name / title
        Removed value: -"New Name"
      • removedInput schema / title
        Removed value: -"rename_layerArguments"
    • Changedrender_preview6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • addedInput schema / properties / scale / description
        Added value: +"Default: 8."
      • removedInput schema / properties / scale / title
        Removed value: -"Scale"
      • removedInput schema / title
        Removed value: -"render_previewArguments"
    • Changedreplace_color12 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / from_color / title
        Removed value: -"From Color"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • removedInput schema / properties / to_color / title
        Removed value: -"To Color"
      • addedInput schema / properties / tolerance / description
        Added value: +"Default: 0."
      • removedInput schema / properties / tolerance / title
        Removed value: -"Tolerance"
      • removedInput schema / title
        Removed value: -"replace_colorArguments"
    • Changedresize_canvas6 fields changed
      • addedInput schema / properties / anchor / description
        Added value: +"Default: \"top_left\"."
      • removedInput schema / properties / anchor / title
        Removed value: -"Anchor"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / title
        Removed value: -"resize_canvasArguments"
    • Changedresize_palette3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / size / title
        Removed value: -"Size"
      • removedInput schema / title
        Removed value: -"resize_paletteArguments"
    • Addedreverse_frames
    • Changedrotate_sprite3 fields changed
      • removedInput schema / properties / angle / title
        Removed value: -"Angle"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"rotate_spriteArguments"
    • Changedsave_sprite_as7 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / flatten / description
        Added value: +"Default: false."
      • removedInput schema / properties / flatten / title
        Removed value: -"Flatten"
      • removedInput schema / properties / new_filename / title
        Removed value: -"New Filename"
      • addedInput schema / properties / overwrite / description
        Added value: +"Default: false."
      • removedInput schema / properties / overwrite / title
        Removed value: -"Overwrite"
      • removedInput schema / title
        Removed value: -"save_sprite_asArguments"
    • Addedscaffold_cycle
    • Changedscale_sprite16 fields changed
      • removedInput schema / properties / factor / anyOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / factor / default
        Removed value: -null
      • removedInput schema / properties / factor / title
        Removed value: -"Factor"
      • addedInput schema / properties / factor / type
        Added value: +"number"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • addedInput schema / properties / method / description
        Added value: +"Default: \"nearest\"."
      • removedInput schema / properties / method / title
        Removed value: -"Method"
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • removedInput schema / title
        Removed value: -"scale_spriteArguments"
    • Addedselect_by_color
    • Addedselect_region
    • Changedset_all_frame_durations3 fields changed
      • removedInput schema / properties / duration_ms / title
        Removed value: -"Duration Ms"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"set_all_frame_durationsArguments"
    • Changedset_cel_opacity5 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • removedInput schema / title
        Removed value: -"set_cel_opacityArguments"
    • Changedset_cel_position6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"set_cel_positionArguments"
    • Addedset_cel_z_index
    • Changedset_color_mode6 fields changed
      • removedInput schema / properties / color_mode / title
        Removed value: -"Color Mode"
      • addedInput schema / properties / dithering / description
        Added value: +"Default: \"none\"."
      • removedInput schema / properties / dithering / title
        Removed value: -"Dithering"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / palette_source
        Added value: +{
        +  "default": "from_art",
        +  "description": "Default: \"from_art\".",
        +  "type": "string"
        +}
      • removedInput schema / title
        Removed value: -"set_color_modeArguments"
    • Changedset_frame_duration4 fields changed
      • removedInput schema / properties / duration_ms / title
        Removed value: -"Duration Ms"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / title
        Removed value: -"set_frame_durationArguments"
    • Changedset_layer_properties23 fields changed
      • removedInput schema / properties / blend_mode / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / blend_mode / default
        Removed value: -null
      • removedInput schema / properties / blend_mode / title
        Removed value: -"Blend Mode"
      • addedInput schema / properties / blend_mode / type
        Added value: +"string"
      • removedInput schema / properties / editable / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / editable / default
        Removed value: -null
      • removedInput schema / properties / editable / title
        Removed value: -"Editable"
      • addedInput schema / properties / editable / type
        Added value: +"boolean"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / name / default
        Removed value: -null
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • addedInput schema / properties / name / type
        Added value: +"string"
      • removedInput schema / properties / opacity / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / opacity / default
        Removed value: -null
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • addedInput schema / properties / opacity / type
        Added value: +"integer"
      • removedInput schema / properties / visible / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / visible / default
        Removed value: -null
      • removedInput schema / properties / visible / title
        Removed value: -"Visible"
      • addedInput schema / properties / visible / type
        Added value: +"boolean"
      • removedInput schema / title
        Removed value: -"set_layer_propertiesArguments"
    • Changedset_palette3 fields changed
      • removedInput schema / properties / colors / title
        Removed value: -"Colors"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"set_paletteArguments"
    • Changedset_palette_color4 fields changed
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / index / title
        Removed value: -"Index"
      • removedInput schema / title
        Removed value: -"set_palette_colorArguments"
    • Addedset_properties
    • Changedset_slice31 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / data / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / data / default
        Removed value: -null
      • removedInput schema / properties / data / title
        Removed value: -"Data"
      • addedInput schema / properties / data / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / properties / new_name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / new_name / default
        Removed value: -null
      • removedInput schema / properties / new_name / title
        Removed value: -"New Name"
      • addedInput schema / properties / new_name / type
        Added value: +"string"
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • removedInput schema / properties / x / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / x / default
        Removed value: -null
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / x / type
        Added value: +"integer"
      • removedInput schema / properties / y / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / y / default
        Removed value: -null
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • addedInput schema / properties / y / type
        Added value: +"integer"
      • removedInput schema / title
        Removed value: -"set_sliceArguments"
    • Changedset_tag24 fields changed
      • removedInput schema / properties / color / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / color / default
        Removed value: -null
      • removedInput schema / properties / color / title
        Removed value: -"Color"
      • addedInput schema / properties / color / type
        Added value: +"string"
      • removedInput schema / properties / direction / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / direction / default
        Removed value: -null
      • removedInput schema / properties / direction / title
        Removed value: -"Direction"
      • addedInput schema / properties / direction / type
        Added value: +"string"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / from_frame / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / from_frame / default
        Removed value: -null
      • removedInput schema / properties / from_frame / title
        Removed value: -"From Frame"
      • addedInput schema / properties / from_frame / type
        Added value: +"integer"
      • removedInput schema / properties / name / title
        Removed value: -"Name"
      • removedInput schema / properties / new_name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / new_name / default
        Removed value: -null
      • removedInput schema / properties / new_name / title
        Removed value: -"New Name"
      • addedInput schema / properties / new_name / type
        Added value: +"string"
      • addedInput schema / properties / repeats
        Added value: +{
        +  "type": "integer"
        +}
      • removedInput schema / properties / to_frame / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / to_frame / default
        Removed value: -null
      • removedInput schema / properties / to_frame / title
        Removed value: -"To Frame"
      • addedInput schema / properties / to_frame / type
        Added value: +"integer"
      • removedInput schema / title
        Removed value: -"set_tagArguments"
    • Changedset_tile8 fields changed
      • removedInput schema / properties / column / title
        Removed value: -"Column"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / row / title
        Removed value: -"Row"
      • removedInput schema / properties / tile_index / title
        Removed value: -"Tile Index"
      • removedInput schema / title
        Removed value: -"set_tileArguments"
    • Changedset_tiles6 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • removedInput schema / properties / tiles / title
        Removed value: -"Tiles"
      • removedInput schema / title
        Removed value: -"set_tilesArguments"
    • Changedset_transparent_color3 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / index / title
        Removed value: -"Index"
      • removedInput schema / title
        Removed value: -"set_transparent_colorArguments"
    • Addedshade_region_by_light
    • Addedshift_along_ramp
    • Addedsmear_frame
    • Changedsort_palette6 fields changed
      • addedInput schema / properties / by / description
        Added value: +"Default: \"luminance\"."
      • removedInput schema / properties / by / title
        Removed value: -"By"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / reverse / description
        Added value: +"Default: false."
      • removedInput schema / properties / reverse / title
        Removed value: -"Reverse"
      • removedInput schema / title
        Removed value: -"sort_paletteArguments"
    • Addedspecular_highlight
    • Changedstamp_file17 fields changed
      • addedInput schema / properties / blend_mode / description
        Added value: +"Default: \"normal\"."
      • removedInput schema / properties / blend_mode / title
        Removed value: -"Blend Mode"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 255."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • removedInput schema / properties / source / title
        Removed value: -"Source"
      • addedInput schema / properties / source_frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / source_frame / title
        Removed value: -"Source Frame"
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"stamp_fileArguments"
    • Changedstamp_pattern29 fields changed
      • addedInput schema / properties / blend_mode / description
        Added value: +"Default: \"normal\"."
      • removedInput schema / properties / blend_mode / title
        Removed value: -"Blend Mode"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • addedInput schema / properties / frame / description
        Added value: +"Default: 1."
      • removedInput schema / properties / frame / title
        Removed value: -"Frame"
      • removedInput schema / properties / height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / height / default
        Removed value: -null
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / height / type
        Added value: +"integer"
      • removedInput schema / properties / layer / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / layer / default
        Removed value: -null
      • removedInput schema / properties / layer / title
        Removed value: -"Layer"
      • addedInput schema / properties / layer / type
        Added value: +"string"
      • addedInput schema / properties / opacity / description
        Added value: +"Default: 255."
      • removedInput schema / properties / opacity / title
        Removed value: -"Opacity"
      • removedInput schema / properties / source / title
        Removed value: -"Source"
      • addedInput schema / properties / spacing_x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / spacing_x / title
        Removed value: -"Spacing X"
      • addedInput schema / properties / spacing_y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / spacing_y / title
        Removed value: -"Spacing Y"
      • removedInput schema / properties / width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / width / default
        Removed value: -null
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • addedInput schema / properties / width / type
        Added value: +"integer"
      • addedInput schema / properties / x / description
        Added value: +"Default: 0."
      • removedInput schema / properties / x / title
        Removed value: -"X"
      • addedInput schema / properties / y / description
        Added value: +"Default: 0."
      • removedInput schema / properties / y / title
        Removed value: -"Y"
      • removedInput schema / title
        Removed value: -"stamp_patternArguments"
    • Changedtrim_sprite2 fields changed
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / title
        Removed value: -"trim_spriteArguments"
    • Addedtween_cels
    • Addedunlink_cels
    • Changedvalidate_asset_spec2 fields changed
      • removedInput schema / properties / spec / title
        Removed value: -"Spec"
      • removedInput schema / title
        Removed value: -"validate_asset_specArguments"
    • Addedvalidate_loop
    • Addedvalidate_minecraft_texture
    • Changedvalidate_sprite_for_game_export47 fields changed
      • removedInput schema / properties / allowed_color_modes / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / allowed_color_modes / default
        Removed value: -null
      • addedInput schema / properties / allowed_color_modes / items
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / allowed_color_modes / title
        Removed value: -"Allowed Color Modes"
      • addedInput schema / properties / allowed_color_modes / type
        Added value: +"array"
      • removedInput schema / properties / expected_exports / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / expected_exports / default
        Removed value: -null
      • addedInput schema / properties / expected_exports / items
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / expected_exports / title
        Removed value: -"Expected Exports"
      • addedInput schema / properties / expected_exports / type
        Added value: +"array"
      • removedInput schema / properties / expected_height / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / expected_height / default
        Removed value: -null
      • removedInput schema / properties / expected_height / title
        Removed value: -"Expected Height"
      • addedInput schema / properties / expected_height / type
        Added value: +"integer"
      • removedInput schema / properties / expected_width / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / expected_width / default
        Removed value: -null
      • removedInput schema / properties / expected_width / title
        Removed value: -"Expected Width"
      • addedInput schema / properties / expected_width / type
        Added value: +"integer"
      • removedInput schema / properties / filename / title
        Removed value: -"Filename"
      • removedInput schema / properties / max_frames / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / max_frames / default
        Removed value: -null
      • removedInput schema / properties / max_frames / title
        Removed value: -"Max Frames"
      • addedInput schema / properties / max_frames / type
        Added value: +"integer"
      • removedInput schema / properties / max_palette_size / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / max_palette_size / default
        Removed value: -null
      • removedInput schema / properties / max_palette_size / title
        Removed value: -"Max Palette Size"
      • addedInput schema / properties / max_palette_size / type
        Added value: +"integer"
      • removedInput schema / properties / min_frames / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / min_frames / default
        Removed value: -null
      • removedInput schema / properties / min_frames / title
        Removed value: -"Min Frames"
      • addedInput schema / properties / min_frames / type
        Added value: +"integer"
      • addedInput schema / properties / require_transparent_background / description
        Added value: +"Default: false."
      • removedInput schema / properties / require_transparent_background / title
        Removed value: -"Require Transparent Background"
      • removedInput schema / properties / required_tags / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "type": "string"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / required_tags / default
        Removed value: -null
      • addedInput schema / properties / required_tags / items
        Added value: +{
        +  "type": "string"
        +}
      • removedInput schema / properties / required_tags / title
        Removed value: -"Required Tags"
      • addedInput schema / properties / required_tags / type
        Added value: +"array"
      • removedInput schema / properties / spritesheet_data / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / spritesheet_data / default
        Removed value: -null
      • removedInput schema / properties / spritesheet_data / title
        Removed value: -"Spritesheet Data"
      • addedInput schema / properties / spritesheet_data / type
        Added value: +"string"
      • removedInput schema / properties / tile_multiple / anyOf
        Removed value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedInput schema / properties / tile_multiple / default
        Removed value: -null
      • removedInput schema / properties / tile_multiple / title
        Removed value: -"Tile Multiple"
      • addedInput schema / properties / tile_multiple / type
        Added value: +"integer"
      • removedInput schema / title
        Removed value: -"validate_sprite_for_game_exportArguments"
    • Addedwrite_pack_mcmeta
    • Addedwrite_texture_mcmeta
  2. 113 tool updatesv0.7.0
    • First observedadd_drop_shadow
    • First observedadd_frame
    • First observedadd_group_layer
    • First observedadd_layer
    • First observedadd_outline
    • First observedadd_palette_color
    • First observedadd_reference_layer
    • First observedadd_slice
    • First observedadd_tag
    • First observedadd_tile
    • First observedadjust_brightness_contrast
    • First observedadjust_hue_saturation
    • First observedapply_operations
    • First observedbuild_asset_from_spec
    • First observedclear_layer
    • First observedconvert_background_to_layer
    • First observedconvert_layer_to_background
    • First observedcopy_cel
    • First observedcreate_character_sprite
    • First observedcreate_icon_set
    • First observedcreate_rpg_item_sheet
    • First observedcreate_sprite
    • First observedcreate_tilemap_layer
    • First observedcreate_tileset_project
    • First observedcrop_sprite
    • First observeddelete_cel
    • First observeddesaturate
    • First observeddraw_brush
    • First observeddraw_curve
    • First observeddraw_ellipse
    • First observeddraw_image_base64
    • First observeddraw_line
    • First observeddraw_pixels
    • First observeddraw_polyline
    • First observeddraw_rectangle
    • First observeddraw_symmetric_pixels
    • First observeddraw_text
    • First observedduplicate_frame
    • First observedduplicate_layer
    • First observedexport_frames
    • First observedexport_game_asset_bundle
    • First observedexport_gif
    • First observedexport_godot_spriteframes
    • First observedexport_layer
    • First observedexport_layers
    • First observedexport_onion_skin
    • First observedexport_png
    • First observedexport_slice_metadata
    • First observedexport_spritesheet
    • First observedexport_tag_gif
    • First observedexport_tags
    • First observedextract_palette
    • First observedfill_area
    • First observedfill_checkerboard
    • First observedfill_gradient
    • First observedfill_layer
    • First observedfill_tile
    • First observedfill_tilemap
    • First observedflatten_sprite
    • First observedflip_sprite
    • First observedgenerate_ramp
    • First observedget_cel
    • First observedget_palette
    • First observedget_pixels
    • First observedget_sprite_info
    • First observedget_tilemap
    • First observedgui_available
    • First observedhealth_check
    • First observedimport_image
    • First observedimport_reference_sequence
    • First observedinvert_colors
    • First observedlist_slices
    • First observedlist_sprites
    • First observedload_palette
    • First observedmake_4_frame_idle_animation
    • First observedmake_8_direction_walk_template
    • First observedmerge_layer_down
    • First observedmirror_layer
    • First observedmove_layer
    • First observedopen_in_editor
    • First observedpaint_tile_pixels
    • First observedplan_asset_spec
    • First observedremove_frame
    • First observedremove_layer
    • First observedremove_slice
    • First observedremove_tag
    • First observedrename_layer
    • First observedrender_preview
    • First observedreplace_color
    • First observedresize_canvas
    • First observedresize_palette
    • First observedrotate_sprite
    • First observedsave_sprite_as
    • First observedscale_sprite
    • First observedset_all_frame_durations
    • First observedset_cel_opacity
    • First observedset_cel_position
    • First observedset_color_mode
    • First observedset_frame_duration
    • First observedset_layer_properties
    • First observedset_palette
    • First observedset_palette_color
    • First observedset_slice
    • First observedset_tag
    • First observedset_tile
    • First observedset_tiles
    • First observedset_transparent_color
    • First observedsort_palette
    • First observedstamp_file
    • First observedstamp_pattern
    • First observedtrim_sprite
    • First observedvalidate_asset_spec
    • First observedvalidate_sprite_for_game_export

TDQS

B3.3/5.0

Scored across 156 tools

Disambiguation3/5

Many tools target clearly distinct resources and actions, and the descriptions sharply differentiate most overlaps (e.g. add_outline vs outline_smart vs glow, or add_drop_shadow vs cast_shadow). However, with 156 tools the set has several neighboring export, shading, and drawing families whose boundaries require careful reading, increasing misselection risk.

Naming Consistency4/5

The tool names overwhelmingly use a consistent snake_case verb_noun pattern, such as export_png, add_layer, set_frame_duration, and validate_loop. A few names depart from the pattern or use noun/adjective forms (health_check, gui_available, outline_smart), but the convention remains predictable.

Tool Count1/5

156 tools is far beyond any reasonable scoped surface and falls into the extreme mismatch band (50+ tools). Even for a complex Aseprite integration, this many tools overwhelms selection and context management despite the high quality of individual descriptions.

Completeness5/5

The surface covers the domain extremely thoroughly: sprite creation, layers, frames, tags, palettes, tilemaps, selections, drawing primitives, shading, animation timing, validation, and many export targets including game-engine and Minecraft formats. There are no obvious dead ends for core Aseprite editing or asset-export workflows.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers