unreal-engine-mcp-server 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/.env.example +1 -1
  2. package/.github/release-drafter-config.yml +51 -0
  3. package/.github/workflows/greetings.yml +5 -1
  4. package/.github/workflows/labeler.yml +2 -1
  5. package/.github/workflows/publish-mcp.yml +2 -4
  6. package/.github/workflows/release-drafter.yml +3 -2
  7. package/.github/workflows/release.yml +3 -3
  8. package/CHANGELOG.md +109 -0
  9. package/CONTRIBUTING.md +1 -1
  10. package/GEMINI.md +115 -0
  11. package/Public/Plugin_setup_guide.mp4 +0 -0
  12. package/README.md +166 -200
  13. package/dist/automation/bridge.d.ts +1 -2
  14. package/dist/automation/bridge.js +24 -23
  15. package/dist/automation/connection-manager.d.ts +1 -0
  16. package/dist/automation/connection-manager.js +10 -0
  17. package/dist/automation/message-handler.js +5 -4
  18. package/dist/automation/request-tracker.d.ts +4 -0
  19. package/dist/automation/request-tracker.js +11 -3
  20. package/dist/config.d.ts +0 -1
  21. package/dist/config.js +0 -1
  22. package/dist/constants.d.ts +4 -0
  23. package/dist/constants.js +4 -0
  24. package/dist/graphql/loaders.d.ts +64 -0
  25. package/dist/graphql/loaders.js +117 -0
  26. package/dist/graphql/resolvers.d.ts +3 -3
  27. package/dist/graphql/resolvers.js +33 -30
  28. package/dist/graphql/server.js +3 -1
  29. package/dist/graphql/types.d.ts +2 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +13 -2
  32. package/dist/server-setup.d.ts +0 -1
  33. package/dist/server-setup.js +0 -40
  34. package/dist/tools/actors.d.ts +58 -24
  35. package/dist/tools/actors.js +22 -6
  36. package/dist/tools/assets.d.ts +19 -71
  37. package/dist/tools/assets.js +28 -22
  38. package/dist/tools/base-tool.d.ts +4 -4
  39. package/dist/tools/base-tool.js +1 -1
  40. package/dist/tools/blueprint.d.ts +45 -61
  41. package/dist/tools/blueprint.js +43 -14
  42. package/dist/tools/consolidated-tool-definitions.js +2 -1
  43. package/dist/tools/consolidated-tool-handlers.js +96 -110
  44. package/dist/tools/dynamic-handler-registry.d.ts +11 -9
  45. package/dist/tools/dynamic-handler-registry.js +17 -95
  46. package/dist/tools/editor.d.ts +19 -193
  47. package/dist/tools/editor.js +11 -2
  48. package/dist/tools/environment.d.ts +8 -14
  49. package/dist/tools/foliage.d.ts +18 -143
  50. package/dist/tools/foliage.js +4 -2
  51. package/dist/tools/handlers/actor-handlers.d.ts +1 -1
  52. package/dist/tools/handlers/actor-handlers.js +14 -13
  53. package/dist/tools/handlers/asset-handlers.js +454 -454
  54. package/dist/tools/handlers/sequence-handlers.d.ts +1 -1
  55. package/dist/tools/handlers/sequence-handlers.js +24 -13
  56. package/dist/tools/introspection.d.ts +1 -1
  57. package/dist/tools/introspection.js +1 -1
  58. package/dist/tools/landscape.d.ts +16 -116
  59. package/dist/tools/landscape.js +7 -3
  60. package/dist/tools/level.d.ts +22 -103
  61. package/dist/tools/level.js +26 -18
  62. package/dist/tools/lighting.d.ts +54 -7
  63. package/dist/tools/lighting.js +9 -5
  64. package/dist/tools/materials.d.ts +1 -1
  65. package/dist/tools/materials.js +5 -1
  66. package/dist/tools/niagara.js +37 -2
  67. package/dist/tools/performance.d.ts +0 -1
  68. package/dist/tools/performance.js +0 -1
  69. package/dist/tools/physics.js +5 -1
  70. package/dist/tools/sequence.d.ts +24 -24
  71. package/dist/tools/sequence.js +13 -0
  72. package/dist/tools/ui.d.ts +0 -2
  73. package/dist/types/automation-responses.d.ts +115 -0
  74. package/dist/types/automation-responses.js +2 -0
  75. package/dist/types/responses.d.ts +249 -0
  76. package/dist/types/responses.js +2 -0
  77. package/dist/types/tool-interfaces.d.ts +135 -135
  78. package/dist/types/tool-types.d.ts +2 -0
  79. package/dist/unreal-bridge.js +4 -4
  80. package/dist/utils/command-validator.js +7 -5
  81. package/dist/utils/error-handler.d.ts +24 -2
  82. package/dist/utils/error-handler.js +58 -23
  83. package/dist/utils/normalize.d.ts +7 -4
  84. package/dist/utils/normalize.js +12 -10
  85. package/dist/utils/path-security.d.ts +2 -0
  86. package/dist/utils/path-security.js +24 -0
  87. package/dist/utils/response-factory.d.ts +4 -4
  88. package/dist/utils/response-factory.js +15 -21
  89. package/dist/utils/response-validator.js +88 -73
  90. package/dist/utils/unreal-command-queue.d.ts +2 -0
  91. package/dist/utils/unreal-command-queue.js +8 -1
  92. package/docs/Migration-Guide-v0.5.0.md +1 -9
  93. package/docs/handler-mapping.md +4 -2
  94. package/docs/testing-guide.md +2 -2
  95. package/package.json +12 -6
  96. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +298 -33
  97. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +7 -8
  98. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +229 -319
  99. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +98 -0
  100. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +24 -0
  101. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +96 -0
  102. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +52 -5
  103. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +5 -268
  104. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +57 -2
  105. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -1
  106. package/scripts/run-all-tests.mjs +25 -20
  107. package/server.json +3 -2
  108. package/src/automation/bridge.ts +27 -25
  109. package/src/automation/connection-manager.ts +18 -0
  110. package/src/automation/message-handler.ts +33 -8
  111. package/src/automation/request-tracker.ts +39 -7
  112. package/src/config.ts +1 -1
  113. package/src/constants.ts +7 -0
  114. package/src/graphql/loaders.ts +244 -0
  115. package/src/graphql/resolvers.ts +47 -49
  116. package/src/graphql/server.ts +3 -1
  117. package/src/graphql/types.ts +3 -0
  118. package/src/index.ts +15 -2
  119. package/src/resources/assets.ts +5 -4
  120. package/src/server/tool-registry.ts +3 -3
  121. package/src/server-setup.ts +3 -37
  122. package/src/tools/actors.ts +77 -44
  123. package/src/tools/animation.ts +1 -0
  124. package/src/tools/assets.ts +76 -65
  125. package/src/tools/base-tool.ts +3 -3
  126. package/src/tools/blueprint.ts +170 -104
  127. package/src/tools/consolidated-tool-definitions.ts +2 -1
  128. package/src/tools/consolidated-tool-handlers.ts +129 -150
  129. package/src/tools/dynamic-handler-registry.ts +22 -140
  130. package/src/tools/editor.ts +43 -29
  131. package/src/tools/environment.ts +21 -27
  132. package/src/tools/foliage.ts +28 -25
  133. package/src/tools/handlers/actor-handlers.ts +16 -17
  134. package/src/tools/handlers/asset-handlers.ts +484 -484
  135. package/src/tools/handlers/sequence-handlers.ts +85 -62
  136. package/src/tools/introspection.ts +7 -7
  137. package/src/tools/landscape.ts +34 -28
  138. package/src/tools/level.ts +100 -80
  139. package/src/tools/lighting.ts +25 -20
  140. package/src/tools/materials.ts +9 -3
  141. package/src/tools/niagara.ts +44 -2
  142. package/src/tools/performance.ts +1 -2
  143. package/src/tools/physics.ts +7 -1
  144. package/src/tools/sequence.ts +42 -26
  145. package/src/tools/ui.ts +1 -3
  146. package/src/types/automation-responses.ts +119 -0
  147. package/src/types/responses.ts +355 -0
  148. package/src/types/tool-interfaces.ts +135 -135
  149. package/src/types/tool-types.ts +4 -0
  150. package/src/unreal-bridge.ts +71 -26
  151. package/src/utils/command-validator.ts +47 -5
  152. package/src/utils/error-handler.ts +128 -45
  153. package/src/utils/normalize.test.ts +162 -0
  154. package/src/utils/normalize.ts +38 -16
  155. package/src/utils/path-security.ts +43 -0
  156. package/src/utils/response-factory.ts +29 -24
  157. package/src/utils/response-validator.ts +103 -87
  158. package/src/utils/safe-json.test.ts +90 -0
  159. package/src/utils/unreal-command-queue.ts +13 -1
  160. package/src/utils/validation.test.ts +184 -0
  161. package/tests/test-animation.mjs +358 -33
  162. package/tests/test-asset-graph.mjs +311 -0
  163. package/tests/test-audio.mjs +314 -116
  164. package/tests/test-behavior-tree.mjs +327 -144
  165. package/tests/test-blueprint-graph.mjs +343 -12
  166. package/tests/test-control-editor.mjs +85 -53
  167. package/tests/test-graphql.mjs +58 -8
  168. package/tests/test-input.mjs +349 -0
  169. package/tests/test-inspect.mjs +291 -61
  170. package/tests/test-landscape.mjs +304 -48
  171. package/tests/test-lighting.mjs +428 -0
  172. package/tests/test-manage-level.mjs +70 -51
  173. package/tests/test-performance.mjs +539 -0
  174. package/tests/test-sequence.mjs +82 -46
  175. package/tests/test-system.mjs +72 -33
  176. package/tests/test-wasm.mjs +98 -8
  177. package/vitest.config.ts +35 -0
  178. package/.github/release-drafter.yml +0 -148
  179. package/dist/prompts/index.d.ts +0 -21
  180. package/dist/prompts/index.js +0 -217
  181. package/dist/tools/blueprint/helpers.d.ts +0 -29
  182. package/dist/tools/blueprint/helpers.js +0 -182
  183. package/src/prompts/index.ts +0 -249
  184. package/src/tools/blueprint/helpers.ts +0 -189
  185. package/tests/test-blueprint-events.mjs +0 -35
  186. package/tests/test-extra-tools.mjs +0 -38
  187. package/tests/test-render.mjs +0 -33
  188. package/tests/test-search-assets.mjs +0 -66
