pixelart-mcp
The pixelart-mcp server is a local toolkit for creating, editing, animating, and exporting pixel art on PNG files, designed to be AI‑friendly by encoding artistic techniques.\n\n- Canvas Management: Create canvases up to 1024×1024 pixels (transparent or colored), duplicate, resize (grow/crop with 9‑way anchor), scale with nearest‑neighbor sampling, shift (with optional wrapping), flip/rotate, copy/composite regions within or between canvases, and view with optional grid overlays. Get canvas info like dimensions and palette.\n- Drawing & Editing: Draw individual pixels in batch (up to 4096 per call), shapes (lines, rectangles, ellipses, polygons, Bézier curves), flood fill, replace colors, draw from text grids using a color legend, and auto‑outline sprites.\n- Craft & Shading: Build color ramps from a base color, auto‑shade regions into 3D forms (sphere, cylinder, bevel), draw dithered gradients (linear/radial with Bayer or checker patterns), mirror canvases for symmetry, apply curated palettes (sweetie16, pico8, dawnbringer16, slso8, nes), snap colors to a palette, and apply sub‑pixel anti‑aliasing.\n- Animation: Onion‑skin view (up to 3 previous frames), filmstrip view, export animated GIFs with per‑frame durations and ping‑pong mode, export/pack spritesheets, and slice spritesheets back into frames.\n- Export & Preview: Export upscaled PNGs with crisp nearest‑neighbor scaling. Use pixel_batch to combine multiple operations in one call, with preview or preview_diff options to save tokens by only showing changed regions.\n- AI‑Friendly Design: Tools bundle pixel art craftsmanship (shading, anti‑aliasing, palette management) so models can produce high‑quality sprites without being artists.
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., "@pixelart-mcp create a 16x16 canvas with a transparent background"
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.
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 jointed parts and the server generates the whole cycle from it — limbs swing from the hip and shoulder, knees and elbows fold, feet stay planted — so an 8-frame walk costs one drawing rather than eight.
Tools
Craft (color, shading, knowledge)
Tool | Purpose |
| Technique playbook: workflow, sizing, color, shading, dithering, materials, characters, scenes, animation |
| One base color → professional dark→light ramp (hue-shifted shadows/highlights) |
| Flat regions → shaded 3D form in one call: |
| Linear/radial gradients with ordered dithering ( |
| Draw from a text grid + character→color legend — the reliable way to place shapes |
| Read the canvas back as a labeled character grid with exact coordinates |
| Draw half a symmetric subject, mirror it across an axis |
| Curated, pre-harmonized palettes (sweetie16, pico8, dawnbringer16, slso8, nes) |
| Angular silhouettes from a handful of vertices (hulls, roofs, blades, mountains) |
| Quadratic/cubic Bézier strokes for organic contours (necks, tails, hair, flames) |
| Sub-pixel anti-aliasing: softens diagonal staircases; uses partial alpha on transparent backgrounds |
| Run many drawing operations on one canvas in a single call — the default way to draw |
| Score a piece for consistency (near-duplicate colors, stray specks, color budget, half-finished outline) and fix the safe ones |
Drawing
Tool | Purpose |
| New PNG canvas (up to 1024x1024), any background or transparent |
| Batch-set individual pixels, per-point colors supported |
| Shape primitives, filled or outlined |
| Paint-bucket fill of a contiguous region |
| Exact-match palette swap across the canvas |
| Snap all colors to the nearest entry of a given palette |
| Auto 1px outline: |
Canvas surgery
Tool | Purpose |
| Copy/composite a rect within or between canvases ( |
| Shift art by (dx, dy), optionally wrapping at edges |
| Grow/crop canvas bounds with a 9-way anchor, art unscaled |
| Nearest-neighbor rescale (squash-and-stretch friendly) |
| Flip / rotate the whole canvas |
Animation
Tool | Purpose |
| Name the jointed parts of a drawn sprite, with a labelled preview showing joints and flagging art no part covers |
| Generate a whole animation loop from one rigged sprite |
| Built-in cycles: |
| Start the next frame from the current one |
| Current frame over faded ghosts of up to 3 earlier frames |
| Filmstrip contact sheet of many frames in one image |
| Looping GIF with per-frame durations and ping-pong mode |
| Pack frames into a grid PNG for game engines |
| 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_gifLimbs swing, they don't slide. Every part has a pivot (its joint, by
default the top-center of its box) and may name a parent: a shin hangs from
its thigh, a forearm from its upper arm, so rotating the thigh carries the shin
and the knee then folds by its own angle — forward kinematics. Leave a child's
at_x/at_y unset and its joint snaps onto the parent's bottom row.
Rotation is RotSprite: the part is upscaled 8× with Scale2x and sampled back down at the new angle, so a rotated limb only ever reuses the drawn palette and keeps a clean edge. Walk and run use ground lock: each frame is shifted so its lowest pixel sits on the rest pose's floor, so planted feet never sink or float and the body bob falls out of the leg angles instead of being keyed by hand. Offsets round to whole pixels and the same rig always renders byte-identical frames.
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 for a
complete 8-frame walk with jointed knees and elbows from a single 48×48 sheet,
and 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.
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.
Motion channels: angle (degrees about the pivot; positive swings a hanging
limb forward, toward +x), dx, dy, squash (interpolated), flip, rot
(90° steps), visible, use (held — swap in a separately drawn pose). Read
pixel_guide topic='animation' first.
Inspection & export
Tool | Purpose |
| Render the canvas as an image; |
| Dimensions + palette report without rendering |
| 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).
Related MCP server: pixscii
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_batchis the default way to draw. Send a whole stage as one call. Operations run in order, share the batch'spath, and produce output byte-identical to running them individually.preview_diff: truereturns 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_polygoncan place thousands of pixels that would otherwise be enumerated by hand.pixel_canvas_infotakestop_nto 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 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.
Two scripts make the comparison mechanical:
bench_stills.py ROOT...re-renders every scripted piece for each checkout (in a scratch copy) and lints them all with one ruler, side by side;--out DIRadds a visual comparison sheet.bench_motion.py SHEET FRAME_W [SOURCE]checks an animation: torn joints, palette leaks, floor jitter, and how evenly the motion flows frame to frame.
Unit tests: uv run python -m unittest.
Setup
Requires uv. Register with Claude Code:
claude mcp add pixelart -s user -- uv --directory /path/to/pixelart-mcp run -m pixelart_mcpOr in any MCP client config:
{
"mcpServers": {
"pixelart": {
"command": "uv",
"args": ["--directory", "/path/to/pixelart-mcp", "run", "-m", "pixelart_mcp"]
}
}
}Available Tools
23 toolspixel_apply_paletteADestructiveIdempotent
Snap every opaque pixel to the nearest color in a given palette — enforce a consistent game palette across sprites or clean up stray colors.
Nearest match is by RGB distance; each pixel's alpha is preserved and fully transparent pixels are untouched. Returns JSON {"canvas", "palette_size", "pixels_changed"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_canvas_infoARead-onlyIdempotent
Report a canvas's dimensions and color palette without rendering it.
Returns JSON: {"canvas", "width", "height", "unique_colors", "has_transparency", "top_colors": [{"color", "count"}, ...]} with the up to 16 most-used colors (fully transparent pixels reported as 'transparent'). On failure returns "Error: ...".
Inputs: params (required). Returns: result
pixel_copy_regionADestructiveIdempotent
Copy a rectangular region from one canvas onto another (or within the same canvas) — for moving limbs between frames, stamping repeated parts, or compositing a sprite onto a background.
mode='over' (default) respects transparency like layering; mode='replace' overwrites the destination rect including alpha. Destination coordinates may be negative or overhang; the region clips to the destination canvas. Returns JSON {"source", "canvas", "region", "pasted_at", "mode"}; plus a rendered image of the destination when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_create_canvasA
Create a new pixel art canvas saved as a PNG file.
The canvas is true-size (one canvas pixel = one image pixel); keep sprites small (e.g. 16x16, 32x32, 64x64) and upscale later with pixel_export_png. Parent directories are created automatically. Refuses to replace an existing file unless overwrite=true.
Returns: JSON {"canvas", "width", "height", "background"}; plus a rendered image of the canvas when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_draw_ellipseADestructiveIdempotent
Draw a filled or outlined ellipse inside a bounding box on a canvas.
(x, y) is the bounding box's top-left corner; equal width and height give a circle. Drawing 'transparent' erases. Returns JSON {"canvas", "ellipse", "color", "filled"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_draw_lineADestructiveIdempotent
Draw a straight line between two points on a canvas.
Endpoints may lie outside the canvas; the visible segment is drawn. Drawing 'transparent' erases. Returns JSON {"canvas", "line", "color"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_draw_pixelsADestructiveIdempotent
Set individual pixels on a canvas in one batch.
Each point may carry its own color; points without one use the batch
default color. Drawing 'transparent' erases pixels. Out-of-bounds points
are skipped and counted, not fatal. Batch as many points per call as
possible — one call per sprite region, not one call per pixel.
Returns: JSON {"canvas", "pixels_drawn", "skipped_out_of_bounds"?}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_draw_rectADestructiveIdempotent
Draw a filled or outlined rectangle on a canvas.
(x, y) is the top-left corner; width/height are in pixels. Drawing 'transparent' erases the region. Returns JSON {"canvas", "rect", "color", "filled"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_duplicate_canvasA
Copy a canvas to a new file — the standard way to start the next animation frame from the current one, then edit only what moves.
Refuses to replace an existing file unless overwrite=true. Returns JSON {"source", "canvas", "width", "height"}. On failure returns "Error: ...".
Inputs: params (required). Returns: result
pixel_export_gifAIdempotent
Combine same-size canvas PNGs into a looping animated GIF.
Frames play in the order given at duration_ms per frame (or per-frame durations_ms). ping_pong=true plays forward then backward for seamless bounce/idle loops. Transparency is preserved as GIF binary transparency (alpha <= 128 becomes transparent). Source canvases are untouched. Returns JSON {"exported", "frames", "frames_played", "scale", "width", "height"}. On failure returns "Error: ...".
Inputs: params (required). Returns: result
pixel_export_pngAIdempotent
Export a canvas as an upscaled PNG with crisp nearest-neighbor pixels.
The source canvas is untouched; the export is written to out_path (parent directories are created). Use scale 1 for game-ready true-size assets and larger scales for display or sharing. Returns JSON {"source", "exported", "scale", "width", "height"}. On failure returns "Error: ...".
Inputs: params (required). Returns: result
pixel_export_spritesheetAIdempotent
Pack same-size canvas PNGs into a single spritesheet PNG grid.
Frames are placed left-to-right, top-to-bottom, columns per row (all in
one row if omitted), with no padding — ideal for game engines. Source
canvases are untouched. Returns JSON {"exported", "frames", "columns",
"rows", "frame_width", "frame_height", "width", "height"}. On failure
returns "Error: ...".
Inputs: params (required). Returns: result
pixel_flood_fillBDestructiveIdempotent
Flood-fill the contiguous region containing (x, y), like a paint bucket.
Fills all connected pixels that exactly match the seed pixel's color. Returns JSON {"canvas", "seed", "color"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_onion_viewARead-onlyIdempotent
Render the current frame over faded ghosts of up to 3 earlier frames — onion-skinning, the standard way to judge motion between animation frames.
List previous_paths most-recent first; ghosts fade with distance (35%, 20%, 12% opacity). Pass a tint color to show ghosts as silhouettes when frame colors overlap too much. Nothing is written to disk. Returns a text summary plus the rendered image. On failure returns "Error: ...".
Inputs: params (required).
pixel_outline_spriteADestructiveIdempotent
Draw a 1px outline around all opaque art on the canvas — the classic finishing pass that makes sprites pop against any background.
The outline occupies transparent pixels adjacent to the art; the art itself is untouched. If the sprite touches the canvas edge, grow the canvas first with pixel_resize_canvas so the outline has room. Returns JSON {"canvas", "color", "pixels_outlined"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_replace_colorBDestructiveIdempotent
Replace every pixel of one exact color with another across the canvas.
Useful for palette swaps and recoloring sprites. Matching is exact RGBA. Returns JSON {"canvas", "find", "replace", "pixels_changed"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_resize_canvasADestructive
Change the canvas bounds without scaling the art — grow the canvas (new space is transparent) or crop it, with the existing art held at the chosen anchor.
Pixel sizes are unchanged; use pixel_scale_canvas to actually rescale art. Example: after squashing a sprite, resize back to the original height with anchor='bottom' to keep it grounded. Returns JSON {"canvas", "width", "height", "anchor"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_scale_canvasADestructive
Rescale the canvas and its art to new dimensions with nearest-neighbor sampling (no blurring).
Integer multiples or divisors keep pixels perfectly crisp; other ratios will distort — useful deliberately for squash-and-stretch animation frames. Returns JSON {"canvas", "width", "height"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_shift_canvasADestructive
Shift the whole canvas by (dx, dy) pixels — quick motion between animation frames (bobbing, jumping, sliding).
Without wrap, pixels shifted past the edge are lost and vacated space is transparent; with wrap=true they re-enter from the opposite edge (good for scrolling backgrounds). Returns JSON {"canvas", "shift", "wrap"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_slice_spritesheetAIdempotent
Split a spritesheet PNG into individual frame canvases — the way to bring existing game assets in for editing or re-animation.
Tiles are read left-to-right, top-to-bottom on a strict frame_width x frame_height grid (partial tiles at the right/bottom edges are ignored) and written to out_dir as '_f00.png', '_f01.png', .... Fully transparent tiles are skipped unless skip_empty=false. Returns JSON {"source", "out_dir", "frames_written", "skipped_empty", "frame_paths"}. On failure returns "Error: ...".
Inputs: params (required). Returns: result
pixel_transform_canvasADestructive
Flip or rotate the entire canvas in place.
Operations: flip_horizontal, flip_vertical, rotate_90_cw, rotate_90_ccw, rotate_180. 90-degree rotations swap the canvas dimensions. Returns JSON {"canvas", "operation", "width", "height"}; plus a rendered image when preview=true. On failure returns "Error: ...".
Inputs: params (required).
pixel_view_canvasARead-onlyIdempotent
Render a canvas as an image so you can see its current state.
Small canvases are upscaled with nearest-neighbor (crisp pixels) to about 512px on the long edge unless an explicit scale is given. Use this after a series of edits to check your work. Returns a text summary plus the rendered image. On failure returns "Error: ...".
Inputs: params (required).
pixel_view_framesARead-onlyIdempotent
Render several same-size canvases side by side as one filmstrip image — review a whole animation or sprite set at a glance.
Frames are laid out left-to-right, top-to-bottom on a neutral gray backdrop with thin separators, in the order given. Nothing is written to disk. Returns a text summary naming each frame position plus the rendered image. On failure returns "Error: ...".
Inputs: params (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 23 tools
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.
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.
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.
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
Related MCP Connectors
Game-dev sprite tools: PNG/GIF to spritesheet, split, trim, animate. OAuth-authenticated MCP server.
Generate authentic pixel art - sprites, animations, and tilesets - from any MCP client
MCP server for Flux AI image generation
An MCP server that provides asset auto generator
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that generates pixel-art PNGs from text prompts, using a free image backend, and saves them directly to your project directory.62MIT
- AlicenseAqualityCmaintenanceA pixel art animation MCP server for AI agents, enabling scene generation, sprite drawing, and PNG export with zero latency.19110 npm3MIT
- FlicenseAqualityDmaintenanceAn MCP server that enables AI coding agents to create pixel art programmatically by providing canvas manipulation tools and PNG export.1028 npm9-
- AlicenseNot gradedqualityDmaintenanceMCP server for generating pixel-art sprites with transparent backgrounds using any diffusers-compatible text-to-image model.MIT