minipainter

io.github.ArturSkowronski由 GitHub 帳號 ArturSkowronski 發布v0.7.3更新於 Oct 24, 2026

Local-first miniature-paint inventory and cross-brand color matching for AI agents.

已驗證STDIO僅桌面位置與生活檔案與儲存

概覽

AI 產生的概覽

本地優先的微縮模型塗料登錄工具,讓助理搜尋內建塗料目錄、跨品牌比對顏色,並記錄你實際擁有的塗料。

可以做什麼
在內建的 1,607 款塗料目錄(Citadel、Army Painter、Vallejo、AK)中依名稱、用途、系列或近似顏色搜尋與檢視塗料,結果優先顯示已擁有的塗料,並提供每款塗料的 RGB 資訊。依顏色或描述比對最接近的塗料,包含跨品牌近似色。列出、標記為已擁有或未擁有本機庫存檔案中的塗料,讓建議優先採用你手邊有的塗料。彩色終端介面與命令列在助理之外提供同一套目錄與庫存功能。
適用情境
適合希望助理從自己現有塗料中推薦顏色、而非隨機給色的微縮模型塗裝者,也適合為某個特定色調尋找其他品牌的近似替代。
執行需求
透過 npx(npm 套件 minipainter)或原始碼在本機以 stdio 執行;需要 Node.js 18 或更新版本,以及類 POSIX 的 shell(Linux、macOS、WSL)。目錄已內建,無需設定;庫存預設位於 ~/.minipainting/inventory.json,可用 INVENTORY_PATH 覆寫。未宣告身分驗證。
安裝前請注意
助理可以修改你的庫存:標記已擁有和標記未擁有的工具會寫入庫存檔案,請檢查變更。庫存路徑可透過 INVENTORY_PATH 設定,只應指向你打算修改的檔案。RGB 值僅為近似參考色,不保證最終塗裝效果。README 另描述自架 HTTP 模式,其 /mcp 端點沒有身分驗證,同步端點由 INVENTORY_SYNC_TOKEN 保護;該模式與本機安裝相互獨立

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 minipainter,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

MINIPAINTER

The paint bench, indexed.

[CI] [npm]

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:

  • a deterministic local catalog (1,607 paints across Citadel, Army Painter, Vallejo, AK) and inventory
  • owned-first paint lookup and cross-brand color matching
  • a colored terminal UI (TUI) that shows each paint's real RGB as a swatch
  • MCP servers for both Claude Desktop and ChatGPT
  • a CLI surface designed for both humans and agent workflows

The colored TUI

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.

[MINIPAINTER terminal UI — catalog]

Why This Exists

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:

  • keep a local record of what is in your paint rack
  • search it quickly by name, role, family, and approximate color
  • prepare a stable inventory foundation for a future AI skill that can inspect links, photos, and model images

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.”

Feature Highlights

  • 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).

Screenshots

Hero Screen

Full-screen TUI with banner, catalog, detail panel, and command strip.

text
See: docs/assets/hero.txt

[Hero Screen]

Search View

Filtered lookup for a semantic search like bone.

text
See: docs/assets/search.txt

[Search View]

Owned View

Inventory-only presentation focused on what is already bound to your collection.

text
See: docs/assets/owned.txt

[Owned View]

CLI Flow

Representative command-line usage for search, ownership updates, and color matching.

text
See: docs/assets/cli.txt

[CLI Flow]

Run with Docker (Postgres)

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).

bash
docker compose up --build        # http://localhost:3000
  • GET /health — liveness
  • GET /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.

Deploy

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:

[Deploy to Render]

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.

Install

The fastest way — run it straight from npm with npx, no clone, no install:

bash
npx minipainter paint search bonenpx minipainter match color "#d2c29b"npx minipainter tui

Or install it globally to get the short mpaint command everywhere:

bash
npm install -g minipaintermpaint paint search bonempaint match color "#d2c29b"

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:

  • Node.js 18 or newer
  • POSIX-ish shell (Linux, macOS, WSL)

From source

To hack on it, clone and run against the working tree:

bash
git clone https://github.com/ArturSkowronski/minipainter.gitcd minipainternpm installnode src/cli.mjs paint search bone

