Skip to main content
Glama

aseprite-lua-mcp

A lightweight Model Context Protocol server that lets LLM agents create pixel art and animations in Aseprite by writing one complete Lua script and running it headlessly with aseprite --batch --script.

Why scripts instead of per-pixel tools?

Most Aseprite integrations expose one IPC/tool call per operation (put pixel, draw line, add frame...). Every call costs tokens and a round-trip. This server exposes a single "run this script" tool instead:

Approach

Tool calls for a 32x32 sprite

Token usage

One MCP call per pixel/shape

hundreds

very high, rate-limit prone

One Lua script (this server)

1

90%+ lower

A Lua loop replaces thousands of tokens of repeated calls, and when something fails the agent fixes a single script and re-runs it.

Related MCP server: mnehmos.aseprite.mcp

Quick start

Requires Node.js 18+ and Aseprite installed locally. No clone or build needed; npx downloads the package on demand.

Claude Code

claude mcp add aseprite -- npx -y aseprite-lua-mcp

With environment variables:

claude mcp add aseprite \
  -e ASEPRITE_PATH="C:/Program Files/Aseprite/Aseprite.exe" \
  -e DEFAULT_OUTPUT_DIR="C:/Users/me/sprites" \
  -- npx -y aseprite-lua-mcp

The -- before npx is required so that -y is passed to npx and not parsed by claude mcp add.

Claude Desktop / .claude.json

Add this to claude_desktop_config.json (or the mcpServers section of .claude.json):

{
  "mcpServers": {
    "aseprite": {
      "command": "npx",
      "args": ["-y", "aseprite-lua-mcp"],
      "env": {
        "ASEPRITE_PATH": "C:/Program Files/Aseprite/Aseprite.exe",
        "DEFAULT_OUTPUT_DIR": "C:/Users/me/sprites"
      }
    }
  }
}

env is optional. Restart the client after editing the config.

Environment variables

Variable

Description

Default

ASEPRITE_PATH

Path to the Aseprite executable. The server errors if it is set but the file doesn't exist.

Auto-detected in common Windows, macOS and Linux locations (including Steam), then PATH

DEFAULT_OUTPUT_DIR

Base directory for a relative output_filename.

process.cwd()

Absolute output_filename values are used as-is. The output file's parent directory is created automatically.

Tools

execute_aseprite_script

Parameter

Type

Description

lua_code

string (required)

Complete Lua script to run.

output_filename

string (optional)

Expected output file, e.g. sprite.png. Absolute, or relative to DEFAULT_OUTPUT_DIR / process.cwd().

The code is written to a temporary .lua file, run with aseprite --batch --script (60 second timeout), and the temp file is always deleted. The result contains stdout and stderr (syntax and runtime errors with line numbers). When output_filename is given, the global OUTPUT_PATH (the resolved absolute path) is available inside the script, and the server reports whether the file was actually created. The script is responsible for saving it.

local spr = Sprite(16, 16)
local img = spr.cels[1].image
local c = Color{ r=220, g=40, b=40 }
for y=0,15 do for x=0,15 do
  if (x-8)^2 + (y-8)^2 <= 36 then img:putPixel(x, y, c) end
end end
spr:saveCopyAs(OUTPUT_PATH)

get_aseprite_lua_docs

Returns a compact cheat sheet of the Aseprite Lua API (Sprite, Layer, Cel, Image, Color, Palette, saveCopyAs) so the agent doesn't need to guess.

To get immediate execution with no explanatory prose, and the biggest token savings, put this in a .clauderules file (or your CLAUDE.md) in your project:

# aseprite-lua-mcp rules

- ALWAYS generate pixel art by writing a complete Lua script and executing it with `execute_aseprite_script`. Never draw pixel by pixel or issue per-operation calls.
- DO NOT explain your drawing strategy or write introductory/concluding prose text. Execute the tool IMMEDIATELY with the generated script.
- If you are unsure about the Aseprite Lua API, call `get_aseprite_lua_docs` once before writing the script.
- Put everything in a single script: create the sprite, draw (use loops and helper functions for lines, circles, rects, fills), set palette/layers/frames/tags, and export with `spr:saveCopyAs(...)`.
- Pass `output_filename` and save to the `OUTPUT_PATH` global inside the script.
- On error, read the stderr line number, fix the script, and re-run the whole script; NEVER fall back to per-pixel commands.
- Use small canvases (16x16 to 64x64) and scale up only for previews.

Development

git clone <this repo> aseprite-lua-mcp
cd aseprite-lua-mcp
npm install
npm run build
node dist/index.js

Security note

This server executes arbitrary Lua inside Aseprite, which can read and write files and run OS commands (os.execute). Only connect it to agents you trust.

