Skip to main content
Glama
Aseprite MCP Server

Aseprite MCP Server

Aseprite MCP Server

An MCP server for drawing pixel art in Aseprite through pixel-level operations, canvas inspection, and iterative correction.

Python FastMCP Aseprite

Quick start

Prerequisites: Aseprite v1.3+ installed (note the full path to its executable) and uv (Windows winget install astral-sh.uv, macOS brew install uv, or curl -LsSf https://astral.sh/uv/install.sh | sh). uv run creates an isolated environment from pyproject.toml and installs fastmcp, pillow, and websockets; no separate pip step or virtualenv is needed.

git clone https://github.com/ZhangDongyang800/Aseprite_MCP.git
cd Aseprite_MCP
uv run -q python -c "import json, os; print(json.dumps({'mcpServers': {'aseprite': {'command': 'uv', 'args': ['run', '--directory', os.getcwd(), 'server.py'], 'env': {'ASEPRITE_PATH': 'C:/Program Files/Aseprite/aseprite.exe'}}}}, indent=2))"

The last command prints a client configuration with your clone path filled in and Windows backslashes escaped for JSON. Set ASEPRITE_PATH to your Aseprite executable; if auto-detection finds it, the env block can be omitted. TRAE, Claude Desktop, Cursor, and Qoder use the same configuration.

To verify the setup, ask the client: "create a new 8x8 canvas, flood it red, then inspect it". A red square and coverage 1.0 indicate a working server.

Aseprite must be installed locally. The server supports two execution modes:

  • CLI mode (default): each tool call starts a headless Aseprite process (aseprite -b). No UI; state is passed through .ase files.

  • Live mode (WebSocket): operations run against a running Aseprite instance, with visible UI and persistent state. See Live mode.

Related MCP server: aseprite-mcp

Demo

The sprites and tileset below were generated through this MCP server. Pixels are written by apply_operations (paint_grid), and frame structure is created through ops. Each demo includes a re-runnable generator under demo/<name>/generator/.

Character

↓ Down

↑ Up

← Left

→ Right

Sprite Sheet

Chibi Knight4 dirs × 6 frames

Dark Reaper4 dirs × 6 frames

Slime Devourer4 dirs × 5 frames

The first two are walk cycles. The third is an action animation with per-phase frame durations: idle → crouch → lunge with open maw → chomp → swallow.

Terrain tileset

Tileset sheet

Composed scene

Water loop

Wilderness 47-blob228 slots · 32px · 12x19

The wilderness tileset covers four overlay terrains (dirt road, sand, water, and stone), each with a complete 47-tile blob transition matrix, plus interior variants and 24 object tiles in a 384x608 sheet. Water is a four-frame loop. The scene is composed by looking up tiles from a terrain map rather than by hand placement, so a missing tile is reported immediately.

Table of contents

Tools

The server exposes three MCP tools.

Tool

Description

apply_operations

Execute a batch of ops inside one transaction — the only mutation entry point. Pass session_id + ops[]; dry_run=true validates without side effects; confirmed=true is required when the batch contains a destructive op (clear_canvas, delete_layer, close_session). If session_id is omitted and the first op is create_sprite / open_sprite, a session is created automatically.

inspect

Read-only perception: returns a canvas preview image plus quantitative metrics (palette, color count, bounding box, coverage, semi-transparent and isolated pixels). On animated documents, frame=N steps through frames one at a time. Never modifies the document.

run_lua

Escape hatch: run arbitrary Lua. Requires unsafe=true and confirmed=true.

Ops are named operations registered in src/v2/ops/ (Pydantic parameter models) with their Lua implementations in scripts/ops_*.lua. Built-in ops: create_sprite, open_sprite, save_sprite, close_session, add_layer, set_layer, delete_layer, set_palette, draw_pixel, draw_rect, draw_line, draw_ellipse, fill_region, clear_canvas, undo, redo, plus the structural ops add_frames, set_durations, add_tag, paint_grid, and export (png/gif/sheet/frames; it writes artifact files but never changes the document).

paint_grid takes a path to a Lua file returning {palette = {b = "#F0A65A"}, rows = {"..bb..", ...}}, one character per pixel, with . for transparent. A 32×32 four-frame sheet costs a few hundred tokens through paint_grid instead of tens of thousands as draw_pixel ops, and still runs validated and inside the same rollback as everything else.

export writes the deliverable without touching the document: {"op": "export", "format": "gif", "output": "walk.gif"}; format="png" needs a frame on multi-frame sprites, while format="frames" writes name1.png…nameN.png and format="sheet" takes layout / columns / padding / scale. Output paths are resolved to absolute; put export last (or in its own batch) so a later failing op cannot leave an uncommitted artifact.

apply_operations(ops=[
    {"op": "create_sprite", "width": 32, "height": 32},
    {"op": "draw_rect", "x": 4, "y": 4, "width": 24, "height": 24, "color": "#E74C3C", "filled": True},
    {"op": "draw_pixel", "x": 16, "y": 6, "color": "#FFFFFF"},
])

All drawing ops accept layer / frame (1-based, default 1/1). A batch runs inside one app.transaction, so atomic=true (the default) rolls the whole batch back if any op fails. With atomic=false the ops that worked are saved and listed one by one, the failed one keeps its reason, and the envelope returns ok=true with a partial success: N of M ops ... warning.

After drawing, call inspect to review the canvas and decide whether to correct it. This forms a draw → inspect → correct loop.

How to use

1. Prerequisites

Dependency

Version

Notes

uv

any recent

manages Python and the dependencies for you

Aseprite

v1.3+

note the full path to the executable, not the folder holding it

Install uv with winget install astral-sh.uv (Windows), brew install uv (macOS), or curl -LsSf https://astral.sh/uv/install.sh | sh.

2. Client configuration

The quick-start command prints a ready-to-paste configuration with your own paths filled in and escaped. By hand it looks like:

{
  "mcpServers": {
    "aseprite": {
      "command": "uv",
      "args": ["run", "--directory", "C:\\path\\to\\Aseprite_MCP", "server.py"],
      "env": {
        "ASEPRITE_PATH": "C:\\Program Files\\Aseprite\\aseprite.exe",
        "ASEPRITE_WORK_DIR": "C:\\ase_work"
      }
    }
  }
}

ASEPRITE_WORK_DIR is optional (it defaults to the repo's own work/). An ASCII-only path is recommended but not required: current Aseprite builds (1.3.17 verified) load scripts from non-ASCII paths, but older builds and some console code pages fail there with a "can't load … (lua)" error that resembles a build without the Lua engine. The server prints a note at startup when the path is non-ASCII.

If the client cannot find uv, give command the absolute path to uv. Avoid a bare python (the Windows Store alias intercepts it) and pip install --user (some hosts strip APPDATA, so Python cannot find the packages). To skip uv entirely, install into a virtualenv and point command at that interpreter:

python -m venv .venv                                  # Windows, if `python` is missing: py -3 -m venv .venv
.venv/Scripts/python.exe -m pip install -e .          # Windows
.venv/bin/python -m pip install -e .                  # macOS / Linux

Live mode (optional, WebSocket)

Live mode operates on the Aseprite instance you have open. Drawing is visible as it happens, and sprite state persists across tool calls, avoiding repeated file open/save overhead.

How it works

┌─────────┐    MCP (stdio)    ┌──────────────┐   WebSocket    ┌──────────────────┐
│  AI/TRAE │ ───────────────► │ Python MCP   │ ─────────────► │ Aseprite Extension│
│          │ ◄─────────────── │ Server       │ ◄──────────── │ (WebSocket client) │
└─────────┘                   └──────────────┘                └──────┬───────────┘
                                                                     │ Lua app.* API
                                                                     ▼
                                                              ┌──────────────┐
                                                              │ Visible Aseprite │
                                                              │ Sprite + UI      │
                                                              └──────────────┘

The Python MCP server starts a WebSocket server on 127.0.0.1:9001. The Aseprite extension connects to it as a client. Each MCP tool call is forwarded to Aseprite over WebSocket, executed through the existing Lua scripts, and the result is sent back.

Setup

1. Install the Aseprite extension

The extension is in the extension/ folder of this repo. Install it via:

  • Open Aseprite → File > Scripts > Open Scripts Folder

  • Copy the entire extension/ folder contents into the scripts folder (or use Edit > Preferences > Extensions > Add Extension and select the extension/ folder)

2. Enable WebSocket mode in the MCP config

Add ASEPRITE_MCP_MODE=ws to the env section of your MCP server config:

{
  "mcpServers": {
    "aseprite": {
      "command": "uv",
      "args": ["run", "--directory", "C:\\path\\to\\Aseprite_MCP", "server.py"],
      "env": {
        "ASEPRITE_PATH": "C:\\Program Files\\Aseprite\\aseprite.exe",
        "ASEPRITE_WORK_DIR": "C:\\ase_work",
        "ASEPRITE_MCP_MODE": "ws",
        "ASEPRITE_WS_HOST": "127.0.0.1",
        "ASEPRITE_WS_PORT": "9001"
      }
    }
  }
}

3. Connect Aseprite

With the MCP server running, open Aseprite and click:

File > Scripts > MCP Bridge: Toggle Connection

Aseprite reports "MCP Bridge: Connected to ws://127.0.0.1:9001" when the connection succeeds; drawing calls then run against the open document.

Environment variables

Variable

Default

Description

ASEPRITE_PATH

auto-detected

Path to the Aseprite executable (overrides auto-detection via PATH and common install locations)

ASEPRITE_WORK_DIR

<repo>/work

The server's state directory: sessions live in <work>/sessions/<uuid>/ and expire after ASEPRITE_SESSION_TIMEOUT. Absolute by default; non-ASCII paths work on current Aseprite builds, but older ones reject them and report a Lua load error

ASEPRITE_SESSION_TIMEOUT

3600

Seconds an idle session survives before the cleanup thread removes it

ASEPRITE_TIMEOUT

30

Seconds one Aseprite call may take. Raise it for big canvases (fill_region on 4096², blur); a timeout rolls the batch back and reports the failure

ASEPRITE_MCP_MODE

cli

Execution mode: cli or ws

ASEPRITE_WS_HOST

127.0.0.1

WebSocket server bind address

ASEPRITE_WS_PORT

9001

WebSocket server port

Example prompts

Example prompts for the demos above.

Chibi Knight · 4 directions × 6 frames · 32x32

Use Aseprite MCP to generate a pixel art sprite sheet of a brave knight in silver armor holding a long sword, red plume and red cape. Four-direction walk cycle (down, up, left, right), 6 frames per direction, 32x32, flat colors, transparent background, 1px dark outline, light from the top-left.

Dark Reaper · 4 directions × 6 frames · 32x32

Use Aseprite MCP to generate a pixel art sprite sheet of a dark reaper in a tattered black robe wielding a giant scythe, glowing red eyes under the hood. Four-direction walk cycle (down, up, left, right), 6 frames per direction, 32x32, flat colors, transparent background, 1px dark outline.

Slime Devourer · 4 directions × 5 frames · 32x32

Use Aseprite MCP to generate a pixel art sprite sheet of a slime monster that devours its prey — green blob body, huge jaws, fangs. Four-direction devour animation (down, up, left, right), 5 frames per direction: idle → crouch → lunge with open maw → chomp → swallow. 32x32, flat colors, transparent background, sprite sheet layout.

Contributing

Issues and pull requests are welcome. Please include reproduction steps and your Aseprite version.

License

This project is open-sourced under the MIT License.

Copyright © 2026 ZhangDongyang800

Available Tools

3 tools
apply_operationsApply OperationsA
Destructive

执行一批 Aseprite 操作(唯一变更入口)。

如果 session_id 为空且首个 op 是 create_sprite/open_sprite, 会先创建会话再执行。destructive op 需要 confirmed=true。

成功时 op_results 只保留服务器才知道的新信息(如 open_sprite 读到的实际尺寸), 回显入参的条目会被丢弃;要完整回显或 dry_run 的执行计划就用 verbose=true。

Inputs: ops (required), atomic, dry_run, verbose, +2 more.

inspectInspectA
Read-only

返回画布预览与量化指标(只读,永不改动文档)。

动画文档用 frame(1 起)指定看哪一帧;越界由 Lua 侧夹到有效范围。

Inputs: session_id (required), view, frame, scale.

run_luaRun LuaA
Destructive

执行任意 Lua(逃逸舱)。必须 unsafe=true 且 confirmed=true。

与 op 批量同样受快照保护:snippet 失败会回滚文档,成功则把改前状态留作 undo 备份。 CLI 模式下每次调用都会重写 .ase,所以 changed 表示"文档被重写"而非"内容语义变化"。

Inputs: code (required), session_id (required), unsafe, confirmed.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 3 tools

    Disambiguation5/5

    The three tools have clearly distinct purposes: apply_operations is the sole programmatic mutation entry point, run_lua is an escape hatch for arbitrary scripts, and inspect is strictly read-only. No two tools overlap in functionality, making selection unambiguous for an agent.

    Naming Consistency5/5

    All names follow a consistent lowercase snake_case pattern starting with a verb: apply_operations, run_lua, inspect. The convention is uniform and predictable, with no mixed styles or ambiguous verbs.

    Tool Count5/5

    With only 3 tools, the surface is minimal but perfectly aligned with the server's purpose. The heavy lifting is encapsulated inside operation types for apply_operations, so the small count is intentional and well-scoped rather than sparse.

    Completeness5/5

    The tool set covers the full lifecycle: mutate (apply_operations), arbitary scripting (run_lua), and read/analyze state (inspect). Supporting operations like create_sprite and open_sprite are exposed as ops within apply_operations, so no critical gap exists for typical Aseprite workflows.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to drive Aseprite for pixel-art creation, including sprite setup, grid-based drawing, layer/frame/tag management, reference image import, and export, with rendered previews after every mutation.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to create and edit pixel art in a live Aseprite window, with tools for drawing, selection, transformation, and animation.
      18
      819 npm
      571
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI coding agents to create, draw, and refine Aseprite documents through deterministic canvas, layer, frame, tag, and palette tools, with pixel analyzers, style validation, and preview/diff visual feedback. It also supports spritesheet and animated GIF export, producing multi-layer game-ready assets.
      1
      MIT