@akiojin/unity-mcp-server 2.42.2 → 2.42.4

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.
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Bootstrap wrapper for unity-mcp-server
4
+ *
5
+ * This wrapper ensures:
6
+ * 1. Early stderr output before any module loading
7
+ * 2. Global exception handlers are registered first
8
+ * 3. Module load failures are caught and reported
9
+ *
10
+ * ESM static imports are hoisted, so we use dynamic import() to
11
+ * ensure our error handlers are set up before loading the main module.
12
+ */
13
+
14
+ // Synchronous stderr write - this MUST appear before any module loading
15
+ process.stderr.write('[unity-mcp-server] Bootstrap starting...\n');
16
+
17
+ // Global exception handlers - catch any unhandled errors
18
+ process.on('uncaughtException', err => {
19
+ process.stderr.write(`[unity-mcp-server] FATAL: Uncaught exception: ${err.message}\n`);
20
+ process.stderr.write(`${err.stack}\n`);
21
+ process.exit(1);
22
+ });
23
+
24
+ process.on('unhandledRejection', (reason, _promise) => {
25
+ const msg = reason instanceof Error ? reason.message : String(reason);
26
+ const stack = reason instanceof Error ? reason.stack : '';
27
+ process.stderr.write(`[unity-mcp-server] FATAL: Unhandled rejection: ${msg}\n`);
28
+ if (stack) process.stderr.write(`${stack}\n`);
29
+ process.exit(1);
30
+ });
31
+
32
+ // Dynamic import to load the main module AFTER error handlers are set up
33
+ // This allows us to catch module load failures
34
+ import('./unity-mcp-server').catch(err => {
35
+ process.stderr.write(`[unity-mcp-server] FATAL: Module load failed: ${err.message}\n`);
36
+ process.stderr.write(`${err.stack}\n`);
37
+ process.exit(1);
38
+ });
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@akiojin/unity-mcp-server",
3
- "version": "2.42.2",
3
+ "version": "2.42.4",
4
4
  "description": "MCP server and Unity Editor bridge — enables AI assistants to control Unity for AI-assisted workflows",
5
5
  "type": "module",
6
6
  "main": "src/core/server.js",
7
7
  "bin": {
8
- "unity-mcp-server": "./bin/unity-mcp-server"
8
+ "unity-mcp-server": "./bin/bootstrap.js"
9
9
  },
10
10
  "scripts": {
11
11
  "start": "node src/core/server.js",
@@ -29,7 +29,7 @@
29
29
  "prebuild:better-sqlite3": "node scripts/prebuild-better-sqlite3.mjs",
30
30
  "prebuilt:manifest": "node scripts/generate-prebuilt-manifest.mjs",
31
31
  "prepublishOnly": "npm run test:ci && npm run prebuilt:manifest",
32
- "postinstall": "node scripts/ensure-better-sqlite3.mjs && chmod +x bin/unity-mcp-server || true",
32
+ "postinstall": "node scripts/ensure-better-sqlite3.mjs && chmod +x bin/bootstrap.js bin/unity-mcp-server || true",
33
33
  "test:ci:unity": "timeout 60 node --test tests/unit/core/codeIndex.test.js tests/unit/core/config.test.js tests/unit/core/indexWatcher.test.js tests/unit/core/projectInfo.test.js tests/unit/core/server.test.js || exit 0",
34
34
  "test:unity": "node tests/run-unity-integration.mjs",
35
35
  "test:nounity": "npm run test:integration",
@@ -1,6 +1,10 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import * as findUpPkg from 'find-up';
4
+
5
+ // Diagnostic log: confirm module loading reached this point
6
+ process.stderr.write('[unity-mcp-server] Config module loading...\n');
7
+
4
8
  function findUpSyncCompat(matcher, options = {}) {
5
9
  if (typeof matcher === 'function') {
6
10
  let dir = options.cwd || process.cwd();
@@ -21,6 +21,7 @@ export class UnityConnection extends EventEmitter {
21
21
  this.sendQueue = [];
22
22
  this.inFlight = 0;
23
23
  this.maxInFlight = 1; // process one command at a time by default
24
+ this.connectedAt = null; // Timestamp when connection was established
24
25
  }
25
26
 
26
27
  /**
@@ -77,8 +78,11 @@ export class UnityConnection extends EventEmitter {
77
78
 
78
79
  // Set up event handlers
79
80
  this.socket.on('connect', () => {
80
- console.error(`[unity-mcp-server] Unity TCP connected successfully`);
81
- logger.info('Connected to Unity Editor');
81
+ this.connectedAt = Date.now();
82
+ console.error(
83
+ `[unity-mcp-server] Unity TCP connected to ${targetHost}:${config.unity.port}`
84
+ );
85
+ logger.info(`Connected to Unity Editor at ${targetHost}:${config.unity.port}`);
82
86
  this.connected = true;
83
87
  this.reconnectAttempts = 0;
84
88
  this.connectPromise = null;
@@ -88,6 +92,12 @@ export class UnityConnection extends EventEmitter {
88
92
  });
89
93
 
90
94
  this.socket.on('end', () => {
95
+ // Unity closed the connection (FIN received)
96
+ const duration = this.connectedAt ? Date.now() - this.connectedAt : 0;
97
+ console.error(
98
+ `[unity-mcp-server] Unity TCP connection ended by remote (FIN received, duration: ${duration}ms)`
99
+ );
100
+ logger.info(`Unity closed connection (FIN received) after ${duration}ms`);
91
101
  // Treat end as close to trigger reconnection
92
102
  this.socket.destroy();
93
103
  });
@@ -130,9 +140,11 @@ export class UnityConnection extends EventEmitter {
130
140
  return;
131
141
  }
132
142
 
133
- console.error(`[unity-mcp-server] Unity TCP disconnected`);
134
- logger.info('Disconnected from Unity Editor');
143
+ const duration = this.connectedAt ? Date.now() - this.connectedAt : 0;
144
+ console.error(`[unity-mcp-server] Unity TCP disconnected (duration: ${duration}ms)`);
145
+ logger.info(`Disconnected from Unity Editor after ${duration}ms`);
135
146
  this.connected = false;
147
+ this.connectedAt = null;
136
148
  this.socket = null;
137
149
 
138
150
  // Clear message buffer
@@ -231,6 +243,9 @@ export class UnityConnection extends EventEmitter {
231
243
  * @param {Buffer} data
232
244
  */
233
245
  handleData(data) {
246
+ // Log received data size for debugging connection issues
247
+ console.error(`[unity-mcp-server] Received ${data.length} bytes from Unity`);
248
+
234
249
  // Fast-path: accept single unframed JSON message (NDJSON style) from tests/clients
235
250
  if (!this.messageBuffer.length) {
236
251
  const asString = data.toString('utf8').trim();