After that you have four usage modes:

  • CLI / TUI — see Quickstart below
  • Self-hosted HTTP server — a single Docker-friendly runtime with JSON storage and API endpoints
  • Local MCP for Claude Desktop — see Claude Desktop MCP Setup
  • Remote MCP for Claude mobile/web — see Remote MCP

Quickstart

Initialize the local inventory at ~/.minipainting/inventory.json:

bash
node src/cli.mjs catalog sync

Search paints:

bash
node src/cli.mjs paint search blacknode src/cli.mjs paint search bone --json

Inspect one paint:

bash
node src/cli.mjs paint show "Abaddon Black" --json

Mark paints as owned or missing:

bash
node src/cli.mjs inventory own "Abaddon Black"node src/cli.mjs inventory unown "Abaddon Black"node src/cli.mjs inventory list

Run semantic or color matching:

bash
node src/cli.mjs match describe bonenode src/cli.mjs match color "#d2c29b"

Launch the TUI:

bash
node src/cli.mjs tui

Run the MCP server locally:

bash
node src/mcp-server.mjs

Run the self-hosted HTTP server locally:

bash
DATA_DIR=.minipainting-data node src/mcp-http-server.mjs

TUI Workflow

The TUI is centered around three presentation areas:

  • FORGE CATALOG: visible paints in the current scope
  • SELECTED PIGMENT: the currently highlighted paint with provider, families, usage, and RGB
  • RITUAL COMMANDS: the command legend for the active session

Current TUI commands:

  • search <text>
  • owned
  • catalog
  • toggle
  • quit

Recommended use:

  1. start with catalog
  2. narrow with search bone, search black, or similar queries
  3. inspect the selected pigment panel
  4. toggle ownership as your collection changes

Project Direction

Implemented now:

  • local JSON registry
  • starter provider catalogs for Citadel and Army Painter
  • owned / missing inventory tracking
  • deterministic search and color matching
  • colored terminal presentation with per-paint swatches
  • local MCP server for Claude Desktop

Planned later:

  • a separate skill for parsing paint-set links
  • image-driven inventory fill from paint bottle photos
  • model-photo analysis that recommends owned paints first
  • stronger cross-provider equivalents and matching hints

Technical Notes

  • Built-in catalog data lives in data/catalog/ (Citadel and Army Painter, kept in version control)
  • Inventory file: ~/.minipainting/inventory.json — stores only owned paint ids in the form { "version": 1, "owned": ["citadel/abaddon-black", ...] }
  • Self-hosted server data directory: DATA_DIR (defaults to /data in Docker); inventory lives at <DATA_DIR>/inventory.json
  • The catalog and inventory are composed at runtime; saving never rewrites the catalog
  • IDs are stable by convention (provider + name slug); on load, owned ids missing from the catalog are reported as warnings instead of being silently dropped
  • A pre-existing project-local .minipainting/registry.json next to the inventory path is auto-migrated on first run
  • Legacy .warpaint/ data directories are auto-renamed to .minipainting/ on first run (both home and project-local variants)
  • Override the inventory location at the API surface with { inventoryPath } or { cwd } (the latter resolves to <cwd>/.minipainting/inventory.json, which is what the test suite uses for isolation)
  • RGB values are approximate reference colors for matching, not a guarantee of final painted appearance
  • MCP entrypoint: node src/mcp-server.mjs
  • MCP helper script: npm run mcp
  • HTTP server helper script: npm run server
  • README demo captures are reproducible via:
bash
npm run generate:demo

Claude Desktop MCP Setup

minipainter now includes a local MCP server so Claude Desktop can use your paint registry directly.

Example local MCP config:

json
{  "mcpServers": {    "minipainter": {      "command": "node",      "args": ["/absolute/path/to/minipainter/src/mcp-server.mjs"]    }  }}

After adding the server, Claude Desktop can call tools such as:

  • paint_search
  • paint_show
  • inventory_list
  • inventory_mark_owned
  • inventory_mark_unowned
  • match_color
  • match_describe

Suggested local flow:

  1. initialize your registry once with node src/cli.mjs catalog sync
  2. add the MCP server to Claude Desktop
  3. ask Claude to search paints or update ownership through the exposed tools

