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.
- package/dist/context-cli.js +16 -16
- package/dist/engine-observer.js +68 -68
- package/dist/flow/guard.d.ts +26 -37
- package/dist/flow/guard.js +40 -25
- package/dist/flow/guard.js.map +1 -1
- package/dist/flow/guarded-bridge.d.ts +0 -10
- package/dist/flow/guarded-bridge.js +18 -23
- package/dist/flow/guarded-bridge.js.map +1 -1
- package/dist/flow/schema.d.ts +276 -16
- package/dist/flow/task-guards.d.ts +1 -1
- package/dist/flow/task-guards.js +44 -68
- package/dist/flow/task-guards.js.map +1 -1
- package/dist/instructions.js +130 -130
- package/dist/plugin-cli.js +299 -299
- package/dist/tool-counts.json +2 -2
- package/package.json +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +76 -76
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.h +27 -27
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +128 -128
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +63 -63
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +230 -230
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +323 -323
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +20 -20
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +537 -537
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +77 -77
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +353 -353
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +18 -18
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_InputRuntime.cpp +246 -246
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +597 -597
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +51 -51
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +878 -878
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +449 -449
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +275 -275
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +551 -551
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +531 -531
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +28 -28
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +677 -677
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +822 -822
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +22 -22
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +218 -218
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +17 -17
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.cpp +46 -46
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.h +23 -23
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/MCPExternalRegistry.cpp +83 -83
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -14
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/UE_MCP_BridgeStatusModule.cpp +37 -37
- package/dist/manifest-signature.d.ts +0 -1
- package/dist/manifest-signature.js +0 -53
- package/dist/manifest-signature.js.map +0 -1
- package/dist/pie/schema.d.ts +0 -791
- package/dist/pie/schema.js +0 -151
- package/dist/pie/schema.js.map +0 -1
- package/dist/watch-cli.js.map +0 -1
- /package/plugin/ue_mcp_bridge/{ue_mcp_bridge.uplugin → UE_MCP_Bridge.uplugin} +0 -0
package/dist/flow/task-guards.js
CHANGED
|
@@ -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.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"task-guards.js","sourceRoot":"","sources":["../../src/flow/task-guards.ts"],"names":[],"mappings":"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"}
|
package/dist/instructions.js
CHANGED
|
@@ -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
|