Team Cereustooling wiki

Smithbox MCP bridge (reference)

Checkedagainst the code on 2026-11-12 11:42

The bridge lets an agent (or any MCP client) drive the Map Editor of a running Smithbox: load maps, list and edit objects, place models, take screenshots.

What was checked for this page: the Python server and the C# bridge were read in full for names, parameters and defaults. No tool was called.

The two halves

Part Where What it does
The bridge inside Smithbox, src/Smithbox.Program/Utilities/McpBridge/ A socket on 127.0.0.1 only. One JSON request per line: {"tool": name, "args": {...}}. One JSON line back: {"ok": true, "result": ...} or {"ok": false, "error": ...}.
The MCP server S:/Smithbox/Tools/mcp/smithbox_mcp.py A stdio MCP server named smithbox. It forwards each tool call to the socket. It adds screenshot and launch_smithbox itself.

Requests are queued and run on Smithbox's UI thread, at most 16 per frame. So they change editor state the same way the GUI does. If the UI thread does not answer within 60 seconds the bridge returns "Timed out waiting for the editor's UI thread (is a modal dialog open?)".

Port and environment variables

Variable Read by Meaning
SMITHBOX_MCP_PORT Smithbox and the MCP server The port. Default 47700. In Smithbox, 0 turns the bridge off.
SMITHBOX_EXE MCP server The exe launch_smithbox starts. Default: src/Smithbox.Vulkan/bin/Release/net10.0/win-x64/Smithbox.Vulkan.exe under the repo the script is in.
SMITHBOX_PID MCP server screenshot only captures the window of this process id. Use it when two Smithbox windows are open.
SMITHBOX_SESSION_DIR Smithbox Where "reopen where you left off" sessions are kept. Default %LOCALAPPDATA%\Smithbox\Sessions. Set it for a test copy so it leaves the real sessions alone.

Smithbox logs "MCP bridge listening on 127.0.0.1:<port>" at start. If the port is taken it logs a warning and runs without the bridge.

How it is registered

The server needs Python with mcp and pillow (pip install mcp pillow). It is registered for Claude Code at user scope under the name smithbox:

claude mcp add --scope user smithbox -- python S:\Smithbox\tools\mcp\smithbox_mcp.py

claude mcp list shows it. The team release also ships the script in the Smithbox folder under Tools/mcp/.

Safety rules

