lpc-spritesheet-mcp
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., "@lpc-spritesheet-mcpGenerate a female archer spritesheet with red hair, teal hood, and a walk cycle"
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.
lpc-spritesheet-mcp
Give an AI agent a character artist's hands. This is the Universal-LPC-Spritesheet-Character-Generator web app re-implemented as a headless Node.js MCP server: an agent describes a character, and gets back a game-ready 832×3456 spritesheet with the exact frame layout — no browser, no screenshotting, no manual export button.
657 selectable items across 104 groups on the current asset pack: 6 body types (male, female, teen, child, muscular, pregnant), 91 hairstyles, 45 heads (human, beast, reptile, undead, …), clothes, armor, 40 weapons, 9 shields with heraldic patterns, hats, capes, tails, wings, prostheses, wheelchairs.
Named palette recoloring for skin, hair, eyes, cloth, metal and wood — 22 skintones, 26 hair colors, a 75-color universal palette.
15 animation row blocks on the standard sheet: 13 run in all four directions,
hurtandclimbship a single facing — that is exactly the 54 rows. Plus custom-animation blocks for wheelchairs and 128/192px oversize weapons and tools.Engine-ready output. Every render returns rows, frame counts, playback cycles and custom-block offsets, and
export_characterfans the same character out into per-animation or per-frame PNGs with a TexturePacker/Phaser JSON Hash atlas and a manifest, so a game engine never has to guess the layout or slice the sheet itself.Deterministic, and now proven.
npm run goldenrecords SHA-256 hashes of seven canonical renders against a pinned asset-pack revision, and the test suite fails if a render drifts.Attribution included. Each sheet gets
-credits.csv/-credits.txtbeside it naming the authors and licenses of the art actually used.
The server ships no art. It reads a local clone of the upstream asset pack and renders it,
entirely offline: no network calls, no telemetry, and one environment variable (LPC_ASSETS_DIR).
Install
The server needs the upstream asset pack once. Any of these three lines does it — pick one:
git clone --depth 1 https://github.com/LiberatedPixelCup/Universal-LPC-Spritesheet-Character-Generator ~/.lpc-spritesheet/lpc-generator-src
lpc-spritesheet-setup # same thing, via the npm bin after `npm install -g lpc-spritesheet-mcp`
npm run setup-assets # same thing, from a checkout of this repoThen wire the server into an MCP client: npx -y lpc-spritesheet-mcp, or npm install -g it and run
lpc-spritesheet-mcp. Prefer a checkout? git clone this repo and run node src/index.js. Updating
assets is a git pull in the pack clone.
The pack is looked up in this order, and the first valid entry wins:
$LPC_ASSETS_DIR../lpc-generator-src(sibling of the package — the dev-checkout convention)~/.lpc-spritesheet/lpc-generator-src(where the setup command above clones)
A valid pack contains both sheet_definitions/ and spritesheets/. If none is found the server
prints what it searched for and exits — it will not start half-configured.
Related MCP server: mnehmos.aseprite.mcp
Try it now
No MCP client required — the official protocol inspector drives the server from a shell:
# list the nine tools and their schemas
npx -y @modelcontextprotocol/inspector --cli node src/index.js --method tools/list
# or render a walk cycle and print the JSON payload that names the PNG it wrote
npx -y @modelcontextprotocol/inspector --cli node src/index.js --method tools/call \
--tool-name get_preview --tool-arg animation=walk --tool-arg scale=3 --tool-arg bodyType=female
# or drive it interactively: browse 657 items, call tools, view the result
npx @modelcontextprotocol/inspector node src/index.jsMCP client configuration
All of these run the same stdio server. LPC_ASSETS_DIR is optional — omit it if the pack is in one
of the two automatic locations above.
{
"mcpServers": {
"lpc-spritesheet": {
"command": "npx",
"args": ["-y", "lpc-spritesheet-mcp"]
}
}
}claude mcp add lpc-spritesheet -- npx -y lpc-spritesheet-mcp{
"mcpServers": {
"lpc-spritesheet": {
"command": "npx",
"args": ["-y", "lpc-spritesheet-mcp"],
"env": { "LPC_ASSETS_DIR": "D:/assets/lpc-generator-src" }
}
}
}{
"mcp": {
"servers": {
"lpc-spritesheet": { "type": "stdio", "command": "npx", "args": ["-y", "lpc-spritesheet-mcp"] }
}
}
}The nine tools
Tool | Purpose |
| All selection groups ( |
| One category: exact |
| Color names per material ( |
| The row layout of every animation (rows, frame counts, playback cycles, y-offsets) plus the custom blocks, which items provide them, and whether any item does. |
| Render the full universal sheet; returns the path, layout, warnings, credits and the asset-pack revision. |
| Render, then crop ONE animation into its own PNG — standard row block or custom block. |
| Render, then crop one direction's playback cycle, upscaled 1–8×. Small enough to return inline, so you also get the image itself, not just a path. |
| Render, then fan out into a directory bundle: |
| Audit instead of render: the port's row-block tables against the pack ( |
The render tools share one argument block: bodyType, selections, colors, character,
match_body_color, include_credits, include_character_json — plus output_path for the three
single-file tools and output_dir for export_character. Item IDs, display names, "none", and
{itemId, variant?, recolor?} objects are all accepted per group. character takes the web app's
saved-character JSON ({version: 2, selections}, or the fuller document this server writes) or a v1
document with a #sex=…&hair=… state hash; explicit selections/colors merge on top. A v1 hash
that names a retired group or a stale color comes back as warnings, not a failure. Defaults mirror
the web app — light-skinned body, human male head, neutral expression (note the head default is not
body-aware).
One call, start to finish
Ask your agent for "a female archer with red hair, a teal hood and a recurve bow, walking toward the viewer", or call the tool directly:
// tools/call → get_preview
{
"bodyType": "female",
"selections": { "hair": "Bangs", "clothes": "Longsleeve", "weapon": "Recurve", "hat": "Hood" },
"colors": { "body": "amber", "hair": "red", "clothes": "teal", "eyes": "green" },
"animation": "walk",
"direction": "down",
"scale": 3,
"output_path": "sprites/archer-walk.png"
}// ← result
{
"output": "…/sprites/archer-walk.png",
"bodyType": "female",
"image": { "width": 1536, "height": 192, "frameSize": 192 },
"animation": "walk", "direction": "down", "scale": 3,
"frames": [1, 2, 3, 4, 5, 6, 7, 8],
"warnings": [
"weapon_ranged_bow_recurve: no sprite for row(s) walk, custom:walk_128 — those rows will be empty (2 missing)"
],
"selections": {
"body": "body (amber)", "head": "heads_human_male (light)", "expression": "face_neutral (light)",
"hair": "hair_bangs (red)", "clothes": "torso_clothes_longsleeve (teal)",
"weapon": "weapon_ranged_bow_recurve [light]", "hat": "hat_hood_cloth (brown)",
"eyes": "heads_human_male [green] (color sub-selection)"
},
"credits": { "csv": "…/archer-walk-credits.csv", "txt": "…/archer-walk-credits.txt", "entries": 7 }
}That warning is the feature working: the recurve bow's definition claims a walk cycle but the pack
ships no walk.png for it, so the engine renders the archer, leaves the bow's walk row empty, and
tells you — one aggregated message per item, never a failure. A test renders this exact call and
asserts these exact numbers and this exact warning, so the example above cannot rot. Note also that
hat_hood_cloth stayed brown: colors.clothes recolors the torso group, not every cloth item.
Relative output_paths resolve against the server's working directory, not the client's. Omit
output_path entirely and the sheet lands in lpc-spritesheet/ under the OS temp directory, with a
timestamp suffix so two renders never overwrite each other.
What comes out
Rendering is fast enough to iterate on inside a conversation, but the number that matters is the first
call, not the steady state. Measured on Node 24 / Windows against pack revision 553ba75: ~200 ms to
load the 657-item catalog, ~1.1 s from process start to the server's ready line, ~0.53 s for the first
832×3456 sheet while sprite PNGs come off disk, then 3–10 ms per further render (including a weapon
sheet with 128px custom blocks) once the engine's image cache is warm — an animation crop ~8 ms, a
preview strip ~80–140 ms. A fresh MCP client pays the cold path once per process.
How it works
src/index.js is the MCP surface, src/character.js is the request pipeline, and src/engine/ is a
headless port of the upstream renderer: catalog reads the pack's JSON definitions, selection
normalizes what the agent asked for, recolor does CPU palette-swapping, sheet composites the draw
calls into the frame grid, and credits collects attribution. The engine knows nothing about MCP.
docs/ARCHITECTURE.md has the upstream-to-here map, every intentional
divergence, and diagrams of the module graph, one render call, and where files land on disk.
Sheet layout (stable)
13 columns × 54 rows of 64px frames = 832×3456. Directions run up, left, down, right within each row block:
Animation | Row | Frames/dir | Animation | Row | Frames/dir | |
| 0 | 7 |
| 30 | 3 | |
| 4 | 8 |
| 34 | 3 | |
| 8 | 9 |
| 38 | 8 | |
| 12 | 6 |
| 42 | 2 | |
| 16 | 13 |
| 46 | 13 | |
| 20 | 6 (1 row, down) |
| 50 | 6 | |
| 21 | 6 (1 row, up) | ||||
| 22 | 2 | ||||
| 26 | 5 |
watering and 1h_slash are aliases that resolve onto another block's frames (thrust and
backslash); combat and 1h_backslash/1h_halfslash own their rows and only differ in the
folder the pack ships them in. Custom blocks (64–192px frames) are appended below row 54 and can widen
the canvas to 1664px; the result payload reports every offset, so a consumer never has to derive them.
Known upstream asset gaps surface as warnings, one message per item — e.g. the child body ships
only hurt/idle/jump/sit/slash/walk, so its other rows come back empty by design, not by bug.
Licensing — read this before you ship
This server's code: GPL-3.0-only, because it derives from the GPL-3.0 upstream generator. See LICENSE.
The sprites it renders come from the Liberated Pixel Cup pack: a mix of OGA-BY 3.0, CC-BY-SA 3.0, CC-BY 3.0/4.0 and GPL held by many artists. Every render writes
*-credits.csv/*-credits.txtbeside the PNG listing exactly the authors, licenses and links for the assets used. Keep those files when you redistribute renders.The images in this README are themselves renders, so they carry attribution too:
docs/img/showcase-credits.csvanddocs/img/demo-credits.csv.
Development
npm install
npm run setup-assets # or lpc-spritesheet-setup if you installed globally
npm test # 66 passing items: 25 engine, 16 stdio MCP, 15 surface, 9 golden, 1 smoke
npm run golden # re-record test/golden.json after an intended rendering change
npm run assets # regenerate every committed image (docs/img/)npm test is the only automated gate — there is no lint, format or typecheck tooling in this repo, so
nothing else is claimed. CI runs the suite on Node 20 and 22 across Ubuntu and Windows, and asserts
that the server fails cleanly when the pack is missing.
See CONTRIBUTING.md, the issue templates under
.github/, docs/ARCHITECTURE.md and
docs/capability-inventory.md (everything the upstream generator
can do).
Acknowledgements
Built on the Universal-LPC-Spritesheet-Character-Generator
by Johannes Sjölund (wulax), bluecarrot16, Stephen Challener (Redshrike), ElizaWy, JaidynReiman and
the many LPC artists credited in its CREDITS.csv — this project exists to make their work usable
from AI agents. All sprites remain the property of their respective authors under the licenses noted
above.
This server cannot be deployed
Maintenance
Related MCP Connectors
Generate pixel art sprites, animations, 8-direction rotations and palettes for games.
AI game assets for agents: consistent sprites, 2D animations, tiles, maps, music and engine exports.
Create AI animations and export transparent sprite sheets, alpha video, frames, and game assets.
Generate game sprite sheets and animations from an image, and clean up sprite backgrounds.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceGenerates random Universal LPC spritesheet characters as full animation PNGs, compositing real sprite layers via a Cloudflare Worker with browser rendering.1-
- AlicenseNot gradedqualityCmaintenanceEnables 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
- FlicenseBqualityCmaintenanceEnables users to automate the creation, editing, animation, and export of pixel-art game assets through a multi-agent pipeline that derives style specs and blueprints, generates Lua build scripts, and drives the canvas editor to produce .aseprite files, spritesheets, atlases, GIFs, and previews.12-
- AlicenseNot gradedqualityCmaintenanceConverts a single character image into game-ready 2D sprite animations (walk, run, idle, attack, etc.) with transparent frames, sprite sheets, and metadata, usable from AI coding agents.MIT