ultimate-unreal-engine-mcp 0.1.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 (124) hide show
  1. package/README.md +729 -0
  2. package/dist/build/error-parser.js +51 -0
  3. package/dist/build/fix-suggester.js +84 -0
  4. package/dist/build/ubt-runner.js +146 -0
  5. package/dist/cli.js +13 -0
  6. package/dist/config.js +8 -0
  7. package/dist/docs/data/ue57-api.js +228 -0
  8. package/dist/docs/doc-index.js +110 -0
  9. package/dist/docs/types.js +4 -0
  10. package/dist/generators/class-generator.js +363 -0
  11. package/dist/generators/file-modifier.js +276 -0
  12. package/dist/generators/uht-validator.js +177 -0
  13. package/dist/index.js +89 -0
  14. package/dist/parsers/cpp-class-index.js +230 -0
  15. package/dist/parsers/cpp-parser.js +369 -0
  16. package/dist/parsers/ini-parser.js +216 -0
  17. package/dist/parsers/uproject-parser.js +130 -0
  18. package/dist/plugin-bridge/client.js +217 -0
  19. package/dist/plugin-bridge/protocol.js +6 -0
  20. package/dist/plugin-bridge/retry.js +23 -0
  21. package/dist/setup.js +209 -0
  22. package/dist/tools/ai-systems/index.js +247 -0
  23. package/dist/tools/ai-systems/types.js +4 -0
  24. package/dist/tools/animation/index.js +241 -0
  25. package/dist/tools/animation/types.js +4 -0
  26. package/dist/tools/audio/index.js +204 -0
  27. package/dist/tools/audio/types.js +4 -0
  28. package/dist/tools/blueprint/index.js +495 -0
  29. package/dist/tools/blueprint/types.js +4 -0
  30. package/dist/tools/build/index.js +163 -0
  31. package/dist/tools/chaos/index.js +230 -0
  32. package/dist/tools/chaos/types.js +4 -0
  33. package/dist/tools/collision-physics/index.js +211 -0
  34. package/dist/tools/config/index.js +288 -0
  35. package/dist/tools/cpp/index.js +305 -0
  36. package/dist/tools/docs/index.js +251 -0
  37. package/dist/tools/editor/index.js +242 -0
  38. package/dist/tools/gas/index.js +222 -0
  39. package/dist/tools/gas/types.js +5 -0
  40. package/dist/tools/import-export/index.js +218 -0
  41. package/dist/tools/input/index.js +146 -0
  42. package/dist/tools/known-issues/index.js +88 -0
  43. package/dist/tools/known-issues/middleware.js +55 -0
  44. package/dist/tools/known-issues/store.js +125 -0
  45. package/dist/tools/livelink/index.js +203 -0
  46. package/dist/tools/livelink/types.js +4 -0
  47. package/dist/tools/material/index.js +190 -0
  48. package/dist/tools/motion-design/index.js +251 -0
  49. package/dist/tools/motion-design/types.js +6 -0
  50. package/dist/tools/movie-render/index.js +220 -0
  51. package/dist/tools/networking/index.js +149 -0
  52. package/dist/tools/pcg/index.js +164 -0
  53. package/dist/tools/selection/index.js +180 -0
  54. package/dist/tools/sequencer/index.js +218 -0
  55. package/dist/tools/validation/index.js +183 -0
  56. package/dist/tools/validation/types.js +4 -0
  57. package/dist/tools/viewport/index.js +310 -0
  58. package/dist/tools/worldpartition/index.js +226 -0
  59. package/dist/tools/worldpartition/types.js +4 -0
  60. package/dist/utils/execFileNoThrow.js +40 -0
  61. package/dist/utils/logger.js +27 -0
  62. package/dist/utils/path-guard.js +26 -0
  63. package/package.json +40 -0
  64. package/unreal-plugin/MCPBridge/MCPBridge.uplugin +29 -0
  65. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/MCPBridgeEditor.Build.cs +68 -0
  66. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAICommands.cpp +919 -0
  67. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAICommands.h +23 -0
  68. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPActorCommands.cpp +415 -0
  69. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPActorCommands.h +16 -0
  70. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAnimationCommands.cpp +653 -0
  71. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAnimationCommands.h +24 -0
  72. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAssetCommands.cpp +290 -0
  73. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAssetCommands.h +17 -0
  74. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAudioCommands.cpp +624 -0
  75. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPAudioCommands.h +22 -0
  76. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBlueprintHandlers.cpp +616 -0
  77. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBlueprintHandlers.h +25 -0
  78. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBlueprintWriteHandlers.cpp +744 -0
  79. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBlueprintWriteHandlers.h +24 -0
  80. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBridgeEditor.cpp +23 -0
  81. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBridgeSubsystem.cpp +149 -0
  82. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPBridgeSubsystem.h +38 -0
  83. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPChaosCommands.cpp +771 -0
  84. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPChaosCommands.h +22 -0
  85. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPCollisionPhysicsCommands.cpp +749 -0
  86. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPCollisionPhysicsCommands.h +22 -0
  87. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPEditorStateCommands.cpp +172 -0
  88. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPEditorStateCommands.h +16 -0
  89. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPGASCommands.cpp +715 -0
  90. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPGASCommands.h +22 -0
  91. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPImportExportCommands.cpp +679 -0
  92. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPImportExportCommands.h +22 -0
  93. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPInputHandlers.cpp +381 -0
  94. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPInputHandlers.h +24 -0
  95. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPLiveLinkCommands.cpp +504 -0
  96. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPLiveLinkCommands.h +22 -0
  97. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMaterialCommands.cpp +511 -0
  98. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMaterialCommands.h +22 -0
  99. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMotionDesignCommands.cpp +1110 -0
  100. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMotionDesignCommands.h +28 -0
  101. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMovieRenderCommands.cpp +590 -0
  102. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPMovieRenderCommands.h +16 -0
  103. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPNetworkingCommands.cpp +482 -0
  104. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPNetworkingCommands.h +16 -0
  105. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPPieCommands.cpp +338 -0
  106. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPPieCommands.h +16 -0
  107. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPSelectionCommands.cpp +677 -0
  108. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPSelectionCommands.h +22 -0
  109. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPSequencerCommands.cpp +721 -0
  110. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPSequencerCommands.h +16 -0
  111. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPValidationCommands.cpp +368 -0
  112. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPValidationCommands.h +22 -0
  113. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPViewportCommands.cpp +1208 -0
  114. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPViewportCommands.h +29 -0
  115. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPWorldPartitionCommands.cpp +822 -0
  116. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Private/MCPWorldPartitionCommands.h +23 -0
  117. package/unreal-plugin/MCPBridge/Source/MCPBridgeEditor/Public/MCPBridgeEditor.h +14 -0
  118. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/MCPBridgeRuntime.Build.cs +28 -0
  119. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Private/MCPBridgeRuntime.cpp +22 -0
  120. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Private/MCPCommandRouter.cpp +118 -0
  121. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Private/MCPTcpServer.cpp +196 -0
  122. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Public/MCPBridgeRuntime.h +15 -0
  123. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Public/MCPCommandRouter.h +55 -0
  124. package/unreal-plugin/MCPBridge/Source/MCPBridgeRuntime/Public/MCPTcpServer.h +59 -0
