Skip to main content
Glama

apply

Run multiple sprite edit operations as one transaction: if any op fails, nothing saves and the error names the failing op. Use dry_run to validate changes before writing.

Instructions

Run edit operations on a sprite as ONE transaction: if any op fails nothing is saved and the error names the op. ops_list items are {"op": name, ...arguments}. Frames are 1-based; drawing ops take frame (one) or frames (list, "all", "2-6", "1,3,5-8"); layer defaults to the top image layer. Pixels drawn past the canvas edge are kept in the cel, never clipped. dry_run=true runs everything and reports, but saves nothing.

Ops (name(arguments), ? = optional): add_frames(count?=1, at? (1-based position to insert before; default: append), duration?=100, copy_from?) add_group(name, group?) add_layer(name, group?, opacity?=255, blend?=normal, visible?=true, reference?=false) add_slice(name, x, y, w, h, frame?=1, pivot? [x,y], center? [x,y,w,h], data?) add_tag(name, from, to, direction?=forward, repeat?=0 (0 = loop forever), color?) blink_flash(layer?, frames, color?=#ffffff (white flash) — alternates flash on/off across the frames) clean(specks?=2 (max size of detached islands to delete), orphans?=true, protect? [colors], layer?, frames?) clear(layer?, frames?, region? [x,y,w,h]) copy_cel(layer, from, to (frames), to_layer?, linked?=false, dx?=0, dy?=0) curve(points (3 = quadratic, 4 = cubic Bezier control points), color, layer?, frames?) damage_number(text, x, y (where it pops: its bottom centre), frames, rise?=10, layer?=damage, color?=#fff1a8, bottom_color?=#ff5a3c, outline?=#3a0c14, font?=bold, pop?=true, fade_frames?=2) duplicate_frame(frame, linked?=false) duplicate_layer(layer, name) ellipse(x, y, w, h (bounding box, even sizes fine), color, fill?=true, layer?, frames?, lock_alpha?) erase(x, y, w, h, layer?, frames?) fade(layer, frames, from?=255, to?=0, ease?=linear) fill(x, y, color, tolerance?=0, diagonal?=false, layer?, frames?) fix_glitches(kinds?=[stray, spur, hole, cut, block], master_frame?=1, master_frames? (key drawings), layer?, frames?) flash(color?=#ffffff, amount?=1.0 (1 = solid silhouette), layer?, frames? (hit flash)) flip(axis?=h|v, center? (canvas x for h, y for v; default canvas middle), layer?, frames?) line(x0, y0, x1, y1, color, perfect?=true, layer?, frames?, lock_alpha?) link_cels(layer, source (frame), frames) map(rows (one string per row), legend {char: color}, x?=0, y?=0, layer?, frames?, lock_alpha? ('.' = leave)) move_cel(layer, dx, dy, frames?) move_frame(frame, to) move_layer(layer, to (1 = bottom among its siblings)) outline(color, where?=outside|inside, diagonal?=false, layer?, frames?) palette_lock(palette? [colors] or source? (.aseprite/.png whose colours to use), layer?, frames?) pixels(points [[x,y],...] or [[x,y,color],...], color?, layer?, frames?, lock_alpha?) polyline(points [[x,y],...], color, closed?=false, perfect?=true, layer?, frames?) rect(x, y, w, h, color, fill?=false, layer?, frames?, lock_alpha?) remap(mapping {from_color: to_color}, tolerance?=0, layer?, frames?) remove_frames(frames) remove_layer(layer) remove_slice(name) remove_tag(name) replace_color(from, to, tolerance?=0, layer?, frames?) reverse_frames(frames (an unbroken range)) rotate(degrees (clockwise), pivot [x,y] (canvas), method?=rotsprite|nearest, layer?, frames?) scale(factor (or sx, sy), anchor?=topleft|center|bottom, layer?, frames? (nearest neighbour)) seal_cuts(master_frame?=1, color? (default: the master's darkest colour), layer?, frames? (outline what animating cut open)) set_cel(layer, frames?, opacity?, z?) set_duration(ms, frames?=all) set_durations(durations (list of ms, one per frame from frame 1)) set_layer(layer, name?, opacity?, blend?, visible?, editable?) set_palette(colors [list], replace?=true) shake(layer, frames, amplitude?=1, axis?=x|y|both) squash_stretch(amount (0.2 = squash 20%, -0.2 = stretch), anchor?=bottom|top|left|right, layer?, frames?) stamp(source (png/aseprite path), x?=0, y?=0, source_frame?=1, source_layer?, blend?=true, layer?, frames?) text(text, x, y, color, font?=tiny|bold, bottom_color?, outline?, shadow?, scale?=1, anchor?=topleft|center|bottom|topright, layer?, frames?) tween_move(layer, frames (in order), dx?, dy?, ease?=linear|ease_in|ease_out|ease_in_out|back_out, arc?=0) unlink_cels(layer, frames)

Input Schema

NameRequiredDescriptionDefault
pathYes
dry_runNo
ops_listYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does substantial work: atomic all-or-nothing save semantics, error messages that name the failing op, 1-based frame indexing, default layer targeting, and the notable 'pixels drawn past the canvas edge are kept in the cel, never clipped' trait. It does not state what path expects (file type, is the original overwritten, are backups made), which is a meaningful gap for a mutating tool on a file.

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 long, but the length is earned by a 50+ op catalog, and the critical semantics (transactionality, frame indexing, dry_run) are front-loaded before the catalog. Minor waste exists in self-evident op names and stray formatting artifacts (e.g. the double space in 'frames? (hit flash)'), but nothing structurally misplaced.

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 complex multi-op mutation tool with no annotations and no output schema, the description supplies nearly everything an agent needs: op syntax, argument defaults, indexing conventions, and failure behavior. The remaining gaps — what path refers to and what a successful call returns — are small but real given the absence of an output 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 0%, yet the description fully specifies ops_list's item contract ({"op": name, ...arguments}) and documents dozens of per-op arguments with defaults and formats, plus dry_run's exact behavior. The one missing piece is 'path', which is never explained in text and is completely undocumented in the schema — the only thing keeping this from 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?

The opening sentence gives a specific verb and resource ('Run edit operations on a sprite') plus a scope qualifier ('as ONE transaction'), and the op catalog makes the boundary with read-only siblings like view/check_animation/lint obvious. It stops short of naming a sibling directly, so it is clear but not fully differentiated in-text.

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 through the transaction contract and the 'dry_run=true runs everything and reports, but saves nothing' hint, which is a real decision rule. However, there is no explicit when-not guidance and no named alternative (e.g. use sprite_new to create, export to write out), so an agent must infer when this is the right entry point versus sibling tools.

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