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

A local MCP server for creating pixel art — no paid software, no external apps.
Canvases are ordinary PNG files on disk, edited with Pillow. One canvas pixel is
one image pixel; exports upscale with nearest-neighbor so pixels stay crisp.

The server encodes pixel-art *craft* in its tools, so models — including small
ones — don't have to be artists to produce good sprites: hue-shifted shading
ramps, one-call auto-shading (sphere / cylinder / bevel), dithered gradients,
symmetry mirroring, text-grid drawing and reading, curated palettes, and an
on-demand technique guide (`pixel_guide`) with a staged workflow
(size → palette → silhouette → flats → shading → details → finish).

Sprites animate the same way: rig one drawing into named parts and the server
generates the whole cycle from it, so an 8-frame walk costs one drawing rather
than eight.

## Tools

### Craft (color, shading, knowledge)

| Tool | Purpose |
|---|---|
| `pixel_guide` | Technique playbook: workflow, sizing, color, shading, dithering, materials, characters, scenes, animation |
| `pixel_build_ramp` | One base color → professional dark→light ramp (hue-shifted shadows/highlights) |
| `pixel_shade_region` | Flat regions → shaded 3D form in one call: `sphere`, `cylinder_upright`, `cylinder_side`, `bevel` |
| `pixel_draw_gradient` | Linear/radial gradients with ordered dithering (`bayer4`, `checker`); can target one flat color or fade out via `transparent` |
| `pixel_paint_grid` | Draw from a text grid + character→color legend — the reliable way to place shapes |
| `pixel_ascii_view` | Read the canvas back as a labeled character grid with exact coordinates |
| `pixel_mirror_canvas` | Draw half a symmetric subject, mirror it across an axis |
| `pixel_palettes` | Curated, pre-harmonized palettes (sweetie16, pico8, dawnbringer16, slso8, nes) |
| `pixel_draw_polygon` | Angular silhouettes from a handful of vertices (hulls, roofs, blades, mountains) |
| `pixel_draw_curve` | Quadratic/cubic Bézier strokes for organic contours (necks, tails, hair, flames) |
| `pixel_apply_spaa` | Sub-pixel anti-aliasing: softens diagonal staircases; uses partial alpha on transparent backgrounds |
| `pixel_batch` | Run many drawing operations on one canvas in a single call — the default way to draw |

### Drawing

| Tool | Purpose |
|---|---|
| `pixel_create_canvas` | New PNG canvas (up to 1024x1024), any background or transparent |
| `pixel_draw_pixels` | Batch-set individual pixels, per-point colors supported |
| `pixel_draw_line` / `pixel_draw_rect` / `pixel_draw_ellipse` | Shape primitives, filled or outlined |
| `pixel_flood_fill` | Paint-bucket fill of a contiguous region |
| `pixel_replace_color` | Exact-match palette swap across the canvas |
| `pixel_apply_palette` | Snap all colors to the nearest entry of a given palette |
| `pixel_outline_sprite` | Auto 1px outline: `solid` color or `selective` (darkened neighbor colors) |

### Canvas surgery

| Tool | Purpose |
|---|---|
| `pixel_copy_region` | Copy/composite a rect within or between canvases (`over` / `replace`) |
| `pixel_shift_canvas` | Shift art by (dx, dy), optionally wrapping at edges |
| `pixel_resize_canvas` | Grow/crop canvas bounds with a 9-way anchor, art unscaled |
| `pixel_scale_canvas` | Nearest-neighbor rescale (squash-and-stretch friendly) |
| `pixel_transform_canvas` | Flip / rotate the whole canvas |

### Animation

| Tool | Purpose |
|---|---|
| `pixel_define_rig` | Name the movable parts of a drawn sprite, with a labelled preview that flags art no part covers |
| `pixel_render_motion` | Generate a whole animation loop from one rigged sprite |
| `pixel_motions` | Built-in cycles: `walk`, `run`, `idle`, `bob`, `squash_land` |
| `pixel_duplicate_canvas` | Start the next frame from the current one |
| `pixel_onion_view` | Current frame over faded ghosts of up to 3 earlier frames |
| `pixel_view_frames` | Filmstrip contact sheet of many frames in one image |
| `pixel_export_gif` | Looping GIF with per-frame durations and ping-pong mode |
| `pixel_export_spritesheet` | Pack frames into a grid PNG for game engines |
| `pixel_slice_spritesheet` | Split an existing sheet back into frame canvases |

#### Rigging: one drawing, N frames

Nobody draws 240 frames. Draw the character **once**, name its parts, and let
the server composite the cycle:

```
pixel_define_rig  →  pixel_render_motion motion='walk'  →  pixel_export_gif
```

Every frame is stamped from the source pixels at new offsets, and offsets round
to whole pixels — so nothing is resampled, nothing flickers, and re-rendering
the same rig is byte-identical. Consistency is arithmetic, not luck.

Draw the limbs in a **parts bin** beside the sprite rather than on the body. A
part is a rectangle of source pixels, so limbs drawn on top of each other can
never be boxed apart — but a true side view needs them to overlap once placed.
`at_x`/`at_y` place a binned part on the body; `frame_width`/`frame_height`
keep the bin out of the rendered frames. See
[`benchmarks/examples/demo_walk.py`](benchmarks/examples/demo_walk.py) for a
complete 8-frame walk from a single 48×48 sheet, and
[`demo_dusk.py`](benchmarks/examples/demo_dusk.py) for a full 128×96 scene —
parallax, a walking figure, a guttering lantern, flapping birds, a tumbling
leaf and twinkling stars, all 24 frames of it composited from one 224×200
sheet, driving every motion channel.