A running Smithbox is someone's live workspace. Stan edits maps between an agent's turns.

  1. Call smithbox_status first. Look at loaded_maps[].unsaved and can_undo. If anything could be someone's work, ask before you unload, close or rebuild. Ask them to save, or save only with their OK.
  2. Never pass discard_changes=true to unload_map on a map someone has touched. Never close Smithbox to rebuild it while it holds unsaved edits. This rule exists because edits were lost that way once.
  3. Every edit is undoable. Edits go through the editor's undo stack, so undo and Ctrl+Z in the editor both take them back.
  4. Nothing reaches disk until save_map. A save writes into the Smithbox project folder, never the game install.
  5. These write to disk at once, with no undo: create_map_copy (new files in the project folder), place_model with game="er" and port_er_map (imported model files in the project folder), set_community_name (the project's alias file), nav_generate with save=True, and preview_status with clear_disk.
  6. Undo does not clear Smithbox's dirty flag. A map that was edited and fully undone still reports unsaved.
  7. Do not launch the game to check a map. Hand over to the person and say what to look for.

Running a test copy on another port

To try a build without touching the Smithbox someone is using:

  • Start the second Smithbox with SMITHBOX_MCP_PORT set to another port (the team has used 47711 and 47715) and SMITHBOX_SESSION_DIR set to a scratch folder.
  • The registered smithbox MCP server reads its port once at start, so it keeps talking to 47700. Reach the test copy with a raw socket instead: connect to 127.0.0.1:<port>, send one JSON line {"tool": ..., "args": {...}}, read one line back. The bridge's tool names are the same as the MCP ones, except status (MCP: smithbox_status).
  • With two Smithbox windows, set SMITHBOX_PID for screenshot, or it captures the largest one.
  • From the team's notes, not re-checked here: a test copy opens the same project, so it writes preview caches and map indexes into that project's .smithbox folder; build a test copy into its own output folder so the shared build is not locked. See build-smithbox.md.

Addressing

  • Objects are addressed by map_id plus MSB name (for example AEG099_090_9000). kind (Part, Region, Event) narrows a name that exists in more than one list.
  • A map must be loaded (load_map) before its objects can be listed or edited.
  • Positions are map-local, as the MSB stores them. m60 tiles sit at a world offset; smithbox_status reports it as loaded_maps[].world_offset. Camera positions are world space.
  • Rotations are in degrees for ER and NR. Y is up.
  • Property paths look like ModelName, EntityGroupIDs[0], Unk1.DisplayGroups[2].
  • A map loaded only as read-only context for the tiles around it refuses edits. Load it with load_map to edit it.

Tools

Every tool in smithbox_mcp.py, grouped by purpose. Defaults are in brackets.

Session

Tool What it does Key parameters
smithbox_status The open project (name, game, paths), loaded maps with unsaved state, maps still loading, the selection, the camera. none
launch_smithbox Starts the build at SMITHBOX_EXE if the bridge does not answer, and waits up to 60 s for it. none
show_map_editor Brings the Map Editor tab to the front. none
screenshot Captures the Smithbox window. Works behind other windows, not when minimised. max_width [1600], crop [left, top, right, bottom]

Maps

Tool What it does Key parameters
list_maps Map ids in the project with their alias names. filter, limit [300]
load_map Loads a map and waits until it is loaded. map_id, wait [true], timeout_s [180]
unload_map Unloads a map. Refuses when it has unsaved changes. map_id, discard_changes [false]: see the safety rules
save_map Writes the map's changed files into the project folder. map_id
create_map_copy Makes a new map in the project as a copy of another map's MSB. Written at once. source, new_id, with_navigation [false]

Look at objects

Tool What it does Key parameters
list_objects Objects of a loaded map with model, alias, position, rotation, entity id, and counts per class. map_id, kind, cls, name_contains, model_contains, near + radius, limit [200]
get_object Every MSB field of one object, and what references it. map_id, name, kind, depth [3]
models_in_map Distinct part models of a loaded map by class, with counts and an example. map_id
get_selection What is selected in the viewport. full [false]
select Selects objects and frames the camera on them. map_id, names, frame [true], kind

Edit objects

Tool What it does Key parameters
set_property Sets fields on one or more objects as one undo step. map_id, changes {path: value}, name or names, kind
transform Moves, rotates or scales objects as one undo step. map_id, name or names, position, offset, rotation, rotate_by, scale
duplicate Copies an object; can swap the copies' model. map_id, name, count [1], offset, positions, model, entity_id [clear / increment / keep], clear_entity_groups [true], rename [true]
place_model Places a new part with a model, cloned from a fitting template part. Same code as the Object Palette. map_id, model, position, snap_to_ground [false], rotation [template / zero / random], clear_ids [true], cls, game ["" or "er"], coordinates [local / world]
delete Deletes objects as one undo step. map_id, names, kind
undo / redo Undo or redo editor actions in the active map view. steps [1]
modal_transform Runs the Blender-style G / R / S modal on the selection with synthetic input. mode [grab / rotate / trackball / scale], axis, plane, numeric, from_px, to_px, finish [confirm / cancel / leave], local, push
rotate_gizmo Reports or drags the Blender-style rotate gizmo on the selection. point, drag [x / y / z / view / trackball], from_px, to_px, finish, rotate_mode [true]

Find models

Tool What it does Key parameters
search_models Searches model ids, names and tags. query, kind [asset / chr / mappiece / part], limit [50], only_in_game [true]
model_maps Which maps use an asset, or which assets the maps matching a search use. game [project / er], id, search, limit [20]
list_files The project's file lists, with the layer each file comes from (project, mod[i], game). kind [chr / asset / map / parts / mappiece / all], filter, limit [100], count_layers
palette_search Opens the Object Palette on a tab with a search typed in. search, tab [used_in_map / assets / characters / map_pieces / recent], game [nr / er], place, category, peek
preview_status How far the Object Palette's previews have got. clear_memory [false], clear_disk [false]
set_community_name Gives a model a community name, saved at once to the project's alias file. id, name, kind, game ["" or "er"]

See place-an-object.md for the Object Palette.

Elden Ring assets and maps

Tool What it does Key parameters
er_assets The Elden Ring install a Nightreign project borrows from: matching assets, and what is already copied into the project. search, limit [50], inspect (an ER asset id)
port_er_map Bulk-ports an Elden Ring map's Asset parts into loaded Nightreign maps. See port-er-map.md
port_status Progress of the running or last port_er_map job. none

See also place-er-asset.md.

Tool What it does Key parameters
nav_info The navmesh models of a loaded map. map_id
nav_validate Runs the navigation validator on a loaded map, with the game's own counts to compare. map_id, limit [30]
nav_generate Generates a model's n and o navmeshes from the map's collision, as one undo. See generate-navmesh.md

Camera and view

Tool What it does Key parameters
look_at Points the camera at a position, framing a box of a radius. position, radius [10], map_id (then the position is map-local)
camera Sets the camera's world position, pitch and yaw in degrees. position, pitch (90 = straight down), yaw (0 = +Z)
render_filter Shows or hides kinds of things in the viewport. Returns what is shown. hide, show (for example Collision, Navmesh, Region)

See rendering.md and move-rotate-snap.md.

Params

Tool What it does Key parameters
param_info Whether params are loaded; a param's type and row count; row ids and names in a range. name, id_min, id_max, limit [60]

Bridge commands with no MCP tool

The C# bridge also answers these names, but smithbox_mcp.py does not expose them. They can only be reached with a raw socket request. Their arguments were read from the code but are not documented further here:

set_visible (the Map Contents eye for objects; not a map edit), variations, focus_variation, copy_variation, open_map, material_info, material_audit, model_materials, viewport_setting (reads or sets a Viewport_* setting by name), extract_file (copies a file the project can see to a folder on disk), snap_to_surface, surface_ray, snap_debug, snap_model_debug.

The tool list in Tools/mcp/README.md is older than the script and misses many tools. Trust the script.

Source files this page documents (4)
  • smithbox:Tools/mcp/smithbox_mcp.py
  • smithbox:Tools/mcp/README.md
  • smithbox:src/Smithbox.Program/Utilities/McpBridge/
  • smithbox:src/Smithbox.Program/Smithbox.cs

Changed one of these? Update this page: smithbox/mcp-bridge.md (how).