@akiojin/unity-mcp-server 2.40.2 → 2.40.3

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 (90) hide show
  1. package/README.md +21 -0
  2. package/bin/unity-mcp-server +1 -1
  3. package/package.json +1 -1
  4. package/src/core/codeIndex.js +64 -15
  5. package/src/core/server.js +3 -34
  6. package/src/handlers/analysis/AnalyzeSceneContentsToolHandler.js +27 -24
  7. package/src/handlers/analysis/FindByComponentToolHandler.js +4 -1
  8. package/src/handlers/analysis/GetAnimatorStateToolHandler.js +5 -5
  9. package/src/handlers/analysis/GetComponentValuesToolHandler.js +4 -1
  10. package/src/handlers/analysis/GetGameObjectDetailsToolHandler.js +27 -24
  11. package/src/handlers/analysis/GetInputActionsStateToolHandler.js +5 -5
  12. package/src/handlers/analysis/GetObjectReferencesToolHandler.js +4 -1
  13. package/src/handlers/asset/AssetDatabaseManageToolHandler.js +24 -6
  14. package/src/handlers/asset/AssetDependencyAnalyzeToolHandler.js +21 -11
  15. package/src/handlers/asset/AssetImportSettingsManageToolHandler.js +7 -7
  16. package/src/handlers/asset/AssetMaterialCreateToolHandler.js +78 -81
  17. package/src/handlers/asset/AssetMaterialModifyToolHandler.js +57 -61
  18. package/src/handlers/asset/AssetPrefabCreateToolHandler.js +61 -64
  19. package/src/handlers/asset/AssetPrefabExitModeToolHandler.js +9 -13
  20. package/src/handlers/asset/AssetPrefabInstantiateToolHandler.js +110 -116
  21. package/src/handlers/asset/AssetPrefabModifyToolHandler.js +58 -58
  22. package/src/handlers/asset/AssetPrefabOpenToolHandler.js +7 -5
  23. package/src/handlers/asset/AssetPrefabSaveToolHandler.js +13 -6
  24. package/src/handlers/compilation/CompilationGetStateToolHandler.js +4 -3
  25. package/src/handlers/component/ComponentAddToolHandler.js +2 -2
  26. package/src/handlers/component/ComponentGetTypesToolHandler.js +17 -21
  27. package/src/handlers/component/ComponentListToolHandler.js +5 -3
  28. package/src/handlers/component/ComponentModifyToolHandler.js +3 -3
  29. package/src/handlers/component/ComponentRemoveToolHandler.js +2 -2
  30. package/src/handlers/console/ConsoleClearToolHandler.js +36 -46
  31. package/src/handlers/editor/EditorLayersManageToolHandler.js +7 -6
  32. package/src/handlers/editor/EditorTagsManageToolHandler.js +20 -11
  33. package/src/handlers/editor/EditorToolsManageToolHandler.js +2 -2
  34. package/src/handlers/editor/EditorWindowsManageToolHandler.js +6 -5
  35. package/src/handlers/gameobject/GameObjectCreateToolHandler.js +62 -66
  36. package/src/handlers/gameobject/GameObjectDeleteToolHandler.js +9 -9
  37. package/src/handlers/gameobject/GameObjectFindToolHandler.js +13 -11
  38. package/src/handlers/gameobject/GameObjectGetHierarchyToolHandler.js +22 -16
  39. package/src/handlers/input/InputActionAddToolHandler.js +2 -2
  40. package/src/handlers/input/InputActionMapCreateToolHandler.js +2 -2
  41. package/src/handlers/input/InputActionMapRemoveToolHandler.js +2 -2
  42. package/src/handlers/input/InputActionRemoveToolHandler.js +2 -2
  43. package/src/handlers/input/InputBindingAddToolHandler.js +2 -2
  44. package/src/handlers/input/InputBindingCompositeCreateToolHandler.js +2 -2
  45. package/src/handlers/input/InputBindingRemoveAllToolHandler.js +2 -2
  46. package/src/handlers/input/InputBindingRemoveToolHandler.js +2 -2
  47. package/src/handlers/input/InputControlSchemesManageToolHandler.js +2 -2
  48. package/src/handlers/package/PackageManagerToolHandler.js +41 -44
  49. package/src/handlers/package/RegistryConfigToolHandler.js +28 -7
  50. package/src/handlers/playmode/PlaymodeGetStateToolHandler.js +12 -16
  51. package/src/handlers/playmode/PlaymodePauseToolHandler.js +8 -12
  52. package/src/handlers/playmode/PlaymodeWaitForStateToolHandler.js +6 -3
  53. package/src/handlers/scene/GetSceneInfoToolHandler.js +11 -11
  54. package/src/handlers/scene/SceneCreateToolHandler.js +28 -31
  55. package/src/handlers/scene/SceneListToolHandler.js +21 -24
  56. package/src/handlers/scene/SceneLoadToolHandler.js +27 -29
  57. package/src/handlers/scene/SceneSaveToolHandler.js +19 -22
  58. package/src/handlers/screenshot/ScreenshotCaptureToolHandler.js +88 -66
  59. package/src/handlers/script/CodeIndexStatusToolHandler.js +4 -3
  60. package/src/handlers/script/CodeIndexUpdateToolHandler.js +24 -14
  61. package/src/handlers/script/ScriptCreateClassToolHandler.js +44 -9
  62. package/src/handlers/script/ScriptPackagesListToolHandler.js +91 -91
  63. package/src/handlers/script/ScriptRefactorRenameToolHandler.js +80 -71
  64. package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +21 -7
  65. package/src/handlers/script/ScriptSearchToolHandler.js +299 -266
  66. package/src/handlers/script/ScriptSymbolsGetToolHandler.js +88 -79
  67. package/src/handlers/settings/SettingsGetToolHandler.js +28 -13
  68. package/src/handlers/settings/SettingsUpdateToolHandler.js +20 -6
  69. package/src/handlers/ui/UIClickElementToolHandler.js +87 -96
  70. package/src/handlers/ui/UIFindElementsToolHandler.js +45 -55
  71. package/src/handlers/ui/UIGetElementStateToolHandler.js +35 -43
  72. package/src/handlers/ui/UISetElementValueToolHandler.js +42 -49
  73. package/src/handlers/ui/UISimulateInputToolHandler.js +134 -136
  74. package/src/handlers/video/VideoCaptureForToolHandler.js +24 -7
  75. package/src/lsp/LspRpcClient.js +24 -12
  76. package/src/tools/analysis/analyzeSceneContents.js +85 -85
  77. package/src/tools/analysis/findByComponent.js +73 -73
  78. package/src/tools/analysis/getAnimatorState.js +287 -287
  79. package/src/tools/analysis/getComponentValues.js +161 -161
  80. package/src/tools/analysis/getGameObjectDetails.js +138 -138
  81. package/src/tools/analysis/getInputActionsState.js +291 -291
  82. package/src/tools/analysis/getObjectReferences.js +72 -72
  83. package/src/tools/input/inputActionsEditor.js +522 -474
  84. package/src/tools/scene/createScene.js +98 -97
  85. package/src/tools/scene/getSceneInfo.js +82 -81
  86. package/src/tools/scene/listScenes.js +70 -69
  87. package/src/tools/scene/loadScene.js +108 -106
  88. package/src/tools/scene/saveScene.js +78 -77
  89. package/src/tools/system/ping.js +9 -12
  90. package/src/utils/validators.js +2 -2