Loops close seamlessly under two rules: layers that tile scroll **exactly one
tile period** per loop, and sprites that don't tile **start and end
off-frame**, so the wrap lands where nobody can see it.

**No arbitrary rotation.** Pixel art does not survive being rotated by
anything but a multiple of 90°, so the orientation channels are `flip` and
`rot` only. For an in-between limb angle, draw that angle as its own part and
switch to it with the `use` channel — which is how real sprite work has always
handled it. Motion channels: `dx`, `dy`, `squash` (interpolated), `flip`,
`rot`, `visible`, `use` (held). Read `pixel_guide topic='animation'` first.

### Inspection & export

| Tool | Purpose |
|---|---|
| `pixel_view_canvas` | Render the canvas as an image; `grid: true` adds labeled 8px coordinate gridlines |
| `pixel_canvas_info` | Dimensions + palette report without rendering |
| `pixel_export_png` | Nearest-neighbor upscaled PNG export |

Mutating tools accept `preview: true` to return a rendered image of the result
in the same call, and `preview_diff: true` to return only the region that
changed (roughly 90% fewer image tokens while iterating on a detail; falls back
to the full canvas when the change is large). Colors are hex (`#1a1c2c`,
`#1a1c2cff`), CSS names (`crimson`), or `transparent` (which erases).

## Design principle

Describe shapes, don't enumerate pixels. Every tool exists so a model can
express an artistic intent in one call rather than hundreds of coordinates: a
mountain is 5 polygon vertices, a dragon's neck is one Bézier, a sky is one
dithered gradient, a shaded sphere is one `pixel_shade_region` call. The staged
workflow in `pixel_guide` (silhouette → flats → shading → details → finish)
mirrors how pixel artists actually construct a piece, and `pixel_apply_spaa` is
the hand-finishing pass at the end.

## Token cost

A finished piece is 20–30 operations. The dominant cost is not the tool schemas
(~18k tokens, sent once and cached by the client) but the **round trips** — every
separate call re-sends the whole conversation. So:

- **`pixel_batch` is the default way to draw.** Send a whole stage as one call.
  Operations run in order, share the batch's `path`, and produce output
  byte-identical to running them individually.
- **`preview_diff: true`** returns only the region a call changed, rendered
  small — roughly 90% fewer image tokens while iterating on a detail.
- **High-level tools over pixel lists.** One `pixel_draw_polygon` can place
  thousands of pixels that would otherwise be enumerated by hand.
- **`pixel_canvas_info`** takes `top_n` to trim its palette report.

Client-side knobs matter too and are worth setting: prompt caching (tool schemas
are a stable prefix, so they cache well) and per-session tool allow-listing.
Deliberately *not* done here: compressing the tool descriptions. They carry the
craft guidance — light direction, material recipes, when to dither — that lets
smaller models draw well, so shrinking them trades quality for tokens the client
is already caching.

## Benchmarks

[benchmarks/BENCHMARKS.md](benchmarks/BENCHMARKS.md) defines 20 standard
subjects (detailed apple, glass bottle with water, medieval knight, Spider-Man,
Iron Man in sunlight, campfire, dragon, ice cave, ...) with per-subject
must-haves and a 7-dimension rubric — run them across models or server versions
to measure whether a tooling change actually improves the art.
`benchmarks/examples/` holds reference pieces drawn with the craft toolset, and
`benchmarks/runs/` holds completed runs with the script for every piece.

## Setup

Requires [uv](https://docs.astral.sh/uv/). Register with Claude Code:

```bash
claude mcp add pixelart -s user -- uv --directory /path/to/pixelart-mcp run -m pixelart_mcp
```

Or in any MCP client config:

```json
{
  "mcpServers": {
    "pixelart": {
      "command": "uv",
      "args": ["--directory", "/path/to/pixelart-mcp", "run", "-m", "pixelart_mcp"]
    }
  }
}
```

TDQS

A4.2/5.0

Scored across 23 tools

Disambiguation5/5

All 23 tools have clearly distinct purposes, from creating and drawing on canvases to exporting and slicing spritesheets. Each tool's description uniquely identifies its function, and there is no overlap or ambiguity between them.

Naming Consistency5/5

All tool names follow a consistent 'pixel_verb_noun' pattern in snake_case (e.g., pixel_create_canvas, pixel_draw_pixels, pixel_export_png). This makes the tool set predictable and easy to navigate for an agent.

Tool Count4/5

With 23 tools, the server is on the higher end of the typical range, covering a broad set of pixel art operations. While each tool is justified, the count could be slightly reduced by merging some related operations, but overall it remains well-scoped.

Completeness5/5

The tool set covers the full lifecycle of pixel art creation and manipulation: creation, drawing (shapes, lines, fill), editing (color replacement, transforms, copy region), viewing, export (PNG, GIF, spritesheet), animation support (onion skinning, shift, duplicate), and import (slicing spritesheets). No obvious gaps are present.

Maintenance

ActivitySlowing
ResponsivenessNo issues