package/README.md CHANGED
@@ -6,161 +6,119 @@
6
6
  [![Unreal Engine](https://img.shields.io/badge/Unreal%20Engine-5.0--5.7-orange)](https://www.unrealengine.com/)
7
7
  [![MCP Registry](https://img.shields.io/badge/MCP%20Registry-Published-green)](https://registry.modelcontextprotocol.io/)
8
8
 
9
- A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal Engine through the native C++ Automation Bridge plugin. Built with TypeScript, C++, and Rust (WebAssembly) for ultra-high-performance game development automation.
9
+ A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal Engine through a native C++ Automation Bridge plugin. Built with TypeScript, C++, and Rust (WebAssembly).
10
10
 
11
- ## Features
11
+ ---
12
12
 
13
- ### Core Capabilities
14
- - **Asset Management** - Browse, import, and create materials
15
- - **Actor Control** - Spawn, delete, and manipulate actors with physics
16
- - **Editor Control** - PIE sessions, camera, and viewport management
17
- - **Level Management** - Load/save levels, lighting, and environment building
18
- - **Animation & Physics** - Blueprints, state machines, ragdolls, constraints, vehicle setup
19
- - **Visual Effects** - Niagara particles, GPU simulations, procedural effects
20
- - **Sequencer** - Cinematics, camera animations, and timeline control
21
- - **Graph Editing** - Blueprint, Niagara, Material, and Behavior Tree graph manipulation
22
- - **World Partition** - Load cells, manage data layers
23
- - **Render Management** - Render targets, Nanite, Lumen
24
- - **Pipeline & Testing** - Run UBT, automated tests
25
- - **Observability** - Log streaming, gameplay debugger, insights, asset queries
26
- - **Console Commands** - Safe execution with dangerous command filtering
27
- - **GraphQL API** - Flexible data querying for assets, actors, and blueprints
28
-
29
- ### High-Performance WebAssembly
30
- - **5-8x faster JSON parsing** - WASM-accelerated property parsing
31
- - **5-10x faster transform math** - Optimized 3D vector/matrix operations
32
- - **3-5x faster dependency resolution** - Rapid asset graph traversal
33
- - **Automatic fallbacks** - Works perfectly without WASM binary
34
- - **Performance monitoring** - Built-in metrics tracking
35
-
36
- ## Quick Start
13
+ ## Table of Contents
37
14
 
38
- ### Prerequisites
39
- - Node.js 18+
40
- - Unreal Engine 5.0-5.7
41
- - Required UE Plugins (enable via **Edit ▸ Plugins**):
42
- - **MCP Automation Bridge** – Native C++ WebSocket automation transport (ships inside `plugins/McpAutomationBridge`)
43
- - **Editor Scripting Utilities** – Unlocks Editor Actor/Asset subsystems for native tool operations
44
- - **Sequencer** *(built-in)* – Keep enabled for cinematic tools
45
- - **Level Sequence Editor** – Required for `manage_sequence` operations
46
- - **Control Rig** – Required for animation and physics tools
47
- - **Subobject Data Interface** – Required for Blueprint component manipulation (UE 5.7+)
48
-
49
- > 💡 After toggling any plugin, restart the editor to finalize activation. The MCP Automation Bridge provides all automation capabilities through native C++ handlers.
50
-
51
- ### Plugin feature map
52
-
53
- | Plugin | Location | Used By | Notes |
54
- |--------|----------|---------|-------|
55
- | MCP Automation Bridge | Project Plugins ▸ MCP Automation Bridge | All automation operations | Primary C++ automation transport with native handlers |
56
- | Editor Scripting Utilities | Scripting | Asset/Actor subsystem operations | Supplies Editor Actor/Asset subsystems |
57
- | Sequencer | Built-in | Sequencer tools | Ensure not disabled in project settings |
58
- | Level Sequence Editor | Animation | Sequencer tools | Required for `manage_sequence` operations |
59
- | Control Rig | Animation | Animation/Physics tools | Required for `animation_physics` operations |
60
- | Subobject Data Interface | Scripting | Blueprint tools | Required for `manage_blueprint` component operations (UE 5.7+) |
61
-
62
- > Tools such as `physics.configureVehicle` accept an optional `pluginDependencies` array so you can list the specific Unreal plugins your project relies on (for example, Chaos Vehicles or third-party vehicle frameworks). When provided, the server will verify those plugins are active before running the configuration.
63
-
64
- ### MCP Automation Bridge plugin
65
- - Location: `plugins/McpAutomationBridge`
66
- - Installation: copy the folder into your project's `Plugins/` directory and regenerate project files.
67
- - Sync helper: run `npm run automation:sync -- --engine "X:/Unreal_Engine/UE_5.6/Engine/Plugins" --project "X:/Newfolder(2)/Game/Unreal/Trial/Plugins" --clean-engine --clean-project` after repo updates to copy the latest bridge build into both plugin folders and strip legacy entries (such as `SupportedTargetPlatforms: ["Editor"]`) that trigger startup warnings.
68
- - Verification: run `node scripts/verify-automation-bridge.js --project "C:/Path/To/YourProject/Plugins" --config "C:/Path/To/YourProject/Config/DefaultEngine.ini"` to confirm the plugin files and automation bridge environment variables are in place before launching Unreal.
69
- - Configuration: enable **MCP Automation Bridge** in **Edit ▸ Plugins**, restart the editor, then set the endpoint/token under **Edit ▸ Project Settings ▸ Plugins ▸ MCP Automation Bridge**. The bridge ships with its own lightweight WebSocket client, so you no longer need the engine's WebSockets plugin enabled.
70
- - Startup: after configuration, the Output Log should show a successful connection and the `bridge_started` broadcast; `SendRawMessage` becomes available to Blueprint and C++ callers for manual testing.
71
- - Current scope: manages a WebSocket session to the Node MCP server (`ws://127.0.0.1:8091` by default), performs optional capability-token handshakes, dispatches inbound JSON to native C++ handlers, implements reconnect backoff, and responds to editor functions, property operations, blueprint actions, and more through native implementations.
72
- - Usage: all consolidated tools use the automation bridge for native C++ execution. Keep the plugin enabled for all workflows.
73
- - Diagnostics: the `ue://automation-bridge` MCP resource surfaces handshake timestamps, recent disconnects, pending automation requests, and whether the Node listener is running—handy when validating editor connectivity from a client.
74
- - Roadmap: expand the bridge with elevated actions (SCS authoring, typed property marshaling, modal mediation, asset workflows).
75
-
76
- ### WebAssembly Performance (Optional)
77
-
78
- The MCP server includes WebAssembly acceleration for computationally intensive operations. WASM is **automatically used when available** and **gracefully falls back** to pure TypeScript when the bundle or toolchain is missing.
79
-
80
- **To enable full WASM acceleration (5–8x faster operations):**
15
+ - [Features](#features)
16
+ - [Getting Started](#getting-started)
17
+ - [Configuration](#configuration)
18
+ - [Available Tools](#available-tools)
19
+ - [WebAssembly Acceleration](#webassembly-acceleration)
20
+ - [GraphQL API](#graphql-api)
21
+ - [Docker](#docker)
22
+ - [Documentation](#documentation)
23
+ - [Development](#development)
24
+ - [Contributing](#contributing)
81
25
 
82
- ```bash
83
- # 1. Install Rust toolchain and wasm-pack (once per machine)
84
- # See https://rustup.rs for installing Rust.
85
- cargo install wasm-pack
86
-
87
- # 2. Build TypeScript + WASM bundle
88
- # The build script always runs the TypeScript compiler and then
89
- # optionally builds the WASM bundle. If wasm-pack is missing the
90
- # build will succeed with a warning and the server will use
91
- # TypeScript fallbacks.
92
- npm run build
26
+ ---
93
27
 
94
- # 3. Ensure WASM is enabled (default is enabled if WASM_ENABLED is unset)
95
- # In .env or your process environment:
96
- # WASM_ENABLED=true
28
+ ## Features
97
29
 
98
- # 4. Start the server or run tests – the logs will include a
99
- # "WebAssembly module initialized successfully" message when the
100
- # bundle is present and loaded.
101
- npm start
102
- ```
30
+ | Category | Capabilities |
31
+ |----------|-------------|
32
+ | **Asset Management** | Browse, import, duplicate, rename, delete assets; create materials |
33
+ | **Actor Control** | Spawn, delete, transform, physics, tags, components |
34
+ | **Editor Control** | PIE sessions, camera, viewport, screenshots, bookmarks |
35
+ | **Level Management** | Load/save levels, streaming, World Partition, data layers |
36
+ | **Animation & Physics** | Animation BPs, state machines, ragdolls, vehicles, constraints |
37
+ | **Visual Effects** | Niagara particles, GPU simulations, procedural effects, debug shapes |
38
+ | **Sequencer** | Cinematics, timeline control, camera animations, keyframes |
39
+ | **Graph Editing** | Blueprint, Niagara, Material, and Behavior Tree graph manipulation |
40
+ | **Audio** | Sound cues, audio components, sound mixes, ambient sounds |
41
+ | **System** | Console commands, UBT, tests, logs, project settings, CVars |
103
42
 
104
- **Without WASM (still fully functional):**
43
+ ### Architecture
105
44
 
106
- ```bash
107
- # Disable WASM explicitly (optional)
108
- # In .env or environment:
109
- # WASM_ENABLED=false
45
+ - **Native C++ Automation** — All operations route through the MCP Automation Bridge plugin
46
+ - **Graceful Degradation** Server starts even without an active Unreal connection
47
+ - **On-Demand Connection** Retries automation handshakes with exponential backoff
48
+ - **Command Safety** — Blocks dangerous console commands
49
+ - **Asset Caching** — 10-second TTL for improved performance
110
50
 
111
- npm start
112
- # Server will always use TypeScript implementations only.
113
- ```
51
+ ---
114
52
 
115
- When the WASM bundle is not present or `wasm-pack` is not installed:
53
+ ## Getting Started
116
54
 
117
- - `npm run build` prints a concise message:
118
- > WASM build failed or wasm-pack missing; continuing with TypeScript-only build.
119
- - At runtime, the server attempts to load the bundle once. On `ERR_MODULE_NOT_FOUND`
120
- it logs a single warning suggesting `npm run build`/`cargo install wasm-pack` and
121
- permanently falls back to TypeScript for that process.
55
+ ### Prerequisites
122
56
 
123
- WASM acceleration applies to:
124
- - JSON property parsing (5-8x faster)
125
- - Transform calculations (5-10x faster)
126
- - Vector/matrix math (5x faster)
127
- - Asset dependency resolution (3-5x faster)
57
+ - **Node.js** 18+
58
+ - **Unreal Engine** 5.0–5.7
128
59
 
129
- ### Installation
60
+ ### Step 1: Install MCP Server
130
61
 
131
- Clone and Build
62
+ **Option A: NPX (Recommended)**
63
+ ```bash
64
+ npx unreal-engine-mcp-server
65
+ ```
132
66
 
67
+ **Option B: Clone & Build**
133
68
  ```bash
134
- # Clone the repository
135
69
  git clone https://github.com/ChiR24/Unreal_mcp.git
136
70
  cd Unreal_mcp
137
-
138
- # Install dependencies and build
139
71
  npm install
140
72
  npm run build
141
-
142
- # Run directly
143
73
  node dist/cli.js
144
74
  ```
145
75
 
146
- ### Unreal Engine Configuration
76
+ ### Step 2: Install Unreal Plugin
77
+
78
+ The MCP Automation Bridge plugin is included at `Unreal_mcp/plugins/McpAutomationBridge`.
79
+
80
+ **Method 1: Copy Folder**
81
+ ```
82
+ Copy: Unreal_mcp/plugins/McpAutomationBridge/
83
+ To: YourUnrealProject/Plugins/McpAutomationBridge/
84
+ ```
85
+ Regenerate project files after copying.
86
+
87
+ **Method 2: Add in Editor**
88
+ 1. Open Unreal Editor → **Edit → Plugins**
89
+ 2. Click **"Add"** → Browse to `Unreal_mcp/plugins/`
90
+ 3. Select the `McpAutomationBridge` folder
91
+
92
+ **Video Guide:**
93
+
94
+ https://github.com/user-attachments/assets/d8b86ebc-4364-48c9-9781-de854bf3ef7d
147
95
 
148
- No additional engine configuration required. The MCP Automation Bridge plugin handles all automation through native C++ code.
96
+ ### Step 3: Enable Required Plugins
149
97
 
150
- ## MCP Client Configuration
98
+ Enable via **Edit → Plugins**, then restart the editor:
151
99
 
152
- ### Claude Desktop / Cursor
100
+ | Plugin | Required For |
101
+ |--------|--------------|
102
+ | **MCP Automation Bridge** | All automation operations |
103
+ | **Editor Scripting Utilities** | Asset/Actor subsystem operations |
104
+ | **Sequencer** | Sequencer tools |
105
+ | **Level Sequence Editor** | `manage_sequence` operations |
106
+ | **Control Rig** | `animation_physics` operations |
107
+ | **Subobject Data Interface** | Blueprint components (UE 5.7+) |
153
108
 
154
- #### For NPM Installation (Local)
109
+ ### Step 4: Configure MCP Client
155
110
 
111
+ Add to your Claude Desktop / Cursor config file:
112
+
113
+ **Using Clone/Build:**
156
114
  ```json
157
115
  {
158
116
  "mcpServers": {
159
117
  "unreal-engine": {
160
- "command": "npx",
161
- "args": ["unreal-engine-mcp-server"],
118
+ "command": "node",
119
+ "args": ["path/to/Unreal_mcp/dist/cli.js"],
162
120
  "env": {
163
- "UE_PROJECT_PATH": "C:/Users/YourName/Documents/Unreal Projects/YourProject",
121
+ "UE_PROJECT_PATH": "C:/Path/To/YourProject",
164
122
  "MCP_AUTOMATION_PORT": "8091"
165
123
  }
166
124
  }
@@ -168,138 +126,144 @@ No additional engine configuration required. The MCP Automation Bridge plugin ha
168
126
  }
169
127
  ```
170
128
 
171
- #### For Clone/Build Installation
172
-
129
+ **Using NPX:**
173
130
  ```json
174
131
  {
175
132
  "mcpServers": {
176
133
  "unreal-engine": {
177
- "command": "node",
178
- "args": ["path/to/Unreal_mcp/dist/cli.js"],
134
+ "command": "npx",
135
+ "args": ["unreal-engine-mcp-server"],
179
136
  "env": {
180
- "UE_PROJECT_PATH": "C:/Users/YourName/Documents/Unreal Projects/YourProject",
181
- "MCP_AUTOMATION_PORT": "8091"
137
+ "UE_PROJECT_PATH": "C:/Path/To/YourProject"
182
138
  }
183
139
  }
184
140
  }
185
141
  }
186
142
  ```
187
143
 
188
- ## Available Tools (17)
144
+ ---
145
+
146
+ ## Configuration
147
+
148
+ ### Environment Variables
149
+
150
+ ```env
151
+ # Required
152
+ UE_PROJECT_PATH="C:/Path/To/YourProject"
153
+
154
+ # Automation Bridge
155
+ MCP_AUTOMATION_HOST=127.0.0.1
156
+ MCP_AUTOMATION_PORT=8091
157
+
158
+ # Logging
159
+ LOG_LEVEL=info # debug | info | warn | error
160
+
161
+ # Optional
162
+ WASM_ENABLED=true
163
+ MCP_AUTOMATION_REQUEST_TIMEOUT_MS=120000
164
+ ASSET_LIST_TTL_MS=10000
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Available Tools
189
170
 
190
171
  | Tool | Description |
191
172
  |------|-------------|
192
173
  | `manage_asset` | Assets, Materials, Render Targets, Behavior Trees |
193
- | `control_actor` | Spawn, delete, modify, physics |
194
- | `control_editor` | PIE, Camera, UI Input |
195
- | `manage_level` | Load/Save, World Partition |
196
- | `manage_lighting` | Spawn Lights, GI, Shadows, Build Lighting |
197
- | `manage_performance` | Profiling, Optimization, Scalability |
174
+ | `control_actor` | Spawn, delete, transform, physics, tags |
175
+ | `control_editor` | PIE, Camera, viewport, screenshots |
176
+ | `manage_level` | Load/Save, World Partition, streaming |
177
+ | `manage_lighting` | Spawn lights, GI, shadows, build lighting |
178
+ | `manage_performance` | Profiling, optimization, scalability |
198
179
  | `animation_physics` | Animation BPs, Vehicles, Ragdolls |
199
180
  | `manage_effect` | Niagara, Particles, Debug Shapes |
200
181
  | `manage_blueprint` | Create, SCS, Graph Editing |
201
182
  | `manage_blueprint_graph` | Direct Blueprint Graph Manipulation |
202
183
  | `build_environment` | Landscape, Foliage, Procedural |
203
184
  | `system_control` | UBT, Tests, Logs, Project Settings, CVars |
204
- | `manage_sequence` | Sequencer/Cinematics |
185
+ | `manage_sequence` | Sequencer / Cinematics |
205
186
  | `inspect` | Object Introspection |
206
187
  | `manage_audio` | Audio Assets & Components |
207
188
  | `manage_behavior_tree` | Behavior Tree Graph Editing |
208
189
  | `manage_input` | Enhanced Input Actions & Contexts |
209
190
 
191
+ ### Supported Asset Types
210
192
 
211
- ## Documentation
212
-
213
- - [Handler Mappings](docs/handler-mapping.md) - TypeScript to C++ routing guide
214
- - [GraphQL API](docs/GraphQL-API.md) - Query and mutation reference
215
- - [Automation Progress](docs/native-automation-progress.md) - Implementation status
193
+ Blueprints • Materials • Textures • Static Meshes • Skeletal Meshes • Levels • Sounds • Particles • Niagara Systems • Behavior Trees
216
194
 
217
- ## Key Features
195
+ ---
218
196
 
219
- - **Native C++ Automation** - All operations route through the MCP Automation Bridge plugin's native C++ handlers
220
- - **Graceful Degradation** - Server starts even without an active Unreal connection
221
- - **On-Demand Connection** - Retries automation handshakes with backoff instead of persistent polling
222
- - **Non-Intrusive Health Checks** - Uses echo commands every 30 seconds while connected
223
- - **Command Safety** - Blocks dangerous console commands
224
- - **Input Flexibility** - Vectors/rotators accept object or array format
225
- - **Asset Caching** - 10-second TTL for improved performance
226
- - **GraphQL** - Specialized endpoint for complex queries
197
+ ## WebAssembly Acceleration
227
198
 
228
- ### Native C++ Architecture
199
+ Optional WASM acceleration for computationally intensive operations. **Enabled by default** when available, falls back to TypeScript automatically.
229
200
 
230
- The server uses a 100% native C++ approach: all automation operations are implemented as native C++ handlers in the MCP Automation Bridge plugin (under `plugins/McpAutomationBridge/Source/`). This eliminates dependencies and provides better performance, reliability, and type safety.
201
+ | Operation | Speedup |
202
+ |-----------|---------|
203
+ | JSON parsing | 5–8x |
204
+ | Transform calculations | 5–10x |
205
+ | Vector/matrix math | 5x |
206
+ | Dependency resolution | 3–5x |
231
207
 
232
- Configuration and runtime defaults are centralized in `src/constants.ts`. All operations route through the automation bridge's WebSocket protocol to native plugin handlers.
208
+ ### Building WASM (Optional)
233
209
 
234
- ## Supported Asset Types
235
-
236
- Blueprints, Materials, Textures, Static/Skeletal Meshes, Levels, Sounds, Particles, Niagara Systems, Behavior Trees
210
+ ```bash
211
+ cargo install wasm-pack # Once per machine
212
+ npm run build # Builds TS + WASM
213
+ ```
237
214
 
238
- ## Example Console Commands
215
+ To disable: `WASM_ENABLED=false`
239
216
 
240
- - **Statistics**: `stat fps`, `stat gpu`, `stat memory`
241
- - **View Modes**: `viewmode wireframe`, `viewmode unlit`
242
- - **Gameplay**: `slomo 0.5`, `god`, `fly`
243
- - **Rendering**: `r.screenpercentage 50`, `r.vsync 0`
217
+ ---
244
218
 
245
- ### Configuration
219
+ ## GraphQL API
246
220
 
247
- ### Environment Variables
221
+ Optional GraphQL endpoint for complex queries. **Disabled by default.**
248
222
 
249
223
  ```env
250
- UE_PROJECT_PATH="C:/Users/YourName/Documents/Unreal Projects/YourProject" # Absolute path to your .uproject file
251
- LOG_LEVEL=info # debug | info | warn | error
252
-
253
- # Automation bridge WebSocket client (Node -> Unreal editor)
254
- MCP_AUTOMATION_HOST=127.0.0.1 # Host/interface for the automation bridge connection
255
- MCP_AUTOMATION_PORT=8091 # Primary bridge port (must match the plugin's port)
256
- MCP_AUTOMATION_CLIENT_MODE=true # Set to false to disable the automation bridge client
257
- MCP_AUTOMATION_CAPABILITY_TOKEN= # Optional capability token for handshake security
258
-
259
- # Legacy/Alternative variables
260
- # MCP_AUTOMATION_WS_PORT=8090 # Fallback port if MCP_AUTOMATION_PORT is unset
261
- # MCP_AUTOMATION_BRIDGE_ENABLED=true # Legacy alias for MCP_AUTOMATION_CLIENT_MODE
262
-
263
- # WebAssembly acceleration
264
- WASM_ENABLED=true # Default: enabled if unset; set false to force TS-only
265
- # Optional override when hosting the WASM bundle elsewhere:
266
- # WASM_PATH=file:///absolute/path/to/unreal_mcp_wasm.js
267
-
268
- # Timeouts / caching (advanced – safe defaults are baked in)
269
- MCP_AUTOMATION_REQUEST_TIMEOUT_MS=120000
270
- MCP_AUTOMATION_EVENT_TIMEOUT_MS=0
271
- ASSET_LIST_TTL_MS=10000
224
+ GRAPHQL_ENABLED=true
225
+ GRAPHQL_PORT=4000
272
226
  ```
273
227
 
274
- Note on configuration precedence
275
- - The server uses `dotenv` to load `.env` for local development. A `.env.production` file is included as a reference for production deployments; copy values into your real environment or secret store as appropriate.
276
- - Environment variables (.env / system env) override the internal runtime defaults (for example, defaults in `src/index.ts`, `src/automation-bridge.ts`, and individual tool implementations). This lets you tune timeouts, logging, and WASM behavior without modifying source code. Keep secrets in `.env` or a secret manager — do not store secrets in source files.
228
+ See [GraphQL API Documentation](docs/GraphQL-API.md).
277
229
 
278
- Mock mode
230
+ ---
279
231
 
280
-
281
- ### Docker
232
+ ## Docker
282
233
 
283
234
  ```bash
284
235
  docker build -t unreal-mcp .
285
- docker run -it --rm unreal-mcp
236
+ docker run -it --rm -e UE_PROJECT_PATH=/project unreal-mcp
286
237
  ```
287
238
 
288
- Pull from Docker Hub
239
+ ---
289
240
 
290
- ```bash
291
- docker pull mcp/server/unreal-engine-mcp-server:latest
292
- docker run --rm -it mcp/server/unreal-engine-mcp-server:latest
293
- ```
241
+ ## Documentation
242
+
243
+ | Document | Description |
244
+ |----------|-------------|
245
+ | [Handler Mappings](docs/handler-mapping.md) | TypeScript to C++ routing |
246
+ | [GraphQL API](docs/GraphQL-API.md) | Query and mutation reference |
247
+ | [WebAssembly Integration](docs/WebAssembly-Integration.md) | WASM performance guide |
248
+ | [Plugin Extension](docs/editor-plugin-extension.md) | C++ plugin architecture |
249
+ | [Testing Guide](docs/testing-guide.md) | How to run and write tests |
250
+ | [Migration Guide v0.5.0](docs/Migration-Guide-v0.5.0.md) | Upgrade to v0.5.0 |
251
+ | [Roadmap](docs/Roadmap.md) | Development phases |
252
+ | [Automation Progress](docs/native-automation-progress.md) | Implementation status |
253
+
254
+ ---
294
255
 
295
256
  ## Development
296
257
 
297
258
  ```bash
298
- npm run build # Build TypeScript and (optionally) the WebAssembly bundle
299
- npm run lint # Run ESLint
300
- npm run lint:fix # Fix linting issues
259
+ npm run build # Build TypeScript + WASM
260
+ npm run lint # Run ESLint
261
+ npm run test:unit # Run unit tests
262
+ npm run test:all # Run all tests
301
263
  ```
302
264
 
265
+ ---
266
+
303
267
  ## Contributing
304
268
 
305
269
  Contributions welcome! Please:
@@ -307,6 +271,8 @@ Contributions welcome! Please:
307
271
  - Keep PRs focused and small
308
272
  - Follow existing code style
309
273
 
274
+ ---
275
+
310
276
  ## License
311
277
 
312
- MIT - See [LICENSE](LICENSE) file
278
+ MIT See [LICENSE](LICENSE)
@@ -24,9 +24,9 @@ export declare class AutomationBridge extends EventEmitter {
24
24
  private lastHandshakeFailure?;
25
25
  private lastDisconnect?;
26
26
  private lastError?;
27
- private requestQueue;
28
27
  private queuedRequestItems;
29
28
  private connectionPromise?;
29
+ private connectionLock;
30
30
  constructor(options?: AutomationBridgeOptions);
31
31
  on<K extends keyof AutomationBridgeEvents>(event: K, listener: AutomationBridgeEvents[K]): this;
32
32
  once<K extends keyof AutomationBridgeEvents>(event: K, listener: AutomationBridgeEvents[K]): this;
@@ -44,7 +44,6 @@ export declare class AutomationBridge extends EventEmitter {
44
44
  private processRequestQueue;
45
45
  send(payload: AutomationBridgeMessage): boolean;
46
46
  private broadcast;
47
- private flushQueue;
48
47
  private emitAutomation;
49
48
  }
50
49
  //# sourceMappingURL=bridge.d.ts.map
@@ -42,9 +42,9 @@ export class AutomationBridge extends EventEmitter {
42
42
  lastHandshakeFailure;
43
43
  lastDisconnect;
44
44
  lastError;
45
- requestQueue = [];
46
45
  queuedRequestItems = [];
47
46
  connectionPromise;
47
+ connectionLock = false;
48
48
  constructor(options = {}) {
49
49
  super();
50
50
  this.host = options.host ?? process.env.MCP_AUTOMATION_WS_HOST ?? DEFAULT_AUTOMATION_HOST;
@@ -162,12 +162,12 @@ export class AutomationBridge extends EventEmitter {
162
162
  this.lastHandshakeMetadata = metadata;
163
163
  this.lastHandshakeFailure = undefined;
164
164
  this.connectionManager.updateLastMessageTime();
165
- const underlying = socket._socket || socket.socket;
165
+ const socketWithInternal = socket;
166
+ const underlying = socketWithInternal._socket || socketWithInternal.socket;
166
167
  const remoteAddr = underlying?.remoteAddress ?? undefined;
167
168
  const remotePort = underlying?.remotePort ?? undefined;
168
169
  this.connectionManager.registerSocket(socket, this.clientPort, metadata, remoteAddr, remotePort);
169
170
  this.connectionManager.startHeartbeat();
170
- this.flushQueue();
171
171
  this.emitAutomation('connected', {
172
172
  socket,
173
173
  metadata,
@@ -273,7 +273,7 @@ export class AutomationBridge extends EventEmitter {
273
273
  ? { message: this.lastError.message, at: this.lastError.at.toISOString() }
274
274
  : null,
275
275
  lastMessageAt: this.connectionManager.getLastMessageTime()?.toISOString() ?? null,
276
- lastRequestSentAt: null,
276
+ lastRequestSentAt: this.requestTracker.getLastRequestSentAt()?.toISOString() ?? null,
277
277
  pendingRequests: this.requestTracker.getPendingCount(),
278
278
  pendingRequestDetails: this.requestTracker.getPendingDetails(),
279
279
  connections: connectionInfos,
@@ -282,15 +282,16 @@ export class AutomationBridge extends EventEmitter {
282
282
  serverName: this.serverName,
283
283
  serverVersion: this.serverVersion,
284
284
  maxConcurrentConnections: this.maxConcurrentConnections,
285
- maxPendingRequests: 100,
286
- heartbeatIntervalMs: 30000
285
+ maxPendingRequests: this.requestTracker.getMaxPendingRequests(),
286
+ heartbeatIntervalMs: this.connectionManager.getHeartbeatIntervalMs()
287
287
  };
288
288
  }
289
289
  async sendAutomationRequest(action, payload = {}, options = {}) {
290
290
  if (!this.isConnected()) {
291
291
  if (this.enabled) {
292
292
  this.log.info('Automation bridge not connected, attempting lazy connection...');
293
- if (!this.connectionPromise) {
293
+ if (!this.connectionPromise && !this.connectionLock) {
294
+ this.connectionLock = true;
294
295
  this.connectionPromise = new Promise((resolve, reject) => {
295
296
  const onConnect = () => {
296
297
  cleanup();
@@ -308,8 +309,8 @@ export class AutomationBridge extends EventEmitter {
308
309
  this.off('connected', onConnect);
309
310
  this.off('error', onError);
310
311
  this.off('handshakeFailed', onHandshakeFail);
311
- if (this.connectionPromise)
312
- this.connectionPromise = undefined;
312
+ this.connectionLock = false;
313
+ this.connectionPromise = undefined;
313
314
  };
314
315
  this.once('connected', onConnect);
315
316
  this.once('error', onError);
@@ -324,10 +325,17 @@ export class AutomationBridge extends EventEmitter {
324
325
  }
325
326
  try {
326
327
  const connectTimeout = 5000;
327
- await Promise.race([
328
- this.connectionPromise,
329
- new Promise((_, reject) => setTimeout(() => reject(new Error('Lazy connection timeout')), connectTimeout))
330
- ]);
328
+ let timeoutId;
329
+ const timeoutPromise = new Promise((_, reject) => {
330
+ timeoutId = setTimeout(() => reject(new Error('Lazy connection timeout')), connectTimeout);
331
+ });
332
+ try {
333
+ await Promise.race([this.connectionPromise, timeoutPromise]);
334
+ }
335
+ finally {
336
+ if (timeoutId)
337
+ clearTimeout(timeoutId);
338
+ }
331
339
  }
332
340
  catch (err) {
333
341
  this.log.error('Lazy connection failed', err);
@@ -341,7 +349,7 @@ export class AutomationBridge extends EventEmitter {
341
349
  if (!this.isConnected()) {
342
350
  throw new Error('Automation bridge not connected');
343
351
  }
344
- if (this.requestTracker.getPendingCount() >= this.requestTracker.maxPendingRequests) {
352
+ if (this.requestTracker.getPendingCount() >= this.requestTracker.getMaxPendingRequests()) {
345
353
  return new Promise((resolve, reject) => {
346
354
  this.queuedRequestItems.push({
347
355
  resolve,
@@ -378,6 +386,7 @@ export class AutomationBridge extends EventEmitter {
378
386
  this.processRequestQueue();
379
387
  }).catch(() => { });
380
388
  if (this.send(message)) {
389
+ this.requestTracker.updateLastRequestSentAt();
381
390
  return resultPromise;
382
391
  }
383
392
  else {
@@ -389,7 +398,7 @@ export class AutomationBridge extends EventEmitter {
389
398
  if (this.queuedRequestItems.length === 0)
390
399
  return;
391
400
  while (this.queuedRequestItems.length > 0 &&
392
- this.requestTracker.getPendingCount() < this.requestTracker.maxPendingRequests) {
401
+ this.requestTracker.getPendingCount() < this.requestTracker.getMaxPendingRequests()) {
393
402
  const item = this.queuedRequestItems.shift();
394
403
  if (item) {
395
404
  this.sendRequestInternal(item.action, item.payload, item.options)
@@ -437,14 +446,6 @@ export class AutomationBridge extends EventEmitter {
437
446
  }
438
447
  return sentCount > 0;
439
448
  }
440
- flushQueue() {
441
- if (this.requestQueue.length === 0)
442
- return;
443
- this.log.info(`Flushing ${this.requestQueue.length} queued automation requests`);
444
- const queue = [...this.requestQueue];
445
- this.requestQueue = [];
446
- queue.forEach(fn => fn());
447
- }
448
449
  emitAutomation(event, ...args) {
449
450
  this.emit(event, ...args);
450
451
  }
@@ -9,6 +9,7 @@ export declare class ConnectionManager extends EventEmitter {
9
9
  private lastMessageAt?;
10
10
  private log;
11
11
  constructor(heartbeatIntervalMs: number);
12
+ getHeartbeatIntervalMs(): number;
12
13
  registerSocket(socket: WebSocket, port: number, metadata?: Record<string, unknown>, remoteAddress?: string, remotePort?: number): void;
13
14
  removeSocket(socket: WebSocket): SocketInfo | undefined;
14
15
  getActiveSockets(): Map<WebSocket, SocketInfo>;
@@ -13,6 +13,9 @@ export class ConnectionManager extends EventEmitter {
13
13
  super();
14
14
  this.heartbeatIntervalMs = heartbeatIntervalMs;
15
15
  }
16
+ getHeartbeatIntervalMs() {
17
+ return this.heartbeatIntervalMs;
18
+ }
16
19
  registerSocket(socket, port, metadata, remoteAddress, remotePort) {
17
20
  const connectionId = randomUUID();
18
21
  const sessionId = metadata && typeof metadata.sessionId === 'string' ? metadata.sessionId : undefined;
@@ -32,6 +35,13 @@ export class ConnectionManager extends EventEmitter {
32
35
  socket.on('pong', () => {
33
36
  this.lastMessageAt = new Date();
34
37
  });
38
+ socket.once('close', () => {
39
+ this.removeSocket(socket);
40
+ });
41
+ socket.once('error', (error) => {
42
+ this.log.error('Socket error in ConnectionManager', error);
43
+ this.removeSocket(socket);
44
+ });
35
45
  }
36
46
  removeSocket(socket) {
37
47
  const info = this.activeSockets.get(socket);