Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "pixelforge-plugins",
"version": "1.0.0",
"description": "Pixel art generation and sprite processing tools for game development.",
"owner": {
"name": "Tomas Grasl",
"url": "https://github.com/freema"
},
"plugins": [
{
"name": "pixelforge-mcp",
"source": "./",
"description": "Forge pixel art sprites, animations, backgrounds & thumbnails using Google Gemini"
}
]
}
14 changes: 14 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "pixelforge-mcp",
"version": "0.1.0",
"description": "Forge pixel art sprites, animations, backgrounds & thumbnails using Google Gemini. Auto prompt engineering, crop, background removal, and sprite sheet splitting.",
"mcpServers": {
"pixelforge": {
"command": "npx",
"args": ["-y", "pixelforge-mcp@latest"],
"env": {
"GEMINI_API_KEY": ""
}
}
}
}
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [20, 22]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci --no-audit --no-fund

- name: Lint
run: npm run lint

- name: Format check
run: npm run format:check

- name: Type check
run: npm run typecheck

- name: Test
run: npm run test:run

- name: Build
run: npm run build

- name: Upload artifacts
if: matrix.node-version == 20
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7
56 changes: 56 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Publish to npm

on:
release:
types: [published]
push:
tags:
- 'v*.*.*'
workflow_dispatch:

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: 'https://registry.npmjs.org/'
cache: 'npm'
always-auth: true

- name: Configure npm auth
run: |
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Format check
run: npm run format:check

- name: Type check
run: npm run typecheck

- name: Test
run: npm run test:run

- name: Build
run: npm run build

- name: Publish
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
11 changes: 11 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"pixelforge": {
"command": "npx",
"args": ["-y", "pixelforge-mcp@latest"],
"env": {
"GEMINI_API_KEY": ""
}
}
}
}
11 changes: 11 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "always",
"endOfLine": "lf",
"bracketSpacing": true
}
164 changes: 163 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,164 @@
# pixelforge-mcp
🎮 MCP server that forges pixel art sprites & game assets using Google Gemini — generate, crop, split & process, all from your AI

MCP server that forges pixel art sprites & game assets using Google Gemini — generate, crop, split & process, all from your AI assistant.

## Features

- **AI-powered generation** — sprites, animations, backgrounds, thumbnails via Google Gemini
- **Smart post-processing** — background removal, auto-crop, pixelation downscale, square padding
- **Sprite sheet splitting** — auto-detect and split sheets into individual frames
- **Style presets** — neon, retro, gameboy, snes, clean
- **Pure PNG pipeline** — zero-dependency PNG encoder/decoder, no native modules
- **Reference matching** — pass existing sprites to match visual style

## Installation

### Claude Code (CLI)

```bash
claude mcp add pixelforge npx pixelforge-mcp@latest \
--env GEMINI_API_KEY=your-api-key
```

### Claude Code (Plugin)

```bash
/plugin marketplace add freema/pixelforge-mcp
/plugin install pixelforge-mcp
```

Restart Claude Code to load the MCP server (check with `/mcp`).

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
"mcpServers": {
"pixelforge": {
"command": "npx",
"args": ["-y", "pixelforge-mcp@latest"],
"env": {
"GEMINI_API_KEY": "your-api-key"
}
}
}
}
```

### Manual (any MCP client)

Add to your `.mcp.json` or equivalent config:

```json
{
"mcpServers": {
"pixelforge": {
"command": "npx",
"args": ["-y", "pixelforge-mcp@latest"],
"env": {
"GEMINI_API_KEY": "your-api-key"
}
}
}
}
```

### Requirements

- Node.js >= 20
- [Google Gemini API key](https://aistudio.google.com/apikey)

## Tools

### `forge_sprite`

Generate a single pixel art sprite with automatic post-processing (crop, bg removal, downscale, square padding).

```
"Generate a green slime enemy sprite, 48px, retro style"
```

**Required:** `description`, `outputPath`
**Optional:** `size` (default: 48), `style`, `background`, `aspect`, `square`, `model`, `references`

### `forge_animation`

Generate animation frames as a sprite sheet, then auto-split into individual frame PNGs.

```
"Animate a slime bouncing, 4 frames"
```

**Required:** `description`, `action`, `outputPrefix`
**Optional:** `frames` (default: 3), `frameDescriptions`, `names`, `size`, `style`, `model`, `references`

### `forge_background`

Generate a full game background — no cropping, outputs the image as-is.

```
"Deep space background with stars and nebula, 16:9"
```

**Required:** `description`, `outputPath`, `aspect`
**Optional:** `style`, `model`

### `forge_thumbnail`

Generate a game thumbnail/screenshot. Pass `references` for visual consistency with your sprites.

```
"Space shooter scene with player ship vs alien rows"
```

**Required:** `description`, `outputPath`
**Optional:** `references`, `aspect` (default: 4:3), `style`, `model`

### `process_sprite`

Post-process an existing PNG — background removal, auto-crop, sprite sheet splitting.

```
"Split this sprite sheet into individual frames"
```

**Required:** `inputPath`
**Optional:** `outputPath`, `split`, `names`, `threshold`, `square`, `padding`, `skipCrop`, `skipTransparent`

### `optimize_sprite`

Downscale oversized AI images to true pixel art resolution using area-averaging (not blurry bilinear).

```
"Optimize this 1024px image down to 48px pixel art"
```

**Required:** `inputPath`, `size`
**Optional:** `outputPath`, `removeBackground`, `square`

> Full parameter docs: see [docs/tools.md](docs/tools.md)

## Models

| Alias | Model ID | Notes |
|-------|----------|-------|
| `nano-banana`, `banana` | nano-banana-pro-preview | **Default** — best for pixel art |
| `flash`, `gemini-flash` | gemini-3.1-flash-image-preview | Fast, reliable |
| `pro`, `gemini-pro` | gemini-3-pro-image-preview | Best quality |
| `25`, `gemini-25` | gemini-2.5-flash-image | Stable fallback |

## Prompts

### `pixel_art_guide`

Built-in MCP prompt with comprehensive pixel art generation guidelines — prompting rules, style tips, size recommendations, and best practices.

## License

MIT — see [LICENSE](LICENSE)

---

Built by [Tomas Grasl](https://tomasgrasl.cz)
34 changes: 34 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
import prettier from 'eslint-config-prettier';

export default [
{
files: ['src/**/*.ts'],
languageOptions: {
parser: tsparser,
parserOptions: {
project: './tsconfig.json',
sourceType: 'module',
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
'prefer-const': 'error',
'no-var': 'error',
eqeqeq: ['error', 'always'],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'off',
},
},
{
files: ['src/**/*.ts'],
...prettier,
},
{
ignores: ['dist/', 'node_modules/', '*.config.*'],
},
];
Loading