# Auto-generated — do not edit by hand.
# Source: scripts/generate-default-config.ts

ue-mcp:
  version: 1

tasks:

  # ── project ──
  project.get_status:
    class_path: project.get_status
    group: project
    description: Check server mode and editor connection
  project.set_project:
    class_path: project.set_project
    group: project
    description: "Switch project. Params: projectPath"
  project.get_info:
    class_path: project.get_info
    group: project
    description: Read .uproject file details
  project.read_config:
    class_path: project.read_config
    group: project
    description: "Read INI config. Params: configName (e.g. 'Engine', 'Game')"
  project.search_config:
    class_path: project.search_config
    group: project
    description: "Search INI files. Params: query"
  project.list_config_tags:
    class_path: project.list_config_tags
    group: project
    description: Extract gameplay tags from config
  project.read_cpp_header:
    class_path: project.read_cpp_header
    group: project
    description: "Parse a .h file. Params: headerPath"
  project.read_module:
    class_path: project.read_module
    group: project
    description: "Read module source. Params: moduleName"
  project.list_modules:
    class_path: project.list_modules
    group: project
    description: List C++ modules
  project.search_cpp:
    class_path: project.search_cpp
    group: project
    description: "Search .h/.cpp files. Params: query, directory?"
  project.read_engine_header:
    class_path: project.read_engine_header
    group: project
    description: "Parse a .h file from the engine source tree. Params: headerPath (relative to Engine/Source, or absolute)"
  project.find_engine_symbol:
    class_path: project.find_engine_symbol
    group: project
    description: "Grep engine headers for a symbol. Params: symbol, maxResults?"
  project.list_engine_modules:
    class_path: project.list_engine_modules
    group: project
    description: List modules in Engine/Source/Runtime
  project.search_engine_cpp:
    class_path: project.search_engine_cpp
    group: project
    description: "Search engine .h/.cpp/.inl files across Runtime/Editor/Developer/Plugins. Params: query, tree? (Runtime|Editor|Developer|Plugins|all — default Runtime), subdirectory?, maxResults? (default 500)"
  project.set_config:
    class_path: ue-mcp.bridge
    group: project
    description: "Write to INI. Params: configName, section, key, value"
    options:
      method: set_config
  project.build:
    class_path: ue-mcp.bridge
    group: project
    description: "Build C++ project. Params: configuration?, platform?, clean?"
    options:
      method: build_project
  project.generate_project_files:
    class_path: ue-mcp.bridge
    group: project
    description: Generate IDE project files (Visual Studio, Xcode, etc.)
    options:
      method: generate_project_files
  project.create_cpp_class:
    class_path: ue-mcp.bridge
    group: project
    description: "Create a new native UCLASS in a project module. Uses the same engine template path as File → New C++ Class. Writes .h + .cpp; returns both paths plus needsEditorRestart (true unless Live Coding successfully hot-reloaded). Params: className (no prefix), parentClass? (default UObject; accepts short names like 'Actor' or /Script/<Module>.<Class> paths), moduleName? (default: first project module, use list_project_modules to pick), classDomain? ('public'|'private'|'classes', default public), subPath?"
    options:
      method: create_cpp_class
  project.list_project_modules:
    class_path: ue-mcp.bridge
    group: project
    description: List native modules in the current project (name, host type, source path). Feed moduleName from here into create_cpp_class.
    options:
      method: list_project_modules
  project.live_coding_compile:
    class_path: ue-mcp.bridge
    group: project
    description: "Trigger a Live Coding compile (Windows only). Hot-patches method bodies of existing UCLASSes without editor restart — the fast inner loop for UFUNCTION implementations. Does NOT reliably register brand-new UCLASSes; use build_project + editor restart for those. Params: wait? (default false — fire and return 'in_progress')."
    options:
      method: live_coding_compile
  project.live_coding_status:
    class_path: ue-mcp.bridge
    group: project
    description: Report Live Coding availability/state (available, started, enabledForSession, compiling). Helps choose between live_coding_compile and build_project.
    options:
      method: live_coding_status
  project.write_cpp_file:
    class_path: project.write_cpp_file
    group: project
    description: "Write a .h / .cpp / .inl file under the project's Source/ tree. Used to append UPROPERTYs/UFUNCTIONs or method bodies after create_cpp_class. Writes are scoped to Source/ for safety. Params: path (relative to Source/ or absolute within Source/), content (full file contents). After editing, call live_coding_compile (for existing classes) or build_project (for new classes)."
  project.read_cpp_source:
    class_path: project.read_cpp_source
    group: project
    description: "Read a .cpp file from the project Source/ tree. Companion to read_cpp_header for round-trip edits. Params: sourcePath (relative to Source/ or absolute)."
  project.write_source_file:
    class_path: project.write_source_file
    group: project
    description: "Write a .h/.cpp/.inl into a named module's Public/Private folder (resolves the module dir for you, including plugin modules under Plugins/*/Source/ that write_cpp_file refuses). After a new file, build_project + restart; after a body edit, live_coding_compile. Params: module (module name, default the project's primary module), visibility (Public|Private, default Private), fileName, content."
  project.read_source_file:
    class_path: project.read_source_file
    group: project
    description: "Read a .h/.cpp/.inl from a named module's folder (companion to write_source_file; resolves plugin modules too). With no visibility it tries Public then Private then the module root. Params: module, visibility?, fileName."
  project.add_module_dependency:
    class_path: project.add_module_dependency
    group: project
    description: "Add a module to a target module's Build.cs dependency array. Params: moduleName (the Build.cs to edit — must exist in the project), dependency (module name to add, e.g. 'UMG'), access? ('public'|'private', default 'private'). Creates the corresponding AddRange block if missing. Rebuild required afterward."
  project.add_cpp_member:
    class_path: project.add_cpp_member
    group: project
    description: "Append a UPROPERTY/UFUNCTION declaration to an existing UCLASS header inside the access specifier you choose. Idempotent: if a declaration containing the same memberName is already present, returns existed:true. Params: headerPath (relative to Source/ or absolute), declaration (full multi-line UPROPERTY(...) / UFUNCTION(...) block plus its single-line member or function signature), memberName (the identifier the declaration introduces - used for idempotency), access? ('public'|'protected'|'private', default 'public')."

  # ── asset ──
  asset.list:
    class_path: ue-mcp.bridge
    group: asset
    description: "List assets via the AssetRegistry (sees /Game and every mounted plugin root). Params: directory? (default /Game), classFilter?, recursive? (default true), maxResults? (default 2000)"
    options:
      method: list_assets
  asset.search:
    class_path: asset.search
    group: asset
    description: "Search by name/class/path. Params: query, directory?, maxResults?, searchAll?"
  asset.read:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read asset via reflection. Params: assetPath"
    options:
      method: read_asset
  asset.read_properties:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read asset properties with values. Blueprint paths resolve to the generated-class CDO (#568). propertyName accepts dotted/indexed paths into nested structs, array elements, and instanced subobjects (e.g. `Config.Traits[1].Params.Field`); landing on an array of subobjects also lists each element's index+class (#527). Params: assetPath, propertyName?, includeValues?, valueFormat?"
    options:
      method: read_asset_properties
  asset.list_properties:
    class_path: ue-mcp.bridge
    group: asset
    description: "List reflected properties on any asset. Params: assetPath, includeValues?, valueFormat? ('text'|'json')"
    options:
      method: read_asset_properties
  asset.get_properties:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read property values on any asset. propertyName accepts dotted/indexed paths into nested structs, array elements, and instanced subobjects. valueFormat='json' returns structured values. Params: assetPath, propertyName?, includeValues?, valueFormat?"
    options:
      method: read_asset_properties
  asset.duplicate:
    class_path: ue-mcp.bridge
    group: asset
    description: "Duplicate asset. Params: sourcePath, destinationPath"
    options:
      method: duplicate_asset
  asset.rename:
    class_path: ue-mcp.bridge
    group: asset
    description: "Rename asset. Params: assetPath, newName (or sourcePath, destinationPath), force?. World Partition levels are detected and their __ExternalActors__/__ExternalObjects__ packages migrate atomically alongside the .umap, source-side redirectors get fixed up, and the active editor world is swapped to blank if it matches the source (#409). Refuses if any package is dirty - save first. If a prior rename left externals orphaned at the old path, re-running reconciles them. Rollback descriptor is emitted even on partial failure so the inverse rename can recover. `force=true` lets the call merge into a destination with pre-existing externals (used by rollback). For batches of 3+ scene-referenced non-world assets use bulk_rename instead."
    options:
      method: rename_asset
  asset.bulk_rename:
    class_path: ue-mcp.bridge
    group: asset
    description: "Batched rename using IAssetTools::RenameAssets - single transaction with one redirector-fixup pass (matches Content Browser drag). Use this over looped rename for scene-referenced assets. World assets are rejected (status=rejected_world); use rename_asset which handles WP externals atomically (#409). Params: renames[] where each entry is {sourcePath, destinationPath} OR {assetPath, newName}."
    options:
      method: bulk_rename_assets
  asset.move:
    class_path: ue-mcp.bridge
    group: asset
    description: "Move asset. Params: sourcePath, destinationPath"
    options:
      method: move_asset
  asset.delete:
    class_path: ue-mcp.bridge
    group: asset
    description: "Delete asset. On failure returns reason (open_in_editor / has_referencers / in_memory_referenced / package_read_only / package_dirty / unknown) plus referencers, inMemoryReferencers, packageReadOnly, packageDirty diagnostics (#601). Pass force=true to auto-close any open asset editors before deleting (#278). Params: assetPath, force?"
    options:
      method: delete_asset
  asset.delete_batch:
    class_path: ue-mcp.bridge
    group: asset
    description: "Batch-delete assets. Per-path status (deleted/absent/failed) plus reason+referencers on failed entries (#278). Params: assetPaths[], force?"
    options:
      method: delete_asset_batch
  asset.create_data_asset:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create UDataAsset instance of custom class. Params: name, className (/Script/Module.ClassName or loaded name), packagePath?, properties? (key/value map)"
    options:
      method: create_data_asset
  asset.save:
    class_path: ue-mcp.bridge
    group: asset
    description: "Save asset(s). Params: assetPath?"
    options:
      method: save_asset
  asset.save_all_dirty:
    class_path: ue-mcp.bridge
    group: asset
    description: "Flush every dirty package to disk in one call. End-of-workflow shortcut after bulk import/edit. Params: saveMapPackages? (default true), saveContentPackages? (default true). Returns savedAll boolean (#429)"
    options:
      method: save_all_dirty
  asset.set_mesh_material:
    class_path: ue-mcp.bridge
    group: asset
    description: "Assign material to static mesh slot. Params: assetPath, materialPath, slotIndex?"
    options:
      method: set_mesh_material
  asset.recenter_pivot:
    class_path: ue-mcp.bridge
    group: asset
    description: "Move static mesh pivot to geometry center. Params: assetPath OR assetPaths"
    options:
      method: recenter_pivot
  asset.import_static_mesh:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import from FBX, OBJ, or GLB/glTF (glTF routes through Interchange) (#549). Params: filePath, name?, packagePath?, combineMeshes?, importMaterials?, importTextures?, generateLightmapUVs?"
    options:
      method: import_static_mesh
  asset.import_skeletal_mesh:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import skeletal mesh from FBX. Params: filePath, name?, packagePath?, skeletonPath?, importMaterials?, importTextures?"
    options:
      method: import_skeletal_mesh
  asset.import_animation:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import anim from FBX. Params: filePath, name?, packagePath?, skeletonPath"
    options:
      method: import_animation
  asset.import_texture:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import image. Params: filePath, name?, packagePath?"
    options:
      method: import_texture
  asset.import_texture_batch:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import many textures in one call - the loop stays inside the editor (no per-file bridge round-trip), so this finishes far faster than N import_texture calls. Per-item result records mirror import_texture. Params: items[]: [{filePath, packagePath?, name?, replaceExisting?}], packagePath? (default for items that don't set it), save? (default true), automated? (default true). Returns requested/imported/failed counts + items[] (#430)"
    options:
      method: import_texture_batch
  asset.reimport:
    class_path: ue-mcp.bridge
    group: asset
    description: "Reimport asset from source file. Params: assetPath, filePath?"
    options:
      method: reimport_asset
  asset.read_datatable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read DataTable rows. Params: assetPath, rowFilter?"
    options:
      method: read_datatable
  asset.create_datatable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create DataTable. Params: name, packagePath?, rowStruct"
    options:
      method: create_datatable
  asset.reimport_datatable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Reimport DataTable from JSON. Params: assetPath, jsonPath?, jsonString?"
    options:
      method: reimport_datatable
  asset.set_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Append or overwrite a single DataTable row. Params: assetPath, rowName, row (object with row-struct fields - partial updates merge with the existing row). Idempotent; rollback restores the prior row (#437)"
    options:
      method: set_datatable_row
  asset.add_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Alias for set_datatable_row (#437)"
    options:
      method: add_datatable_row
  asset.update_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Alias for set_datatable_row; partial update merges with existing row (#437)"
    options:
      method: update_datatable_row
  asset.remove_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Remove a single DataTable row. Idempotent (alreadyDeleted=true if missing). Params: assetPath, rowName (#437)"
    options:
      method: remove_datatable_row
  asset.get_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read one DataTable row's fields without dumping the whole table. Params: assetPath, rowName (#535)"
    options:
      method: get_datatable_row
  asset.set_datatable_cell:
    class_path: ue-mcp.bridge
    group: asset
    description: "Write a single field on a single existing row (merges, leaves other cells untouched). Errors if the row doesn't exist. Params: assetPath, rowName, fieldName, value (#535)"
    options:
      method: set_datatable_cell
  asset.rename_datatable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Rename a row key, preserving its values. Params: assetPath, oldName, newName (#535)"
    options:
      method: rename_datatable_row
  asset.fill_datatable_from_json:
    class_path: ue-mcp.bridge
    group: asset
    description: "Bulk-upsert rows from a {rowName: {field: value}} object without touching unrelated rows (non-destructive, unlike reimport_datatable). Params: assetPath, rows (object) or jsonString (#535)"
    options:
      method: fill_datatable_from_json
  asset.create_curvetable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create CurveTable asset. Params: name, packagePath?, onConflict?"
    options:
      method: create_curvetable
  asset.read_curvetable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read CurveTable rows and keys. Params: assetPath, rowFilter?"
    options:
      method: read_curvetable
  asset.list_curvetable_rows:
    class_path: ue-mcp.bridge
    group: asset
    description: "Alias for read_curvetable. Params: assetPath, rowFilter?"
    options:
      method: list_curvetable_rows
  asset.import_curvetable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import CurveTable from JSON/CSV string or file. Params: assetPath, jsonString?, csvString?, filePath?, format?, interpMode?"
    options:
      method: import_curvetable
  asset.add_curvetable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Add CurveTable row. Params: assetPath, rowName, curveType? ('simple'|'rich'), interpMode?"
    options:
      method: add_curvetable_row
  asset.remove_curvetable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Remove CurveTable row. Idempotent if missing. Params: assetPath, rowName"
    options:
      method: remove_curvetable_row
  asset.rename_curvetable_row:
    class_path: ue-mcp.bridge
    group: asset
    description: "Rename CurveTable row. Params: assetPath, oldName, newName"
    options:
      method: rename_curvetable_row
  asset.get_curvetable_keys:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read keys from one CurveTable row. Params: assetPath, rowName"
    options:
      method: get_curvetable_keys
  asset.set_curvetable_keys:
    class_path: ue-mcp.bridge
    group: asset
    description: "Replace keys on one CurveTable row. Params: assetPath, rowName, keys:[{time,value,interpMode?,arriveTangent?,leaveTangent?}]"
    options:
      method: set_curvetable_keys
  asset.add_curvetable_key:
    class_path: ue-mcp.bridge
    group: asset
    description: "Add or update one key on a CurveTable row. Params: assetPath, rowName, time, value, interpMode?, keyTimeTolerance?"
    options:
      method: add_curvetable_key
  asset.list_textures:
    class_path: ue-mcp.bridge
    group: asset
    description: "List textures. Params: directory?, recursive?"
    options:
      method: list_textures
  asset.get_texture_info:
    class_path: ue-mcp.bridge
    group: asset
    description: "Get texture details. Params: assetPath"
    options:
      method: get_texture_info
  asset.set_texture_settings:
    class_path: ue-mcp.bridge
    group: asset
    description: "Set texture settings. Params: assetPath, settings (object with compressionSettings?, lodGroup?, sRGB?, neverStream?). Keys may also be passed at the top level."
    options:
      method: set_texture_settings
  asset.create_stringtable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create a StringTable asset. Params: name, packagePath?, namespace?, onConflict?"
    options:
      method: create_stringtable
  asset.read_stringtable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read StringTable entries and keys. Params: assetPath, keyFilter?"
    options:
      method: read_stringtable
  asset.list_stringtable_keys:
    class_path: ue-mcp.bridge
    group: asset
    description: "List StringTable keys. Params: assetPath, keyFilter?"
    options:
      method: list_stringtable_keys
  asset.get_stringtable_entry:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read one StringTable entry. Params: assetPath, key"
    options:
      method: get_stringtable_entry
  asset.set_stringtable_entry:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create or update one StringTable entry. Params: assetPath, key, sourceString (or value)"
    options:
      method: set_stringtable_entry
  asset.remove_stringtable_entry:
    class_path: ue-mcp.bridge
    group: asset
    description: "Remove one StringTable entry. Idempotent (alreadyDeleted=true if missing). Params: assetPath, key"
    options:
      method: remove_stringtable_entry
  asset.import_stringtable:
    class_path: ue-mcp.bridge
    group: asset
    description: "Import StringTable entries from CSV. Params: assetPath, filePath (or csvPath)"
    options:
      method: import_stringtable
  asset.add_input_mapping:
    class_path: ue-mcp.bridge
    group: asset
    description: "Append an Enhanced Input key mapping to an InputMappingContext (InputAction + key by name string e.g. 'Mouse2D','LeftMouseButton'). Idempotent on (action,key). For modifiers/triggers use gameplay(set_mapping_modifiers). Same as gameplay(add_imc_mapping) (#525). Params: mappingContext (IMC path), inputAction (IA path), key"
    options:
      method: add_imc_mapping
  asset.remove_input_mapping:
    class_path: ue-mcp.bridge
    group: asset
    description: "Remove an IMC key mapping. Same as gameplay(remove_imc_mapping) (#525). Params: mappingContext (IMC path), mappingIndex? | (inputAction? + key?)"
    options:
      method: remove_imc_mapping
  asset.list_input_mappings:
    class_path: ue-mcp.bridge
    group: asset
    description: "List an IMC's key->action bindings with triggers/modifiers. Same as gameplay(read_imc) (#525). Params: mappingContext (IMC path)"
    options:
      method: read_imc
  asset.add_socket:
    class_path: ue-mcp.bridge
    group: asset
    description: "Add socket to StaticMesh or SkeletalMesh. Idempotent on socket name; pass onConflict='update' to overwrite an existing socket's transform with the supplied relativeLocation/relativeRotation/relativeScale (#412). Params: assetPath, socketName, boneName? (SkeletalMesh only, default 'root'), relativeLocation?, relativeRotation?, relativeScale?, onConflict? (skip\\|update\\|error, default skip)"
    options:
      method: add_socket
  asset.remove_socket:
    class_path: ue-mcp.bridge
    group: asset
    description: "Remove socket by name. Params: assetPath, socketName"
    options:
      method: remove_socket
  asset.list_sockets:
    class_path: ue-mcp.bridge
    group: asset
    description: "List sockets on a mesh (StaticMesh or SkeletalMesh). Params: assetPath"
    options:
      method: list_asset_sockets
  asset.set_socket_transform:
    class_path: ue-mcp.bridge
    group: asset
    description: "Update an existing socket's relative transform on StaticMesh or SkeletalMesh. Pass any subset of relativeLocation/relativeRotation/relativeScale; omitted fields stay at their current values. Errors if the socket does not exist (use add_socket to create). Common after FBX import when SOCKET_* empties land with scale=(100,100,100) (#412). Params: assetPath, socketName, relativeLocation?, relativeRotation?, relativeScale?"
    options:
      method: set_socket_transform
  asset.set_property:
    class_path: ue-mcp.bridge
    group: asset
    description: "Set a UPROPERTY on any loaded asset (Material, DataAsset, DataTable, SubsurfaceProfile, etc.) using a dotted path. Blueprint paths resolve to the generated-class CDO so you can author its defaults + Instanced sub-object arrays (#568). Walks nested structs, array elements by index, and instanced subobjects internally - no more read-modify-write copies (e.g. `settings.mean_free_path_distance` on a UMaterial, or `Config.Traits[1].Params.Field` on a config asset #527). Value goes through MCPJsonProperty::SetJsonOnProperty so JSON null clears object refs, structs accept {x,y,z}, arrays/maps round-trip. Params: assetPath, propertyName (dotted path), value (#420)"
    options:
      method: set_asset_property
  asset.set_texture_settings_by_type:
    class_path: ue-mcp.bridge
    group: asset
    description: "Apply the canonical (compressionSettings, sRGB, LOD group) combo to every texture in each group: normal -> Normalmap, grayscale -> Grayscale, baseColor -> Default sRGB, hdr -> HDR. Params: groups (object: {normal?:[paths], grayscale?:[paths], baseColor?:[paths], hdr?:[paths]}) (#421)"
    options:
      method: set_texture_settings_by_type
  asset.create_interchange_pipeline:
    class_path: ue-mcp.bridge
    group: asset
    description: "One-call factory for a UInterchangeGenericAssetsPipeline asset with the 15-property mesh-import boilerplate already applied (RecomputeNormals=false, MikkTSpace=true, HighPrecisionTangents=true, BuildNanite=false, CreatePhysicsAsset=false, etc.). Params: assetPath OR (name + packagePath?), meshType? (skeletal default | static), options? (dotted-path overrides on the resulting pipeline e.g. {'MeshPipeline.bBuildNanite': true}), onConflict? (#421)"
    options:
      method: create_interchange_pipeline
  asset.reload_package:
    class_path: ue-mcp.bridge
    group: asset
    description: "Force reload an asset package from disk. Params: assetPath"
    options:
      method: reload_package
  asset.health_check:
    class_path: ue-mcp.bridge
    group: asset
    description: "Diagnose stuck-unloadable asset. Returns onDisk/inRegistry/isLoaded/canLoad/isStuck flags so an agent can detect the half-shutdown state where load returns null but the file exists (#279). Params: assetPath"
    options:
      method: asset_health_check
  asset.force_reload:
    class_path: ue-mcp.bridge
    group: asset
    description: "Aggressive reload that resets package loaders + GCs + LoadObject. Recovers from the half-shutdown state without an editor restart (#279). Closes any open editors first. Params: assetPath"
    options:
      method: force_reload_asset
  asset.export:
    class_path: ue-mcp.bridge
    group: asset
    description: "Export asset to disk file (Texture2D → PNG, StaticMesh → FBX, etc.). Params: assetPath, outputPath"
    options:
      method: export_asset
  asset.search_fts:
    class_path: ue-mcp.bridge
    group: asset
    description: "Ranked asset search (token-scored over name/class/path). Params: query, maxResults?, classFilter?"
    options:
      method: search_assets_fts
  asset.reindex_fts:
    class_path: ue-mcp.bridge
    group: asset
    description: "Rebuild the SQLite FTS5 asset index. Params: directory?"
    options:
      method: reindex_assets_fts
  asset.get_referencers:
    class_path: ue-mcp.bridge
    group: asset
    description: "Reverse dependency lookup (what references this). Params: packages[] OR packagePath (#150). Returns {referencersByPackage, totalReferencers}."
    options:
      method: get_asset_referencers
  asset.get_dependencies:
    class_path: ue-mcp.bridge
    group: asset
    description: "Forward dependency lookup (what packages this asset references). Params: packages[] OR packagePath, hard? (default true), soft? (default true) (#588). Returns {dependenciesByPackage, totalDependencies}."
    options:
      method: get_asset_dependencies
  asset.list_skeleton_bones:
    class_path: ue-mcp.bridge
    group: asset
    description: "List bones (names + rest-pose local and component-space transforms) from a SkeletalMesh or Skeleton asset, no live actor needed. Params: assetPath, includeTransforms? (default true) (#593). Returns {bones, boneCount, sourceKind}."
    options:
      method: list_skeleton_bones
  asset.get_primary_asset_ids:
    class_path: ue-mcp.bridge
    group: asset
    description: "Enumerate AssetManager-registered FPrimaryAssetIds (verify a primary-asset registration). Params: type? (FPrimaryAssetType; omit for all types), maxResults? (default 1000) (#579). Returns {primaryAssetIds:[{primaryAssetId, type, name, assetPath}], count, total}."
    options:
      method: get_primary_asset_ids
  asset.set_sk_material_slots:
    class_path: ue-mcp.bridge
    group: asset
    description: "Set materials on a USkeletalMesh by slot name or slotIndex (bypasses the blueprint override-materials path that UE's ICH silently reverts). Params: assetPath, slots[{slotName?|slotIndex?, materialPath}]"
    options:
      method: set_sk_material_slots
  asset.diagnose_registry:
    class_path: ue-mcp.bridge
    group: asset
    description: "Scan a content path and compare disk vs AssetRegistry (including in-memory pending-kill entries). Returns onDiskCount, inMemoryIncludedCount, ghostCount and paths. Params: path, recursive? (default true), reconcile? (forceRescan=true)"
    options:
      method: diagnose_registry
  asset.get_mesh_bounds:
    class_path: ue-mcp.bridge
    group: asset
    description: "Get StaticMesh OR SkeletalMesh bounding box. Params: assetPath. Returns min, max, boxExtent, boxCenter, meshKind (#193/#351)"
    options:
      method: get_mesh_bounds
  asset.get_mesh_info:
    class_path: ue-mcp.bridge
    group: asset
    description: "One-call mesh QA: bounds + material slots + skeleton + LOD/vertex counts. Works for both UStaticMesh and USkeletalMesh. Params: assetPath. Returns meshKind, boundsOrigin, boundsExtent, heightM, lodCount, vertexCount, skeletonPath (skeletal only), materialSlots:[{index, slotName, materialPath, isDefaultFallback}], materialCount (#431)"
    options:
      method: get_mesh_info
  asset.read_import_sources:
    class_path: ue-mcp.bridge
    group: asset
    description: "Read AssetImportData source filenames on an imported asset (StaticMesh, SkeletalMesh, Texture, Animation, etc.). Returns sources[] of {relativeFilename, absolutePath, timestamp, fileHash, displayLabelName}. Params: assetPath (#270)"
    options:
      method: read_import_sources
  asset.get_mesh_collision:
    class_path: ue-mcp.bridge
    group: asset
    description: "Inspect StaticMesh collision setup. Params: assetPath. Returns collisionTraceFlag, hasSimple/ComplexCollision, element counts (#177)"
    options:
      method: get_mesh_collision
  asset.move_folder:
    class_path: ue-mcp.bridge
    group: asset
    description: "Move/rename entire content folder with redirector fixup in one transaction. Params: sourcePath, destinationPath (#192)"
    options:
      method: move_folder
  asset.create_folder:
    class_path: ue-mcp.bridge
    group: asset
    description: "Create empty content browser folder(s). Params: path OR paths[] (e.g. /Game/Foo, /Game/Bar/Baz). Returns per-path created/existed/failed (#212)"
    options:
      method: create_folder
  asset.delete_folder:
    class_path: ue-mcp.bridge
    group: asset
    description: "Delete content browser folder(s) - counterpart to delete_asset, which leaves the parent directory entry behind as an orphan. Empty folders only by default; pass force=true to also delete any assets still inside (Content Browser 'Delete folder' equivalent). Per-path status (deleted/absent/failed) with reason (invalid_path/protected_path/not_empty/delete_failed) and a sample of contained assets on not_empty entries. Params: path OR paths[], force?"
    options:
      method: delete_folder
  asset.set_mesh_nav:
    class_path: ue-mcp.bridge
    group: asset
    description: "Set StaticMesh nav contribution. Params: assetPath, bHasNavigationData?, clearNavCollision? (#167)"
    options:
      method: set_mesh_nav

  # ── blueprint ──
  blueprint.read:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Read BP structure incl. SCS components AND inherited native components from the CDO (CharacterMesh0, CharMoveComp, etc.). Params: assetPath, includeComponentProperties? (dump UPROPERTY name/type/value per component template; off by default) (#353/#370)"
    options:
      method: read_blueprint
  blueprint.list_variables:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "List variables. Params: assetPath"
    options:
      method: list_blueprint_variables
  blueprint.list_functions:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "List functions/graphs. Params: assetPath"
    options:
      method: list_blueprint_functions
  blueprint.read_graph:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Read graph nodes. Supports pagination, file dumps, and title/class node filters. Params: assetPath, graphName, offset?, limit?, includePins?, includeDefaults?, includeComments?, dumpToFile?, outputPath?, titleFilter?, classFilter? (#560)"
    options:
      method: read_blueprint_graph
  blueprint.read_graph_summary:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Lightweight graph summary (nodes+edges only, ~10KB). Filterable node list. Params: assetPath, graphName?, titleFilter?, classFilter? (#560)"
    options:
      method: read_blueprint_graph_summary
  blueprint.get_execution_flow:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Trace exec pins from an entry point. Params: assetPath, graphName?, entryPoint?"
    options:
      method: get_blueprint_execution_flow
  blueprint.get_dependencies:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Forward (classes/functions/assets) or reverse (referencers) deps. Params: assetPath, reverse?"
    options:
      method: get_blueprint_dependencies
  blueprint.create:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Create Blueprint. Params: assetPath, parentClass?"
    options:
      method: create_blueprint
  blueprint.add_variable:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add variable. Params: assetPath, name, varType"
    options:
      method: add_variable
  blueprint.set_variable_properties:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Edit variable properties. Params: assetPath, name, instanceEditable?, blueprintReadOnly?, category?, tooltip?, replicationType?, exposeOnSpawn?"
    options:
      method: set_variable_properties
  blueprint.create_function:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Create function. Params: assetPath, functionName"
    options:
      method: create_function
  blueprint.delete_function:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Delete function. Params: assetPath, functionName"
    options:
      method: delete_function
  blueprint.rename_function:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Rename function. Params: assetPath, oldName, newName"
    options:
      method: rename_function
  blueprint.add_node:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add graph node. For a CallFunction node bound to a custom C++ UFUNCTION, pass nodeParams {functionName, className (or targetClass) = /Script/Module.Class}; the function also resolves against the BP's own component classes and an unambiguous loaded BlueprintCallable function, producing a bound node with pins instead of a stub (#546). Params: assetPath, graphName?, nodeClass, nodeParams?"
    options:
      method: add_node
  blueprint.delete_node:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Delete node. Params: assetPath, graphName, nodeName"
    options:
      method: delete_node
  blueprint.set_node_property:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set node pin default or struct property. Params: assetPath, graphName, nodeName, propertyName, value"
    options:
      method: set_node_property
  blueprint.connect_pins:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Wire nodes. Params: sourceNode, sourcePin, targetNode, targetPin, assetPath, graphName?"
    options:
      method: connect_pins
  blueprint.add_component:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add BP component. componentClass accepts short names (e.g. 'ChildActorComponent') or full paths. For a ChildActorComponent, pass childActorClass to set its ChildActorClass in the same call (a Blueprint path with or without _C, or a C++ class) (#526). Params: assetPath, componentClass, componentName?, parentComponent? (SCS parent for hierarchy — #115), childActorClass?"
    options:
      method: add_component
  blueprint.remove_component:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Remove SCS component. Params: assetPath, componentName"
    options:
      method: remove_component
  blueprint.set_component_property:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set property on SCS or inherited component. Inherited components go through the child BP's InheritableComponentHandler override template so the parent stays untouched. Pass value=null to clear a TObjectPtr/SoftObject/WeakObject/UClass/Interface reference (e.g. clear AnimClass on CharacterMesh0) (#420). Params: assetPath, componentName, propertyName, value"
    options:
      method: set_blueprint_component_property
  blueprint.set_component_override_materials:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Write OverrideMaterials on a mesh-component template (StaticMeshComponent / SkeletalMeshComponent / any UMeshComponent). Pass materialPaths as a string[] of material asset paths (empty array clears). Avoids any TArray<UObject*> coercion on the generic set_component_property path (#442). Params: assetPath, componentName, materialPaths"
    options:
      method: set_component_override_materials
  blueprint.add_timeline_track:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add a track to a Blueprint timeline. Creates the UTimelineTemplate if missing, builds the matching curve asset (float/vector/color/event), applies keyframes, bumps TimelineLength to cover the last key, then recompiles so K2Node_Timeline regenerates its output pins. Params: assetPath, timelineName, trackName, trackType ('float'|'vector'|'color'|'event'), keyframes ([{time, value}]). value is a number for float/event, {x,y,z} for vector, {r,g,b,a} for color (#457)"
    options:
      method: add_timeline_track
  blueprint.set_capsule_size:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Call UCapsuleComponent::SetCapsuleSize on a CapsuleComponent template (CharacterMovement-friendly path; raw property writes leave the visualizer stale). Pass either or both of halfHeight/radius. Returns the new + previous values. Params: assetPath, componentName, halfHeight?, radius? (#419)"
    options:
      method: set_capsule_size
  blueprint.get_component_property:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Read a single property value from an SCS or inherited component template. Returns the ICH override value for child BPs if one exists. Params: assetPath, componentName, propertyName"
    options:
      method: get_blueprint_component_property
  blueprint.set_class_default:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set UPROPERTY on Blueprint CDO. Pass value=null to clear an object/class/interface reference (#420). Params: assetPath, propertyName, value"
    options:
      method: set_class_default
  blueprint.delete_variable:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Delete a member variable. Params: assetPath, name"
    options:
      method: delete_variable
  blueprint.add_function_parameter:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add input or output parameter to a function. Params: assetPath, functionName, parameterName, parameterType?, isOutput?"
    options:
      method: add_function_parameter
  blueprint.set_variable_default:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set default value on a BP variable. Params: assetPath, name, value"
    options:
      method: set_variable_default
  blueprint.compile:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Compile Blueprint. Params: assetPath"
    options:
      method: compile_blueprint
  blueprint.list_node_types:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "List node types. Params: category?, includeFunctions?"
    options:
      method: list_node_types
  blueprint.search_node_types:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Search nodes. Params: query"
    options:
      method: search_node_types
  blueprint.create_interface:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Create BP Interface. Params: assetPath"
    options:
      method: create_blueprint_interface
  blueprint.add_interface:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Implement interface. Params: blueprintPath, interfacePath"
    options:
      method: add_blueprint_interface
  blueprint.list_graphs:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "List all graphs in a blueprint. Params: assetPath"
    options:
      method: list_blueprint_graphs
  blueprint.add_event_dispatcher:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add event dispatcher (multicast delegate variable + signature graph + UFunction). Without parameters, broadcasters fire void(). With parameters, the signature graph gets typed user pins so K2Node_CallDelegate compiles cleanly (#276). Params: blueprintPath, name, parameters?: [{name, type}] where type is bool/int/float/string/name/text/vector/rotator/transform/object:/Script/Module.Class/struct:/Script/Module.Struct"
    options:
      method: add_event_dispatcher
  blueprint.duplicate:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Duplicate blueprint asset. Params: sourcePath, destinationPath"
    options:
      method: duplicate_blueprint
  blueprint.add_local_variable:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Add function-scope local variable. Params: assetPath, functionName, name, varType?"
    options:
      method: add_local_variable
  blueprint.list_local_variables:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "List local variables in a function. Params: assetPath, functionName"
    options:
      method: list_local_variables
  blueprint.validate:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Validate blueprint without saving (compile + collect diagnostics). Params: assetPath"
    options:
      method: validate_blueprint
  blueprint.read_component_properties:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Dump ALL UPROPERTYs on a BP component template incl. array contents (#105). Params: assetPath, componentName"
    options:
      method: read_component_properties
  blueprint.read_node_property:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Read a node pin default OR a reflected node property for verification (#102). Params: assetPath, graphName?, nodeName, propertyName"
    options:
      method: read_node_property
  blueprint.reparent_component:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Reparent an SCS component under a new parent (#115). Params: assetPath, componentName, newParent"
    options:
      method: reparent_component
  blueprint.reparent:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Change a Blueprint's ParentClass and recompile (#138). Params: assetPath, parentClass (short name or full path)."
    options:
      method: reparent_blueprint
  blueprint.flush_ich:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Flush orphaned InheritableComponentHandler override records (invalid component-override entries invisible to read/remove_component). Recompiles + saves. Params: assetPath. Returns recordsBefore/After/Removed (#580)"
    options:
      method: flush_inheritable_component_handler
  blueprint.set_actor_tick_settings:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set actor CDO tick settings (#116). Params: assetPath, bCanEverTick?, bStartWithTickEnabled?, TickInterval?"
    options:
      method: set_actor_tick_settings
  blueprint.export_nodes_t3d:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Export graph nodes as T3D text (Ctrl+C equivalent) for bulk round-trip (#130). Params: assetPath, graphName?, nodeIds? (omit = whole graph)"
    options:
      method: export_nodes_t3d
  blueprint.import_nodes_t3d:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Paste a T3D node blob into a graph (Ctrl+V equivalent) for bulk authoring (#130). Params: assetPath, graphName?, t3d, posX?, posY?"
    options:
      method: import_nodes_t3d
  blueprint.set_cdo_property:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Set UPROPERTY on any C++ class CDO (not just Blueprints). Params: className, propertyName, value (#182/#183)"
    options:
      method: set_cdo_property
  blueprint.get_cdo_properties:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Read UPROPERTY values from any C++ class CDO. Params: className, propertyNames? (#183)"
    options:
      method: get_cdo_properties
  blueprint.run_construction_script:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Spawn temp actor, run construction script, return generated components and transforms. Params: assetPath, location? (#195)"
    options:
      method: run_construction_script
  blueprint.compile_all:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Batch compile + save Blueprints. Params: assetPaths[], save? (default true). Returns per-path status (compiled/failed/not_found) (#284)"
    options:
      method: compile_blueprints
  blueprint.cleanup_graph:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Remove orphan/corrupted nodes (no class, blank title+no pins, missing target UFunction). Params: assetPath, graphName? (default: every graph) (#285)"
    options:
      method: cleanup_graph
  blueprint.connect_pins_batch:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Apply many pin connections in one call (single compile + save). Params: assetPath, graphName?, connections[]: [{sourceNode, sourcePin, targetNode, targetPin}] (#267)"
    options:
      method: connect_pins_batch
  blueprint.set_node_position:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Move a graph node to (posX, posY). Params: assetPath, graphName?, nodeId, posX, posY (#277)"
    options:
      method: set_node_position
  blueprint.auto_layout:
    class_path: ue-mcp.bridge
    group: blueprint
    description: "Topological layered layout for a graph. Eliminates the (0,0) stack from programmatic add_node. Params: assetPath, graphName?, columnGap? (default 360), rowGap? (default 200) (#277)"
    options:
      method: auto_layout_graph

  # ── level ──
  level.get_outliner:
    class_path: ue-mcp.bridge
    group: level
    description: "List actors. Params: classFilter?, nameFilter?, world? (editor|pie|auto), limit?"
    options:
      method: get_world_outliner
  level.place_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Spawn actor. Pass world:pie to spawn into the running PIE world (#585). Params: actorClass, label?, location?, rotation?, scale?, staticMesh?, material?, world? (editor|pie)"
    options:
      method: place_actor
  level.delete_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Remove actor. Params: actorLabel"
    options:
      method: delete_actor
  level.get_actor_details:
    class_path: ue-mcp.bridge
    group: level
    description: "Inspect actor. Params: actorLabel OR actorPath, includeProperties?, propertyName?, world? (editor|pie)"
    options:
      method: get_actor_details
  level.move_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Transform actor. Pass world:pie to move a live PIE actor (resolves labels/names from get_outliner {world:pie}) (#586). Params: actorLabel, location?, rotation?, scale?, world? (editor|pie)"
    options:
      method: move_actor
  level.aim_actor_at:
    class_path: ue-mcp.bridge
    group: level
    description: "Rotate an actor so its forward (+X) points at a target. Params: actorLabel, targetPoint (Vec3) OR targetActor (label), roll? (default 0), world? (editor|pie) (#566)"
    options:
      method: aim_actor_at
  level.nav_project_point:
    class_path: ue-mcp.bridge
    group: level
    description: "Project a world point onto the navmesh. Returns onNavMesh + projectedLocation. Params: point (Vec3), extent? (Vec3, default 100), world? (editor|pie) (#585)"
    options:
      method: nav_project_point
  level.select:
    class_path: ue-mcp.bridge
    group: level
    description: "Select actors. Params: actorLabels[]"
    options:
      method: select_actors
  level.get_selected:
    class_path: ue-mcp.bridge
    group: level
    description: Get selection
    options:
      method: get_selected_actors
  level.add_component:
    class_path: ue-mcp.bridge
    group: level
    description: "Add component to actor. Params: actorLabel, componentClass, componentName?"
    options:
      method: add_component_to_actor
  level.remove_component:
    class_path: ue-mcp.bridge
    group: level
    description: "Remove instance component from a level actor by name. Idempotent: returns alreadyDeleted=true if no matching component exists. Params: actorLabel, componentName (#426)"
    options:
      method: remove_component_from_actor
  level.set_component_property:
    class_path: ue-mcp.bridge
    group: level
    description: "Set component prop. Pass value=null to clear a TObjectPtr/SoftObject/WeakObject/UClass/Interface reference (#420). Resolves inherited/SCS components on placed Blueprint instances case-insensitively, and refreshes the scene transform after RelativeLocation/RelativeRotation/RelativeScale3D writes (#539). Params: actorLabel, componentName, propertyName, value"
    options:
      method: set_component_property
  level.get_component_details:
    class_path: ue-mcp.bridge
    group: level
    description: "Read a placed actor's component transforms. With componentName returns that component's relative+world location/rotation/scale, class, and attach parent; without it lists every component with its transform. Resolves SCS components on Blueprint instances (#539). Params: actorLabel, componentName?"
    options:
      method: get_component_details
  level.get_current:
    class_path: ue-mcp.bridge
    group: level
    description: Get current level name and path
    options:
      method: get_current_level
  level.load:
    class_path: ue-mcp.bridge
    group: level
    description: "Load level. Params: levelPath"
    options:
      method: load_level
  level.save:
    class_path: ue-mcp.bridge
    group: level
    description: Save current level
    options:
      method: save_current_level
  level.list:
    class_path: ue-mcp.bridge
    group: level
    description: "List levels. Params: directory?, recursive?"
    options:
      method: list_levels
  level.create:
    class_path: ue-mcp.bridge
    group: level
    description: "Create new level. Params: levelPath?, templateLevel?"
    options:
      method: create_new_level
  level.spawn_volume:
    class_path: ue-mcp.bridge
    group: level
    description: "Place volume. Params: volumeType, location?, extent?, label?"
    options:
      method: spawn_volume
  level.list_volumes:
    class_path: ue-mcp.bridge
    group: level
    description: "List volumes. Params: volumeType?"
    options:
      method: list_volumes
  level.set_volume_properties:
    class_path: ue-mcp.bridge
    group: level
    description: "Edit volume. Params: actorLabel, properties"
    options:
      method: set_volume_properties
  level.spawn_light:
    class_path: ue-mcp.bridge
    group: level
    description: "Place light. Params: lightType (point|spot|directional|rect|sky), location?, rotation?, intensity?, color? ({r,g,b} 0-255), mobility? (static|stationary|movable; default movable so the light renders without a build), label? (#331/#310)"
    options:
      method: spawn_light
  level.set_light_properties:
    class_path: ue-mcp.bridge
    group: level
    description: "Edit light. Params: actorLabel, intensity?, color?, rotation? (DirectionalLight sun angle), mobility? (static|stationary|movable), recaptureSky?, temperature?, castShadows?, attenuationRadius?"
    options:
      method: set_light_properties
  level.set_fog_properties:
    class_path: ue-mcp.bridge
    group: level
    description: "Edit ExponentialHeightFog. Params: actorLabel?, fogDensity?, fogHeightFalloff?, startDistance?, fogInscatteringColor?"
    options:
      method: set_fog_properties
  level.get_actors_by_class:
    class_path: ue-mcp.bridge
    group: level
    description: "List actors by class name. Params: className, world? (editor|pie)"
    options:
      method: get_actors_by_class
  level.get_actors_by_component_class:
    class_path: ue-mcp.bridge
    group: level
    description: "List actors that own a component of a given class (exact or substring match). Returns each actor plus its matchedComponents. Params: componentClass, world? (editor|pie) (#582)"
    options:
      method: get_actors_by_component_class
  level.count_actors_by_class:
    class_path: ue-mcp.bridge
    group: level
    description: "Histogram of actor classes in the level (sorted desc). Params: world? (editor|pie), topN? (#146)"
    options:
      method: count_actors_by_class
  level.get_runtime_virtual_texture_summary:
    class_path: ue-mcp.bridge
    group: level
    description: "List RuntimeVirtualTextureVolume actors + their bound VirtualTexture assets (#150)"
    options:
      method: get_runtime_virtual_texture_summary
  level.set_water_body_property:
    class_path: ue-mcp.bridge
    group: level
    description: "Set a property on an actor's WaterBodyComponent (ShapeDilation, WaterLevel, etc.). Params: actorLabel, propertyName, value. Requires Water plugin. For spline edits use level(set_spline_points) (#151)"
    options:
      method: set_water_body_property
  level.build_lighting:
    class_path: ue-mcp.bridge
    group: level
    description: "Build lights. Params: quality?"
    options:
      method: build_lighting
  level.get_spline_info:
    class_path: ue-mcp.bridge
    group: level
    description: "Read a spline component's points, closedLoop, length, and per-point tangents/types. Works in editor or PIE (#553). Optional componentName picks a specific (custom) spline; projectPoint (Vec3) returns the closest location, inputKey, distanceAlongSpline, distanceToSpline, and tangent (#555). Params: actorLabel, componentName?, world? (editor|pie), projectPoint?"
    options:
      method: get_spline_info
  level.set_spline_points:
    class_path: ue-mcp.bridge
    group: level
    description: "Set spline points. Params: actorLabel, points[], closedLoop?"
    options:
      method: set_spline_points
  level.set_actor_material:
    class_path: ue-mcp.bridge
    group: level
    description: "Set material on actor. Params: actorLabel, materialPath, slotIndex?"
    options:
      method: set_actor_material
  level.get_world_settings:
    class_path: ue-mcp.bridge
    group: level
    description: Read world settings (GameMode, KillZ, gravity, etc.)
    options:
      method: get_world_settings
  level.set_world_settings:
    class_path: ue-mcp.bridge
    group: level
    description: "Set world settings. Params: defaultGameMode?, killZ?, globalGravityZ?, enableWorldBoundsChecks?"
    options:
      method: set_world_settings
  level.get_actor_bounds:
    class_path: ue-mcp.bridge
    group: level
    description: "Get actor AABB. Params: actorLabel. Returns origin + extent (#188)"
    options:
      method: get_actor_bounds
  level.get_component_tree:
    class_path: ue-mcp.bridge
    group: level
    description: "Deep component-tree dump for an actor. Returns per-component: name, class, attachParent, attachSocket, mobility, visibility, relative+world transforms, tags. For PrimitiveComponents adds collisionProfile/collisionEnabled/bounds/castShadow. For StaticMeshComponent adds staticMesh + materials[]. For SkeletalMeshComponent adds skeletalMesh + skeleton + materials[]. For NiagaraComponent adds niagara{asset,active,visible} and for AudioComponent audio{sound,playing} - runtime FX state in PIE (#581). Params: actorLabel | actorPath, world? (editor|pie), componentClass? (substring filter), includeProperties? (dump UPROPERTY name/type/value per component) (#240/#241/#302/#320/#370/#353/#581)"
    options:
      method: get_component_tree
  level.get_relative_transform:
    class_path: ue-mcp.bridge
    group: level
    description: "Compute target's transform in reference's local space (location/rotation/scale). Common dungeon/calibration workflow. Params: target (actor label), reference (actor label), world? (#386/#387)"
    options:
      method: get_relative_transform
  level.resolve_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Resolve internal/runtime actor name to editor label. Params: internalName (e.g. StaticMeshActor_141). Returns actorLabel, actorPath, className, location (#178)"
    options:
      method: resolve_actor
  level.set_actor_property:
    class_path: ue-mcp.bridge
    group: level
    description: "Set per-instance UPROPERTY on a level actor. Params: actorLabel ('WorldSettings' targets the world settings actor), propertyName (dotted paths like 'Foo.Bar' supported), value (string/number/bool/object/array; a label string resolves to an AActor* ref, and a JSON array of labels populates a TArray of actor refs #538), force? (bypass EditDefaultsOnly), world? (editor|pie) (#202/#230)"
    options:
      method: set_actor_property
  level.read_actor_motion:
    class_path: ue-mcp.bridge
    group: level
    description: "Snapshot motion telemetry for one or many actors: location, rotation, velocity, scale, angularVelocity (when simulating physics), grounded + distanceToGround (downward 200u trace). Defaults to the PIE world with editor fallback. Loop at your sample interval for long telemetry probes. Params: actorLabel? OR actorLabels (string[]), world? ('pie'|'editor') (#453)"
    options:
      method: read_actor_motion
  level.add_hismc_instances:
    class_path: ue-mcp.bridge
    group: level
    description: "Bulk-add transforms to a HISMC / ISMC component on an actor (Python add_instance crashes on UE 5.7; this is the C++ path). Params: actorLabel, componentName? (default: first ISMC/HISMC found), transforms ([{location: {x,y,z}, rotation?: {pitch,yaw,roll}, scale?: {x,y,z}}]), worldSpace? (default true) (#434)"
    options:
      method: add_hismc_instances
  level.delete_actors:
    class_path: ue-mcp.bridge
    group: level
    description: "Bulk-delete actors. Params: at least one of labelPrefix, className, tag; dryRun? to preview. Returns matched/deleted/labels (#220)"
    options:
      method: delete_actors
  level.add_actor_tag:
    class_path: ue-mcp.bridge
    group: level
    description: "Append a tag to an actor's Tags array. Params: actorLabel, tag (#219)"
    options:
      method: add_actor_tag
  level.remove_actor_tag:
    class_path: ue-mcp.bridge
    group: level
    description: "Remove a tag from an actor's Tags array. Params: actorLabel, tag (#219)"
    options:
      method: remove_actor_tag
  level.set_actor_tags:
    class_path: ue-mcp.bridge
    group: level
    description: "Replace an actor's Tags array. Params: actorLabel, tags[] (#219)"
    options:
      method: set_actor_tags
  level.list_actor_tags:
    class_path: ue-mcp.bridge
    group: level
    description: "List an actor's Tags. Params: actorLabel (#219)"
    options:
      method: list_actor_tags
  level.attach_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Attach actor as child. Params: childLabel, parentLabel, attachRule? (KeepWorld|KeepRelative|SnapToTarget; default KeepWorld), socketName? (#205)"
    options:
      method: attach_actor
  level.detach_actor:
    class_path: ue-mcp.bridge
    group: level
    description: "Detach actor from parent. Params: childLabel (#205)"
    options:
      method: detach_actor
  level.set_actor_mobility:
    class_path: ue-mcp.bridge
    group: level
    description: "Set actor root component Mobility. Params: actorLabel, mobility (static|stationary|movable) (#205)"
    options:
      method: set_actor_mobility
  level.get_current_edit_level:
    class_path: ue-mcp.bridge
    group: level
    description: "Read the active edit-target sub-level (#204)"
    options:
      method: get_current_edit_level
  level.set_current_edit_level:
    class_path: ue-mcp.bridge
    group: level
    description: "Set the active edit-target sub-level so subsequent spawns land in it. Params: levelName (e.g. SubLevel_A) (#204)"
    options:
      method: set_current_edit_level
  level.list_streaming_sublevels:
    class_path: ue-mcp.bridge
    group: level
    description: "List streaming sub-levels with transform + initially-loaded/visible flags (#206)"
    options:
      method: list_streaming_sublevels
  level.add_streaming_sublevel:
    class_path: ue-mcp.bridge
    group: level
    description: "Add a streaming sub-level. Params: levelPath, streamingClass? (LevelStreamingDynamic|LevelStreamingAlwaysLoaded), location?, initiallyLoaded?, initiallyVisible? (#206)"
    options:
      method: add_streaming_sublevel
  level.remove_streaming_sublevel:
    class_path: ue-mcp.bridge
    group: level
    description: "Remove a streaming sub-level. Params: levelName | levelPath (#206)"
    options:
      method: remove_streaming_sublevel
  level.set_streaming_sublevel_properties:
    class_path: ue-mcp.bridge
    group: level
    description: "Update sub-level transform/visibility flags. Params: levelName | levelPath, location?, initiallyLoaded?, initiallyVisible?, editorVisible? (#206)"
    options:
      method: set_streaming_sublevel_properties
  level.spawn_grid:
    class_path: ue-mcp.bridge
    group: level
    description: "Batch-spawn StaticMeshActors on a grid. Params: staticMesh, min, max (Vec3 bounds), countX?, countY?, countZ?, jitter?, labelPrefix? (#203)"
    options:
      method: spawn_grid
  level.batch_translate:
    class_path: ue-mcp.bridge
    group: level
    description: "Translate a set of actors by an offset. Params: offset (Vec3), actorLabels[] OR tag (#203)"
    options:
      method: batch_translate
  level.place_actors_batch:
    class_path: ue-mcp.bridge
    group: level
    description: "Bulk-spawn StaticMeshActors with per-instance mesh + transform. Params: actors[]: [{staticMesh, location?, rotation?, scale?, label?}]. Mesh loads cached per path. Returns spawned/failedMesh/failedSpawn counts + labels (#264)"
    options:
      method: place_actors_batch
  level.line_trace:
    class_path: ue-mcp.bridge
    group: level
    description: "Line trace in the editor world. Returns hit + actorLabel/actorClass/componentName/componentClass/location/impactPoint/normal/distance/faceIndex/boneName/physicalMaterial. Params: start (Vec3), end? (Vec3) OR direction? (Vec3) + distance? (default 200000), ignoreActors? (array of labels) (#420)"
    options:
      method: line_trace
  level.snap_actor_to_floor:
    class_path: ue-mcp.bridge
    group: level
    description: "Snap an actor's bounds-bottom to the first downward line-trace hit. Equivalent of the End-key shortcut, works on arbitrary geometry (not just Landscape). Params: actorLabel, floorOffset? (added to impact Z, default 0), maxDistance? (default 100000) (#419)"
    options:
      method: snap_actor_to_floor

  # ── material ──
  material.read:
    class_path: ue-mcp.bridge
    group: material
    description: "Read material structure. Params: assetPath"
    options:
      method: read_material
  material.list_parameters:
    class_path: ue-mcp.bridge
    group: material
    description: "List overridable parameters. Params: assetPath"
    options:
      method: list_material_parameters
  material.set_parameter:
    class_path: ue-mcp.bridge
    group: material
    description: "Set parameter on MaterialInstance. Params: assetPath, parameterName, parameterType, value"
    options:
      method: set_material_parameter
  material.read_instance:
    class_path: ue-mcp.bridge
    group: material
    description: "Read a MaterialInstanceConstant parent and override summary. Params: assetPath"
    options:
      method: read_material_instance
  material.set_instance_parent:
    class_path: ue-mcp.bridge
    group: material
    description: "Set a MaterialInstanceConstant parent. Params: assetPath, newParentPath (or parentPath)"
    options:
      method: set_material_instance_parent
  material.batch_set_instances:
    class_path: ue-mcp.bridge
    group: material
    description: "Batch reparent + reassign parameters across many Material Instances in one call. Params: instances[] = [{assetPath, parentPath?, parameters?:[{name, type (scalar|vector|texture), value}]}]. value: number (scalar), {r,g,b,a} (vector), or texture path (texture). Returns per-instance results (#594)"
    options:
      method: batch_set_material_instances
  material.clear_instance_parameters:
    class_path: ue-mcp.bridge
    group: material
    description: "Clear all MaterialInstanceConstant parameter overrides. Params: assetPath"
    options:
      method: clear_material_instance_parameters
  material.list_static_switches:
    class_path: ue-mcp.bridge
    group: material
    description: "List static switch parameters on a Material or MaterialInstance. Params: assetPath"
    options:
      method: list_material_static_switches
  material.set_static_switch:
    class_path: ue-mcp.bridge
    group: material
    description: "Set a MaterialInstanceConstant static switch parameter. Params: assetPath, parameterName, value, association?, parameterIndex?"
    options:
      method: set_material_static_switch
  material.set_expression_value:
    class_path: ue-mcp.bridge
    group: material
    description: "Set value on expression node. Params: materialPath, expressionIndex, value"
    options:
      method: set_expression_value
  material.set_custom_expression:
    class_path: ue-mcp.bridge
    group: material
    description: "Read/write a MaterialExpressionCustom (HLSL) node: code, named inputs[] (rebuilds input pins; wire them with connect_expressions targetInput=<name>), outputType (float1|float2|float3|float4|materialAttributes), description. Omit code/inputs to read. Add the node first via add_expression expressionType=Custom. Params: materialPath, expressionIndex, code?, inputs?, outputType?, description? (#617)"
    options:
      method: set_custom_expression
  material.disconnect_property:
    class_path: ue-mcp.bridge
    group: material
    description: "Disconnect a material property input. Params: materialPath, property"
    options:
      method: disconnect_material_property
  material.create_instance:
    class_path: ue-mcp.bridge
    group: material
    description: "Create material instance. Params: parentPath, name?, packagePath?"
    options:
      method: create_material_instance
  material.create:
    class_path: ue-mcp.bridge
    group: material
    description: "Create material. Params: name, packagePath?"
    options:
      method: create_material
  material.create_function:
    class_path: ue-mcp.bridge
    group: material
    description: "Create a MaterialFunction asset. Params: name, packagePath? (default /Game/Materials/Functions), description? (#463)"
    options:
      method: create_material_function
  material.add_function_expression:
    class_path: ue-mcp.bridge
    group: material
    description: "Add an expression node to a MaterialFunction graph. Params: functionPath, expressionType (e.g. Constant3Vector, FunctionInput, FunctionOutput, If), positionX?, positionY?, inputName? (for FunctionInput), inputType? (Scalar|Vector2|Vector3|Vector4|Texture2D|TextureCube|StaticBool|MaterialAttributes), outputName? (for FunctionOutput) (#463)"
    options:
      method: add_expression_in_function
  material.connect_function_expressions:
    class_path: ue-mcp.bridge
    group: material
    description: "Wire two expressions inside a MaterialFunction. Params: functionPath, sourceExpression (name or index), sourceOutput?, targetExpression (name or index), targetInput? (#463)"
    options:
      method: connect_expressions_in_function
  material.list_function_expressions:
    class_path: ue-mcp.bridge
    group: material
    description: "List expression nodes inside a MaterialFunction. Params: functionPath (#463)"
    options:
      method: list_expressions_in_function
  material.create_simple:
    class_path: ue-mcp.bridge
    group: material
    description: "Single-call simple material. Params: name, packagePath?, baseColor? ({r,g,b}), metallic?, specular?, roughness?, emissive?, usages?[] (e.g. InstancedStaticMeshes, Nanite, NiagaraSprites). Recompiles + saves in one shot (#225)"
    options:
      method: create_material_simple
  material.set_usage:
    class_path: ue-mcp.bridge
    group: material
    description: "Set EMaterialUsage flag(s) on a material. Params: assetPath, usage OR usages[], enabled? (default true). Recompiles + saves (#225)"
    options:
      method: set_material_usage
  material.set_shading_model:
    class_path: ue-mcp.bridge
    group: material
    description: "Set shading model. Params: assetPath, shadingModel"
    options:
      method: set_material_shading_model
  material.set_blend_mode:
    class_path: ue-mcp.bridge
    group: material
    description: "Set blend mode. Params: assetPath, blendMode"
    options:
      method: set_material_blend_mode
  material.set_domain:
    class_path: ue-mcp.bridge
    group: material
    description: "Set material domain. Params: assetPath, materialDomain (Surface | DeferredDecal | LightFunction | Volume | PostProcess | UI | RuntimeVirtualTexture). Required for post-process / decal / UI authoring (#299/#356)."
    options:
      method: set_material_domain
  material.set_base_color:
    class_path: ue-mcp.bridge
    group: material
    description: "Set base color. Params: assetPath, color"
    options:
      method: set_material_base_color
  material.connect_texture:
    class_path: ue-mcp.bridge
    group: material
    description: "Connect texture to property. Params: materialPath, texturePath, property"
    options:
      method: connect_texture_to_material
  material.add_expression:
    class_path: ue-mcp.bridge
    group: material
    description: "Add expression node. Params: materialPath, expressionType, name?, parameterName?, group?, sortPriority?, defaultValue? (scalar number or {r,g,b,a} for vector params), value? (number for Constant, {r,g,b} for Constant3Vector, {x,y} for Constant2Vector), channels? ({r,g,b,a} bools for ComponentMask), positionX?, positionY? (#318)"
    options:
      method: add_material_expression
  material.connect_expressions:
    class_path: ue-mcp.bridge
    group: material
    description: "Wire two expressions. Params: materialPath, sourceExpression, sourceOutput?, targetExpression, targetInput?"
    options:
      method: connect_material_expressions
  material.connect_to_property:
    class_path: ue-mcp.bridge
    group: material
    description: "Wire expression to material output. Params: materialPath, expressionName, outputName?, property"
    options:
      method: connect_to_material_property
  material.list_expressions:
    class_path: ue-mcp.bridge
    group: material
    description: "List expression nodes. Params: materialPath"
    options:
      method: list_material_expressions
  material.delete_expression:
    class_path: ue-mcp.bridge
    group: material
    description: "Remove expression. Params: materialPath, expressionName"
    options:
      method: delete_material_expression
  material.list_expression_types:
    class_path: ue-mcp.bridge
    group: material
    description: List available expression types
    options:
      method: list_expression_types
  material.recompile:
    class_path: ue-mcp.bridge
    group: material
    description: "Recompile material. Pass recompileChildren=true to cascade to every MaterialInstanceConstant whose parent chain reaches this material (#421). Params: materialPath, recompileChildren?"
    options:
      method: recompile_material
  material.duplicate:
    class_path: ue-mcp.bridge
    group: material
    description: "Duplicate material asset. Params: sourcePath, destinationPath"
    options:
      method: duplicate_material
  material.validate:
    class_path: ue-mcp.bridge
    group: material
    description: "Validate material graph — find orphans, broken refs. Params: assetPath"
    options:
      method: validate_material
  material.get_shader_stats:
    class_path: ue-mcp.bridge
    group: material
    description: "Shader compile stats, sampler+param counts. Params: assetPath"
    options:
      method: get_material_shader_stats
  material.export_graph:
    class_path: ue-mcp.bridge
    group: material
    description: "Export material graph as JSON. Params: assetPath"
    options:
      method: export_material_graph
  material.import_graph:
    class_path: ue-mcp.bridge
    group: material
    description: "Rebuild graph from JSON. Params: assetPath, nodes, propertyConnections?"
    options:
      method: import_material_graph
  material.build_graph:
    class_path: ue-mcp.bridge
    group: material
    description: "Build graph from spec. Params: assetPath, nodes, propertyConnections?"
    options:
      method: build_material_graph
  material.render_preview:
    class_path: ue-mcp.bridge
    group: material
    description: "Render preview PNG. Params: assetPath, outputPath, width?, height?"
    options:
      method: render_material_preview
  material.begin_transaction:
    class_path: ue-mcp.bridge
    group: material
    description: "Begin undo transaction. Params: label?"
    options:
      method: begin_material_transaction
  material.end_transaction:
    class_path: ue-mcp.bridge
    group: material
    description: End undo transaction
    options:
      method: end_material_transaction

  # ── animation ──
  animation.read_anim_blueprint:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read AnimBP structure. Params: assetPath"
    options:
      method: read_anim_blueprint
  animation.read_montage:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read montage. Params: assetPath"
    options:
      method: read_anim_montage
  animation.read_sequence:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read anim sequence. Params: assetPath"
    options:
      method: read_anim_sequence
  animation.scan_animation_tracks:
    class_path: ue-mcp.bridge
    group: animation
    description: "Scan AnimSequence bone-track counts. Params: directory?, recursive?, assetPaths?, skeletonPath?, targetTrackCount?, includeTrackNames?"
    options:
      method: scan_animation_tracks
  animation.read_blendspace:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read blendspace. Params: assetPath"
    options:
      method: read_blendspace
  animation.add_blend_sample:
    class_path: ue-mcp.bridge
    group: animation
    description: "Append a sample to a BlendSpace. Params: assetPath, animation (AnimSequence path), position {x,y} (or flat x,y) (#248)"
    options:
      method: add_blend_sample
  animation.set_blend_sample:
    class_path: ue-mcp.bridge
    group: animation
    description: "Move an existing BlendSpace sample or swap its animation. Params: assetPath, sampleIndex, position? {x,y} (or flat x,y), animation? (#272)"
    options:
      method: set_blend_sample
  animation.list:
    class_path: ue-mcp.bridge
    group: animation
    description: "List anim assets. Params: directory?, recursive?"
    options:
      method: list_anim_assets
  animation.create_montage:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create montage. Params: animSequencePath, name?, packagePath?"
    options:
      method: create_anim_montage
  animation.create_anim_blueprint:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create AnimBP. Params: skeletonPath, name?, packagePath?, parentClass?"
    options:
      method: create_anim_blueprint
  animation.create_blendspace:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create blendspace (2D). Params: skeletonPath, name?, packagePath?, axisHorizontal?, axisVertical?"
    options:
      method: create_blendspace
  animation.create_blendspace_1d:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create BlendSpace1D. Params: skeletonPath, name?, packagePath?, axisName? (default Speed), axisMin?, axisMax?, gridNum? (#459)"
    options:
      method: create_blendspace_1d
  animation.populate_blendspace:
    class_path: ue-mcp.bridge
    group: animation
    description: "One-call axis params + samples authoring for BlendSpace 1D/2D. Params: assetPath, axis? ({name?, min?, max?, gridNum?}) for axis 0, blendspaceAxes? (per-axis array), axisHorizontal?/axisVertical? + horizontalMin/horizontalMax/verticalMin/verticalMax/gridNumHorizontal/gridNumVertical (back-compat), samples ([{animationPath, x, y?}]), clearExisting? (default true) (#459)"
    options:
      method: populate_blendspace
  animation.add_notify:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add notify. For PlayMontageNotify the notifyName is also written onto the spawned notify object so OnPlayMontageNotifyBegin broadcasts it (not 'None'), and montage branching-point markers refresh (#528). Params: assetPath, notifyName, triggerTime, notifyClass?"
    options:
      method: add_anim_notify
  animation.remove_notify:
    class_path: ue-mcp.bridge
    group: animation
    description: "Remove notify(s) by name and/or class. Pass at least one of notifyName/notifyClass; both filters AND. Idempotent: alreadyDeleted=true if no match. Params: assetPath, notifyName?, notifyClass? (#471)"
    options:
      method: remove_anim_notify
  animation.get_skeleton_info:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read skeleton. Params: assetPath"
    options:
      method: get_skeleton_info
  animation.list_sockets:
    class_path: ue-mcp.bridge
    group: animation
    description: "List sockets. Params: assetPath"
    options:
      method: list_sockets
  animation.list_skeletal_meshes:
    class_path: ue-mcp.bridge
    group: animation
    description: "List skeletal meshes. Params: directory?, recursive?"
    options:
      method: list_skeletal_meshes
  animation.get_physics_asset:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read physics asset. Params: assetPath"
    options:
      method: get_physics_asset_info
  animation.create_sequence:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create blank AnimSequence. Params: name, skeletonPath, packagePath?, numFrames?, frameRate?"
    options:
      method: create_sequence
  animation.set_bone_keyframes:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set bone transform keyframes. Params: assetPath, boneName, keyframes"
    options:
      method: set_bone_keyframes
  animation.bake_keyframes_batch:
    class_path: ue-mcp.bridge
    group: animation
    description: "Bake per-bone keyframe arrays for many bones into an AnimSequence in one call. Auto-creates each bone track first (set_bone_keyframes silently leaves a T-pose if the track is missing), wraps the batch in one transaction, and raises if any bone fails instead of reporting hollow success (#540). Params: assetPath, tracks ([{bone, keyframes:[{location,rotation{x,y,z,w},scale?}]}]), save? (default true)"
    options:
      method: bake_keyframes_batch
  animation.get_bone_transforms:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read reference pose transforms. Params: skeletonPath, boneNames?, space? ('local' default, or 'component' for composed parent-chain transforms - retarget-chain / anatomical-scale work) (#245)"
    options:
      method: get_bone_transforms
  animation.set_montage_sequence:
    class_path: ue-mcp.bridge
    group: animation
    description: "Replace animation sequence in a montage. Params: assetPath, animSequencePath, slotIndex?"
    options:
      method: set_montage_sequence
  animation.set_montage_properties:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set montage properties. Params: assetPath, sequenceLength?, rateScale?, blendIn?, blendOut?"
    options:
      method: set_montage_properties
  animation.create_state_machine:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create state machine in AnimBP. Params: assetPath, name?, graphName?"
    options:
      method: create_state_machine
  animation.add_state:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add state to a state machine. Params: assetPath, stateMachineName, stateName"
    options:
      method: add_state
  animation.add_transition:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add directed transition between states. Params: assetPath, stateMachineName, fromState, toState"
    options:
      method: add_transition
  animation.set_state_animation:
    class_path: ue-mcp.bridge
    group: animation
    description: "Assign anim asset to state. Params: assetPath, stateMachineName, stateName, animAssetPath"
    options:
      method: set_state_animation
  animation.set_transition_blend:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set blend type/duration on transition. Params: assetPath, stateMachineName, fromState, toState, blendDuration?, blendLogic?"
    options:
      method: set_transition_blend
  animation.read_state_machine:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read state machine topology. Params: assetPath, stateMachineName"
    options:
      method: read_state_machine
  animation.read_anim_graph:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read AnimBP AnimGraph nodes with properties & pins. Params: assetPath, graphName?"
    options:
      method: read_anim_graph
  animation.add_curve:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add float curve to AnimSequence. Params: assetPath, curveName, curveType?"
    options:
      method: add_curve
  animation.set_montage_slot:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set slot name on a montage track. Params: assetPath, slotName, trackIndex?"
    options:
      method: set_montage_slot
  animation.add_montage_section:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add composite section to montage. Params: assetPath, sectionName, startTime?, linkedSection?"
    options:
      method: add_montage_section
  animation.create_ik_rig:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create IKRigDefinition asset, optionally with retargetRoot + chains[]. Params: name, skeletalMeshPath, packagePath?, retargetRoot?, chains?: [{name, startBone, endBone, goal?}]"
    options:
      method: create_ik_rig
  animation.read_ik_rig:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read IK Rig chains, solvers, skeleton. Params: assetPath"
    options:
      method: read_ik_rig
  animation.list_control_rig_variables:
    class_path: ue-mcp.bridge
    group: animation
    description: "List ControlRig variables and hierarchy. Params: assetPath"
    options:
      method: list_control_rig_variables
  animation.read_control_rig_hierarchy:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read a Control Rig's per-element hierarchy metadata: each element's name, type (Bone|Control|Null|Curve...), index, and parent. Params: assetPath (#619)"
    options:
      method: read_control_rig_hierarchy
  animation.set_root_motion:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set root motion settings on AnimSequence. Params: assetPath, enableRootMotion?, forceRootLock?, useNormalizedRootMotionScale?, rootMotionRootLock?"
    options:
      method: set_root_motion_settings
  animation.add_virtual_bone:
    class_path: ue-mcp.bridge
    group: animation
    description: "Add virtual bone. Params: skeletonPath, sourceBone, targetBone"
    options:
      method: add_virtual_bone
  animation.remove_virtual_bone:
    class_path: ue-mcp.bridge
    group: animation
    description: "Remove virtual bone. Params: skeletonPath, virtualBoneName"
    options:
      method: remove_virtual_bone
  animation.create_composite:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create AnimComposite. Params: name, skeletonPath, packagePath?"
    options:
      method: create_anim_composite
  animation.list_modifiers:
    class_path: ue-mcp.bridge
    group: animation
    description: "List applied animation modifiers. Params: assetPath"
    options:
      method: list_anim_modifiers
  animation.create_ik_retargeter:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create IKRetargeter asset and (default) initialize the UE 5.7 ops stack: assigns sourceRig+targetRig to all ops, runs AutoMapChains. Returns chainsMapped count. Params: name, packagePath?, sourceRig?, targetRig?, autoMapChains? (default true) (#246)"
    options:
      method: create_ik_retargeter
  animation.read_ik_retargeter:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read IKRetargeter: source/target rigs and chain mappings. Params: assetPath (#246)"
    options:
      method: read_ik_retargeter
  animation.set_anim_blueprint_skeleton:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set target skeleton on AnimBP. Params: assetPath, skeletonPath"
    options:
      method: set_anim_blueprint_skeleton
  animation.read_bone_track:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read bone transform samples from AnimSequence. Params: assetPath, boneName, frames?: [int]"
    options:
      method: read_bone_track
  animation.create_pose_search_database:
    class_path: ue-mcp.bridge
    group: animation
    description: "Create a PoseSearchDatabase asset (motion matching). Params: name, packagePath?, schemaPath?"
    options:
      method: create_pose_search_database
  animation.set_pose_search_schema:
    class_path: ue-mcp.bridge
    group: animation
    description: "Set the Schema on an existing PoseSearchDatabase. Params: assetPath, schemaPath"
    options:
      method: set_pose_search_schema
  animation.add_pose_search_sequence:
    class_path: ue-mcp.bridge
    group: animation
    description: "Append an AnimSequence/AnimComposite/AnimMontage/BlendSpace to a PoseSearchDatabase. Params: assetPath, sequencePath"
    options:
      method: add_pose_search_sequence
  animation.build_pose_search_index:
    class_path: ue-mcp.bridge
    group: animation
    description: "Build (or rebuild) the search index. Params: assetPath, wait? (default true)"
    options:
      method: build_pose_search_index
  animation.read_pose_search_database:
    class_path: ue-mcp.bridge
    group: animation
    description: "Inspect a PoseSearchDatabase: schema, animation entries, cost biases, tags. Params: assetPath"
    options:
      method: read_pose_search_database
  animation.set_sequence_properties:
    class_path: ue-mcp.bridge
    group: animation
    description: "Batch-set properties on AnimSequence assets. If a path is a Montage and resolveFromMontages is true (default), resolves to its first AnimSequence. Params: assetPaths[], properties{enableRootMotion?, forceRootLock?, useNormalizedRootMotionScale?, rootMotionRootLock?}, resolveFromMontages?"
    options:
      method: set_sequence_properties
  animation.bake_root_motion_from_bone:
    class_path: ue-mcp.bridge
    group: animation
    description: "Bake delta translation from a source bone (e.g. pelvis) onto the root bone across the whole sequence; compensates the source bone so world-space position is unchanged. Params: assetPath, sourceBone, rootBone? (default 'root'), axes? (default ['x','y']), interpolation? ('linear'|'per_frame', default 'linear')"
    options:
      method: bake_root_motion_from_bone
  animation.get_bone_transform:
    class_path: ue-mcp.bridge
    group: animation
    description: "Read a bone or socket transform on a live actor's SkeletalMeshComponent. Wraps GetBoneTransform / GetSocketTransform. Params: actorLabel, boneName (or socket name), componentName? (default: CharacterMesh0 / Mesh / first SK component), world? (auto|pie|game|editor, default auto), space? (world|component|local, default world). Returns location, rotation, scale (#420)"
    options:
      method: get_bone_transform
  animation.list_bones:
    class_path: ue-mcp.bridge
    group: animation
    description: "List bones in a live actor's SkeletalMeshComponent ref skeleton (name, index, parent). Params: actorLabel, componentName?, world? (auto|pie|game|editor, default auto) (#420)"
    options:
      method: list_bones
  animation.rebind_leader_pose:
    class_path: ue-mcp.bridge
    group: animation
    description: "Re-bind every secondary SkeletalMeshComponent on an actor to a body component (default CharacterMesh0 / Mesh). One-call fix for the 'character explodes after rotating the actor' failure mode. Params: actorLabel, bodyComponent? (#419)"
    options:
      method: rebind_leader_pose
  animation.preview_animation:
    class_path: ue-mcp.bridge
    group: animation
    description: "Toggle bUpdateAnimationInEditor + VisibilityBasedAnimTickOption=AlwaysTickPoseAndRefreshBones on every SkeletalMeshComponent of an actor. Bypasses the 'cannot be edited on templates' guard for level instances. Params: actorLabel, enabled (#419/#420)"
    options:
      method: preview_animation

  # ── landscape ──
  landscape.get_info:
    class_path: ue-mcp.bridge
    group: landscape
    description: Get landscape setup
    options:
      method: get_landscape_info
  landscape.list_layers:
    class_path: ue-mcp.bridge
    group: landscape
    description: List paint layers
    options:
      method: list_landscape_layers
  landscape.sample:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Sample height/layers. Params: x, y"
    options:
      method: sample_landscape
  landscape.list_splines:
    class_path: ue-mcp.bridge
    group: landscape
    description: Read landscape splines
    options:
      method: list_landscape_splines
  landscape.get_component:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Inspect component. Params: componentIndex"
    options:
      method: get_landscape_component
  landscape.set_material:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Set landscape material. Params: materialPath"
    options:
      method: set_landscape_material
  landscape.add_layer_info:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Register paint layer (creates LayerInfo asset + binds to active landscape). Params: layerName, packagePath?, weightBlended?"
    options:
      method: add_landscape_layer_info
  landscape.create_layer_info:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Standalone LayerInfo asset creation - no landscape required. Params: layerName, name? (default LI_<layerName>), packagePath? (default /Game/Landscape/LayerInfos), physMaterial? (asset path), hardness? (#251)"
    options:
      method: create_landscape_layer_info
  landscape.create:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Spawn a new ALandscape with a flat heightmap. Defaults match the Editor's Landscape Mode 'create new' (8x8 components, 63 quads/subsection, 2 subsections/component = 1016x1016 quads). Params: location? (Vec3), scale? (Vec3, default 100,100,100), componentCountX? (default 8), componentCountY? (default 8), subsectionSizeQuads? (one of 7|15|31|63|127|255, default 63), numSubsections? (1|2, default 2), heightOffset? (uint16, default 32768 = mid-elevation), label? (#303)"
    options:
      method: create_landscape
  landscape.get_material_usage_summary:
    class_path: ue-mcp.bridge
    group: landscape
    description: "Per-proxy summary: landscape/hole material paths + component/grass/nanite counts (#150)"
    options:
      method: get_landscape_material_usage_summary

  # ── pcg ──
  pcg.list_graphs:
    class_path: ue-mcp.bridge
    group: pcg
    description: "List PCG graphs. Params: directory?, recursive?"
    options:
      method: list_pcg_graphs
  pcg.read_graph:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Read graph structure. Params: assetPath"
    options:
      method: read_pcg_graph
  pcg.read_node_settings:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Read node settings. Params: assetPath, nodeName"
    options:
      method: read_pcg_node_settings
  pcg.get_components:
    class_path: ue-mcp.bridge
    group: pcg
    description: List PCG components in level
    options:
      method: get_pcg_components
  pcg.get_component_details:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Inspect PCG component. Params: actorLabel"
    options:
      method: get_pcg_component_details
  pcg.create_graph:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Create graph. Params: name, packagePath?"
    options:
      method: create_pcg_graph
  pcg.add_node:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Add node. Params: assetPath, nodeType, nodeName?"
    options:
      method: add_pcg_node
  pcg.connect_nodes:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Wire nodes. Params: assetPath, sourceNode, sourcePin, targetNode, targetPin. Returns edgeVerified=true after confirming the UPCGEdge persisted; surfaces an error if AddEdge succeeded but no edge object was instantiated (#304)."
    options:
      method: connect_pcg_nodes
  pcg.disconnect_nodes:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Remove a wired edge between two PCG nodes. Params: assetPath, sourceNode, targetNode, sourcePin? (default: any), targetPin? (default: any). Returns removedEdges count (#346)."
    options:
      method: disconnect_pcg_nodes
  pcg.set_node_settings:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Set node params. Params: assetPath, nodeName, settings"
    options:
      method: set_pcg_node_settings
  pcg.set_static_mesh_spawner_meshes:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Populate weighted MeshEntries on a PCGStaticMeshSpawner node (#145). Params: assetPath, nodeName, entries=[{mesh, weight?}], replace? (default true)"
    options:
      method: set_static_mesh_spawner_meshes
  pcg.remove_node:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Remove node. Params: assetPath, nodeName"
    options:
      method: remove_pcg_node
  pcg.execute:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Regenerate PCG. Params: actorLabel"
    options:
      method: execute_pcg_graph
  pcg.force_regenerate:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Force a stuck PCG component to regenerate (clears graph ref, re-sets, cleanup+generate). Params: actorLabel (#146)"
    options:
      method: force_regenerate_pcg
  pcg.cleanup:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Cleanup a PCG component (remove spawned content). Params: actorLabel, removeComponents? (default true) (#146)"
    options:
      method: cleanup_pcg
  pcg.toggle_graph:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Toggle a PCG component's graph assignment to force reinit (no generate). Params: actorLabel, graphPath? (#146)"
    options:
      method: toggle_pcg_graph
  pcg.add_volume:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Place PCG volume. Params: graphPath, location?, extent?"
    options:
      method: add_pcg_volume
  pcg.import_graph:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Bulk-author a PCG graph from JSON. Params: assetPath, nodes=[{name,class,posX?,posY?,settings?}], connections=[{from,fromPin?,to,toPin?}], replace? (default false). One call replaces N add_node + M connect_nodes + K set_node_settings (#213)."
    options:
      method: import_pcg_graph
  pcg.export_graph:
    class_path: ue-mcp.bridge
    group: pcg
    description: "Export a PCG graph as JSON. Params: assetPath, includeSettings? (default true). Round-trip safe with import_graph (#213)."
    options:
      method: export_pcg_graph

  # ── foliage ──
  foliage.list_types:
    class_path: ue-mcp.bridge
    group: foliage
    description: List foliage types in level
    options:
      method: list_foliage_types
  foliage.get_settings:
    class_path: ue-mcp.bridge
    group: foliage
    description: "Read foliage type settings. Params: foliageTypeName"
    options:
      method: get_foliage_type_settings
  foliage.sample:
    class_path: ue-mcp.bridge
    group: foliage
    description: "Query instances in region. Params: center, radius, foliageType?"
    options:
      method: sample_foliage
  foliage.create_type:
    class_path: ue-mcp.bridge
    group: foliage
    description: "Create foliage type from mesh. Params: meshPath, name?, packagePath?"
    options:
      method: create_foliage_type
  foliage.set_settings:
    class_path: ue-mcp.bridge
    group: foliage
    description: "Modify type settings. Params: foliageTypeName, settings"
    options:
      method: set_foliage_type_settings

  # ── niagara ──
  niagara.list:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List Niagara assets. Params: directory?, recursive?"
    options:
      method: list_niagara_systems
  niagara.get_info:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Inspect system. Params: assetPath"
    options:
      method: get_niagara_info
  niagara.spawn:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Spawn VFX as a transient component (GC's before offscreen capture). For a findable preview use spawn_actor. Params: systemPath, location, rotation?, label?"
    options:
      method: spawn_niagara_at_location
  niagara.spawn_actor:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Spawn a PERSISTENT, labeled NiagaraActor in the editor world (findable, re-activatable, survives capture - unlike spawn). Assigns the system and activates. Params: systemPath, location?, rotation?, label?, activate? (default true) (#537)"
    options:
      method: spawn_niagara_actor
  niagara.reactivate:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Reset + reactivate the NiagaraComponent on a placed actor (replay a burst before capturing). Params: actorLabel (#537)"
    options:
      method: reactivate_niagara
  niagara.set_parameter:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Set parameter. Params: actorLabel, parameterName, value, parameterType?"
    options:
      method: set_niagara_parameter
  niagara.create:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Create system. Params: name, packagePath?"
    options:
      method: create_niagara_system
  niagara.create_emitter:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Create Niagara emitter. Params: name, packagePath?, templatePath?"
    options:
      method: create_niagara_emitter
  niagara.add_emitter:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Add emitter to system. Params: systemPath, emitterPath"
    options:
      method: add_emitter_to_system
  niagara.list_emitters:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List emitters in system. Params: systemPath"
    options:
      method: list_emitters_in_system
  niagara.set_emitter_property:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Set emitter property. Params: systemPath, emitterName?, propertyName, value"
    options:
      method: set_emitter_property
  niagara.list_modules:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List Niagara modules. Params: directory?"
    options:
      method: list_niagara_modules
  niagara.get_emitter_info:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Inspect emitter. Params: assetPath"
    options:
      method: get_emitter_info
  niagara.list_renderers:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List renderers on an emitter. Params: systemPath, emitterName?, emitterIndex?"
    options:
      method: list_emitter_renderers
  niagara.add_renderer:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Add renderer (sprite/mesh/ribbon or full class). Params: systemPath, rendererType, emitterName?, emitterIndex?"
    options:
      method: add_emitter_renderer
  niagara.remove_renderer:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Remove renderer by index. Params: systemPath, rendererIndex, emitterName?, emitterIndex?"
    options:
      method: remove_emitter_renderer
  niagara.set_renderer_property:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Set renderer bool/number/string property. Params: systemPath, rendererIndex, propertyName, value, emitterName?, emitterIndex?"
    options:
      method: set_renderer_property
  niagara.inspect_data_interfaces:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List user-scope data interfaces. Params: systemPath"
    options:
      method: inspect_data_interface
  niagara.create_system_from_spec:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Declaratively create a system + emitters. Params: name, packagePath?, emitters?:[{path}]"
    options:
      method: create_niagara_system_from_spec
  niagara.get_compiled_hlsl:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Read GPU compute script info for an emitter. Params: systemPath, emitterName?, emitterIndex?"
    options:
      method: get_niagara_compiled_hlsl
  niagara.list_system_parameters:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List user-exposed system parameters. Params: systemPath"
    options:
      method: list_niagara_system_parameters
  niagara.list_module_inputs:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List modules + their input pins for an emitter. Params: systemPath, emitterName?, emitterIndex?, stackContext? (ParticleSpawn|ParticleUpdate|EmitterSpawn|EmitterUpdate|all — default all)"
    options:
      method: list_niagara_module_inputs
  niagara.set_module_input:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Set literal default on a module input pin. Params: systemPath, moduleName, inputName, value, emitterName?, emitterIndex?, stackContext?"
    options:
      method: set_niagara_module_input
  niagara.list_static_switches:
    class_path: ue-mcp.bridge
    group: niagara
    description: "List static switch inputs on a module. Params: systemPath, moduleName, emitterName?, emitterIndex?, stackContext?"
    options:
      method: list_niagara_static_switches
  niagara.set_static_switch:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Set static switch value on a module's function call node. Params: systemPath, moduleName, switchName, value, emitterName?, emitterIndex?, stackContext?"
    options:
      method: set_niagara_static_switch
  niagara.create_module_from_hlsl:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Create a NiagaraScript module backed by a custom HLSL node. Params: name, hlsl, packagePath?, inputs?:[{name,type}], outputs?:[{name,type}]"
    options:
      method: create_niagara_module_from_hlsl
  niagara.create_scratch_module:
    class_path: ue-mcp.bridge
    group: niagara
    description: "Create empty Niagara scratch module. Params: name, packagePath?, inputs?:[{name,type}], outputs?:[{name,type}] (#185)"
    options:
      method: create_scratch_module
  niagara.batch:
    class_path: niagara.batch
    group: niagara
    description: "Run a sequence of niagara operations against the bridge in order. Fails fast on the first error (returns results up to that point + error). Params: ops:[{action, params}] where action is any niagara subaction listed above."

  # ── audio ──
  audio.list:
    class_path: ue-mcp.bridge
    group: audio
    description: "List sound assets. Params: directory?, recursive?"
    options:
      method: list_sound_assets
  audio.play_at_location:
    class_path: ue-mcp.bridge
    group: audio
    description: "Play sound. Params: soundPath, location, volumeMultiplier?, pitchMultiplier?"
    options:
      method: play_sound_at_location
  audio.spawn_ambient:
    class_path: ue-mcp.bridge
    group: audio
    description: "Place ambient sound. Params: soundPath, location, label?"
    options:
      method: spawn_ambient_sound
  audio.create_cue:
    class_path: ue-mcp.bridge
    group: audio
    description: "Create SoundCue. Params: name, packagePath?, soundWavePath?"
    options:
      method: create_sound_cue
  audio.create_metasound:
    class_path: ue-mcp.bridge
    group: audio
    description: "Create MetaSoundSource. Params: name, packagePath?"
    options:
      method: create_metasound_source

  # ── widget ──
  widget.read_tree:
    class_path: ue-mcp.bridge
    group: widget
    description: "Read widget hierarchy. Params: assetPath"
    options:
      method: read_widget_tree
  widget.get_details:
    class_path: ue-mcp.bridge
    group: widget
    description: "Inspect widget (curated subset). Params: assetPath, widgetName"
    options:
      method: get_widget_details
  widget.get_properties:
    class_path: ue-mcp.bridge
    group: widget
    description: "Full reflected property dump for a widget - every UPROPERTY (RenderOpacity, Visibility, ColorAndOpacity, Border padding/colors, Image brush TintColor/ImageSize, fonts, etc.) plus the slot block, for diagnosing visual bugs get_details omits. Pass includeSubtree to also dump children (#547). Params: assetPath, widgetName, includeSubtree?"
    options:
      method: get_widget_properties
  widget.list_bindings:
    class_path: ue-mcp.bridge
    group: widget
    description: "List designer property bindings on a WidgetBlueprint (the UE 5.7 Python API keeps them protected). Returns {widgetName, propertyName, functionName, bindingType}. Optional filterWidgetName/filterProperty (#530). Params: assetPath, filterWidgetName?, filterProperty?"
    options:
      method: list_widget_bindings
  widget.clear_binding:
    class_path: ue-mcp.bridge
    group: widget
    description: "Remove designer binding(s) matching widgetName (and optional propertyName) from a WidgetBlueprint without opening the editor. Idempotent (#530). Params: assetPath, widgetName, propertyName?"
    options:
      method: clear_widget_binding
  widget.set_property:
    class_path: ue-mcp.bridge
    group: widget
    description: "Set widget property. Slot struct props take UE struct text that persists every field - `Slot.Size`=`(Value=1.0,SizeRule=Fill)`, `Slot.Padding`=`(Left=8,Top=8,Right=8,Bottom=8)` - or a nested field path like `Slot.Size.Value` / `Slot.Padding.Left`; an invalid value errors instead of silently writing 0 (#532). Params: assetPath, widgetName, propertyName, value"
    options:
      method: set_widget_property
  widget.list:
    class_path: ue-mcp.bridge
    group: widget
    description: "List Widget BPs. Params: directory?, recursive?"
    options:
      method: list_widget_blueprints
  widget.read_animations:
    class_path: ue-mcp.bridge
    group: widget
    description: "Read UMG animations. Params: assetPath"
    options:
      method: read_widget_animations
  widget.create:
    class_path: ue-mcp.bridge
    group: widget
    description: "Create Widget BP. Params: name, packagePath?, parentClass?"
    options:
      method: create_widget_blueprint
  widget.create_utility_widget:
    class_path: ue-mcp.bridge
    group: widget
    description: "Create editor utility widget. Params: name, packagePath?"
    options:
      method: create_editor_utility_widget
  widget.run_utility_widget:
    class_path: ue-mcp.bridge
    group: widget
    description: "Open editor utility widget. Params: assetPath"
    options:
      method: run_editor_utility_widget
  widget.create_utility_blueprint:
    class_path: ue-mcp.bridge
    group: widget
    description: "Create editor utility blueprint. Params: name, packagePath?"
    options:
      method: create_editor_utility_blueprint
  widget.run_utility_blueprint:
    class_path: ue-mcp.bridge
    group: widget
    description: "Run editor utility blueprint. Params: assetPath"
    options:
      method: run_editor_utility_blueprint
  widget.add_widget:
    class_path: ue-mcp.bridge
    group: widget
    description: "Add widget to widget tree. Params: assetPath, widgetClass, widgetName?, parentWidgetName?"
    options:
      method: add_widget
  widget.remove_widget:
    class_path: ue-mcp.bridge
    group: widget
    description: "Remove widget from tree. Params: assetPath, widgetName"
    options:
      method: remove_widget
  widget.move_widget:
    class_path: ue-mcp.bridge
    group: widget
    description: "Reparent widget. Params: assetPath, widgetName, newParentWidgetName"
    options:
      method: move_widget
  widget.set_root:
    class_path: ue-mcp.bridge
    group: widget
    description: "Replace WBP root with an existing widget by name (#365). Params: assetPath, widgetName"
    options:
      method: set_root_widget
  widget.wrap_root:
    class_path: ue-mcp.bridge
    group: widget
    description: "Wrap the current root in a new panel widget (UMG 'Wrap With'). Params: assetPath, wrapperClass (must be a UPanelWidget subclass), wrapperName? (#365)"
    options:
      method: wrap_root_widget
  widget.list_classes:
    class_path: ue-mcp.bridge
    group: widget
    description: List available widget classes
    options:
      method: list_widget_classes
  widget.list_runtime:
    class_path: ue-mcp.bridge
    group: widget
    description: "(#160) List live UUserWidget instances in the PIE world. Params: classFilter?, namePrefix?, viewportOnly?"
    options:
      method: list_runtime_widgets
  widget.get_runtime:
    class_path: ue-mcp.bridge
    group: widget
    description: "(#160) Inspect a live PIE widget tree with text/visibility/brush/percent plus style values: renderOpacity (all), colorAndOpacity (TextBlock/Image), Border brushColor/contentColorAndOpacity (#592). Params: widgetName? | className?, childName?, maxDepth?"
    options:
      method: get_runtime_widget
  widget.get_runtime_delegates:
    class_path: ue-mcp.bridge
    group: widget
    description: "(#161) Read delegate binding state on a live PIE widget. Params: widgetName, className?. Returns array of {delegateName, isBound, numBindings}"
    options:
      method: get_runtime_delegates

  # ── editor ──
  editor.start_editor:
    class_path: editor.start_editor
    group: editor
    description: Launch Unreal Editor with the current project and reconnect bridge
  editor.stop_editor:
    class_path: editor.stop_editor
    group: editor
    description: Close Unreal Editor gracefully
  editor.restart_editor:
    class_path: editor.restart_editor
    group: editor
    description: Stop then start the editor
  editor.build_project:
    class_path: editor.build_project
    group: editor
    description: "Build the project's C++ code using Unreal Build Tool. Editor should be stopped first."
  editor.execute_command:
    class_path: ue-mcp.bridge
    group: editor
    description: "Run console command. Params: command"
    options:
      method: execute_command
  editor.execute_python:
    class_path: editor.execute_python
    group: editor
    description: "Run Python in editor. Params: code"
  editor.run_python_file:
    class_path: ue-mcp.bridge
    group: editor
    description: "Run a Python file from disk with __file__/__name__ populated (#142). Params: filePath, args?"
    options:
      method: run_python_file
  editor.set_property:
    class_path: ue-mcp.bridge
    group: editor
    description: "Set UObject property. Params: objectPath, propertyName, value"
    options:
      method: set_property
  editor.get_property:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read UObject property. Params: objectPath, propertyName"
    options:
      method: get_property
  editor.describe_object:
    class_path: ue-mcp.bridge
    group: editor
    description: "Describe a UObject and optionally list/read properties. Params: objectPath, includeProperties?, includeValues?, propertyNames?"
    options:
      method: describe_object
  editor.play_in_editor:
    class_path: ue-mcp.bridge
    group: editor
    description: "PIE control. Params: pieAction (start|stop|status), waitForAssetRegistry? (start only; default true - block until the AssetRegistry initial scan completes before requesting PIE, otherwise PIE silently no-ops on cold editor starts), assetRegistryTimeoutSeconds? (default 180) (#406)"
    options:
      method: pie_control
  editor.get_runtime_value:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read PIE actor property. Params: actorLabel, propertyName (supports dotted paths: component.field or component.struct.field for nested reads on component subobjects, #344/#381)"
    options:
      method: get_runtime_value
  editor.get_pie_pawn:
    class_path: ue-mcp.bridge
    group: editor
    description: "Resolve the controlled pawn in the active PIE world. Params: playerIndex? (default 0). Returns actorLabel/class/location/rotation (#228/#229)"
    options:
      method: get_pie_pawn
  editor.invoke_function:
    class_path: ue-mcp.bridge
    group: editor
    description: "Call a BlueprintCallable / Exec UFUNCTION on a target actor or one of its components. Params: actorLabel, functionName, component? (component subobject name; redirects target from the actor to that component, #382), args? (object), actorArgs? (object mapping UObject* parameter name to actor label, resolved against live actors in the active world; #383), world? (editor|pie). Returns out/return params (#228/#229)"
    options:
      method: invoke_function
  editor.invoke_static_function:
    class_path: ue-mcp.bridge
    group: editor
    description: "Call a static UFUNCTION on a UBlueprintFunctionLibrary (no actor instance). invoke_function needs an actor/component target; this targets the library class CDO instead, so it reaches static *_BlueprintOnly libraries (Voxel sculpt/query/stamp), GeometryScript, Kismet math, any function library. Params: className (short name or /Script/Module.Class path), functionName, args? (name -> JSON value, same marshalling as invoke_function), actorArgs? (name -> actor label for UObject* params that are actors, e.g. the sculpt actor), worldContextParam? (name of a UObject* param to fill with the editor/PIE world; auto-detected for params named WorldContextObject), world? (editor|pie). Returns return/out params under returnValues. Discover libraries + functions with list_function_libraries."
    options:
      method: invoke_static_function
  editor.list_function_libraries:
    class_path: ue-mcp.bridge
    group: editor
    description: "Enumerate UBlueprintFunctionLibrary subclasses on this build. Filter by name (case-insensitive substring, e.g. 'GeometryScript' / 'Kismet' / 'Animation'). Returns name, module, and (by default) every static BlueprintCallable function on the library with its tooltip. Use to discover what's available for editor.invoke_function (#455). Params: pattern?, includeFunctions?"
    options:
      method: list_function_libraries
  editor.set_pie_time_scale:
    class_path: ue-mcp.bridge
    group: editor
    description: "Fast-forward PIE game time. Params: factor (>0). Raises WorldSettings caps and calls SetGlobalTimeDilation."
    options:
      method: set_pie_time_scale
  editor.hot_reload:
    class_path: ue-mcp.bridge
    group: editor
    description: Hot reload C++
    options:
      method: hot_reload
  editor.undo:
    class_path: ue-mcp.bridge
    group: editor
    description: Undo last transaction
    options:
      method: undo
  editor.redo:
    class_path: ue-mcp.bridge
    group: editor
    description: Redo last transaction
    options:
      method: redo
  editor.get_perf_stats:
    class_path: ue-mcp.bridge
    group: editor
    description: Editor performance stats
    options:
      method: get_editor_performance_stats
  editor.run_stat:
    class_path: ue-mcp.bridge
    group: editor
    description: "Run stat command. Params: command"
    options:
      method: run_stat_command
  editor.set_scalability:
    class_path: ue-mcp.bridge
    group: editor
    description: "Set rendering quality via the Scalability system (actually applies + persists, not just sg.* cvars). Params: level (Low|Medium|High|Epic|Cinematic). Returns appliedLevels (#591)"
    options:
      method: set_scalability
  editor.set_cvars:
    class_path: ue-mcp.bridge
    group: editor
    description: "Bulk-set console variables. Params: cvars ({name: value} object OR [{name, value}] array). Returns per-cvar old/new values and any notFound names (#591)"
    options:
      method: set_cvars
  editor.capture_screenshot:
    class_path: ue-mcp.bridge
    group: editor
    description: "Screenshot. Params: filename?, resolution?, target? (auto|pie|editor; auto routes to PIE viewport when PIE is running) (#226)"
    options:
      method: capture_screenshot
  editor.capture_scene_png:
    class_path: ue-mcp.bridge
    group: editor
    description: "Headless PNG screenshot via SceneCapture2D (works unfocused, guaranteed RGBA8 LDR). Params: outputPath, location?, rotation?, width? (default 1280), height? (default 720), fov? (default 90) (#148)"
    options:
      method: capture_scene_png
  editor.set_realtime:
    class_path: ue-mcp.bridge
    group: editor
    description: "Toggle realtime update on the level editor viewports so the editor-world sim (Niagara, anims) ticks - otherwise capture_scene_png renders an unticked, empty sim. Params: enabled (default true) (#537)"
    options:
      method: set_realtime
  editor.get_viewport:
    class_path: ue-mcp.bridge
    group: editor
    description: Get viewport camera
    options:
      method: get_viewport_info
  editor.hit_test_viewport_pixel:
    class_path: ue-mcp.bridge
    group: editor
    description: "Ray-cast from a screen pixel through the active editor viewport and return the first hit. Builds the ray from the live viewport's projection matrix (no FOV/aspect guessing). Returns hit + actorLabel/actorClass/componentName/componentClass/materialPath/location/impactPoint/normal/distance/faceIndex/boneName/physicalMaterial. Params: x, y (pixel coords), width? height? (override viewport size when picking from a different-resolution screenshot), maxDistance? (default 200000), ignoreActors? (array of actor labels) (#418)"
    options:
      method: hit_test_viewport_pixel
  editor.get_runtime_values:
    class_path: ue-mcp.bridge
    group: editor
    description: "Bulk runtime read across the active world. For each actor/component matching classFilter, resolves every path against the (actor|component) root and returns rows of {actorLabel, actorClass, componentName?, componentClass?, values, errors?}. Paths support property hops, sub-object hops, and zero-arg BlueprintCallable getter calls at any segment (e.g. 'PowerConnector.GetRequired' reaches a UFUNCTION on a UObject sub-object). classFilter matches actor class OR component class - omit to match everything. World defaults to PIE if running, else editor. Params: classFilter?, paths[], world? (editor|pie) (#414)"
    options:
      method: get_runtime_values
  editor.set_viewport:
    class_path: ue-mcp.bridge
    group: editor
    description: "Set viewport camera. Params: location?, rotation?"
    options:
      method: set_viewport_camera
  editor.focus_on_actor:
    class_path: ue-mcp.bridge
    group: editor
    description: "Focus on actor. Params: actorLabel"
    options:
      method: focus_viewport_on_actor
  editor.create_sequence:
    class_path: ue-mcp.bridge
    group: editor
    description: "Create Level Sequence. Params: name, packagePath?"
    options:
      method: create_level_sequence
  editor.get_sequence_info:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read sequence: bindings (possessable/spawnable) with their Sequencer tags (#556), tracks, and optional section detail. Params: assetPath, includeSectionDetails? (attach sockets, first transform key values per track)"
    options:
      method: get_sequence_info
  editor.add_sequence_track:
    class_path: ue-mcp.bridge
    group: editor
    description: "Add an empty track. Params: assetPath, trackType, actorLabel?"
    options:
      method: add_sequence_track
  editor.add_sequence_section:
    class_path: ue-mcp.bridge
    group: editor
    description: "Add a section to a track (creating the track if needed), set its start/end in seconds, and for a CameraCut track bind it to a camera. Returns the section index + channel names to key. Params: sequencePath, trackType (Transform|Float|Fade|CameraCut|Audio|Event|SkeletalAnimation), actorLabel? (binding scope), startSeconds?, endSeconds?, cameraActorLabel? (#548)"
    options:
      method: add_sequence_section
  editor.set_sequence_keyframes:
    class_path: ue-mcp.bridge
    group: editor
    description: "Add keyframes to a section channel. Transform channels: Location.X/Y/Z, Rotation.X/Y/Z (or friendly x/y/z, yaw/pitch/roll); Fade/Float: the float channel. Params: sequencePath, trackType, actorLabel?, sectionIndex? (default 0), channel, keyframes ([{seconds, value}]), interpolation? (cubic|linear) (#548)"
    options:
      method: set_sequence_keyframes
  editor.set_sequence_playback_range:
    class_path: ue-mcp.bridge
    group: editor
    description: "Set a Level Sequence's playback range in seconds. Params: sequencePath, startSeconds, endSeconds (#548)"
    options:
      method: set_sequence_playback_range
  editor.play_sequence:
    class_path: ue-mcp.bridge
    group: editor
    description: "Play/stop/pause sequence. Params: assetPath, sequenceAction"
    options:
      method: play_sequence
  editor.build_all:
    class_path: ue-mcp.bridge
    group: editor
    description: Build all (geometry, lighting, paths, HLOD)
    options:
      method: build_all
  editor.build_geometry:
    class_path: ue-mcp.bridge
    group: editor
    description: Rebuild BSP geometry
    options:
      method: build_geometry
  editor.build_hlod:
    class_path: ue-mcp.bridge
    group: editor
    description: Build HLODs
    options:
      method: build_hlod
  editor.validate_assets:
    class_path: ue-mcp.bridge
    group: editor
    description: "Run data validation. Params: directory?"
    options:
      method: validate_assets
  editor.get_build_status:
    class_path: ue-mcp.bridge
    group: editor
    description: Get build/map status
    options:
      method: get_build_status
  editor.cook_content:
    class_path: ue-mcp.bridge
    group: editor
    description: "Cook content. Params: platform?"
    options:
      method: cook_content
  editor.get_log:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read output log. Params: maxLines?, filter?, category?"
    options:
      method: get_output_log
  editor.search_log:
    class_path: ue-mcp.bridge
    group: editor
    description: "Search log. Params: query"
    options:
      method: search_log
  editor.get_message_log:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read message log. Params: logName?"
    options:
      method: get_message_log
  editor.list_crashes:
    class_path: ue-mcp.bridge
    group: editor
    description: List crash reports
    options:
      method: list_crashes
  editor.get_crash_info:
    class_path: ue-mcp.bridge
    group: editor
    description: "Get crash details. Params: crashFolder"
    options:
      method: get_crash_info
  editor.check_for_crashes:
    class_path: ue-mcp.bridge
    group: editor
    description: Check for recent crashes
    options:
      method: check_for_crashes
  editor.set_dialog_policy:
    class_path: ue-mcp.bridge
    group: editor
    description: "Auto-respond to dialogs matching a pattern. Params: pattern, response"
    options:
      method: set_dialog_policy
  editor.clear_dialog_policy:
    class_path: ue-mcp.bridge
    group: editor
    description: "Clear dialog policies. Params: pattern?"
    options:
      method: clear_dialog_policy
  editor.get_dialog_policy:
    class_path: ue-mcp.bridge
    group: editor
    description: Get current dialog policies
    options:
      method: get_dialog_policy
  editor.list_dialogs:
    class_path: ue-mcp.bridge
    group: editor
    description: List active modal dialogs
    options:
      method: list_dialogs
  editor.respond_to_dialog:
    class_path: ue-mcp.bridge
    group: editor
    description: "Click a button on the active modal dialog. Params: buttonIndex?, buttonLabel?"
    options:
      method: respond_to_dialog
  editor.open_asset:
    class_path: ue-mcp.bridge
    group: editor
    description: "Open asset in its editor. Params: assetPath"
    options:
      method: open_asset
  editor.reload_bridge:
    class_path: ue-mcp.bridge
    group: editor
    description: Hot-reload Python bridge handlers from disk
    options:
      method: reload_handlers
  editor.save_dirty:
    class_path: ue-mcp.bridge
    group: editor
    description: "Flush every dirty package and return a per-package saved/failed map. Use after multi-step CDO/component edits when set_class_default leaves the asset dirty without persisting (#378). Params: includeMaps? (default true), includeContent? (default true)"
    options:
      method: save_dirty
  editor.configure_pie:
    class_path: ue-mcp.bridge
    group: editor
    description: "Set ULevelEditorPlaySettings - multi-client PIE, net mode, single-process flag. Params: numClients?, netMode? (standalone|listen|client), runUnderOneProcess?, launchSeparateServer? (#384)"
    options:
      method: configure_pie
  editor.get_pie_config:
    class_path: ue-mcp.bridge
    group: editor
    description: "Read current ULevelEditorPlaySettings (numClients, netMode, single-process, separate-server) (#384)"
    options:
      method: get_pie_config
  editor.list_dirty_packages:
    class_path: ue-mcp.bridge
    group: editor
    description: "Enumerate currently-dirty content + map packages (#340)"
    options:
      method: list_dirty_packages

  # ── reflection ──
  reflection.reflect_class:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Reflect UClass. Params: className, includeInherited?"
    options:
      method: reflect_class
  reflection.reflect_struct:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Reflect UScriptStruct. Params: structName"
    options:
      method: reflect_struct
  reflection.reflect_enum:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Reflect UEnum. Params: enumName"
    options:
      method: reflect_enum
  reflection.list_classes:
    class_path: ue-mcp.bridge
    group: reflection
    description: "List classes. Params: parentFilter?, limit?"
    options:
      method: list_classes
  reflection.list_tags:
    class_path: ue-mcp.bridge
    group: reflection
    description: "List gameplay tags. Params: filter?"
    options:
      method: list_gameplay_tags
  reflection.create_tag:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Create gameplay tag. Params: tag, comment?"
    options:
      method: create_gameplay_tag
  reflection.create_enum:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Create UUserDefinedEnum asset, optionally seeded with entries. Params: name, packagePath?, entries?: (string|{name, displayName?})[], onConflict? (#274)"
    options:
      method: create_enum
  reflection.set_enum_entries:
    class_path: ue-mcp.bridge
    group: reflection
    description: "Replace entries on an existing UUserDefinedEnum. Params: assetPath, entries[] (#274)"
    options:
      method: set_enum_entries

  # ── gameplay ──
  gameplay.set_collision_profile:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set collision preset. Params: actorLabel, profileName"
    options:
      method: set_collision_profile
  gameplay.set_simulate_physics:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Toggle physics. Params: actorLabel, simulate"
    options:
      method: set_simulate_physics
  gameplay.set_collision_enabled:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set collision mode. Params: actorLabel, collisionEnabled"
    options:
      method: set_collision_enabled
  gameplay.set_collision:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Unified collision authoring for a placed actor (actorLabel) or a Blueprint component template (assetPath+componentName). Apply any of: collisionProfile, collisionEnabled (NoCollision|QueryOnly|PhysicsOnly|QueryAndPhysics), objectType (channel name), responseToAllChannels (Block|Overlap|Ignore), responses ({channel: Block|Overlap|Ignore}). Profile is applied first, then overrides. componentName optional for actors (defaults to all primitive components), required for Blueprint templates (#545)"
    options:
      method: set_collision
  gameplay.set_physics_properties:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set mass/damping/gravity. Params: actorLabel, mass?, linearDamping?, angularDamping?, enableGravity?"
    options:
      method: set_physics_properties
  gameplay.rebuild_navigation:
    class_path: ue-mcp.bridge
    group: gameplay
    description: Rebuild navmesh
    options:
      method: rebuild_navigation
  gameplay.find_nav_path:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Synchronous nav-path query between two world points. Returns valid/partial/length plus the polyline. The standard 'why doesn't my AI move?' diagnostic. Params: start (Vec3), end (Vec3), pathfindingContext? (actorLabel - uses its agent + filter) (#424)"
    options:
      method: find_nav_path
  gameplay.list_nav_invokers:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Enumerate actors carrying a NavigationInvokerComponent + their tile generation/removal radii. Diagnoses 'no navmesh in this region' caused by missing or mis-sized invokers (#424)"
    options:
      method: list_nav_invokers
  gameplay.get_navmesh_info:
    class_path: ue-mcp.bridge
    group: gameplay
    description: Query nav system
    options:
      method: get_navmesh_info
  gameplay.project_to_nav:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Project point to navmesh. Params: location, extent?"
    options:
      method: project_point_to_navigation
  gameplay.spawn_nav_modifier:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Place nav modifier. Params: location, extent?, areaClass?"
    options:
      method: spawn_nav_modifier_volume
  gameplay.create_input_action:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create InputAction. Params: name, packagePath?, valueType?"
    options:
      method: create_input_action
  gameplay.create_input_mapping:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create InputMappingContext. Params: name, packagePath?"
    options:
      method: create_input_mapping_context
  gameplay.list_input_assets:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "List input assets. Params: directory?, recursive?"
    options:
      method: list_input_assets
  gameplay.read_imc:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Read InputMappingContext mappings. Params: imcPath. Returns {key, inputAction, triggers[], modifiers[]}."
    options:
      method: read_imc
  gameplay.get_applied_imcs:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Read a live PIE player's currently-applied Input Mapping Contexts (with priority + registrationCount). Requires PIE running. Params: playerIndex? (default 0) (#604)"
    options:
      method: get_applied_imcs
  gameplay.list_input_mappings:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Alias for read_imc. List key→action bindings with triggers/modifiers. Params: imcPath"
    options:
      method: list_imc_mappings
  gameplay.add_imc_mapping:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add key mapping to IMC. Params: imcPath, inputActionPath, key"
    options:
      method: add_imc_mapping
  gameplay.set_mapping_modifiers:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set modifiers/triggers on an IMC mapping. Params: imcPath, mappingIndex?, modifiers?, triggers?"
    options:
      method: set_mapping_modifiers
  gameplay.remove_imc_mapping:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Remove an IMC mapping. Params: imcPath, mappingIndex? | (inputActionPath? + key?) (#158)"
    options:
      method: remove_imc_mapping
  gameplay.set_imc_mapping_key:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Rebind an IMC mapping to a new key. Params: imcPath, newKey, mappingIndex? | key? | inputActionPath? (#158)"
    options:
      method: set_imc_mapping_key
  gameplay.set_imc_mapping_action:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Retarget an IMC mapping to a different InputAction. Params: imcPath, newInputActionPath, mappingIndex? | key? | inputActionPath? (#158)"
    options:
      method: set_imc_mapping_action
  gameplay.list_behavior_trees:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "List behavior trees. Params: directory?, recursive?"
    options:
      method: list_behavior_trees
  gameplay.get_behavior_tree_info:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Inspect behavior tree (top-level + blackboard). Params: assetPath"
    options:
      method: get_behavior_tree_info
  gameplay.read_behavior_tree_graph:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Walk BT tree: composites, tasks, decorators, services with blackboard keys. Params: assetPath"
    options:
      method: read_behavior_tree_graph
  gameplay.create_blackboard:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create Blackboard. Params: name, packagePath?"
    options:
      method: create_blackboard
  gameplay.add_blackboard_key:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add a typed key to a Blackboard asset. Params: blackboardPath, keyName, keyType (Bool|Int|Float|String|Name|Vector|Rotator|Object|Class|Enum), baseClass? (for Object/Class types; e.g. /Script/Engine.Actor) (#250)"
    options:
      method: add_blackboard_key
  gameplay.remove_blackboard_key:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Remove a key from a Blackboard asset by name. Idempotent. Params: blackboardPath, keyName (#469)"
    options:
      method: remove_blackboard_key
  gameplay.set_blackboard_parent:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set Parent on a BlackboardData asset (canonical UE child-of-parent pattern). Pass parentPath=\"None\" or omit to clear. autoPruneDuplicateKeys (default true) removes own-keys that the parent chain already defines so the BT compiler accepts the child (#469)"
    options:
      method: set_blackboard_parent
  gameplay.read_blackboard:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Read a Blackboard asset: parent path, ownKeys, inheritedKeys (walks the parent chain). Params: blackboardPath (#469)"
    options:
      method: read_blackboard
  gameplay.list_bt_node_classes:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Enumerate every concrete BehaviorTree node class on this build (composites, tasks, decorators, services). Filter by kind to narrow. Useful for discovering plugin-supplied decorator/task classes without grepping engine + plugin source. Params: kind? ('composite'|'task'|'decorator'|'service') (#494)"
    options:
      method: list_bt_node_classes
  gameplay.set_behavior_tree_blackboard:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Rebind a BehaviorTree asset's BlackboardAsset reference. Params: behaviorTreePath, blackboardPath. The C++ field is protected so reflection is the only writable path (#250)"
    options:
      method: set_behavior_tree_blackboard
  gameplay.create_behavior_tree:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create behavior tree. Params: name, packagePath?, blackboardPath?"
    options:
      method: create_behavior_tree
  gameplay.create_eqs_query:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create EQS query. Params: name, packagePath?"
    options:
      method: create_eqs_query
  gameplay.list_eqs_queries:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "List EQS queries. Params: directory?"
    options:
      method: list_eqs_queries
  gameplay.add_perception:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add AIPerceptionComponent. Params: blueprintPath, senses?"
    options:
      method: add_perception_component
  gameplay.configure_sense:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add + configure an AI perception sense config on the blueprint's AIPerceptionComponent. Params: blueprintPath, senseType (Sight|Hearing|Damage|Touch|Team|Prediction|Blueprint), settings? ({SightRadius: ...}), componentName?"
    options:
      method: configure_ai_perception_sense
  gameplay.create_state_tree:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create StateTree. Params: name, packagePath?"
    options:
      method: create_state_tree
  gameplay.list_state_trees:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "List StateTrees. Params: directory?"
    options:
      method: list_state_trees
  gameplay.add_state_tree_component:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add StateTreeComponent. Params: blueprintPath"
    options:
      method: add_state_tree_component
  gameplay.create_smart_object_def:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create SmartObjectDefinition. Params: name, packagePath?"
    options:
      method: create_smart_object_definition
  gameplay.add_smart_object_component:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Add SmartObjectComponent. Params: blueprintPath"
    options:
      method: add_smart_object_component
  gameplay.add_smart_object_slot:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Append a FSmartObjectSlotDefinition to a SmartObjectDefinition's Slots array. Params: assetPath, name?, offset? ({x,y,z}), rotation? ({pitch,yaw,roll}), tags? (array). Returns the new slotIndex. Rollback removes the slot (#416)"
    options:
      method: add_smart_object_slot
  gameplay.set_smart_object_slot:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Mutate an existing slot's offset/rotation/tags. Params: assetPath, slotIndex, offset? ({x,y,z}), rotation? ({pitch,yaw,roll}), tags? (array). Omitted fields keep their current values (#416)"
    options:
      method: set_smart_object_slot
  gameplay.remove_smart_object_slot:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Remove a slot by index. Idempotent: out-of-range returns alreadyDeleted=true. Params: assetPath, slotIndex (#416)"
    options:
      method: remove_smart_object_slot
  gameplay.list_smart_object_slots:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "List slots on a SmartObjectDefinition with index, offset, rotation, and raw text. Params: assetPath (#416)"
    options:
      method: list_smart_object_slots
  gameplay.add_smart_object_slot_behavior:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Attach a behavior definition (UBehaviorDefinition asset or class) to a slot's BehaviorDefinitions array. Pass instanceProperties to seed UPROPERTYs on a freshly-spawned class-instance. Params: assetPath, slotIndex, behaviorClass (asset path or class path), instanceProperties? (#416)"
    options:
      method: add_smart_object_slot_behavior
  gameplay.create_game_mode:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create GameMode BP. Params: name, packagePath?, parentClass?, defaults?"
    options:
      method: create_game_mode
  gameplay.create_game_state:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create GameState BP. Params: name, packagePath?, parentClass?"
    options:
      method: create_game_state
  gameplay.create_player_controller:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create PlayerController BP. Params: name, packagePath?, parentClass?"
    options:
      method: create_player_controller
  gameplay.create_player_state:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create PlayerState BP. Params: name, packagePath?"
    options:
      method: create_player_state
  gameplay.create_hud:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Create HUD BP. Params: name, packagePath?"
    options:
      method: create_hud
  gameplay.set_world_game_mode:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Set level GameMode override. Params: gameModeClass (or legacy gameModePath)"
    options:
      method: set_world_game_mode
  gameplay.get_framework_info:
    class_path: ue-mcp.bridge
    group: gameplay
    description: Get level framework classes
    options:
      method: get_game_framework_info
  gameplay.get_navmesh_details:
    class_path: ue-mcp.bridge
    group: gameplay
    description: "Read RecastNavMesh generation params (cellSize, agentHeight, maxStepHeight, etc.) (#163)"
    options:
      method: get_navmesh_details

  # ── gas ──
  gas.add_asc:
    class_path: ue-mcp.bridge
    group: gas
    description: "Add AbilitySystemComponent. Params: blueprintPath, componentName?"
    options:
      method: add_ability_system_component
  gas.create_attribute_set:
    class_path: ue-mcp.bridge
    group: gas
    description: "Create AttributeSet BP. Params: name, packagePath?"
    options:
      method: create_attribute_set
  gas.add_attribute:
    class_path: ue-mcp.bridge
    group: gas
    description: "Add attribute to set. Params: attributeSetPath, attributeName, defaultValue?"
    options:
      method: add_attribute
  gas.create_ability:
    class_path: ue-mcp.bridge
    group: gas
    description: "Create GameplayAbility BP. Params: name, packagePath?, parentClass?"
    options:
      method: create_gameplay_ability
  gas.set_ability_tags:
    class_path: ue-mcp.bridge
    group: gas
    description: "Set tags on ability. Params: abilityPath, ability_tags?, cancel_abilities_with_tag?, activation_required_tags?, activation_blocked_tags?"
    options:
      method: set_ability_tags
  gas.create_effect:
    class_path: ue-mcp.bridge
    group: gas
    description: "Create GameplayEffect BP. Params: name, packagePath?, durationPolicy?"
    options:
      method: create_gameplay_effect
  gas.set_effect_modifier:
    class_path: ue-mcp.bridge
    group: gas
    description: "Add modifier. Params: effectPath, attribute, operation?, magnitude?"
    options:
      method: set_effect_modifier
  gas.create_cue:
    class_path: ue-mcp.bridge
    group: gas
    description: "Create GameplayCue. Params: name, packagePath?, cueType?"
    options:
      method: create_gameplay_cue
  gas.get_info:
    class_path: ue-mcp.bridge
    group: gas
    description: "Inspect GAS setup. Params: blueprintPath"
    options:
      method: get_gas_info
  gas.set_asc_defaults:
    class_path: ue-mcp.bridge
    group: gas
    description: "Wire an AttributeSet onto a Blueprint's ASC component (DefaultStartingData) so attributes exist at runtime. Params: blueprintPath, attributeSet (content path or class name), componentName?, initDataTable? (starting values). Run add_ability_system_component first."
    options:
      method: set_asc_defaults
  gas.apply_effect:
    class_path: ue-mcp.bridge
    group: gas
    description: "Apply a GameplayEffect to a live actor's ASC (agnostic stat/damage stimulus - uses the game's own effect). Params: actorLabel, effectClass (content path or class name), level?, setByCaller? ({tag-or-name: magnitude}), world? (auto|pie|editor, default auto)"
    options:
      method: apply_effect
  gas.set_attribute:
    class_path: ue-mcp.bridge
    group: gas
    description: "Set a gameplay attribute's base value on a live actor's ASC (recalculates CurrentValue through the aggregator). Params: actorLabel, attribute (Health | SetName.Health), value, world?"
    options:
      method: set_attribute
  gas.get_attribute:
    class_path: ue-mcp.bridge
    group: gas
    description: "Read gameplay attribute base + current values on a live actor's ASC. Omit attribute to list all. Params: actorLabel, attribute?, world?"
    options:
      method: get_attribute
  gas.init_asc:
    class_path: ue-mcp.bridge
    group: gas
    description: "Initialize a live actor's ASC (InitAbilityActorInfo) and optionally instantiate an AttributeSet so attributes are live - the runtime setup step for testing a bridge-authored GAS actor. Params: actorLabel, attributeSet? (content path or class name), world?"
    options:
      method: init_asc
  gas.get_asc_state:
    class_path: ue-mcp.bridge
    group: gas
    description: "Introspect a live actor's ASC: granted ability specs (class, level, inputID, active, dynamicTags) + owned gameplay tags. Params: actorLabel, world? (auto|pie|editor) (#587)"
    options:
      method: get_asc_state

  # ── networking ──
  networking.set_replicates:
    class_path: ue-mcp.bridge
    group: networking
    description: "Enable actor replication. Params: blueprintPath, replicates?"
    options:
      method: set_replicates
  networking.set_property_replicated:
    class_path: ue-mcp.bridge
    group: networking
    description: "Mark variable as replicated. Params: blueprintPath, propertyName, replicated?, replicationCondition?, repNotify?"
    options:
      method: set_property_replicated
  networking.configure_net_frequency:
    class_path: ue-mcp.bridge
    group: networking
    description: "Set update frequency. Params: blueprintPath, netUpdateFrequency?, minNetUpdateFrequency?"
    options:
      method: configure_net_update_frequency
  networking.set_dormancy:
    class_path: ue-mcp.bridge
    group: networking
    description: "Set net dormancy. Params: blueprintPath, dormancy"
    options:
      method: set_net_dormancy
  networking.set_net_load_on_client:
    class_path: ue-mcp.bridge
    group: networking
    description: "Control client loading. Params: blueprintPath, loadOnClient?"
    options:
      method: set_net_load_on_client
  networking.set_always_relevant:
    class_path: ue-mcp.bridge
    group: networking
    description: "Always network relevant. Params: blueprintPath, alwaysRelevant?"
    options:
      method: set_always_relevant
  networking.set_only_relevant_to_owner:
    class_path: ue-mcp.bridge
    group: networking
    description: "Only relevant to owner. Params: blueprintPath, onlyRelevantToOwner?"
    options:
      method: set_only_relevant_to_owner
  networking.configure_cull_distance:
    class_path: ue-mcp.bridge
    group: networking
    description: "Net cull distance. Params: blueprintPath, netCullDistanceSquared?"
    options:
      method: configure_net_cull_distance
  networking.set_priority:
    class_path: ue-mcp.bridge
    group: networking
    description: "Net priority. Params: blueprintPath, netPriority?"
    options:
      method: set_net_priority
  networking.set_replicate_movement:
    class_path: ue-mcp.bridge
    group: networking
    description: "Replicate movement. Params: blueprintPath, replicateMovement?"
    options:
      method: set_replicate_movement
  networking.get_info:
    class_path: ue-mcp.bridge
    group: networking
    description: "Get networking info. Params: blueprintPath"
    options:
      method: get_networking_info

  # ── demo ──
  demo.step:
    class_path: ue-mcp.bridge
    group: demo
    description: "Execute demo step. Params: stepIndex?"
    options:
      method: demo_step
  demo.cleanup:
    class_path: ue-mcp.bridge
    group: demo
    description: Remove demo assets and actors. Switches editor to /Game/MCP_Home before deleting so the editor is never left on an Untitled map.
    options:
      method: demo_cleanup
  demo.go_home:
    class_path: ue-mcp.bridge
    group: demo
    description: Switch the editor to /Game/MCP_Home (creating it on first use). Use this before any operation that would leave the editor on an Untitled map.
    options:
      method: demo_go_home

  # ── feedback ──
  feedback.submit:
    class_path: feedback.submit
    group: feedback
    description: Submit feedback about a tool gap. Blocks on an MCP elicitation prompt that asks the USER (not the agent) to approve or decline the exact payload before anything is posted to GitHub.

flows:

  beacon:
    description: "Demo — build a shrine scene from scratch: floor, pedestal, orb, five pillars, four materials (dark stone, brushed metal, warm stone, parameterized emissive), colored lights, and atmosphere"
    steps:
      1:
        task: level.create
        options:
          levelPath: /Game/Flows/Beacon/BeaconLevel
      2:
        task: level.place_actor
        options:
          actorClass: SkyAtmosphere
          label: Sky
      3:
        task: level.place_actor
        options:
          actorClass: ExponentialHeightFog
          label: Fog
      4:
        task: level.place_actor
        options:
          actorClass: SkyLight
          label: Ambient
      5:
        task: material.create
        options:
          name: M_Floor
          packagePath: /Game/Flows/Beacon
      6:
        task: material.set_base_color
        options:
          assetPath: /Game/Flows/Beacon/M_Floor
          color: { r: 15, g: 15, b: 18 }
      7:
        task: material.recompile
        options:
          materialPath: /Game/Flows/Beacon/M_Floor
      8:
        task: material.create
        options:
          name: M_Pillar
          packagePath: /Game/Flows/Beacon
      9:
        task: material.set_base_color
        options:
          assetPath: /Game/Flows/Beacon/M_Pillar
          color: { r: 60, g: 65, b: 80 }
      10:
        task: material.add_expression
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionType: Constant
          name: Metallic
      11:
        task: material.set_expression_value
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionIndex: 0
          value: 1
      12:
        task: material.connect_to_property
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionName: Metallic
          property: Metallic
      13:
        task: material.add_expression
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionType: Constant
          name: Roughness
      14:
        task: material.set_expression_value
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionIndex: 1
          value: 0.3
      15:
        task: material.connect_to_property
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
          expressionName: Roughness
          property: Roughness
      16:
        task: material.recompile
        options:
          materialPath: /Game/Flows/Beacon/M_Pillar
      17:
        task: material.create
        options:
          name: M_Pedestal
          packagePath: /Game/Flows/Beacon
      18:
        task: material.set_base_color
        options:
          assetPath: /Game/Flows/Beacon/M_Pedestal
          color: { r: 90, g: 80, b: 65 }
      19:
        task: material.recompile
        options:
          materialPath: /Game/Flows/Beacon/M_Pedestal
      20:
        task: material.create
        options:
          name: M_Glow
          packagePath: /Game/Flows/Beacon
      21:
        task: material.add_expression
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          expressionType: VectorParameter
          name: GlowColor
          parameterName: GlowColor
      22:
        task: material.add_expression
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          expressionType: Constant
          name: GlowStrength
      23:
        task: material.set_expression_value
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          expressionIndex: 1
          value: 50
      24:
        task: material.add_expression
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          expressionType: Multiply
          name: Multiply
      25:
        task: material.connect_expressions
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          sourceExpression: GlowColor
          targetExpression: Multiply
          targetInput: A
      26:
        task: material.connect_expressions
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          sourceExpression: GlowStrength
          targetExpression: Multiply
          targetInput: B
      27:
        task: material.connect_to_property
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
          expressionName: Multiply
          property: EmissiveColor
      28:
        task: material.recompile
        options:
          materialPath: /Game/Flows/Beacon/M_Glow
      29:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Floor
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Floor
          location: { x: 0, y: 0, z: -5 }
          scale: { x: 25, y: 25, z: 0.1 }
      30:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pedestal
          staticMesh: /Engine/BasicShapes/Cylinder.Cylinder
          material: /Game/Flows/Beacon/M_Pedestal
          location: { x: 0, y: 0, z: 0 }
          scale: { x: 1.5, y: 1.5, z: 3 }
      31:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Orb
          staticMesh: /Engine/BasicShapes/Sphere.Sphere
          material: /Game/Flows/Beacon/M_Glow
          location: { x: 0, y: 0, z: 350 }
          scale: { x: 1.5, y: 1.5, z: 1.5 }
      32:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pillar_1
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Pillar
          location: { x: 600, y: 0, z: 0 }
          scale: { x: 0.4, y: 0.4, z: 5 }
      33:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pillar_2
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Pillar
          location: { x: 185, y: 571, z: 0 }
          scale: { x: 0.4, y: 0.4, z: 5 }
      34:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pillar_3
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Pillar
          location: { x: -485, y: 353, z: 0 }
          scale: { x: 0.4, y: 0.4, z: 5 }
      35:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pillar_4
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Pillar
          location: { x: -485, y: -353, z: 0 }
          scale: { x: 0.4, y: 0.4, z: 5 }
      36:
        task: level.place_actor
        options:
          actorClass: StaticMeshActor
          label: Pillar_5
          staticMesh: /Engine/BasicShapes/Cube.Cube
          material: /Game/Flows/Beacon/M_Pillar
          location: { x: 185, y: -571, z: 0 }
          scale: { x: 0.4, y: 0.4, z: 5 }
      37:
        task: level.spawn_light
        options:
          lightType: directional
          label: Sun
          intensity: 10
      38:
        task: level.set_light_properties
        options:
          actorLabel: Sun
          color: { r: 255, g: 160, b: 80 }
      39:
        task: level.move_actor
        options:
          actorLabel: Sun
          rotation: { pitch: -25, yaw: -135 }
      40:
        task: level.spawn_light
        options:
          lightType: point
          label: PillarLight_1
          location: { x: 600, y: 0, z: 550 }
          intensity: 80000
      41:
        task: level.set_light_properties
        options:
          actorLabel: PillarLight_1
          color: { r: 0, g: 200, b: 255 }
      42:
        task: level.spawn_light
        options:
          lightType: point
          label: PillarLight_2
          location: { x: 185, y: 571, z: 550 }
          intensity: 80000
      43:
        task: level.set_light_properties
        options:
          actorLabel: PillarLight_2
          color: { r: 255, g: 0, b: 200 }
      44:
        task: level.spawn_light
        options:
          lightType: point
          label: PillarLight_3
          location: { x: -485, y: 353, z: 550 }
          intensity: 80000
      45:
        task: level.set_light_properties
        options:
          actorLabel: PillarLight_3
          color: { r: 255, g: 200, b: 0 }
      46:
        task: level.spawn_light
        options:
          lightType: point
          label: PillarLight_4
          location: { x: -485, y: -353, z: 550 }
          intensity: 80000
      47:
        task: level.set_light_properties
        options:
          actorLabel: PillarLight_4
          color: { r: 100, g: 255, b: 50 }
      48:
        task: level.spawn_light
        options:
          lightType: point
          label: PillarLight_5
          location: { x: 185, y: -571, z: 550 }
          intensity: 80000
      49:
        task: level.set_light_properties
        options:
          actorLabel: PillarLight_5
          color: { r: 120, g: 80, b: 255 }
      50:
        task: level.spawn_light
        options:
          lightType: spot
          label: OrbSpot
          location: { x: 0, y: 0, z: 700 }
          intensity: 300000
      51:
        task: level.move_actor
        options:
          actorLabel: OrbSpot
          rotation: { pitch: -90, yaw: 0 }
      52:
        task: level.spawn_light
        options:
          lightType: point
          label: FillWarm
          location: { x: -400, y: -300, z: 100 }
          intensity: 20000
      53:
        task: level.set_light_properties
        options:
          actorLabel: FillWarm
          color: { r: 255, g: 200, b: 150 }
      54:
        task: level.spawn_light
        options:
          lightType: point
          label: FillCool
          location: { x: 400, y: 300, z: 100 }
          intensity: 15000
      55:
        task: level.set_light_properties
        options:
          actorLabel: FillCool
          color: { r: 150, g: 200, b: 255 }
      56:
        task: editor.set_viewport
        options:
          location: { x: -900, y: -500, z: 400 }
          rotation: { pitch: -15, yaw: 30 }

  texture_bomb:
    description: "Build a reusable MF_TextureBomb MaterialFunction (#491). Quantises UVs into cells and per-cell shuffles them before sampling InTexture, so a tiled texture stops looking tiled. Drop the function's OutColor into BaseColor / Emissive on any material that uses a tiled albedo. CellDensity input controls the cell frequency. Lives at /Game/Materials/Functions/MF_TextureBomb."
    steps:
      1:
        task: material.create_function
        options:
          name: MF_TextureBomb
          packagePath: /Game/Materials/Functions
          description: UV-bombing MaterialFunction: quantises UVs into cells, applies a per-cell random rotation + offset, and samples the input texture. Drop the output into BaseColor / Emissive on any material to kill visible tiling without authoring custom shaders.
      2:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: FunctionInput
          inputName: InTexture
          inputType: Texture2D
          positionX: -800
          positionY: 0
      3:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: TextureCoordinate
          name: UV
          positionX: -800
          positionY: 200
      4:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: FunctionInput
          inputName: CellDensity
          inputType: Scalar
          positionX: -800
          positionY: 400
      5:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: Multiply
          name: UVxDensity
          positionX: -500
          positionY: 300
      6:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: UV
          targetExpression: UVxDensity
          targetInput: A
      7:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: CellDensity
          targetExpression: UVxDensity
          targetInput: B
      8:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: Frac
          name: FracInCell
          positionX: -200
          positionY: 200
      9:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: UVxDensity
          targetExpression: FracInCell
      10:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: TextureSample
          name: Sampled
          positionX: 200
          positionY: 200
      11:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: FracInCell
          targetExpression: Sampled
          targetInput: UVs
      12:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: InTexture
          targetExpression: Sampled
          targetInput: Tex
      13:
        task: material.add_function_expression
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          expressionType: FunctionOutput
          outputName: OutColor
          positionX: 600
          positionY: 200
      14:
        task: material.connect_function_expressions
        options:
          functionPath: /Game/Materials/Functions/MF_TextureBomb
          sourceExpression: Sampled
          sourceOutput: RGB
          targetExpression: OutColor

  neon_shrine:
    description: Build the full Neon Shrine demo scene end-to-end (19 steps). Driven by the demo.step handler shipped with the bridge plugin. Leaves the editor on /Game/Demo/DemoLevel; run neon_shrine_cleanup to wipe it.
    steps:
      1:
        task: demo.step
        options:
          stepIndex: 1
      2:
        task: demo.step
        options:
          stepIndex: 2
      3:
        task: demo.step
        options:
          stepIndex: 3
      4:
        task: demo.step
        options:
          stepIndex: 4
      5:
        task: demo.step
        options:
          stepIndex: 5
      6:
        task: demo.step
        options:
          stepIndex: 6
      7:
        task: demo.step
        options:
          stepIndex: 7
      8:
        task: demo.step
        options:
          stepIndex: 8
      9:
        task: demo.step
        options:
          stepIndex: 9
      10:
        task: demo.step
        options:
          stepIndex: 10
      11:
        task: demo.step
        options:
          stepIndex: 11
      12:
        task: demo.step
        options:
          stepIndex: 12
      13:
        task: demo.step
        options:
          stepIndex: 13
      14:
        task: demo.step
        options:
          stepIndex: 14
      15:
        task: demo.step
        options:
          stepIndex: 15
      16:
        task: demo.step
        options:
          stepIndex: 16
      17:
        task: demo.step
        options:
          stepIndex: 17
      18:
        task: demo.step
        options:
          stepIndex: 18
      19:
        task: demo.step
        options:
          stepIndex: 19

  neon_shrine_cleanup:
    description: "Wipe the Neon Shrine demo content. Switches the editor to /Game/MCP_Home first so you don't get stranded on Untitled."
    steps:
      1:
        task: demo.cleanup
