Skip to content
ClaudeUnreal
GitHub

Assets

24 tools — 0 typed MCP · 24 via cu CLI.

  • Asset — Search & Browse — 5 tools
  • Asset — Operations — 5 tools
  • Asset — Data Assets & Tables — 6 tools
  • Asset — Import & Export — 3 tools
  • Asset — Tags & Management — 5 tools

Search project assets by name, class type, or content path using the Asset Registry.

@mcp.tool()
@showcase(
"Search project assets by name, class type, or content path using the Asset Registry.",
featured=True,
)
def find_assets(
ctx: Context,
name: str = None,
class_type: str = None,
path: str = None,
max_results: int = None,
limit: int = None,
offset: int = None,
) -> ToolResult:
"""[Asset] Search for assets by name, class type, or path using the Asset Registry.
At least one search parameter is required. Results are returned from /Game by default.
Use limit and offset for pagination through large result sets.
Args:
ctx: The MCP context
name: Partial name match (case-insensitive), e.g. "MyChar"
class_type: Asset class to filter by, e.g. "StaticMesh", "Material", "Blueprint",
"AnimSequence", "AnimBlueprint", "Texture2D", "SoundWave", "SkeletalMesh"
path: Content path to search in, e.g. "/Game/Characters" (recursive)
max_results: Maximum number of results (default 100, max 1000) — use limit instead
limit: Maximum number of results to return (default 50, max 500), e.g. 50
offset: Number of results to skip for pagination (default 0), e.g. 50
Returns:
Dict with 'assets' list (name, path, package_path, class), 'total' (all matches),
'limit', and 'offset'
Examples:
First page: find_assets(class_type="StaticMesh", limit=50, offset=0)
Second page: find_assets(class_type="StaticMesh", limit=50, offset=50)
"""
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("find_assets failed", error="Failed to connect to Unreal Engine")
params = {}
if name is not None:
params["name"] = name
if class_type is not None:
params["class_type"] = class_type
if path is not None:
params["path"] = path
if max_results is not None:
params["max_results"] = max_results
if limit is not None:
params["limit"] = limit
if offset is not None:
params["offset"] = offset
response = unreal.send_command("find_assets", params)
if not response:
return err("find_assets failed", error="No response from Unreal Engine")
if response.get("status") == "error":
return err("find_assets failed", error=response.get("error", "Unknown error"))
result = response.get("result", response)
assets = result.get("assets", [])
total = result.get("total", len(assets))
return ok_list(f"Found {total} asset{'s' if total != 1 else ''}", assets, total=total)
except Exception as e:
logger.error(f"Error in find_assets: {e}")
return err("find_assets failed", error=str(e))

Import external files (FBX, OBJ, PNG, WAV) into the Unreal project.

