PixelLab Forge MCP
# PixelLab Forge MCP
An MCP server that connects AI assistants to the [PixelLab](https://pixellab.ai) pixel art generation API. Generate sprites, tilesets, characters, animations, and more directly from Claude, Cursor, or any MCP-compatible client.
Generated images are automatically saved to `./pixellab-forge-output/` in your project directory, ready to be moved into your game assets.
## Prerequisites
- **Node.js** 18 or later
- A **PixelLab API key** — get one at [pixellab.ai/account](https://pixellab.ai/account)
## Setup
No installation needed. `npx` downloads and runs the package automatically on first use.
> **Package registry:** `pixellab-forge-mcp` is published to the public [npm registry (npmjs.org)](https://www.npmjs.com/package/pixellab-forge-mcp) — that's what `npx`/`npm install` use. It is **not** distributed via GitHub Packages, so the repo's `/pkgs/npm/…` page will 404; that's expected.
### Claude Code (CLI)
```bash
claude mcp add pixellab-forge-mcp -e PIXELLAB_API_KEY=your-api-key-here -- npx pixellab-forge-mcp
```
This adds it to the current project. To make it available across all your projects:
```bash
claude mcp add pixellab-forge-mcp -s user -e PIXELLAB_API_KEY=your-api-key-here -- npx pixellab-forge-mcp
```
That's it. Claude Code will start the server automatically when you begin a conversation.
### Claude Desktop
Add to your config file:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"pixellab-forge-mcp": {
"command": "npx",
"args": ["pixellab-forge-mcp"],
"env": {
"PIXELLAB_API_KEY": "your-api-key-here"
}
}
}
}
```
### Cursor
Add to `.cursor/mcp.json`:
```json
{
"mcpServers": {
"pixellab-forge-mcp": {
"command": "npx",
"args": ["pixellab-forge-mcp"],
"env": {
"PIXELLAB_API_KEY": "your-api-key-here"
}
}
}
}
```
### Other MCP Clients
Any MCP client that supports stdio transport can use PixelLab Forge. Set the command to `npx pixellab-forge-mcp` and pass `PIXELLAB_API_KEY` as an environment variable.
## Generated Images
When a tool returns image data, PixelLab Forge automatically saves the images as PNGs to `./pixellab-forge-output/` in whatever directory the MCP server is running from (usually your project root).
Image inputs can be passed by **`file_path`** instead of inline base64 — any image argument accepts `{ "file_path": "pixellab-forge-output/sprite.png" }`, which the server resolves from disk before calling the API (saves passing large base64 blobs through the model). Paths are restricted to the output directory and workspace root. The dedicated `read_image` tool remains available for loading an image explicitly.
Add this to your `.gitignore`:
```
pixellab-forge-output/
```
## Available Tools (103)
Generation tools automatically poll for results — no manual job status checking needed. If a job takes longer than 10 minutes or the connection drops, use `list_pending_jobs` to find the job ID and `get_job_status` to retrieve the result.
### Image Generation
| Tool | Description | Key Options |
|------|-------------|-------------|
| `generate_image` | Generate pixel art from text | `reference_images`, `style_image`, `style_options`, `no_background`, `seed` |
| `generate_with_style` | Match style from 1-4 references | `style_images`, `style_description`, `no_background`, `seed` |
| `generate_ui` | Game UI elements (buttons, panels, icons) | `concept_image`, `color_palette`, `no_background`, `seed` |
| `create_image_pixen` | Pixen engine (max area 512×512, dims ÷4) | `outline`, `detail`, `view`, `direction`, `no_background`, `enhance_prompt`, `seed` |
| `create_image_pixflux` | Pixflux engine (32-400px) | `text_guidance_scale`, `init_image`, `color_image`, `no_background`, `isometric`, `outline/shading/detail`, `seed` |
| `create_image_pixflux_background` | Pixflux engine tuned for backgrounds/scenes | Same as `create_image_pixflux` |
| `create_image_bitforge` | Bitforge engine (max 200px) | `text_guidance_scale`, `style_image`, `inpainting_image`, `mask_image`, `color_image`, `skeleton_keypoints`, `outline/shading/detail`, `seed` |
### Pro Flash
Newest engine. Native sizes 16×16 to 96×96 (custom 16–256, multiples of 4). Image results carry a durable `source_image_id` you can reuse to build a character or object from the same image without paying for it again.
| Tool | Description | Key Options |
|------|-------------|-------------|
| `create_image_pro_flash` | Generate one native pixel-art image | `image_size`, `style_image`, `style_options`, `no_background`, `seed`, `project_id` |
| `edit_image_pro_flash` | Edit by text or reference; canvas never resizes | `method` (text/reference), `description`, `reference_image`, `use_color_palette_correction`, `no_background`, `seed` |
| `inpaint_image_pro_flash` | Repaint only white mask pixels | `mask_image`, `context_image` + `bounding_box`, `output_method`, `crop_to_mask`, `no_background`, `seed` |
| `create_character_pro_flash` | Saved character: first frame + 8 v3 views in one call | `image_size`, `source_image_id` or `first_frame`, `view`, `template_id`, `n_directions`, `style_image`, `seed` |
| `create_object_pro_flash` | Saved object: first frame + optional 8 views | `image_size`, `source_image_id` or `first_frame`, `view`, `n_directions` (1/8), `style_image`, `seed` |
| `get_pro_flash_capabilities` | Native presets, beta dimension rules, supported controls (free) | |
| `get_pro_flash_cost` | Provisional cost split into first-image + rotation units (free) | `operation`, `width`, `height`, `n_directions` |
### Characters & Objects
| Tool | Description | Key Options |
|------|-------------|-------------|
| `create_character_v3` | Character via v3 model (32-256px, newest) | `reference_image` (rotate exact character) or text-only, `view`, `template_id`, `outline`, `detail`, `enhance_prompt`, `no_background`, `seed` |
| `create_character_pro` | Character/object via Pro engine (32-168px) | `method` (style/concept/rotate), `concept_image`, `reference_image`, `style_description`, `view`, `template_id`, `no_background`, `seed` |
| `create_character_4dir` | Character with N/S/E/W views | `proportions`, `view`, `text_guidance_scale`, `outline/shading/detail`, `color_image`, `force_colors`, `template_id`, `isometric`, `seed` |
| `create_character_8dir` | Character with 8 directional views | Same as 4dir |
| `create_character_state` | New state/variant of a saved character | `character_id`, `edit_description`, `use_color_palette_from_reference`, `no_background`, `seed` |
| `animate_character` | Animate saved character (template only) | `template_animation_id` (walking, fireball, breathing-idle, etc. — [47 templates](docs/prompting-guide.md#animation-templates)), `action_description`, `directions`, `outline/shading/detail`, `seed` |
| `create_character_animation` | Animate saved character (template/v3/pro) | `character_id`, `mode`, `template_animation_id`, `action_description`, `frame_count`, `directions`, `seed` |
| `create_object_1dir` | Object, single direction (32-256px) | `size`, `view` (top-down/sidescroller), `style_images`, `item_descriptions` |
| `create_object_8dir` | Object with 8 directional views (32-256px) | `size`, `view`, `reference_image` (rotate exact) or `style_image` (new in style) |
| `animate_object` | Animate a saved object | `object_id`, `mode` (v3/pro), `animation_description`, `directions`, `frame_count`, `custom_start_frame`, `end_frame`, `enhance_prompt` |
| `create_object_state` | New state/variant of a saved object | `object_id`, `edit_description`, `seed` |
| `select_object_frames` | Keep specific candidate frames as objects | `object_id`, `indices`, `common_tag` |
| `dismiss_object_review` | Accept an object as-is (clear review) | `object_id` |
| `list_characters` / `list_objects` | List with pagination | `limit`, `offset` |
| `get_character` / `get_object` | Get details by ID | |
| `delete_character` / `delete_object` | Delete by ID | |
| `delete_character_animations` / `delete_object_animations` | Delete animations (all, or scoped) | `animation_type`, `animation_group_id`, `direction` |
| `download_character_zip` | Export character as ZIP (saved to `pixellab-forge-output/`, returns file path) | |
| `download_character_spritesheet` / `download_object_spritesheet` | Export as one uniform-grid spritesheet PNG + layout JSON (ZIP saved to `pixellab-forge-output/`) | |
| `update_character_tags` / `update_object_tags` | Manage tags | |
| `set_character_portrait` | Attach a bust portrait to a character (free; used by `vocal_animation`) | `character_id`, `image` |
### Animation
| Tool | Description | Key Options |
|------|-------------|-------------|
| `animate_with_text` | Animate from text + reference | `text_guidance_scale`, `image_guidance_scale`, `n_frames`, `init_images`, `color_image`, `seed` |
| `animate_with_text_v2` | Animate existing image (32-256px) | `reference_image`, `action`, `view`, `direction`, `no_background`, `seed` |
| `animate_with_text_v3` | Animate from first/last keyframes | `first_frame`, `last_frame`, `frame_count`, `no_background`, `seed` |
| `animate_pixminimax` | Beta (tier 1+): fluid 4–40 frame clips via PixMiniMax, up to 256px | `first_frame`, `last_frame`, `description`, `frame_count`, `drift_threshold`, `enhance_prompt`, `direction`, `no_background`, `seed` |
| `animate_with_skeleton` | Pose control via keypoints | `skeleton_keypoints`, `reference_guidance_scale`, `pose_guidance_scale`, `isometric`, `color_image`, `seed` |
| `edit_animation` | Edit animation frames (2-16) | `frames`, `description`, `no_background`, `seed` |
| `interpolate_frames` | Generate in-between frames | `start_image`, `end_image`, `action`, `no_background`, `seed` |
| `transfer_outfit` | Apply outfit to frames | `reference_image`, `frames`, `no_background`, `seed` |
| `estimate_skeleton` | Extract keypoints from image | `image`, `image_size` |
### Rotation
| Tool | Description | Key Options |
|------|-------------|-------------|
| `generate_8_rotations` | 8 directional views (32-168px) | `method` (rotate/style/concept), `view`, `style_description`, `no_background`, `seed` |
| `generate_8_rotations_v3` | 8 rotations from one frame (v3) | `first_frame`, `no_background`, `seed` |
| `rotate` | Rotate between views/directions | `from_view/to_view`, `from_direction/to_direction`, `view_change`, `direction_change`, `image_guidance_scale`, `isometric`, `seed` |
### Editing & Inpainting
| Tool | Description | Key Options |
|------|-------------|-------------|
| `edit_images` | Batch edit 1-16 images | `method` (text/reference), `description`, `reference_image`, `no_background`, `seed` |
| `edit_image` | Edit single image | `image`, `description`, `width`, `height`, `text_guidance_scale`, `color_image`, `no_background`, `seed` |
| `edit_image_pixen` | Edit on the Pixen model; preserves pose and pixel style (max 256px source) | `image`, `description`, `width`, `height`, `no_background`, `seed` |
| `inpaint_v3` | Mask-based editing | `mask_image`, `bounding_box`, `crop_to_mask`, `no_background`, `seed` |
| `inpaint` | Inpainting (legacy, max 200px) | `mask_image`, `text_guidance_scale`, `outline/shading/detail`, `isometric`, `color_image`, `seed` |
### Image Operations
| Tool | Description | Key Options |
|------|-------------|-------------|
| `image_to_pixelart` | Convert photo to pixel art | `image`, `output_size` |
| `image_to_pixelart_pro` | Convert photo to pixel art (Pro, auto-sizes) | `image`, `description`, `seed` |
| `resize_image` | AI-powered pixel art resize | `reference_image`, `target_size`, `color_image` |
| `remove_background` | Remove background (max 400px) | `background_removal_task`, `text_hint` |
| `unzoom` | Recover native-resolution art from an upscaled image (min 256px, result is opaque) | `image`, `quantize` |
| `correct_pixelart` | Clean stray/anti-aliased pixels without resizing (batch frames together) | `images`, `strength` |
| `reduce_colors` | Quantize frames onto one shared palette, optional dithering | `images`, `num_colors` or `palette_image`, `dithering`, `dithering_strength` |
### Tilesets
| Tool | Description | Key Options |
|------|-------------|-------------|
| `create_tileset` | Top-down tileset (16 or 32px) | `lower/upper/transition_description`, `tile_size`, `view`, `text_guidance_scale`, `tile_strength`, `tileset_adherence`, `lower/upper/transition_reference_image`, `seed` |
| `create_tileset_sidescroller` | Platformer tileset | `lower_description`, `transition_description`, `text_guidance_scale`, `tile_strength`, `tileset_adherence`, `base_tile_id`, `seed` |
| `create_isometric_tile` | Isometric tile (16-64px) | `isometric_tile_shape` (block/thick/thin), `text_guidance_scale`, `outline/shading/detail`, `color_image`, `seed` |
| `create_tiles_pro` | Pro tiles (hex, iso, octagon, square) | `tile_type`, `tile_size`, `tile_view`, `tile_depth_ratio`, `style_images`, `style_options`, `n_tiles`, `seed` |
| `get_tileset` / `get_tileset_sidescroller` / `get_isometric_tile` / `get_tiles_pro` | Retrieve by ID | |
| `list_tilesets` / `list_tilesets_sidescroller` / `list_isometric_tiles` / `list_tiles_pro` | List with pagination | `limit`, `offset` |
| `delete_tileset` / `delete_tileset_sidescroller` / `delete_isometric_tile` / `delete_tiles_pro` | Delete by ID | |
### Map Objects
| Tool | Description | Key Options |
|------|-------------|-------------|
| `create_map_object` | Game-ready object | `view`, `outline/shading/detail`, `text_guidance_scale`, `background_image`, `inpainting`, `color_image`, `seed` |
| `get_map_object` | Status + metadata by ID | `object_id` |
### UI Assets & Fonts
| Tool | Description | Key Options |
|------|-------------|-------------|
| `create_ui_asset` | Persistent shape-based UI panel (distinct from the one-shot `generate_ui`) | `image_size`, `elements`, `pieces` (shape layout), `style_image`, `color_palette`, `no_background`, `name`, `project_id` |
| `get_ui_asset` / `list_ui_assets` / `delete_ui_asset` | Retrieve, list (paginated), or delete UI assets | `ui_asset_id`; `limit`, `offset` |
| `generate_font_pro` | Styled pixel-art font (glyph atlas + `.ttf`) | `description`, `weight`, `image_size`, `glyph_px`, `font_name` |
| `portrait_character_pro` | Convert between a bust portrait and a full-body sprite (both directions) | `direction`, `image`, `view`, `result_size`, `seed` |
### Talking Animation
Generate mouth positions once per expression (`vocal_animation` is the only step that costs generations), then produce unlimited talking GIFs or engine-ready lip-sync plans for free.
| Tool | Description | Key Options |
|------|-------------|-------------|
| `vocal_animation` | Generate mouth positions ("visemes") for a portrait (costs generations, once per expression) | `character_id` or inline `portrait` (max 256×256), `mood`, `viseme_count` (3/5/7/12), `no_background`, `seed` |
| `get_vocal_animation_job` | Poll a `vocal_animation` job (visemes stream in as produced) | `job_id` |
| `talking_gif` | Text → animated GIF of the character speaking (free) | `text`, `character_id` or `visemes`, `mood`, `frame_ms`, `hold_ms` |
| `lip_sync` | Frame-by-frame mouth plan for driving lips in a game engine (free, nothing rendered) | `text`, `character_id` or `viseme_count`, `mood`, `frame_ms`, `hold_ms` |
### Prompt Enhancement
Expand a short description into a richer prompt. These return enhanced **text only** — they do not generate images.
| Tool | Description | Key Options |
|------|-------------|-------------|
| `enhance_character_prompt` | Enrich a prompt for `create_character_v3` | `description`, `image_size`, `view`, `outline`, `detail` |
| `enhance_animation_prompt` | Enrich a motion prompt for `animate_with_text_v3` | `first_frame`, `action`, `last_frame` |
| `enhance_pixen_prompt` | Enrich a prompt for `create_image_pixen` | `description`, `image_size`, `outline`, `detail`, `view`, `direction`, `no_background` |
### Account & Jobs
| Tool | Description |
|------|-------------|
| `get_balance` | Check your credit balance |
| `get_job_status` | Check a background job by ID |
| `get_font_pro_job` / `get_portrait_character_pro_job` | Check a font-pro / portrait↔character job (dedicated endpoints) |
| `list_pending_jobs` | List jobs that haven't completed (for recovery after disconnection) |
| `list_job_history` | Recent job history (auto-pruned after 24h) |
| `read_image` | Load a saved PNG as a Base64 image to pass into other tools |
### Common Options
Most tools share these parameters, but the field names differ between endpoint generations:
| Concept | v2 endpoints | Legacy endpoints |
|---------|-------------|------------------|
| Prompt adherence | n/a | `text_guidance_scale` (1-20) |
| Transparent background | `no_background` | `no_background` |
| Color reference | n/a | `color_image` (reference image) |
| Style controls | n/a | `outline`, `shading`, `detail` |
| Negative prompt | n/a | `negative_description` |
| Isometric mode | n/a | `isometric`, `oblique_projection` |
| Reproducibility | `seed` | `seed` |
Character, object, tileset, and map object endpoints also accept `text_guidance_scale`, `outline`, `shading`, `detail`, and `color_image`.
## Usage
Just describe what you want in plain language. The assistant picks the right tool and parameters automatically.
### Quick Examples
**Sprites and icons:**
```
"Generate a 64x64 pixel art knight with a blue cape, no background"
"Make a 16x16 health potion icon"
"Create a 128x128 dragon boss with detailed shading and thick outlines"
```
**Characters (persistent, multi-directional):**
```
"Create a 48x48 character with 4 directions: a dwarf blacksmith in a leather apron, chibi proportions"
"Animate that character with the walk template"
"Now add a fireball animation"
```
**Tilesets:**
```
"Create a 32x32 top-down tileset: ocean water below, sandy beach on top, foam transition"
"Make a 16x16 sidescroller tileset with stone platforms"
```
**Editing existing art:**
```
"Edit this sprite to make the armor gold instead of silver"
"Remove the background from this image"
"Generate 8 rotations of this character"
```
### Which Tool Gets Used?
The assistant picks the right tool automatically, but the key decision is:
- **`generate_image`** — default for most requests, highest quality, largest sizes
- **`generate_with_style`** — when you want new art matching existing art ("in the same style as these sprites")
- **`generate_ui`** — for game UI elements (buttons, panels, health bars, icons)
- **`create_tileset` / `create_tiles_pro`** — for tileable terrain; standard for square RPG tiles, pro for hex/isometric/octagon
- **`create_character_4dir` / `8dir`** — for persistent characters you can animate later by ID
### Key Concepts
- **Sizes are in pixels** as `width x height` — different tools have different limits (e.g. characters max 128x128, `generate_image` goes up to 792x688)
- **Transparent backgrounds** are the default on most tools — ask for a background explicitly if you want one
- **Characters are persistent** — once created, you can animate them by ID without re-describing
- **Seeds** make results reproducible — same seed + same description = same output
For detailed size limits, style controls, endpoint comparison, and step-by-step workflows, see the **[Prompting Guide](docs/prompting-guide.md)**.
### Prompt Commands
PixelLab Forge includes MCP prompt templates that appear as slash commands in supported clients (Claude Desktop, Cursor, etc.):
| Command | Description |
|---------|-------------|
| `pf:help` | Overview of all tools and how to use them |
| `pf:sprite` | Generate a pixel art sprite |
| `pf:character` | Create a character with directional views + animation |
| `pf:animate` | Animate an existing sprite or character |
| `pf:tileset` | Create a top-down or sidescroller tileset |
| `pf:tiles` | Create hex, isometric, or octagon tiles |
| `pf:ui` | Generate game UI elements |
| `pf:style` | Generate art matching existing sprites' style |
| `pf:edit` | Edit or modify an existing sprite |
## Reliability
- **Auto-polling**: Generation jobs are polled every 2 seconds for up to 10 minutes
- **Retry on failure**: Network errors during polling are retried 3 times with backoff
- **Job recovery**: If the connection drops, job IDs are logged to stderr and persisted to disk. Use `list_pending_jobs` to find them and `get_job_status` to retrieve results
- **Image saving**: Generated images are automatically saved as PNGs to `./pixellab-forge-output/`
## Testing
```bash
npx @modelcontextprotocol/inspector node dist/index.js
```
Set `PIXELLAB_API_KEY` in the inspector's environment variables, connect, and test any tool.
## Contributing
Contributions are welcome via pull requests.
See [CHANGELOG.md](CHANGELOG.md) for release history. Maintainers: see [RELEASING.md](RELEASING.md) for the release process.
## License
MIT
TDQS
Scored across 103 tools
Many tools have near-overlapping purposes: generate_image, create_image_bitforge, create_image_pixflux, create_image_pixen, and create_image_pro_flash all generate pixel art, and character/animation creation is similarly fragmented across 4dir/8dir/v3/pro/pro_flash and v2/v3 text animation variants. The descriptions try to steer selection, but the boundaries are still unclear enough that an agent will frequently face ambiguous choices.
Most names follow a readable verb_noun snake_case pattern, but consistency breaks down with irregular version/engine suffixes like v2, v3, pro, pro_flash, bitforge, pixflux, and pixen pasted onto similar operations. The broader pattern is recognizable, but tool-to-tool naming is not predictable enough to guess the right variant.
103 tools is an extreme count for a single MCP server, driven largely by multiple overlapping engine generations and legacy alternatives for the same core capabilities. This is well beyond a manageable scope and will impose a heavy navigation burden on agents.
Domain coverage is very strong: characters, objects, tilesets, UI assets, animations, images, jobs, and talking portraits all have solid create/read/update/delete and conversion workflows. Minor gaps exist—fonts have generate/get but no list/delete, and map objects lack full lifecycle management—but no critical dead ends block the main pixel-art generation workflow.