@@ -5,28 +5,25 @@ import { BaseToolHandler } from '../base/BaseToolHandler.js';
5
5
  */
6
6
  export class SceneListToolHandler extends BaseToolHandler {
7
7
  constructor(unityConnection) {
8
- super(
9
- 'scene_list',
10
- 'List scenes in project (filter to loaded/build scenes or by path).',
11
- {
12
- type: 'object',
13
- properties: {
14
- includeLoadedOnly: {
15
- type: 'boolean',
16
- description: 'Only include currently loaded scenes (default: false)'
17
- },
18
- includeBuildScenesOnly: {
19
- type: 'boolean',
20
- description: 'Only include scenes in build settings (default: false)'
21
- },
22
- includePath: {
23
- type: 'string',
24
- description: 'Filter scenes by path pattern (e.g., "Levels" to find scenes in Levels folder)'
25
- }
8
+ super('scene_list', 'List scenes in project (filter to loaded/build scenes or by path).', {
9
+ type: 'object',
10
+ properties: {
11
+ includeLoadedOnly: {
12
+ type: 'boolean',
13
+ description: 'Only include currently loaded scenes (default: false)'
26
14
  },
27
- required: []
28
- }
29
- );
15
+ includeBuildScenesOnly: {
16
+ type: 'boolean',
17
+ description: 'Only include scenes in build settings (default: false)'
18
+ },
19
+ includePath: {
20
+ type: 'string',
21
+ description:
22
+ 'Filter scenes by path pattern (e.g., "Levels" to find scenes in Levels folder)'
23
+ }
24
+ },
25
+ required: []
26
+ });
30
27
  this.unityConnection = unityConnection;
31
28
  }
32
29
 
@@ -40,10 +37,10 @@ export class SceneListToolHandler extends BaseToolHandler {
40
37
  if (!this.unityConnection.isConnected()) {
41
38
  throw new Error('Unity connection not available');
42
39
  }
43
-
40
+
44
41
  // Send command to Unity
45
42
  const result = await this.unityConnection.sendCommand('list_scenes', params);
46
-
43
+
47
44
  // The unityConnection.sendCommand already extracts the result field
48
45
  // Check for Unity-side errors
49
46
  if (result && result.error) {
@@ -51,7 +48,7 @@ export class SceneListToolHandler extends BaseToolHandler {
51
48
  error.code = 'UNITY_ERROR';
52
49
  throw error;
53
50
  }
54
-
51
+
55
52
  // Return the result directly since it's already unwrapped
56
53
  return result;
57
54
  }
@@ -5,29 +5,27 @@ import { BaseToolHandler } from '../base/BaseToolHandler.js';
5
5
  */
6
6
  export class SceneLoadToolHandler extends BaseToolHandler {
7
7
  constructor(unityConnection) {
8
- super(
9
- 'scene_load',
10
- 'Load a scene by path or name (Single/Additive).',
11
- {
12
- type: 'object',
13
- properties: {
14
- scenePath: {
15
- type: 'string',
16
- description: 'Full path to the scene file (e.g., "Assets/Scenes/MainMenu.unity")'
17
- },
18
- sceneName: {
19
- type: 'string',
20
- description: 'Name of the scene to load (must be in build settings). Use either scenePath or sceneName, not both.'
21
- },
22
- loadMode: {
23
- type: 'string',
24
- enum: ['Single', 'Additive'],
25
- description: 'How to load the scene. Single replaces current scene(s), Additive adds to current scene(s) (default: Single)'
26
- }
8
+ super('scene_load', 'Load a scene by path or name (Single/Additive).', {
9
+ type: 'object',
10
+ properties: {
11
+ scenePath: {
12
+ type: 'string',
13
+ description: 'Full path to the scene file (e.g., "Assets/Scenes/MainMenu.unity")'
27
14
  },
28
- required: []
29
- }
30
- );
15
+ sceneName: {
16
+ type: 'string',
17
+ description:
18
+ 'Name of the scene to load (must be in build settings). Use either scenePath or sceneName, not both.'
19
+ },
20
+ loadMode: {
21
+ type: 'string',
22
+ enum: ['Single', 'Additive'],
23
+ description:
24
+ 'How to load the scene. Single replaces current scene(s), Additive adds to current scene(s) (default: Single)'
25
+ }
26
+ },
27
+ required: []
28
+ });
31
29
  this.unityConnection = unityConnection;
32
30
  }
33
31
 
@@ -38,17 +36,17 @@ export class SceneLoadToolHandler extends BaseToolHandler {
38
36
  */
39
37
  validate(params) {
40
38
  // Don't call super.validate() since we have no required fields
41
-
39
+
42
40
  // Validate that either scenePath or sceneName is provided
43
41
  if (!params.scenePath && !params.sceneName) {
44
42
  throw new Error('Either scenePath or sceneName must be provided');
45
43
  }
46
-
44
+
47
45
  // Validate that only one is provided
48
46
  if (params.scenePath && params.sceneName) {
49
47
  throw new Error('Provide either scenePath or sceneName, not both');
50
48
  }
51
-
49
+
52
50
  // Validate load mode
53
51
  if (params.loadMode && !['Single', 'Additive'].includes(params.loadMode)) {
54
52
  throw new Error('Invalid load mode. Must be "Single" or "Additive"');
@@ -65,17 +63,17 @@ export class SceneLoadToolHandler extends BaseToolHandler {
65
63
  if (!this.unityConnection.isConnected()) {
66
64
  throw new Error('Unity connection not available');
67
65
  }
68
-
66
+
69
67
  // Send command to Unity
70
68
  const result = await this.unityConnection.sendCommand('load_scene', params);
71
-
69
+
72
70
  // Check for Unity-side errors
73
71
  if (result.status === 'error') {
74
72
  const error = new Error(result.error);
75
73
  error.code = 'UNITY_ERROR';
76
74
  throw error;
77
75
  }
78
-
76
+
79
77
  // Handle undefined or null results from Unity
80
78
  if (result.result === undefined || result.result === null) {
81
79
  return {
@@ -86,7 +84,7 @@ export class SceneLoadToolHandler extends BaseToolHandler {
86
84
  message: 'Scene operation completed but Unity returned no details'
87
85
  };
88
86
  }
89
-
87
+
90
88
  return result.result;
91
89
  }
92
90
  }
@@ -5,24 +5,21 @@ import { BaseToolHandler } from '../base/BaseToolHandler.js';
5
5
  */
6
6
  export class SceneSaveToolHandler extends BaseToolHandler {
7
7
  constructor(unityConnection) {
8
- super(
9
- 'scene_save',
10
- 'Save current scene or save as a specified path.',
11
- {
12
- type: 'object',
13
- properties: {
14
- scenePath: {
15
- type: 'string',
16
- description: 'Path where to save the scene. If not provided, saves to current scene path. Required if saveAs is true.'
17
- },
18
- saveAs: {
19
- type: 'boolean',
20
- description: 'Whether to save as a new scene (creates a copy). Default: false'
21
- }
8
+ super('scene_save', 'Save current scene or save as a specified path.', {
9
+ type: 'object',
10
+ properties: {
11
+ scenePath: {
12
+ type: 'string',
13
+ description:
14
+ 'Path where to save the scene. If not provided, saves to current scene path. Required if saveAs is true.'
22
15
  },
23
- required: []
24
- }
25
- );
16
+ saveAs: {
17
+ type: 'boolean',
18
+ description: 'Whether to save as a new scene (creates a copy). Default: false'
19
+ }
20
+ },
21
+ required: []
22
+ });
26
23
  this.unityConnection = unityConnection;
27
24
  }
28
25
 
@@ -33,7 +30,7 @@ export class SceneSaveToolHandler extends BaseToolHandler {
33
30
  */
34
31
  validate(params) {
35
32
  // Don't call super.validate() since we have no required fields
36
-
33
+
37
34
  // Validate saveAs requires scenePath
38
35
  if (params.saveAs && !params.scenePath) {
39
36
  throw new Error('scenePath is required when saveAs is true');
@@ -50,17 +47,17 @@ export class SceneSaveToolHandler extends BaseToolHandler {
50
47
  if (!this.unityConnection.isConnected()) {
51
48
  throw new Error('Unity connection not available');
52
49
  }
53
-
50
+
54
51
  // Send command to Unity
55
52
  const result = await this.unityConnection.sendCommand('save_scene', params);
56
-
53
+
57
54
  // Check for Unity-side errors
58
55
  if (result.status === 'error') {
59
56
  const error = new Error(result.error);
60
57
  error.code = 'UNITY_ERROR';
61
58
  throw error;
62
59
  }
63
-
60
+
64
61
  // Handle undefined or null results from Unity
65
62
  if (result.result === undefined || result.result === null) {
66
63
  return {
@@ -70,7 +67,7 @@ export class SceneSaveToolHandler extends BaseToolHandler {
70
67
  message: 'Scene save completed but Unity returned no details'
71
68
  };
72
69
  }
73
-
70
+
74
71
  return result.result;
75
72
  }
76
73
  }
@@ -14,27 +14,33 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
14
14
  captureMode: {
15
15
  type: 'string',
16
16
  enum: ['game', 'scene', 'window', 'explorer'],
17
- description: 'Capture mode selection:\n- "game": Game View (player\'s perspective, what the user sees)\n- "scene": Scene View (editor\'s 3D workspace view)\n- "explorer": AI/LLM exploration mode (optimized view for understanding scene content)\n- "window": Specific Unity Editor window by name'
17
+ description:
18
+ 'Capture mode selection:\n- "game": Game View (player\'s perspective, what the user sees)\n- "scene": Scene View (editor\'s 3D workspace view)\n- "explorer": AI/LLM exploration mode (optimized view for understanding scene content)\n- "window": Specific Unity Editor window by name'
18
19
  },
19
20
  width: {
20
21
  type: 'number',
21
- description: 'Screenshot width in pixels (0 = use current view size). Range: 1-8192. Not applicable for explorer mode (use explorerSettings.camera.width instead)'
22
+ description:
23
+ 'Screenshot width in pixels (0 = use current view size). Range: 1-8192. Not applicable for explorer mode (use explorerSettings.camera.width instead)'
22
24
  },
23
25
  height: {
24
26
  type: 'number',
25
- description: 'Screenshot height in pixels (0 = use current view size). Range: 1-8192. Not applicable for explorer mode (use explorerSettings.camera.height instead)'
27
+ description:
28
+ 'Screenshot height in pixels (0 = use current view size). Range: 1-8192. Not applicable for explorer mode (use explorerSettings.camera.height instead)'
26
29
  },
27
30
  includeUI: {
28
31
  type: 'boolean',
29
- description: 'Whether to include UI overlay elements in Game View captures. Set to false for clean gameplay screenshots (default: true)'
32
+ description:
33
+ 'Whether to include UI overlay elements in Game View captures. Set to false for clean gameplay screenshots (default: true)'
30
34
  },
31
35
  windowName: {
32
36
  type: 'string',
33
- description: 'Name of the Unity Editor window to capture (required when captureMode is "window"). Examples: "Console", "Inspector", "Hierarchy", "Project"'
37
+ description:
38
+ 'Name of the Unity Editor window to capture (required when captureMode is "window"). Examples: "Console", "Inspector", "Hierarchy", "Project"'
34
39
  },
35
40
  encodeAsBase64: {
36
41
  type: 'boolean',
37
- description: 'Return screenshot data as base64 string for immediate processing/analysis without file I/O (default: false)'
42
+ description:
43
+ 'Return screenshot data as base64 string for immediate processing/analysis without file I/O (default: false)'
38
44
  },
39
45
  explorerSettings: {
40
46
  type: 'object',
@@ -47,15 +53,18 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
47
53
  type: {
48
54
  type: 'string',
49
55
  enum: ['gameObject', 'tag', 'area', 'position'],
50
- description: 'Target selection method:\n- "gameObject": Focus on a specific GameObject by name\n- "tag": Focus on all objects with a specific tag\n- "area": Focus on a circular area defined by center and radius\n- "position": Manual camera positioning without auto-framing'
56
+ description:
57
+ 'Target selection method:\n- "gameObject": Focus on a specific GameObject by name\n- "tag": Focus on all objects with a specific tag\n- "area": Focus on a circular area defined by center and radius\n- "position": Manual camera positioning without auto-framing'
51
58
  },
52
59
  name: {
53
60
  type: 'string',
54
- description: 'GameObject name to target (required for "gameObject" type). Example: "Player", "MainCamera", "Enemy_01"'
61
+ description:
62
+ 'GameObject name to target (required for "gameObject" type). Example: "Player", "MainCamera", "Enemy_01"'
55
63
  },
56
64
  tag: {
57
65
  type: 'string',
58
- description: 'Tag to search for GameObjects (required for "tag" type). Example: "Enemy", "Collectible", "Player"'
66
+ description:
67
+ 'Tag to search for GameObjects (required for "tag" type). Example: "Enemy", "Collectible", "Player"'
59
68
  },
60
69
  center: {
61
70
  type: 'object',
@@ -68,11 +77,13 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
68
77
  },
69
78
  radius: {
70
79
  type: 'number',
71
- description: 'Radius around center for area targeting (used with "area" type). Defines the circular area to capture'
80
+ description:
81
+ 'Radius around center for area targeting (used with "area" type). Defines the circular area to capture'
72
82
  },
73
83
  includeChildren: {
74
84
  type: 'boolean',
75
- description: 'Include child objects when calculating the target bounds for framing (default: true)'
85
+ description:
86
+ 'Include child objects when calculating the target bounds for framing (default: true)'
76
87
  }
77
88
  }
78
89
  },
@@ -109,24 +120,29 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
109
120
  },
110
121
  fieldOfView: {
111
122
  type: 'number',
112
-
113
- description: 'Camera field of view in degrees (1-179). Lower values zoom in, higher values zoom out'
123
+
124
+ description:
125
+ 'Camera field of view in degrees (1-179). Lower values zoom in, higher values zoom out'
114
126
  },
115
127
  nearClip: {
116
128
  type: 'number',
117
- description: 'Near clipping plane distance. Objects closer than this won\'t be rendered (default: 0.3)'
129
+ description:
130
+ "Near clipping plane distance. Objects closer than this won't be rendered (default: 0.3)"
118
131
  },
119
132
  farClip: {
120
133
  type: 'number',
121
- description: 'Far clipping plane distance. Objects farther than this won\'t be rendered'
134
+ description:
135
+ "Far clipping plane distance. Objects farther than this won't be rendered"
122
136
  },
123
137
  autoFrame: {
124
138
  type: 'boolean',
125
- description: 'Automatically position camera to frame the target. Disable for manual positioning (default: true)'
139
+ description:
140
+ 'Automatically position camera to frame the target. Disable for manual positioning (default: true)'
126
141
  },
127
142
  padding: {
128
143
  type: 'number',
129
- description: 'Padding around target when auto-framing (0-1). 0 = tight fit, 1 = lots of space (default: 0.2)'
144
+ description:
145
+ 'Padding around target when auto-framing (0-1). 0 = tight fit, 1 = lots of space (default: 0.2)'
130
146
  },
131
147
  offset: {
132
148
  type: 'object',
@@ -164,11 +180,13 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
164
180
  layers: {
165
181
  type: 'array',
166
182
  items: { type: 'string' },
167
- description: 'Unity layer names to include in rendering. If not specified, all layers are included. Examples: ["Default", "UI", "Player"]'
183
+ description:
184
+ 'Unity layer names to include in rendering. If not specified, all layers are included. Examples: ["Default", "UI", "Player"]'
168
185
  },
169
186
  showGizmos: {
170
187
  type: 'boolean',
171
- description: 'Show editor gizmos (transform handles, icons) in the capture (default: false)'
188
+ description:
189
+ 'Show editor gizmos (transform handles, icons) in the capture (default: false)'
172
190
  },
173
191
  showColliders: {
174
192
  type: 'boolean',
@@ -180,7 +198,8 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
180
198
  },
181
199
  highlightTarget: {
182
200
  type: 'boolean',
183
- description: 'Highlight the target object(s) with an outline or color (default: false)'
201
+ description:
202
+ 'Highlight the target object(s) with an outline or color (default: false)'
184
203
  }
185
204
  }
186
205
  }
@@ -190,7 +209,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
190
209
  required: []
191
210
  }
192
211
  );
193
-
212
+
194
213
  this.unityConnection = unityConnection;
195
214
  }
196
215
 
@@ -213,119 +232,119 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
213
232
  if (captureMode === 'window' && !windowName) {
214
233
  throw new Error(
215
234
  'windowName is required when captureMode is "window". ' +
216
- 'Specify the name of the Unity Editor window to capture (e.g., "Console", "Inspector", "Hierarchy")'
235
+ 'Specify the name of the Unity Editor window to capture (e.g., "Console", "Inspector", "Hierarchy")'
217
236
  );
218
237
  }
219
238
 
220
239
  // Explorer mode validation
221
240
  if (captureMode === 'explorer' && explorerSettings) {
222
241
  const { target, camera, display } = explorerSettings;
223
-
242
+
224
243
  // Validate target settings
225
244
  if (target) {
226
245
  const { type } = target;
227
246
  if (type && !['gameObject', 'tag', 'area', 'position'].includes(type)) {
228
247
  throw new Error(
229
248
  'Invalid target.type for explorer mode. Must be one of:\n' +
230
- '- "gameObject": Focus on a specific GameObject by name\n' +
231
- '- "tag": Focus on all objects with a specific tag\n' +
232
- '- "area": Focus on a circular area (center + radius)\n' +
233
- '- "position": Manual camera positioning'
249
+ '- "gameObject": Focus on a specific GameObject by name\n' +
250
+ '- "tag": Focus on all objects with a specific tag\n' +
251
+ '- "area": Focus on a circular area (center + radius)\n' +
252
+ '- "position": Manual camera positioning'
234
253
  );
235
254
  }
236
-
255
+
237
256
  if (type === 'gameObject' && !target.name) {
238
257
  throw new Error(
239
258
  'target.name is required when target.type is "gameObject". ' +
240
- 'Specify the name of the GameObject to focus on (e.g., "Player", "MainCamera")'
259
+ 'Specify the name of the GameObject to focus on (e.g., "Player", "MainCamera")'
241
260
  );
242
261
  }
243
-
262
+
244
263
  if (type === 'tag' && !target.tag) {
245
264
  throw new Error(
246
265
  'target.tag is required when target.type is "tag". ' +
247
- 'Specify the tag to search for (e.g., "Enemy", "Collectible")'
266
+ 'Specify the tag to search for (e.g., "Enemy", "Collectible")'
248
267
  );
249
268
  }
250
-
269
+
251
270
  if (type === 'area') {
252
271
  if (!target.center) {
253
272
  throw new Error(
254
273
  'target.center is required when target.type is "area". ' +
255
- 'Specify the center position as {x, y, z} in world coordinates'
274
+ 'Specify the center position as {x, y, z} in world coordinates'
256
275
  );
257
276
  }
258
277
  if (target.radius === undefined || target.radius <= 0) {
259
278
  throw new Error(
260
279
  'target.radius must be a positive number when target.type is "area". ' +
261
- 'Specify the radius of the area to capture'
280
+ 'Specify the radius of the area to capture'
262
281
  );
263
282
  }
264
283
  }
265
284
  }
266
-
285
+
267
286
  // Validate camera settings
268
287
  if (camera) {
269
288
  if (camera.fieldOfView !== undefined) {
270
289
  if (camera.fieldOfView < 1 || camera.fieldOfView > 179) {
271
290
  throw new Error(
272
291
  'camera.fieldOfView must be between 1 and 179 degrees. ' +
273
- 'Lower values (20-40) provide zoom effect, standard is 60, wide angle is 90+'
292
+ 'Lower values (20-40) provide zoom effect, standard is 60, wide angle is 90+'
274
293
  );
275
294
  }
276
295
  }
277
-
296
+
278
297
  if (camera.padding !== undefined) {
279
298
  if (camera.padding < 0 || camera.padding > 1) {
280
299
  throw new Error(
281
300
  'camera.padding must be between 0 and 1. ' +
282
- '0 = tight framing, 0.2 = normal padding, 0.5+ = lots of surrounding space'
301
+ '0 = tight framing, 0.2 = normal padding, 0.5+ = lots of surrounding space'
283
302
  );
284
303
  }
285
304
  }
286
-
305
+
287
306
  if (camera.width !== undefined) {
288
307
  if (camera.width < 1 || camera.width > 8192) {
289
308
  throw new Error(
290
309
  'camera.width must be between 1 and 8192 pixels. ' +
291
- 'Common values: 1920 (Full HD), 2560 (2K), 3840 (4K)'
310
+ 'Common values: 1920 (Full HD), 2560 (2K), 3840 (4K)'
292
311
  );
293
312
  }
294
313
  }
295
-
314
+
296
315
  if (camera.height !== undefined) {
297
316
  if (camera.height < 1 || camera.height > 8192) {
298
317
  throw new Error(
299
318
  'camera.height must be between 1 and 8192 pixels. ' +
300
- 'Common values: 1080 (Full HD), 1440 (2K), 2160 (4K)'
319
+ 'Common values: 1080 (Full HD), 1440 (2K), 2160 (4K)'
301
320
  );
302
321
  }
303
322
  }
304
-
323
+
305
324
  if (camera.nearClip !== undefined && camera.nearClip <= 0) {
306
325
  throw new Error(
307
326
  'camera.nearClip must be a positive number. ' +
308
- 'Typically 0.01 to 1.0 for close-up views, 0.3 is default'
327
+ 'Typically 0.01 to 1.0 for close-up views, 0.3 is default'
309
328
  );
310
329
  }
311
-
330
+
312
331
  if (camera.farClip !== undefined && camera.farClip <= 0) {
313
332
  throw new Error(
314
333
  'camera.farClip must be a positive number. ' +
315
- 'Should be larger than nearClip. Default is 1000, reduce for performance'
334
+ 'Should be larger than nearClip. Default is 1000, reduce for performance'
316
335
  );
317
336
  }
318
-
337
+
319
338
  if (camera.nearClip !== undefined && camera.farClip !== undefined) {
320
339
  if (camera.nearClip >= camera.farClip) {
321
340
  throw new Error(
322
341
  'camera.nearClip must be less than camera.farClip. ' +
323
- 'nearClip defines the closest visible distance, farClip the farthest'
342
+ 'nearClip defines the closest visible distance, farClip the farthest'
324
343
  );
325
344
  }
326
345
  }
327
346
  }
328
-
347
+
329
348
  // Validate display settings
330
349
  if (display) {
331
350
  if (display.backgroundColor) {
@@ -334,7 +353,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
334
353
  if (value !== undefined && (value < 0 || value > 1)) {
335
354
  throw new Error(
336
355
  `backgroundColor.${name} must be between 0 and 1. ` +
337
- 'Color components use normalized values (0 = black/transparent, 1 = full intensity)'
356
+ 'Color components use normalized values (0 = black/transparent, 1 = full intensity)'
338
357
  );
339
358
  }
340
359
  };
@@ -343,11 +362,11 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
343
362
  validateColorComponent(b, 'b');
344
363
  validateColorComponent(a, 'a');
345
364
  }
346
-
365
+
347
366
  if (display.layers && !Array.isArray(display.layers)) {
348
367
  throw new Error(
349
368
  'display.layers must be an array of layer names. ' +
350
- 'Example: ["Default", "UI", "Player"]'
369
+ 'Example: ["Default", "UI", "Player"]'
351
370
  );
352
371
  }
353
372
  }
@@ -357,26 +376,26 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
357
376
  if (outputPath) {
358
377
  const validExtensions = ['.png', '.jpg', '.jpeg'];
359
378
  const hasValidExtension = validExtensions.some(ext => outputPath.toLowerCase().endsWith(ext));
360
-
379
+
361
380
  if (!hasValidExtension) {
362
381
  throw new Error(
363
382
  'outputPath must end with .png, .jpg, or .jpeg. ' +
364
- 'PNG is recommended for best quality, JPG for smaller file size'
383
+ 'PNG is recommended for best quality, JPG for smaller file size'
365
384
  );
366
385
  }
367
-
386
+
368
387
  if (!outputPath.startsWith('Assets/')) {
369
388
  throw new Error(
370
389
  'outputPath must be within the Assets folder. ' +
371
- 'Example: "Assets/Screenshots/capture.png"'
390
+ 'Example: "Assets/Screenshots/capture.png"'
372
391
  );
373
392
  }
374
-
393
+
375
394
  // Warn about potential path issues
376
395
  if (outputPath.includes('\\')) {
377
396
  throw new Error(
378
397
  'outputPath should use forward slashes (/) not backslashes (\\). ' +
379
- 'Example: "Assets/Screenshots/capture.png"'
398
+ 'Example: "Assets/Screenshots/capture.png"'
380
399
  );
381
400
  }
382
401
  }
@@ -387,16 +406,16 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
387
406
  if (params.width < 0 || params.width > 8192) {
388
407
  throw new Error(
389
408
  'width must be between 0 and 8192 pixels. ' +
390
- '0 = use current view size, common values: 1920, 2560, 3840'
409
+ '0 = use current view size, common values: 1920, 2560, 3840'
391
410
  );
392
411
  }
393
412
  }
394
-
413
+
395
414
  if (params.height !== undefined) {
396
415
  if (params.height < 0 || params.height > 8192) {
397
416
  throw new Error(
398
417
  'height must be between 0 and 8192 pixels. ' +
399
- '0 = use current view size, common values: 1080, 1440, 2160'
418
+ '0 = use current view size, common values: 1080, 1440, 2160'
400
419
  );
401
420
  }
402
421
  }
@@ -420,7 +439,10 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
420
439
 
421
440
  // Send capture command to Unity
422
441
  const { WORKSPACE_ROOT } = await import('../../core/config.js');
423
- const response = await this.unityConnection.sendCommand('capture_screenshot', { ...(params||{}), workspaceRoot: WORKSPACE_ROOT });
442
+ const response = await this.unityConnection.sendCommand('capture_screenshot', {
443
+ ...(params || {}),
444
+ workspaceRoot: WORKSPACE_ROOT
445
+ });
424
446
 
425
447
  // Handle Unity response
426
448
  if (response.error) {
@@ -487,7 +509,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
487
509
  outputPath: 'Assets/Screenshots/scene_4k.png'
488
510
  }
489
511
  },
490
-
512
+
491
513
  // Explorer mode examples for AI/LLM usage
492
514
  analyzePlayer: {
493
515
  description: 'AI/LLM: Analyze the player character and its surroundings',
@@ -603,7 +625,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
603
625
  }
604
626
  },
605
627
  birdEyeView: {
606
- description: 'AI/LLM: Top-down bird\'s eye view of the entire level',
628
+ description: "AI/LLM: Top-down bird's eye view of the entire level",
607
629
  params: {
608
630
  captureMode: 'explorer',
609
631
  encodeAsBase64: true,
@@ -620,7 +642,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
620
642
  }
621
643
  }
622
644
  },
623
-
645
+
624
646
  // Window capture examples
625
647
  captureConsole: {
626
648
  description: 'Capture Unity console for error debugging',
@@ -637,7 +659,7 @@ export class ScreenshotCaptureToolHandler extends BaseToolHandler {
637
659
  windowName: 'Inspector'
638
660
  }
639
661
  },
640
-
662
+
641
663
  // Advanced explorer examples
642
664
  cinematicShot: {
643
665
  description: 'AI/LLM: Cinematic angle shot of a specific scene moment',