Aseprite MCP Server
Provides tools for pixel art creation in Aseprite, including pixel-level drawing, layer and frame management, palette editing, animation tags, image transforms, and canvas preview, enabling AI agents to create and edit sprites programmatically.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Aseprite MCP Servercreate a 16x16 pixel art of a red apple"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🎨 Aseprite MCP Server
Let AI draw pixel art in Aseprite
A Model Context Protocol (MCP) server that enables AI to create pixel art in Aseprite through pixel-level drawing primitives, read canvas screenshots, and iterate until satisfied.
Demo
All three characters were drawn by an AI through this MCP — every pixel written by
apply_operations. The structural work (adding frames, setting durations, building tags,
exporting the sheet) had to go through run_lua when these were made; three of those four now
have ops of their own — add_frames, set_durations, add_tag.
Character | ↓ Down | ↑ Up | ← Left | → Right | Sprite Sheet |
Chibi Knight4 dirs × 6 frames |
|
|
|
|
|
Dark Reaper4 dirs × 6 frames |
|
|
|
|
|
Slime Devourer4 dirs × 5 action frames |
|
|
|
|
|
The first two are walk cycles (the knight steps on anti-phase leg swings; the reaper has no legs, so the walk reads through a travelling wave in the robe hem plus alternating bone feet). The third is an action animation: idle → crouch → lunge with open maw → chomp → swallow, with per-phase frame durations. Each character ships a re-runnable parametric generator and a per-frame pixel check under
demo/<name>/generator/.
This project requires a local installation ofAseprite v1.3+. AI performs drawing via the MCP protocol by calling the Aseprite CLI + Lua scripts.
Two execution modes are supported:
CLI mode (default): Each tool call spawns a headless Aseprite process (
aseprite -b). No UI, state passed via.asefiles.Live mode (WebSocket): AI operates the running Aseprite instance directly through a WebSocket bridge. UI is visible, state is persistent, and you can watch AI draw in real time. See Live Mode Setup below.
Related MCP server: aseprite-mcp
Table of Contents
Tools
Exactly three MCP tools:
Tool | Description |
| Execute a batch of ops inside one transaction — the only mutation entry point. Pass |
| 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, |
| Escape hatch: run arbitrary Lua. Requires |
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, draw_pixel, draw_rect, fill_region, clear_canvas, undo, redo, plus the structural ones — add_frames, set_durations, add_tag and paint_grid.
paint_grid takes a path to a Lua file returning {palette = {b = "#F0A65A"}, rows = {"..bb..", ...}}, one character per pixel, . for transparent. It keeps whole-sprite art out of the tool call: 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.
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.
inspect is the core of the workflow: after drawing, AI calls it to "see" the canvas, analyze it, and decide whether to fix it, forming a draw → inspect → analyze → fix loop.
How to Use
1. Prerequisites
Dependency | Version | Notes |
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. Clone
git clone https://github.com/ZhangDongyang800/Aseprite_MCP.gitThere is no install step: the uv run command in step 3 provisions an isolated environment from pyproject.toml on first launch, with fastmcp / pillow / websockets.
3. Client Configuration
Replace C:\path\to\Aseprite_MCP with where you cloned this repo, and the two env paths with your own.
JSON config (TRAE, Claude Desktop, Cursor, Qoder, …):
{
"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"
}
}
}
}If the client cannot find uv, give command the absolute path to uv. Never fall back to a bare python — Windows shadows it with a Store alias — or to pip install --user, because hosts strip APPDATA and Python then 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 lets AI operate your running Aseprite instance directly — you can watch every stroke happen in real time on your screen, and the sprite state persists across tool calls (no 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 via 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 FolderCopy the entire
extension/folder contents into the scripts folder (or useEdit > Preferences > Extensions > Add Extensionand select theextension/folder)
2. Enable WebSocket mode in 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
You should see an alert: "MCP Bridge: Connected to ws://127.0.0.1:9001".
Now AI can operate Aseprite directly — create a sprite, draw pixels, and you'll see it happen live.
Environment Variables
Variable | Default | Description |
| auto-detected | Path to the Aseprite executable (overrides auto-detection via |
|
| The server's state directory: sessions live in |
|
| Seconds an idle session survives before the cleanup thread removes it |
|
| Execution mode: |
|
| WebSocket server bind address |
|
| WebSocket server port |
Example Prompts
The prompt behind each row of the table at the top.
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!
I've tried it, but I can't guarantee it works perfectly. It still needs more optimization.
License
This project is open-sourced under the MIT License.
Copyright © 2026 ZhangDongyang800
Built with ❤️ for pixel art lovers
Available Tools
3 toolsapply_operationsApply OperationsADestructive
执行一批 Aseprite 操作(唯一变更入口)。
如果 session_id 为空且首个 op 是 create_sprite/open_sprite, 会先创建会话再执行。destructive op 需要 confirmed=true。
成功时 op_results 只保留服务器才知道的新信息(如 open_sprite 读到的实际尺寸), 回显入参的条目会被丢弃;要完整回显或 dry_run 的执行计划就用 verbose=true。
| Name | Required | Description | Default |
|---|---|---|---|
| ops | Yes | ||
| atomic | No | ||
| dry_run | No | ||
| verbose | No | ||
| confirmed | No | ||
| session_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses important behaviors beyond annotations: automatic session creation, the confirmed=true requirement for destructive ops, and the filtering of echo results on success. It also explains the verbose flag for complete echoes and dry_run plans, which is valuable for predicting tool behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, followed by conditional behavior and output semantics. Every sentence adds useful information without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers session handling, confirmation, and result filtering well, but the central ops parameter is only vaguely defined as a batch of operations with examples. With no output schema and no schema-level parameter descriptions, the lack of op structure details and atomic semantics makes it incomplete for reliably invoking the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates by explaining session_id, confirmed, verbose, and dry_run behavior, and by giving examples of ops such as create_sprite/open_sprite. However, the structure of the ops array is not specified, and the atomic parameter is left unexplained, leaving gaps in full parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action: executing a batch of Aseprite operations, and labels itself as the unique mutation entry point. This clearly distinguishes it from sibling tools like inspect and run_lua by emphasizing that it is the only path for changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear contextual guidance: it is the only mutation entry, session creation is automatic for create_sprite/open_sprite, and destructive operations require confirmed=true. However, it does not explicitly name alternatives or state when not to use this tool, so it falls short of a fully explicit when/when-not comparison.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspectInspectARead-only
返回画布预览与量化指标(只读,永不改动文档)。
动画文档用 frame(1 起)指定看哪一帧;越界由 Lua 侧夹到有效范围。
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | composite | |
| frame | No | ||
| scale | No | ||
| session_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and openWorldHint, and the description adds meaningful behavior beyond that: the operation never mutates the document, frame starts at 1, and out-of-range frames are clamped by the Lua side. This gives the agent concrete expectations about side effects and edge-case handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences deliver the purpose, safety characteristic, and frame-handling detail with no redundancy. The key purpose is front-loaded, and every clause contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and the description covers the core use case, safety, and frame behavior. It is incomplete on parameter semantics for session_id, view, and scale, and it does not explain what the returned preview/metrics look like, which matters because there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must compensate, but it only explains frame semantics (1-based, clamped). The required session_id and the view and scale parameters are left undefined, so the agent must guess their meaning or defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and output: it returns a canvas preview and quantitative metrics. The explicit 'read-only, never modifies the document' note clearly sets it apart from the modification-oriented siblings apply_operations and run_lua.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides useful context for animated documents by explaining how to use frame and that out-of-bounds values are clamped. However, it never explicitly tells an agent when to choose inspect over apply_operations or run_lua; the read-only statement only implies the appropriate use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_luaRun LuaADestructive
执行任意 Lua(逃逸舱)。必须 unsafe=true 且 confirmed=true。
与 op 批量同样受快照保护:snippet 失败会回滚文档,成功则把改前状态留作 undo 备份。 CLI 模式下每次调用都会重写 .ase,所以 changed 表示"文档被重写"而非"内容语义变化"。
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | ||
| unsafe | No | ||
| confirmed | No | ||
| session_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds rich behavioral context beyond the destructiveHint/openWorldHint annotations: snippet failure rolls back the document, success creates an undo backup, and CLI mode rewrites .ase so changed means 'rewritten' rather than 'semantically changed.' This is exactly the kind of 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: purpose and safety gate first, then snapshot/rollback behavior, then CLI caveat. Every sentence carries distinct operational value with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description does well to explain safety gating, rollback, undo behavior, and the meaning of changed in CLI mode. The main gaps are the unexplained session_id parameter and reliance on the reader already knowing apply_operations' snapshot behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It gives real meaning to unsafe and confirmed (both must be true) and implies code is the Lua snippet to execute. However, session_id — a required parameter — is never explained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Execute arbitrary Lua (escape hatch)' — a specific verb and resource, and clearly frames this as an escape hatch beyond normal operations. It doesn't explicitly name sibling alternatives, but the scope is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'escape hatch' wording implies use when standard operations or inspection are insufficient, and it explicitly mandates unsafe=true and confirmed=true. However, it never states when to prefer this over apply_operations or inspect, nor gives any when-not-to-use guidance.
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.
3 tool updates
v0.1.0- First observed
apply_operations - First observed
inspect - First observed
run_lua
TDQS
Scored across 3 tools
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.
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.
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.
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
Related MCP Connectors
Generate pixel art sprites, animations, 8-direction rotations and palettes for games.
Generate game assets with AI for 2D games, including sprites, tilesets, and animations.
Build a game's 2D art layer with your agent: characters, animations, tilesets, levels, 5 engines.
AI game assets for agents: consistent sprites, 2D animations, tiles, maps, music and engine exports.
Related MCP Servers
- AlicenseCqualityDmaintenanceEnables AI assistants to control Aseprite for creating pixel art and animated sprites, with 104 tools covering canvas, drawing, animation, palettes, effects, and more.100MIT
- AlicenseNot gradedqualityBmaintenanceEnables 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
- AlicenseAqualityAmaintenanceEnables AI agents to create and edit pixel art in a live Aseprite window, with tools for drawing, selection, transformation, and animation.1849 npm5MIT
- AlicenseNot gradedqualityBmaintenanceEnables 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.1MIT