Agent Skill

For 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.

bash
# project-scopedmkdir -p .claude/skills/minipaintercurl -fsSL https://arturskowronski.github.io/minipainter/SKILL.md \  -o .claude/skills/minipainter/SKILL.md

Or save it to ~/.claude/skills/minipainter/SKILL.md to use it everywhere.

Self-Hosted Docker

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):

bash
docker build -t minipainter .docker run -p 3000:3000 -v minipainting-data:/data minipainter

Or bring up the server together with Postgres in one step with docker compose up -d.

The server exposes:

  • GET /health
  • GET /api/paints
  • GET /api/paints/:paint
  • GET /api/inventory
  • PUT /api/inventory/:paint
  • DELETE /api/inventory/:paint
  • POST /api/match/color
  • POST /api/match/describe
  • POST /mcp

Optional runtime configuration:

  • PORT — listen port, defaults to 3000
  • DATA_DIR — persistent state directory, defaults to /data in Docker
  • AUTH_TOKEN — protects /api/* and /mcp with Authorization: Bearer ...
  • INVENTORY_SYNC_TOKEN — protects the legacy /inventory sync endpoint

Remote MCP (Claude Mobile)

For 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.

Local smoke test

bash
export INVENTORY_SYNC_TOKEN=$(openssl rand -hex 32)export PORT=3000export INVENTORY_PATH=$HOME/.minipainting/inventory.jsonnpm run mcp:http

Then in another shell:

bash
curl -s http://localhost:3000/healthcurl -s -X POST http://localhost:3000/mcp \  -H "Content-Type: application/json" \  -H "Accept: application/json, text/event-stream" \  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Sync endpoint (bearer-token protected)curl -s -H "Authorization: Bearer $INVENTORY_SYNC_TOKEN" \     http://localhost:3000/inventory

Deploy to Fly.io

The repo ships a Dockerfile and fly.toml. Full recipe in docs/deploy-fly.md. Short version:

bash
fly launch --no-deploy --copy-config --name <your-app-name>fly volumes create inventory_data --region <your-region> --size 1fly secrets set INVENTORY_SYNC_TOKEN="$(openssl rand -hex 32)"fly deploy

Connect Claude

In Claude (mobile or web), add a custom connector:

  • URL: https://<your-app-name>.fly.dev/mcp

The /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.

Environment variables

VariableRequiredPurpose
INVENTORY_SYNC_TOKENfor /inventoryBearer token protecting GET/POST /inventory; when unset, sync returns 503
INVENTORY_PATHnoPath to inventory.json; default ~/.minipainting/inventory.json locally, /data/inventory.json in the Docker image
INVENTORY_JSONnoOne-time seed JSON; only used when INVENTORY_PATH is absent on first boot
WARPAINT_INVENTORY_JSONnoLegacy alias of INVENTORY_JSON
MCP_SERVER_NAMEnoServer name in MCP handshake + startup log; default paint-inventory
PORTno (default 3000)TCP port to listen on

Known limitations

  • /mcp has no authentication yet. The bearer token only protects /inventory.
  • Stateless transport: no long-running SSE tool streams (the tools are fast so this is fine).

Self-hosting your own MCP

The MCP server is generic — only the CLI (mpaint) is branded. To run your own instance:

  1. Fork or clone the repo.

  2. (Optional) rename your Fly app in fly.toml.

  3. Create a Fly volume and set secrets:

    bash
    fly volumes create inventory_data --size 1 --region <your-region>fly secrets set INVENTORY_SYNC_TOKEN=$(openssl rand -hex 24)# Optional one-time seed:fly secrets set INVENTORY_JSON="$(cat ~/.minipainting/inventory.json)"
  4. (Optional) name your MCP server (shown in the MCP handshake and startup logs):

    bash
    fly secrets set MCP_SERVER_NAME=my-paints
  5. Deploy:

    bash
    fly deploy
  6. Register the remote in your local CLI and sync:

    bash
    mpaint sync add default \  --url https://my-app.fly.dev \  --token <token-from-step-3>mpaint sync push

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).

License

MIT © Artur Skowronski

來源:README.md,提交 fe3fd9b

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.7.3最新Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分