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.
- package/README.md +56 -0
- package/bin/flockbay-mcp.mjs +56 -0
- package/bin/flockbay.mjs +78 -0
- package/dist/codex/flockbayMcpStdioBridge.cjs +383 -0
- package/dist/codex/flockbayMcpStdioBridge.d.cts +2 -0
- package/dist/codex/flockbayMcpStdioBridge.d.mts +2 -0
- package/dist/codex/flockbayMcpStdioBridge.mjs +381 -0
- package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +136 -0
- package/dist/flockbayScreenshotGate-DkxU24cR.cjs +138 -0
- package/dist/index--o4BPz5o.cjs +10311 -0
- package/dist/index-CUp3juDS.mjs +10268 -0
- package/dist/index.cjs +43 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +40 -0
- package/dist/lib.cjs +33 -0
- package/dist/lib.d.cts +957 -0
- package/dist/lib.d.mts +957 -0
- package/dist/lib.mjs +23 -0
- package/dist/runCodex-D3eT-TvB.cjs +3449 -0
- package/dist/runCodex-o6PCbHQ7.mjs +3446 -0
- package/dist/runGemini-Bt0oEj_g.mjs +3183 -0
- package/dist/runGemini-CBxZp6I7.cjs +3185 -0
- package/dist/types-C-jnUdn_.cjs +4498 -0
- package/dist/types-DGd6ea2Z.mjs +4450 -0
- package/kits/kit.open_world/kit.json +59 -0
- package/package.json +130 -0
- package/scripts/claude_local_launcher.cjs +73 -0
- package/scripts/claude_remote_launcher.cjs +16 -0
- package/scripts/claude_version_utils.cjs +391 -0
- package/scripts/ripgrep_launcher.cjs +33 -0
- package/scripts/session_hook_forwarder.cjs +49 -0
- package/scripts/test-codex-abort-history.mjs +77 -0
- package/scripts/unpack-tools.cjs +222 -0
- package/tools/licenses/difftastic-LICENSE +21 -0
- package/tools/licenses/ripgrep-LICENSE +3 -0
- package/tools/unreal-mcp/UPSTREAM_VERSION.md +8 -0
- package/tools/unreal-mcp/upstream/Docs/README.md +8 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/README.md +7 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/actor_tools.md +184 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/blueprint_tools.md +268 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/editor_tools.md +104 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/node_tools.md +274 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Config/FilterPlugin.ini +8 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +1160 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +924 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +709 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +896 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPProjectCommands.cpp +72 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPUMGCommands.cpp +544 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +321 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +419 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPModule.cpp +21 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +34 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +27 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommonUtils.h +59 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +40 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPProjectCommands.h +20 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPUMGCommands.h +82 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/MCPServerRunnable.h +34 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPBridge.h +64 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPModule.h +22 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +78 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/UnrealMCP.uplugin +36 -0
- package/tools/unreal-mcp/upstream/Python/README.md +40 -0
- package/tools/unreal-mcp/upstream/Python/pyproject.toml +22 -0
- package/tools/unreal-mcp/upstream/Python/scripts/actors/test_cube.py +203 -0
- package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_blueprints_with_different_components.py +497 -0
- package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_cube_blueprint.py +194 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_component_reference.py +267 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_create_bird_blueprint_with_input_and_camera.py +618 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_input_mapping.py +366 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_physics_variables.py +390 -0
- package/tools/unreal-mcp/upstream/Python/tools/blueprint_tools.py +420 -0
- package/tools/unreal-mcp/upstream/Python/tools/editor_tools.py +369 -0
- package/tools/unreal-mcp/upstream/Python/tools/node_tools.py +430 -0
- package/tools/unreal-mcp/upstream/Python/tools/project_tools.py +64 -0
- package/tools/unreal-mcp/upstream/Python/tools/umg_tools.py +333 -0
- package/tools/unreal-mcp/upstream/Python/unreal_mcp_server.py +398 -0
- package/tools/unreal-mcp/upstream/Python/uv.lock +521 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unreal Engine MCP Server
|
|
3
|
+
|
|
4
|
+
A simple MCP server for interacting with Unreal Engine.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import socket
|
|
9
|
+
import sys
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from contextlib import asynccontextmanager
|
|
13
|
+
from typing import AsyncIterator, Dict, Any, Optional
|
|
14
|
+
from mcp.server.fastmcp import FastMCP
|
|
15
|
+
|
|
16
|
+
# Configure logging with more detailed format
|
|
17
|
+
def _default_log_path() -> str:
|
|
18
|
+
# Prefer an explicit path from the launcher/daemon.
|
|
19
|
+
explicit = os.environ.get("FLOCKBAY_UNREAL_MCP_LOG_PATH", "").strip()
|
|
20
|
+
if explicit:
|
|
21
|
+
return explicit
|
|
22
|
+
|
|
23
|
+
# Fall back to a writable per-user folder.
|
|
24
|
+
home = os.environ.get("FLOCKBAY_HOME_DIR", "").strip()
|
|
25
|
+
if not home:
|
|
26
|
+
home = os.path.join(os.path.expanduser("~"), ".flockbay")
|
|
27
|
+
|
|
28
|
+
runtime_dir = os.path.join(home, "unreal-mcp")
|
|
29
|
+
try:
|
|
30
|
+
os.makedirs(runtime_dir, exist_ok=True)
|
|
31
|
+
except Exception:
|
|
32
|
+
# Last resort: current working directory (may fail on locked installs).
|
|
33
|
+
return "unreal_mcp.log"
|
|
34
|
+
|
|
35
|
+
return os.path.join(runtime_dir, "unreal_mcp.log")
|
|
36
|
+
|
|
37
|
+
logging.basicConfig(
|
|
38
|
+
level=logging.DEBUG, # Change to DEBUG level for more details
|
|
39
|
+
format='%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
|
40
|
+
handlers=[
|
|
41
|
+
logging.FileHandler(_default_log_path()),
|
|
42
|
+
# logging.StreamHandler(sys.stdout) # Remove this handler to unexpected non-whitespace characters in JSON
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
logger = logging.getLogger("UnrealMCP")
|
|
46
|
+
|
|
47
|
+
# Configuration
|
|
48
|
+
UNREAL_HOST = "127.0.0.1"
|
|
49
|
+
UNREAL_PORT = 55557
|
|
50
|
+
|
|
51
|
+
class UnrealConnection:
|
|
52
|
+
"""Connection to an Unreal Engine instance."""
|
|
53
|
+
|
|
54
|
+
def __init__(self):
|
|
55
|
+
"""Initialize the connection."""
|
|
56
|
+
self.socket = None
|
|
57
|
+
self.connected = False
|
|
58
|
+
|
|
59
|
+
def connect(self) -> bool:
|
|
60
|
+
"""Connect to the Unreal Engine instance."""
|
|
61
|
+
try:
|
|
62
|
+
# Close any existing socket
|
|
63
|
+
if self.socket:
|
|
64
|
+
try:
|
|
65
|
+
self.socket.close()
|
|
66
|
+
except:
|
|
67
|
+
pass
|
|
68
|
+
self.socket = None
|
|
69
|
+
|
|
70
|
+
logger.info(f"Connecting to Unreal at {UNREAL_HOST}:{UNREAL_PORT}...")
|
|
71
|
+
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
72
|
+
self.socket.settimeout(5) # 5 second timeout
|
|
73
|
+
|
|
74
|
+
# Set socket options for better stability
|
|
75
|
+
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
|
76
|
+
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
77
|
+
|
|
78
|
+
# Set larger buffer sizes
|
|
79
|
+
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
|
|
80
|
+
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
|
|
81
|
+
|
|
82
|
+
self.socket.connect((UNREAL_HOST, UNREAL_PORT))
|
|
83
|
+
self.connected = True
|
|
84
|
+
logger.info("Connected to Unreal Engine")
|
|
85
|
+
return True
|
|
86
|
+
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logger.error(f"Failed to connect to Unreal: {e}")
|
|
89
|
+
self.connected = False
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
def disconnect(self):
|
|
93
|
+
"""Disconnect from the Unreal Engine instance."""
|
|
94
|
+
if self.socket:
|
|
95
|
+
try:
|
|
96
|
+
self.socket.close()
|
|
97
|
+
except:
|
|
98
|
+
pass
|
|
99
|
+
self.socket = None
|
|
100
|
+
self.connected = False
|
|
101
|
+
|
|
102
|
+
def receive_full_response(self, sock, buffer_size=4096) -> bytes:
|
|
103
|
+
"""Receive a complete response from Unreal, handling chunked data."""
|
|
104
|
+
chunks = []
|
|
105
|
+
sock.settimeout(5) # 5 second timeout
|
|
106
|
+
try:
|
|
107
|
+
while True:
|
|
108
|
+
chunk = sock.recv(buffer_size)
|
|
109
|
+
if not chunk:
|
|
110
|
+
if not chunks:
|
|
111
|
+
raise Exception("Connection closed before receiving data")
|
|
112
|
+
break
|
|
113
|
+
chunks.append(chunk)
|
|
114
|
+
|
|
115
|
+
# Process the data received so far
|
|
116
|
+
data = b''.join(chunks)
|
|
117
|
+
decoded_data = data.decode('utf-8')
|
|
118
|
+
|
|
119
|
+
# Try to parse as JSON to check if complete
|
|
120
|
+
try:
|
|
121
|
+
json.loads(decoded_data)
|
|
122
|
+
logger.info(f"Received complete response ({len(data)} bytes)")
|
|
123
|
+
return data
|
|
124
|
+
except json.JSONDecodeError:
|
|
125
|
+
# Not complete JSON yet, continue reading
|
|
126
|
+
logger.debug(f"Received partial response, waiting for more data...")
|
|
127
|
+
continue
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.warning(f"Error processing response chunk: {str(e)}")
|
|
130
|
+
continue
|
|
131
|
+
except socket.timeout:
|
|
132
|
+
logger.warning("Socket timeout during receive")
|
|
133
|
+
if chunks:
|
|
134
|
+
# If we have some data already, try to use it
|
|
135
|
+
data = b''.join(chunks)
|
|
136
|
+
try:
|
|
137
|
+
json.loads(data.decode('utf-8'))
|
|
138
|
+
logger.info(f"Using partial response after timeout ({len(data)} bytes)")
|
|
139
|
+
return data
|
|
140
|
+
except:
|
|
141
|
+
pass
|
|
142
|
+
raise Exception("Timeout receiving Unreal response")
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.error(f"Error during receive: {str(e)}")
|
|
145
|
+
raise
|
|
146
|
+
|
|
147
|
+
def send_command(self, command: str, params: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
|
|
148
|
+
"""Send a command to Unreal Engine and get the response."""
|
|
149
|
+
# Always reconnect for each command, since Unreal closes the connection after each command
|
|
150
|
+
# This is different from Unity which keeps connections alive
|
|
151
|
+
if self.socket:
|
|
152
|
+
try:
|
|
153
|
+
self.socket.close()
|
|
154
|
+
except:
|
|
155
|
+
pass
|
|
156
|
+
self.socket = None
|
|
157
|
+
self.connected = False
|
|
158
|
+
|
|
159
|
+
if not self.connect():
|
|
160
|
+
logger.error("Failed to connect to Unreal Engine for command")
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
# Match Unity's command format exactly
|
|
165
|
+
command_obj = {
|
|
166
|
+
"type": command, # Use "type" instead of "command"
|
|
167
|
+
"params": params or {} # Use Unity's params or {} pattern
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# Send without newline, exactly like Unity
|
|
171
|
+
command_json = json.dumps(command_obj)
|
|
172
|
+
logger.info(f"Sending command: {command_json}")
|
|
173
|
+
self.socket.sendall(command_json.encode('utf-8'))
|
|
174
|
+
|
|
175
|
+
# Read response using improved handler
|
|
176
|
+
response_data = self.receive_full_response(self.socket)
|
|
177
|
+
response = json.loads(response_data.decode('utf-8'))
|
|
178
|
+
|
|
179
|
+
# Log complete response for debugging
|
|
180
|
+
logger.info(f"Complete response from Unreal: {response}")
|
|
181
|
+
|
|
182
|
+
# Check for both error formats: {"status": "error", ...} and {"success": false, ...}
|
|
183
|
+
if response.get("status") == "error":
|
|
184
|
+
error_message = response.get("error") or response.get("message", "Unknown Unreal error")
|
|
185
|
+
logger.error(f"Unreal error (status=error): {error_message}")
|
|
186
|
+
# We want to preserve the original error structure but ensure error is accessible
|
|
187
|
+
if "error" not in response:
|
|
188
|
+
response["error"] = error_message
|
|
189
|
+
elif response.get("success") is False:
|
|
190
|
+
# This format uses {"success": false, "error": "message"} or {"success": false, "message": "message"}
|
|
191
|
+
error_message = response.get("error") or response.get("message", "Unknown Unreal error")
|
|
192
|
+
logger.error(f"Unreal error (success=false): {error_message}")
|
|
193
|
+
# Convert to the standard format expected by higher layers
|
|
194
|
+
response = {
|
|
195
|
+
"status": "error",
|
|
196
|
+
"error": error_message
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# Always close the connection after command is complete
|
|
200
|
+
# since Unreal will close it on its side anyway
|
|
201
|
+
try:
|
|
202
|
+
self.socket.close()
|
|
203
|
+
except:
|
|
204
|
+
pass
|
|
205
|
+
self.socket = None
|
|
206
|
+
self.connected = False
|
|
207
|
+
|
|
208
|
+
return response
|
|
209
|
+
|
|
210
|
+
except Exception as e:
|
|
211
|
+
logger.error(f"Error sending command: {e}")
|
|
212
|
+
# Always reset connection state on any error
|
|
213
|
+
self.connected = False
|
|
214
|
+
try:
|
|
215
|
+
self.socket.close()
|
|
216
|
+
except:
|
|
217
|
+
pass
|
|
218
|
+
self.socket = None
|
|
219
|
+
return {
|
|
220
|
+
"status": "error",
|
|
221
|
+
"error": str(e)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# Global connection state
|
|
225
|
+
_unreal_connection: UnrealConnection = None
|
|
226
|
+
|
|
227
|
+
def get_unreal_connection() -> Optional[UnrealConnection]:
|
|
228
|
+
"""Get the connection to Unreal Engine."""
|
|
229
|
+
global _unreal_connection
|
|
230
|
+
try:
|
|
231
|
+
if _unreal_connection is None:
|
|
232
|
+
_unreal_connection = UnrealConnection()
|
|
233
|
+
if not _unreal_connection.connect():
|
|
234
|
+
logger.warning("Could not connect to Unreal Engine")
|
|
235
|
+
_unreal_connection = None
|
|
236
|
+
else:
|
|
237
|
+
# Verify connection is still valid with a ping-like test
|
|
238
|
+
try:
|
|
239
|
+
# Simple test by sending an empty buffer to check if socket is still connected
|
|
240
|
+
_unreal_connection.socket.sendall(b'\x00')
|
|
241
|
+
logger.debug("Connection verified with ping test")
|
|
242
|
+
except Exception as e:
|
|
243
|
+
logger.warning(f"Existing connection failed: {e}")
|
|
244
|
+
_unreal_connection.disconnect()
|
|
245
|
+
_unreal_connection = None
|
|
246
|
+
# Try to reconnect
|
|
247
|
+
_unreal_connection = UnrealConnection()
|
|
248
|
+
if not _unreal_connection.connect():
|
|
249
|
+
logger.warning("Could not reconnect to Unreal Engine")
|
|
250
|
+
_unreal_connection = None
|
|
251
|
+
else:
|
|
252
|
+
logger.info("Successfully reconnected to Unreal Engine")
|
|
253
|
+
|
|
254
|
+
return _unreal_connection
|
|
255
|
+
except Exception as e:
|
|
256
|
+
logger.error(f"Error getting Unreal connection: {e}")
|
|
257
|
+
return None
|
|
258
|
+
|
|
259
|
+
@asynccontextmanager
|
|
260
|
+
async def server_lifespan(server: FastMCP) -> AsyncIterator[Dict[str, Any]]:
|
|
261
|
+
"""Handle server startup and shutdown."""
|
|
262
|
+
global _unreal_connection
|
|
263
|
+
logger.info("UnrealMCP server starting up")
|
|
264
|
+
try:
|
|
265
|
+
_unreal_connection = get_unreal_connection()
|
|
266
|
+
if _unreal_connection:
|
|
267
|
+
logger.info("Connected to Unreal Engine on startup")
|
|
268
|
+
else:
|
|
269
|
+
logger.warning("Could not connect to Unreal Engine on startup")
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.error(f"Error connecting to Unreal Engine on startup: {e}")
|
|
272
|
+
_unreal_connection = None
|
|
273
|
+
|
|
274
|
+
try:
|
|
275
|
+
yield {}
|
|
276
|
+
finally:
|
|
277
|
+
if _unreal_connection:
|
|
278
|
+
_unreal_connection.disconnect()
|
|
279
|
+
_unreal_connection = None
|
|
280
|
+
logger.info("Unreal MCP server shut down")
|
|
281
|
+
|
|
282
|
+
# Initialize server
|
|
283
|
+
mcp = FastMCP(
|
|
284
|
+
"UnrealMCP",
|
|
285
|
+
description="Unreal Engine integration via Model Context Protocol",
|
|
286
|
+
lifespan=server_lifespan
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
# Import and register tools
|
|
290
|
+
from tools.editor_tools import register_editor_tools
|
|
291
|
+
from tools.blueprint_tools import register_blueprint_tools
|
|
292
|
+
from tools.node_tools import register_blueprint_node_tools
|
|
293
|
+
from tools.project_tools import register_project_tools
|
|
294
|
+
from tools.umg_tools import register_umg_tools
|
|
295
|
+
|
|
296
|
+
# Register tools
|
|
297
|
+
register_editor_tools(mcp)
|
|
298
|
+
register_blueprint_tools(mcp)
|
|
299
|
+
register_blueprint_node_tools(mcp)
|
|
300
|
+
register_project_tools(mcp)
|
|
301
|
+
register_umg_tools(mcp)
|
|
302
|
+
|
|
303
|
+
@mcp.prompt()
|
|
304
|
+
def info():
|
|
305
|
+
"""Information about available Unreal MCP tools and best practices."""
|
|
306
|
+
return """
|
|
307
|
+
# Unreal MCP Server Tools and Best Practices
|
|
308
|
+
|
|
309
|
+
## UMG (Widget Blueprint) Tools
|
|
310
|
+
- `create_umg_widget_blueprint(widget_name, parent_class="UserWidget", path="/Game/UI")`
|
|
311
|
+
Create a new UMG Widget Blueprint
|
|
312
|
+
- `add_text_block_to_widget(widget_name, text_block_name, text="", position=[0,0], size=[200,50], font_size=12, color=[1,1,1,1])`
|
|
313
|
+
Add a Text Block widget with customizable properties
|
|
314
|
+
- `add_button_to_widget(widget_name, button_name, text="", position=[0,0], size=[200,50], font_size=12, color=[1,1,1,1], background_color=[0.1,0.1,0.1,1])`
|
|
315
|
+
Add a Button widget with text and styling
|
|
316
|
+
- `bind_widget_event(widget_name, widget_component_name, event_name, function_name="")`
|
|
317
|
+
Bind events like OnClicked to functions
|
|
318
|
+
- `add_widget_to_viewport(widget_name, z_order=0)`
|
|
319
|
+
Add widget instance to game viewport
|
|
320
|
+
- `set_text_block_binding(widget_name, text_block_name, binding_property, binding_type="Text")`
|
|
321
|
+
Set up dynamic property binding for text blocks
|
|
322
|
+
|
|
323
|
+
## Editor Tools
|
|
324
|
+
### Viewport and Screenshots
|
|
325
|
+
- `focus_viewport(target, location, distance, orientation)` - Focus viewport
|
|
326
|
+
- `take_screenshot(filename, show_ui, resolution)` - Capture screenshots
|
|
327
|
+
|
|
328
|
+
### Actor Management
|
|
329
|
+
- `get_actors_in_level()` - List all actors in current level
|
|
330
|
+
- `find_actors_by_name(pattern)` - Find actors by name pattern
|
|
331
|
+
- `spawn_actor(name, type, location=[0,0,0], rotation=[0,0,0], scale=[1,1,1])` - Create actors
|
|
332
|
+
- `delete_actor(name)` - Remove actors
|
|
333
|
+
- `set_actor_transform(name, location, rotation, scale)` - Modify actor transform
|
|
334
|
+
- `get_actor_properties(name)` - Get actor properties
|
|
335
|
+
|
|
336
|
+
## Blueprint Management
|
|
337
|
+
- `create_blueprint(name, parent_class)` - Create new Blueprint classes
|
|
338
|
+
- `add_component_to_blueprint(blueprint_name, component_type, component_name)` - Add components
|
|
339
|
+
- `set_static_mesh_properties(blueprint_name, component_name, static_mesh)` - Configure meshes
|
|
340
|
+
- `set_physics_properties(blueprint_name, component_name)` - Configure physics
|
|
341
|
+
- `compile_blueprint(blueprint_name)` - Compile Blueprint changes
|
|
342
|
+
- `set_blueprint_property(blueprint_name, property_name, property_value)` - Set properties
|
|
343
|
+
- `set_pawn_properties(blueprint_name)` - Configure Pawn settings
|
|
344
|
+
- `spawn_blueprint_actor(blueprint_name, actor_name)` - Spawn Blueprint actors
|
|
345
|
+
|
|
346
|
+
## Blueprint Node Management
|
|
347
|
+
- `add_blueprint_event_node(blueprint_name, event_type)` - Add event nodes
|
|
348
|
+
- `add_blueprint_input_action_node(blueprint_name, action_name)` - Add input nodes
|
|
349
|
+
- `add_blueprint_function_node(blueprint_name, target, function_name)` - Add function nodes
|
|
350
|
+
- `connect_blueprint_nodes(blueprint_name, source_node_id, source_pin, target_node_id, target_pin)` - Connect nodes
|
|
351
|
+
- `add_blueprint_variable(blueprint_name, variable_name, variable_type)` - Add variables
|
|
352
|
+
- `add_blueprint_get_self_component_reference(blueprint_name, component_name)` - Add component refs
|
|
353
|
+
- `add_blueprint_self_reference(blueprint_name)` - Add self references
|
|
354
|
+
- `find_blueprint_nodes(blueprint_name, node_type, event_type)` - Find nodes
|
|
355
|
+
|
|
356
|
+
## Project Tools
|
|
357
|
+
- `create_input_mapping(action_name, key, input_type)` - Create input mappings
|
|
358
|
+
|
|
359
|
+
## Best Practices
|
|
360
|
+
|
|
361
|
+
### UMG Widget Development
|
|
362
|
+
- Create widgets with descriptive names that reflect their purpose
|
|
363
|
+
- Use consistent naming conventions for widget components
|
|
364
|
+
- Organize widget hierarchy logically
|
|
365
|
+
- Set appropriate anchors and alignment for responsive layouts
|
|
366
|
+
- Use property bindings for dynamic updates instead of direct setting
|
|
367
|
+
- Handle widget events appropriately with meaningful function names
|
|
368
|
+
- Clean up widgets when no longer needed
|
|
369
|
+
- Test widget layouts at different resolutions
|
|
370
|
+
|
|
371
|
+
### Editor and Actor Management
|
|
372
|
+
- Use unique names for actors to avoid conflicts
|
|
373
|
+
- Clean up temporary actors
|
|
374
|
+
- Validate transforms before applying
|
|
375
|
+
- Check actor existence before modifications
|
|
376
|
+
- Take regular viewport screenshots during development
|
|
377
|
+
- Keep the viewport focused on relevant actors during operations
|
|
378
|
+
|
|
379
|
+
### Blueprint Development
|
|
380
|
+
- Compile Blueprints after changes
|
|
381
|
+
- Use meaningful names for variables and functions
|
|
382
|
+
- Organize nodes logically
|
|
383
|
+
- Test functionality in isolation
|
|
384
|
+
- Consider performance implications
|
|
385
|
+
- Document complex setups
|
|
386
|
+
|
|
387
|
+
### Error Handling
|
|
388
|
+
- Check command responses for success
|
|
389
|
+
- Handle errors gracefully
|
|
390
|
+
- Log important operations
|
|
391
|
+
- Validate parameters
|
|
392
|
+
- Clean up resources on errors
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
# Run the server
|
|
396
|
+
if __name__ == "__main__":
|
|
397
|
+
logger.info("Starting MCP server with stdio transport")
|
|
398
|
+
mcp.run(transport='stdio')
|