@akiojin/unity-mcp-server 2.26.0 → 2.26.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/codeIndexDb.js +26 -10
- package/src/core/projectInfo.js +74 -65
- package/src/core/server.js +88 -65
- package/src/core/transports/HybridStdioServerTransport.js +179 -0
- package/src/core/unityConnection.js +52 -45
- package/src/handlers/base/BaseToolHandler.js +5 -5
- package/src/handlers/console/ConsoleReadToolHandler.js +285 -295
- package/src/handlers/editor/EditorSelectionManageToolHandler.js +10 -9
- package/src/handlers/gameobject/GameObjectModifyToolHandler.js +22 -11
- package/src/handlers/menu/MenuItemExecuteToolHandler.js +75 -37
- package/src/handlers/screenshot/ScreenshotAnalyzeToolHandler.js +12 -10
- package/src/handlers/script/ScriptEditStructuredToolHandler.js +162 -154
- package/src/handlers/script/ScriptReadToolHandler.js +80 -85
- package/src/handlers/script/ScriptRefsFindToolHandler.js +123 -123
- package/src/handlers/script/ScriptSymbolFindToolHandler.js +125 -112
- package/src/handlers/system/SystemGetCommandStatsToolHandler.js +1 -1
- package/src/handlers/system/SystemRefreshAssetsToolHandler.js +10 -14
- package/src/handlers/video/VideoCaptureStartToolHandler.js +15 -5
- package/src/handlers/video/VideoCaptureStatusToolHandler.js +5 -9
- package/src/handlers/video/VideoCaptureStopToolHandler.js +8 -9
- package/src/lsp/LspProcessManager.js +26 -9
- package/src/tools/video/recordFor.js +13 -7
- package/src/tools/video/recordPlayMode.js +7 -6
- package/src/utils/csharpParse.js +14 -8
package/package.json
CHANGED
package/src/core/codeIndexDb.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import Database from 'better-sqlite3';
|
|
4
|
-
import { logger } from './config.js';
|
|
5
|
-
|
|
6
4
|
let dbCache = new Map();
|
|
7
5
|
|
|
8
6
|
function getDbPath(projectRoot) {
|
|
@@ -47,16 +45,29 @@ export function openDb(projectRoot) {
|
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
export function upsertFile(db, filePath, mtimeMs) {
|
|
50
|
-
const stmt = db.prepare(
|
|
48
|
+
const stmt = db.prepare(
|
|
49
|
+
'INSERT INTO files(path, mtime) VALUES(?, ?) ON CONFLICT(path) DO UPDATE SET mtime=excluded.mtime'
|
|
50
|
+
);
|
|
51
51
|
stmt.run(filePath, Math.floor(mtimeMs));
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export function replaceSymbols(db, filePath, symbols) {
|
|
55
55
|
const del = db.prepare('DELETE FROM symbols WHERE path = ?');
|
|
56
56
|
del.run(filePath);
|
|
57
|
-
const ins = db.prepare(
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const ins = db.prepare(
|
|
58
|
+
'INSERT INTO symbols(path, name, kind, container, ns, line, column) VALUES(?,?,?,?,?,?,?)'
|
|
59
|
+
);
|
|
60
|
+
const tr = db.transaction(rows => {
|
|
61
|
+
for (const s of rows)
|
|
62
|
+
ins.run(
|
|
63
|
+
filePath,
|
|
64
|
+
s.name || '',
|
|
65
|
+
s.kind || '',
|
|
66
|
+
s.container || null,
|
|
67
|
+
s.ns || null,
|
|
68
|
+
s.line || 0,
|
|
69
|
+
s.column || 0
|
|
70
|
+
);
|
|
60
71
|
});
|
|
61
72
|
tr(symbols || []);
|
|
62
73
|
}
|
|
@@ -65,7 +76,7 @@ export function replaceReferences(db, filePath, refs) {
|
|
|
65
76
|
const del = db.prepare('DELETE FROM refs WHERE path = ?');
|
|
66
77
|
del.run(filePath);
|
|
67
78
|
const ins = db.prepare('INSERT INTO refs(path, name, line, snippet) VALUES(?,?,?,?)');
|
|
68
|
-
const tr = db.transaction(
|
|
79
|
+
const tr = db.transaction(rows => {
|
|
69
80
|
for (const r of rows) ins.run(filePath, r.name || '', r.line || 0, r.snippet || null);
|
|
70
81
|
});
|
|
71
82
|
tr(refs || []);
|
|
@@ -73,9 +84,15 @@ export function replaceReferences(db, filePath, refs) {
|
|
|
73
84
|
|
|
74
85
|
export function querySymbolsByName(db, name, kind = null) {
|
|
75
86
|
if (kind) {
|
|
76
|
-
return db
|
|
87
|
+
return db
|
|
88
|
+
.prepare(
|
|
89
|
+
'SELECT path,name,kind,container,ns,line,column FROM symbols WHERE name = ? AND kind = ? LIMIT 500'
|
|
90
|
+
)
|
|
91
|
+
.all(name, kind);
|
|
77
92
|
}
|
|
78
|
-
return db
|
|
93
|
+
return db
|
|
94
|
+
.prepare('SELECT path,name,kind,container,ns,line,column FROM symbols WHERE name = ? LIMIT 500')
|
|
95
|
+
.all(name);
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
export function queryRefsByName(db, name) {
|
|
@@ -93,4 +110,3 @@ export function isFresh(projectRoot, filePath, db) {
|
|
|
93
110
|
return false;
|
|
94
111
|
}
|
|
95
112
|
}
|
|
96
|
-
|
package/src/core/projectInfo.js
CHANGED
|
@@ -1,65 +1,74 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
projectRoot
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { logger, config, WORKSPACE_ROOT } from './config.js';
|
|
3
|
+
|
|
4
|
+
const normalize = p => p.replace(/\\/g, '/');
|
|
5
|
+
|
|
6
|
+
const resolveDefaultCodeIndexRoot = projectRoot => {
|
|
7
|
+
const base = WORKSPACE_ROOT || projectRoot || process.cwd();
|
|
8
|
+
return normalize(path.join(base, '.unity', 'cache', 'code-index'));
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Lazy project info resolver. Prefers Unity via get_editor_info, otherwise infers by walking up for Assets/Packages.
|
|
12
|
+
export class ProjectInfoProvider {
|
|
13
|
+
constructor(unityConnection) {
|
|
14
|
+
this.unityConnection = unityConnection;
|
|
15
|
+
this.cached = null;
|
|
16
|
+
this.lastTried = 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async get() {
|
|
20
|
+
if (this.cached) return this.cached;
|
|
21
|
+
// Config-driven project root (no env fallback)
|
|
22
|
+
const cfgRootRaw = config?.project?.root;
|
|
23
|
+
if (typeof cfgRootRaw === 'string' && cfgRootRaw.trim().length > 0) {
|
|
24
|
+
const cfgRoot = cfgRootRaw.trim();
|
|
25
|
+
// Resolve relative paths against WORKSPACE_ROOT
|
|
26
|
+
const projectRoot = normalize(
|
|
27
|
+
path.isAbsolute(cfgRoot) ? cfgRoot : path.resolve(WORKSPACE_ROOT, cfgRoot)
|
|
28
|
+
);
|
|
29
|
+
const codeIndexRoot = normalize(
|
|
30
|
+
config?.project?.codeIndexRoot || resolveDefaultCodeIndexRoot(projectRoot)
|
|
31
|
+
);
|
|
32
|
+
this.cached = {
|
|
33
|
+
projectRoot,
|
|
34
|
+
assetsPath: normalize(path.join(projectRoot, 'Assets')),
|
|
35
|
+
packagesPath: normalize(path.join(projectRoot, 'Packages')),
|
|
36
|
+
codeIndexRoot
|
|
37
|
+
};
|
|
38
|
+
return this.cached;
|
|
39
|
+
}
|
|
40
|
+
// Try Unity if connected (rate-limit attempts)
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
if (this.unityConnection && this.unityConnection.isConnected() && now - this.lastTried > 1000) {
|
|
43
|
+
this.lastTried = now;
|
|
44
|
+
try {
|
|
45
|
+
const info = await this.unityConnection.sendCommand('get_editor_info', {});
|
|
46
|
+
if (info && info.projectRoot && info.assetsPath) {
|
|
47
|
+
this.cached = {
|
|
48
|
+
projectRoot: info.projectRoot,
|
|
49
|
+
assetsPath: info.assetsPath,
|
|
50
|
+
packagesPath: normalize(info.packagesPath || path.join(info.projectRoot, 'Packages')),
|
|
51
|
+
codeIndexRoot: normalize(
|
|
52
|
+
info.codeIndexRoot || resolveDefaultCodeIndexRoot(info.projectRoot)
|
|
53
|
+
)
|
|
54
|
+
};
|
|
55
|
+
return this.cached;
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
logger.warn(`get_editor_info failed: ${e.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (typeof cfgRootRaw === 'string') {
|
|
62
|
+
throw new Error(
|
|
63
|
+
'project.root is configured but empty. Set a valid path in .unity/config.json or UNITY_MCP_CONFIG.'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
throw new Error(
|
|
67
|
+
'Unable to resolve Unity project root. Configure project.root in .unity/config.json or provide UNITY_MCP_CONFIG.'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
inferFromCwd() {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/core/server.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
ListToolsRequestSchema,
|
|
3
|
+
import {
|
|
4
|
+
ListToolsRequestSchema,
|
|
6
5
|
CallToolRequestSchema,
|
|
7
6
|
ListResourcesRequestSchema,
|
|
8
7
|
ListPromptsRequestSchema
|
|
@@ -12,6 +11,7 @@ import { UnityConnection } from './unityConnection.js';
|
|
|
12
11
|
import { createHandlers } from '../handlers/index.js';
|
|
13
12
|
import { config, logger } from './config.js';
|
|
14
13
|
import { IndexWatcher } from './indexWatcher.js';
|
|
14
|
+
import { HybridStdioServerTransport } from './transports/HybridStdioServerTransport.js';
|
|
15
15
|
|
|
16
16
|
// Create Unity connection
|
|
17
17
|
const unityConnection = new UnityConnection();
|
|
@@ -23,7 +23,7 @@ const handlers = createHandlers(unityConnection);
|
|
|
23
23
|
const server = new Server(
|
|
24
24
|
{
|
|
25
25
|
name: config.server.name,
|
|
26
|
-
version: config.server.version
|
|
26
|
+
version: config.server.version
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
capabilities: {
|
|
@@ -41,20 +41,24 @@ const server = new Server(
|
|
|
41
41
|
|
|
42
42
|
// Handle tool listing
|
|
43
43
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
44
|
-
const tools = Array.from(handlers.values())
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const tools = Array.from(handlers.values())
|
|
45
|
+
.map((handler, index) => {
|
|
46
|
+
try {
|
|
47
|
+
const definition = handler.getDefinition();
|
|
48
|
+
// Validate inputSchema
|
|
49
|
+
if (definition.inputSchema && definition.inputSchema.type !== 'object') {
|
|
50
|
+
logger.error(
|
|
51
|
+
`[MCP] Tool ${handler.name} (index ${index}) has invalid inputSchema type: ${definition.inputSchema.type}`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return definition;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
logger.error(`[MCP] Failed to get definition for handler ${handler.name}:`, error);
|
|
57
|
+
return null;
|
|
50
58
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}).filter(tool => tool !== null);
|
|
57
|
-
|
|
59
|
+
})
|
|
60
|
+
.filter(tool => tool !== null);
|
|
61
|
+
|
|
58
62
|
logger.info(`[MCP] Returning ${tools.length} tool definitions`);
|
|
59
63
|
return { tools };
|
|
60
64
|
});
|
|
@@ -74,36 +78,42 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
// Handle tool execution
|
|
77
|
-
server.setRequestHandler(CallToolRequestSchema, async
|
|
81
|
+
server.setRequestHandler(CallToolRequestSchema, async request => {
|
|
78
82
|
const { name, arguments: args } = request.params;
|
|
79
83
|
const requestTime = Date.now();
|
|
80
|
-
|
|
81
|
-
logger.info(
|
|
82
|
-
|
|
84
|
+
|
|
85
|
+
logger.info(
|
|
86
|
+
`[MCP] Received tool call request: ${name} at ${new Date(requestTime).toISOString()}`,
|
|
87
|
+
{ args }
|
|
88
|
+
);
|
|
89
|
+
|
|
83
90
|
const handler = handlers.get(name);
|
|
84
91
|
if (!handler) {
|
|
85
92
|
logger.error(`[MCP] Tool not found: ${name}`);
|
|
86
93
|
throw new Error(`Tool not found: ${name}`);
|
|
87
94
|
}
|
|
88
|
-
|
|
95
|
+
|
|
89
96
|
try {
|
|
90
97
|
logger.info(`[MCP] Starting handler execution for: ${name} at ${new Date().toISOString()}`);
|
|
91
98
|
const startTime = Date.now();
|
|
92
|
-
|
|
99
|
+
|
|
93
100
|
// Handler returns response in our format
|
|
94
101
|
const result = await handler.handle(args);
|
|
95
|
-
|
|
102
|
+
|
|
96
103
|
const duration = Date.now() - startTime;
|
|
97
104
|
const totalDuration = Date.now() - requestTime;
|
|
98
|
-
logger.info(`[MCP] Handler completed at ${new Date().toISOString()}: ${name}`, {
|
|
105
|
+
logger.info(`[MCP] Handler completed at ${new Date().toISOString()}: ${name}`, {
|
|
99
106
|
handlerDuration: `${duration}ms`,
|
|
100
107
|
totalDuration: `${totalDuration}ms`,
|
|
101
|
-
status: result.status
|
|
108
|
+
status: result.status
|
|
102
109
|
});
|
|
103
|
-
|
|
110
|
+
|
|
104
111
|
// Convert to MCP format
|
|
105
112
|
if (result.status === 'error') {
|
|
106
|
-
logger.error(`[MCP] Handler returned error: ${name}`, {
|
|
113
|
+
logger.error(`[MCP] Handler returned error: ${name}`, {
|
|
114
|
+
error: result.error,
|
|
115
|
+
code: result.code
|
|
116
|
+
});
|
|
107
117
|
return {
|
|
108
118
|
content: [
|
|
109
119
|
{
|
|
@@ -113,22 +123,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
113
123
|
]
|
|
114
124
|
};
|
|
115
125
|
}
|
|
116
|
-
|
|
126
|
+
|
|
117
127
|
// Success response
|
|
118
128
|
logger.info(`[MCP] Returning success response for: ${name} at ${new Date().toISOString()}`);
|
|
119
|
-
|
|
129
|
+
|
|
120
130
|
// Handle undefined or null results from handlers
|
|
121
131
|
let responseText;
|
|
122
132
|
if (result.result === undefined || result.result === null) {
|
|
123
|
-
responseText = JSON.stringify(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
responseText = JSON.stringify(
|
|
134
|
+
{
|
|
135
|
+
status: 'success',
|
|
136
|
+
message: 'Operation completed successfully but no details were returned',
|
|
137
|
+
tool: name
|
|
138
|
+
},
|
|
139
|
+
null,
|
|
140
|
+
2
|
|
141
|
+
);
|
|
128
142
|
} else {
|
|
129
143
|
responseText = JSON.stringify(result.result, null, 2);
|
|
130
144
|
}
|
|
131
|
-
|
|
145
|
+
|
|
132
146
|
return {
|
|
133
147
|
content: [
|
|
134
148
|
{
|
|
@@ -139,8 +153,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
139
153
|
};
|
|
140
154
|
} catch (error) {
|
|
141
155
|
const errorTime = Date.now();
|
|
142
|
-
logger.error(`[MCP] Handler threw exception at ${new Date(errorTime).toISOString()}: ${name}`, {
|
|
143
|
-
error: error.message,
|
|
156
|
+
logger.error(`[MCP] Handler threw exception at ${new Date(errorTime).toISOString()}: ${name}`, {
|
|
157
|
+
error: error.message,
|
|
144
158
|
stack: error.stack,
|
|
145
159
|
duration: `${errorTime - requestTime}ms`
|
|
146
160
|
});
|
|
@@ -164,7 +178,7 @@ unityConnection.on('disconnected', () => {
|
|
|
164
178
|
logger.info('Unity connection lost');
|
|
165
179
|
});
|
|
166
180
|
|
|
167
|
-
unityConnection.on('error',
|
|
181
|
+
unityConnection.on('error', error => {
|
|
168
182
|
logger.error('Unity connection error:', error.message);
|
|
169
183
|
});
|
|
170
184
|
|
|
@@ -172,14 +186,14 @@ unityConnection.on('error', (error) => {
|
|
|
172
186
|
export async function startServer() {
|
|
173
187
|
try {
|
|
174
188
|
// Create transport - no logging before connection
|
|
175
|
-
const transport = new
|
|
176
|
-
|
|
189
|
+
const transport = new HybridStdioServerTransport();
|
|
190
|
+
|
|
177
191
|
// Connect to transport
|
|
178
192
|
await server.connect(transport);
|
|
179
|
-
|
|
193
|
+
|
|
180
194
|
// Now safe to log after connection established
|
|
181
195
|
logger.info('MCP server started successfully');
|
|
182
|
-
|
|
196
|
+
|
|
183
197
|
// Attempt to connect to Unity
|
|
184
198
|
try {
|
|
185
199
|
await unityConnection.connect();
|
|
@@ -189,13 +203,17 @@ export async function startServer() {
|
|
|
189
203
|
}
|
|
190
204
|
|
|
191
205
|
// Best-effort: prepare and start persistent C# LSP process (non-blocking)
|
|
192
|
-
|
|
206
|
+
(async () => {
|
|
193
207
|
try {
|
|
194
208
|
const { LspProcessManager } = await import('../lsp/LspProcessManager.js');
|
|
195
209
|
const mgr = new LspProcessManager();
|
|
196
210
|
await mgr.ensureStarted();
|
|
197
211
|
// Attach graceful shutdown
|
|
198
|
-
const shutdown = async () => {
|
|
212
|
+
const shutdown = async () => {
|
|
213
|
+
try {
|
|
214
|
+
await mgr.stop(3000);
|
|
215
|
+
} catch {}
|
|
216
|
+
};
|
|
199
217
|
process.on('SIGINT', shutdown);
|
|
200
218
|
process.on('SIGTERM', shutdown);
|
|
201
219
|
} catch (e) {
|
|
@@ -206,10 +224,14 @@ export async function startServer() {
|
|
|
206
224
|
// Start periodic index watcher (incremental)
|
|
207
225
|
const watcher = new IndexWatcher(unityConnection);
|
|
208
226
|
watcher.start();
|
|
209
|
-
const stopWatch = () => {
|
|
227
|
+
const stopWatch = () => {
|
|
228
|
+
try {
|
|
229
|
+
watcher.stop();
|
|
230
|
+
} catch {}
|
|
231
|
+
};
|
|
210
232
|
process.on('SIGINT', stopWatch);
|
|
211
233
|
process.on('SIGTERM', stopWatch);
|
|
212
|
-
|
|
234
|
+
|
|
213
235
|
// Handle shutdown
|
|
214
236
|
process.on('SIGINT', async () => {
|
|
215
237
|
logger.info('Shutting down...');
|
|
@@ -217,14 +239,13 @@ export async function startServer() {
|
|
|
217
239
|
await server.close();
|
|
218
240
|
process.exit(0);
|
|
219
241
|
});
|
|
220
|
-
|
|
242
|
+
|
|
221
243
|
process.on('SIGTERM', async () => {
|
|
222
244
|
logger.info('Shutting down...');
|
|
223
245
|
unityConnection.disconnect();
|
|
224
246
|
await server.close();
|
|
225
247
|
process.exit(0);
|
|
226
248
|
});
|
|
227
|
-
|
|
228
249
|
} catch (error) {
|
|
229
250
|
console.error('Failed to start server:', error);
|
|
230
251
|
console.error('Stack trace:', error.stack);
|
|
@@ -233,17 +254,17 @@ export async function startServer() {
|
|
|
233
254
|
}
|
|
234
255
|
|
|
235
256
|
// Maintain backwards compatibility for older callers that expect main()
|
|
236
|
-
const main = startServer;
|
|
257
|
+
export const main = startServer;
|
|
237
258
|
|
|
238
259
|
// Export for testing
|
|
239
260
|
export async function createServer(customConfig = config) {
|
|
240
261
|
const testUnityConnection = new UnityConnection();
|
|
241
262
|
const testHandlers = createHandlers(testUnityConnection);
|
|
242
|
-
|
|
263
|
+
|
|
243
264
|
const testServer = new Server(
|
|
244
265
|
{
|
|
245
266
|
name: customConfig.server.name,
|
|
246
|
-
version: customConfig.server.version
|
|
267
|
+
version: customConfig.server.version
|
|
247
268
|
},
|
|
248
269
|
{
|
|
249
270
|
capabilities: {
|
|
@@ -253,24 +274,24 @@ export async function createServer(customConfig = config) {
|
|
|
253
274
|
}
|
|
254
275
|
}
|
|
255
276
|
);
|
|
256
|
-
|
|
277
|
+
|
|
257
278
|
// Register handlers for test server
|
|
258
279
|
testServer.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
259
280
|
const tools = Array.from(testHandlers.values()).map(handler => handler.getDefinition());
|
|
260
281
|
return { tools };
|
|
261
282
|
});
|
|
262
|
-
|
|
283
|
+
|
|
263
284
|
testServer.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
264
285
|
return { resources: [] };
|
|
265
286
|
});
|
|
266
|
-
|
|
287
|
+
|
|
267
288
|
testServer.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
268
289
|
return { prompts: [] };
|
|
269
290
|
});
|
|
270
|
-
|
|
271
|
-
testServer.setRequestHandler(CallToolRequestSchema, async
|
|
291
|
+
|
|
292
|
+
testServer.setRequestHandler(CallToolRequestSchema, async request => {
|
|
272
293
|
const { name, arguments: args } = request.params;
|
|
273
|
-
|
|
294
|
+
|
|
274
295
|
const handler = testHandlers.get(name);
|
|
275
296
|
if (!handler) {
|
|
276
297
|
return {
|
|
@@ -279,10 +300,10 @@ export async function createServer(customConfig = config) {
|
|
|
279
300
|
code: 'TOOL_NOT_FOUND'
|
|
280
301
|
};
|
|
281
302
|
}
|
|
282
|
-
|
|
303
|
+
|
|
283
304
|
return await handler.handle(args);
|
|
284
305
|
});
|
|
285
|
-
|
|
306
|
+
|
|
286
307
|
return {
|
|
287
308
|
server: testServer,
|
|
288
309
|
unityConnection: testUnityConnection
|
|
@@ -300,8 +321,10 @@ const isDirectExecution = (() => {
|
|
|
300
321
|
}
|
|
301
322
|
})();
|
|
302
323
|
|
|
303
|
-
if (isDirectExecution)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
324
|
+
if (isDirectExecution) {
|
|
325
|
+
startServer().catch(error => {
|
|
326
|
+
console.error('Fatal error:', error);
|
|
327
|
+
console.error('Stack trace:', error.stack);
|
|
328
|
+
process.exit(1);
|
|
329
|
+
});
|
|
330
|
+
}
|