@akiojin/unity-mcp-server 5.2.1 → 5.3.2

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 (28) hide show
  1. package/README.md +1 -0
  2. package/package.json +28 -40
  3. package/src/core/codeIndex.js +54 -7
  4. package/src/core/config.js +15 -1
  5. package/src/core/httpServer.js +30 -6
  6. package/src/core/indexBuildWorkerPool.js +57 -3
  7. package/src/core/indexWatcher.js +10 -4
  8. package/src/core/projectInfo.js +34 -12
  9. package/src/core/server.js +58 -27
  10. package/src/core/toolManifest.json +145 -629
  11. package/src/handlers/addressables/AddressablesAnalyzeToolHandler.js +14 -6
  12. package/src/handlers/addressables/AddressablesBuildToolHandler.js +6 -3
  13. package/src/handlers/addressables/AddressablesManageToolHandler.js +6 -3
  14. package/src/handlers/input/InputSystemControlToolHandler.js +1 -1
  15. package/src/handlers/input/InputTouchToolHandler.js +7 -3
  16. package/src/handlers/package/PackageManagerToolHandler.js +6 -3
  17. package/src/handlers/script/CodeIndexStatusToolHandler.js +37 -1
  18. package/src/handlers/script/CodeIndexUpdateToolHandler.js +1 -1
  19. package/src/handlers/script/ScriptEditSnippetToolHandler.js +1 -2
  20. package/src/handlers/script/ScriptEditStructuredToolHandler.js +6 -1
  21. package/src/handlers/script/ScriptRefactorRenameToolHandler.js +3 -1
  22. package/src/handlers/script/ScriptRefsFindToolHandler.js +22 -4
  23. package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +6 -1
  24. package/src/handlers/script/ScriptSymbolsGetToolHandler.js +1 -1
  25. package/src/lsp/CSharpLspUtils.js +11 -3
  26. package/src/lsp/LspProcessManager.js +24 -5
  27. package/src/lsp/LspRpcClient.js +115 -23
  28. package/src/lsp/LspRpcClientSingleton.js +79 -2
@@ -1,4 +1,5 @@
1
1
  import { LspRpcClient } from './LspRpcClient.js';
2
+ import { LspProcessManager } from './LspProcessManager.js';
2
3
  import { logger } from '../core/config.js';
3
4
 
4
5
  /**
@@ -8,6 +9,9 @@ import { logger } from '../core/config.js';
8
9
 
9
10
  let instance = null;
10
11
  let currentProjectRoot = null;
12
+ let validationInstance = null;
13
+ let validationProjectRoot = null;
14
+ const isolatedInstances = new Map();
11
15
  let heartbeatTimer = null;
12
16
 
13
17
  export class LspRpcClientSingleton {
@@ -33,6 +37,50 @@ export class LspRpcClientSingleton {
33
37
  return instance;
34
38
  }
35
39
 
40
+ /**
41
+ * Get or create an isolated LspRpcClient instance for validation.
42
+ * Uses a separate LSP process to avoid blocking on long-running requests.
43
+ * @param {string} projectRoot - Project root path
44
+ * @returns {Promise<LspRpcClient>} Isolated client instance
45
+ */
46
+ static async getValidationInstance(projectRoot) {
47
+ if (validationInstance && validationProjectRoot !== projectRoot) {
48
+ logger.info('[LspRpcClientSingleton] validation projectRoot changed, resetting instance');
49
+ await LspRpcClientSingleton.#resetValidation();
50
+ }
51
+
52
+ if (!validationInstance) {
53
+ const manager = new LspProcessManager({ shared: false });
54
+ validationInstance = new LspRpcClient(projectRoot, manager);
55
+ validationProjectRoot = projectRoot;
56
+ logger.info(`[LspRpcClientSingleton] created validation instance for ${projectRoot}`);
57
+ }
58
+
59
+ return validationInstance;
60
+ }
61
+
62
+ /**
63
+ * Get or create an isolated LspRpcClient instance for a specific purpose.
64
+ * Each kind is backed by its own LSP process to avoid cross-tool blocking.
65
+ * @param {string} projectRoot - Project root path
66
+ * @param {string} kind - Purpose key (e.g., "symbols", "rename")
67
+ * @returns {Promise<LspRpcClient>} Isolated client instance
68
+ */
69
+ static async getIsolatedInstance(projectRoot, kind) {
70
+ if (!kind) {
71
+ throw new Error('kind is required for isolated LSP instance');
72
+ }
73
+ const key = `${projectRoot}::${kind}`;
74
+ const existing = isolatedInstances.get(key);
75
+ if (existing) return existing;
76
+
77
+ const manager = new LspProcessManager({ shared: false });
78
+ const client = new LspRpcClient(projectRoot, manager);
79
+ isolatedInstances.set(key, client);
80
+ logger.info(`[LspRpcClientSingleton] created isolated instance (${kind}) for ${projectRoot}`);
81
+ return client;
82
+ }
83
+
36
84
  /**
37
85
  * Reset the singleton instance and stop the process.
38
86
  */
@@ -48,6 +96,35 @@ export class LspRpcClientSingleton {
48
96
  currentProjectRoot = null;
49
97
  logger.info('[LspRpcClientSingleton] instance reset');
50
98
  }
99
+ await LspRpcClientSingleton.#resetValidation();
100
+ await LspRpcClientSingleton.#resetIsolated();
101
+ }
102
+
103
+ static async #resetValidation() {
104
+ if (validationInstance) {
105
+ try {
106
+ await validationInstance.mgr.stop();
107
+ } catch (e) {
108
+ logger.warning(`[LspRpcClientSingleton] validation stop error: ${e.message}`);
109
+ }
110
+ validationInstance = null;
111
+ validationProjectRoot = null;
112
+ logger.info('[LspRpcClientSingleton] validation instance reset');
113
+ }
114
+ }
115
+
116
+ static async #resetIsolated() {
117
+ if (isolatedInstances.size === 0) return;
118
+ const entries = Array.from(isolatedInstances.entries());
119
+ isolatedInstances.clear();
120
+ for (const [key, client] of entries) {
121
+ try {
122
+ await client.mgr.stop();
123
+ } catch (e) {
124
+ logger.warning(`[LspRpcClientSingleton] isolated stop error (${key}): ${e.message}`);
125
+ }
126
+ }
127
+ logger.info('[LspRpcClientSingleton] isolated instances reset');
51
128
  }
52
129
 
53
130
  /**
@@ -66,8 +143,8 @@ export class LspRpcClientSingleton {
66
143
  return;
67
144
  }
68
145
  try {
69
- // Use workspace/symbol with empty query as a lightweight ping
70
- await instance.request('workspace/symbol', { query: '' });
146
+ // Lightweight ping to avoid heavy workspace scans
147
+ await instance.request('mcp/ping', {});
71
148
  } catch (e) {
72
149
  logger.warning(`[LspRpcClientSingleton] heartbeat failed: ${e.message}, resetting...`);
73
150
  // Process is dead, reset instance for next request