lpc-spritesheet-mcp
README.md
# lpc-spritesheet-mcp
[](./LICENSE)
[](./package.json)
[](https://www.npmjs.com/package/lpc-spritesheet-mcp)
[](../../actions)
**MCP server that generates [Universal LPC](https://lpc.opengameart.org) character spritesheets headlessly** — the [Universal-LPC-Spritesheet-Character-Generator](https://github.com/LiberatedPixelCup/Universal-LPC-Spritesheet-Character-Generator) web app, re-implemented as a Node.js MCP server so AI agents can compose and render game-ready character sheets without a browser.
<p align="center">
<img src="docs/img/hero.png" alt="Knight, archer and mage — generated by this server" width="720">
</p>
- **657 selectable items** across 104 groups: 6 body types (male, female, teen, child, muscular, pregnant), 91 hairstyles, 45 heads (human/beast/reptile/undead/…), clothes, armor, 40 weapons, shields with heraldic patterns, hats, capes, tails, wings, prostheses, wheelchairs…
- **Named palette recoloring** for skin/hair/eyes/cloth/metal/wood (22 skintones, 26 hair colors, 74-color universal palette…).
- **15 standard animations** × 4 directions (walk, slash, thrust, spellcast, shoot, hurt, climb, idle, jump, sit, emote, run, combat idle, backslash, halfslash) on the standard **832×3456** sheet (13×54 frames of 64px), plus **custom-animation blocks** for wheelchairs and 128/192px oversize weapons/tools.
- Engine-ready results: every render returns the exact frame layout (rows, frame counts, playback cycles, custom-block offsets), and per-asset **attribution files** are written next to each sheet as the upstream licenses require.
The server does **not** bundle any art: it reads a local clone of the upstream asset pack and renders it with `@napi-rs/canvas` — fully offline.
## Install
```bash
npm install -g lpc-spritesheet-mcp # or just use npx (see below)
# one-time: fetch the ~350MB asset pack the server renders from
npm run setup-assets # clones into ~/.lpc-spritesheet/lpc-generator-src
```
Prefer a local checkout? Clone the repo, `npm install`, and either run
`npm run setup-assets` or clone
[Universal-LPC-Spritesheet-Character-Generator](https://github.com/LiberatedPixelCup/Universal-LPC-Spritesheet-Character-Generator)
yourself next to it as `../lpc-generator-src`. Any location works if you point
`LPC_ASSETS_DIR` at it. Updating assets = `git pull` in that clone.
## MCP client configuration
Run command (stdio): `npx lpc-spritesheet-mcp` (or `node <path>/src/index.js`).
<details>
<summary>ZCode (<code>~/.zcode/cli/config.json</code>)</summary>
```json
{
"mcp": {
"servers": {
"lpc-spritesheet": {
"type": "stdio",
"command": "npx",
"args": ["-y", "lpc-spritesheet-mcp"]
}
}
}
}
```
</details>
<details>
<summary>Claude Desktop (<code>claude_desktop_config.json</code>)</summary>
```json
{
"mcpServers": {
"lpc-spritesheet": {
"command": "npx",
"args": ["-y", "lpc-spritesheet-mcp"]
}
}
}
```
</details>
<details>
<summary>Cursor / generic (with a custom asset location)</summary>
```json
{
"mcpServers": {
"lpc-spritesheet": {
"command": "npx",
"args": ["-y", "lpc-spritesheet-mcp"],
"env": { "LPC_ASSETS_DIR": "D:/assets/lpc-generator-src" }
}
}
}
```
</details>
## Tools
| Tool | Purpose |
|---|---|
| `list_categories` | All selection groups (body, hair, head, clothes, legs, shoes, weapon, hat, shield, tail, wings, …) with item counts. Start here. |
| `list_items` | Items of one category: exact `itemId`s, display names, pre-sliced variants; recolor colors deduplicated into a response-level `palettes` map. |
| `list_palettes` | Color names per material (body=skintone, hair, cloth, eye, metal, wood, all). |
| `list_animations` | Animation row layout (rows, frame counts, playback cycles) + custom-animation definitions and which items provide them. |
| `generate_spritesheet` | Render the full universal sheet PNG + custom blocks; returns paths, layout, warnings, credits. |
| `get_animation` | Render + crop ONE animation into its own PNG (e.g. walk = 832×256, 9 frames × 4 directions). |
| `get_preview` | Render + crop a playback-cycle strip for one direction — quick visual check. |
### Example
Ask your agent for *"a female archer with red hair and a bow, teal hood, and a walk cycle"*, or call directly:
```jsonc
{
"tool": "get_preview",
"arguments": {
"bodyType": "female",
"selections": { "hair": "Bangs", "clothes": "Longsleeve", "weapon": "Recurve Bow", "hat": "Hood" },
"colors": { "body": "amber", "hair": "red", "clothes": "teal", "eyes": "green" },
"animation": "walk",
"direction": "down",
"scale": 3,
"output_path": "sprites/archer-walk.png"
}
}
// → { "output": "…/archer-walk.png", "image": { "width": 1536, "height": 192 },
// "frames": [1,2,3,4,5,6,7,8], "credits": { … } }
```
<p align="center">
<table>
<tr>
<td align="center"><img src="docs/img/walk-strip.png" alt="get_preview: knight walk cycle, down" width="480"><br><sub><code>get_preview</code> — walk cycle, down, 3×</sub></td>
<td align="center"><img src="docs/img/sheet-katana.png" alt="generate_spritesheet: full katana sheet" width="150"><br><sub><code>generate_spritesheet</code> — full sheet (katana,<br>two 128px custom blocks at the bottom)</sub></td>
</tr>
</table>
</p>
Regenerate the showcase images yourself with `npm run showcase`.
ItemIds, display names, `"none"`, and `{itemId, variant?, recolor?}` objects are all accepted per group; a saved-character JSON (`{version:2, selections}` from the web app) can be passed as `character` and explicit `selections`/`colors` merge on top. Defaults mirror the web app (light-skinned male body, human male head, neutral expression).
## Sheet layout (stable)
13 columns × 54 rows of 64px frames. Row blocks (directions top-to-bottom: up, left, down, right): spellcast r0 (7f), thrust r4 (8f), walk r8 (9f), slash r12 (6f), shoot r16 (13f), hurt r20 (1 row, 6f, down-facing), climb r21 (1 row, 6f, up-facing), idle r22 (2f), jump r26 (5f), sit r30 (3f), emote r34 (3f), run r38 (8f), combat_idle r42 (2f), backslash r46 (13f), halfslash r50 (6f). `watering`/`combat`/`1h_*` are aliases of these rows. Custom blocks (64–192px frames) are appended below and can widen the canvas; the result payload reports every offset.
## Licensing — important
- **This server's code:** GPL-3.0-only — it is a port of the GPL-3.0 upstream generator. See [LICENSE](./LICENSE).
- **The sprites it renders** come from the Liberated Pixel Cup asset pack: a mix of **OGA-BY 3.0, CC-BY-SA 3.0, CC-BY 3.0/4.0 and GPL** licenses held by many artists. The server writes `*-credits.csv` / `*-credits.txt` next to every generated sheet listing exactly the authors, licenses and links for the assets used — **keep these files when you redistribute renders**, and check `CREDITS.csv` in the asset repo for details.
## Development
```bash
npm test # 32 tests: engine + real stdio MCP protocol tests
```
See [CONTRIBUTING.md](./CONTRIBUTING.md), [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) (upstream→port mapping and port invariants) and [docs/capability-inventory.md](./docs/capability-inventory.md) (everything the upstream generator can do).
## Acknowledgements
Built on the [Universal-LPC-Spritesheet-Character-Generator](https://github.com/LiberatedPixelCup/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.