Goxel-MCP
by yberudev
README.md
# Goxel-MCP
A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for
the [Goxel](https://goxel.xyz) voxel editor. It lets any MCP client (Claude
Code, Claude Desktop, Gemini CLI, Codex CLI, and others) create and edit voxel
models with tools such as "draw a box", "recolor these voxels", "add a layer",
"save" and "export". You can work on files, or edit the scene that is open in
Goxel and watch the model change in the editor as you go.

- 17 tools: scenes, voxels, primitives, regions, colors, layers, preview,
save, export, validation, live editing and undo.
- Reads and writes Goxel's native `.gox` format, and MagicaVoxel's `.vox`.
Exports `.obj`/`.mtl`, `.txt` and `.png` natively, plus `.gltf`, `.glb`,
`.ply`, `.qb`, `.kv6`, `.kvx`, `.vxl` and `.pov` through Goxel's own
exporters.
- Built-in preview renderer: tools return PNG images, so the client can look
at the model it is building.
- Every file written is validated with Goxel's own parser, voxel by voxel,
when Goxel is available.
- Safe by default: all paths stay inside a workspace folder, nothing is
overwritten without asking, and backups are made before anything is
replaced.
- Local only: stdio transport, no network services, no accounts.
---
## Contents
1. [How it works](#how-it-works)
2. [Requirements](#requirements)
3. [Step-by-step setup](#step-by-step-setup)
4. [Using it](#using-it)
5. [Tools](#tools)
6. [Conventions](#conventions)
7. [Examples](#examples)
8. [Safety](#safety)
9. [Troubleshooting](#troubleshooting)
10. [Development](#development)
11. [Limitations](#limitations)
12. [License](#license)
---
## How it works
```
MCP client ──stdio──> goxel-mcp ──┬── file mode: scene in memory, read / written as .gox, .vox, ...
(Claude Code, │
Gemini CLI, ...) └── live mode: Unix socket ──> Goxel editor (command bridge)
```
**File mode** works everywhere and needs only Node.js. The scene is kept in
memory, and the tools read and write voxel files directly. The server has its
own readers and writers for `.gox` and `.vox`, written from Goxel's source
code.
**Live mode** edits the scene open in the Goxel editor. It uses the Goxel
*command bridge*: a small local server built into Goxel that listens on a Unix
socket (see [docs/BRIDGE.md](docs/BRIDGE.md)). Before each operation the
server reads the scene from Goxel, so edits you make by hand in the editor are
kept. It then sends only the changes back, as a single undo step.
The bridge is not part of the official Goxel release yet.
[`scripts/build-goxel.sh`](scripts/build-goxel.sh) builds Goxel from the
official sources and adds the bridge from
[`bridge/goxel-mcp-bridge.patch`](bridge/goxel-mcp-bridge.patch).
---
## Requirements
| | File mode | Live mode and Goxel exporters |
|---|---|---|
| Node.js 20 or newer | required | required |
| Goxel built with the bridge | – | required (step 3) |
| macOS | ✓ | ✓ |
| Linux / BSD | ✓ | ✓ (needs `scons`, `pkg-config`, GLFW and GTK 3 development packages) |
| Windows | ✓ | – (the bridge uses Unix sockets) |
---
## Step-by-step setup
### 1. Get the code
```bash
git clone https://github.com/yberudev/Goxel-MCP.git
cd Goxel-MCP
```
### 2. Install and build the server
```bash
npm install
npm run build
```
This creates `dist/index.js`, the MCP server. You can check it with:
```bash
npm test
```
### 3. Build Goxel with the command bridge (for live mode)
Skip this step if you only want to work with files.
```bash
npm run build:goxel
```
The script:
1. clones the official Goxel repository into `goxel-src/` (or uses
`GOXEL_SRC=/path/to/goxel` if you already have the sources);
2. copies the sources to `goxel-build/` and applies the bridge patch if
needed;
3. builds `goxel-build/goxel` in release mode.
Nothing is installed globally and `sudo` is never used. On macOS, missing
build tools (SCons, CMake, GLFW) are installed locally in `.tools/`. On
Debian / Ubuntu, install the dependencies first:
```bash
sudo apt install scons pkg-config libglfw3-dev libgtk-3-dev
```
On macOS you can also make a double-clickable application that starts Goxel
with the bridge for a given workspace:
```bash
sh scripts/make-app.sh /path/to/your/workspace
```
This creates `Goxel MCP.app` in the repository folder. The first time you
open it, macOS may ask you to confirm that you want to run it.
### 4. Choose a workspace
The workspace is the only folder the server reads and writes. Your models,
exports and previews go there, and the server keeps its backups and the
bridge socket in `<workspace>/.goxel-mcp/`. Set it with the
`GOXEL_MCP_WORKSPACE` environment variable; when the variable is not set,
the current directory is used.
### 5. Register the server with your MCP client
Replace `/path/to/Goxel-MCP` and `/path/to/workspace` with your own folders.
**Claude Code**, for the current project:
```bash
claude mcp add --scope project goxel -e GOXEL_MCP_WORKSPACE=/path/to/workspace -- node /path/to/Goxel-MCP/dist/index.js
```
or add this to `.mcp.json` at the root of the project:
```json
{
"mcpServers": {
"goxel": {
"type": "stdio",
"command": "node",
"args": ["/path/to/Goxel-MCP/dist/index.js"],
"env": { "GOXEL_MCP_WORKSPACE": "/path/to/workspace" }
}
}
}
```
**Claude Desktop**: add the same `"goxel"` entry under `"mcpServers"` in
`claude_desktop_config.json`.
**Gemini CLI**: add it to `.gemini/settings.json`:
```json
{
"mcpServers": {
"goxel": {
"command": "node",
"args": ["/path/to/Goxel-MCP/dist/index.js"],
"env": { "GOXEL_MCP_WORKSPACE": "/path/to/workspace" },
"timeout": 120000
}
}
}
```
**Codex CLI**:
```bash
codex mcp add goxel --env GOXEL_MCP_WORKSPACE=/path/to/workspace -- node /path/to/Goxel-MCP/dist/index.js
```
or in `~/.codex/config.toml`:
```toml
[mcp_servers.goxel]
command = "node"
args = ["/path/to/Goxel-MCP/dist/index.js"]
env = { GOXEL_MCP_WORKSPACE = "/path/to/workspace" }
tool_timeout_sec = 180
```
**Any other client**: start `node /path/to/Goxel-MCP/dist/index.js` with the
stdio transport.
### 6. Check the connection
Start a new session of your client. Approve the `goxel` server if the client
asks, then ask:
> Call goxel_info.
The answer lists the server version, the Goxel build found, the current
`mode` (`file` or `live`) and the supported formats.
---
## Using it
Just describe what you want. For example:
> Create a red voxel race car with four black wheels, dark windows and a big
> rear wing. Put each part on its own layer.
> Show me the car from the front and from the side.
> Make the rims black.
> Save the project as output/car/car.gox and export it for Blender.
### Live editing in Goxel
> Open output/car/car.gox in Goxel, live.
`goxel_open_in_app` starts the Goxel build with the bridge and connects to
it. If `Goxel MCP.app` (or `goxel --mcp-socket <workspace>/.goxel-mcp/goxel.sock`)
is already running, the server connects to it automatically when it starts,
or when asked with `goxel_live {action: "connect"}`.
From then on:
- every editing tool changes the scene open in the editor, and you see the
result right away;
- each tool call is one undo step in Goxel, so Ctrl+Z (⌘Z) reverts it;
- what you change by hand in the editor is kept, because the server reads
the scene before each operation;
- `goxel_save_scene` is done by Goxel itself;
- `goxel_render_preview {engine: "goxel"}` returns an image rendered by
Goxel, with its lighting and shadows.
`goxel_live {action: "disconnect"}` goes back to file mode and keeps the
current scene in memory.
### Exporting for Blender
- **OBJ:** `goxel_export {path: "output/car.obj", scale: 0.1}` writes
`car.obj` and `car.mtl`, one material per color, with hidden faces removed.
Blender imports it with *File › Import › Wavefront (.obj)*.
- **glTF:** `goxel_export {path: "output/car.gltf"}` uses Goxel's own glTF
exporter, and needs the Goxel build.
---
## Tools
| Tool | What it does |
|---|---|
| `goxel_info` | Versions, mode, supported formats and capabilities, scene summary |
| `goxel_new_scene` | Start an empty scene (the previous one is auto-saved if it had unsaved changes) |
| `goxel_open_scene` | Open a `.gox`, `.vox` or `.txt` file (in live mode, in the editor) |
| `goxel_add_voxels` | Set up to 200,000 voxels in one call; best for geometry computed by a script |
| `goxel_draw_primitive` | Up to 500 shape operations per call: box, sphere / ellipsoid, cylinder (with inner radius), cone, line, points; modes add / remove / paint; clip planes; mirror copies; one layer per operation |
| `goxel_erase_region` | Erase by box / shape and / or by color |
| `goxel_recolor_region` | Recolor by box / shape and / or by source color, with a tolerance |
| `goxel_transform` | Move the voxels of a layer or region |
| `goxel_layers` | `list`, `create`, `delete`, `rename`, `set_visible`, `set_active`, `duplicate`, `clear`, `merge_into` |
| `goxel_get_voxels` | Scene summary (bounding boxes, colors per layer) and voxel lists |
| `goxel_render_preview` | PNG preview: `iso`, `iso_back`, `front`, `back`, `left`, `right`, `top`; built-in renderer or Goxel's |
| `goxel_save_scene` | Save as `.gox`, with backup and validation |
| `goxel_export` | Export to `gox`, `vox`, `obj`, `txt`, `png`, and with Goxel to `gltf`, `glb`, `ply`, `qubicle`, `kv6`, `kvx`, `vxl`, `povray` |
| `goxel_validate_scene` | Check a file and compare it, voxel by voxel, with what Goxel's own parser reads |
| `goxel_open_in_app` | Start Goxel with the bridge and switch to live mode (or open the file in the official app) |
| `goxel_live` | `status`, `connect`, `disconnect` |
| `goxel_undo` | Undo / redo (Goxel's own history in live mode) |
All the arguments are described in [docs/TOOLS.md](docs/TOOLS.md). Tips for
building detailed models are in [docs/MODELING.md](docs/MODELING.md).
---
## Conventions
- Integer coordinates; voxel `(x, y, z)` fills the cube `[x, x+1] × [y, y+1] × [z, z+1]`.
- **Z is up**, like in Goxel. For vehicles and buildings it helps to use +X
as the front, Y as the width, and z = 0 as the ground.
- Colors: `"#rrggbb"`, `"#rrggbbaa"`, `[r, g, b]`, `[r, g, b, a]`, or names
such as `red`, `black`, `silver`, `glass`.
- Symmetric models: draw one half (y ≥ 0) and add
`mirror: [{axis: "y", center: -0.5}]` (y → −1 − y).
- Clip planes `{point, normal}` remove the voxels on the side the normal
points to, for slopes, windshields and bevels.
---
## Examples
The [`examples/`](examples) folder has three scripts that build complete
models through the MCP tools, with the official MCP client: the same calls an
MCP client makes.
```bash
node examples/red-sports-car.mjs # GT sports car built with primitives
node examples/stilt-house.mjs # stilt house on the water, voxel by voxel
node examples/supercar.mjs # supercar sculpted from height profiles
```
They write to `output/` inside the current directory, or inside
`GOXEL_MCP_WORKSPACE` when it is set. If Goxel is running with the bridge,
the model is drawn live in the editor.
| | |
|---|---|
|  |  |
---
## Safety
- Every path is resolved inside the workspace. `..` and symbolic links that
point outside of it are refused.
- Writing into the server's own folders (`src/`, `dist/`, `goxel-src/`,
`goxel-build/`, …) and into `.git/` or the clients' configuration folders is
refused.
- Existing files are never replaced without `overwrite: true`, except the
scene's own file when you save it. The previous version is copied to
`.goxel-mcp/backups/` first. Writes are atomic (temporary file + rename).
- `goxel_new_scene` and `goxel_open_scene` auto-save an unsaved scene before
replacing it. Destructive tools can be undone with `goxel_undo`.
- Logs go to stderr (`GOXEL_MCP_LOG_LEVEL=debug|info|warn|error`). Stdout is
only used by the MCP protocol.
- The bridge socket is only accessible by the current user (mode `0600`).
Goxel opens it only when it is started with `--mcp-socket` or
`GOXEL_MCP_SOCKET`.
---
## Troubleshooting
| Problem | Solution |
|---|---|
| The `goxel` tools do not show up | Start a new session of the client after registering the server, and approve it if asked. Check that `node /path/to/Goxel-MCP/dist/index.js` exists (run `npm run build`). |
| `goxel_open_in_app` times out the first time | macOS may be showing a security prompt for the new Goxel build. Accept it and try again. |
| A live call times out | A dialog is probably open in Goxel, or another client is connected to the bridge (only one client is served at a time). Close the dialog, or disconnect the other client. |
| A script cannot connect to the bridge while your client is connected | Same reason: call `goxel_live {action: "disconnect"}` first, and `connect` again afterwards. |
| The official Goxel app does not open the file | The official macOS build ignores files sent by Finder or `open`. Use *File › Open*, or the live mode. |
| glTF / PLY export is not available | Build Goxel with `npm run build:goxel`, or set `GOXEL_MCP_GOXEL_BIN` to a Goxel build with the bridge. |
| Where are the logs? | The server's stderr (your client's MCP log), and `<workspace>/.goxel-mcp/goxel-live.log` for Goxel. |
### Environment variables
| Variable | Default | Meaning |
|---|---|---|
| `GOXEL_MCP_WORKSPACE` | current directory | Folder for every file operation |
| `GOXEL_MCP_GOXEL_BIN` | `goxel-build/goxel` | Goxel build with the bridge |
| `GOXEL_APP` | `/Applications/goxel.app`, … | Official Goxel app (used with `live: false`) |
| `GOXEL_MCP_LOG_LEVEL` | `info` | `debug`, `info`, `warn` or `error` |
| `GOXEL_SRC`, `GOXEL_REPO`, `GOXEL_REF` | | Used by `scripts/build-goxel.sh` |
---
## Development
```bash
npm run build # compile TypeScript into dist/
npm test # unit tests + end-to-end MCP test over stdio
GOXEL_LIVE_TEST=1 npm test # + live test (opens a Goxel window)
```
The tests that use the Goxel build (validation, glTF export, live editing)
open a Goxel window for a moment. Set `GOXEL_MCP_SKIP_GOXEL=1` to skip them.
| Path | Content |
|---|---|
| `src/index.ts` | MCP server and tool definitions |
| `src/session.ts` | File / live modes (pull, edit, push the changes) |
| `src/bridge.ts` | Client of the Goxel command bridge |
| `src/operations.ts`, `src/shapes.ts` | Editing operations and shape rasterization |
| `src/formats/` | `.gox`, `.vox`, `.obj` and PNG readers / writers |
| `src/render.ts` | Software preview renderer |
| `src/workspace.ts` | Path sandbox, overwrite protection and backups |
| `bridge/` | The command bridge for Goxel (`mcp_bridge.c`, `mcp_bridge.h`) and the patch that adds it to Goxel |
| `scripts/` | Goxel build and macOS app packaging |
---
## Limitations
- When the server writes a `.gox` file itself (file mode), it keeps the
layers, names, visibility and voxels. Per-layer materials, cameras and
lights are not kept. In live mode Goxel saves the file itself, so
everything is kept.
- Clone layers, shape layers and image layers are read as empty layers, with
a warning.
- `.vox`: node rotations are ignored when reading. Models larger than 256³
are split automatically, and palettes are limited to 255 colors (quantized
automatically).
- The bridge serves one client at a time and is not available on Windows.
- When Goxel exports through its command line (validation, glTF, …), a window
opens for a moment.
---
## License
GPL-3.0-or-later, like Goxel. See [LICENSE](LICENSE).
Goxel is developed by Guillaume Chereau: https://github.com/guillaumechereau/goxel
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues