Skip to content
ClaudeUnreal
GitHub

Scene & Actors

This content is not available in your language yet.

40 tools — 12 typed MCP · 28 via cu CLI.

  • Scene — Actors — 26 tools
  • Editor — Viewport & Console — 4 tools
  • Level Management — 5 tools
  • Scene — Spline Components — 5 tools

Create a new actor in the current level with position, rotation, and type.

@mcp.tool()
@showcase(
"Create a new actor in the current level with position, rotation, and type.",
featured=True,
)
def spawn_actor(
ctx: Context,
name: str,
type: str,
location: List[float] = [0.0, 0.0, 0.0],
rotation: List[float] = [0.0, 0.0, 0.0]
) -> ToolResult:
"""[Actor] Create a new actor in the current level.
Anti-patterns:
- Do not pass ``type`` outside the fixed enum below — the handler rejects
unknown types. For project-defined C++ classes or Blueprints, use
``spawn_actor_by_class`` / ``spawn_blueprint_actor`` instead.
- Do not reuse a ``name`` already in use by another actor in the level —
the handler returns "Actor with name '...' already exists".
- Do not pass ``location`` / ``rotation`` arrays of length != 3 — Python
wrapper rejects before sending.
Args:
ctx: The MCP context
name: The name to give the new actor (must be unique)
type: The type of actor to create. Supported:
StaticMeshActor, PointLight, SpotLight, DirectionalLight, CameraActor,
PlayerStart, TargetPoint, TriggerBox, TriggerSphere,
SkyLight, SkyAtmosphere, ExponentialHeightFog, VolumetricCloud,
PostProcessVolume
location: The [x, y, z] world location to spawn at
rotation: The [pitch, yaw, roll] rotation in degrees
Returns:
ToolResult with headline "Spawned <type> '<name>' at (x, y, z)" on success
(with rotation appended when non-zero), or
"Failed to spawn '<name>': reason" on failure.
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
logger.error("Failed to connect to Unreal Engine")
return err(f"Failed to spawn '{name}': no response from Unreal Engine")
# Ensure all parameters are properly formatted
params = {
"name": name,
"type": type.upper(), # Make sure type is uppercase
"location": location,
"rotation": rotation
}
# Validate location and rotation formats
for param_name in ["location", "rotation"]:
param_value = params[param_name]
if not isinstance(param_value, list) or len(param_value) != 3:
logger.error(f"Invalid {param_name} format: {param_value}. Must be a list of 3 float values.")
return err(
f"Failed to spawn '{name}': invalid {param_name} format",
error=f"{param_name} must be a list of 3 float values",
)
# Ensure all values are float
params[param_name] = [float(val) for val in param_value]
logger.info(f"Creating actor '{name}' of type '{type}' with params: {params}")
response = unreal.send_command("spawn_actor", params)
if not response:
logger.error("No response from Unreal Engine")
return err(f"Failed to spawn '{name}': no response from Unreal Engine")
# Log the complete response for debugging
logger.info(f"Actor creation response: {response}")
# Handle error responses correctly
if response.get("status") == "error":
error_message = response.get("error", "Unknown error")
logger.error(f"Error creating actor: {error_message}")
return err(f"Failed to spawn '{name}': {error_message}", error=error_message)
loc = params["location"]
loc_str = f"({loc[0]:g}, {loc[1]:g}, {loc[2]:g})"
rot = params["rotation"]
headline = f"Spawned {type} '{name}' at {loc_str}"
if any(r != 0.0 for r in rot):
headline += f" rot ({rot[0]:g}, {rot[1]:g}, {rot[2]:g})"
return ok(headline)
except Exception as e:
error_msg = f"Error creating actor: {e}"
logger.error(error_msg)
return err(f"Failed to spawn '{name}'", error=str(e))

Capture the active editor viewport and save it as a PNG file for visual verification.

@mcp.tool()
@showcase(
"Capture the active editor viewport and save it as a PNG file for visual verification.",
featured=True,
)
def take_screenshot(
ctx: Context,
filepath: str,
) -> ToolResult:
"""[Viewport]
Take a screenshot of the active editor viewport and save it as a PNG file.
Args:
filepath: File path to save the screenshot (e.g. "C:/Screenshots/my_shot.png").
The .png extension will be added automatically if missing.
Returns:
ToolResult with headline "Screenshot saved to <path>" on success, or
"Failed to save screenshot: reason" on failure.
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
logger.error("Failed to connect to Unreal Engine")
return err("Failed to save screenshot: no response from Unreal Engine")
response = unreal.send_command("take_screenshot", {
"filepath": filepath
})
if not response:
logger.error("No response from Unreal Engine")
return err("Failed to save screenshot: no response from Unreal Engine")
logger.info(f"Take screenshot response: {response}")
result = response.get("result", response)
if response.get("status") == "error" or result.get("success") is False:
error_message = response.get("error") or result.get("error") or result.get("message") or "unknown error"
return err(f"Failed to save screenshot: {error_message}", error=error_message)
saved_path = result.get("filepath") or result.get("file_path") or filepath
return ok(f"Screenshot saved to {saved_path}")
except Exception as e:
error_msg = f"Error taking screenshot: {e}"
logger.error(error_msg)
return err("Failed to save screenshot", error=str(e))