License

MIT

Available Tools

2 tools
execute_aseprite_scriptA

Run a complete Aseprite Lua script headlessly (aseprite --batch --script). Write the whole drawing/animation/export as one script instead of many small calls. Call get_aseprite_lua_docs first if unsure about the API.

ParametersJSON Schema
NameRequiredDescriptionDefault
lua_codeYesFull Lua script to execute
output_filenameNoExpected output file (e.g. sprite.png). Absolute paths are used as-is; relative paths resolve against DEFAULT_OUTPUT_DIR (or the server's working directory). Missing directories are created. The script itself must save it (e.g. spr:saveCopyAs(...)); this is used to verify the result.

TDQS

A4/5.0
Behavior3/5

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

With no annotations, the description carries the full burden, and it does disclose the important runtime model: headless batch execution and that the script itself must save the output. It says nothing about execution limits, timeouts, error/sandbox behavior for arbitrary Lua, or what happens when the expected output file is never produced, which are meaningful gaps for a code-execution tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the composition guidance, then the prerequisite. Every sentence carries distinct information and none restates the name or schema.

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?

With no output schema, the description should ideally say what comes back (e.g. verification of output_filename, captured stdout). The output_filename schema hints at result verification, and the description covers the script/Save contract, so an agent can call it correctly, but return-value behavior is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema, including path resolution and the save/verify contract for output_filename. The description adds no parameter detail beyond what the schema provides, which is the expected baseline when the schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Run a complete Aseprite Lua script') and even names the underlying invocation ('aseprite --batch --script'), so the mechanism is unambiguous. It also distinguishes itself from the sibling tool by pointing at get_aseprite_lua_docs for API reference rather than execution.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the key usage pattern explicitly: 'Write the whole drawing/animation/export as one script instead of many small calls,' and gives a prerequisite ('Call get_aseprite_lua_docs first if unsure'). It stops short of naming when NOT to use it or what a 'small call' alternative would actually be, so the routing advice is clear but not exhaustive.

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

get_aseprite_lua_docsA

Return a compact cheat sheet of the Aseprite Lua API (Sprite, Layer, Cel, Image, Color, Palette, saveCopyAs).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden, and it does disclose the payload shape ('compact cheat sheet') and its coverage scope, which is the key trait for a static documentation tool. It says nothing about read-only nature, output format (markdown vs prose), or size limits, but the operation is inherently low-risk and self-evident.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence stating the action, the artifact, and the covered surface, with zero filler. Nothing could be removed without losing information.

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 zero-parameter, no-output-schema documentation fetcher, the description is nearly sufficient: it tells the agent what content comes back and which API areas are covered. It omits the return format (plain text, markdown, etc.), which is the only real remaining gap.

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?

The tool takes zero parameters, so there is nothing to disambiguate and the baseline is 4 per the rubric. The description adds no parameter discussion, which is correct since no input exists.

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 description gives a specific verb ('Return') and resource ('cheat sheet of the Aseprite Lua API') and even enumerates the covered domain objects (Sprite, Layer, Cel, Image, Color, Palette, saveCopyAs), so an agent immediately knows this is a reference-lookup tool. It does not explicitly contrast itself with its sibling execute_aseprite_script, which keeps it short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to call this versus execute_aseprite_script, nor any prerequisite (e.g. 'call before writing a script'). The use case is only inferable from the name and from the word 'cheat sheet', which is weak 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.

  1. 2 tool updatesv0.1.1
    • First observedexecute_aseprite_script
    • First observedget_aseprite_lua_docs

TDQS

A3.9/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: one retrieves API documentation, the other executes a script. There is no overlap or ambiguity in their roles.

Naming Consistency5/5

Both names follow a consistent snake_case verb_aseprite_noun pattern (get_..._docs, execute_..._script). The verbs are different but appropriate for their actions, and the structure is predictable.

Tool Count3/5

With only 2 tools, the set is borderline thin for the stated purpose. While each tool earns its place, a more complete server might include additional operations like listing sprites or validating scripts.

Completeness5/5

The server covers the essential workflow for Aseprite Lua scripting: accessing API documentation and executing scripts headlessly. No obvious gaps exist for the intended use case.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to create, inspect, edit, and export pixel art, sprites, animations, and spritesheets using headless Aseprite, and to convert arbitrary images into indexed pixel art.
    MIT
  • A
    license
    Not graded
    quality
    B
    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
  • A
    license
    B
    quality
    C
    maintenance
    Enables AI assistants to create and edit pixel art and animated sprites in Aseprite through 104 tools covering drawing, layers, animation, palettes, tilemaps, exports, visual analysis, and raw Lua scripting.
    116
    MIT