Skip to main content
Glama

aseprite-mcp

MCP server for safe local automation of Aseprite. It exposes a focused set of Model Context Protocol tools that create, inspect, edit, save, and export pixel art documents through the official Aseprite CLI and controlled Lua scripts.

The current implementation is a working MVP for the prompt's Phase 3. It intentionally avoids generic run_lua, execute_command, or shell tools.

Requirements

  • Node.js 20+

  • Aseprite installed locally

  • A client that can launch MCP servers over stdio

Official references used for this implementation:

Related MCP server: aseprite-mcp

Install

npm install
npm run build

Configure

Copy the example config if you want file-based configuration:

cp aseprite-mcp.config.example.json aseprite-mcp.config.json

On Windows PowerShell:

$env:ASEPRITE_PATH = "C:\Program Files\Aseprite\Aseprite.exe"
$env:ASEPRITE_MCP_ALLOWED_DIRECTORIES = "C:\Users\Usuario\Documents\MAX\PROYECTOS"

Supported environment variables:

  • ASEPRITE_PATH

  • ASEPRITE_MCP_ALLOWED_DIRECTORIES

  • ASEPRITE_MCP_TEMP_DIRECTORY

  • ASEPRITE_MCP_MAX_WIDTH

  • ASEPRITE_MCP_MAX_HEIGHT

  • ASEPRITE_MCP_MAX_FRAMES

  • ASEPRITE_MCP_PROCESS_TIMEOUT

  • ASEPRITE_MCP_ALLOW_OVERWRITE

  • ASEPRITE_MCP_LOG_LEVEL

Run

npm run build
npm start

The server uses stdio, so it is meant to be launched by an MCP client.

Codex MCP Example

See examples/codex.mcp.json.

{
  "mcpServers": {
    "aseprite": {
      "command": "node",
      "args": ["C:/absolute/path/to/aseprite-mcp/dist/index.js"],
      "env": {
        "ASEPRITE_PATH": "C:/Program Files/Aseprite/Aseprite.exe",
        "ASEPRITE_MCP_ALLOWED_DIRECTORIES": "C:/Users/Usuario/Documents/MAX/PROYECTOS"
      }
    }
  }
}

Claude Desktop Example

See examples/claude-desktop.mcp.json.

Implemented Tools

  • aseprite_create_sprite

  • aseprite_get_document_info

  • aseprite_list_layers

  • aseprite_list_frames

  • aseprite_set_pixels

  • aseprite_fill_region

  • aseprite_clear_region

  • aseprite_draw_line

  • aseprite_draw_rectangle

  • aseprite_create_frame

  • aseprite_create_tag

  • aseprite_get_animation_info

  • aseprite_set_frame_duration

  • aseprite_set_tag_range

  • aseprite_set_tag_direction

  • aseprite_get_palette

  • aseprite_export_palette

  • aseprite_create_dual_grid_tileset

  • aseprite_save_document

  • aseprite_export_png

  • aseprite_export_spritesheet

Resources

  • aseprite://capabilities

  • aseprite://config

  • aseprite://runtime

Prompts

  • create-pixel-character

  • prepare-spritesheet-for-unity

Example Calls

Create a 32x32 sprite:

{
  "width": 32,
  "height": 32,
  "colorMode": "rgb",
  "frameCount": 1,
  "frameDurationMs": 100,
  "outputPath": "examples/output/player.aseprite",
  "overwrite": true
}

Draw several pixels:

{
  "filePath": "examples/output/player.aseprite",
  "frameIndex": 1,
  "layerIndex": 1,
  "pixels": [
    { "x": 1, "y": 2, "color": "#FF0000FF" },
    { "x": 2, "y": 2, "color": "#00FF00FF" }
  ],
  "createBackup": true
}

Create four frames:

{
  "width": 32,
  "height": 32,
  "frameCount": 4,
  "frameDurationMs": 120,
  "outputPath": "examples/output/player.aseprite",
  "overwrite": true
}

Create the idle tag:

{
  "filePath": "examples/output/player.aseprite",
  "name": "idle",
  "fromFrame": 1,
  "toFrame": 4,
  "direction": "ping-pong"
}

Export a spritesheet:

