Skip to main content
Glama
hoklims

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.

![Four painted grass tiles projected to 2:1 isometric diamonds](docs/assets/grass-iso-grid.png)

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](pyproject.toml)
[![CI](https://github.com/hoklims/material-workbench/actions/workflows/ci.yml/badge.svg)](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 |
| --- | --- |
| ![Grass iso tile](docs/assets/grass-iso.png) | ![Rust base color](docs/assets/rust-basecolor.png) |

## 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