unreal-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| unreal_get_statusA | Check whether a running Unreal Editor is reachable, and describe it. Call this first when any other tool fails, to distinguish "the editor is not listening" from "the script had a bug". Discovery is UDP multicast, so an editor that is open but has remote execution disabled will NOT appear. Args: params (StatusInput): Validated input containing: - wait_seconds (float): Discovery listen window, 0.5-15.0 (default 2.0) Returns: str: JSON with the following schema: { "connected": bool, # True if at least one editor answered "node_count": int, # Number of editor instances discovered "nodes": [ # One entry per editor instance { "node_id": str, # Internal session id "user": str, # OS user running the editor "machine": str, # Host name "engine_version": str, # e.g. "5.6.0-..." "engine_root": str, # Engine install path "project_name": str, # Loaded project "project_root": str # Project directory on disk } ], "live_check": { # Present only when connected "engine_version": str, "project_file": str, "current_level": str, "actor_count": int } } On failure: "Error: " Examples: - Use when: another tool returned a connection error and you need the cause - Use when: confirming which project the editor currently has open - Don't use when: you already know the editor is connected and want to run code (use unreal_execute_python instead) |
| unreal_execute_pythonA | Run arbitrary Python inside the running Unreal Editor. This is the general-purpose escape hatch for anything the dedicated tools do not cover. Prefer a specific tool when one exists, because those return structured data while this returns raw console output. The code runs in the editor's own interpreter with full access to the
Args: params (ExecuteInput): Validated input containing: - code (str): Python source to run - evaluate (bool): True for single-expression evaluation (default False) Returns: str: JSON with the following schema: { "success": bool, # False if Unreal reported the command as failed "result": str, # Value for evaluate=True, else Unreal's status string "output": str # Everything the script printed / logged } On failure: "Error: " Examples: - Use when: "how many static meshes are in /Game/Props?" -> code that counts them and prints the number - Use when: calling an unreal API no other tool exposes - Don't use when: listing actors or assets (use unreal_list_actors / unreal_list_assets, which paginate and return structured fields) |
| unreal_list_assetsA | List assets in the project's content browser, with filtering and pagination. Use this to find the object path of an asset before spawning it into a level.
Returns paths in Unreal's Args: params (ListAssetsInput): Validated input containing: - directory (str): Content path to list (default '/Game') - recursive (bool): Recurse into subfolders (default True) - name_filter (Optional[str]): Case-insensitive substring match - limit (int): Max results, 1-500 (default 50) - offset (int): Results to skip (default 0) Returns: str: JSON with the following schema: { "total": int, # Assets matching the filter "count": int, # Assets in this page "offset": int, "has_more": bool, "next_offset": int | None, "items": [ { "name": str, # Asset name (e.g. "SM_Chair") "path": str, # Object path for loading (e.g. "/Game/Props/SM_Chair") "class": str # Asset class (e.g. "StaticMesh", "Material") } ] } On failure: "Error: " Examples: - Use when: "what meshes did my FBX import create?" -> directory of the import - Use when: you need an asset path to pass to unreal_spawn_actor - Don't use when: you want actors placed in the level (use unreal_list_actors) |
| unreal_import_assetA | Import a file from disk (FBX, OBJ, texture) into the project's content browser. Runs Unreal's automated import pipeline, so no import dialog appears. With
Args: params (ImportAssetInput): Validated input containing: - source_file (str): Absolute path to the file on disk - destination_path (str): Content folder, must start with /Game - replace_existing (bool): Overwrite same-named assets (default True) - save (bool): Save to disk right away (default True) Returns: str: JSON with the following schema: { "imported_count": int, # Number of assets created "imported": [str], # Object paths of the new assets "destination": str # Folder they landed in } On failure: "Error: " — including a clear message when the source file does not exist on the machine running the editor. Examples: - Use when: "bring this FBX into Unreal" -> source_file set to the .fbx - Use when: staging a model before placing it with unreal_spawn_actor - Don't use when: the asset is already in the project (use unreal_list_assets) |
| unreal_list_actorsA | List actors placed in the currently open level, with their transforms. The Args: params (ListActorsInput): Validated input containing: - name_filter (Optional[str]): Substring match on the actor label - class_filter (Optional[str]): Substring match on the actor class - limit (int): Max results, 1-500 (default 50) - offset (int): Results to skip (default 0) Returns: str: JSON with the following schema: { "total": int, "count": int, "offset": int, "has_more": bool, "next_offset": int | None, "items": [ { "label": str, # Outliner name, use this as an identifier "path": str, # Unique full path "class": str, # e.g. "StaticMeshActor" "location": [float, float, float], # X, Y, Z in cm "rotation": [float, float, float], # pitch, yaw, roll in degrees "scale": [float, float, float] } ] } On failure: "Error: " Examples: - Use when: "what's in this level?" -> no filters - Use when: finding the exact label to pass to unreal_set_actor_transform - Don't use when: looking for unplaced content (use unreal_list_assets) |
| unreal_spawn_actorA | Place an existing content asset into the current level as a new actor. Each call creates a new actor, so calling it twice spawns two copies. Get
valid Args: params (SpawnActorInput): Validated input containing: - asset_path (str): Content path of the asset to place - location (list[float]): [X, Y, Z] in centimetres (default origin) - rotation (list[float]): [pitch, yaw, roll] in degrees - scale (list[float]): [X, Y, Z] multipliers - label (Optional[str]): Outliner name for the actor Returns: str: JSON describing the created actor: { "label": str, "path": str, "class": str, "location": [float, float, float], "rotation": [float, float, float], "scale": [float, float, float] } On failure: "Error: " — including a clear message when asset_path does not exist. Examples: - Use when: "put the imported chair at the origin" after unreal_import_asset - Don't use when: moving something already in the level (use unreal_set_actor_transform) |
| unreal_set_actor_transformA | Change the location, rotation and/or scale of an actor already in the level. Any field left as None keeps its current value, so this can nudge one axis of a transform without disturbing the rest. Setting the same values twice has no additional effect. Args: params (SetTransformInput): Validated input containing: - actor (str): Label or path identifying the actor - location (Optional[list[float]]): New [X, Y, Z] in cm - rotation (Optional[list[float]]): New [pitch, yaw, roll] in degrees - scale (Optional[list[float]]): New [X, Y, Z] multipliers Returns: str: JSON describing the actor after the change, same schema as unreal_spawn_actor. On failure: "Error: " — including the hint to list actors when the label does not resolve. Examples: - Use when: "raise the camera rig 200 units" -> location with new Z - Don't use when: creating a new copy (use unreal_spawn_actor) |
| unreal_delete_actorA | Permanently remove an actor from the current level. This is destructive. The actor is destroyed in the editor world; recovering
it requires an undo inside Unreal, which this server cannot trigger. Confirm
the intended target with Args: params (DeleteActorInput): Validated input containing: - actor (str): Label or path identifying the actor to destroy Returns: str: JSON confirming the removal: { "deleted": bool, "label": str, # Label of the actor that was destroyed "path": str # Its former path } On failure: "Error: " Examples: - Use when: the user explicitly asks to remove a placed object - Don't use when: you only want to hide it, or when unsure which actor the label refers to (list them first) |
| unreal_set_viewport_cameraA | Move the editor's perspective viewport camera to a specific pose. Affects only the editor view, not any CameraActor in the level and no saved
project data. Pair with Args: params (ViewportCameraInput): Validated input containing: - location (list[float]): Camera position [X, Y, Z] in cm - rotation (list[float]): Camera orientation [pitch, yaw, roll] degrees Returns: str: JSON with the camera pose actually applied: { "location": [float, float, float], "rotation": [float, float, float] } On failure: "Error: " Examples: - Use when: framing a shot before unreal_take_screenshot - Don't use when: you want a camera the level keeps (spawn a CameraActor) |
| unreal_take_screenshotA | Capture a high-resolution screenshot of the editor viewport to a PNG file. Unreal writes the file asynchronously, so the path is returned before the
image is guaranteed to be on disk; allow a moment before reading it. Frame
the shot first with Args: params (ScreenshotInput): Validated input containing: - filename (str): Absolute output path for the PNG - width (int): Width in pixels, 64-7680 (default 1920) - height (int): Height in pixels, 64-4320 (default 1080) Returns: str: JSON confirming the request: { "requested": bool, "filename": str, # Where Unreal was told to write "resolution": [int, int], "note": str # Reminder that the write is asynchronous } On failure: "Error: " Examples: - Use when: producing a visual check of the level after placing actors - Don't use when: you need a final production render (use Movie Render Queue via unreal_execute_python) |
| unreal_save_allA | Save every modified asset, and optionally the open level, to disk. Writes to the project on disk. Running it twice with nothing changed in between is harmless. Args: params (SaveInput): Validated input containing: - save_level (bool): Also save the open level (default True) Returns: str: JSON with the outcome: { "saved": bool, # False if the user cancelled a save prompt "save_level": bool # What was requested } On failure: "Error: " Examples: - Use when: finishing a batch of spawns or imports the user wants kept - Don't use when: the user is still experimenting and may want to discard |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 11 tools
Each tool targets a distinct resource and action—actors, assets, the viewport, saving, or status. The only broad tool, unreal_execute_python, explicitly frames itself as an escape hatch and tells agents to prefer specific tools, so there is no real ambiguity.
Every tool follows the same `unreal_<verb>_<noun>` snake_case pattern, e.g. list_actors, spawn_actor, delete_actor, take_screenshot, save_all. This makes the tool surface highly predictable.
Eleven tools is a well-scoped size for Unreal Editor automation: core actor and asset operations, viewport control, diagnostics, and saving are all represented without excessive redundancy. Each tool earns its place.
The set covers the main actor lifecycle (list, spawn, transform, delete), asset listing/import, viewport framing, screenshots, and saving, which forms a coherent workflow. Some asset management operations like delete or rename are missing, but unreal_execute_python provides a workaround for uncovered cases.