@uemcp/server 0.1.0 → 0.3.0

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 (3) hide show
  1. package/README.md +56 -0
  2. package/dist/index.mjs +2037 -31
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -16,10 +16,21 @@ The MCP tool surface currently exposes:
16
16
 
17
17
  - `get_project_id`
18
18
  - `add_module`
19
+ - `list_registered_projects`
19
20
  - `ping_project`
21
+ - `wait_for_job`
20
22
  - `build_target`
21
23
  - `generate_project_files`
22
24
  - `clean_build`
25
+ - `cook_content`
26
+ - `package_project`
27
+ - `run_editor_commandlet`
28
+ - `get_package_status`
29
+ - `cancel_package_job`
30
+ - `analyze_trace`
31
+ - `get_config_value`
32
+ - `set_config_value`
33
+ - `list_config_section`
23
34
  - `run_clang_tidy`
24
35
 
25
36
  ## Project Identity
@@ -55,6 +66,14 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
55
66
  - Refuses to overwrite an existing module name or `Source/<moduleName>` directory
56
67
  - Pure filesystem scaffold; it does not consult the registry or a running editor. Run project-file generation and a build afterward to compile the module.
57
68
 
69
+ ### `list_registered_projects`
70
+
71
+ - Returns every Unreal Editor currently registered with this server: `projectId`, `projectName`, `projectPath`, `host` (always `127.0.0.1`), `port`, `pid`, `registeredAt`, `lastSeenAt`
72
+ - Discovery entry point — call it before the project-scoped tools instead of guessing a `projectId`
73
+ - Default path performs no network I/O; `verify: true` pings each returned entry once, concurrently, and adds `reachable` (plus `reason` when unreachable) under an overall time budget
74
+ - Bounded by `maxResults` (default 50) with `totalCount` and `truncated`; ordering is stable across calls
75
+ - Never mutates the registry — `ping_project` owns stale-registration eviction
76
+
58
77
  ### `ping_project`
59
78
 
60
79
  - Accepts a canonical `projectId`
@@ -67,6 +86,14 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
67
86
  - Uses retry delays of approximately `500ms`, `1s`, and `2s`
68
87
  - Removes the stale registration from memory and persists the cleanup if the bridge remains dead after retries
69
88
 
89
+ ### `wait_for_job`
90
+
91
+ - Blocks server-side until an async job reaches a terminal state, then returns the payload the matching `get_*_status` tool would have returned under `status`
92
+ - Replaces a client-side poll loop for `kind` `compile` (`trigger_live_compile` / `trigger_hot_reload`), `create_class`, `test_run`, and `pie`; `kind` is required because job ids are bare GUIDs
93
+ - `outcome` is `completed`, `timed_out` (last observed status still returned), or `unknown_job` (unknown/expired/cancelled id, returned on the first poll)
94
+ - Per-kind default budgets (compile 120s, create_class 60s, pie 30s, test_run 300s), clamped to 600s; polls back off from 250ms (1s for test runs) and a transient bridge read timeout or dropped socket is retried rather than failing the wait
95
+ - For `test_run`, `status.results` is the first page — page the rest with `get_test_run_status` and `nextCursor`
96
+
70
97
  ### `build_target` / `generate_project_files` / `clean_build`
71
98
 
72
99
  - Resolve the engine from the `.uproject` `EngineAssociation` (or an explicit `engineVersion`) under `UE_INSTALLS_DIR`
@@ -75,6 +102,35 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
75
102
  - `build_target`/`clean_build` refuse to run when the project's editor is registered and reachable (link conflicts on Windows, ignored output on macOS/Linux) — pass `force: true` to override
76
103
  - Do not require a running editor
77
104
 
