AgentStack
MCP verified MIT Self-run

Aseprite Mcp

mcp-malloythedev-aseprite-mcp · by MalloyTheDev

An extensive Model Context Protocol (MCP) server that drives Aseprite headlessly: draw pixel art, build animations, manage layers/frames/tags/cels/palettes/slices/tilemaps, apply effects, render text, and export to PNG/GIF/sprite sheets. 96 tools.

No reviews yet
0 installs
1 views
0.0% view→install

Install

$ agentstack add mcp-malloythedev-aseprite-mcp

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Aseprite Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Aseprite MCP

[](https://github.com/MalloyTheDev/aseprite-mcp/actions/workflows/ci.yml) [](LICENSE) [](https://www.python.org/) [](https://modelcontextprotocol.io)

   

This slime was drawn, shaded, outlined, and animated entirely through MCP tool calls — no manual pixel-pushing.

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](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.

  • 108 tools — including high-level workflow tools that scaffold and validate whole

assets in one call, and a batch op-runner that applies many edits atomically in a single Aseprite process — across sprites, layers, frames, cels, drawing (incl. pixel-perfect & anti-aliased modes), custom brushes & symmetry, palettes (extract/sort/ramps), animation tags, slices/9-patch, effects (gradients/outline/drop-shadow/colour adjustments), text rendering, tilemaps, image stamping, reference/rotoscope layers, transforms, rich export (per-layer/per-tag, sprite sheets, onion-skin), a GUI companion view, and a health_check self-test.

  • 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 tool returns JSON describing the updated sprite.
  • 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.

Showcase

Everything below was produced entirely through MCP tool calls — no manual pixel-pushing.

🟢 Easy — one call scaffolds usable pixel art

createrpgitem_sheet lays out named item slices in one call; filled here with the drawing tools — heart / coin / potion / sword, each its own export-ready slice.

🟡 Medium — animation & tag generation

   

make8directionwalktemplate generates the frames and one animation tag per direction (N / NE / E / SE / S / SW / W / NW) — ready to draw the walk cycle into.

🔴 Hard — the full pipeline: create → animate → validate → export

One agent run: createcharactersprite → draw → make4frameidleanimation → validatespriteforgameexport → exportgameasset_bundle.

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

More examples

 

 

 

A bouncing slime, a skeleton, a tilemap scene from 4 painted tiles, and a hue-shifted generate_ramp palette.


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. Verify it can find Aseprite and run the test suite (tests auto-skip if Aseprite isn't found):

uv run pytest

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. | /workspace | | ASEPRITE_MCP_TIMEOUT | Per-operation timeout in seconds. | 90 | | ASEPRITE_MCP_ALLOW_ABSOLUTE | Allow absolute / workspace-escaping paths (1/true to enable). | off (sandboxed) |

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

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](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 108 tools will be available. Ask the agent to run health_check to confirm Aseprite is wired up correctly.


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. | | 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. | | export_godot_spriteframes | Godot 4 SpriteFrames resource (.tres) + packed sheet — one animation per tag, timed from frame durations. | | export_slice_metadata | Engine-agnostic _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). |

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

  1. create_character_sprite("hero", 32, 32, base_color="#3878c8") — layers + palette + placeholder.
  2. Draw the character on the body / details layers (low-level tools).
  3. make_4_frame_idle_animation("hero.aseprite") — 4-frame loop tagged idle.
  4. validate_sprite_for_game_export("hero.aseprite", expected_width=32, required_tags=["idle"]) — confirm it's game-ready.
  5. export_game_asset_bundle("hero.aseprite", scale=8) — PNG/GIF/sheet+JSON/manifest in hero_bundle/.

Workflow manifest contract

Every workflow tool returns a standardized workflow_manifest.v1 object (defined in [core/manifest.py](src/aseprite_mcp/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{}. File/export entries are {role, path, format, metadata_path?}.

{
  "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 },
  "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/duration · tag add/remove · draw setpixel/line/rectangle/fillrectangle/ellipse/fillellipse/filllayer/clearlayer · slice add/remove · replacecolor.


Tool catalogue

Relative filenames resolve inside the workspace (absolute paths require ASEPRITE_MCP_ALLOW_ABSOLUTE=1 — see [Security](#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). | | save_sprite_as | Save a copy under a new path (optionally flattened). | | set_color_mode | Convert between rgb / indexed / gray (with dithering). | | 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). | | get_pixels | Read composited pixel colours of a region (≤ 64×64 per call). | | 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 | Append a frame (empty, or a copy of another). | | duplicate_frame · remove_frame | Duplicate / delete a frame. | | set_frame_duration · set_all_frame_durations | Set per-frame / uniform durations (ms). |

Cels (a layer's image at a frame)

| Tool | Description | | --- | --- | | get_cel | Inspect a cel (exists, position, bounds, opacity). | | set_cel_position · set_cel_opacity | Move / fade a cel. | | copy_cel · delete_cel | Copy a cel between frames / delete it. |

Animation tags

| Tool | Description | | --- | --- | | add_tag | Tag a frame range with a name, direction, colour. | | set_tag · remove_tag | Edit / delete a tag. |

Drawing

| Tool | Description | | --- | --- | | draw_pixels | Plot individual pixels (per-pixel or shared colour). | | 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. | | 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. |

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). | | add_drop_shadow | Hard drop shadow on a new layer beneath the art. | | replace_color | Swap a colour (with per-channel tolerance). | | 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/`

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.