@mcp.tool()
@showcase(
"Import external files (FBX, OBJ, PNG, WAV) into the Unreal project.",
featured=True,
)
def import_asset(
ctx: Context,
file_path: str,
destination_path: str = None,
destination_name: str = None,
replace_existing: bool = None,
automated: bool = None,
) -> ToolResult:
"""[Asset] Import an external file (FBX, OBJ, PNG, WAV, etc.) into the Unreal project.
Supports all file types that Unreal can import: 3D meshes (FBX, OBJ, glTF),
textures (PNG, TGA, JPG, EXR), audio (WAV, OGG), and more.
Anti-patterns:
- ``file_path`` is a **filesystem absolute path** (where the source file lives).
``destination_path`` is a **Content package path** (must start with ``/Game``).
They are NOT interchangeable.
- Do not include the asset extension in ``destination_name`` (no ``.uasset``).
- Do not pass a relative ``file_path``; use the absolute path on disk.
- Do not call this on a ``file_path`` that does not exist on disk — the
handler verifies the file before invoking the importer.
- Stick to formats Unreal can import (FBX, OBJ, glTF for meshes; PNG/TGA/JPG/EXR
for textures; WAV/OGG for audio). Other extensions silently produce no assets.
Args:
ctx: The MCP context
file_path: Absolute path to the source file on disk, e.g. "C:/Assets/MyMesh.fbx"
destination_path: Content path to import into, e.g. "/Game/Meshes" (default "/Game")
destination_name: Override the imported asset name (default: source filename without extension)
replace_existing: If true, overwrite an existing asset with the same name (default false)
automated: If true, skip all dialog prompts (default true)
Returns:
Dict with source_file, destination_path, imported_assets list, and count
"""
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("import_asset failed", error="Failed to connect to Unreal Engine")
params = {"file_path": file_path}
if destination_path is not None:
params["destination_path"] = destination_path
if destination_name is not None:
params["destination_name"] = destination_name
if replace_existing is not None:
params["replace_existing"] = replace_existing
if automated is not None:
params["automated"] = automated
response = unreal.send_command("import_asset", params)
if not response:
return err("import_asset failed", error="No response from Unreal Engine")
if response.get("status") == "error":
return err("import_asset failed", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(f"Imported '{file_path}'", **result)
except Exception as e:
logger.error(f"Error in import_asset: {e}")
return err("import_asset failed", error=str(e))

Create a UPrimaryDataAsset subclass instance with optional initial property values.

@mcp.tool()
@showcase(
"Create a UPrimaryDataAsset subclass instance with optional initial property values.",
featured=True,
)
def create_data_asset(
ctx: Context,
package_path: str,
asset_name: str,
parent_class: str,
properties: Dict[str, str] = None,
) -> ToolResult:
"""[Asset] Create an instance of a UPrimaryDataAsset (or UDataAsset) subclass.
parent_class must derive from UDataAsset; use "/Script/Mod.Class" if short
name lookup fails. Soft refs auto-expand; unresolved surface in `warnings`.
package_path must be under /Game/.
Anti-patterns: non-UDataAsset parent_class rejected; package_path outside
/Game/ rejected; existing asset at same path rejected.
Example:
create_data_asset("/Game/Data", "SL_Dune", "ALFSceneLayoutAsset",
properties={"SceneId": "Dune", "LevelAsset": "/Game/L_Dune"})
"""
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("create_data_asset failed", error="Failed to connect to Unreal Engine")
params = {
"package_path": package_path,
"asset_name": asset_name,
"parent_class": parent_class,
}
if properties is not None:
params["properties"] = properties
response = unreal.send_command("create_data_asset", params)
if not response:
return err("create_data_asset failed", error="No response from Unreal Engine")
if response.get("status") == "error":
return err("create_data_asset failed", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(f"Created data asset '{asset_name}' ({parent_class})", **result)
except Exception as e:
logger.error(f"Error in create_data_asset: {e}")
return err("create_data_asset failed", error=str(e))

Set a property on an existing UDataAsset instance by reflection.

@mcp.tool()
@showcase(
"Set a property on an existing UDataAsset instance by reflection.",
featured=True,
)
def set_data_asset_property(
ctx: Context,
asset_path: str,
property_name: str,
property_value: str,
save: bool = False,
) -> ToolResult:
"""[Asset] Set a property on an existing UDataAsset instance via reflection.
Supports dotted+indexed paths (e.g. "Strata[0].Rules.SlopeDegreeRange"),
structs ("X=1,Y=2"), arrays ("(A,B,C)"), and soft refs (auto-expanded to
"/Game/Foo.Foo"; unresolved surface in `warnings`).
Anti-patterns: non-UDataAsset rejected; array-index on non-array rejected;
dotted on non-struct rejected; save=True mid-edit risks inconsistent state.
Example:
set_data_asset_property("/Game/Data/SL_Foo", "LevelAsset",
"/Game/Maps/L_Foo", save=True)
"""
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("set_data_asset_property failed", error="Failed to connect to Unreal Engine")
response = unreal.send_command("set_data_asset_property", {
"asset_path": asset_path,
"property_name": property_name,
"property_value": property_value,
"save": save,
})
if not response:
return err("set_data_asset_property failed", error="No response from Unreal Engine")
if response.get("status") == "error":
return err("set_data_asset_property failed", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(f"Set '{property_name}' on {asset_path}", **result)
except Exception as e:
logger.error(f"Error in set_data_asset_property: {e}")
return err("set_data_asset_property failed", error=str(e))

Create a UDataTable asset with a specified row struct for data-driven content.

@mcp.tool()
@showcase(
"Create a UDataTable asset with a specified row struct for data-driven content.",
featured=True,
)
def create_data_table(
ctx: Context,
package_path: str,
asset_name: str,
row_struct: str,
) -> ToolResult:
"""[Asset] Create an empty UDataTable asset with the specified row struct.
After creation, use data_table_add_row to populate it with rows.
The row struct must inherit from FTableRowBase.
Anti-patterns:
- Do not pass ``row_struct`` that doesn't inherit from ``FTableRowBase`` —
handler rejects.
- Do not pass ``row_struct`` from an unloaded module — pass full path
``/Script/ModuleName.StructName`` when the short-name lookup fails.
- Do not pass a ``package_path`` outside ``/Game/``.
- Do not call when an asset already exists at ``package_path/asset_name``.
Args:
ctx: The MCP context
package_path: Content path for the asset, e.g. "/Game/Data"
asset_name: Name of the new DataTable, e.g. "DT_SceneCatalog"
row_struct: Row struct name — short name like "MyRowStruct"
or full path like "/Script/MyModule.MyRowStruct"
Returns:
Dict with asset_path, asset_name, row_struct, package_path
Examples:
create_data_table(
package_path="/Game/Data/Scenes",
asset_name="DT_SceneCatalog",
row_struct="ALFSceneCatalogRow",
)
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("create_data_table failed", error="Failed to connect to Unreal Engine")
response = unreal.send_command("create_data_table", {
"package_path": package_path,
"asset_name": asset_name,
"row_struct": row_struct,
})
if not response:
return err("create_data_table failed", error="No response from Unreal Engine")
if response.get("status") == "error":
return err("create_data_table failed", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(f"Created DataTable '{asset_name}' (row struct: {row_struct})", **result)
except Exception as e:
logger.error(f"Error in create_data_table: {e}")
return err("create_data_table failed", error=str(e))