ue-mcp 1.2.1 → 1.2.2

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 (54) hide show
  1. package/dist/context-cli.js +16 -16
  2. package/dist/engine-observer.js +68 -68
  3. package/dist/flow/guard.d.ts +26 -37
  4. package/dist/flow/guard.js +40 -25
  5. package/dist/flow/guard.js.map +1 -1
  6. package/dist/flow/guarded-bridge.d.ts +0 -10
  7. package/dist/flow/guarded-bridge.js +18 -23
  8. package/dist/flow/guarded-bridge.js.map +1 -1
  9. package/dist/flow/schema.d.ts +276 -16
  10. package/dist/flow/task-guards.d.ts +1 -1
  11. package/dist/flow/task-guards.js +44 -68
  12. package/dist/flow/task-guards.js.map +1 -1
  13. package/dist/instructions.js +130 -130
  14. package/dist/plugin-cli.js +299 -299
  15. package/dist/tool-counts.json +2 -2
  16. package/package.json +2 -2
  17. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +76 -76
  18. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.h +27 -27
  19. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +128 -128
  20. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +63 -63
  21. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +230 -230
  22. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +323 -323
  23. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +20 -20
  24. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +537 -537
  25. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +77 -77
  26. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +353 -353
  27. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +18 -18
  28. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_InputRuntime.cpp +246 -246
  29. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +597 -597
  30. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +51 -51
  31. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +878 -878
  32. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +449 -449
  33. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +275 -275
  34. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +551 -551
  35. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +531 -531
  36. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +28 -28
  37. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +677 -677
  38. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +822 -822
  39. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +22 -22
  40. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +218 -218
  41. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +17 -17
  42. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.cpp +46 -46
  43. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.h +23 -23
  44. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/MCPExternalRegistry.cpp +83 -83
  45. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -14
  46. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/UE_MCP_BridgeStatusModule.cpp +37 -37
  47. package/dist/manifest-signature.d.ts +0 -1
  48. package/dist/manifest-signature.js +0 -53
  49. package/dist/manifest-signature.js.map +0 -1
  50. package/dist/pie/schema.d.ts +0 -791
  51. package/dist/pie/schema.js +0 -151
  52. package/dist/pie/schema.js.map +0 -1
  53. package/dist/watch-cli.js.map +0 -1
  54. /package/plugin/ue_mcp_bridge/{ue_mcp_bridge.uplugin → UE_MCP_Bridge.uplugin} +0 -0
@@ -10,20 +10,29 @@
10
10
  * - `afterWrite` run after a write-classified call
11
11
  *
12
12
  * No new plugin-activation concept is needed: the loader already registers every
13
- * `manifest.tasks` entry by name, so a `guard.*.*` task is picked up here. Each
14
- * matched task becomes one `BridgeGuard`. The core knows nothing about what a
15
- * guard does - source control, access policy, audit, and rate limiting are all
16
- * just guards.
13
+ * `manifest.tasks` entry by name, so a `guard.*.*` task is picked up here. The
14
+ * core knows nothing about what a guard does - source control, access policy,
15
+ * audit, and rate limiting are all just guards.
17
16
  *
18
- * A guard task is invoked with `{ method, params, paths }` (paths = the existing
19
- * on-disk files the call will touch, empty for non-writes) plus, for `after`
20
- * guards, `result`. A `before` guard denies the call by returning `success:false`
21
- * or throwing.
17
+ * The naming convention and the discovery walk are flowkit's; this module binds
18
+ * them to the bridge: the `write` scope comes from `write-methods.ts`, the guard
19
+ * task is invoked with `{ method, params, paths }` (plus `result` for `after`
20
+ * guards), and a denial surfaces as an `McpError` the tool layer already knows
21
+ * how to render.
22
22
  */
23
23
  import * as fs from "node:fs";
24
+ import { discoverTaskGuards as discoverFlowkitGuards } from "@db-lyon/flowkit/guard";
25
+ import { writeScope } from "./guard.js";
24
26
  import { McpError, ErrorCode } from "../errors.js";
25
- import { debug } from "../log.js";
26
- const GUARD_TASK_RE = /^guard\.(.+)\.(before|beforeWrite|after|afterWrite)$/;
27
+ import { debug, info } from "../log.js";
28
+ /** Adapts flowkit's logger to this server's `guard`-component logging. */
29
+ const GUARD_LOGGER = {
30
+ debug: (...args) => debug("guard", args.map(String).join(" ")),
31
+ info: (...args) => info("guard", args.map(String).join(" ")),
32
+ warn: (...args) => info("guard", args.map(String).join(" ")),
33
+ error: (...args) => info("guard", args.map(String).join(" ")),
34
+ child: () => GUARD_LOGGER,
35
+ };
27
36
  /** Resolve a UE content path to an absolute file, or null if it does not exist. */
