material-workbench
by hoklims
README.md
# Material Workbench
Recipe-driven, **deterministic** procedural materials and isometric terrain tiles for game engines — a Python engine, a desktop app, and an MCP server, all rendering from the same JSON recipe.

[](LICENSE)
[](pyproject.toml)
[](https://github.com/hoklims/material-workbench/actions/workflows/ci.yml)
---
A **recipe** is a small JSON document — an archetype plus a handful of parameters and a seed. Feed it to the engine and you get back textures: PBR map sets for 3D engines (Unreal/Godot/Unity), or hand-painted-looking isometric ground tiles for 2D/iso games. Same recipe, same seed, same bytes — every time. The render is content-addressed and cached by a hash of the recipe, so nothing is recomputed twice.
## What you get
- **Two archetypes today**
- `metal_rust` — procedural rusted metal: 5 PBR maps (base color, normal, roughness, metallic, AO), tileable.
- `painted_grass` — Dofus-style painted terrain: a mottled green wash, grass tufts, and scattered blossoms, projected to a **2:1 isometric diamond** with a transparent surround.
- **Three ways to drive it**
- **CLI** — `material-workbench render recipe.json --out ./out` writes the PBR maps to disk.
- **Desktop app** (Tauri + React + Three.js) — pick a preset, tweak sliders, preview in 3D (materials) or as an iso tile (terrain), and export.
- **MCP server** — expose the workbench as tools to an MCP-capable agent over stdio.
- **Cached** — every recipe carries a `render_hash`; identical recipes hit the cache instead of re-rendering.
- **Adding an archetype is one registry entry** plus a render function — no central refactor.
| Painted grass → iso tile | Rusted metal base color |
| --- | --- |
|  |  |
## Prerequisites
The Python engine is cross-platform. The desktop app targets **Windows 11** today (the Rust toolchain is pinned to `stable-x86_64-pc-windows-msvc`); the sidecar has a POSIX fallback but the Tauri shell is not yet wired/tested for macOS/Linux.
| Tool | Version | Needed for |
| --- | --- | --- |
| [uv](https://docs.astral.sh/uv/) | latest | Python env + commands |
| Python | 3.12 (`>=3.12,<3.13`) | engine, CLI, MCP, sidecar |
| Node.js + npm | 20.19+ (or 22.12+) | desktop app frontend (Vite 7) |
| Rust (rustup) | stable | desktop app shell |
| MSVC C++ Build Tools + WebView2 | — | Tauri on Windows |
## Quickstart
### Python engine / CLI
```bash
uv sync --extra dev
uv run pytest # run the test suite
uv run material-workbench render examples/recipe-rusty-floor.json --out ./out
```
`render` writes the PBR maps to `./out`. It works for any archetype the engine supports (`metal_rust`, `painted_grass`); the isometric tile projection is exposed through the desktop app and the JSON-RPC service.
### Desktop app
> **Order matters.** The Rust shell launches the Python engine as a sidecar by locating `.venv/Scripts/python.exe` (walking up from the binary). Run `uv sync` at the repo root **before** starting the app, or set `PYTHON_BIN` to a Python with the package installed.
```bash
uv sync # 1. create the .venv the app will find
cd tauri
npm install # 2. frontend deps
npm run tauri dev # 3. build the Rust shell + launch
```
Pick a preset (`Prairie`, `Prairie fleurie`, `Herbe rase`, or the `metal_rust` presets), hit
**Render (force)**, change the seed for variations, then **Export tuile iso…** to write a
transparent 2:1 diamond PNG (terrain) — or **Export to UE5…** to write the BC/N/ORM PBR set (materials).
To build a distributable bundle: `npm run tauri build`.
### MCP server
```bash
uv run material-workbench serve-mcp # FastMCP over stdio
```
Register it with any MCP client (the tool surface mirrors the service: archetypes, recipes, render, cache).
## How it works
```
recipe.json ──► normalize + validate ──► engine (numpy/PIL) ──► PBR maps ──► cache (by render_hash)
│
┌────────────────────────────────────────┼─────────────────────────┐
CLI JSON-RPC sidecar (Tauri app) MCP server
(write maps) (render, iso-tile export, recipes) (agent tools)
```
The engine is pure `numpy` + `Pillow` (no GPU, no external services). Transport adapters (CLI, JSON-RPC, MCP) are thin wrappers around a single `MaterialWorkbenchService`. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the full layering.
## Project layout
```
src/material_workbench/ Python engine, IR, cache, adapters (CLI / JSON-RPC / MCP)
tauri/ Desktop app (React + Three.js frontend, Rust shell)
examples/ Sample recipes
tests/ pytest suite (engine, services, adapters)
tools/ Calibration & snapshot scripts (dev only)
docs/ Architecture & assets
```
## Contributing
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the dev setup, test/lint commands, and pull-request flow. By participating you agree to the [Code of Conduct](CODE_OF_CONDUCT.md).
## License
[MIT](LICENSE) © 2026 hoklims
TDQS
B3.4/5.0
Scored across 12 tools
Disambiguation5/5
Each tool targets a distinct action and resource: archetypes, cache, recipes (multiple operations), rendering, server control, and workspace. No two tools overlap significantly in purpose.
Naming Consistency5/5
All tools follow a consistent verb_noun pattern using lowercase snake_case (e.g., recipe_read, render_run). No deviations or mixed conventions.
Tool Count5/5
12 tools cover the domain comprehensively without unnecessary duplication. The number feels appropriate for a material/workbench server.
Completeness4/5
Core workflows (read, write, normalize, validate, mutate, render) are present, but there is no explicit delete recipe tool or a way to list all recipes. Minor gaps that agents might work around.
Maintenance
ActivityInactive
ResponsivenessNo issues