使用说明
UnrealPyMCP
A pure Python Unreal plugin containing an MCP-like server that lets an AI/LLM talk to Unreal by:
- Reading Unreal's Output Log
- Sending Python code to execute in Unreal
There are no pre-programmed commands, it fully relies on your AI executing Unreal Python commands, with no guardrails. There may be limits, since Unreal does not expose everything to Python.
Asked GPT to create a small maze with cubes
Asked to create a new red material and apply it to actor MCP_Maze_6_6
Project plugin that starts a local MCP-like HTTP server inside Unreal Editor so an AI client can:
- Read Unreal log output
- Execute Python in the running editor
This plugin is intentionally powerful. unreal_py_mcp/exec and unreal_py_mcp/exec_async run arbitrary Python in the editor process.
What It Starts
When the plugin is enabled, Unreal runs:
Content/Python/init_unreal.py
That imports unreal_py_mcp.py (primary implementation), which starts a server on:
http://127.0.0.1:3001(default)
Endpoints
GET /mcp- Tool discovery
- Includes
meta.startup_guidancefor MCP auto-detection and config hints
GET /mcp/help- Built-in API docs (tools, limits, examples, endpoints)
GET /health- Server and main-thread runner status
- Includes current log resolution and startup guidance
GET /tasks/{task_id}/status- Poll async execution task state/result (fallback when SSE is unavailable)
GET /tasks/{task_id}/stream- Server-Sent Events (SSE) stream for live task events
- Streams task status, progress, stdout/stderr, and tailed log lines
POST /mcp/messages- Execute a tool with payload:
{"tool": "...", "arguments": {...}}
- Execute a tool with payload:
Tools
unreal_py_mcp/get_logs- Return last N log lines (default 500, max 5000)
unreal_py_mcp/get_log_path- Return resolved log file and search paths
unreal_py_mcp/exec- Execute Python synchronously on Unreal main thread
- Supports
timeoutargument - Exposes
report_progress(message, current=None, total=None)in execution context
unreal_py_mcp/exec_async- Queue Python execution and return immediately with
task_id - Stream live events via
GET /tasks/{task_id}/stream - Poll
GET /tasks/{task_id}/statusas fallback
- Queue Python execution and return immediately with
OpenCode Config
Example:
{
"mcp": {
"unreal_py_mcp": {
"type": "remote",
"url": "http://127.0.0.1:3001",
"enabled": true
}
}
}
Request Examples
Get logs:
{
"tool": "unreal_py_mcp/get_logs",
"arguments": { "limit": 200 }
}
Sync exec:
{
"tool": "unreal_py_mcp/exec",
"arguments": {
"code": "print('hello from unreal')",
"timeout": 60
}
}
Async exec:
{
"tool": "unreal_py_mcp/exec_async",
"arguments": {
"code": "import time\nfor i in range(3):\n report_progress(f'step {i+1}', i+1, 3)\n time.sleep(1)\nresult={'done': True}",
"timeout": 60
}
}
Then poll:
GET /tasks/<task_id>/status
Or stream live events:
curl -N http://127.0.0.1:3001/tasks/<task_id>/stream
SSE event types currently emitted:
task_statusprogressstdoutstderrlog_linelog_infolog_errortask_result
Resume from a known event cursor:
- Query param:
GET /tasks/<task_id>/stream?cursor=<seq> - Or header:
Last-Event-ID: <seq>
Structured Errors
HTTP/API errors are returned as JSON:
{
"status": "error",
"error_type": "InvalidJson",
"message": "Invalid JSON payload: ...",
"timestamp": "2026-02-25T09:23:41.032949+00:00"
}
Execution failures from unreal_py_mcp/exec / exec_async include:
error_type,message,stack_tracestdout,stderrrecent_logscontexttimestamp,timeout_seconds
Config Environment Variables
UNREAL_MCP_PORT- Server port (default
3001)
- Server port (default
UNREAL_MCP_LOG_PATH- Absolute path to a specific
.logfile
- Absolute path to a specific
UNREAL_MCP_EXEC_TIMEOUT- Default sync/async execution timeout seconds (default
60)
- Default sync/async execution timeout seconds (default
UNREAL_MCP_MAX_EXEC_TIMEOUT- Maximum allowed timeout seconds (default
300)
- Maximum allowed timeout seconds (default
UNREAL_MCP_ERROR_LOG_LINES- Number of log lines attached to exec error payloads (default
120)
- Number of log lines attached to exec error payloads (default
UNREAL_MCP_TASK_EVENT_BUFFER- Max buffered SSE events per task before oldest events are dropped (default
2000)
- Max buffered SSE events per task before oldest events are dropped (default
UNREAL_MCP_SSE_HEARTBEAT_SECONDS- Idle heartbeat interval for SSE connections (default
15)
- Idle heartbeat interval for SSE connections (default
UNREAL_MCP_LOG_TAIL_POLL_SECONDS- Poll interval for disk log tail streaming during async tasks (default
0.25)
- Poll interval for disk log tail streaming during async tasks (default
UNREAL_MCP_DISABLE_SERVER- Set to
1to disable server startup
- Set to
Log Path Resolution
Resolution order:
- Explicit
pathargument (tool call) UNREAL_MCP_LOG_PATH<Project>/Saved/Logs/*.log(preferred)%LOCALAPPDATA%/UnrealEngine/*/Saved/Logs/*.log%LOCALAPPDATA%/<ProjectName>/Saved/Logs/*.log
Notes on Async Behavior
- Async is non-blocking for the MCP client (you get a
task_idimmediately). - Unreal Python still executes on Unreal's main thread for editor safety.
- Use
exec_async+/streamfor real-time visibility on long jobs. - Keep
/statuspolling as a compatibility fallback.
Limitations
- Unreal editor API calls must run on Unreal's main thread.
exec_asyncimproves client responsiveness, but Unreal execution remains serialized on the main thread.- Live log streaming is based on tailing the resolved log file on disk (not Unreal in-memory log hooks).
Troubleshooting
- If
/mcpis down:- verify plugin enabled
- verify Python plugin enabled
- restart Unreal Editor
- If logs cannot be resolved:
- call
unreal_py_mcp/get_log_path - set
UNREAL_MCP_LOG_PATH
- call
- For capability/introspection:
- call
/mcp/helpand/health
- call