@akiojin/unity-mcp-server 2.14.14

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 (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/bin/unity-mcp-server +2 -0
  4. package/package.json +73 -0
  5. package/src/core/codeIndex.js +163 -0
  6. package/src/core/codeIndexDb.js +96 -0
  7. package/src/core/config.js +165 -0
  8. package/src/core/indexWatcher.js +52 -0
  9. package/src/core/projectInfo.js +111 -0
  10. package/src/core/server.js +294 -0
  11. package/src/core/unityConnection.js +426 -0
  12. package/src/handlers/analysis/AnalyzeSceneContentsToolHandler.js +35 -0
  13. package/src/handlers/analysis/FindByComponentToolHandler.js +20 -0
  14. package/src/handlers/analysis/GetAnimatorStateToolHandler.js +37 -0
  15. package/src/handlers/analysis/GetComponentValuesToolHandler.js +20 -0
  16. package/src/handlers/analysis/GetGameObjectDetailsToolHandler.js +35 -0
  17. package/src/handlers/analysis/GetInputActionsStateToolHandler.js +37 -0
  18. package/src/handlers/analysis/GetObjectReferencesToolHandler.js +20 -0
  19. package/src/handlers/asset/AssetDatabaseToolHandler.js +221 -0
  20. package/src/handlers/asset/AssetDependencyToolHandler.js +201 -0
  21. package/src/handlers/asset/AssetImportSettingsToolHandler.js +170 -0
  22. package/src/handlers/asset/CreateMaterialToolHandler.js +96 -0
  23. package/src/handlers/asset/CreatePrefabToolHandler.js +78 -0
  24. package/src/handlers/asset/ExitPrefabModeToolHandler.js +83 -0
  25. package/src/handlers/asset/InstantiatePrefabToolHandler.js +133 -0
  26. package/src/handlers/asset/ModifyMaterialToolHandler.js +76 -0
  27. package/src/handlers/asset/ModifyPrefabToolHandler.js +72 -0
  28. package/src/handlers/asset/OpenPrefabToolHandler.js +121 -0
  29. package/src/handlers/asset/SavePrefabToolHandler.js +106 -0
  30. package/src/handlers/base/BaseToolHandler.js +133 -0
  31. package/src/handlers/compilation/GetCompilationStateToolHandler.js +90 -0
  32. package/src/handlers/component/AddComponentToolHandler.js +126 -0
  33. package/src/handlers/component/GetComponentTypesToolHandler.js +100 -0
  34. package/src/handlers/component/ListComponentsToolHandler.js +85 -0
  35. package/src/handlers/component/ModifyComponentToolHandler.js +143 -0
  36. package/src/handlers/component/RemoveComponentToolHandler.js +108 -0
  37. package/src/handlers/console/ClearConsoleToolHandler.js +160 -0
  38. package/src/handlers/console/ReadConsoleToolHandler.js +276 -0
  39. package/src/handlers/editor/LayerManagementToolHandler.js +160 -0
  40. package/src/handlers/editor/SelectionToolHandler.js +141 -0
  41. package/src/handlers/editor/TagManagementToolHandler.js +129 -0
  42. package/src/handlers/editor/ToolManagementToolHandler.js +135 -0
  43. package/src/handlers/editor/WindowManagementToolHandler.js +125 -0
  44. package/src/handlers/gameobject/CreateGameObjectToolHandler.js +131 -0
  45. package/src/handlers/gameobject/DeleteGameObjectToolHandler.js +101 -0
  46. package/src/handlers/gameobject/FindGameObjectToolHandler.js +119 -0
  47. package/src/handlers/gameobject/GetHierarchyToolHandler.js +132 -0
  48. package/src/handlers/gameobject/ModifyGameObjectToolHandler.js +128 -0
  49. package/src/handlers/index.js +389 -0
  50. package/src/handlers/input/AddInputActionToolHandler.js +20 -0
  51. package/src/handlers/input/AddInputBindingToolHandler.js +20 -0
  52. package/src/handlers/input/CreateActionMapToolHandler.js +20 -0
  53. package/src/handlers/input/CreateCompositeBindingToolHandler.js +20 -0
  54. package/src/handlers/input/GamepadSimulationHandler.js +116 -0
  55. package/src/handlers/input/InputSystemHandler.js +80 -0
  56. package/src/handlers/input/KeyboardSimulationHandler.js +79 -0
  57. package/src/handlers/input/ManageControlSchemesToolHandler.js +20 -0
  58. package/src/handlers/input/MouseSimulationHandler.js +107 -0
  59. package/src/handlers/input/RemoveActionMapToolHandler.js +20 -0
  60. package/src/handlers/input/RemoveAllBindingsToolHandler.js +20 -0
  61. package/src/handlers/input/RemoveInputActionToolHandler.js +20 -0
  62. package/src/handlers/input/RemoveInputBindingToolHandler.js +20 -0
  63. package/src/handlers/input/TouchSimulationHandler.js +142 -0
  64. package/src/handlers/menu/ExecuteMenuItemToolHandler.js +304 -0
  65. package/src/handlers/package/PackageManagerToolHandler.js +248 -0
  66. package/src/handlers/package/RegistryConfigToolHandler.js +198 -0
  67. package/src/handlers/playmode/GetEditorStateToolHandler.js +81 -0
  68. package/src/handlers/playmode/PauseToolHandler.js +44 -0
  69. package/src/handlers/playmode/PlayToolHandler.js +91 -0
  70. package/src/handlers/playmode/StopToolHandler.js +77 -0
  71. package/src/handlers/playmode/WaitForEditorStateToolHandler.js +45 -0
  72. package/src/handlers/scene/CreateSceneToolHandler.js +91 -0
  73. package/src/handlers/scene/GetSceneInfoToolHandler.js +20 -0
  74. package/src/handlers/scene/ListScenesToolHandler.js +58 -0
  75. package/src/handlers/scene/LoadSceneToolHandler.js +92 -0
  76. package/src/handlers/scene/SaveSceneToolHandler.js +76 -0
  77. package/src/handlers/screenshot/AnalyzeScreenshotToolHandler.js +238 -0
  78. package/src/handlers/screenshot/CaptureScreenshotToolHandler.js +692 -0
  79. package/src/handlers/script/BuildCodeIndexToolHandler.js +163 -0
  80. package/src/handlers/script/ScriptCreateClassFileToolHandler.js +60 -0
  81. package/src/handlers/script/ScriptEditStructuredToolHandler.js +173 -0
  82. package/src/handlers/script/ScriptIndexStatusToolHandler.js +61 -0
  83. package/src/handlers/script/ScriptPackagesListToolHandler.js +103 -0
  84. package/src/handlers/script/ScriptReadToolHandler.js +106 -0
  85. package/src/handlers/script/ScriptRefactorRenameToolHandler.js +83 -0
  86. package/src/handlers/script/ScriptRefsFindToolHandler.js +144 -0
  87. package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +79 -0
  88. package/src/handlers/script/ScriptSearchToolHandler.js +320 -0
  89. package/src/handlers/script/ScriptSymbolFindToolHandler.js +117 -0
  90. package/src/handlers/script/ScriptSymbolsGetToolHandler.js +96 -0
  91. package/src/handlers/settings/GetProjectSettingsToolHandler.js +161 -0
  92. package/src/handlers/settings/UpdateProjectSettingsToolHandler.js +272 -0
  93. package/src/handlers/system/GetCommandStatsToolHandler.js +25 -0
  94. package/src/handlers/system/PingToolHandler.js +53 -0
  95. package/src/handlers/system/RefreshAssetsToolHandler.js +45 -0
  96. package/src/handlers/ui/ClickUIElementToolHandler.js +110 -0
  97. package/src/handlers/ui/FindUIElementsToolHandler.js +63 -0
  98. package/src/handlers/ui/GetUIElementStateToolHandler.js +50 -0
  99. package/src/handlers/ui/SetUIElementValueToolHandler.js +49 -0
  100. package/src/handlers/ui/SimulateUIInputToolHandler.js +156 -0
  101. package/src/handlers/video/CaptureVideoForToolHandler.js +96 -0
  102. package/src/handlers/video/CaptureVideoStartToolHandler.js +38 -0
  103. package/src/handlers/video/CaptureVideoStatusToolHandler.js +30 -0
  104. package/src/handlers/video/CaptureVideoStopToolHandler.js +32 -0
  105. package/src/lsp/CSharpLspUtils.js +134 -0
  106. package/src/lsp/LspProcessManager.js +60 -0
  107. package/src/lsp/LspRpcClient.js +133 -0
  108. package/src/tools/analysis/analyzeSceneContents.js +100 -0
  109. package/src/tools/analysis/findByComponent.js +87 -0
  110. package/src/tools/analysis/getAnimatorState.js +326 -0
  111. package/src/tools/analysis/getComponentValues.js +182 -0
  112. package/src/tools/analysis/getGameObjectDetails.js +159 -0
  113. package/src/tools/analysis/getInputActionsState.js +329 -0
  114. package/src/tools/analysis/getObjectReferences.js +86 -0
  115. package/src/tools/input/inputActionsEditor.js +556 -0
  116. package/src/tools/scene/createScene.js +112 -0
  117. package/src/tools/scene/getSceneInfo.js +95 -0
  118. package/src/tools/scene/listScenes.js +82 -0
  119. package/src/tools/scene/loadScene.js +122 -0
  120. package/src/tools/scene/saveScene.js +91 -0
  121. package/src/tools/system/ping.js +72 -0
  122. package/src/tools/video/recordFor.js +31 -0
  123. package/src/tools/video/recordPlayMode.js +61 -0
  124. package/src/utils/csharpParse.js +88 -0
  125. package/src/utils/validators.js +90 -0
@@ -0,0 +1,326 @@
1
+ // Tool definition for get_animator_state
2
+ export const getAnimatorStateToolDefinition = {
3
+ name: 'get_animator_state',
4
+ description: 'Get Animator state: layers, transitions, and parameter values for a GameObject.',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ gameObjectName: {
9
+ type: 'string',
10
+ description: 'Name of the GameObject with the Animator component'
11
+ },
12
+ includeParameters: {
13
+ type: 'boolean',
14
+ description: 'Include all animator parameters and their current values. Default: true',
15
+ default: true
16
+ },
17
+ includeStates: {
18
+ type: 'boolean',
19
+ description: 'Include current state information for each layer. Default: true',
20
+ default: true
21
+ },
22
+ includeTransitions: {
23
+ type: 'boolean',
24
+ description: 'Include active transition information. Default: true',
25
+ default: true
26
+ },
27
+ includeClips: {
28
+ type: 'boolean',
29
+ description: 'Include animation clip information. Default: false',
30
+ default: false
31
+ },
32
+ layerIndex: {
33
+ type: 'number',
34
+ description: 'Specific layer index to query (-1 for all layers). Default: -1',
35
+ default: -1
36
+ }
37
+ },
38
+ required: ['gameObjectName']
39
+ }
40
+ };
41
+
42
+ // Tool definition for get_animator_runtime_info
43
+ export const getAnimatorRuntimeInfoToolDefinition = {
44
+ name: 'get_animator_runtime_info',
45
+ description: 'Get Animator runtime info (IK, root motion, performance) — Play mode only.',
46
+ inputSchema: {
47
+ type: 'object',
48
+ properties: {
49
+ gameObjectName: {
50
+ type: 'string',
51
+ description: 'Name of the GameObject with the Animator component'
52
+ },
53
+ includeIK: {
54
+ type: 'boolean',
55
+ description: 'Include IK (Inverse Kinematics) information. Default: true',
56
+ default: true
57
+ },
58
+ includeRootMotion: {
59
+ type: 'boolean',
60
+ description: 'Include root motion information. Default: true',
61
+ default: true
62
+ },
63
+ includeBehaviours: {
64
+ type: 'boolean',
65
+ description: 'Include state machine behaviours. Default: false',
66
+ default: false
67
+ }
68
+ },
69
+ required: ['gameObjectName']
70
+ }
71
+ };
72
+
73
+ // Handler for get_animator_state
74
+ export async function getAnimatorStateHandler(unityConnection, args) {
75
+ try {
76
+ // Check connection
77
+ if (!unityConnection.isConnected()) {
78
+ return {
79
+ content: [
80
+ {
81
+ type: 'text',
82
+ text: 'Failed to get animator state: Unity connection not available'
83
+ }
84
+ ],
85
+ isError: true
86
+ };
87
+ }
88
+
89
+ // Validate required parameters
90
+ if (!args.gameObjectName) {
91
+ return {
92
+ content: [
93
+ {
94
+ type: 'text',
95
+ text: 'Failed to get animator state: gameObjectName is required'
96
+ }
97
+ ],
98
+ isError: true
99
+ };
100
+ }
101
+
102
+ // Send command to Unity
103
+ const result = await unityConnection.sendCommand('get_animator_state', args);
104
+
105
+ // Check for errors
106
+ if (!result || typeof result === 'string') {
107
+ return {
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: `Failed to get animator state: Invalid response format`
112
+ }
113
+ ],
114
+ isError: true
115
+ };
116
+ }
117
+
118
+ if (result.error) {
119
+ return {
120
+ content: [
121
+ {
122
+ type: 'text',
123
+ text: `Failed to get animator state: ${result.error}`
124
+ }
125
+ ],
126
+ isError: true
127
+ };
128
+ }
129
+
130
+ // Format the response
131
+ let text = result.summary || `Animator state retrieved for '${args.gameObjectName}'`;
132
+
133
+ if (result.controllerName) {
134
+ text += `\nController: ${result.controllerName}`;
135
+ }
136
+
137
+ if (result.layers && Array.isArray(result.layers)) {
138
+ text += `\n\n## Layer States:`;
139
+ result.layers.forEach(layer => {
140
+ text += `\n\n### Layer ${layer.layerIndex}: ${layer.layerName || 'Base Layer'}`;
141
+ text += `\n- Weight: ${layer.layerWeight}`;
142
+
143
+ if (layer.currentState) {
144
+ text += `\n- Current State: ${layer.currentState.name || `Hash: ${layer.currentState.fullPathHash}`}`;
145
+ text += `\n - Normalized Time: ${layer.currentState.normalizedTime?.toFixed(3)}`;
146
+ text += `\n - Speed: ${layer.currentState.speed}`;
147
+ if (layer.currentState.motion) {
148
+ text += `\n - Motion: ${layer.currentState.motion}`;
149
+ }
150
+ }
151
+
152
+ if (layer.activeTransition) {
153
+ text += `\n- Active Transition:`;
154
+ text += `\n - Duration: ${layer.activeTransition.duration}`;
155
+ text += `\n - Progress: ${(layer.activeTransition.normalizedTime * 100).toFixed(1)}%`;
156
+ if (layer.activeTransition.nextState) {
157
+ text += `\n - To: ${layer.activeTransition.nextState.name || 'Unknown'}`;
158
+ }
159
+ }
160
+ });
161
+ }
162
+
163
+ if (result.parameters && Object.keys(result.parameters).length > 0) {
164
+ text += `\n\n## Parameters:`;
165
+ for (const [name, param] of Object.entries(result.parameters)) {
166
+ text += `\n- ${name} (${param.type}): ${param.value}`;
167
+ if (param.defaultValue !== undefined && param.type !== 'Trigger') {
168
+ text += ` [default: ${param.defaultValue}]`;
169
+ }
170
+ }
171
+ }
172
+
173
+ return {
174
+ content: [
175
+ {
176
+ type: 'text',
177
+ text: text
178
+ }
179
+ ],
180
+ isError: false
181
+ };
182
+ } catch (error) {
183
+ return {
184
+ content: [
185
+ {
186
+ type: 'text',
187
+ text: `Failed to get animator state: ${error.message}`
188
+ }
189
+ ],
190
+ isError: true
191
+ };
192
+ }
193
+ }
194
+
195
+ // Handler for get_animator_runtime_info
196
+ export async function getAnimatorRuntimeInfoHandler(unityConnection, args) {
197
+ try {
198
+ // Check connection
199
+ if (!unityConnection.isConnected()) {
200
+ return {
201
+ content: [
202
+ {
203
+ type: 'text',
204
+ text: 'Failed to get animator runtime info: Unity connection not available'
205
+ }
206
+ ],
207
+ isError: true
208
+ };
209
+ }
210
+
211
+ // Validate required parameters
212
+ if (!args.gameObjectName) {
213
+ return {
214
+ content: [
215
+ {
216
+ type: 'text',
217
+ text: 'Failed to get animator runtime info: gameObjectName is required'
218
+ }
219
+ ],
220
+ isError: true
221
+ };
222
+ }
223
+
224
+ // Send command to Unity
225
+ const result = await unityConnection.sendCommand('get_animator_runtime_info', args);
226
+
227
+ // Check for errors
228
+ if (!result || typeof result === 'string') {
229
+ return {
230
+ content: [
231
+ {
232
+ type: 'text',
233
+ text: `Failed to get animator runtime info: Invalid response format`
234
+ }
235
+ ],
236
+ isError: true
237
+ };
238
+ }
239
+
240
+ if (result.error) {
241
+ return {
242
+ content: [
243
+ {
244
+ type: 'text',
245
+ text: `Failed to get animator runtime info: ${result.error}`
246
+ }
247
+ ],
248
+ isError: true
249
+ };
250
+ }
251
+
252
+ // Format the response
253
+ let text = result.summary || `Animator runtime info retrieved for '${args.gameObjectName}'`;
254
+
255
+ text += `\n\n## General Info:`;
256
+ text += `\n- Controller: ${result.runtimeAnimatorController || 'None'}`;
257
+ text += `\n- Update Mode: ${result.updateMode}`;
258
+ text += `\n- Culling Mode: ${result.cullingMode}`;
259
+ text += `\n- Speed: ${result.speed}`;
260
+ text += `\n- Playback Time: ${result.playbackTime?.toFixed(3)}`;
261
+
262
+ if (result.avatar) {
263
+ text += `\n\n## Avatar:`;
264
+ text += `\n- Name: ${result.avatar.name}`;
265
+ text += `\n- Valid: ${result.avatar.isValid}`;
266
+ text += `\n- Human: ${result.avatar.isHuman}`;
267
+ }
268
+
269
+ if (result.rootMotion) {
270
+ text += `\n\n## Root Motion:`;
271
+ text += `\n- Apply Root Motion: ${result.rootMotion.applyRootMotion}`;
272
+ text += `\n- Has Root Motion: ${result.rootMotion.hasRootMotion}`;
273
+ text += `\n- Velocity: (${result.rootMotion.velocity.x?.toFixed(2)}, ${result.rootMotion.velocity.y?.toFixed(2)}, ${result.rootMotion.velocity.z?.toFixed(2)})`;
274
+ text += `\n- Angular Velocity: (${result.rootMotion.angularVelocity.x?.toFixed(2)}, ${result.rootMotion.angularVelocity.y?.toFixed(2)}, ${result.rootMotion.angularVelocity.z?.toFixed(2)})`;
275
+ }
276
+
277
+ if (result.ikInfo) {
278
+ text += `\n\n## IK Info:`;
279
+ text += `\n- Human Scale: ${result.ikInfo.humanScale}`;
280
+ text += `\n- Feet Pivot Active: ${result.ikInfo.feetPivotActive}`;
281
+ text += `\n- Pivot Weight: ${result.ikInfo.pivotWeight}`;
282
+
283
+ if (result.ikInfo.goals) {
284
+ text += `\n\n### IK Goals:`;
285
+ for (const [goal, data] of Object.entries(result.ikInfo.goals)) {
286
+ text += `\n- ${goal}:`;
287
+ text += `\n - Position Weight: ${data.positionWeight}`;
288
+ text += `\n - Rotation Weight: ${data.rotationWeight}`;
289
+ }
290
+ }
291
+ }
292
+
293
+ if (result.behaviours && result.behaviours.length > 0) {
294
+ text += `\n\n## State Machine Behaviours:`;
295
+ result.behaviours.forEach(behaviour => {
296
+ text += `\n- Layer ${behaviour.layer}: ${behaviour.type} (${behaviour.enabled ? 'Enabled' : 'Disabled'})`;
297
+ });
298
+ }
299
+
300
+ text += `\n\n## Performance:`;
301
+ text += `\n- Has Bound Playables: ${result.hasBoundPlayables}`;
302
+ text += `\n- Has Transform Hierarchy: ${result.hasTransformHierarchy}`;
303
+ text += `\n- Is Optimizable: ${result.isOptimizable}`;
304
+ text += `\n- Gravity Weight: ${result.gravityWeight}`;
305
+
306
+ return {
307
+ content: [
308
+ {
309
+ type: 'text',
310
+ text: text
311
+ }
312
+ ],
313
+ isError: false
314
+ };
315
+ } catch (error) {
316
+ return {
317
+ content: [
318
+ {
319
+ type: 'text',
320
+ text: `Failed to get animator runtime info: ${error.message}`
321
+ }
322
+ ],
323
+ isError: true
324
+ };
325
+ }
326
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Tool definition for get_component_values
3
+ */
4
+ export const getComponentValuesToolDefinition = {
5
+ name: 'get_component_values',
6
+ description: 'Get properties/values from a component on a GameObject (scene or prefab mode).',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ gameObjectName: {
11
+ type: 'string',
12
+ description: 'Name of the GameObject'
13
+ },
14
+ componentType: {
15
+ type: 'string',
16
+ description: 'Type of component (e.g., "Light", "Camera", "Rigidbody")'
17
+ },
18
+ componentIndex: {
19
+ type: 'number',
20
+ description: 'Index if multiple components of same type. Default: 0'
21
+ },
22
+ includePrivateFields: {
23
+ type: 'boolean',
24
+ description: 'Include non-public fields. Default: false'
25
+ },
26
+ includeInherited: {
27
+ type: 'boolean',
28
+ description: 'Include inherited properties. Default: true'
29
+ }
30
+ },
31
+ required: ['gameObjectName', 'componentType']
32
+ }
33
+ };
34
+
35
+ /**
36
+ * Handler for get_component_values tool
37
+ */
38
+ export async function getComponentValuesHandler(unityConnection, args) {
39
+ try {
40
+ // Check connection
41
+ if (!unityConnection.isConnected()) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: 'text',
46
+ text: 'Failed to get component values: Unity connection not available'
47
+ }
48
+ ],
49
+ isError: true
50
+ };
51
+ }
52
+
53
+ // Validate required parameters
54
+ if (!args.componentType) {
55
+ return {
56
+ content: [
57
+ {
58
+ type: 'text',
59
+ text: 'Failed to get component values: componentType is required'
60
+ }
61
+ ],
62
+ isError: true
63
+ };
64
+ }
65
+
66
+ // Validate componentIndex if provided
67
+ if (args.componentIndex !== undefined && args.componentIndex < 0) {
68
+ return {
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: 'Failed to get component values: componentIndex must be non-negative'
73
+ }
74
+ ],
75
+ isError: true
76
+ };
77
+ }
78
+
79
+ // Send command to Unity
80
+ const result = await unityConnection.sendCommand('get_component_values', args);
81
+
82
+ // The unityConnection.sendCommand already extracts the result field
83
+ // from the response, so we access properties directly on result
84
+ if (!result || typeof result === 'string') {
85
+ return {
86
+ content: [
87
+ {
88
+ type: 'text',
89
+ text: `Failed to get component values: Invalid response format`
90
+ }
91
+ ],
92
+ isError: true
93
+ };
94
+ }
95
+
96
+ // Check if result has error property (error response from Unity)
97
+ if (result.error) {
98
+ return {
99
+ content: [
100
+ {
101
+ type: 'text',
102
+ text: `Failed to get component values: ${result.error}`
103
+ }
104
+ ],
105
+ isError: true
106
+ };
107
+ }
108
+
109
+ // Success response - result is already the unwrapped data
110
+ console.log('[DEBUG] GetComponentValues - Full result:', JSON.stringify(result, null, 2));
111
+
112
+ let responseText = result.summary || `Component values retrieved`;
113
+
114
+ // Add detailed property information if available
115
+ if (result.properties && Object.keys(result.properties).length > 0) {
116
+ console.log('[DEBUG] Properties found:', Object.keys(result.properties).length);
117
+ responseText += '\n\nProperties:';
118
+ for (const [key, value] of Object.entries(result.properties)) {
119
+ if (value && typeof value === 'object') {
120
+ if (value.error) {
121
+ responseText += `\n- ${key}: ERROR - ${value.error}`;
122
+ } else {
123
+ const valueStr = value.value ? JSON.stringify(value.value, null, 2) : 'null';
124
+ const typeStr = value.type || 'unknown';
125
+ responseText += `\n- ${key} (${typeStr}): ${valueStr}`;
126
+
127
+ // Add range info if available
128
+ if (value.range) {
129
+ responseText += ` [range: ${value.range.min}-${value.range.max}]`;
130
+ }
131
+
132
+ // Add tooltip if available
133
+ if (value.tooltip) {
134
+ responseText += ` // ${value.tooltip}`;
135
+ }
136
+
137
+ // Add serialization info
138
+ if (value.serialized) {
139
+ responseText += ` (SerializeField)`;
140
+ }
141
+ if (value.hiddenInInspector) {
142
+ responseText += ` (HideInInspector)`;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ } else {
148
+ console.log('[DEBUG] No properties found in result');
149
+ console.log('[DEBUG] Result keys:', Object.keys(result));
150
+ }
151
+
152
+ // Add debug information if available
153
+ if (result.debug) {
154
+ responseText += '\n\nDebug Info:';
155
+ responseText += `\n- Properties type: ${result.debug.propertiesType}`;
156
+ responseText += `\n- Properties count: ${result.debug.propertiesCount}`;
157
+ if (result.debug.firstPropertyKey) {
158
+ responseText += `\n- First property key: ${result.debug.firstPropertyKey}`;
159
+ }
160
+ }
161
+
162
+ return {
163
+ content: [
164
+ {
165
+ type: 'text',
166
+ text: responseText
167
+ }
168
+ ],
169
+ isError: false
170
+ };
171
+ } catch (error) {
172
+ return {
173
+ content: [
174
+ {
175
+ type: 'text',
176
+ text: `Failed to get component values: ${error.message}`
177
+ }
178
+ ],
179
+ isError: true
180
+ };
181
+ }
182
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Tool definition for get_gameobject_details
3
+ */
4
+ export const getGameObjectDetailsToolDefinition = {
5
+ name: 'get_gameobject_details',
6
+ description: 'Get details for a GameObject by name or path (children/components/materials).',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ gameObjectName: {
11
+ type: 'string',
12
+ description: 'Name of the GameObject to inspect'
13
+ },
14
+ path: {
15
+ type: 'string',
16
+ description: 'Full hierarchy path to the GameObject (use either name or path)'
17
+ },
18
+ includeChildren: {
19
+ type: 'boolean',
20
+ description: 'Include full hierarchy details. Default: false'
21
+ },
22
+ includeComponents: {
23
+ type: 'boolean',
24
+ description: 'Include all component details. Default: true'
25
+ },
26
+ includeMaterials: {
27
+ type: 'boolean',
28
+ description: 'Include material information. Default: false'
29
+ },
30
+ maxDepth: {
31
+ type: 'number',
32
+ description: 'Maximum depth for child traversal. Default: 3, Range: 0-10'
33
+ }
34
+ },
35
+ required: ['gameObjectName']
36
+ }
37
+ };
38
+
39
+ /**
40
+ * Handler for get_gameobject_details tool
41
+ */
42
+ export async function getGameObjectDetailsHandler(unityConnection, args) {
43
+ try {
44
+ // Check connection
45
+ if (!unityConnection.isConnected()) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: 'text',
50
+ text: 'Failed to get GameObject details: Unity connection not available'
51
+ }
52
+ ],
53
+ isError: true
54
+ };
55
+ }
56
+
57
+ // Validate that either gameObjectName or path is provided
58
+ if (!args.gameObjectName && !args.path) {
59
+ return {
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: 'Failed to get GameObject details: Either gameObjectName or path must be provided'
64
+ }
65
+ ],
66
+ isError: true
67
+ };
68
+ }
69
+
70
+ // Validate that only one identifier is provided
71
+ if (args.gameObjectName && args.path) {
72
+ return {
73
+ content: [
74
+ {
75
+ type: 'text',
76
+ text: 'Failed to get GameObject details: Provide either gameObjectName or path, not both'
77
+ }
78
+ ],
79
+ isError: true
80
+ };
81
+ }
82
+
83
+ // Validate maxDepth if provided
84
+ if (args.maxDepth !== undefined) {
85
+ if (args.maxDepth < 0 || args.maxDepth > 10) {
86
+ return {
87
+ content: [
88
+ {
89
+ type: 'text',
90
+ text: 'Failed to get GameObject details: maxDepth must be between 0 and 10'
91
+ }
92
+ ],
93
+ isError: true
94
+ };
95
+ }
96
+ }
97
+
98
+ // Build params only with provided values and defaults where needed
99
+ const params = {};
100
+
101
+ if (args.gameObjectName) params.gameObjectName = args.gameObjectName;
102
+ if (args.path) params.path = args.path;
103
+ if (args.includeChildren !== undefined) params.includeChildren = args.includeChildren;
104
+ if (args.includeComponents !== undefined) params.includeComponents = args.includeComponents;
105
+ if (args.includeMaterials !== undefined) params.includeMaterials = args.includeMaterials;
106
+ if (args.maxDepth !== undefined) params.maxDepth = args.maxDepth;
107
+
108
+ // Send command to Unity
109
+ const result = await unityConnection.sendCommand('get_gameobject_details', args);
110
+
111
+ // The unityConnection.sendCommand already extracts the result field
112
+ // from the response, so we access properties directly on result
113
+ if (!result || typeof result === 'string') {
114
+ return {
115
+ content: [
116
+ {
117
+ type: 'text',
118
+ text: `Failed to get GameObject details: Invalid response format`
119
+ }
120
+ ],
121
+ isError: true
122
+ };
123
+ }
124
+
125
+ // Check if result has error property (error response from Unity)
126
+ if (result.error) {
127
+ return {
128
+ content: [
129
+ {
130
+ type: 'text',
131
+ text: `Failed to get GameObject details: ${result.error}`
132
+ }
133
+ ],
134
+ isError: true
135
+ };
136
+ }
137
+
138
+ // Success response - result is already the unwrapped data
139
+ return {
140
+ content: [
141
+ {
142
+ type: 'text',
143
+ text: result.summary || `GameObject details retrieved`
144
+ }
145
+ ],
146
+ isError: false
147
+ };
148
+ } catch (error) {
149
+ return {
150
+ content: [
151
+ {
152
+ type: 'text',
153
+ text: `Failed to get GameObject details: ${error.message}`
154
+ }
155
+ ],
156
+ isError: true
157
+ };
158
+ }
159
+ }