Local-first miniature-paint inventory and cross-brand color matching for AI agents.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
The paint bench, indexed.
Site: arturskowronski.github.io/minipainter
minipainter is a local-first paint registry for miniature-painting workflows. It exists for one practical reason: AI paint suggestions are much more useful when they understand the paints you actually own.
The project gives you:
The ledger TUI is a real colored terminal app: a MINIPAINTER banner, gold section
frames, green OWNED / red MISSING status, and a truecolor swatch of every paint's own
RGB. Color turns on for a TTY and honors NO_COLOR.
Most paint advice workflows break at the same point: they recommend paints you do not have on hand.
minipainter is built to solve that exact problem:
The long-term goal is not βAI picks random colors for miniatures.β The goal is βAI reasons from your actual inventory first, then suggests stronger alternatives only when useful.β
Owned-first matching: lookups and recommendations can prioritize paints you already have.Catalog in repo, inventory in your home: paint records live in data/catalog/; what you own lives in ~/.minipainting/inventory.json and follows you across projects.RGB-aware search: approximate RGB values help with nearest-color matching.Colored TUI: terminal ledger with per-paint RGB swatches and OWNED/MISSING status.Agent-friendly CLI: deterministic command output for AI integration (Claude + ChatGPT MCP).Full-screen TUI with banner, catalog, detail panel, and command strip.
Filtered lookup for a semantic search like bone.
Inventory-only presentation focused on what is already bound to your collection.
Representative command-line usage for search, ownership updates, and color matching.
The whole stack β MCP/HTTP server plus a Postgres that stores your inventory β starts with
one command. Inventory persists in a named volume, so it survives container restarts and
docker compose down / recreation (only down -v wipes it).
GET /health β livenessGET /api/inventory β owned paints (from Postgres)POST /mcp β MCP for Claude Desktop Β· POST /mcp/v3 β MCP for ChatGPT (search/fetch)Storage is selected by DATABASE_URL: set it (as docker-compose.yml does) for Postgres,
leave it unset to use a local JSON inventory file (unchanged local behavior). See .env.example.
Any Docker + Postgres host works (Fly.io, Railway, a VPSβ¦). For a one-click remote MCP
server with a managed database, the repo ships a Render Blueprint (render.yaml) that
provisions the web service and Postgres together and wires DATABASE_URL automatically:
The reference deployment warpaint-mcp.fly.dev runs on Fly.io with Fly Managed Postgres β see
docs/deploy-fly.md for the fly mpg attach + migration steps.
The fastest way β run it straight from npm with npx, no clone, no install:
Or install it globally to get the short mpaint command everywhere:
The catalog is bundled, so search and matching work on first run with nothing to configure. Your inventory lives at ~/.minipainting/inventory.json, created automatically the first time you mark a paint owned (legacy ~/.warpaint/ is auto-migrated).
Requirements:
To hack on it, clone and run against the working tree:
After that you have four usage modes:
Initialize the local inventory at ~/.minipainting/inventory.json:
Search paints:
Inspect one paint:
Mark paints as owned or missing:
Run semantic or color matching:
Launch the TUI:
Run the MCP server locally:
Run the self-hosted HTTP server locally:
The TUI is centered around three presentation areas:
FORGE CATALOG: visible paints in the current scopeSELECTED PIGMENT: the currently highlighted paint with provider, families, usage, and RGBRITUAL COMMANDS: the command legend for the active sessionCurrent TUI commands:
search <text>ownedcatalogtogglequitRecommended use:
catalogsearch bone, search black, or similar queriesImplemented now:
Planned later:
data/catalog/ (Citadel and Army Painter, kept in version control)~/.minipainting/inventory.json β stores only owned paint ids in the form { "version": 1, "owned": ["citadel/abaddon-black", ...] }DATA_DIR (defaults to /data in Docker); inventory lives at <DATA_DIR>/inventory.json.minipainting/registry.json next to the inventory path is auto-migrated on first run.warpaint/ data directories are auto-renamed to .minipainting/ on first run (both home and project-local variants){ inventoryPath } or { cwd } (the latter resolves to <cwd>/.minipainting/inventory.json, which is what the test suite uses for isolation)node src/mcp-server.mjsnpm run mcpnpm run serverminipainter now includes a local MCP server so Claude Desktop can use your paint registry directly.
Example local MCP config:
After adding the server, Claude Desktop can call tools such as:
paint_searchpaint_showinventory_listinventory_mark_ownedinventory_mark_unownedmatch_colormatch_describeSuggested local flow:
node src/cli.mjs catalog syncFor Claude Code, fetch the skill straight from the site, no clone required. It ships with the
right guardrails baked in: JSON-only reads, product_format rules, failure handling.
Or save it to ~/.claude/skills/minipainter/SKILL.md to use it everywhere.
The Docker image runs a single HTTP server runtime designed for self-hosted use. Build it from the repo (no image is published to a registry yet):
Or bring up the server together with Postgres in one step with docker compose up -d.
The server exposes:
GET /healthGET /api/paintsGET /api/paints/:paintGET /api/inventoryPUT /api/inventory/:paintDELETE /api/inventory/:paintPOST /api/match/colorPOST /api/match/describePOST /mcpOptional runtime configuration:
PORT β listen port, defaults to 3000DATA_DIR β persistent state directory, defaults to /data in DockerAUTH_TOKEN β protects /api/* and /mcp with Authorization: Bearer ...INVENTORY_SYNC_TOKEN β protects the legacy /inventory sync endpointFor Claude mobile or web, the stdio MCP server above is not reachable. Run
minipainter-mcp-http instead β a Streamable HTTP MCP transport exposing the
same tools, plus GET/POST /inventory for syncing the local inventory.
Then in another shell:
The repo ships a Dockerfile and fly.toml. Full recipe in
docs/deploy-fly.md. Short version:
In Claude (mobile or web), add a custom connector:
https://<your-app-name>.fly.dev/mcpThe /mcp endpoint currently has no authentication β anyone with the URL can
call tools. Use the obscurity of the URL plus Fly's network controls for now;
add per-user auth before sharing the URL.
| Variable | Required | Purpose |
|---|---|---|
INVENTORY_SYNC_TOKEN | for /inventory | Bearer token protecting GET/POST /inventory; when unset, sync returns 503 |
INVENTORY_PATH | no | Path to inventory.json; default ~/.minipainting/inventory.json locally, /data/inventory.json in the Docker image |
INVENTORY_JSON | no | One-time seed JSON; only used when INVENTORY_PATH is absent on first boot |
WARPAINT_INVENTORY_JSON | no | Legacy alias of INVENTORY_JSON |
MCP_SERVER_NAME | no | Server name in MCP handshake + startup log; default paint-inventory |
PORT | no (default 3000) | TCP port to listen on |
/mcp has no authentication yet. The bearer token only protects /inventory.The MCP server is generic β only the CLI (mpaint) is branded. To run your
own instance:
Fork or clone the repo.
(Optional) rename your Fly app in fly.toml.
Create a Fly volume and set secrets:
(Optional) name your MCP server (shown in the MCP handshake and startup logs):
Deploy:
Register the remote in your local CLI and sync:
After this, your local inventory and the deployed MCP stay in sync via
mpaint sync push (upload local β remote) and mpaint sync pull --force
(overwrite local from remote).
MIT Β© Artur Skowronski
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/minipainter)<a href="https://allmcps.com/mcp/minipainter"><img src="https://allmcps.com/api/badge/minipainter?style=directory" alt="Minipainter on AllMCPs" /></a>