Run any Unreal console command — CVars, stat overlays, showdebug, cheat manager (Slomo, God), or UFUNCTION(Exec) via ke * &lt;FunctionName> — against the editor or a running PIE session.

@mcp.tool()
@showcase(
"Run any Unreal console command — CVars, stat overlays, showdebug, cheat manager (Slomo, God), or UFUNCTION(Exec) via `ke * <FunctionName>` — against the editor or a running PIE session.",
featured=True,
)
def exec_console_command(
ctx: Context,
command: str,
target: str = "auto",
) -> ToolResult:
"""[Debug] Execute an Unreal console command in the editor or a running PIE session.
This lets you drive the same commands you'd normally type into the in-editor `~`
console: stat overlays, `showdebug`, CVars (`r.ScreenPercentage 50`), cheat
manager commands (`Slomo 0.1`, `God`), and `UFUNCTION(Exec)` functions on the
player controller / pawn / game mode via `ke * <FunctionName>`.
Anti-patterns:
- Do not pass an empty ``command`` — rejected at the handler.
- Do not include the leading backtick / tilde (``~``); pass just the command body.
- ``target="pie"`` requires an active PIE session; if no PIE is running, use
``start_play_in_editor`` first or use ``target="editor"``.
Args:
command: The console command string, e.g. "stat fps", "r.ScreenPercentage 50",
"ke * SetAgentState Thinking".
target: Which world to execute against:
- "auto" (default): use PIE if a session is running, else the editor world.
- "editor": run against the editor world (useful for r.* CVars, stat overlays in the editor viewport).
- "pie": require a running PIE session; route through the first local PlayerController so cheat manager and Exec UFUNCTIONs work. Errors if no PIE is active.
- "game": alias for "pie".
Returns:
ToolResult with headline "Executed console command: '<command>'" on success,
or "Failed to execute console command: reason" on failure.
Examples:
exec_console_command(command="stat fps")
exec_console_command(command="r.ScreenPercentage 50", target="editor")
exec_console_command(command="ke * SetAgentState Thinking", target="pie")
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
logger.error("Failed to connect to Unreal Engine")
return err("Failed to execute console command: no response from Unreal Engine")
response = unreal.send_command("exec_console_command", {
"command": command,
"target": target,
})
if not response:
logger.error("No response from Unreal Engine")
return err("Failed to execute console command: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to execute console command", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(f"Executed console command: {command!r}", **result)
except Exception as e:
logger.error(f"Error executing console command: {e}")
return err("Failed to execute console command", error=str(e))