{
  "filePath": "examples/output/player.aseprite",
  "sheetPath": "examples/output/player.png",
  "dataPath": "examples/output/player.json",
  "sheetType": "horizontal",
  "listLayers": true,
  "listTags": true,
  "overwrite": true
}

Create a dual-grid tileset:

{
  "outputPath": "examples/output/dual-grid-grass.aseprite",
  "metadataPath": "examples/output/dual-grid-grass.json",
  "tileSize": 16,
  "columns": 4,
  "layoutPreset": "template",
  "referenceStencil": [
    "00011000",
    "10011111",
    "10011111",
    "01111110",
    "01111110",
    "00000110",
    "00000110",
    "00110000"
  ],
  "terrainColor": "#49AD52FF",
  "backgroundColor": "#00000000",
  "gridColor": "#FF55D6FF",
  "guideMode": "none",
  "labelMode": "quadrants",
  "styleMode": "basic",
  "requireUniqueTiles": true,
  "overwrite": true
}

The default template layout follows a dual-grid stencil with 16 unique tile patterns. Material pixels are placed according to a pixel-level template grid, not by row-major binary mask order. referenceStencil is optional; when provided, it must be a rectangular 0/1 matrix whose width is divisible by columns and whose height is divisible by the tileset rows. requireUniqueTiles rejects repeated patterns. labelMode: "quadrants" overlays G for ground and V for void in each tile quadrant, useful for debugging the template before art styling. Use styleMode: "grass" to render styled grass details instead of plain terrain fills. Use layoutPreset: "bitmask" only when you need the direct NW=1, NE=2, SE=4, SW=8 quadrant map. The metadata file includes tile rectangles, per-tile stencil patterns, pattern resolution, and quadrant summaries for engine-side lookup.

Query the palette:

Use aseprite_get_document_info; the document.palette array contains palette entries.

Generate a preview:

Use aseprite_export_png:

{
  "filePath": "examples/output/player.aseprite",
  "outputPath": "examples/output/player-preview.png",
  "overwrite": true
}

Modify an existing file safely:

{
  "filePath": "examples/output/player.aseprite",
  "outputPath": "examples/output/player-edited.aseprite",
  "pixels": [
    { "x": 10, "y": 10, "color": { "r": 255, "g": 255, "b": 255, "a": 255 } }
  ],
  "createBackup": true,
  "overwrite": true
}

Security Model

  • All paths are resolved against the server working directory.

  • Reads and writes are restricted to configured allowed directories.

  • Path traversal and unsupported extensions are rejected.

  • Aseprite is launched with argument arrays, not shell command strings.

  • Lua is generated by the server and selected by operation name.

  • Clients cannot send arbitrary Lua or shell commands.

  • Writes can require explicit overwrite.

  • Destructive operations can create backups.

  • Per-file locks serialize writes to the same destination.

  • Processes have timeouts and output size limits.

Tests

npm run build
npm test

Current verified result:

  • TypeScript build passes.

  • 5 test files pass.

  • 11 tests pass.

The integration smoke test checks discovery without requiring Aseprite. Full real-file tests require ASEPRITE_PATH.

Known Aseprite Limitations

  • CLI export is strong for conversion and spritesheets, but many document edits require Lua.

  • --sheet overwrites output files, so this server validates overwrite before invoking it.

  • Some Lua standard library operations can be permission-sensitive in Aseprite; this MVP avoids client-supplied Lua and passes operation payload through script parameters.

  • Spritesheet export options are limited to documented CLI flags currently wired in command-builder.ts.

  • Additional tileset systems, region transforms, palette mutation tools, and high-level deterministic generators are not implemented yet.

Pending Tools

Next priority groups:

  • Sequence duplication and animation preview export

  • Palette mutation/import

  • Region ellipse/flood-fill/move/flip/rotate

  • Additional tileset creation systems and metadata

  • High-level deterministic templates for 16/32px characters, enemies, objects, and UI

Complete Animation Flow

See examples/create-animation.json for a complete sequence:

  1. Create a 32x32 four-frame document.

  2. Draw a compact set of pixels.

  3. Create an idle ping-pong tag.

  4. Export a horizontal spritesheet and JSON metadata.

Related MCP Connectors

Related MCP Servers