105
+ ### `cook_content` / `package_project` / `run_editor_commandlet` / `get_package_status` / `cancel_package_job`
106
+
107
+ - Resolve `UnrealEditor-Cmd` and AutomationTool from the same `resolveEngine` result the build tools use, and take no new configuration. On macOS/Linux AutomationTool is `RunUAT.sh` (never the `RunUAT.command` Finder wrapper). On Windows it is `AutomationTool.dll` run under the engine-bundled `dotnet` (falling back to `dotnet` on `PATH` if the bundle is absent), because Node cannot spawn a `.bat` without a shell and routing these arguments through `cmd.exe` would put project and archive paths through a command interpreter. That path builds the child environment `RunUAT.bat` would have: the bundled runtime prepended to `PATH`, `DOTNET_ROOT` / `DOTNET_MULTILEVEL_LOOKUP` / `DOTNET_ROLL_FORWARD` set, and the Visual Studio variables a developer shell exports cleared so they cannot steer .NET resolution
108
+ - `cook_content` runs a full offline cook (`-run=Cook -TargetPlatform=<platform>`, `-CookAll` or `-Map=A+B`); `package_project` runs AutomationTool `BuildCookRun` (build + cook + stage + pak + archive)
109
+ - Both return a `packageJobId` immediately and run in the background — expect **minutes to tens of minutes** (default timeout 90 minutes, ceiling 2 hours). Poll with `get_package_status`, abort with `cancel_package_job`
110
+ - One job at a time per project, and four across the server: a second job for the same project contends for the same `Saved/`, `Intermediate/` and DDC paths, so it is refused rather than queued. Cancel the running one with `cancel_package_job` if you need the slot
111
+ - `get_package_status` reports `running` / `succeeded` / `failed` / `cancelled` / `unknown_job` plus structured cook/UAT diagnostics, an output tail that fills while the job runs, truncation flags, exit code and timing. `kind` is absent for `unknown_job` — a bare job id carries no kind. `cancel_package_job` marks the job cancelled but leaves it `running` until the process actually exits, so a caller cannot start a conflicting job while the old one is still writing. Diagnostics are collected by streaming the log as it is produced (cook errors are spread across the whole run, so a retained tail alone would lose them); the retained raw text is a tail and is capped
112
+ - `run_editor_commandlet` runs one commandlet by name. Allowed: a name of identifier characters only (`ResavePackages`, `FixupRedirects`, `DataValidation`, …) plus arguments as separate argv entries — no shell is involved. Rejected: names with path separators, whitespace or switch prefixes, and arguments overriding `-run=` or `-Project=`. There is no allowlist of commandlets, so note that **a commandlet can modify or delete project assets**
113
+ - `cook_content`, `package_project` and `run_editor_commandlet` refuse to run while the project's editor is registered and reachable (a second editor process contends for the same `Saved/`, `Intermediate/` and DDC paths, and write-capable commandlets race packages the live editor holds in memory) — pass `force: true` to override
114
+
115
+ ### `analyze_trace`
116
+
117
+ - Turns the `.utrace` that `stop_insights_trace` hands back into a readable summary; the binary container is otherwise a dead end for an assistant
118
+ - Runs the engine's `UnrealInsights` headlessly (`-OpenTraceFile=… -ExecOnAnalysisCompleteCmd=… -AutoQuit`), exports CSVs into a temp directory, parses them, and deletes the directory on every exit path including timeout and analyzer failure
119
+ - The analyzer is located through the same `resolveEngine` discovery as the build tools (`engineVersion` or `projectPath`) — no new path configuration
120
+ - Returns frame-time p50/p90/p99, the worst N hitches with timestamps, a CPU vs GPU split, and top-N scopes by inclusive and exclusive time. Every list is top-N, the response is byte-capped, and `truncated` names what was shortened
121
+ - Memory and LLM-tag totals are **not** reported: they do not fall out of this analysis pass
122
+ - Distinct failures: a missing/unreadable `.utrace` and an analyzer timeout or non-zero exit each raise their own error; an engine install with no Insights binary returns `state: 'unsupported'` with a reason instead of failing
123
+
124
+ ### `get_config_value` / `set_config_value` / `list_config_section`
125
+
126
+ - Read and write project ini settings through the **running editor's** config system rather than by touching files: the engine resolves the `Base*` → `Default*` → `Saved/Config` hierarchy and the `+`/`-`/`.`/`!` array operators, and a live editor rewrites its config on save, so a raw file write behind it is clobbered
127
+ - `file` is a closed enum (`Engine`, `Game`, `Input`, `Editor`, `EditorPerProjectUserSettings`) — the tools cannot be pointed at an arbitrary path
128
+ - `get_config_value` returns the resolved value, the ini it came from, and `resolvedFrom` (`engine_base` / `project_default` / `saved_user`), and reports `present: false` for an unset key so absent is distinguishable from present-but-empty
129
+ - `set_config_value` writes `Config/Default<File>.ini` by default (or the `Saved/Config` override with `scope: 'saved_user'`), flushes, mirrors the write into the merged runtime config so the live editor sees it without a restart, and returns the previous value. That previous value is the one the editor resolved across the whole hierarchy, not the contents of the layer being written: if it came from an engine or default layer, writing it back leaves the key materialised in the target layer rather than restoring the original state
130
+ - Values longer than the protocol bound (4096 characters — reachable with asset path lists and accumulated `+Array=` entries) come back shortened with `valueTruncated` / `previousValueTruncated` set, rather than failing the whole call
131
+ - `list_config_section` dumps one section as key/value pairs, sorted for a stable cursor and paged with `nextCursor` / `totalCount` / `truncated`
132
+ - All three require a registered editor; without one, `set_config_value` explains why instead of writing the file behind the editor's back
133
+
78
134
  ### `run_clang_tidy`
79
135
 
80
136
  - Reads the synced `compile_commands.json` from the provided `compileCommandsDir`