Reliable headless Unreal Engine MCP server for running AngelScript/UE automation tests without hanging
ue-headless-mcp
A small Model Context Protocol server that runs Unreal Engine automation tests headlessly and returns promptly — purpose-built for the AngelScript (Test_* / IntegrationTest_*) test loop on the Hazelight UnrealEngine-Angelscript fork, but works for any UE automation test.
It is a focused replacement for the headless-test slice of remiphilippe/mcp-unreal. It does not do in-editor blueprint/actor/PIE editing — just the test loop.
Why
The original server tied "test run finished" to the editor process exiting: it ran UnrealEditor-Cmd … -ExecCmds="Automation RunTests …;Quit", buffered stdout/stderr, and blocked on cmd.Wait(). When the editor's graceful ;Quit stalls during shutdown (DDC maintenance, a lingering ShaderCompileWorker/UBA/CEF child holding an inherited handle), Wait() blocks — so a run whose tests finished in milliseconds would hang until the client's multi-minute timeout and return nothing useful.
This server fixes that:
- No inherited pipe. The child's stdout/stderr go to the null device; the editor writes its full log to a per-run file via
-abslog. The classic pipe-EOF deadlock cannot occur. - Result-driven completion, not process exit. It tails the per-run log for the canonical
**** TEST COMPLETE. EXIT CODE: N ****marker (and the optional-ReportExportPathindex.json). The AngelScriptHot reload failed due to script compile errorsmarker is a first-class terminal signal, so a compile failure — the case that previously hung — returns in seconds with the extracted errors. - Immediate process-tree kill. On results, the whole tree is reaped at once via a Windows Job Object (
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, plustaskkill /T /Fas a fallback) instead of waiting for graceful shutdown. - Safety nets. An idle watchdog (no log growth after boot) and a hard timeout guarantee the call always returns.
Tools
| Tool | Purpose |
|---|---|
| status | Report config + whether the editor binary and project file exist. No subprocess. |
| list_tests | List discovered automation test paths (optionally filtered). |
| run_tests | Run tests headless (-nullrhi); structured pass/fail. |
| run_visual_tests | Same, GPU/RHI enabled (for tests needing a render target). |
| get_test_log | Read a run's log (latest McpTest_*.log by default) with filter/offset/limit. |
Configuration (environment)
| Var | Meaning |
|---|---|
| UE_EDITOR_PATH | Absolute path to UnrealEditor-Cmd.exe. Required. |
| MCP_UNREAL_PROJECT | Absolute path to the .uproject. Required. |
| UEHM_TIMEOUT_MS | Hard-timeout backstop in ms (default 300000). Optional. |
The variable names UE_EDITOR_PATH / MCP_UNREAL_PROJECT are intentionally the same as mcp-unreal so swapping servers in .mcp.json is a drop-in change.
Install
go install github.com/osseous/ue-headless-mcp/cmd/ue-headless-mcp@latest
This builds from source into $(go env GOPATH)\bin\ue-headless-mcp.exe.
Register in .mcp.json
{
"mcpServers": {
"ue-headless-mcp": {
"type": "stdio",
"timeout": 360000,
"command": "C:\\Users\\<you>\\go\\bin\\ue-headless-mcp.exe",
"env": {
"UE_EDITOR_PATH": "…\\Engine\\Binaries\\Win64\\UnrealEditor-Cmd.exe",
"MCP_UNREAL_PROJECT": "…\\YourProject.uproject"
}
}
}
}
Build & test
go test ./...
go build -o bin/ue-headless-mcp.exe ./cmd/ue-headless-mcp
The completion state machine (internal/runner) and log/report parsers (internal/parse) are unit-tested against real captured UE logs in testdata/.
Platform
Targets Windows (the Job Object tree-kill is Windows-specific; other platforms fall back to a direct process kill).