Contents
MCX is a stateful CLI for inspecting one Minecraft .litematic structure and maintaining agent-readable selection state. It is read-only with respect to schematic blocks.
Why MCX: the thing about 3D in LLM is a problem of compressing existing information, not generating it. The harness is built for inspection; the LLM can still generate code to generate 3D.
These rules hold unconditionally. Any violation returns a structured JSON error.
| Category | Invariant | Detail |
|---|---|---|
| Input | Format | .litematic only |
| Input | Region count | Exactly one component/region per file |
| Palette | Index 0 | Must be minecraft:air; files that cannot satisfy this fail |
| State | Scope | One state file ↔ one loaded litematic |
| State | Command prereq | All commands except load and clear require loaded state |
| Output | Format | Success and error outputs are always JSON |
| Output | Help | mcx, mcx -h, mcx --help print human-readable help |
| Output | Narrowing | Success JSON narrowable with --jsonpath PATH |
| Output | Folding | Long arrays folded by default; disable with --fulljson |
| Coordinates | Order | Always y,z,x; y is vertical |
| Coordinates | Frame | Loaded-schematic-local coordinates |
| Coordinates | Bbox | Min-inclusive, max-exclusive: [y0,z0,x0, y1,z1,x1] |
| Selection | Default scope | Commands operate on the current selection |
| Encoding | Supported | semantic_chunk_rle (default) and raw |
| Palette | Sort order | Descending block count, then by blockstate string |
MCX keeps a JSON state file tracking the loaded schematic, selections, geometry context, and active anchor. All writes are atomic (temp file → fsync → rename).
Loaded litematic metadata · palette · geometry context · current selection · named selections · active anchor.
state.geometry)| Field | Valid values | Default | How to change |
|---|---|---|---|
encoding | semantic_chunk_rle, raw | semantic_chunk_rle | Set at load --encoding |
chunk_size_yzx | Any positive cubic size | [16,16,16] | Edit directly in state file |
compact_method | majority, weighted, surface_blocks, surface_faces | majority | Edit in state file (no CLI flag) |
Selection note: a selected minecraft:air cell is still selected. An unselected cell is encoded as the pseudo blockstate mcx:unselected.
Every MCX command outputs a top-level JSON envelope. The ok field discriminates success from failure.
The result object is command-specific. Its structure is documented per command below.
See the Error Types section for all possible type values.
MCX supports two geometry encodings set at load time. Switching requires a reload.
Splits geometry into fixed-size chunks. Each chunk has its own local palette and a CODE:COUNT RLE body. Semantic codes (e.g. S_L for spruce log) are designed to be readable by LLMs.
| Token | Meaning |
|---|---|
CODE:N | N consecutive blocks of type CODE |
| space | Separate runs within a row |
; | Separate rows (z axis) |
| | Separate layers (y axis) |
Always y → z → x with x fastest (innermost). Each row must decode to exactly shape_yzx[2] cells. Each layer must have exactly shape_yzx[1] rows. Each body must have exactly shape_yzx[0] layers.
y,z,x chunk order (x changes fastest)chunk_size_yzxmcx:unselected marks unselected cellsA fixed-width palette-symbol grid. Easy to visually inspect, but may spend tokens on selected air and unselected cells.
blocks[y][z] is one row string. Row string length = shape_yzx[2] × symbol_width.
| Symbol | Blockstate |
|---|---|
. (× symbol_width) | minecraft:air |
~ (× symbol_width) | mcx:unselected |
| Other | Assigned in stable loaded-palette-index order |
If one-character symbols are insufficient, MCX increases symbol_width automatically.
Palette codes are short human-readable aliases. The algorithm generates the shortest unique prefix without inventing arbitrary codes.
minecraft:)facing, axis, etc.)InvalidPalette error (no arbitrary fallback)| Blockstate | Code | Reasoning |
|---|---|---|
minecraft:stone | ST | stone → ST |
minecraft:sand | SA | sand → SA (distinguishes from stone) |
minecraft:spruce_log | S_L | spruce + log → S_L |
minecraft:spruce_planks | S_P | spruce + planks → S_P |
minecraft:spruce_stairs | S_S | spruce + stairs → S_S (only one stairs variant) |
minecraft:spruce_stairs[facing=north] | S_S_N | state discriminator appended when multiple variants present |
minecraft:spruce_stairs[facing=east] | S_S_E | state discriminator appended when multiple variants present |
minecraft:smooth_stone | SM_ST | smooth + stone → SM_ST (if needed to distinguish) |
minecraft:stone_slab | ST_SL | stone + slab → ST_SL (if needed to distinguish) |
Each line = one y-layer. Rows separated by ;. Runs are CODE:COUNT separated by spaces. The 4 lines are joined by | in the actual JSON string.
code values must be unique within a chunkblockstate values must be unique within a chunkInvalidPalette errorInvalidPalette error (not arbitrary fallback)
flowchart LR
A[/"mcx load"/] -->|creates| S[("state.json")]
B[/"mcx clear"/] -->|deletes| S
S --> C[/"mcx info"/]
S --> D[/"mcx print"/]
S --> E[/"mcx query blocks"/]
S --> F[/"mcx select"/]
S --> G[/"mcx diff"/]
S --> H[/"mcx anchors"/]
All commands except load and clear require loaded state. Commands below are expandable.
| Flag | Default | Description |
|---|---|---|
--encoding | semantic_chunk_rle | Geometry encoding for this state |
Validates invariants, stores geometry context, resets anchor to [0,0,0], sets current selection to the entire litematic, and replaces prior state.
Falls back to MCIO NBT/block-container primitives for older single-region files; success output includes a warnings entry when this path is used.
Returns: loaded schematic metadata · geometry context · current selection occupancy · active anchor · symbol width · full palette.
Never prints the stored selection representation — only summary data.
The candidate must have the same size_yzx as the loaded schematic.
| Error type counted | Definition |
|---|---|
| Occupancy error | One side is air, other is non-air |
| Blockstate error | Matching occupancy but different exact blockstate strings |
Read-only; does not mutate state. Empty selections return zero counts and 0.0 rates.
| Mode | Flag | Description |
|---|---|---|
| Exact | (default) | Full selection bbox; unselected cells → mcx:unselected |
| Compact | --compact N | Downsampled; caps each representative axis at N; strategy from state.geometry.compact_method |
| Projection | --projection DIR | Collapses one axis to a single visible non-air surface layer |
state.geometry.compact_method)| Method | Strategy |
|---|---|
majority | Most frequent selected blockstate in integer source region (default) |
weighted | Blockstate with greatest float-box overlap volume |
surface_blocks | Ranks non-air by exposed surface block count; air only if no non-air exists |
surface_faces | Same as surface_blocks but scores exposed face count (0–6 per block) |
| Flag value | Camera | Notes |
|---|---|---|
+y | Above, looking down | Rows in ascending z; first row = −z side |
-y | Below, looking up | Rows in ascending z; first row = +z side |
+z | South, looking north | One z-row per y-layer; display higher y first |
-z | North, looking south | One z-row per y-layer; display higher y first |
+x | East, looking west | One x-column per y,z cell; display higher y first |
-x | West, looking east | One x-column per y,z cell; display higher y first |
Use --projection=-y form (equals sign) so argparse does not treat the negative value as an option flag.
| Flag | Matches by | Notes |
|---|---|---|
--id | Block ID only | Ignores block state properties |
--state | Exact blockstate string | Must include all state properties |
--name | — | Saves matching coordinates as a named selection; must be unique |
Exactly one of --id or --state is required. A duplicate name returns SelectionNameAlreadyExists.
| Form | Description |
|---|---|
--bbox y0,z0,x0;y1,z1,x1 | Absolute bbox selection |
--bbox y0:y1,z0:z1,x0:x1 | Anchor-relative bbox selection |
--input file.json | Load from raw/chunk RLE geometry or full MCX success envelope |
--input - | Read geometry from stdin (folded JSON is rejected; use --fulljson) |
--prompt "text" | Visual selection via mc_vision; cannot combine with bbox, input, or set ops |
--propagate | Valid only with --prompt |
infect | 6-neighbor expand through matching block IDs; stops at air / mismatch |
union A B | Union of named selections A and B |
subtract A B | Subtract B from A |
intersect A B | Intersection of A and B |
clear | Reset to empty selection |
named_selection | Restore a previously saved named selection |
Selection output is summaries only — no stored representations, chunks, masks, or full coordinate lists. Unnamed selections replace the previous unnamed selection. Named selections must be unique; --max-voxels defaults to 32768 for infect.
Anchor-relative bbox syntax (y0:y1,z0:z1,x0:x1) resolves through the active anchor. Anchor changes do not alter the loaded schematic or existing selection coordinates.
Deletes the state file when it exists. Result includes cleared: true and state_existed (whether a file was present before the command ran).
Use --jsonpath PATH to select part of success JSON before stdout folding is applied:
| Syntax | Example |
|---|---|
| Root | $ |
| Dot child | $.result.palette |
| Bracket child | $["result"] |
| Array index | $.result.rle[0] |
| Array slice | $.result.palette[0:5] |
Arrays with ≥ 6 non-numeric items are folded by default — first 5 kept, rest replaced by a marker object. Use --fulljson to disable folding entirely.
Tip: pipe to mcx print --fulljson then use --input to load the full geometry into a selection.
| Error type | When it occurs |
|---|---|
InvalidArguments | Invalid CLI arguments, coordinate syntax, JSONPath, or incompatible options |
StateNotLoaded | State file is missing or not a valid MCX state |
InvalidState | State file exists but violates the MCX schema |
InvalidLitematic | Litematic cannot be loaded or normalized |
InvalidSelection | Supplied bbox or geometry input is malformed or out of bounds |
SelectionNotFound | Named selection does not exist |
SelectionNameAlreadyExists | Attempted to save a selection with a duplicate name |
InfectSelectionTooLarge | select infect exceeded --max-voxels limit |
VisionSelectionFailed | select --prompt could not render, edit, project, or encode the visual selection |
InvalidPalette | Duplicate blockstates or unresolvable code collisions in RLE palette |
These examples use the bundled fixture. Run from the project root with uv run mcx ....