28
37
  export function makeResolveExistingFile(project) {
29
38
  return (contentPath) => {
@@ -42,63 +51,30 @@ export function makeResolveExistingFile(project) {
42
51
  * guard that itself calls the bridge cannot recurse through the pipeline.
43
52
  */
44
53
  export function discoverTaskGuards(registry, ctx, rawBridge) {
45
- const guards = [];
46
- for (const taskName of registry.listRegistered()) {
47
- const m = GUARD_TASK_RE.exec(taskName);
48
- if (!m)
49
- continue;
50
- const [, name, phase] = m;
51
- const writeScoped = phase.endsWith("Write");
52
- const isBefore = phase.startsWith("before");
53
- const runTask = async (cc, result) => {
54
- // Bind the guard to the editor whose call it is guarding, not to
55
- // whichever bridge happened to be built first. cc.bridge is the RAW
56
- // bridge of the session serving this call, so a guard can neither
57
- // recurse through the pipeline nor act on another project's editor.
58
- const guardCtx = cc.session
59
- ? { ...ctx, bridge: cc.bridge, project: cc.session.project, session: cc.session }
60
- : { ...ctx, bridge: rawBridge };
61
- const options = {
62
- method: cc.method,
63
- params: cc.params,
64
- paths: cc.writeFiles(),
65
- };
66
- if (result !== undefined)
67
- options.result = result;
68
- try {
69
- const task = await registry.create(taskName, guardCtx, options);
70
- return await task.run();
71
- }
72
- catch (e) {
73
- throw new McpError(ErrorCode.WRITE_BLOCKED, `guard '${name}' errored on ${cc.method}: ${e.message}`);
74
- }
75
- };
76
- const guard = {
77
- name: `${name}.${phase}`,
78
- appliesTo: writeScoped ? (cc) => cc.writeFiles().length > 0 : undefined,
79
- };
80
- if (isBefore) {
81
- guard.before = async (cc) => {
82
- const r = await runTask(cc);
83
- if (!r.success) {
84
- const reason = r.error?.message ?? `denied by guard '${name}'`;
85
- const scope = cc.writeFiles().length ? ` on ${cc.writeFiles().join(", ")}` : "";
86
- throw new McpError(ErrorCode.WRITE_BLOCKED, `blocked (${cc.method})${scope}: ${reason}`);
87
- }
88
- debug("guard", `guard '${name}' allowed ${cc.method}`);
89
- };
90
- }
91
- else {
92
- // `after` guards observe the result for side effects (audit); a failing
93
- // after-guard is logged but does not fail the already-completed call.
94
- guard.after = async (cc, result) => {
95
- const r = await runTask(cc, result);
96
- if (!r.success)
97
- debug("guard", `after-guard '${name}' reported failure on ${cc.method}: ${r.error?.message}`);
98
- };
99
- }
100
- guards.push(guard);
101
- }
102
- return guards;
54
+ return discoverFlowkitGuards(registry, {
55
+ scopes: { write: writeScope },
56
+ // Bind the guard to the editor whose call it is guarding, not to whichever
57
+ // bridge happened to be built first. cc.bridge is the RAW bridge of the
58
+ // session serving this call, so a guard can neither recurse through the
59
+ // pipeline nor act on another project's editor.
60
+ contextFor: (cc) => cc.session
61
+ ? { ...ctx, bridge: cc.bridge, project: cc.session.project, session: cc.session }
62
+ : { ...ctx, bridge: rawBridge },
63
+ optionsFor: (cc, result) => ({
64
+ method: cc.method,
65
+ params: cc.params,
66
+ paths: cc.writeFiles(),
67
+ ...(result !== undefined ? { result } : {}),
68
+ }),
69
+ onDeny: (info) => {
70
+ const files = info.ctx.writeFiles();
71
+ const scope = files.length ? ` on ${files.join(", ")}` : "";
72
+ return new McpError(ErrorCode.WRITE_BLOCKED, `blocked (${info.ctx.method})${scope}: ${info.reason}`);
73
+ },
74
+ onError: (info) => new McpError(ErrorCode.WRITE_BLOCKED, `guard '${info.guard}' errored on ${info.ctx.method}: ${info.reason}`),
75
+ // A failing after-guard is logged but does not fail the already-completed call.
76
+ onAfterFailure: (info) => debug("guard", `after-guard '${info.guard}' reported failure on ${info.ctx.method}: ${info.reason}`),
77
+ logger: GUARD_LOGGER,
78
+ });
103
79
  }
104
80
  //# sourceMappingURL=task-guards.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-guards.js","sourceRoot":"","sources":["../../src/flow/task-guards.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-guards.js","sourceRoot":"","sources":["../../src/flow/task-guards.ts"],"names":[],"mappings":"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"}
@@ -35,145 +35,145 @@ function categoryList() {
35
35
  return lines.join("\n").replace(/\bepic\b(?![\w-])/, "epic (830 wrapped Unreal 5.8 tools; UE 5.8+)");
36
36
  }
37
37
  const CATEGORIES = categoryList();
38
- export const SERVER_INSTRUCTIONS = `UE-MCP: Unreal Engine editor bridge (C++ plugin) - ${CATEGORY_COUNT} category tools covering ${ACTION_COUNT} actions, plus 830 official Unreal 5.8 tools wrapped in-process (UE 5.8+; see the epic category).
39
-
40
- Every tool takes an "action" parameter that selects the operation. Call project(action="get_status") first.
41
-
42
- ═══ QUICK START ═══
43
- 1. project(action="get_status") - check if the editor is connected
44
- 2. If not connected: editor(action="start_editor") to launch UE
45
- 3. level(action="get_outliner") - see what's in the current level
46
- 4. asset(action="list") - browse project assets
47
- 5. reflection(action="reflect_class", className="StaticMeshActor") - understand any UE class
48
- 6. demo(action="step", stepIndex=1) through 19 - run the Neon Shrine demo to see the bridge in action
49
- 7. demo(action="cleanup") - clean up after the demo
50
-
51
- ═══ TOOLS ═══
52
-
53
- Every category tool lists its own actions (and each action's parameters) in
54
- its description - read the description of the category you need. Categories:
55
- ${CATEGORIES}.
56
-
57
- ═══ TIPS ═══
58
- • Start with level(action="get_outliner") or asset(action="list") to discover what's in the project.
59
- • Use reflection(action="reflect_class") to understand any UE class's properties.
60
- • asset(action="search", query="/Game/Characters/*") accepts wildcards.
61
- • For BP scripting: blueprint(action="search_node_types") → blueprint(action="add_node") → blueprint(action="connect_pins").
62
- • editor(action="execute_python") is the escape hatch for any Unreal Python API call.
63
- • Animation tools need a skeleton path - use animation(action="list_skeletal_meshes") to find it.
64
- • Editor lifecycle: editor(action="stop_editor") / editor(action="start_editor") / editor(action="restart_editor") manage the UE process. editor(action="build_project") builds the project C++ code (stop the editor first).
65
- • editor(action="hot_reload") triggers Live Coding compilation without restarting the editor.
66
- • editor(action="focus_on_actor", actorLabel="MyActor") snaps the viewport to any actor.
67
- • Log output: editor(action="get_log", category="LogMCPBridge") to see bridge-specific logs.
68
-
69
- ═══ FLOWS - READ BEFORE ACTING ═══
70
-
71
- Before you run bash/npm commands or chain 3+ category tool calls to
72
- satisfy a user request, look at the \`flows\` field returned by
73
- project(action="get_status").
74
-
75
- That field lists named, pre-built sequences for this project. Each
76
- entry has a name and description. If ANY flow's description matches
77
- what the user asked for, you MUST run it instead of building the
78
- sequence yourself.
79
-
80
- Examples:
81
- User asks | Look for a flow like
82
- ---------------------------------- | ------------------------------
83
- "rebuild and relaunch the editor" | rebuild
84
- "run the smoke tests" | smoke
85
- "redeploy the plugin" | deploy, redeploy
86
- "package the project" | package
87
-
88
- Run a matched flow with: flow(action="run", flowName="<name>")
89
-
90
- DO NOT:
91
- - Skip the get_status flows check before running bash/npm yourself.
92
- - Author a new flow on your own. Only the user authors flows.
93
- - Suggest a flow for a one-off task the user is unlikely to repeat.
94
-
95
- DO suggest a new flow IF AND ONLY IF all three are true:
96
- 1. You just finished a sequence with 3+ steps.
97
- 2. The sequence had the same shape every run, with only 1-2 values
98
- changing.
99
- 3. The user is likely to ask for the same shape again.
100
- In that case say: "This sequence (X -> Y -> Z) might be worth registering
101
- as a flow in ue-mcp.yml. Want me to draft one?" Then STOP. Wait.
102
-
103
- ═══ FEEDBACK ═══
104
- If you had to use editor(action="execute_python") as a workaround because a native tool
105
- couldn't handle the task, keep a mental note of what you did and why. When your task is
106
- complete, tell the user:
107
- "I had to use custom Python scripts to [describe what]. Would you like to submit
108
- feedback to help improve ue-mcp?"
109
- If the user agrees, call feedback(action="submit") with:
110
- • title - short, generic description of the gap (no project-specific details)
111
- • summary - what was attempted and why the native tool fell short
112
- • pythonWorkaround - the Python code that was used
113
- • idealTool - what tool/action should handle this natively
114
- This creates a GitHub issue so the maintainers can add proper support.
115
-
116
- Not every gap belongs to ue-mcp core. Plugins (PIE Studio, Perforce, Meshy, ...)
117
- own their own surfaces and their own trackers. submit checks the plugin registry
118
- and aims the issue at the owning repo on its own, and the approval prompt lets
119
- the user change it - do NOT set the repo parameter yourself unless the user
120
- names a repo. feedback(action="route") answers "where would this land?" without
121
- posting anything.
38
+ export const SERVER_INSTRUCTIONS = `UE-MCP: Unreal Engine editor bridge (C++ plugin) - ${CATEGORY_COUNT} category tools covering ${ACTION_COUNT} actions, plus 830 official Unreal 5.8 tools wrapped in-process (UE 5.8+; see the epic category).
39
+
40
+ Every tool takes an "action" parameter that selects the operation. Call project(action="get_status") first.
41
+
42
+ ═══ QUICK START ═══
43
+ 1. project(action="get_status") - check if the editor is connected
44
+ 2. If not connected: editor(action="start_editor") to launch UE
45
+ 3. level(action="get_outliner") - see what's in the current level
46
+ 4. asset(action="list") - browse project assets
47
+ 5. reflection(action="reflect_class", className="StaticMeshActor") - understand any UE class
48
+ 6. demo(action="step", stepIndex=1) through 19 - run the Neon Shrine demo to see the bridge in action
49
+ 7. demo(action="cleanup") - clean up after the demo
50
+
51
+ ═══ TOOLS ═══
52
+
53
+ Every category tool lists its own actions (and each action's parameters) in
54
+ its description - read the description of the category you need. Categories:
55
+ ${CATEGORIES}.
56
+
57
+ ═══ TIPS ═══
58
+ • Start with level(action="get_outliner") or asset(action="list") to discover what's in the project.
59
+ • Use reflection(action="reflect_class") to understand any UE class's properties.
60
+ • asset(action="search", query="/Game/Characters/*") accepts wildcards.
61
+ • For BP scripting: blueprint(action="search_node_types") → blueprint(action="add_node") → blueprint(action="connect_pins").
62
+ • editor(action="execute_python") is the escape hatch for any Unreal Python API call.
63
+ • Animation tools need a skeleton path - use animation(action="list_skeletal_meshes") to find it.
64
+ • Editor lifecycle: editor(action="stop_editor") / editor(action="start_editor") / editor(action="restart_editor") manage the UE process. editor(action="build_project") builds the project C++ code (stop the editor first).
65
+ • editor(action="hot_reload") triggers Live Coding compilation without restarting the editor.
66
+ • editor(action="focus_on_actor", actorLabel="MyActor") snaps the viewport to any actor.
67
+ • Log output: editor(action="get_log", category="LogMCPBridge") to see bridge-specific logs.
68
+
69
+ ═══ FLOWS - READ BEFORE ACTING ═══
70
+
71
+ Before you run bash/npm commands or chain 3+ category tool calls to
72
+ satisfy a user request, look at the \`flows\` field returned by
73
+ project(action="get_status").
74
+
75
+ That field lists named, pre-built sequences for this project. Each
76
+ entry has a name and description. If ANY flow's description matches
77
+ what the user asked for, you MUST run it instead of building the
78
+ sequence yourself.
79
+
80
+ Examples:
81
+ User asks | Look for a flow like
82
+ ---------------------------------- | ------------------------------
83
+ "rebuild and relaunch the editor" | rebuild
84
+ "run the smoke tests" | smoke
85
+ "redeploy the plugin" | deploy, redeploy
86
+ "package the project" | package
87
+
88
+ Run a matched flow with: flow(action="run", flowName="<name>")
89
+
90
+ DO NOT:
91
+ - Skip the get_status flows check before running bash/npm yourself.
92
+ - Author a new flow on your own. Only the user authors flows.
93
+ - Suggest a flow for a one-off task the user is unlikely to repeat.
94
+
95
+ DO suggest a new flow IF AND ONLY IF all three are true:
96
+ 1. You just finished a sequence with 3+ steps.
97
+ 2. The sequence had the same shape every run, with only 1-2 values
98
+ changing.
99
+ 3. The user is likely to ask for the same shape again.
100
+ In that case say: "This sequence (X -> Y -> Z) might be worth registering
101
+ as a flow in ue-mcp.yml. Want me to draft one?" Then STOP. Wait.
102
+
103
+ ═══ FEEDBACK ═══
104
+ If you had to use editor(action="execute_python") as a workaround because a native tool
105
+ couldn't handle the task, keep a mental note of what you did and why. When your task is
106
+ complete, tell the user:
107
+ "I had to use custom Python scripts to [describe what]. Would you like to submit
108
+ feedback to help improve ue-mcp?"
109
+ If the user agrees, call feedback(action="submit") with:
110
+ • title - short, generic description of the gap (no project-specific details)
111
+ • summary - what was attempted and why the native tool fell short
112
+ • pythonWorkaround - the Python code that was used
113
+ • idealTool - what tool/action should handle this natively
114
+ This creates a GitHub issue so the maintainers can add proper support.
115
+
116
+ Not every gap belongs to ue-mcp core. Plugins (PIE Studio, Perforce, Meshy, ...)
117
+ own their own surfaces and their own trackers. submit checks the plugin registry
118
+ and aims the issue at the owning repo on its own, and the approval prompt lets
119
+ the user change it - do NOT set the repo parameter yourself unless the user
120
+ names a repo. feedback(action="route") answers "where would this land?" without
121
+ posting anything.
122
122
  `;
123
123
  // Compact instructions used when context.strategy = "lean". The per-action
124
124
  // catalog is intentionally omitted: agents pull it on demand via the `catalog`
125
125
  // tool or a category's `describe` action. This keeps the initialize handshake
126
126
  // small for token-constrained clients while preserving full capability.
127
- export const SERVER_INSTRUCTIONS_LEAN = `UE-MCP (lean mode): Unreal Engine editor bridge (C++ plugin). ${CATEGORY_COUNT} category tools covering ${ACTION_COUNT} actions; the per-action catalog is loaded on demand to keep context small.
128
-
129
- Every tool takes an "action" parameter that selects the operation. Start with project(action="get_status").
130
-
131
- ═══ DISCOVER ACTIONS ═══
132
- Tool descriptions are trimmed in lean mode. Find the action you need with:
133
- - catalog(action="search", query="spawn actor") - rank matching actions across every category
134
- - catalog(action="list_categories") - the ${CATEGORY_COUNT} categories with one-line summaries
135
- - <category>(action="describe") - every action in one category (e.g. blueprint(action="describe"))
136
-
137
- Each category's "action" parameter is still a validated enum, so unknown actions are rejected up front. Call describe/search first when you are unsure of the exact action name.
138
-
139
- ═══ CATEGORIES ═══
140
- ${CATEGORIES}.
141
-
142
- ═══ FLOWS ═══
143
- Before chaining 3+ tool calls, check the \`flows\` field from project(action="get_status")
144
- and run a matching flow with flow(action="run", flowName="<name>") instead of rebuilding it.
145
-
146
- ═══ FEEDBACK ═══
147
- If you had to fall back to editor(action="execute_python") because a native tool could not
148
- do the job, tell the user when done and offer to feedback(action="submit") the gap. submit
149
- routes the issue to the tracker that owns the surface (core, or the plugin that provides it)
150
- by checking the plugin registry; feedback(action="route") previews that without posting.
151
-
152
- Full mode (every action listed inline) is the default. This lean surface is selected by
153
- context.strategy: lean in ue-mcp.yml or UE_MCP_CONTEXT_STRATEGY=lean.
127
+ export const SERVER_INSTRUCTIONS_LEAN = `UE-MCP (lean mode): Unreal Engine editor bridge (C++ plugin). ${CATEGORY_COUNT} category tools covering ${ACTION_COUNT} actions; the per-action catalog is loaded on demand to keep context small.
128
+
129
+ Every tool takes an "action" parameter that selects the operation. Start with project(action="get_status").
130
+
131
+ ═══ DISCOVER ACTIONS ═══
132
+ Tool descriptions are trimmed in lean mode. Find the action you need with:
133
+ - catalog(action="search", query="spawn actor") - rank matching actions across every category
134
+ - catalog(action="list_categories") - the ${CATEGORY_COUNT} categories with one-line summaries
135
+ - <category>(action="describe") - every action in one category (e.g. blueprint(action="describe"))
136
+
137
+ Each category's "action" parameter is still a validated enum, so unknown actions are rejected up front. Call describe/search first when you are unsure of the exact action name.
138
+
139
+ ═══ CATEGORIES ═══
140
+ ${CATEGORIES}.
141
+
142
+ ═══ FLOWS ═══
143
+ Before chaining 3+ tool calls, check the \`flows\` field from project(action="get_status")
144
+ and run a matching flow with flow(action="run", flowName="<name>") instead of rebuilding it.
145
+
146
+ ═══ FEEDBACK ═══
147
+ If you had to fall back to editor(action="execute_python") because a native tool could not
148
+ do the job, tell the user when done and offer to feedback(action="submit") the gap. submit
149
+ routes the issue to the tracker that owns the surface (core, or the plugin that provides it)
150
+ by checking the plugin registry; feedback(action="route") previews that without posting.
151
+
152
+ Full mode (every action listed inline) is the default. This lean surface is selected by
153
+ context.strategy: lean in ue-mcp.yml or UE_MCP_CONTEXT_STRATEGY=lean.
154
154
  `;
155
155
  // Smallest surface (context.strategy = "micro"). The entire ue-mcp API is
156
156
  // reached through one gateway tool, mirroring the native MCP toolset gateway
157
157
  // (list_toolsets / describe_toolset / call_tool). Nothing else is advertised.
158
- export const SERVER_INSTRUCTIONS_MICRO = `UE-MCP (micro mode): Unreal Engine editor bridge (C++ plugin). The entire surface (${CATEGORY_COUNT} categories, ${ACTION_COUNT} actions) is reached through a single gateway tool to keep context tiny.
159
-
160
- ═══ HOW TO USE ═══
161
- - tools(action="list_categories") - list every category with a one-line summary
162
- - tools(action="describe", category="blueprint") - list a category's actions and how to call them
163
- - tools(action="call", category="blueprint", method="create", args={ ... }) - invoke any action
164
-
165
- \`method\` is the action name; \`args\` is the object of that action's parameters.
166
- Start with: tools(action="call", category="project", method="get_status").
167
-
168
- ═══ CATEGORIES ═══
169
- ${CATEGORIES}.
170
-
171
- ═══ FLOWS ═══
172
- flow(action="run", flowName="<name>") runs a named sequence; see the \`flows\` field
173
- from tools(action="call", category="project", method="get_status").
174
-
175
- Full mode (every action listed inline) is the default. This micro surface is selected by
176
- context.strategy: micro in ue-mcp.yml or UE_MCP_CONTEXT_STRATEGY=micro.
158
+ export const SERVER_INSTRUCTIONS_MICRO = `UE-MCP (micro mode): Unreal Engine editor bridge (C++ plugin). The entire surface (${CATEGORY_COUNT} categories, ${ACTION_COUNT} actions) is reached through a single gateway tool to keep context tiny.
159
+
160
+ ═══ HOW TO USE ═══
161
+ - tools(action="list_categories") - list every category with a one-line summary
162
+ - tools(action="describe", category="blueprint") - list a category's actions and how to call them
163
+ - tools(action="call", category="blueprint", method="create", args={ ... }) - invoke any action
164
+
165
+ \`method\` is the action name; \`args\` is the object of that action's parameters.
166
+ Start with: tools(action="call", category="project", method="get_status").
167
+
168
+ ═══ CATEGORIES ═══
169
+ ${CATEGORIES}.
170
+
171
+ ═══ FLOWS ═══
172
+ flow(action="run", flowName="<name>") runs a named sequence; see the \`flows\` field
173
+ from tools(action="call", category="project", method="get_status").
174
+
175
+ Full mode (every action listed inline) is the default. This micro surface is selected by
176
+ context.strategy: micro in ue-mcp.yml or UE_MCP_CONTEXT_STRATEGY=micro.
177
177
  `;
178
178
  /**
179
179
  * Targeting block, appended to whichever instruction variant is in use, and