flockbay 0.10.15

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 (80) hide show
  1. package/README.md +56 -0
  2. package/bin/flockbay-mcp.mjs +56 -0
  3. package/bin/flockbay.mjs +78 -0
  4. package/dist/codex/flockbayMcpStdioBridge.cjs +383 -0
  5. package/dist/codex/flockbayMcpStdioBridge.d.cts +2 -0
  6. package/dist/codex/flockbayMcpStdioBridge.d.mts +2 -0
  7. package/dist/codex/flockbayMcpStdioBridge.mjs +381 -0
  8. package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +136 -0
  9. package/dist/flockbayScreenshotGate-DkxU24cR.cjs +138 -0
  10. package/dist/index--o4BPz5o.cjs +10311 -0
  11. package/dist/index-CUp3juDS.mjs +10268 -0
  12. package/dist/index.cjs +43 -0
  13. package/dist/index.d.cts +1 -0
  14. package/dist/index.d.mts +1 -0
  15. package/dist/index.mjs +40 -0
  16. package/dist/lib.cjs +33 -0
  17. package/dist/lib.d.cts +957 -0
  18. package/dist/lib.d.mts +957 -0
  19. package/dist/lib.mjs +23 -0
  20. package/dist/runCodex-D3eT-TvB.cjs +3449 -0
  21. package/dist/runCodex-o6PCbHQ7.mjs +3446 -0
  22. package/dist/runGemini-Bt0oEj_g.mjs +3183 -0
  23. package/dist/runGemini-CBxZp6I7.cjs +3185 -0
  24. package/dist/types-C-jnUdn_.cjs +4498 -0
  25. package/dist/types-DGd6ea2Z.mjs +4450 -0
  26. package/kits/kit.open_world/kit.json +59 -0
  27. package/package.json +130 -0
  28. package/scripts/claude_local_launcher.cjs +73 -0
  29. package/scripts/claude_remote_launcher.cjs +16 -0
  30. package/scripts/claude_version_utils.cjs +391 -0
  31. package/scripts/ripgrep_launcher.cjs +33 -0
  32. package/scripts/session_hook_forwarder.cjs +49 -0
  33. package/scripts/test-codex-abort-history.mjs +77 -0
  34. package/scripts/unpack-tools.cjs +222 -0
  35. package/tools/licenses/difftastic-LICENSE +21 -0
  36. package/tools/licenses/ripgrep-LICENSE +3 -0
  37. package/tools/unreal-mcp/UPSTREAM_VERSION.md +8 -0
  38. package/tools/unreal-mcp/upstream/Docs/README.md +8 -0
  39. package/tools/unreal-mcp/upstream/Docs/Tools/README.md +7 -0
  40. package/tools/unreal-mcp/upstream/Docs/Tools/actor_tools.md +184 -0
  41. package/tools/unreal-mcp/upstream/Docs/Tools/blueprint_tools.md +268 -0
  42. package/tools/unreal-mcp/upstream/Docs/Tools/editor_tools.md +104 -0
  43. package/tools/unreal-mcp/upstream/Docs/Tools/node_tools.md +274 -0
  44. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Config/FilterPlugin.ini +8 -0
  45. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +1160 -0
  46. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +924 -0
  47. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +709 -0
  48. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +896 -0
  49. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPProjectCommands.cpp +72 -0
  50. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPUMGCommands.cpp +544 -0
  51. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +321 -0
  52. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +419 -0
  53. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPModule.cpp +21 -0
  54. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +34 -0
  55. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +27 -0
  56. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommonUtils.h +59 -0
  57. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +40 -0
  58. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPProjectCommands.h +20 -0
  59. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPUMGCommands.h +82 -0
  60. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/MCPServerRunnable.h +34 -0
  61. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPBridge.h +64 -0
  62. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPModule.h +22 -0
  63. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +78 -0
  64. package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/UnrealMCP.uplugin +36 -0
  65. package/tools/unreal-mcp/upstream/Python/README.md +40 -0
  66. package/tools/unreal-mcp/upstream/Python/pyproject.toml +22 -0
  67. package/tools/unreal-mcp/upstream/Python/scripts/actors/test_cube.py +203 -0
  68. package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_blueprints_with_different_components.py +497 -0
  69. package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_cube_blueprint.py +194 -0
  70. package/tools/unreal-mcp/upstream/Python/scripts/node/test_component_reference.py +267 -0
  71. package/tools/unreal-mcp/upstream/Python/scripts/node/test_create_bird_blueprint_with_input_and_camera.py +618 -0
  72. package/tools/unreal-mcp/upstream/Python/scripts/node/test_input_mapping.py +366 -0
  73. package/tools/unreal-mcp/upstream/Python/scripts/node/test_physics_variables.py +390 -0
  74. package/tools/unreal-mcp/upstream/Python/tools/blueprint_tools.py +420 -0
  75. package/tools/unreal-mcp/upstream/Python/tools/editor_tools.py +369 -0
  76. package/tools/unreal-mcp/upstream/Python/tools/node_tools.py +430 -0
  77. package/tools/unreal-mcp/upstream/Python/tools/project_tools.py +64 -0
  78. package/tools/unreal-mcp/upstream/Python/tools/umg_tools.py +333 -0
  79. package/tools/unreal-mcp/upstream/Python/unreal_mcp_server.py +398 -0
  80. package/tools/unreal-mcp/upstream/Python/uv.lock +521 -0
