Pixscii

io.github.rxolvePublished by GitHub account rxolvev0.5.0Updated Nov 3, 2026

LLMs can't draw. This MCP can. Pixel art animation toolkit — draw, animate, compose, export.

VerifiedSTDIODesktop onlyDeveloper ToolsMedia & Design

Overview

AI-generated overview

Pixscii is a local pixel-art workbench that lets an assistant generate, draw, animate and export sprites and scenes as PNG images.

What you can do
  • Search and load bundled sprites, or generate characters, creatures, beings and seeded landscapes
  • Draw on canvases with pixels, lines, rectangles, flood fill, mirror, shapes and single-step undo
  • Inspect a canvas as a hex character grid and switch palettes to recolor the same art
  • Compose sprites into scenes, build tilemaps and stitch canvases into spritesheets
  • Animate sprites or actors along paths, or produce a full animated scene in one call
  • Export canvases as scaled PNG images, and convert an image from a URL or base64 to pixel art
When to use it
Useful when you want an assistant to produce game-style pixel art, sprite sheets or short animations without any image model, and to iterate on them deterministically from a seed or a text description.
Requirements
Runs as a local stdio process, typically started with npx from the npm package pixscii, so Node.js and npm are needed. No accounts, API keys, environment variables or headers are declared. Image conversion and PNG export rely on the bundled Node-side tooling.
Before you install
The convert tool fetches images from a URL you supply, so the server makes outbound network requests to that address. Drawing tools modify canvases in place, though undo only steps back one operation. Generated PNGs are written where you ask them to be exported.

Installation

In SourceWeft

  1. Open Pixscii in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

pixscii

LLMs can't draw. This MCP can. A pixel art animation toolkit for AI agents.

Sister project of artscii. While artscii provides terminal ASCII art, pixscii gives AI agents a full pixel art workbench — generate characters, animate scenes, draw sprites, and export PNGs. Offline, deterministic, zero latency.

One Call Animation

json
animate_scene {  "width": 128, "height": 48,  "background": { "tiles": [["tree","grass","grass","sand","stone","wall","wall","door"]] },  "actors": [    { "seed": "hero", "species": "human", "armor": "plate", "weapon": "sword",      "motion": "walk", "from": {"x":0,"y":28}, "to": {"x":96,"y":28} },    { "seed": "mage", "species": "elf", "armor": "cloth", "weapon": "staff",      "motion": "walk", "from": {"x":-16,"y":30}, "to": {"x":72,"y":30} },    { "seed": "guard", "species": "skeleton", "motion": "idle",      "from": {"x":108,"y":28}, "to": {"x":108,"y":28} }  ],  "frames": 24, "delay": 150}

One tool call. 3 characters, tiled background, 24 frames. 9ms.

The LLM translates a scene description into structured input. pixscii executes it instantly.

Quick Start

bash
npx pixscii

Or add to your MCP client config:

json
{  "mcpServers": {    "pixscii": {      "command": "npx",      "args": ["-y", "pixscii"]    }  }}

Tools (25)

High-Level — Full scenes in one call

ToolDescription
animate_sceneText description → animated scene with characters, background, and motion

Source — Create or load a canvas

ToolDescription
createNew blank canvas with optional fill color
getLoad a bundled sprite into an editable canvas
characterGenerate a procedural pixel character
convertQuantize any image (URL or base64) to pixel art
searchBrowse the sprite library
creatureEndless symmetric robots, aliens and critters from a mask and a seed, or an asymmetric nebula
beingA 24×24 person, cat or elf as a baby, an adult or old
landscapeGenerate a landscape from a seed: sky by time of day, sun or moon, stars, clouds, mountains, hills, sea, forest, ground, rain

Mutate — Draw on a canvas

ToolDescription
pixelSet individual pixels (batch up to 512)
lineBresenham line between two points
rectRectangle — outline or filled
fillFlood fill from a point (with leak detection)
mirrorMirror left half to right half
shapesDraw geometry as crisp pixel art: rect, circle, ellipse, polygon, line, curve, with dithered fills and gradients
undoRevert the last drawing operation

Observe — Read the canvas state

ToolDescription
inspectView the canvas as a hex character grid

Compose & Output

