MCP server for BuildArena, a text-interface for building and managing machines in the Besiege game environment. Provides tools for machine lifecycle management, block attachment, and machine state persistence.
BuildArena exposes 4 tools with clear naming conventions (verb_noun pattern: create_, close_, load_, save_) and reasonably detailed docstrings. However, schemas are inferred from Python function signatures rather than explicitly registered, parameter descriptions lack type constraints and format guidance, and output schemas are undocumented. No error handling guidance, no recovery patterns, no idempotency declarations. Tool composition is reasonable (each does one thing), but lacks chaining support details (e.g., does close_machine_lifespan return a name that load_machine_from_history accepts?). Security considerations are absent, no secret injection patterns, no permission gates, no audit logging guidance.
Save the active machine to files and close its lifespan. Args: spawn_y: Export spawn height (game vertical axis, game length units). When omitted (the default), it is inferred from the machine's collision geometry so it lands on the ground instead of falling/bouncing from a fixed height. Returns: str: Saved machine name and output directory. Limits: saves authoring state; does not inspect runtime telemetry. Example: call with no arguments to infer spawn height.
Create a new active machine lifespan using machine_name plus a short timestamp. Args: machine_name: Base name; a short timestamp is appended. note: Optional description of the machine. Returns: str: Created lifespan name and save directory. Example: create_machine_lifespan(machine_name="demo"). After creating, either call start() to build from scratch, or load_machine_from_history to reconstruct a previous valid-only <name>.json build history and continue editing that machine.
Replay a valid-only build-history JSON into the current new lifespan. Call this after create_machine_lifespan. The reconstructed machine lives only on that new lifespan: the source JSON is read, never overwritten. Replay re-executes the original operations (start, attach_block_to, ...), so the new machine's history is a copy of those operations — not a single load record that would break if the source file later moves. Args: history_json: Complete path to a valid-only <name>.json written by save_machine or close_machine_lifespan. Absolute paths or repository-relative paths are accepted; any directory is fine. Do not pass a .bsg, *_full.json, or full.json. Do not pass a machine name or folder. Returns: str: Rebuild status plus the reconstructed machine summary. Example: load_machine_from_history(history_json="saved/demo.json").
Output schemas are completely undocumented. All 4 tools return plain strings. Agents cannot parse results programmatically or extract values for downstream calls (e.g., machine_id, save_dir paths).
Input parameter constraints are missing. machine_name accepts 'A-Za-z0-9 _.-' (1-64 chars) per code validation, but schema has no minLength, maxLength, or pattern. spawn_y accepts any float but code may have range expectations. This forces agents to guess valid ranges and invite validation errors.
No error handling or recovery guidance. Descriptions do not explain failure modes: What happens if create_machine_lifespan is called twice? If save_machine is called before start()? If history_json path does not exist? Agents have no guidance on how to recover.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Save the authoritative build history and its .bsg export. Args: spawn_y: Export spawn height (game vertical axis, game length units). When omitted (the default), it is inferred from the machine's collision geometry so it lands on the ground instead of falling/bouncing from a fixed height. Returns: str: Saved machine name and output directory. Limits: saves authoring state; does not inspect runtime telemetry. Example: call with no arguments to infer spawn height.
Tool composition unclear. close_machine_lifespan and save_machine appear to do similar things (save the machine). Description does not distinguish when to use each. load_machine_from_history depends on output from close_machine_lifespan or save_machine (a .json file), but the relationship is not documented.
Parameter descriptions lack format/constraint guidance. history_json says 'Complete path' but does not clarify: absolute vs relative? What if path is relative, relative to what working directory? Agents need this detail to form valid calls.
Idempotency and side effects not declared. save_machine called twice, does it overwrite, version, or fail? create_machine_lifespan appends a timestamp to avoid collisions, but is the behavior idempotent if called with the same machine_name? Agents need this clarity to retry safely.
No tool annotations. Rich descriptions mention WRITE and READ_ONLY semantics in Risk field, but no idempotentHint, destructiveHint, or readOnlyHint metadata is present in schema. Agents cannot infer safe-to-retry vs irreversible operations from structured tool metadata.