@@ -0,0 +1,618 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Test script for blueprint node tools via MCP.
4
+ This script creates a simple flapping bird Blueprint with basic physics and input handling.
5
+
6
+ Commands used:
7
+ 1. create_blueprint - Creates a new Blueprint class inheriting from Pawn
8
+ 2. add_component_to_blueprint - Adds a StaticMeshComponent named "BirdMesh"
9
+ 3. set_physics_properties - Configures physics properties for the mesh
10
+ 4. add_blueprint_variable - Adds a Float variable "FlapStrength"
11
+ 5. set_static_mesh_properties - Sets the mesh to a sphere
12
+ 6. create_input_mapping - Creates a "Flap" action mapped to SpaceBar
13
+ 7. find_blueprint_nodes - Searches for existing nodes (e.g., BeginPlay)
14
+ 8. add_blueprint_event_node - Creates event nodes (BeginPlay)
15
+ 9. add_blueprint_input_action_node - Creates input action node for Flap
16
+ 10. add_blueprint_get_self_component_reference - Creates component reference node
17
+ 11. add_blueprint_function_node - Creates function nodes (AddImpulse, GetActorOfClass, etc.)
18
+ 12. connect_blueprint_nodes - Connects nodes together
19
+ 13. compile_blueprint - Compiles the Blueprint
20
+ 14. set_pawn_properties - Sets auto-possess properties
21
+ 15. spawn_blueprint_actor - Spawns the bird in the level
22
+ 16. create_actor - Creates a camera actor
23
+
24
+ Blueprint Graph Layout:
25
+ ```
26
+ [BeginPlay] ──────┐
27
+
28
+ [InputAction] ───┼─── [BirdMesh] ─── [AddImpulse]
29
+
30
+ [GetActorOfClass] ─── [SetViewTargetWithBlend]
31
+
32
+ └── [GetPlayerController]
33
+ ```
34
+
35
+ Node Positions:
36
+ - BeginPlay: [-400, 0]
37
+ - InputAction: [-400, 300]
38
+ - BirdMesh: [0, 300]
39
+ - AddImpulse: [400, 300]
40
+ - GetActorOfClass: [0, -200]
41
+ - SetViewTargetWithBlend: [400, -200]
42
+ - GetPlayerController: [0, -100]
43
+
44
+ Connections:
45
+ 1. InputAction.Pressed -> AddImpulse.Execute
46
+ 2. BirdMesh -> AddImpulse.self
47
+ 3. BeginPlay.Then -> GetActorOfClass.Execute
48
+ 4. GetActorOfClass.Then -> SetViewTargetWithBlend.Execute
49
+ 5. GetActorOfClass.ReturnValue -> SetViewTargetWithBlend.NewViewTarget
50
+ 6. GetPlayerController.ReturnValue -> SetViewTargetWithBlend.self
51
+ """
52
+
53
+ import sys
54
+ import os
55
+ import time
56
+ import socket
57
+ import json
58
+ import logging
59
+ from typing import Dict, Any, Optional
60
+
61
+ # Add the parent directory to the path so we can import the server module
62
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
63
+
64
+ # Set up logging
65
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
66
+ logger = logging.getLogger("TestBlueprintNodes")
67
+
68
+ def send_command(sock: socket.socket, command: str, params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
69
+ """Send a command to the Unreal MCP server and get the response."""
70
+ try:
71
+ # Create command object
72
+ command_obj = {
73
+ "type": command,
74
+ "params": params
75
+ }
76
+
77
+ # Convert to JSON and send
78
+ command_json = json.dumps(command_obj)
79
+ logger.info(f"Sending command: {command_json}")
80
+ sock.sendall(command_json.encode('utf-8'))
81
+
82
+ # Receive response
83
+ chunks = []
84
+ while True:
85
+ chunk = sock.recv(4096)
86
+ if not chunk:
87
+ break
88
+ chunks.append(chunk)
89
+
90
+ # Try parsing to see if we have a complete response
91
+ try:
92
+ data = b''.join(chunks)
93
+ json.loads(data.decode('utf-8'))
94
+ # If we can parse it, we have the complete response
95
+ break
96
+ except json.JSONDecodeError:
97
+ # Not a complete JSON object yet, continue receiving
98
+ continue
99
+
100
+ # Parse response
101
+ data = b''.join(chunks)
102
+ response = json.loads(data.decode('utf-8'))
103
+ logger.info(f"Received response: {response}")
104
+ return response
105
+
106
+ except Exception as e:
107
+ logger.error(f"Error sending command: {e}")
108
+ return None
109
+
110
+ def send_mcp_command(command: str, params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
111
+ """Send a command to the Unreal MCP server with automatic socket lifecycle management."""
112
+ sock = None
113
+ try:
114
+ # Create a new socket for each command
115
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
116
+ sock.connect(("127.0.0.1", 55557))
117
+
118
+ # Send the command and get the response
119
+ return send_command(sock, command, params)
120
+
121
+ except Exception as e:
122
+ logger.error(f"Error in socket communication: {e}")
123
+ return None
124
+ finally:
125
+ # Always close the socket when done
126
+ if sock:
127
+ sock.close()
128
+
129
+ def main():
130
+ """Main function to test blueprint node tools."""
131
+ try:
132
+ # Step 1: Create a blueprint for the bird
133
+ bp_params = {
134
+ "name": "BirdBP",
135
+ "parent_class": "Pawn"
136
+ }
137
+
138
+ response = send_mcp_command("create_blueprint", bp_params)
139
+
140
+ if not response or response.get("status") != "success":
141
+ logger.error(f"Failed to create blueprint: {response}")
142
+ return
143
+
144
+ # Check if blueprint already existed
145
+ if response.get("result", {}).get("already_exists"):
146
+ logger.info(f"Blueprint 'BirdBP' already exists, reusing it")
147
+ else:
148
+ logger.info("Blueprint created successfully!")
149
+
150
+ # Step 2: Add a static mesh component
151
+ component_params = {
152
+ "blueprint_name": "BirdBP",
153
+ "component_type": "StaticMeshComponent",
154
+ "component_name": "BirdMesh",
155
+ "location": [0.0, 0.0, 0.0],
156
+ "rotation": [0.0, 0.0, 0.0],
157
+ "scale": [0.5, 0.5, 0.5] # Smaller bird
158
+ }
159
+
160
+ response = send_mcp_command("add_component_to_blueprint", component_params)
161
+
162
+ if not response or response.get("status") != "success":
163
+ logger.error(f"Failed to add component: {response}")
164
+ return
165
+
166
+ logger.info("Bird mesh component added successfully!")
167
+
168
+ # Step 3: Add physics properties to the mesh
169
+ physics_params = {
170
+ "blueprint_name": "BirdBP",
171
+ "component_name": "BirdMesh",
172
+ "simulate_physics": True,
173
+ "gravity_enabled": True,
174
+ "mass": 2.0, # Light bird
175
+ "linear_damping": 0.5, # Some air resistance
176
+ "angular_damping": 0.5 # Prevent too much spinning
177
+ }
178
+
179
+ response = send_mcp_command("set_physics_properties", physics_params)
180
+
181
+ if not response or response.get("status") != "success":
182
+ logger.error(f"Failed to set physics properties: {response}")
183
+ return
184
+
185
+ logger.info("Physics properties set successfully!")
186
+
187
+ # Step 4: Add variables for tracking bird state
188
+ response = send_mcp_command("add_blueprint_variable", {
189
+ "blueprint_name": "BirdBP",
190
+ "variable_name": "FlapStrength",
191
+ "variable_type": "Float",
192
+ "default_value": 500.0,
193
+ "is_exposed": True
194
+ })
195
+
196
+ if not response or response.get("status") != "success":
197
+ logger.error(f"Failed to add variable: {response}")
198
+ return
199
+
200
+ logger.info("FlapStrength variable added successfully!")
201
+
202
+ # Step 4b: Set the static mesh of the BirdMesh component to a sphere
203
+ response = send_mcp_command("set_static_mesh_properties", {
204
+ "blueprint_name": "BirdBP",
205
+ "component_name": "BirdMesh",
206
+ "static_mesh": "/Engine/BasicShapes/Sphere.Sphere"
207
+ })
208
+
209
+ if not response or response.get("status") != "success":
210
+ logger.error(f"Failed to set static mesh: {response}")
211
+ return
212
+
213
+ logger.info("Setting Static Mesh Component of Bird to sphere successfully!")
214
+
215
+ # Step 5: Create input mapping for flap action
216
+ response = send_mcp_command("create_input_mapping", {
217
+ "action_name": "Flap",
218
+ "key": "SpaceBar",
219
+ "input_type": "Action"
220
+ })
221
+
222
+ if not response or response.get("status") != "success":
223
+ logger.error(f"Failed to create input mapping: {response}")
224
+ return
225
+
226
+ logger.info("Flap input mapping created successfully!")
227
+
228
+ # Step 6: Create BeginPlay event node - check if it exists first
229
+ begin_play_response = None
230
+
231
+ # First try to find existing BeginPlay nodes
232
+ find_begin_play_params = {
233
+ "blueprint_name": "BirdBP",
234
+ "node_type": "Event",
235
+ "event_name": "ReceiveBeginPlay" # Use the exact Unreal Engine event name
236
+ }
237
+
238
+ response = send_mcp_command("find_blueprint_nodes", find_begin_play_params)
239
+
240
+ if response and response.get("status") == "success":
241
+ # Look for BeginPlay nodes in the response
242
+ nodes = response.get("result", {}).get("node_guids", [])
243
+ if nodes:
244
+ logger.info(f"Found existing ReceiveBeginPlay node, reusing it")
245
+ # Use the first BeginPlay node we find
246
+ begin_play_node_id = nodes[0]
247
+ begin_play_response = {"result": {"success": True, "node_id": begin_play_node_id}}
248
+
249
+ # Only create a new BeginPlay node if we didn't find one
250
+ if begin_play_response is None:
251
+ begin_play_params = {
252
+ "blueprint_name": "BirdBP",
253
+ "event_name": "ReceiveBeginPlay",
254
+ "node_position": [-400, 0] # Move BeginPlay further left
255
+ }
256
+
257
+ response = send_mcp_command("add_blueprint_event_node", begin_play_params)
258
+
259
+ if not response or response.get("status") != "success":
260
+ logger.error(f"Failed to add ReceiveBeginPlay event node: {response}")
261
+ return
262
+
263
+ logger.info("ReceiveBeginPlay event node added successfully!")
264
+
265
+ # Save the node ID for later connections
266
+ begin_play_node_id = begin_play_response.get("result", {}).get("node_id")
267
+
268
+ # Step 7: Create input action event node
269
+ input_action_params = {
270
+ "blueprint_name": "BirdBP",
271
+ "action_name": "Flap",
272
+ "node_position": [-400, 300] # Move input action down and left
273
+ }
274
+
275
+ # Create the InputAction event node using the dedicated function
276
+ response = send_mcp_command("add_blueprint_input_action_node", input_action_params)
277
+
278
+ if not response or response.get("status") != "success":
279
+ logger.error(f"Failed to add Input action node: {response}")
280
+ return
281
+
282
+ logger.info("Input action node added successfully")
283
+
284
+ # Save the node ID for later connections
285
+ input_node_id = response.get("result", {}).get("node_id")
286
+
287
+ # Step 8: Add a get component reference node for BirdMesh
288
+ get_component_params = {
289
+ "blueprint_name": "BirdBP",
290
+ "component_name": "BirdMesh",
291
+ "node_position": [0, 300] # Center the component reference
292
+ }
293
+
294
+ response = send_mcp_command("add_blueprint_get_self_component_reference", get_component_params)
295
+
296
+ if not response or response.get("status") != "success":
297
+ logger.error(f"Failed to add component reference node: {response}")
298
+ return
299
+
300
+ get_component_node_id = response.get("result", {}).get("node_id")
301
+
302
+ # Step 9: Add function node to apply impulse on flap
303
+ function_params = {
304
+ "blueprint_name": "BirdBP",
305
+ "function_name": "AddImpulse",
306
+ "target": "UPrimitiveComponent",
307
+ "params": {
308
+ "Impulse": [0, 0, 1000]
309
+ },
310
+ "node_position": [400, 300] # Move AddImpulse to the right
311
+ }
312
+
313
+ response = send_mcp_command("add_blueprint_function_node", function_params)
314
+
315
+ if not response or response.get("status") != "success":
316
+ logger.error(f"Failed to add AddImpulse function node: {response}")
317
+ # If UPrimitiveComponent fails, try alternatives
318
+ targets_to_try = ["PrimitiveComponent", "SceneComponent", "USceneComponent"]
319
+
320
+ for target in targets_to_try:
321
+ logger.info(f"Trying alternative class for AddImpulse: {target}")
322
+ function_params["target"] = target
323
+
324
+ response = send_mcp_command("add_blueprint_function_node", function_params)
325
+ if response and response.get("status") == "success":
326
+ logger.info(f"Successfully added AddImpulse using target class: {target}")
327
+ break
328
+ else:
329
+ logger.error("All attempts to add AddImpulse function failed")
330
+ return
331
+
332
+ logger.info("AddImpulse function node added successfully!")
333
+
334
+ # Save the node ID for later connections
335
+ add_impulse_node_id = response.get("result", {}).get("node_id")
336
+
337
+ # Step 10: Connect input event to add impulse function
338
+ connect_params = {
339
+ "blueprint_name": "BirdBP",
340
+ "source_node_id": input_node_id,
341
+ "source_pin": "Pressed", # Execute pin on input action event node
342
+ "target_node_id": add_impulse_node_id,
343
+ "target_pin": "Execute" # Execute pin on function node
344
+ }
345
+
346
+ response = send_mcp_command("connect_blueprint_nodes", connect_params)
347
+
348
+ if not response or response.get("status") != "success":
349
+ logger.error(f"Failed to connect nodes: {response}")
350
+ return
351
+
352
+ logger.info("Input node connected to AddImpulse successfully!")
353
+
354
+ # Step 11: Connect get component to add impulse function (target connection)
355
+ connect_target_params = {
356
+ "blueprint_name": "BirdBP",
357
+ "source_node_id": get_component_node_id,
358
+ "source_pin": "BirdMesh", # Use component name as the output pin name (UE5.5 convention)
359
+ "target_node_id": add_impulse_node_id,
360
+ "target_pin": "self" # Change from "Target" to "self" - this is the actual pin name in UE5.5
361
+ }
362
+
363
+ response = send_mcp_command("connect_blueprint_nodes", connect_target_params)
364
+
365
+ if not response or response.get("status") != "success":
366
+ logger.error(f"Failed to connect component to target pin: {response}")
367
+ return
368
+
369
+ logger.info("Component target connected successfully!")
370
+
371
+ # Step 12: Compile the blueprint
372
+ response = send_mcp_command("compile_blueprint", {
373
+ "blueprint_name": "BirdBP"
374
+ })
375
+
376
+ if not response or response.get("status") != "success":
377
+ logger.error(f"Failed to compile blueprint: {response}")
378
+ return
379
+
380
+ logger.info("Blueprint compiled successfully!")
381
+
382
+ # Step 13: Set pawn properties using the new utility function
383
+ response = send_mcp_command("set_pawn_properties", {
384
+ "blueprint_name": "BirdBP",
385
+ "auto_possess_player": "Player0" # Use short enum name as per reflection docs
386
+ })
387
+
388
+ if not response or response.get("status") != "success":
389
+ logger.error(f"Failed to set pawn properties: {response}")
390
+ return
391
+
392
+ logger.info("Pawn properties set successfully!")
393
+
394
+ # Step 14: Add GetActorOfClass node to BirdBP's BeginPlay
395
+ # Note: In UE5.5, class references must use the full path format: /Script/ModuleName.ClassName
396
+ # This format is the standard way Unreal Engine references classes internally:
397
+ # - /Script/ prefix indicates this is a C++ (native) class
398
+ # - ModuleName is the module where the class is defined (e.g., Engine, Game)
399
+ # - ClassName is the actual class name
400
+ # Examples:
401
+ # - /Script/Engine.CameraActor for the camera actor class
402
+ # - /Script/Engine.PlayerController for the player controller class
403
+ get_camera_params = {
404
+ "blueprint_name": "BirdBP",
405
+ "function_name": "GetActorOfClass",
406
+ "target": "UGameplayStatics",
407
+ "params": {
408
+ "ActorClass": "/Script/Engine.CameraActor"
409
+ },
410
+ "node_position": [0, -200] # Move camera setup nodes down
411
+ }
412
+
413
+ response = send_mcp_command("add_blueprint_function_node", get_camera_params)
414
+
415
+ if not response or response.get("status") != "success":
416
+ logger.error(f"Failed to add GetActorOfClass node: {response}")
417
+ return
418
+
419
+ logger.info("GetActorOfClass node added successfully!")
420
+ get_camera_node_id = response.get("result", {}).get("node_id")
421
+
422
+ # Step 15 (formerly 17): Add SetViewTargetWithBlend node
423
+ # Add SetViewTargetWithBlend function node
424
+ set_view_params = {
425
+ "blueprint_name": "BirdBP",
426
+ "function_name": "SetViewTargetWithBlend",
427
+ "target": "PlayerController",
428
+ "params": {
429
+ "BlendTime": 0.0,
430
+ "BlendFunc": "VTBlend_EaseInOut",
431
+ "LockOutgoing": True
432
+ },
433
+ "node_position": [400, -200] # Align with GetActorOfClass
434
+ }
435
+
436
+ response = send_mcp_command("add_blueprint_function_node", set_view_params)
437
+
438
+ if not response or response.get("status") != "success":
439
+ logger.error(f"Failed to add SetViewTargetWithBlend node: {response}")
440
+ return
441
+
442
+ logger.info("SetViewTargetWithBlend node added successfully!")
443
+ set_view_node_id = response.get("result", {}).get("node_id")
444
+
445
+ # Step 16 (formerly 18): Connect BeginPlay to the SetViewTargetWithBlend node
446
+ # Try to find existing BeginPlay node first
447
+ find_begin_play_params = {
448
+ "blueprint_name": "BirdBP",
449
+ "node_type": "Event",
450
+ "event_name": "ReceiveBeginPlay" # Use the exact Unreal Engine event name
451
+ }
452
+
453
+ response = send_mcp_command("find_blueprint_nodes", find_begin_play_params)
454
+
455
+ if response and response.get("status") == "success":
456
+ # Use existing BeginPlay node if found
457
+ nodes = response.get("result", {}).get("nodes", [])
458
+ if nodes:
459
+ logger.info(f"Found existing ReceiveBeginPlay node, reusing it")
460
+ begin_play_node_id = nodes[0].get("node_id")
461
+ else:
462
+ # Create a new BeginPlay node only if none exists
463
+ begin_play_params = {
464
+ "blueprint_name": "BirdBP",
465
+ "event_name": "ReceiveBeginPlay", # Use the exact Unreal Engine event name
466
+ "node_position": [-400, 0] # Move BeginPlay further left
467
+ }
468
+
469
+ response = send_mcp_command("add_blueprint_event_node", begin_play_params)
470
+
471
+ if not response or response.get("status") != "success":
472
+ logger.error(f"Failed to get/create ReceiveBeginPlay node: {response}")
473
+ return
474
+
475
+ begin_play_node_id = response.get("result", {}).get("node_id")
476
+ else:
477
+ logger.error(f"Failed to search for ReceiveBeginPlay nodes: {response}")
478
+ return
479
+
480
+ # Connect BeginPlay to GetActorOfClass (instead of directly to SetViewTargetWithBlend)
481
+ connect_begin_play_params = {
482
+ "blueprint_name": "BirdBP",
483
+ "source_node_id": begin_play_node_id,
484
+ "source_pin": "Then",
485
+ "target_node_id": get_camera_node_id,
486
+ "target_pin": "Execute" # Connect to GetActorOfClass's execute pin (capital E)
487
+ }
488
+
489
+ response = send_mcp_command("connect_blueprint_nodes", connect_begin_play_params)
490
+
491
+ if not response or response.get("status") != "success":
492
+ logger.error(f"Failed to connect BeginPlay to GetActorOfClass: {response}")
493
+ return
494
+
495
+ logger.info("Connected BeginPlay to GetActorOfClass successfully!")
496
+
497
+ # Then connect GetActorOfClass to SetViewTargetWithBlend
498
+ connect_camera_exec_params = {
499
+ "blueprint_name": "BirdBP",
500
+ "source_node_id": get_camera_node_id,
501
+ "source_pin": "Then", # Output execution pin from GetActorOfClass (capital T)
502
+ "target_node_id": set_view_node_id,
503
+ "target_pin": "Execute" # Input execution pin on SetViewTargetWithBlend (capital E)
504
+ }
505
+
506
+ response = send_mcp_command("connect_blueprint_nodes", connect_camera_exec_params)
507
+
508
+ if not response or response.get("status") != "success":
509
+ logger.error(f"Failed to connect GetActorOfClass to SetViewTargetWithBlend execution: {response}")
510
+ return
511
+
512
+ logger.info("Connected GetActorOfClass execution to SetViewTargetWithBlend successfully!")
513
+
514
+ # Now connect GetActorOfClass result to SetViewTargetWithBlend's target parameter
515
+ connect_camera_params = {
516
+ "blueprint_name": "BirdBP",
517
+ "source_node_id": get_camera_node_id,
518
+ "source_pin": "ReturnValue",
519
+ "target_node_id": set_view_node_id,
520
+ "target_pin": "NewViewTarget"
521
+ }
522
+
523
+ response = send_mcp_command("connect_blueprint_nodes", connect_camera_params)
524
+
525
+ if not response or response.get("status") != "success":
526
+ logger.error(f"Failed to connect camera to SetViewTargetWithBlend: {response}")
527
+ return
528
+
529
+ logger.info("Connected GetActorOfClass to SetViewTargetWithBlend successfully!")
530
+
531
+ # Step 18 (formerly 20): Get Player Controller for the SetViewTargetWithBlend function
532
+ # Add Get Player Controller node
533
+ get_pc_params = {
534
+ "blueprint_name": "BirdBP",
535
+ "function_name": "GetPlayerController",
536
+ "target": "UGameplayStatics",
537
+ "params": {
538
+ "PlayerIndex": 0
539
+ },
540
+ "node_position": [0, -100] # Place between GetActorOfClass and SetViewTarget
541
+ }
542
+
543
+ response = send_mcp_command("add_blueprint_function_node", get_pc_params)
544
+
545
+ if not response or response.get("status") != "success":
546
+ logger.error(f"Failed to add GetPlayerController node: {response}")
547
+ return
548
+
549
+ logger.info("GetPlayerController node added successfully!")
550
+ get_pc_node_id = response.get("result", {}).get("node_id")
551
+
552
+ # Connect Player Controller to SetViewTargetWithBlend
553
+ connect_pc_params = {
554
+ "blueprint_name": "BirdBP",
555
+ "source_node_id": get_pc_node_id,
556
+ "source_pin": "ReturnValue",
557
+ "target_node_id": set_view_node_id,
558
+ "target_pin": "self"
559
+ }
560
+
561
+ response = send_mcp_command("connect_blueprint_nodes", connect_pc_params)
562
+
563
+ if not response or response.get("status") != "success":
564
+ logger.error(f"Failed to connect player controller to SetViewTargetWithBlend: {response}")
565
+ return
566
+
567
+ logger.info("Connected PlayerController to SetViewTargetWithBlend target successfully!")
568
+
569
+ # Step 19 (formerly 21): Compile the blueprint with the new camera view setup
570
+ response = send_mcp_command("compile_blueprint", {
571
+ "blueprint_name": "BirdBP"
572
+ })
573
+
574
+ if not response or response.get("status") != "success":
575
+ logger.error(f"Failed to compile blueprint: {response}")
576
+ return
577
+
578
+ logger.info("Blueprint with camera view setup compiled successfully!")
579
+
580
+ # Step 20 (formerly 14): Spawn the bird in the level
581
+ response = send_mcp_command("spawn_blueprint_actor", {
582
+ "blueprint_name": "BirdBP",
583
+ "actor_name": "Bird",
584
+ "location": [0.0, 0.0, 200.0], # 200 units up
585
+ "rotation": [0.0, 0.0, 0.0],
586
+ "scale": [1.0, 1.0, 1.0]
587
+ })
588
+
589
+ if not response or response.get("status") != "success":
590
+ logger.error(f"Failed to spawn blueprint actor: {response}")
591
+ return
592
+
593
+ logger.info("Bird spawned successfully!")
594
+
595
+ # Step 21 (formerly 15): Add a camera to the level
596
+ # Create a camera actor
597
+ response = send_mcp_command("create_actor", {
598
+ "name": "GameCamera",
599
+ "type": "CameraActor",
600
+ "location": [500.0, 0.0, 250.0], # Position camera to view the bird from a distance
601
+ "rotation": [0.0, 180.0, 0.0], # Point camera at bird's spawn location
602
+ "scale": [1.0, 1.0, 1.0]
603
+ })
604
+
605
+ if not response or response.get("status") != "success":
606
+ logger.error(f"Failed to create camera actor: {response}")
607
+ return
608
+
609
+ logger.info("Camera actor created successfully!")
610
+
611
+ logger.info("You can now press spacebar to make the bird flap! The camera will automatically view the bird.")
612
+
613
+ except Exception as e:
614
+ logger.error(f"Error: {e}")
615
+ sys.exit(1)
616
+
617
+ if __name__ == "__main__":
618
+ main()