ToolDescription
sequenceAnimate actors across a scene with per-frame positions
composeLayer multiple canvases/sprites into a scene
tilemapBuild a map from a tile grid
spritesheetStitch frames into a single PNG (horizontal/vertical/grid)
animateAnimate a sprite with pixel motion (idle, walk, attack...)
exportRender a canvas to scaled PNG

Palette — Recolor by mood

ToolDescription
palettesList palettes and their named slots (filter by schema)
repaletteSwitch a canvas to another palette: same schema keeps pixels, others map by slot name or nearest color

Shapes: Write Geometry, Get Pixels

LLMs can't place pixels well, but they write coordinates fine. shapes rasterizes geometry at pixel centers with no anti-aliasing, so every pixel is one palette index. Soft fills come from ordered dithering:

json
shapes {  "width": 128, "height": 72, "palette": "scene-dusk",  "shapes": [    { "type": "rect", "x": 0, "y": 0, "w": 128, "h": 46, "fill": { "gradient": ["sky-top", "sky-mid", "sky-low"] } },    { "type": "circle", "cx": 92, "cy": 40, "r": 9, "fill": "sun" },    { "type": "polygon", "points": [[0,46],[22,26],[40,38],[62,20],[90,42],[128,40],[128,48],[0,48]], "fill": "far" },    { "type": "rect", "x": 0, "y": 46, "w": 128, "h": 26, "fill": { "gradient": ["water", "near"] } },    { "type": "curve", "points": [[34,56],[44,44],[56,56]], "color": "accent" }  ]}

Then repalette to scene-sea or scene-night for the same picture in another mood. In code: drawShapes(sprite, shapes, palette).

Landscapes from a Seed

landscape builds a whole scene from a seed in the scene schema, so one seed is one place you can show in any mood:

json
landscape { "seed": "harbor-town", "preset": "dusk" }landscape { "seed": "harbor-town", "preset": "dusk", "palette": "scene-night" }landscape { "seed": "pine-ridge", "time": "dawn", "layers": ["sky", "sun", "mountains", "forest", "ground"] }

Presets match the scene palettes: dawn, home, school, night, sea, storm, window, forest, dusk, stars. Layers: sky (dithered gradient), stars, sun or moon (with a halo, and glitter on water), clouds, mountains (midpoint-displacement ridge), hills (value noise), sea (waves), forest (pines and round trees), ground, rain. Default size 128×72. In code: landscape({ seed, preset }).

Creatures and Beings

creature mirrors a mask filled by the seed (body, maybe-body, empty), drops stray pixels, outlines it, lights it from the top and gives it eyes. Kinds: robot, alien, critter, plus nebula (asymmetric noise cloud with caught stars). being draws a person, cat or elf at a life stage from shapes: babies have big heads and no legs, old people white hair and a cane, old elves a staff, old cats a rounder body and a lowered tail.

json
creature { "seed": "voyager-7", "kind": "robot" }being { "species": "elf", "stage": "old", "palette": "scene-forest" }

Both use the scene schema, so they sit on a landscape in the same palette.

Three Layers of Control

Layer 1: animate_scene     → full scene in one call (fast path)Layer 2: sequence/compose  → manual frame composition (precise control)Layer 3: pixel/line/rect   → individual pixel editing (full control)

Start with animate_scene for a fast draft. Drop to lower layers to refine.

Example: One-Call Scene Animation

→ animate_scene {    width: 80, height: 40,    background: { tiles: [["grass","grass","stone","wall","door","wall"]] },    actors: [{      seed: "hero-girl", species: "human", armor: "cloth",      motion: "walk", from: {x:0, y:24}, to: {x:60, y:24}    }],    frames: 16, delay: 120  }← 16 frame PNGs + frame_ids
→ spritesheet { frames: [frame_ids], direction: "horizontal" }← single strip PNG with all 16 frames

Two calls: one to generate, one to assemble. Done.

Example: Drawing a Sprite from Scratch

→ create  { width: 16, height: 16, fill: "." }← canvas_id + hex grid
→ rect    { canvas_id, x: 3, y: 5, w: 10, h: 9, color: "1" }→ fill    { canvas_id, x: 7, y: 7, color: "8" }← filled: 56 pixels, leaked: false (grid returned — agent verifies)
→ inspect { canvas_id }← agent reads grid, spots issue, fixes with pixel tool
→ export  { canvas_id, scale: 4 }← 64x64 PNG

