summer-engine npm package 3.3.0 (its MCP server’s tools/list, library/tools/*/resource.yaml and registry/generated/index.json in SummerEngine/summer) and the hosted Summer Engine MCP (src/lib/mcp/hosted at commit 8c4351ee30). If something here is wrong, the tool definition is wrong.summer_camera_bookmark
On the local MCP (summer-engine npm).
Save, list, or delete named camera viewpoints for the edited 3D scene. A bookmark is a fixed pose (position, look_at, fov) stored IN THE PROJECT at res://.summer/camera_bookmarks.json, so it survives sessions and machines — the scene file is never touched.
WHY: screenshots taken from a preset framing re-fit the scene bounds every time, so a before/after pair shifts whenever anything moves; a bookmark is the same pose every time, which makes before/after comparison real. Save once, then reuse on every capture: summer_screenshot target:“scene” framing:“bookmark” bookmark_name:“<name>” (add marks:true for numbered labels mapped to node paths).
action:
“save” — name (1-64 of A-Z a-z 0-9 \_ -) plus EITHER position + look_at as Godot literals (“Vector3(x, y, z)”, optional fov, default 60) OR neither: omit both to capture the CURRENT editor 3D viewport camera (result pose_source: “editor_viewport” vs “explicit”; overwritten says whether a same-named bookmark was replaced).
“list” — every saved bookmark (names sorted, poses, created timestamps, file path).
“delete” — remove one by name (result lists the remaining names).
Failures are structured: bad_args (name grammar, half-given pose, fov outside 1..179, position == look_at), no_editor_camera (no pose given and no 3D viewport camera to capture), not_found (+ available names), io_failed (file unreadable/unwritable; a malformed file is reported, never overwritten). Edit-time only — no running game needed. If this engine build predates the bookmark ops, the result is a structured engine_lacks_op failure (nothing is sent) naming the fallback.
- “save this camera angle” / “remember this viewpoint” so later screenshots line up with it
- comparing a scene before and after a change from one fixed, repeatable camera pose
- listing or removing the saved viewpoints of a project
- taking the screenshot itself —
summer_screenshottarget “scene” with framing “bookmark” and bookmark_name reuses a saved pose - a one-off pose you will not reuse —
summer_screenshotframing “free” with camera_position/camera_look_at - requires an engine build with the camera bookmark ops (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_clear_console
On the local MCP (summer-engine npm).
Clear the editor’s Output panel. Useful before running the game to get a clean slate for error checking.
- before a play session whose console output you want isolated
- “the Output panel is full of old noise, wipe it”
- resetting before reproducing a bug so only the new messages show
- you still need to read the messages —
summer_get_consolefirst; clearing destroys them
Input JSON schema
Input JSON schema
isError.
summer_create_debug_report
On the local MCP (summer-engine npm).
Create a support-ready Markdown report for /summer debug.
Use this when the user says “/summer debug”, asks to send Summer a bug report,
or needs a portable artifact from a failing Codex, cloud or agent session. The
report includes Summer doctor checks, engine health, diagnostics, console
output, debugger errors/warnings, and an agent handoff prompt. It omits auth
tokens and project file contents, but the user should still review it before
sending because local paths and stack traces may appear.
- the user wants to send Summer a bug report
- handing a failing session to another agent as a portable artifact
- running against a hosted/remote MCP endpoint — it probes the local disk (~/.summer, MCP log, project files) and must run where the CLI is installed
Input JSON schema
Input JSON schema
isError.
summer_debug_views
On the local MCP (summer-engine npm).
One pose rendered as a grid of debug views next to the beauty pass: beauty, lighting (light only: direction, pools, dead-dark areas), unshaded (albedo: texture quality, value grouping), normals (world-space, x red y green z blue: seams, flipped or faceted normals), overdraw (stacked transparent layers), wireframe (triangle density, floating or duplicated pieces).
Use it on the weakest shot of a sheet to see WHY it reads badly. lighting/unshaded/overdraw/wireframe are the engine’s Viewport debug draw modes; normals uses an unshaded override material on a private copy (normal maps and alpha cut-outs are not applied) and works on every renderer. The caption names the method per view.
Returns the grid + caption. Read-only: the scene file, the open tab and the undo history are never touched (the render is an offscreen copy of the SAVED scene). The image arrives inline; the caption carries poses, labels and numbers. Failures are structured (failure_reason), never a silent fallback.
- understanding WHY a shot reads badly: light direction and pools, texture/value balance, normal seams, overdraw hot spots, triangle density
- checking floating or duplicated geometry, flipped normals or missing light in one framed view
- judging an environment like an artist, on the weakest shot of a sheet
- you only need the final image —
summer_shot_sheetorsummer_frame_nodes - a pixel-exact close-up of a problem —
summer_zoomwith the same pose
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the grid + caption.
summer_frame_nodes
On the local MCP (summer-engine npm).
Frame one or more nodes with a camera fitted to their WORLD bounds and render it with the scene’s REAL WorldEnvironment, lights, fog and tonemap (unlike summer_screenshot nodePath, which only works with the flat preview environment).
Pick the side with direction (front/back/left/right/top/iso) or an explicit from vector; fill sets how much of the frame they span. bookmark_name also saves the fitted pose so every later render (summer_shot_sheet, summer_debug_views, summer_screenshot framing:“bookmark”) lines up with it. marks:true adds numbered labels mapped to node paths.
An explicit from is checked in-engine before you trust the image: if walls block the nodes, or the camera stands behind or inside a one-sided surface (its back is not drawn, so the image would look THROUGH the wall), the caption opens with a WARNING and the nearest valid from (+ fov) to pass back. With marks:true every labelled node gets an occlusion test (centre + 4 bounds points); hidden ones are noted “(hidden behind <path>)”.
Returns the image + caption: the pose as Vector3 literals, the bounds, the environment used, the view check, and the mark list. Read-only: the scene file, the open tab and the undo history are never touched (the render is an offscreen copy of the SAVED scene). The image arrives inline; the caption carries poses, labels and numbers. Failures are structured (failure_reason), never a silent fallback.
- “show me the houses/props with the real lighting” — fit a camera to one or more nodes and render it with the scene’s WorldEnvironment
- framing a node from a chosen side (front/back/left/right/top/iso or an explicit direction) for a lighting or mood check; an explicit direction is checked for walls and back faces between the camera and the nodes
- creating a hero-view bookmark that fits a group of nodes, so later shot sheets and compares line up
- the editor viewport or a game frame is what you need —
summer_screenshot - you do not know a good view —
summer_frame_shotfinds and scores poses for a shot type - requires an engine build with ScenePreview fixed-pose framings (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op or framing_unsupported
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the image + caption: the pose as Vector3 literals, the bounds, the environment used, the view check, and the mark list.
summer_frame_shot
On the local MCP (summer-engine npm).
Smart framing: find good camera poses for a shot type automatically, measured in-engine against the real geometry.
shot: establishing (wide), eye_level (from a spawn node at player eye height), low_angle (hero, near the ground looking up: the camera moves closer and widens its FOV instead of sinking into the ground), detail (close-up), corridor (down a lane or corridor found inside the subject by a free-space scan, preferring the view in from its open end, walls on both sides).
How: candidate poses on a ring/hemisphere (or along the corridor line) at the distance where the subject fills the shot’s target share of the frame; each is checked with a THICK sphere sweep to points on the subject (thin rays miss corners), a near-lens sphere (camera inside or touching geometry is nudged forward or rejected), a ray grid through the frame, and a small beauty render per pose. Walls/terrain blocking the subject reject a pose, and so does a camera behind or inside a one-sided surface (a sight line or a quarter of the frame meeting a wall from behind: its back is not drawn, so the image would look through it). Foliage, fences, props and pipes in front are allowed (wanted, up to a limit) as framing; transparent materials (alpha, scissor, glass, foliage cards) are see-through cover at partial weight. Scored on rule-of-thirds placement, frame fill, level horizon, sky share, depth behind the subject (no flat wall right behind it), empty or featureless areas, near-wall clearance, near/far value contrast, foreground framing, surfaces seen from behind, the key light’s direction (side or front-side beats a flat front-lit face) and the world edge (sky or void below the horizon).
Returns the top 3 with score breakdowns and poses — three different views (one per side of the subject while the score allows, at least 25 degrees apart) — saves the best as a bookmark (default <shot>_<subject>), and renders the 3 as one sheet with real lighting (render:“best” or “none” to save context). Read-only: the scene file, the open tab and the undo history are never touched (the render is an offscreen copy of the SAVED scene). The image arrives inline; the caption carries poses, labels and numbers. Failures are structured (failure_reason), never a silent fallback. Saving the bookmark writes res://.summer/camera_bookmarks.json.
- “find a good view of X” / “frame an establishing shot” / “show it from the player’s eye” / “look down the street”
- choosing hero views to bookmark for an environment review loop
- checking whether walls or terrain block the view of a subject, and which props frame it (a camera behind or inside a one-sided wall is rejected; transparent foliage and glass are see-through cover)
- three different establishing views at once (one per side while the score allows), scored on the key light’s direction and the world edge below the horizon
- you already have the pose —
summer_shot_sheet,summer_frame_nodesorsummer_screenshot - gameplay camera collision in the running game — that is the camera rig’s job (camera-collision-avoidance knowledge)
- a 2D scene
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the top 3 with score breakdowns and poses — three different views (one per side of the subject while the score allows, at least 25 degrees apart) — saves the best as a bookmark (default <shot>_<subject>), and renders the 3 as one sheet with real lighting (render:“best” or “none” to save context).
summer_game_control
On the local MCP (summer-engine npm).
Control the clock of the RUNNING game and list instances. action:‘pause’ suspends it (GamePause — Engine time frozen, physics inactive; SceneTree.paused untouched), ‘resume’ lifts the suspension, ‘step’ advances EXACTLY frames (1..600) of kind ‘physics’ (default) or ‘process’ and leaves the game suspended (GameStep), ‘speed’ sets the user time scale (GameSpeed, 0.25 = quarter speed), ‘instances’ lists every live game instance (ListGameInstances: name, mode, pid, attached, breaked, scene, seed, fixed_fps, deterministic, summer_capture).
Frame stepping is how you make exact assertions: pause -> summer_game_probe -> act -> step 1 -> probe; the step result reports before/after frame counters, exact, overshoot, and draws the last stepped frame before replying so the following probe shows it. A minimized game window draws no frames and cannot step (timeout). step and pause answer game_breaked while the game sits at a breakpoint. GameSpeed rides a no-reply channel: acknowledged:false means the engine could not read the new time_scale back (older game build) — verify with summer_game_probe time_scale.
‘instances’ is also the boot check after summer_play {instance, mode:‘offscreen’}: address an instance only once attached:true (before that the ops answer request_failed). THE LOOP: summer_play (add instance + mode:‘offscreen’ for a disposable instance; deterministic:true + seed for a reproducible run; fixed_fps for exact timing) -> wait for boot (summer_is_running, or summer_game_control action:‘instances’ showing attached:true) -> summer_game_probe BEFORE (frame-stamped state + pixels) -> act (summer_runtime_set / summer_runtime_call / summer_game_input) -> summer_game_control action:‘step’ for exact frames, or let it run -> summer_game_probe AFTER -> assert on the two probes. Never claim something moved, spawned or fired without a probe that shows it.
Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. On an engine build that predates these ops the result is a structured engine_lacks_op failure; the fallback for exact frames is a RunVerification probe awaiting physics_frame N times.
- pausing the running game and stepping one physics frame at a time to make exact frame-by-frame assertions
- “pause the game and advance a single physics frame” / “run the game at quarter speed” / “which game instances are up?”
- checking that an offscreen playtest instance has attached before addressing it
- starting or stopping the game —
summer_play/summer_stop - a probe-based check inside a hidden disposable instance — a RunVerification probe awaiting physics_frame
- requires an engine build with GamePause / GameStep / GameSpeed / ListGameInstances (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_game_input
On the local MCP (summer-engine npm).
Drive the RUNNING game’s input like a player would. action:‘script’ schedules up to 1000 timed synthetic events (SimulateInputScript): [{at_frame: 0, type:‘action’, action:‘move_right’, hold_ms: 500}, {at_frame: 30, type:‘action’, action:‘jump’, hold_ms: 50}]; types action | key (keycode / physical_keycode) | mouse_click (position [x,y], button) | axis (action_negative/action_positive, signed strength) | raw ({class, props} — a recorded InputEvent). clock ‘frame’ (at_frame, exact) or ‘ms’ (at_ms — exact only when the instance runs with fixed_fps, else approximate; the result reports clock_mapping). action:‘record_start’ / ‘record_stop’ capture the game’s REAL input into res://.summer/replays/<id>.json (InputRecordStart/Stop — cap 20,000 events / ~1 MiB, truncated:true when hit); action:‘replay’ plays a recording (or inline events) back (InputReplay), with seed asserting reproducibility on a deterministic offscreen instance.
script returns {scheduled, applied, rejected[{index, failure_reason, error}], first_frame, last_frame, completed, clock_mapping}; per-event rejections (unknown_action: not in the project InputMap — summer_input_map_bind, or use type:‘key’) are non-fatal unless all_rejected. ONE script in flight per instance: a second call answers busy — wait for the first. wait:true (default) blocks until the last event fires but the engine caps it at 20 s; a longer script uses wait:false and observes with summer_game_probe. replay returns the same shape plus {recording, deterministic}; seed on an instance not started with summer_play {mode:‘offscreen’, deterministic:true} answers nondeterministic_instance.
Scripts vs recordings: a script is the readable, editable repro you write from the spec; a recording is the exact repro of what a human (or a script) actually did — replay it on a deterministic instance for an A/B under identical inputs. Input is an ACTION: prove what it caused with summer_game_probe before/after (or summer_game_control action:‘step’ for the exact frame). THE LOOP: summer_play (add instance + mode:‘offscreen’ for a disposable instance; deterministic:true + seed for a reproducible run; fixed_fps for exact timing) -> wait for boot (summer_is_running, or summer_game_control action:‘instances’ showing attached:true) -> summer_game_probe BEFORE (frame-stamped state + pixels) -> act (summer_runtime_set / summer_runtime_call / summer_game_input) -> summer_game_control action:‘step’ for exact frames, or let it run -> summer_game_probe AFTER -> assert on the two probes. Never claim something moved, spawned or fired without a probe that shows it.
Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. engine_lacks_op on an older build names the fallback (single SimulateInput ops via summer_batch, or a RunVerification probe’s press()/key()).
- scripting a timed input sequence against the running game (walk right for 500 ms, jump at frame 30, click a button)
- recording my inputs while the game runs and replaying them deterministically for a repro or an A/B
- “record what I do and replay it” / “press jump 10 times in a row in the running game”
- binding or renaming input actions —
summer_input_map_bind - a hidden disposable probe run — a RunVerification probe with press()/key()
- no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with SimulateInputScript / InputRecordStart / InputRecordStop / InputReplay (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_game_probe
On the local MCP (summer-engine npm).
State AND pixels of ONE frame of the RUNNING game, atomically (GameProbe): the live scene tree (tree {path, depth, limit}), up to 64 property reads (props [‘/root/Main/Player:position’, ‘/root/Main/HUD/Health:value’]) and a screenshot of the game viewport, all stamped with the SAME frame counters. This is the evidence tool of the playtest loop — the only read where “what the tree says” and “what the screen shows” cannot come from different moments.
You SEE the screenshot as an image block; the text block carries the frame stamp ({frame: {process_frames, physics_frames, frames_drawn}, image_frame, suspended, paused, time_scale}), values {key: Godot literal string}, missing[] (keys that did not resolve — a typo or a node that is gone), tree/total_nodes/truncated. Two probes around an action are a claim’s proof: cite both frame numbers. screenshot:false is the cheap state-only read (works when the window draws nothing). max_dim (default 1280) bounds the image. Unlike summer_screenshot target:‘game’, the capture happens game-side, so it works for offscreen and floating instances.
THE LOOP: summer_play (add instance + mode:‘offscreen’ for a disposable instance; deterministic:true + seed for a reproducible run; fixed_fps for exact timing) -> wait for boot (summer_is_running, or summer_game_control action:‘instances’ showing attached:true) -> summer_game_probe BEFORE (frame-stamped state + pixels) -> act (summer_runtime_set / summer_runtime_call / summer_game_input) -> summer_game_control action:‘step’ for exact frames, or let it run -> summer_game_probe AFTER -> assert on the two probes. Never claim something moved, spawned or fired without a probe that shows it.
Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. A probe still answers while the game is breaked. On an engine build that predates GameProbe the result is a structured engine_lacks_op failure; fall back to summer_get_runtime_tree + summer_screenshot target:‘game’ (two calls, two frames).
- proving what the running game is actually doing before and after an action — the evidence read of every playtest loop
- “show me the game right now with the player position” / “screenshot the offscreen instance and read the HUD values”
- a claim about motion, spawning, or a state change needs a frame-stamped before/after pair
- the EDITED scene, not the running game —
summer_world_snapshot/summer_screenshottarget viewport - no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with GameProbe (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op — fall back to
summer_get_runtime_tree+summer_screenshottarget game
Input JSON schema
Input JSON schema
isError.
summer_get_board
On the local MCP (summer-engine npm).
Read the person’s approved planning board for this game: the look (palette,
description, picture), the characters, the place, the first-minute storyboard
and the cards they picked, with a version that changes when the board does.
The look and the picked cards come back as images you can see. Read the board at
the start of each build step and compare your screenshot against its images
(palette, shapes and proportions, camera angle, composition); fix the biggest
difference. Use the picked card pictures as referenceImageUrl for
summer_generate_image to make sprites and backgrounds in the same look.
Cloud tool — runs on Summer’s servers and works WITHOUT the Summer Engine app open.
Requires authentication: run ‘npx -y summer-engine@latest login’ first.
- starting a build step for a game made from a planning board
- “does the game look like the board?”
- comparing a screenshot with the chosen look and picked cards
- the game was not made from a planning board (no project id in the brief)
Input JSON schema
Input JSON schema
isError.
summer_get_console
On the local MCP (summer-engine npm).
Read recent messages from the editor’s Output panel (print() output, editor-side warnings and errors).
SCOPE: the editor console ONLY. Runtime errors from a played game are collected by the debugger, not the console — right after summer_play this tool can honestly report errors 0 while summer_get_debugger_errors holds several. Never treat this tool alone as the post-play verdict: read summer_get_diagnostics (console + debugger + script errors together) first, then come here for message bodies. Every result carries a “_scope” note restating this.
Output is post-processed for token economy: consecutive identical messages collapse into one entry with a ”(×N)” count suffix, and the response carries a “_filter” summary so you can see what was hidden. Message types come straight from the editor log (error / warning / std / editor); errors_only=true (default) drops the std/editor lines — startup banners and print() output — and keeps errors and warnings. Use errors_only=false to read print() output, raw=true to bypass all shaping.
Use after summer_get_diagnostics indicates console issues, or to check what your print() statements said.
- diagnostics report console issues and you need the message bodies
- “what did the game print?” / “show me the log output”
- checking whether your print() statements fired
- runtime errors with stack traces —
summer_get_debugger_errors - compile errors in a script you just edited —
summer_get_script_errors - the post-play verdict — a played game’s runtime errors live in the debugger, so this can report 0 errors after a failing run; read
summer_get_diagnosticsfirst
Input JSON schema
Input JSON schema
isError.
summer_get_debugger_errors
On the local MCP (summer-engine npm).
Read runtime errors from the debugger. These occur while the game is running (null references, missing nodes, physics errors). Different from console output — these come from the debugger, not print statements.
For warning text, use summer_get_debugger_warnings (separate tool — engine returns warning count here but not the bodies).
Output is deduped: identical errors firing every frame collapse into one entry with a ”(×N)” count suffix. A “_filter” summary tells you exactly what was collapsed or truncated. Use raw=true to bypass shaping when you really need every entry.
- the running game hit failures like null references or missing nodes
- “the game crashed while I was playing, what was it?”
- “why did my scene fail at runtime?”
- the script will not even compile —
summer_get_script_errors - plain print output —
summer_get_console
Input JSON schema
Input JSON schema
isError.
summer_get_debugger_warnings
On the local MCP (summer-engine npm).
Read runtime warnings from the debugger panel. Warnings are non-fatal issues the game flags during play: missing optional resources, dead signal connections, deprecated API use, large allocations, physics warnings, etc.
Returns structured entries with file/line/function/error_descr/callstack — same shape as summer_get_debugger_errors but filtered to severity = “warning”. Engine-internal warnings without a source file are filtered out as noise.
Use this when summer_get_diagnostics shows a non-zero debugger.warnings count and you want to see what they actually say.
- diagnostics show a non-zero debugger warning count
- “the debugger shows yellow warnings, what are they?”
- checking for deprecated calls or node configuration warnings after a run
- errors, not warnings —
summer_get_debugger_errors
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns structured entries with file/line/function/error_descr/callstack — same shape as summer_get_debugger_errors but filtered to severity = “warning”.
summer_get_diagnostics
On the local MCP (summer-engine npm).
Quick overview of all errors and warnings from the editor console, the runtime debugger, and script errors together. Returns error counts and a guidance message.
ALWAYS call this FIRST before diving into summer_get_console or summer_get_debugger_errors. It tells you where to look. It is also THE post-play read: a played game’s runtime errors land in the debugger section here (and in summer_get_debugger_errors), never in the editor console — summer_get_console alone can honestly report errors 0 right after a play session that produced several.
By default the response is a prioritized view: errors first, then warnings, then a small capped tail of recent info/std noise. Counts (console totals, debugger totals) are always complete — only low-severity message bodies are trimmed, and a “_view” block reports exactly what was suppressed. Pass includeAll: true for the full untrimmed engine payload.
Typical workflow after making changes or playing:
1. summer_get_diagnostics — are there issues? (after a play session: check debugger.errors)
2. If errors: summer_get_debugger_errors (runtime, with stacks) or summer_get_console (editor output) for details
3. Fix the issues
4. summer_get_diagnostics again to verify
- first stop after any change, before targeted console or debugger reads
- verifying a fix removed the errors it targeted
- the post-play read after
summer_playor a RunVerification probe: runtime errors land in the debugger section here, never in the console
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns error counts and a guidance message.
summer_get_runtime_tree
On the local MCP (summer-engine npm).
Scene tree of the RUNNING GAME — live runtime state, not the edited scene. Use it during playtests to see what actually spawned: dynamically created enemies/projectiles/UI, autoloads, pooled nodes — everything summer_get_scene_tree (an EDITOR read) can never show. Inspecting live keeps the bug alive; stopping the game to look usually resets it.
Returns {tree: {name, class, path, children}, total_nodes, truncated}. Depth/limit are capped and truncation is declared — never assume a capped tree is complete. Drill into one node’s live properties with summer_inspect_runtime_node.
Needs a running game: fails with failure_reason “game_not_running” otherwise — start with summer_play, then re-run.
- inspecting what actually spawned during a playtest without stopping the game
- “which enemies are actually alive right now?”
- “what did the spawner create?” / “is the autoload there?”
- no game is running (failure_reason game_not_running) —
summer_playfirst, or read the edited scene withsummer_get_scene_tree - requires an engine build with GetRuntimeSceneTree (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns {tree: {name, class, path, children}, total_nodes, truncated}.
summer_get_script_errors
On the local MCP (summer-engine npm).
Check a GDScript file for parse/compile errors without running the game.
Use after writing or editing a .gd file to verify it compiles. Returns line numbers, error messages, and severity. Much faster than running the game to discover script errors.
- after writing or editing a .gd file, to verify it compiles
- “does this script compile?” / “is there a syntax error in player.gd?”
- the editor shows a red error marker on a .gd file
- runtime failures while playing —
summer_get_debugger_errors
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns line numbers, error messages, and severity.
summer_inspect_runtime_node
On the local MCP (summer-engine npm).
Live properties of ONE node in the RUNNING GAME: {node: {path, class, properties, children_names}} with a curated common-property set (transform, visibility, physics state, …). The runtime counterpart of summer_inspect_node (which reads the EDITED scene) — use it to answer “what are this enemy’s actual stats right now”, “where IS the player”, “did that flag flip” without stopping the game and losing the state.
Find the path with summer_get_runtime_tree first — runtime paths (e.g. ‘/root/Main/Enemies/Goblin3’) often differ from edited-scene paths because nodes are spawned, renamed, or reparented at runtime.
Needs a running game: fails with failure_reason “game_not_running” otherwise — start with summer_play, then re-run.
- answering “where IS the player” or “what are this enemy’s stats right now” during a playtest
- “how much health does the boss have right now?”
- “what is the player’s actual velocity mid-jump?”
- no game is running —
summer_playfirst; for the edited scene usesummer_inspect_node - requires an engine build with GetRuntimeNode (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_is_running
On the local MCP (summer-engine npm).
Check if the game is currently running. Returns the active scene path if running.
- deciding whether to boot, restart, or capture the running game
- “is the game already open / still playing?”
- before
summer_playor a game-target screenshot, to avoid a double launch
- you need the live scene contents —
summer_get_runtime_tree
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the active scene path if running.
summer_play
On the local MCP (summer-engine npm).
Start running the game in the engine. With no extra parameters the game runs inside Summer Engine’s viewport (the ‘main’ instance) QUIETLY — see below.
QUIET BY DEFAULT (focus:false, PlayGame agent:true): the user is usually working on the same machine while you build, so a play must not take over their screen. Quiet play makes the EDITOR stay put: it does not switch the main screen to the Game tab, does not grab keyboard focus for the embedded game, ignores the game’s later focus report, and skips the render-health self-check that would otherwise misread the untouched Game view as a GPU failure and flip the user’s embed setting. Quiet play does NOT hide the game: it still runs embedded in the Game view (visible if the user already has that tab open), it is the running game for summer_is_running / summer_screenshot target:‘game’ / summer_get_diagnostics, and on engines without the background launch posture it does not change a user who has “Embed Game on Play” turned off — their game opens in its own OS window as always. Engines with the background posture (—summer-background, 0.5.66+) also launch the play child with that flag, so a separate-window game appears without activating or taking focus either. The result echoes agent_quiet:true when honoured; a launch result WITHOUT agent_quiet means the engine predates quiet play and most likely took focus — the tool adds posture_note saying so. focus:true launches like the toolbar Play button (Game tab + focus): use it ONLY when the user is watching and asked to see the game come up.
After starting, confirm boot with summer_is_running (boot time varies — never sleep a guessed delay), then summer_get_diagnostics for runtime errors. You can run a specific scene instead of the main scene — useful for testing individual levels or UI screens.
DETERMINISTIC RUNS (newer engines): seed / fixed_fps / time_scale pin THIS launch only (nothing is persisted). seed pins the game’s GLOBAL RNG (randi/randf/randi_range/randf_range/randfn, Array.shuffle/pick_random) — it does NOT pin RandomNumberGenerator instances, scripts that call randomize(), rand_from_seed, wall-clock reads, or thread/IO/audio timing. fixed_fps decouples scene time from the wall clock so frame-count-derived state lands on the same frame run to run. The result’s determinism block says whether the pins were applied (applied:false carries a reason: already_running, editor_run_args_override, launch_not_started) and restates seed_scope. If the result has NO determinism block although you sent a pin, the engine predates the params and the run is NOT reproducible — the tool says so; do not claim otherwise. Omitting every pin and instance parameter is exactly the v1 launch.
PLAYTEST LAUNCH (engine runtime-control build): instance + mode:‘offscreen’ spawn a disposable hidden instance (at most 3) that summer_game_probe / summer_game_input / summer_game_control / summer_runtime_* address by name — run two variants side by side for an A/B. deterministic:true (offscreen only) launches with —fixed-fps 60 —summer-seed —audio-driver Dummy and is what lets summer_game_input action:‘replay’ accept a seed; speed sets the user time scale on session start. The instance result reports session_attached; poll summer_game_control action:‘instances’ until attached:true before addressing it. Then: probe -> act -> step/probe -> assert (the agent-playtesting skill). Failure reasons: too_many_instances, instance_exists, session_timeout (child never attached — check summer_get_console), unsupported_mode, main_scene_not_configured. A game already running answers playing:true with determinism.applied:false — summer_stop first to apply seed/fixed_fps.
MULTIPLAYER — LOCAL PLAY (Summer multiplayer games; engine with Local Play): players:N starts the game’s authority headless plus N clients on this machine, each joining through the game’s OWN Summer.client.join(SummerJoinTarget.queue(…)) — no account, login, Docker, CLI or local-only game code. The scenes and queue come from the project’s summer.build.json and its WorldDefinition (client_entry_point + the headless_engine component entry_point); queue picks another declared queue — pass queue WITHOUT players to start that queue’s minPlayers (a 4-player queue starts 4), or players to choose; spectators adds spectator clients. local_play.warnings flags a roster outside the queue’s minPlayers..maxPlayers. The result’s local_play block lists every process (label, role, persona) and the port; failure_reason local_play_unavailable says exactly what to declare. Every process attaches to the editor debugger: screenshots, input and summer_game_* go to the FIRST client, the authority’s output is in summer_get_console, and summer_stop stops them all. A join for a different queue fails with a message naming both queues. It is not a proof of sign-in, matchmaking or hosted admission (staging). No local_play block although you sent players means the engine predates Local Play and ran ONE client — the tool says so.
- runtime verification after edits
- the user wants to try the game or one level after a change
- reproducing a bug that only shows at runtime
- a deterministic, repeatable playtest run — pin the global RNG with seed and the timestep with fixed_fps
- launching a deterministic or parallel offscreen playtest instance (seed, fixed frame rate, named offscreen instance) for the runtime tools to drive
- testing a Summer multiplayer game on this machine — players:2 (Local Play) runs its authority headless and two clients that join through the game’s own Summer.client.join; no account, Docker or extra tools
- launching while the user works on the same machine — the default (focus omitted or false) sends PlayGame agent:true, so the editor does not switch to the Game tab or grab focus; the game still runs embedded and is visible to the runtime tools
- the game is already running and needs a restart —
summer_stopfirst (seed/fixed_fps cannot reach a game that is already up) - focus: true unless the user is watching and asked to see the game come up — it launches like the toolbar Play button (Game tab + focus). Quiet play does not hide the game; on engines without the background launch posture a user whose Embed Game on Play is off still gets the game in its own OS window as always, while engines with the posture (0.5.66+) also launch that window with —summer-background so it never takes focus
- only checking whether it is running —
summer_is_running - instance/mode/deterministic need an engine build with the runtime-control ops (Summer Engine 0.5.66 or newer); older engines return for those parameters engine_lacks_op (plain play still works)
Input JSON schema
Input JSON schema
isError. From the tool’s own description: The result echoes agent_quiet:true when honoured; a launch result WITHOUT agent_quiet means the engine predates quiet play and most likely took focus — the tool adds posture_note saying so. The result’s determinism block says whether the pins were applied (applied:false carries a reason: already_running, editor_run_args_override, launch_not_started) and restates seed_scope. The result’s local_play block lists every process (label, role, persona) and the port; failure_reason local_play_unavailable says exactly what to declare.
summer_recent_events
On the local MCP (summer-engine npm).
Read the newest engine events in ONE zero-wait poll — what just happened (saves, plays, op receipts, script errors, imports, selection) and, above all, the CURSOR: its next_seq is the since to hand summer_wait_for_event BEFORE you trigger the action you will wait on.
since omitted = the newest limit sequence numbers (a kinds filter applies inside that window, so fewer may come back). since:0 = the whole retained ring from the oldest, paged — pass next_seq back as since while truncated is true. since:N = everything after N.
Each event is {seq, kind, ts, data}; kinds (v1): op.applied, op.failed, script.error, play.started, play.stopped, scene.saved, scene.opened, import.completed, selection.changed, snapshot.published. The engine retains 512 events / 10 minutes — older history is gone, so an empty result is not proof nothing happened earlier. Payloads over 4 KB arrive clamped with truncated:true inside data. On an engine build without the events channel the result is a structured engine_lacks_events failure (nothing sent).
- “what just happened in the engine?” / “show me the recent events” — the last saves, plays, op receipts, script errors, imports
- taking a cursor BEFORE triggering an action you will wait on — pass its next_seq as
sincetosummer_wait_for_event - after a
summer_wait_for_eventtimeout, reading everything that arrived since its next_seq
- blocking until something happens —
summer_wait_for_event - full console or debugger bodies —
summer_get_console/summer_get_debugger_errors(events carry compact payloads, clamped at 4 KB) - requires an engine build with the events channel (capabilities.events, /api/events; Summer Engine 0.5.66 or newer); older engines return engine_lacks_events
Input JSON schema
Input JSON schema
isError.
summer_runtime_animate
On the local MCP (summer-engine npm).
Drive and read animation in the RUNNING game. target:‘player’ = an AnimationPlayer (cmd state|play|pause|stop|seek|speed — RuntimeAnimation); target:‘tree’ = an AnimationTree state machine (cmd state|travel|start|stop|set_param|get_param — RuntimeAnimationTree); target:‘bones’ = a Skeleton3D’s live bone poses (GetRuntimeBones, read-only). Default cmd is ‘state’ (read-only), so the same tool answers “which clip is playing”, “which state is the machine in” and “where is the hand bone” before and after an action.
player returns state {current_animation, assigned_animation, position, length, speed_scale, playing, animations[]}. tree returns state {active, current_node, travel_path, playing, position, length, fading_from, parameters{}}. bones returns {skeleton: {path, bone_count, motion_scale}, bones[{idx, name, parent, global_pose{origin, rotation, scale} | pose | rest}], truncated} — at most 256 bones per call; filter with bones[] to page larger rigs. unknown_animation / unknown_state / unknown_bone list the valid names in the error.
Animation is motion: one ‘state’ read proves a clip is assigned, not that it moves. Prove motion with summer_game_control action:‘step’ between two reads (position advances, bone poses change) or two summer_game_probe frames. Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. target:‘bones’ and cmd:‘state’ still answer while the game is breaked; the mutating cmds do not. engine_lacks_op on an older build names the fallback.
- checking which clip or state-machine state is actually playing in the running game, then driving it (play, seek, travel, set a blend parameter)
- “which animation is the player in right now?” / “travel the state machine to Attack and see if it blends”
- reading live bone poses to prove a rig moves or an IK target lands
- wiring or authoring animation in the scene — character-animation-wiring / animation-tree skills
- no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with RuntimeAnimation / RuntimeAnimationTree / GetRuntimeBones (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_runtime_call
On the local MCP (summer-engine npm).
Call ONE method on a node in the RUNNING game and get its return value: ‘take_damage’ [25], ‘get_velocity’, ‘has_method’, ‘start_wave’ [3]. The direct way to trigger gameplay code and read its answer without wiring input or waiting for a timer.
Returns {path, method, return, return_type, return_truncated, frame}; return is a Godot literal string for math values. Arguments are JSON scalars/arrays/objects or Godot literal strings (‘Vector3(0, 1, 0)’); Object/RID arguments are refused (bad_args). failure_reason call_error carries call_error_detail (the method raised); method_not_found means check summer_api_docs / the node’s script.
Calling a method is an ACTION, not evidence: probe after it (summer_game_probe) to see what it did. Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. engine_lacks_op on an older build names the fallback; a game whose build predates the summer capture answers unsupported (no legacy fallback carries a return value).
- triggering gameplay code in the running game and reading its answer — take_damage, start_wave, get_velocity
- “call take_damage(25) on the boss in the running game” / “what does get_velocity return right now?”
- a method’s result is the fact you need and no property exposes it
- a plain property read or write —
summer_game_probeprops /summer_runtime_setare cheaper - no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with CallRuntimeMethod (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns {path, method, return, return_type, return_truncated, frame}; return is a Godot literal string for math values.
summer_runtime_set
On the local MCP (summer-engine npm).
Set ONE property on a node in the RUNNING game — the live object, never the scene file (nothing is saved; the change dies with the run). Use it to put the game into the state you want to test without playing there by hand: teleport the player (‘/root/Main/Player’ position ‘Vector3(0, 2, 0)’), set health to 1, flip a flag, toggle visibility.
Returns {path, property, value_before, value_after, applied, transport, frame}. READ applied: false means the read-back did not match (failure_reason not_applied) — a script rewrites the value every frame, or the literal type was wrong. Math values in and out are Godot literal strings (‘Vector3(1, 2, 3)’); ‘script’ and ‘owner’ are refused. For a persistent change edit the EDITED scene (summer_set_prop) and restart.
THE LOOP: summer_play (add instance + mode:‘offscreen’ for a disposable instance; deterministic:true + seed for a reproducible run; fixed_fps for exact timing) -> wait for boot (summer_is_running, or summer_game_control action:‘instances’ showing attached:true) -> summer_game_probe BEFORE (frame-stamped state + pixels) -> act (summer_runtime_set / summer_runtime_call / summer_game_input) -> summer_game_control action:‘step’ for exact frames, or let it run -> summer_game_probe AFTER -> assert on the two probes. Never claim something moved, spawned or fired without a probe that shows it.
Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. On an engine build that predates SetRuntimeProp the result is a structured engine_lacks_op failure naming the fallback.
- putting the running game into a test state without playing there by hand — teleport the player, set health to 1, flip a flag, toggle visibility
- “move the player to (0, 2, 0) in the running game” / “set the boss health to 1 while it is running”
- a runtime experiment whose change should die with the run instead of landing in the scene file
- the change must persist — edit the scene with
summer_set_propand restart the game - no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with SetRuntimeProp (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns {path, property, value_before, value_after, applied, transport, frame}.
summer_runtime_spawn
On the local MCP (summer-engine npm).
Spawn a PackedScene into the RUNNING game (action:‘spawn’ — SpawnRuntimeScene) or free a live node (action:‘free’ — FreeRuntimeNode). Stage a test in seconds: drop three goblins under ‘/root/Main/Enemies’ with props {position: ‘Vector3(4, 0, -2)’, health: 10}, or remove the boss to test the empty-arena path. Nothing touches the scene file.
spawn returns {node: {path, class}, renamed_to?, prop_warnings[], frame} — use node.path (absolute) for follow-up set/call/probe; unknown props land in prop_warnings, they never fail the spawn. free returns {path, queued, freed}: mode ‘queue_free’ (default) frees at the end of the frame, so a probe on the SAME frame may still list the node — step one frame (summer_game_control action:‘step’) before asserting it is gone; ‘free’ is immediate. The scene root cannot be freed (refused_root).
THE LOOP: summer_play (add instance + mode:‘offscreen’ for a disposable instance; deterministic:true + seed for a reproducible run; fixed_fps for exact timing) -> wait for boot (summer_is_running, or summer_game_control action:‘instances’ showing attached:true) -> summer_game_probe BEFORE (frame-stamped state + pixels) -> act (summer_runtime_set / summer_runtime_call / summer_game_input) -> summer_game_control action:‘step’ for exact frames, or let it run -> summer_game_probe AFTER -> assert on the two probes. Never claim something moved, spawned or fired without a probe that shows it.
Needs a RUNNING game: failure_reason game_not_running (summer_play first), request_failed (debug session still attaching — wait, retry), unknown_instance (summer_game_control action:‘instances’), game_breaked (the game sits at a breakpoint — continue it first), timeout (game wedged, minimized or breaked — summer_get_debugger_errors, or summer_stop + summer_play), unsupported (the running game predates the summer capture; restart it after updating). All runtime paths are ABSOLUTE (‘/root/Main/Player’) and come from summer_game_probe tree / summer_get_runtime_tree. engine_lacks_op on an older build names the fallback (summer_instantiate_scene / summer_remove_node in the EDITED scene, then restart).
- staging a runtime test — place three goblins under the spawner, add a pickup next to the player, remove the boss to test the empty-arena path
- “spawn a goblin at (4, 0, -2) in the running game” / “delete that projectile while the game runs”
- the spawned or freed node must exist only for this run
- the node should be part of the scene permanently —
summer_instantiate_scene/summer_remove_nodein the EDITED scene, then restart - no game is running (failure_reason game_not_running) —
summer_playfirst - requires an engine build with SpawnRuntimeScene / FreeRuntimeNode (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_scene_audit
On the local MCP (summer-engine npm).
Audit a 3D scene in one fast, read-only call: every node and subnode is walked and likely visual and placement problems come back as a short list, sorted by severity, so you know exactly where to look. Each issue is a flag to LOOK at, never an auto-fix.
Checks (each can be picked with checks):
- through_hole: capped ray grids through every facade line (coplanar wall fronts); clusters of rays that pass the wall AND reach the far side of the building (a door insert narrower than its frame, a missing module, a seam). Walls, structure and inserts close an opening; props do not.
- exposed_edge: open outline edges of walls and facade members (bands, piers, corner blocks; cached per mesh) that nothing covers within 4-7 mm, seen from walkable space (eye points over open-sky floor cells, flood-filled from the scene’s cameras and characters, sight lines not through a building), with a 2-60 cm reveal behind them, or a coplanar sheet continuing within 4 cm (seam) or 35 cm (gap). Warn on band pieces and when depth_step agrees, look otherwise; repeats group per piece type.
- open_fixture_end: open ends of run pieces (a mesh with two or more open rims of one size: pipe, duct or gutter sections, elbows, tees) that nothing joins within 2.5 cm (sleeve tolerance), seen from walkable space: a missing elbow, coupler, section or end piece (warn). A piece with one rim or rims of different sizes (a cap, a funnel, an outlet) is open by design.
- depth_step (look): ray rows across each visible facade side at its band levels and every 1.25 m: band recesses and missing runs, seams, modules standing proud, holes with something behind them; a hole next to a through_hole confirms it (warn -> error); runs a door-like opening covers are skipped.
- floor_gap: down rays over the floor tiles, along their seams, and from each tile edge to a wall within 1 m (bare strips at wall bases), classified by the FIRST surface hit: the void (error); an underlay over the floor’s own lower surface such as a drain channel (“covers the floor”, warn, not a hole); an underlay through a hole or strip. Areas are the missed rays’ own footprints with the strip’s size; a tile whose own mesh has holes is one issue for the piece.
- floating / sunken: support under each prop’s footprint; gap over 2 cm, embed over 3 cm, measured against the first surface from above (the tile it is buried in, not the underlay under it); structure and pieces touching a wall well off the ground excluded.
- interpenetration: each prop’s convex hulls against props, walls, structure and inserts; a deepest overlap over 3 cm, then every partner it cuts (up to 3).
- orientation (look): long props within 1.2 m of a wall more than 15 deg off parallel. It never says which way a piece should face.
- uv_stretch: per mesh resource, large triangles whose UV-to-world mapping is stretched over 8:1 or collapsed to a line, where an instance shows them (a reveal that inserts normally cover = warn).
- duplicate: the same scene at the same transform.
- z_fight: coplanar overlapping faces anywhere, from each mesh’s planar face groups: between any two pieces (props, roofs, ledges, side walls, inserts against hosts, decals; opposite-facing only when both are double-sided) and between two surfaces of one mesh (once per mesh), plus the ray samples. Coplanar = a gap under twice the 24-bit depth step at the view distance (the nearest walkable eye point, camera or bookmark; 30 m without one) for the main camera’s near/far; ev carries the overlap, gap, tolerance, surfaces, the plane’s normal and the axis to nudge (nudge.world, nudge.local: a window can share its head or a jamb with its host, not its front). Warn over 0.05 m2 seen from a viewpoint; the material decides what is demoted to look, with the reason: render_priority, depth or normal offsets, a see-through (alpha) material, no depth test or depth writes.
- lights: meshes paired with more than the per-object limit of omni or spot lights (Compatibility: 8 each; light cuts off at seams), spot lights with spot_angle_attenuation under 3; shadowed light counts.
- transform: NaN, negative or non-uniform scale, a piece far out of bounds, and pieces left at the origin: an identity LOCAL transform under an identity parent, touching nothing and not one of a row of siblings (several sharing it warn, one alone is look; a module whose corner is the world origin is placed).
- resource: missing dependency files, MeshInstance3D without a mesh, surfaces without a material.
- after each build stage of a 3D level or kit-built street: “what is wrong with this scene and where exactly?”
- before calling a scene done: find see-through walls (an insert narrower than its frame), floor tiles with holes, props floating, sunk or poking into walls
- facade bands with an open end or a gap, seams between modules and modules out of line seen from the street; a duct or downpipe with a missing elbow, coupler or section
- the same look items keep coming back: accept the ones you judged fine (accept:[{key, reason}]) so later audits count them but hide them until their evidence changes
- finding props turned the wrong way against a wall (a bench standing perpendicular to it), stretched texture strips, duplicated pieces
- flickering faces: coplanar overlaps anywhere (props, roofs, ledges, inserts against hosts, decals, two surfaces of one mesh), judged by the 24-bit depth precision at the view distance
- bare ground at wall bases, an underlay plane covering drain channels, buried props: floor_gap and sunken say which surface a ray hits first
- a lit city scene in the Compatibility renderer: meshes lit by more than the per-object light limit, hard spot rims
- you already know the spot: look at it with
summer_frame_nodesorsummer_zoom, measure it withsummer_raycastorsummer_measure - the question is gameplay or reachability:
summer_navigation_probe,summer_play - the scene has unsaved edits you want audited: it reads the SAVED file, so save first
- requires ScenePreview (any current Summer Engine); an engine without it answers engine_lacks_op
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns at most 5 KB of JSON: counts per check, time per check (editor ms), the scene size, and ONE page of issues {n, check, sev (error|warn|look), path, pos (world), why, ev (evidence numbers: sizes, distances, angles, the ray to reproduce), next (the tool to use next), key (for accept)}.
summer_screenshot
On the local MCP (summer-engine npm).
Capture a frame from Summer Engine and return it as an image you can look at directly.
Use this to visually verify your work: scene layout, asset placement, scale, framing, missing/untextured assets, or runtime gameplay state. You see the actual pixels — no description layer in between. Lighting and materials are only truthfully shown by the “viewport” and “game” targets — see the note on “scene” below.
target:
“viewport” (default) — the editor’s CURRENT view (whatever scene/tab is open). No game boot. Use for edit-time checks of how the scene looks right now.
“scene” — an OFFSCREEN render of a scene file (no game boot; scripts do not run, physics/particles/animations are static at t=0, so runtime-hidden UI shows as saved). Optionally pass scenePath/framing/size/nodePath. Use for COMPOSITION, SCALE and FRAMING without touching the editor’s open tab.
With the preset framings (iso/top/…), it does NOT use the scene’s environment/sky, and it injects a synthetic camera and light when the scene has none. The scene’s WorldEnvironment — sky, fog, tonemap, glow, SSAO, ambient — is replaced by a flat preview environment. So those framings CANNOT verify lighting, mood, or any material property that depends on the environment: change them and the frame comes back identical.
framing:“camera” is the exception and the trustworthy way to check lighting edit-time: it renders through the scene’s OWN current/first Camera3D (or the one named by camera_path) with the scene’s REAL WorldEnvironment — sky, fog, tonemap, glow, ambient all live. Use it before/after any lighting, environment, or emissive-material change, and to see the scene the way the played game will actually frame it.
STABLE VIEWPOINTS (newer engines): framing:“bookmark” + bookmark_name renders from a pose saved with summer_camera_bookmark, and framing:“free” from an explicit camera_position / camera_look_at (+ fov). Both are fixed synthetic poses rendered with the scene’s REAL WorldEnvironment, and the same pose every time — the way to take before/after frames that actually line up. marks:true draws a Set-of-Mark overlay (numbered tags + boxes over the largest visible 3D nodes, up to max_marks) and the caption lists label -> node path, so you can say “label 3 (Props/Crate_02) is floating” instead of guessing. The scene file is never touched. 2D scenes render normally with marks_unsupported. Older engines resolve the new framings to a preset and ignore marks — the caption says so; a frame from such a build is NOT pose-stable.
“game” — a frame from the RUNNING game (real runtime state). Start the game first (summer_play). Works over the plain local connection on current Summer Engine builds (verified on 0.5.65, about 1.4 s); if a build refuses with bridge_required the result says so and names the alternatives.
BLANK FRAMES ARE A CAPTURE CONDITION, NOT A SCENE FACT. A uniformly black/grey “viewport” frame means the editor had not redrawn its viewport texture when it was read (typically right after a tab switch or a scene mutation) — not that the scene is dark or has no camera. Every frame is content-checked; a flat viewport frame is recaptured once automatically and the caption says what happened. Never conclude anything about lights, cameras, or content from a blank frame: recapture first.
Static frame only — one moment, not motion. For a SEQUENCE of frames over time, or for anything lighting-dependent on an engine build without framing:“camera”, use a RunVerification probe’s save_frame(name) — its instance has a real renderer.
- visually verifying layout, scale, framing, or runtime state
- “show me what the scene looks like right now”
- “did the model land where I put it?” / “does the UI overlap?”
- “take a screenshot of the game” / “screenshot the running game” — target “game” grabs the live frame
- before/after frames from the SAME viewpoint (framing “bookmark” / “free”), or an annotated screenshot with numbered labels mapped to node paths (marks)
- “what changed since the last render of this view?” — framing “bookmark” with compare_previous returns previous | now | difference map in one image
- verifying lighting, mood, or environment-dependent materials with a preset framing (iso/top/front/…) of the scene target - those replace the WorldEnvironment with a flat preview; use framing “camera” (the scene’s own Camera3D + real environment), a fixed pose (“free” / “bookmark”, real environment too), or the game target instead
- capturing motion or a sequence of frames (use a RunVerification probe’s save_frame)
- treating a uniformly black or grey “viewport” frame as evidence about lights, cameras, or content - the editor had not redrawn its viewport texture yet; the tool recaptures once and says so in the caption, otherwise recapture yourself
- saving or listing the viewpoints themselves —
summer_camera_bookmark - fitting a camera to nodes with the real environment, many views in one image, debug views, zooms or automatic framing —
summer_frame_nodes,summer_shot_sheet,summer_debug_views,summer_zoom,summer_frame_shot
Input JSON schema
Input JSON schema
isError.
summer_shot_sheet
On the local MCP (summer-engine npm).
Render several bookmarks and/or explicit poses into ONE labelled grid image in a single call: same tile size, same view, real lighting. Use it after every change to see all hero views at once instead of N screenshots.
compare_previous:true turns each bookmark into a row of [previous | now | difference map] and reports the share of pixels that changed and where. Each bookmark keeps exactly one previous render (its compare baseline) at res://.summer/shots/<bookmark>.jpg (JPEG, <= 1024 px; the folder is capped at 20 MB, oldest first). Only compare_previous:true or update_previous:true replaces it; a plain sheet creates a missing baseline and never overwrites one. view renders every tile as lighting/unshaded/normals/overdraw/wireframe instead of beauty.
Returns the grid + caption (tile number -> label and pose, difference stats). Read-only: the scene file, the open tab and the undo history are never touched (the render is an offscreen copy of the SAVED scene). The image arrives inline; the caption carries poses, labels and numbers. Failures are structured (failure_reason), never a silent fallback.
- seeing every hero view of an environment at once after a change, in one image
- “did this change make it better?” — compare_previous puts previous, now and a difference map side by side per bookmark; plain sheets in between never reset that baseline
- rendering several poses in one debug view (lighting, unshaded, normals, overdraw, wireframe) for a quick sweep
- one pose in all debug views —
summer_debug_views - motion or a frame sequence — a RunVerification probe’s save_frame
- requires ScenePreview (any current Summer Engine); bookmarks require the camera bookmark ops (0.5.66 or newer)
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the grid + caption (tile number -> label and pose, difference stats).
summer_snapshot_diff
On the local MCP (summer-engine npm).
Diff two world snapshots into exactly what changed: added/removed node paths, changed nodes with the fields that moved (pos, scale, material fingerprint, …), and per-class count deltas. Reads like a receipt — no wading through two full dumps.
Standard use: take summer_world_snapshot BEFORE a mutation batch, mutate, then call this with from_id (to_id omitted = the engine takes a fresh snapshot now). Verify the diff matches your INTENT: exactly the nodes you meant to add were added, nothing you didn’t touch changed, nothing vanished. An empty diff after a “successful” mutation is a red flag — the change did not land (wrong scene? unsaved? unowned nodes dropped on save?).
The engine retains the last 8 snapshot ids per session; an expired/unknown id fails with failure_reason “unknown_snapshot” — take a fresh baseline and re-run the mutation check rather than guessing.
- verifying a mutation batch against the snapshot_id taken before it
- “what changed in the scene after that script ran?”
- proving a batch only moved the props it was meant to
- no baseline snapshot exists — take
summer_world_snapshotfirst - requires an engine build with DiffWorldSnapshot (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_stop
On the local MCP (summer-engine npm).
Stop the running game. Use after runtime verification or when you intentionally need to restart the running instance; ordinary editor scene mutations do not require a blanket stop. Pass instance to stop ONE offscreen instance started with summer_play {instance, mode:‘offscreen’} (the result reports was_playing and killed); omit it for the editor’s main game.
- runtime verification is finished
- the game must restart to pick up scene or script changes
- a runaway or frozen playtest needs killing
- an offscreen playtest instance (
summer_playwith instance + mode offscreen) is no longer needed — pass instance
- you want to undo scene edits — stopping reverts nothing; use editor undo /
summer_batchUndo - saving — stopping does not save;
summer_save_scene
Input JSON schema
Input JSON schema
isError.
summer_ui_screenshot
On the local MCP (summer-engine npm).
PNG of the editor window (or one dock / dialog / control’s rect) returned as an image you can look at — the PIXELS-LAST fallback of the UI ladder: use it to see layout, an unfamiliar panel, or to sanity-check what the tree described, never to pick click coordinates (there is no coordinate click; summer_ui_activate takes paths). For the 3D/2D viewport, a scene render, or the running game use summer_screenshot instead — that is the visual-verification tool for scene work, and scene work itself goes through summer_run_script and the scene tools, never through the editor UI. (preview — needs an engine build with UiScreenshot)
Order of preference: a dedicated tool -> summer_ui_actions mode:‘invoke’ by name -> summer_ui_tree + summer_ui_activate by control path -> summer_ui_screenshot (pixels, last, and only to LOOK — never to pick coordinates). Prefer summer_ui_tree for state: a control’s checked/current_tab/text is exact there and costs a fraction of an image.
root: ‘window’ (default; the whole editor window incl. embedded dialogs) | ‘main’ | ‘dock:<title|id>’ | ‘dialog:<title>’ | ‘path:<node path>’ — a Control or embedded dialog is cropped out of the root viewport texture; a native OS sub-window is not in it (native_subwindow). max_size caps the longest edge (default 1024, 16-4096). Captured from the editor’s own root viewport texture, never the OS screen (safety_boundary:‘no_os_screen_capture’).
Headless is honest: under a headless editor (dummy rendering driver) the result is failure_reason no_renderer — nothing was drawn, so there are no pixels; summer_ui_tree is the structured view of the same UI and a display (Linux: —xvfb) is needed for pixels. Other failures: texture_unavailable | zero_size | native_subwindow | unknown_root | not_found | encode_failed. Engine builds without the op return a structured engine_lacks_op failure (nothing is sent).
- “show me what the editor looks like right now” / “screenshot the Inspector dock” — seeing layout or an unfamiliar panel after
summer_ui_treehas described it - sanity-checking an editor-UI step visually when the structured read-back is not enough
- verifying scene work —
summer_screenshot(viewport, scene render with framing camera, or the running game) is the visual-verification tool for scenes - reading a control’s state (checked, current_tab, text) —
summer_ui_treeis exact and far cheaper - picking coordinates to click — there is no coordinate click;
summer_ui_activatetakes tree paths - a headless editor — no renderer, no pixels (no_renderer); use
summer_ui_tree - requires an engine build with UiScreenshot (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_ui_tree
On the local MCP (summer-engine npm).
Structured tree of the live editor UI — every visible Control with its class, path, rect, text/tooltip and state (checked, enabled, focused, tabs + current_tab, value/min/max, selected item) — or, with root:‘dialogs’, every visible dialog/popup and whether one is BLOCKING input. The structured alternative to a screenshot: the tree states outright what exists and what is clickable, at a fraction of the tokens, and its paths are what summer_ui_activate takes. (preview — needs an engine build with UiTree/UiDialogs)
SCENE WORK IS NOT UI WORK: to add, move, retune, or read nodes use summer_run_script, the scene tools, summer_world_snapshot and summer_screenshot — never by clicking through the editor. UI ops are for editor-workflow steps a human would do with the mouse: open Project Settings or the Import dock, switch the 2D/3D/Script main screen, clear a dialog that is blocking input, read what a dock currently shows. Use this tree to READ editor state (which main screen is active, what a dock shows, what a dialog says and which buttons it has) and to find a control’s path when no named action covers the step; use summer_get_scene_tree / summer_world_snapshot for the SCENE — the editor’s Scene dock is a view of that data, not the data.
root: ‘main’ (default; the editor chrome) | ‘window’ (incl. every sub-window) | ‘dock:<title|id>’ (file_system | scene_tree | inspector or any dock title) | ‘dialog:<title>’ | ‘path:<node path>’ (zoom into an earlier result) | ‘dialogs’ -> {count, blocking, blocking_dialog?, dialogs:[{title, path, class, kind, exclusive, popup, embedded, focused, text?, items?, buttons:[{text, path, kind:‘ok’|‘cancel’|‘custom’, enabled}]}]}.
Tree results: {root, root_path, total_emitted, truncated, tree:{name, class, path, visible, rect, text?, tooltip?, enabled?, checked?, focused?, tabs?, current_tab?, value?, child_count, children_truncated?, children}}. Strings clip at 200 chars; icon-only toolbar buttons are named by tooltip; child_count is always the real count, so a children_truncated node can be re-read with root:‘path:<its path>’ and a larger depth/limit.
Paths (@Panel@123) are stable within a session, not across builds — re-read instead of persisting them. The blocking-dialog pattern: root:‘dialogs’ -> blocking:true -> summer_ui_activate action:‘dismiss_dialog’ path:<blocking_dialog.path> -> root:‘dialogs’ again to confirm blocking:false. Failures: unknown_root (+available_docks, dock_ids) | not_found (+visible_titles) | ambiguous_dialog (+candidates) | editor_unavailable. Engine builds without these ops return a structured engine_lacks_op failure (nothing is sent).
- “is a dialog blocking the editor” / “what does the Inspector dock show” / “which main screen is active” — read editor UI state as structure instead of pixels
- finding a control’s path before
summer_ui_activate, and reading its state back afterwards - listing visible dialogs and popups (root dialogs) before dismissing one with
summer_ui_activateaction dismiss_dialog
- reading the scene —
summer_get_scene_tree/summer_world_snapshotread the data the Scene dock merely displays - a named action already covers the step —
summer_ui_actionsmode invoke needs no tree walk - judging appearance (layout, colours, an unfamiliar panel) —
summer_ui_screenshot, pixels last - requires an engine build with UiTree / UiDialogs (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_wait_for_event
On the local MCP (summer-engine npm).
Block until the engine emits a matching EVENT, or a bounded timeout elapses — the replacement for sleeping and re-polling. Use it right after summer_play to wait for play.started (the game actually booting), after a long op (import, script, save) to wait for op.applied / op.failed by requestId instead of guessing a delay, and during a playtest to catch script.error the moment it fires.
Event kinds (v1): op.applied, op.failed, script.error, play.started, play.stopped, scene.saved, scene.opened, import.completed, selection.changed, snapshot.published. Each event is {seq, kind, ts, data}; seq is a monotonic cursor.
CURSOR DISCIPLINE: events are delivered live from since (omitted = from now). An event that fired BEFORE this call is NOT delivered, so when the moment may come fast, take a cursor first: summer_recent_events returns next_seq — pass it as since BEFORE triggering the action (summer_recent_events -> summer_play -> summer_wait_for_event since:<next_seq> kinds:[‘play.started’]). Every result carries next_seq: pass it as since on the next call to keep waiting with no gap.
match.requestId narrows op.applied / op.failed to one request (other kinds pass through). The call long-polls the engine in slices of at most 25 s until a match or timeout_seconds (default 30, max 120) elapses.
Returns {ok, matched, events, next_seq, since, timed_out, waited_ms, polls}. timed_out:true means NO matching event arrived — it is not evidence the thing did not happen (verify with summer_is_running / summer_get_diagnostics) and you must never claim an event you did not receive. A gap field means events between since and the oldest retained were evicted — re-read state instead of trusting the stream. On an engine build without the events channel (no capabilities.events in /api/health) the result is a structured engine_lacks_events failure and nothing is sent: fall back to polling the state.
- “wait for the game to start” — right after
summer_play, wait for play.started instead of guessing how long boot takes - “wait for an event” / “tell me when the import finishes” — block on op.applied / op.failed for one requestId, import.completed, or scene.saved after a long op
- during a playtest, catching script.error the moment it fires instead of reading the console afterwards
- any time you would otherwise sleep and re-check state — take a cursor with
summer_recent_eventsfirst, then wait from it
- reading what already happened —
summer_recent_events(events fired beforesinceare never delivered here) - checking a fact right now (is the game running, what is in the tree) —
summer_is_running/summer_get_scene_treeare immediate - requires an engine build with the events channel (capabilities.events, /api/events; Summer Engine 0.5.66 or newer); older engines return engine_lacks_events
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns {ok, matched, events, next_seq, since, timed_out, waited_ms, polls}.
summer_world_snapshot
On the local MCP (summer-engine npm).
Compact structured snapshot of the whole EDITED scene — the cheap read to run BEFORE and AFTER every mutation batch. Per node: path, class, transform (pos/rot/scale as Godot literal strings, 3-decimal floats), world AABB (3D visuals), visibility, and 8-hex resource fingerprints (script/materials — detect-change markers, never content). Plus a light summary, camera list, environment fingerprint, and per-class counts.
THE LOOP: summer_world_snapshot (note snapshot_id) -> mutate (summer_run_script / scene tools / imports) -> summer_snapshot_diff from_id:<that id> -> summer_screenshot. The diff proves exactly what changed structurally; the screenshot proves it looks right. This is how you catch a node that silently vanished on save, a transform that landed at the origin, or an AABB clipping through the floor.
Node lists are path-sorted and truncated DETERMINISTICALLY (result carries total_nodes + truncated) so two snapshots stay diffable without phantom adds/removes. The engine retains the last 8 snapshots per session, keyed by snapshot_id. Use this instead of summer_get_scene_tree when you need transforms/AABBs/fingerprints or a diffable baseline; the tree read remains the hierarchy-shaped view. On an engine build that predates GetWorldSnapshot the result is a structured engine_lacks_op failure naming the fallback.
KEEP IT SMALL (about 250 bytes per node): at most 200 nodes are listed by default. path_prefix reads one subtree (‘House3’, ‘Lane2/Props’), classes keeps some node classes, fields keeps some per-node fields (e.g. [‘pos’,‘aabb’]), offset/next_offset page the list. A filtered read adds matched_nodes and matched_counts (class counts of the subtree). counts and total_nodes always describe the whole scene, and snapshot_id always covers the whole scene, so summer_snapshot_diff still sees every change.
- taking a diffable baseline before a mutation batch, or verifying transforms/AABBs/fingerprints after one
- “where exactly is everything in this scene?” — positions, sizes, bounds
- “are these two props overlapping?” / “is anything floating?”
- “where did the pieces of House3 land?” — path_prefix + fields:[pos, aabb] reads one subtree cheaply
- counting instances per class in one subtree (matched_counts)
- you only need the hierarchy shape —
summer_get_scene_tree - requires an engine build with GetWorldSnapshot (Summer Engine 0.5.66 or newer); older engines return engine_lacks_op
Input JSON schema
Input JSON schema
isError.
summer_zoom
On the local MCP (summer-engine npm).
High-resolution close look at part of a frame: region [x, y, w, h] (fractions of the frame) or mark N from a marks render of the same pose. The camera renders the EXACT sub-frustum of that region at full output resolution, so you see real texture detail, seams, gaps and floating pieces, not upscaled pixels. A region is honoured exactly (no pad by default, never widened to an aspect ratio: the image takes the region’s own aspect, with dark bars only for extreme shapes); a mark gets pad 0.15.
Use after a sheet or debug view shows something suspicious. view picks beauty or a debug view. Returns the zoomed image + caption (the real zoom factor, the rendered region, widened_because when it is larger than asked, mark -> node path and a warning when that node is hidden). Read-only: the scene file, the open tab and the undo history are never touched (the render is an offscreen copy of the SAVED scene). The image arrives inline; the caption carries poses, labels and numbers. Failures are structured (failure_reason), never a silent fallback.
- checking seams, gaps, floating pieces, texture resolution or tiling up close
- looking closer at a numbered mark from a marks render (
summer_frame_nodesmarks:true, orsummer_screenshotmarks at the same size) - inspecting a region a difference map or debug view flagged
- the whole view —
summer_shot_sheet/summer_frame_nodes - you have no pose yet — get one from a bookmark or
summer_frame_shotfirst
Input JSON schema
Input JSON schema
isError. From the tool’s own description: Returns the zoomed image + caption (the real zoom factor, the rendered region, widened_because when it is larger than asked, mark -> node path and a warning when that node is hidden).

