@akiojin/unity-mcp-server 3.2.0 → 3.2.1
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/package.json +1 -1
- package/src/core/unityCommandType.js +10 -0
- package/src/core/unityConnection.js +4 -2
- package/src/tools/analysis/analyzeSceneContents.js +1 -1
- package/src/tools/analysis/findByComponent.js +19 -4
- package/src/tools/analysis/getAnimatorState.js +7 -4
- package/src/tools/analysis/getComponentValues.js +2 -1
- package/src/tools/analysis/getGameObjectDetails.js +1 -1
- package/src/tools/analysis/getInputActionsState.js +2 -2
- package/src/tools/analysis/getObjectReferences.js +17 -4
- package/src/tools/input/inputActionsEditor.js +13 -10
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const TOOL_NAME_TO_UNITY_COMMAND_TYPE = Object.freeze({
|
|
2
|
+
// Animator tools: tool name (MCP) -> Unity command type (TCP)
|
|
3
|
+
analysis_animator_state_get: 'get_animator_state',
|
|
4
|
+
analysis_animator_runtime_info_get: 'get_animator_runtime_info'
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
export function normalizeUnityCommandType(type) {
|
|
8
|
+
if (typeof type !== 'string' || type.length === 0) return type;
|
|
9
|
+
return TOOL_NAME_TO_UNITY_COMMAND_TYPE[type] ?? type;
|
|
10
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import net from 'net';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { config, logger } from './config.js';
|
|
4
|
+
import { normalizeUnityCommandType } from './unityCommandType.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Manages TCP connection to Unity Editor
|
|
@@ -360,7 +361,8 @@ export class UnityConnection extends EventEmitter {
|
|
|
360
361
|
* @returns {Promise<any>} - Response from Unity
|
|
361
362
|
*/
|
|
362
363
|
async sendCommand(type, params = {}) {
|
|
363
|
-
|
|
364
|
+
const normalizedType = normalizeUnityCommandType(type);
|
|
365
|
+
logger.info(`[Unity] enqueue sendCommand: ${normalizedType}`, { connected: this.connected });
|
|
364
366
|
|
|
365
367
|
if (!this.connected) {
|
|
366
368
|
logger.warning('[Unity] Not connected; waiting for reconnection before sending command');
|
|
@@ -371,7 +373,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
371
373
|
|
|
372
374
|
// Create an external promise that will resolve when Unity responds
|
|
373
375
|
return new Promise((outerResolve, outerReject) => {
|
|
374
|
-
const task = { type, params, outerResolve, outerReject };
|
|
376
|
+
const task = { type: normalizedType, params, outerResolve, outerReject };
|
|
375
377
|
this.sendQueue.push(task);
|
|
376
378
|
this._pumpQueue();
|
|
377
379
|
});
|
|
@@ -47,7 +47,7 @@ export async function analyzeSceneContentsHandler(unityConnection, args) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Send command to Unity with provided parameters
|
|
50
|
-
const result = await unityConnection.sendCommand('
|
|
50
|
+
const result = await unityConnection.sendCommand('analyze_scene_contents', args);
|
|
51
51
|
|
|
52
52
|
// The unityConnection.sendCommand already extracts the result field
|
|
53
53
|
// from the response, so we access properties directly on result
|
|
@@ -48,10 +48,23 @@ export async function findByComponentHandler(unityConnection, args) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Send command to Unity
|
|
51
|
-
const result = await unityConnection.sendCommand('
|
|
51
|
+
const result = await unityConnection.sendCommand('find_by_component', args);
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
|
|
53
|
+
// The unityConnection.sendCommand already extracts the result field
|
|
54
|
+
// from the response, so we access properties directly on result
|
|
55
|
+
if (!result || typeof result === 'string') {
|
|
56
|
+
return {
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: 'text',
|
|
60
|
+
text: `Failed to find GameObjects: Invalid response format`
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
isError: true
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (result.error) {
|
|
55
68
|
return {
|
|
56
69
|
content: [
|
|
57
70
|
{
|
|
@@ -63,12 +76,14 @@ export async function findByComponentHandler(unityConnection, args) {
|
|
|
63
76
|
};
|
|
64
77
|
}
|
|
65
78
|
|
|
79
|
+
const summary = result.summary || `Found ${result.totalFound ?? 0} GameObjects`;
|
|
80
|
+
|
|
66
81
|
// Success response
|
|
67
82
|
return {
|
|
68
83
|
content: [
|
|
69
84
|
{
|
|
70
85
|
type: 'text',
|
|
71
|
-
text:
|
|
86
|
+
text: summary
|
|
72
87
|
}
|
|
73
88
|
],
|
|
74
89
|
isError: false
|
|
@@ -99,8 +99,8 @@ export async function getAnimatorStateHandler(unityConnection, args) {
|
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// Send command to Unity
|
|
103
|
-
const result = await unityConnection.sendCommand(
|
|
102
|
+
// Send command to Unity (tool name is normalized to Unity command type in UnityConnection)
|
|
103
|
+
const result = await unityConnection.sendCommand(getAnimatorStateToolDefinition.name, args);
|
|
104
104
|
|
|
105
105
|
// Check for errors
|
|
106
106
|
if (!result || typeof result === 'string') {
|
|
@@ -221,8 +221,11 @@ export async function getAnimatorRuntimeInfoHandler(unityConnection, args) {
|
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
// Send command to Unity
|
|
225
|
-
const result = await unityConnection.sendCommand(
|
|
224
|
+
// Send command to Unity (tool name is normalized to Unity command type in UnityConnection)
|
|
225
|
+
const result = await unityConnection.sendCommand(
|
|
226
|
+
getAnimatorRuntimeInfoToolDefinition.name,
|
|
227
|
+
args
|
|
228
|
+
);
|
|
226
229
|
|
|
227
230
|
// Check for errors
|
|
228
231
|
if (!result || typeof result === 'string') {
|
|
@@ -77,7 +77,7 @@ export async function getComponentValuesHandler(unityConnection, args) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Send command to Unity
|
|
80
|
-
const result = await unityConnection.sendCommand('
|
|
80
|
+
const result = await unityConnection.sendCommand('get_component_values', args);
|
|
81
81
|
|
|
82
82
|
// The unityConnection.sendCommand already extracts the result field
|
|
83
83
|
// from the response, so we access properties directly on result
|
|
@@ -106,6 +106,7 @@ export async function getComponentValuesHandler(unityConnection, args) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// Success response - result is already the unwrapped data
|
|
109
110
|
let responseText = result.summary || `Component values retrieved`;
|
|
110
111
|
|
|
111
112
|
// Add detailed property information if available
|
|
@@ -106,7 +106,7 @@ export async function getGameObjectDetailsHandler(unityConnection, args) {
|
|
|
106
106
|
if (args.maxDepth !== undefined) params.maxDepth = args.maxDepth;
|
|
107
107
|
|
|
108
108
|
// Send command to Unity
|
|
109
|
-
const result = await unityConnection.sendCommand('
|
|
109
|
+
const result = await unityConnection.sendCommand('get_gameobject_details', params);
|
|
110
110
|
|
|
111
111
|
// The unityConnection.sendCommand already extracts the result field
|
|
112
112
|
// from the response, so we access properties directly on result
|
|
@@ -75,7 +75,7 @@ export async function getInputActionsStateHandler(unityConnection, args) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// Send command to Unity
|
|
78
|
-
const result = await unityConnection.sendCommand('
|
|
78
|
+
const result = await unityConnection.sendCommand('get_input_actions_state', args);
|
|
79
79
|
|
|
80
80
|
// Check for errors
|
|
81
81
|
if (!result || typeof result === 'string') {
|
|
@@ -216,7 +216,7 @@ export async function analyzeInputActionsAssetHandler(unityConnection, args) {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
// Send command to Unity
|
|
219
|
-
const result = await unityConnection.sendCommand('
|
|
219
|
+
const result = await unityConnection.sendCommand('analyze_input_actions_asset', args);
|
|
220
220
|
|
|
221
221
|
// Check for errors
|
|
222
222
|
if (!result || typeof result === 'string') {
|
|
@@ -47,10 +47,23 @@ export async function getObjectReferencesHandler(unityConnection, args) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Send command to Unity
|
|
50
|
-
const result = await unityConnection.sendCommand('
|
|
50
|
+
const result = await unityConnection.sendCommand('get_object_references', args);
|
|
51
51
|
|
|
52
|
-
//
|
|
53
|
-
|
|
52
|
+
// The unityConnection.sendCommand already extracts the result field
|
|
53
|
+
// from the response, so we access properties directly on result
|
|
54
|
+
if (!result || typeof result === 'string') {
|
|
55
|
+
return {
|
|
56
|
+
content: [
|
|
57
|
+
{
|
|
58
|
+
type: 'text',
|
|
59
|
+
text: `Failed to get object references: Invalid response format`
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
isError: true
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (result.error) {
|
|
54
67
|
return {
|
|
55
68
|
content: [
|
|
56
69
|
{
|
|
@@ -67,7 +80,7 @@ export async function getObjectReferencesHandler(unityConnection, args) {
|
|
|
67
80
|
content: [
|
|
68
81
|
{
|
|
69
82
|
type: 'text',
|
|
70
|
-
text: result.
|
|
83
|
+
text: result.summary || `References analyzed for ${args.gameObjectName}`
|
|
71
84
|
}
|
|
72
85
|
],
|
|
73
86
|
isError: false
|
|
@@ -303,7 +303,10 @@ function formatUnityResponse(result, successMessage) {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
if (result.success) {
|
|
306
|
-
let text = result.message ||
|
|
306
|
+
let text = successMessage || result.message || 'Operation completed';
|
|
307
|
+
if (successMessage && result.message && result.message !== successMessage) {
|
|
308
|
+
text += `\n${result.message}`;
|
|
309
|
+
}
|
|
307
310
|
// Add any additional info from result
|
|
308
311
|
Object.keys(result).forEach(key => {
|
|
309
312
|
if (key !== 'success' && key !== 'message' && key !== 'error') {
|
|
@@ -348,7 +351,7 @@ export async function createActionMapHandler(unityConnection, args) {
|
|
|
348
351
|
};
|
|
349
352
|
}
|
|
350
353
|
|
|
351
|
-
const result = await unityConnection.sendCommand('
|
|
354
|
+
const result = await unityConnection.sendCommand('create_action_map', args);
|
|
352
355
|
return formatUnityResponse(result, `Created Action Map: ${args.mapName}`);
|
|
353
356
|
} catch (error) {
|
|
354
357
|
return {
|
|
@@ -377,7 +380,7 @@ export async function removeActionMapHandler(unityConnection, args) {
|
|
|
377
380
|
};
|
|
378
381
|
}
|
|
379
382
|
|
|
380
|
-
const result = await unityConnection.sendCommand('
|
|
383
|
+
const result = await unityConnection.sendCommand('remove_action_map', args);
|
|
381
384
|
return formatUnityResponse(result, `Removed Action Map: ${args.mapName}`);
|
|
382
385
|
} catch (error) {
|
|
383
386
|
return {
|
|
@@ -407,7 +410,7 @@ export async function addInputActionHandler(unityConnection, args) {
|
|
|
407
410
|
};
|
|
408
411
|
}
|
|
409
412
|
|
|
410
|
-
const result = await unityConnection.sendCommand('
|
|
413
|
+
const result = await unityConnection.sendCommand('add_input_action', args);
|
|
411
414
|
return formatUnityResponse(result, `Added Action: ${args.actionName}`);
|
|
412
415
|
} catch (error) {
|
|
413
416
|
return {
|
|
@@ -436,7 +439,7 @@ export async function removeInputActionHandler(unityConnection, args) {
|
|
|
436
439
|
};
|
|
437
440
|
}
|
|
438
441
|
|
|
439
|
-
const result = await unityConnection.sendCommand('
|
|
442
|
+
const result = await unityConnection.sendCommand('remove_input_action', args);
|
|
440
443
|
return formatUnityResponse(result, `Removed Action: ${args.actionName}`);
|
|
441
444
|
} catch (error) {
|
|
442
445
|
return {
|
|
@@ -466,7 +469,7 @@ export async function addInputBindingHandler(unityConnection, args) {
|
|
|
466
469
|
};
|
|
467
470
|
}
|
|
468
471
|
|
|
469
|
-
const result = await unityConnection.sendCommand('
|
|
472
|
+
const result = await unityConnection.sendCommand('add_input_binding', args);
|
|
470
473
|
return formatUnityResponse(result, `Added Binding: ${args.path}`);
|
|
471
474
|
} catch (error) {
|
|
472
475
|
return {
|
|
@@ -495,7 +498,7 @@ export async function removeInputBindingHandler(unityConnection, args) {
|
|
|
495
498
|
};
|
|
496
499
|
}
|
|
497
500
|
|
|
498
|
-
const result = await unityConnection.sendCommand('
|
|
501
|
+
const result = await unityConnection.sendCommand('remove_input_binding', args);
|
|
499
502
|
return formatUnityResponse(result, 'Removed Binding');
|
|
500
503
|
} catch (error) {
|
|
501
504
|
return {
|
|
@@ -524,7 +527,7 @@ export async function removeAllBindingsHandler(unityConnection, args) {
|
|
|
524
527
|
};
|
|
525
528
|
}
|
|
526
529
|
|
|
527
|
-
const result = await unityConnection.sendCommand('
|
|
530
|
+
const result = await unityConnection.sendCommand('remove_all_bindings', args);
|
|
528
531
|
return formatUnityResponse(result, `Removed all bindings from ${args.actionName}`);
|
|
529
532
|
} catch (error) {
|
|
530
533
|
return {
|
|
@@ -553,7 +556,7 @@ export async function createCompositeBindingHandler(unityConnection, args) {
|
|
|
553
556
|
};
|
|
554
557
|
}
|
|
555
558
|
|
|
556
|
-
const result = await unityConnection.sendCommand('
|
|
559
|
+
const result = await unityConnection.sendCommand('create_composite_binding', args);
|
|
557
560
|
return formatUnityResponse(
|
|
558
561
|
result,
|
|
559
562
|
`Created composite binding: ${args.name || args.compositeType}`
|
|
@@ -586,7 +589,7 @@ export async function manageControlSchemesHandler(unityConnection, args) {
|
|
|
586
589
|
};
|
|
587
590
|
}
|
|
588
591
|
|
|
589
|
-
const result = await unityConnection.sendCommand('
|
|
592
|
+
const result = await unityConnection.sendCommand('manage_control_schemes', args);
|
|
590
593
|
const operationText =
|
|
591
594
|
args.operation === 'add' ? 'Added' : args.operation === 'remove' ? 'Removed' : 'Modified';
|
|
592
595
|
return formatUnityResponse(result, `${operationText} control scheme: ${args.schemeName}`);
|