The Hex Grid Protocol

Every pixel is one character. The agent reads and writes in the same alphabet:

0-F = PICO-8 palette colors (0=black, 7=white, 8=red, ...).   = transparent
     0123456789ABCDEF  0: ................  1: .....111111.....  2: .....177771.....  3: .....177771.....  4: ...1111111111...  5: ...1888888881...  6: ...1788888881...

~80 tokens for a full 16x16 sprite. The LLM reads this like source code and reasons about it spatially.

Bundled Assets

22 sprites across 4 categories:

  • Items: sword, shield, potion, key, bow, coin
  • Tiles: grass, stone, water, wall, door, tree, sand, dirt
  • Effects: slash, sparkle, explosion, heal
  • UI: heart-full, heart-empty, arrow-up, cursor

648 procedural characters: 4 species (human, elf, dwarf, skeleton) x 3 armors x 3 weapons x 3 helms x 6 skin tones.

13 palettes: pico8 (default), grayscale, gameboy, and 10 scene moods (scene-dawn, home, school, night, sea, storm, window, forest, dusk, stars)

The scene palettes share one schema: the same 16 named slots (ink, sky-top, sky-mid, sky-low, sun, cloud, far, mid, near, ground, water, foam, accent, skin, cloth, light). Draw once with those slots, then render with any scene palette to get the same picture in another mood. In code: SCENE.ground, slotIndex(palette, 'water'), remapPalette(sprite, from, to).

6 motion types: idle, walk, attack, hurt, bounce, blink

CLI

bash
npx pixscii import sprite.png --id my-sword --category itemsnpx pixscii export sword --scale 4 --out sword.png

Use in the Browser: pixscii/core

Everything that draws, composes and renders also runs without Node. pixscii/core has no Node built-ins, no sharp and no MCP:

ts
import { createEmpty, drawRect, registerPalette, getPalette, renderToRGBA } from 'pixscii/core';
registerPalette({  id: 'dusk',  name: 'Dusk',  colors: [    { index: 0, hex: '#1A1016', name: 'sky' },    { index: 1, hex: '#E88FB0', name: 'sun' },    { index: 2, hex: '#3A2433', name: 'ground' },  ],});
let scene = createEmpty(32, 18, 0);scene = drawRect(scene, 13, 4, 6, 6, 1, true);scene = drawRect(scene, 0, 12, 32, 6, 2, true);
const { width, height, data } = renderToRGBA(scene, getPalette('dusk'), 8);canvas.getContext('2d')!.putImageData(new ImageData(new Uint8ClampedArray(data), width, height), 0, 0);

Bundled sprites, palettes and characters load through an asset source. In Node the MCP server and CLI use the files in sprites/. Elsewhere, pass anything that can read those files:

ts
import { setAssetSource, loadPalettes } from 'pixscii/core';
setAssetSource({  readJSON: (file) => fetch(`/pixscii/sprites/${file}`).then((r) => r.json()),  list: async (dir) => (dir === 'palettes' ? ['pico8.json', 'gameboy.json', 'grayscale.json'] : []),});await loadPalettes();

Development

bash
npm installnpm run dev      # Start MCP server (stdio)npm run build    # Compile TypeScriptnpm test         # Run tests
src/core/   pure TypeScript, runs anywhere (exported as pixscii/core)src/node/   sprites/ on disk, PNG encode and image import (sharp), CLIsrc/mcp/    MCP server and tools

src/core/boundary.test.ts fails if anything in core imports a Node built-in, sharp, MCP or a file outside core.

See ROADMAP.md for where pixscii is going: shapes, procedural landscapes and creatures.

License

MIT

Source: README.md at commit de290da

Tools

25

get

Get a sprite as a PNG image by its ID. Returns a scaled pixel art PNG.

Parametersidrequiredscalepalette

character

Generate a procedural pixel character sprite. Same seed always produces the same character. 648 unique combinations.

Parametershelmseedrequiredskinarmorscaleweaponpalettespecies

convert

