Skip to main content
Glama
README.md
# aseprite-mcp

An [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server that gives AI agents the ability to create and edit Aseprite sprites programmatically.

An AI can use this server to draw pixels, lines, shapes, manage layers and frames, read back pixel data, inspect the full sprite state, and self-iterate until the result matches the request — all without leaving the chat.

## How it works

The server exposes Aseprite's sprite manipulation capabilities as [MCP tools](https://github.com/modelcontextprotocol/servers) that an AI assistant can call. Under the hood it generates Lua scripts that Aseprite executes in batch mode.

## Tools

| Tool | What it does |
|------|-------------|
| `create_sprite` | Create a new `.aseprite` file |
| `draw_pixels`, `draw_line`, `draw_rectangle`, `draw_circle` | Drawing operations |
| `flood_fill` | Flood fill an area |
| `add_layer`, `remove_layer` | Layer management |
| `add_frame`, `set_frame_duration` | Frame/animation control |
| `set_palette_color`, `resize_canvas` | Palette and canvas |
| `export_png`, `export_gif` | Export to image formats |
| `get_sprite_info`, `inspect_sprite` | Read sprite metadata |
| `get_pixel_color`, `get_palette` | Read back pixel data |

The AI can read back what it drew, inspect the full sprite state, and self-iterate until it's happy with the result.

## Usage

```bash
npm run build
npm start        # stdio transport (default)
npm start -- --port 3100   # HTTP server on port 3100
```

The server runs in **stdio mode** by default (standard MCP protocol). Pass `--port` to start an **HTTP server** instead, allowing remote MCP clients to connect via `http://localhost:<port>/mcp`.

On startup the server prints its PID, transport mode, and Aseprite binary path to stderr. Use the PID to manage the server process (e.g. `kill <pid>` to stop).

## Requirements

- [Aseprite](https://www.aseprite.org) installed

The server auto-detects Aseprite from common install paths. If it's not found, set the `ASEPRITE_PATH` environment variable to point to the executable:

| Platform | Steam | itch.io / Humble / Gumroad |
|----------|-------|---------------------------|
| macOS | `~/Library/Application Support/Steam/steamapps/common/Aseprite/Aseprite.app/Contents/MacOS/aseprite` | `/Applications/Aseprite.app/Contents/MacOS/aseprite` |
| Windows | `C:\Program Files (x86)\Steam\steamapps\common\Aseprite\Aseprite.exe` | `C:\Program Files\Aseprite\Aseprite.exe` |
| Linux | `~/.steam/steam/steamapps/common/Aseprite/aseprite` | `/usr/bin/aseprite` |

```bash
export ASEPRITE_PATH="/path/to/aseprite"   # macOS / Linux
set ASEPRITE_PATH="C:\path\to\aseprite.exe"  # Windows
```

## Connecting other agents

This is a standard MCP server — any MCP-compatible client can connect to it. The server runs on stdio transport:

```bash
node /path/to/aseprite-mcp/dist/index.js
```

### opencode

Already configured in `opencode.json`:

```json
{
  "mcp": {
    "aseprite-mcp": {
      "type": "local",
      "command": ["node", "dist/index.js"],
      "enabled": true
    }
  }
}
```

### Claude Code

Add to `~/.claude/config.json` or project `CLAUDE.md`:

```json
{
  "mcpServers": {
    "aseprite-mcp": {
      "command": "node",
      "args": ["path/to/aseprite-mcp/dist/index.js"],
      "env": {
        "ASEPRITE_PATH": "/path/to/aseprite"
      }
    }
  }
}
```

### Cursor

Create `.cursor/mcp.json` in the project root:

```json
{
  "mcpServers": {
    "aseprite-mcp": {
      "command": "node",
      "args": ["path/to/aseprite-mcp/dist/index.js"],
      "env": {
        "ASEPRITE_PATH": "/path/to/aseprite"
      }
    }
  }
}
```

### VS Code (GitHub Copilot)

Add to `.vscode/settings.json`:

```json
{
  "github.copilot.chat.agent.mcpServers": {
    "aseprite-mcp": {
      "command": "node",
      "args": ["path/to/aseprite-mcp/dist/index.js"],
      "env": {
        "ASEPRITE_PATH": "/path/to/aseprite"
      }
    }
  }
}
```

### Over HTTP (remote clients)

Start the server with a port:

```bash
npm start -- --port 3100
```

Then point any MCP client to `http://localhost:3100/mcp`:

```json
{
  "mcpServers": {
    "aseprite-mcp": {
      "url": "http://localhost:3100/mcp",
      "type": "http",
      "headers": {}
    }
  }
}
```

Health check: `http://localhost:3100/health`

### Cline / Roo Code

Add to `cline_mcp_settings.json` or `roo_mcp_settings.json`:

```json
{
  "mcpServers": {
    "aseprite-mcp": {
      "command": "node",
      "args": ["path/to/aseprite-mcp/dist/index.js"],
      "env": {
        "ASEPRITE_PATH": "/path/to/aseprite"
      }
    }
  }
}
```

### Using `ASEPRITE_PATH` with the MCP config

If the auto-detection fails, pass the environment variable in the MCP server config:

```json
{
  "env": {
    "ASEPRITE_PATH": "/Applications/Aseprite.app/Contents/MacOS/aseprite"
  }
}
```

See `mcp.example.json` for all config variants.

## Example

An AI is asked to *"draw a red heart on a 16x16 canvas"*:

**1. Create the sprite**

```
→ create_sprite(file: "heart.aseprite", width: 16, height: 16)
← Created sprite: heart.aseprite (16x16, rgb)
```

**2. Draw the heart using rectangles and flood fill**

The AI calls a series of drawing tools — first a red rectangle for the base, then flood fills to shape it into a heart.

```
→ draw_rectangle(file: "heart.aseprite", x: 2, y: 5, w: 12, h: 6, color: "#ff0000", fill: true)
← Rectangle drawn on heart.aseprite
→ flood_fill(file: "heart.aseprite", x: 2, y: 4, color: "#ff0000")
← Flood fill done on heart.aseprite
→ flood_fill(file: "heart.aseprite", x: 13, y: 4, color: "#ff0000")
← Flood fill done on heart.aseprite
```

**3. Inspect the result**

```
→ get_pixel_color(file: "heart.aseprite", x: 4, y: 4)
← Color at (4, 4): #ff0000ff (rgba: 255, 0, 0, 255)
→ export_png(file: "heart.aseprite", output: "heart.png")
← Exported PNG: heart.png
```

The AI reads back pixel data, verifies the shape, and exports the final sprite — all autonomously.

<!-- result
     . . . . . . . . . . . . . . . .
     . . . . . . . . . . . . . . . .
     . . . . . . . . . . . . . . . .
     . . . . . . . . . . . . . . . .
     . . . . # # # . . # # # . . . .
     . . . # # # # # # # # # # . . .
     . . # # # # # # # # # # # # . .
     . . # # # # # # # # # # # # . .
     . . # # # # # # # # # # # # . .
     . . . # # # # # # # # # # . . .
     . . . . # # # # # # # # . . . .
     . . . . . # # # # # # . . . . .
     . . . . . . # # # # . . . . . .
     . . . . . . . # # . . . . . . .
     . . . . . . . . . . . . . . . .
     . . . . . . . . . . . . . . . .
-->

## Assets

The `assets/` directory contains sample sprites generated with this server:

| File | Size | Description |
|------|------|-------------|
| `player.aseprite` | 64×64 | Player character with head, body, arms, hands, legs — 14 animated frames (idle/walk/attack) |
| `kitten_plane.aseprite` | 96×64 | Orange kitten in a vintage toy airplane with aviator helmet and goggles |
| `heart.aseprite` | 16×16 | Heart pickup |
| `coin.aseprite` | 16×16 | Gold coin |
| `enemy.aseprite` | 16×16 | Spike-top enemy |
| `platform.aseprite` | 32×16 | Dirt platform with grass |

![Player](assets/player.gif)
![Player](assets/player.png)
![Kitten plane](assets/kitten_plane.png)
![Heart](assets/heart.png)
![Coin](assets/coin.png)
![Enemy](assets/enemy.png)
![Platform](assets/platform.png)

Each `.aseprite` file has a scaled `.png` export. Open them in Aseprite to edit, or use the PNGs directly in a game.

## opencode-office

The `opencode-office/` directory is a pixel-art agent HQ for opencode, inspired by [Pixel Agents](https://github.com/pixel-agents-hq/pixel-agents). It visualizes AI agents as animated characters in a virtual office.

![Blue agent](opencode-office/assets/characters/blue_0.png)
![Desk](opencode-office/assets/furniture/desk.png)
![Chair](opencode-office/assets/furniture/chair.png)
![Computer](opencode-office/assets/furniture/computer.png)
![Plant](opencode-office/assets/furniture/plant.png)

**6 agent colors** — blue, green, red, purple, orange, teal — each with 8 animation frames across 3 states:

| State | Frames | Duration | Description |
|-------|--------|----------|-------------|
| idle | 2 | 400ms | Subtle breathing bounce |
| walk | 4 | 150ms | Leg alternation cycle |
| work | 2 | 500ms | Typing arm motion |

Plus **furniture**: desk (24×16), chair (12×12), computer monitor (8×6 with glow), potted plant (12×12), and tileable floor/wall tiles.

### Using the viewer

Open `opencode-office/index.html` in any browser:

- Click **+ Agent / - Agent** to spawn or remove pixel agents (up to 9 desks)
- Agents auto-animate: work at their desk, take random walks, and return
- Click an agent to inspect its name, state, and recent activity
- **Debug** mode overlays state and position on each character

### Regenerating office sprites

```bash
ASEPRITE_PATH="/path/to/aseprite" node scripts/generate-characters.cjs
ASEPRITE_PATH="/path/to/aseprite" node scripts/generate-furniture.cjs
```

## License

MIT