@@ -0,0 +1,183 @@
1
+ // src/tools/validation/index.ts
2
+ // MCP tool implementations for UE data validation and Blueprint compile-check (Phase 16).
3
+ // All tools route commands through PluginBridgeClient to the C++ MCPBridge handlers.
4
+ // Returns structured plugin_not_connected errors when the plugin is absent.
5
+ import { z } from 'zod';
6
+ import { withKnownIssues } from '../known-issues/middleware.js';
7
+ import { PluginBridgeClient, PluginNotConnectedError } from '../../plugin-bridge/client.js';
8
+ // Module-level bridge instance — injected in tests via exported handler signatures.
9
+ const bridge = new PluginBridgeClient();
10
+ // ---------------------------------------------------------------------------
11
+ // sendOrDisconnect helper
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Sends a command to the bridge and returns a ToolResult.
15
+ *
16
+ * - On success (response.success true): returns data as JSON text.
17
+ * - On command-level failure (response.success false): returns isError:true with error JSON.
18
+ * - On PluginNotConnectedError: returns isError:true with plugin_not_connected JSON.
19
+ * - On other errors: rethrows (withKnownIssues catches and formats).
20
+ *
21
+ * NOTE: sendCommand() overwrites correlationId with crypto.randomUUID() internally;
22
+ * passing an empty string is safe and correct (per STATE.md decision).
23
+ */
24
+ async function sendOrDisconnect(b, cmd) {
25
+ try {
26
+ const response = await b.sendCommand({ ...cmd, correlationId: '' });
27
+ if (!response.success) {
28
+ return {
29
+ isError: true,
30
+ content: [{ type: 'text', text: JSON.stringify({ error: response.error }) }],
31
+ };
32
+ }
33
+ return {
34
+ content: [{ type: 'text', text: JSON.stringify(response.data ?? {}) }],
35
+ };
36
+ }
37
+ catch (err) {
38
+ if (err instanceof PluginNotConnectedError) {
39
+ return {
40
+ isError: true,
41
+ content: [{ type: 'text', text: JSON.stringify(err.bridgeError) }],
42
+ };
43
+ }
44
+ throw err; // withKnownIssues catches unexpected errors
45
+ }
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Exported handler functions (for direct unit testing via bridge injection)
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * ue_validate_asset handler — satisfies VAL-01.
52
+ * Sends validate.asset to the plugin; returns structured pass/fail with error/warning counts.
53
+ *
54
+ * @param args Tool arguments including asset_path.
55
+ * @param b PluginBridgeClient instance (defaults to module-level singleton).
56
+ */
57
+ export async function handleValidateAsset(args, b = bridge) {
58
+ // Response data shape: ValidationAssetResult
59
+ return sendOrDisconnect(b, {
60
+ type: 'validate.asset',
61
+ payload: { asset_path: args.asset_path },
62
+ });
63
+ }
64
+ /**
65
+ * ue_validate_folder handler — satisfies VAL-02.
66
+ * Sends validate.folder to the plugin; returns per-folder summary with asset counts.
67
+ *
68
+ * @param args Tool arguments including folder_path.
69
+ * @param b PluginBridgeClient instance (defaults to module-level singleton).
70
+ */
71
+ export async function handleValidateFolder(args, b = bridge) {
72
+ // Response data shape: ValidationFolderResult
73
+ return sendOrDisconnect(b, {
74
+ type: 'validate.folder',
75
+ payload: { folder_path: args.folder_path },
76
+ });
77
+ }
78
+ /**
79
+ * ue_validate_project handler — satisfies VAL-03.
80
+ * Sends validate.project to the plugin; returns categorized project-wide counts.
81
+ *
82
+ * @param _args No input arguments (empty record).
83
+ * @param b PluginBridgeClient instance (defaults to module-level singleton).
84
+ */
85
+ export async function handleValidateProject(_args, b = bridge) {
86
+ return sendOrDisconnect(b, { type: 'validate.project' });
87
+ }
88
+ /**
89
+ * ue_check_blueprint handler — satisfies VAL-04.
90
+ * Sends validate.blueprint to the plugin; returns compiled:bool with status and errorMessage.
91
+ *
92
+ * @param args Tool arguments including asset_path.
93
+ * @param b PluginBridgeClient instance (defaults to module-level singleton).
94
+ */
95
+ export async function handleCheckBlueprint(args, b = bridge) {
96
+ // Response data shape: BlueprintCompileResult
97
+ return sendOrDisconnect(b, {
98
+ type: 'validate.blueprint',
99
+ payload: { asset_path: args.asset_path },
100
+ });
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // registerValidationTools
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Register UE data validation and Blueprint compile-check tools on the MCP server.
107
+ *
108
+ * All tools in this domain require the MCPBridge editor plugin.
109
+ * When the plugin is not connected, each handler returns:
110
+ * { isError: true, content: [{ type: 'text', text: <plugin_not_connected JSON> }] }
111
+ *
112
+ * Tools registered (Phase 16):
113
+ * ue_validate_asset — VAL-01: Run data validation on a single asset
114
+ * ue_validate_folder — VAL-02: Run data validation on all assets in a folder
115
+ * ue_validate_project — VAL-03: Run data validation across all /Game/ assets
116
+ * ue_check_blueprint — VAL-04: Compile-check a Blueprint asset
117
+ *
118
+ * @param server The McpServer instance to register tools on.
119
+ * @param bridge Optional PluginBridgeClient for testing (defaults to a new instance).
120
+ */
121
+ export function registerValidationTools(server, bridge) {
122
+ const _bridge = bridge ?? new PluginBridgeClient();
123
+ // --------------------------------------------------------------------------
124
+ // ue_validate_asset (VAL-01)
125
+ // --------------------------------------------------------------------------
126
+ server.registerTool('ue_validate_asset', {
127
+ title: 'Validate UE Asset',
128
+ description: '[requires_plugin] Run UE data validation rules on a single asset and return structured pass/fail results with error and warning counts.',
129
+ inputSchema: z.object({
130
+ asset_path: z
131
+ .string()
132
+ .describe('UE long package path, e.g. /Game/Blueprints/BP_MyActor'),
133
+ }),
134
+ annotations: {
135
+ readOnlyHint: true,
136
+ destructiveHint: false,
137
+ },
138
+ }, withKnownIssues('ue_validate_asset', async (args) => handleValidateAsset(args, _bridge)));
139
+ // --------------------------------------------------------------------------
140
+ // ue_validate_folder (VAL-02)
141
+ // --------------------------------------------------------------------------
142
+ server.registerTool('ue_validate_folder', {
143
+ title: 'Validate UE Assets in Folder',
144
+ description: '[requires_plugin] Run UE data validation on all assets under a folder path and return a summary report.',
145
+ inputSchema: z.object({
146
+ folder_path: z
147
+ .string()
148
+ .describe('UE package path prefix, e.g. /Game/Blueprints'),
149
+ }),
150
+ annotations: {
151
+ readOnlyHint: true,
152
+ destructiveHint: false,
153
+ },
154
+ }, withKnownIssues('ue_validate_folder', async (args) => handleValidateFolder(args, _bridge)));
155
+ // --------------------------------------------------------------------------
156
+ // ue_validate_project (VAL-03)
157
+ // --------------------------------------------------------------------------
158
+ server.registerTool('ue_validate_project', {
159
+ title: 'Validate All Project Assets',
160
+ description: '[requires_plugin] Run UE data validation across all /Game/ assets and return categorized error, warning, and info counts.',
161
+ inputSchema: z.object({}),
162
+ annotations: {
163
+ readOnlyHint: true,
164
+ destructiveHint: false,
165
+ },
166
+ }, withKnownIssues('ue_validate_project', async (_args) => handleValidateProject({}, _bridge)));
167
+ // --------------------------------------------------------------------------
168
+ // ue_check_blueprint (VAL-04)
169
+ // --------------------------------------------------------------------------
170
+ server.registerTool('ue_check_blueprint', {
171
+ title: 'Check Blueprint Compilation',
172
+ description: '[requires_plugin] Compile-check a Blueprint asset and return structured compiler messages indicating success or failure.',
173
+ inputSchema: z.object({
174
+ asset_path: z
175
+ .string()
176
+ .describe('UE long package path to the Blueprint asset, e.g. /Game/Blueprints/BP_MyActor'),
177
+ }),
178
+ annotations: {
179
+ readOnlyHint: false,
180
+ destructiveHint: false,
181
+ },
182
+ }, withKnownIssues('ue_check_blueprint', async (args) => handleCheckBlueprint(args, _bridge)));
183
+ }
@@ -0,0 +1,4 @@
1
+ // src/tools/validation/types.ts
2
+ // TypeScript result interfaces for the four validation MCP tools (Phase 16).
3
+ // These interfaces mirror the JSON shapes returned by the C++ handlers in Plan 01.
4
+ export {};
@@ -0,0 +1,310 @@
1
+ // src/tools/viewport/index.ts
2
+ // MCP tool implementations for editor state, PIE control, and viewport operations (Phase 12).
3
+ // All tools route commands through PluginBridgeClient to the C++ MCPBridge plugin.
4
+ // Returns structured plugin_not_connected errors when the plugin is absent.
5
+ import { z } from 'zod';
6
+ import { withKnownIssues } from '../known-issues/middleware.js';
7
+ import { PluginBridgeClient, PluginNotConnectedError } from '../../plugin-bridge/client.js';
8
+ // ---------------------------------------------------------------------------
9
+ // sendOrDisconnect helper
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Sends a command to the bridge and returns a ToolResult.
13
+ *
14
+ * - On success (response.success true): returns data as JSON text.
15
+ * - On command-level failure (response.success false): returns isError:true with error JSON.
16
+ * - On PluginNotConnectedError: returns isError:true with plugin_not_connected JSON.
17
+ * - On other errors: rethrows (withKnownIssues catches and formats).
18
+ *
19
+ * NOTE: sendCommand() overwrites correlationId with crypto.randomUUID() internally;
20
+ * passing an empty string is safe and correct (per STATE.md decision).
21
+ */
22
+ async function sendOrDisconnect(bridge, cmd) {
23
+ try {
24
+ const response = await bridge.sendCommand({ ...cmd, correlationId: '' });
25
+ if (!response.success) {
26
+ return {
27
+ isError: true,
28
+ content: [{ type: 'text', text: JSON.stringify({ error: response.error }) }],
29
+ };
30
+ }
31
+ return {
32
+ content: [{ type: 'text', text: JSON.stringify(response.data ?? {}) }],
33
+ };
34
+ }
35
+ catch (err) {
36
+ if (err instanceof PluginNotConnectedError) {
37
+ return {
38
+ isError: true,
39
+ content: [{ type: 'text', text: JSON.stringify(err.bridgeError) }],
40
+ };
41
+ }
42
+ throw err; // withKnownIssues catches unexpected errors
43
+ }
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // registerViewportTools
47
+ // ---------------------------------------------------------------------------
48
+ /**
49
+ * Register UE Editor viewport, PIE control, and editor state tools on the MCP server.
50
+ *
51
+ * All tools in this domain require the MCPBridge editor plugin.
52
+ * When the plugin is not connected, each handler returns:
53
+ * { isError: true, content: [{ type: 'text', text: <plugin_not_connected JSON> }] }
54
+ *
55
+ * Tools registered (Phase 12):
56
+ * ue_editor_state — Query selected actors, open assets, viewport camera
57
+ * ue_pie_start — Start a PIE session
58
+ * ue_pie_stop — Stop the active PIE session
59
+ * ue_pie_logs — Read PIE output log lines
60
+ * ue_pie_game_state — Query runtime game state during PIE
61
+ * ue_viewport_screenshot — Capture viewport as screenshot
62
+ * ue_viewport_camera — Control viewport camera position/rotation/FOV
63
+ * ue_viewport_render_mode — Switch viewport render mode
64
+ * ue_viewport_hires_screenshot — Take a high-resolution screenshot
65
+ *
66
+ * @param server The McpServer instance to register tools on.
67
+ * @param bridge Optional PluginBridgeClient for testing (defaults to a new instance).
68
+ */
69
+ export function registerViewportTools(server, bridge) {
70
+ const _bridge = bridge ?? new PluginBridgeClient();
71
+ // --------------------------------------------------------------------------
72
+ // ue_editor_state
73
+ // --------------------------------------------------------------------------
74
+ server.registerTool('ue_editor_state', {
75
+ title: 'Query UE Editor State',
76
+ description: '[requires_plugin] Query the current UE Editor state — selected actors, open assets, and viewport camera position.',
77
+ inputSchema: z.object({}),
78
+ annotations: {
79
+ readOnlyHint: true,
80
+ destructiveHint: false,
81
+ },
82
+ }, withKnownIssues('ue_editor_state', async (_args) => {
83
+ return sendOrDisconnect(_bridge, { type: 'editor.state' });
84
+ }));
85
+ // --------------------------------------------------------------------------
86
+ // ue_pie_start
87
+ // --------------------------------------------------------------------------
88
+ server.registerTool('ue_pie_start', {
89
+ title: 'Start PIE Session',
90
+ description: '[requires_plugin] Start a Play In Editor (PIE) session.',
91
+ inputSchema: z.object({}),
92
+ annotations: {
93
+ readOnlyHint: false,
94
+ destructiveHint: false,
95
+ },
96
+ }, withKnownIssues('ue_pie_start', async (_args) => {
97
+ return sendOrDisconnect(_bridge, { type: 'pie.start' });
98
+ }));
99
+ // --------------------------------------------------------------------------
100
+ // ue_pie_stop
101
+ // --------------------------------------------------------------------------
102
+ server.registerTool('ue_pie_stop', {
103
+ title: 'Stop PIE Session',
104
+ description: '[requires_plugin] Stop the active Play In Editor (PIE) session.',
105
+ inputSchema: z.object({}),
106
+ annotations: {
107
+ readOnlyHint: false,
108
+ destructiveHint: false,
109
+ },
110
+ }, withKnownIssues('ue_pie_stop', async (_args) => {
111
+ return sendOrDisconnect(_bridge, { type: 'pie.stop' });
112
+ }));
113
+ // --------------------------------------------------------------------------
114
+ // ue_pie_logs
115
+ // --------------------------------------------------------------------------
116
+ server.registerTool('ue_pie_logs', {
117
+ title: 'Read PIE Logs',
118
+ description: '[requires_plugin] Read PIE output log lines captured since the PIE session started.',
119
+ inputSchema: z.object({
120
+ category_filter: z
121
+ .string()
122
+ .optional()
123
+ .describe('Filter log lines containing this string (case-insensitive, empty = all)'),
124
+ max_lines: z
125
+ .number()
126
+ .int()
127
+ .min(1)
128
+ .max(1000)
129
+ .optional()
130
+ .describe('Maximum log lines to return (default 100)'),
131
+ }),
132
+ annotations: {
133
+ readOnlyHint: true,
134
+ destructiveHint: false,
135
+ },
136
+ }, withKnownIssues('ue_pie_logs', async (args) => {
137
+ const payload = {};
138
+ if (args.category_filter)
139
+ payload['category_filter'] = args.category_filter;
140
+ if (args.max_lines !== undefined)
141
+ payload['max_lines'] = args.max_lines;
142
+ return sendOrDisconnect(_bridge, { type: 'pie.logs', payload });
143
+ }));
144
+ // --------------------------------------------------------------------------
145
+ // ue_pie_game_state
146
+ // --------------------------------------------------------------------------
147
+ server.registerTool('ue_pie_game_state', {
148
+ title: 'Query PIE Game State',
149
+ description: '[requires_plugin] Query runtime game state during an active PIE session — actor positions and active GameMode.',
150
+ inputSchema: z.object({}),
151
+ annotations: {
152
+ readOnlyHint: true,
153
+ destructiveHint: false,
154
+ },
155
+ }, withKnownIssues('ue_pie_game_state', async (_args) => {
156
+ return sendOrDisconnect(_bridge, { type: 'pie.gameState' });
157
+ }));
158
+ // --------------------------------------------------------------------------
159
+ // ue_viewport_screenshot
160
+ // --------------------------------------------------------------------------
161
+ server.registerTool('ue_viewport_screenshot', {
162
+ title: 'Take Viewport Screenshot',
163
+ description: '[requires_plugin] Capture the active UE viewport as a screenshot. Returns the screenshot directory path.',
164
+ inputSchema: z.object({
165
+ width: z
166
+ .number()
167
+ .int()
168
+ .min(64)
169
+ .max(7680)
170
+ .optional()
171
+ .describe('Screenshot width in pixels (default 1920)'),
172
+ height: z
173
+ .number()
174
+ .int()
175
+ .min(64)
176
+ .max(4320)
177
+ .optional()
178
+ .describe('Screenshot height in pixels (default 1080)'),
179
+ }),
180
+ annotations: {
181
+ readOnlyHint: true,
182
+ destructiveHint: false,
183
+ },
184
+ }, withKnownIssues('ue_viewport_screenshot', async (args) => {
185
+ const payload = {};
186
+ if (args.width !== undefined)
187
+ payload['width'] = args.width;
188
+ if (args.height !== undefined)
189
+ payload['height'] = args.height;
190
+ return sendOrDisconnect(_bridge, { type: 'viewport.screenshot', payload });
191
+ }));
192
+ // --------------------------------------------------------------------------
193
+ // ue_viewport_camera
194
+ // --------------------------------------------------------------------------
195
+ server.registerTool('ue_viewport_camera', {
196
+ title: 'Control Viewport Camera',
197
+ description: '[requires_plugin] Set the viewport camera position, rotation, FOV, or orbit around a target point.',
198
+ inputSchema: z.object({
199
+ location: z
200
+ .object({
201
+ x: z.number(),
202
+ y: z.number(),
203
+ z: z.number(),
204
+ })
205
+ .optional()
206
+ .describe('Camera world position in Unreal units (cm)'),
207
+ rotation: z
208
+ .object({
209
+ pitch: z.number(),
210
+ yaw: z.number(),
211
+ roll: z.number(),
212
+ })
213
+ .optional()
214
+ .describe('Camera rotation in degrees'),
215
+ fov: z
216
+ .number()
217
+ .min(5)
218
+ .max(170)
219
+ .optional()
220
+ .describe('Horizontal field of view in degrees'),
221
+ look_at: z
222
+ .object({
223
+ x: z.number(),
224
+ y: z.number(),
225
+ z: z.number(),
226
+ })
227
+ .optional()
228
+ .describe('Point to orbit/look at — overrides rotation when location is also provided'),
229
+ }),
230
+ annotations: {
231
+ readOnlyHint: false,
232
+ destructiveHint: false,
233
+ },
234
+ }, withKnownIssues('ue_viewport_camera', async (args) => {
235
+ const payload = {};
236
+ if (args.location !== undefined)
237
+ payload['location'] = args.location;
238
+ if (args.rotation !== undefined)
239
+ payload['rotation'] = args.rotation;
240
+ if (args.fov !== undefined)
241
+ payload['fov'] = args.fov;
242
+ if (args.look_at !== undefined)
243
+ payload['look_at'] = args.look_at;
244
+ return sendOrDisconnect(_bridge, { type: 'viewport.camera', payload });
245
+ }));
246
+ // --------------------------------------------------------------------------
247
+ // ue_viewport_render_mode
248
+ // --------------------------------------------------------------------------
249
+ server.registerTool('ue_viewport_render_mode', {
250
+ title: 'Switch Viewport Render Mode',
251
+ description: '[requires_plugin] Switch the active viewport render mode.',
252
+ inputSchema: z.object({
253
+ mode: z
254
+ .enum(['lit', 'unlit', 'wireframe', 'collision', 'detail_lighting'])
255
+ .describe('Render mode: lit (default), unlit, wireframe, collision, detail_lighting'),
256
+ }),
257
+ annotations: {
258
+ readOnlyHint: false,
259
+ destructiveHint: false,
260
+ },
261
+ }, withKnownIssues('ue_viewport_render_mode', async (args) => {
262
+ return sendOrDisconnect(_bridge, {
263
+ type: 'viewport.renderMode',
264
+ payload: { mode: args.mode },
265
+ });
266
+ }));
267
+ // --------------------------------------------------------------------------
268
+ // ue_viewport_hires_screenshot
269
+ // --------------------------------------------------------------------------
270
+ server.registerTool('ue_viewport_hires_screenshot', {
271
+ title: 'High-Resolution Viewport Screenshot',
272
+ description: '[requires_plugin] Take a high-resolution screenshot with configurable multiplier. Returns the screenshot directory path.',
273
+ inputSchema: z.object({
274
+ resolution_multiplier: z
275
+ .number()
276
+ .int()
277
+ .min(1)
278
+ .max(8)
279
+ .optional()
280
+ .describe('Resolution multiplier (default 2 = 2x base resolution)'),
281
+ width: z
282
+ .number()
283
+ .int()
284
+ .min(64)
285
+ .max(7680)
286
+ .optional()
287
+ .describe('Base width in pixels (default 1920)'),
288
+ height: z
289
+ .number()
290
+ .int()
291
+ .min(64)
292
+ .max(4320)
293
+ .optional()
294
+ .describe('Base height in pixels (default 1080)'),
295
+ }),
296
+ annotations: {
297
+ readOnlyHint: true,
298
+ destructiveHint: false,
299
+ },
300
+ }, withKnownIssues('ue_viewport_hires_screenshot', async (args) => {
301
+ const payload = {};
302
+ if (args.resolution_multiplier !== undefined)
303
+ payload['resolution_multiplier'] = args.resolution_multiplier;
304
+ if (args.width !== undefined)
305
+ payload['width'] = args.width;
306
+ if (args.height !== undefined)
307
+ payload['height'] = args.height;
308
+ return sendOrDisconnect(_bridge, { type: 'viewport.hiresScreenshot', payload });
309
+ }));
310
+ }