Convert an image (URL or base64) to pixel art by quantizing to a palette. Returns both the PNG and sprite data.

Parametersscalewidthheightsourcerequiredpalette

create

Create a new blank canvas for drawing. Returns canvas ID and hex grid for inspection.

Parametersfillwidthrequiredheightrequiredpalette

pixel

Set individual pixels on a canvas. Batch up to 512 pixels per call.

Parameterspixelsrequiredcanvas_idrequired

line

Draw a line between two points on a canvas using Bresenham's algorithm.

Parametersx1requiredx2requiredy1requiredy2requiredcolorrequiredcanvas_idrequired

rect

Draw a rectangle on a canvas (outline or filled).

Parametershrequiredwrequiredxrequiredyrequiredcolorrequiredfilledcanvas_idrequired

fill

Flood fill from a point on a canvas. Returns the updated grid so you can verify the result.

Parametersxrequiredyrequiredcolorrequiredcanvas_idrequired

mirror

Mirror a canvas horizontally (left half copied to right half). Returns the updated grid.

Parametersaxis_xcanvas_idrequired

inspect

Read the current pixel state of a canvas as a hex character grid. For canvases >32px, provide x,y,w,h to inspect a region.

Parametershwxycanvas_idrequired

undo

Revert the last drawing operation on a canvas. Single-step undo.

Parameterscanvas_idrequired

export

Export a canvas as a scaled PNG image.

Parametersscalecanvas_idrequired

compose

Compose multiple sprites into a single scene. Place sprites at specific x,y positions on a canvas.

Parametersscalewidthrequiredheightrequiredlayersrequiredpalette

tilemap

Build a tilemap from a 2D grid of tile IDs. Each cell becomes a 16x16 tile.

Parametersgridrequiredscalepalette

spritesheet

Stitch multiple canvases into a single PNG spritesheet. Supports horizontal, vertical, or grid layout.

Parametersgapscaleframesrequiredcolumnspalettedirection

animate

Animate a sprite or character with pixel motion. Returns multiple PNG frames or a spritesheet.

Parametersidseedscalemotionrequiredpalette

sequence

Animate actors across a scene. Each actor has a pose cycle and a path of positions. Returns one PNG per frame.

Parametersdelayscalewidthrequiredactorsrequiredheightrequiredpalettebackground

animate_scene

Create a full animated scene in one call. Generate characters, place them on a background, and animate them along paths. Returns multiple PNG frames.

Parametersdelayscalewidthrequiredactorsrequiredframesheightrequiredpalettebackground

palettes

List palettes and their named slots. Palettes that share a schema (e.g. "scene") use each index for the same role, so swapping between them recolors the same art for a different mood.

Parametersschema

repalette

Switch a canvas to another palette. Within one schema the pixels stay and only the colors change; across schemas each color moves to the slot with the same name, or else the nearest color.

Parametersscalepaletterequiredcanvas_idrequired

shapes

Draw geometry as crisp pixel art: rect (with radius), circle, ellipse, polygon, line, curve. Fills can be a color, a dither of two colors, or a dithered gradient; filled shapes can have an outline. Draws on an existing canvas, or creates one. Write coordinates, not pixels.

Parametersscalewidthheightshapesrequiredpalettecanvas_id

landscape

Generate a pixel landscape from a seed: sky by time of day, sun or moon, stars, clouds, mountains, hills, sea, forest, ground, rain. Uses the "scene" palette schema, so the same seed renders in any scene-* palette. Presets: dawn, home, school, night, sea, storm, window, forest, dusk, stars. Returns a canvas you can keep drawing on.

Parametersseedrequiredtimescalewidthheightlayerspresethorizonpalette

creature

Generate a creature from a seed: symmetric robot, alien or critter from a mask (outlined, lit from the top, with eyes), or an asymmetric nebula. Endless variety, same seed same creature. Scene palette schema.

Parameterskindseedrequiredsizescalepalette

being

Draw a 24×24 person, cat or elf at a life stage: baby, adult or old (white hair, a cane or staff, a plumper cat). The seed varies hair and clothes. Scene palette schema.

Parametersseedscalestagerequiredpalettespeciesrequired

Version history

1
  1. v0.5.0LatestOct 29, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts