zapcode-figma-mcp 1.0.3 → 1.0.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.
Files changed (2) hide show
  1. package/build/index.js +70 -8
  2. package/package.json +3 -3
package/build/index.js CHANGED
@@ -24,6 +24,39 @@ function parseArgs() {
24
24
  }
25
25
  return { figmaPort };
26
26
  }
27
+ // --- Helper: Find Available Port ---
28
+ async function findAvailablePort(startPort, maxAttempts = 4) {
29
+ for (let i = 0; i < maxAttempts; i++) {
30
+ const port = startPort + i;
31
+ try {
32
+ const testServer = createHttpServer();
33
+ await new Promise((resolve, reject) => {
34
+ testServer.once('error', (err) => {
35
+ testServer.close();
36
+ if (err.code === 'EADDRINUSE') {
37
+ console.error(`Zapcode: Port ${port} is already in use, trying next port...`);
38
+ reject(err);
39
+ }
40
+ else {
41
+ reject(err);
42
+ }
43
+ });
44
+ testServer.listen(port, () => {
45
+ testServer.close();
46
+ resolve();
47
+ });
48
+ });
49
+ return port;
50
+ }
51
+ catch (err) {
52
+ if (err.code !== 'EADDRINUSE' || i === maxAttempts - 1) {
53
+ throw new Error(`No available ports in range ${startPort}-${startPort + maxAttempts - 1}`);
54
+ }
55
+ // Continue to next port
56
+ }
57
+ }
58
+ throw new Error('Unexpected error in port detection');
59
+ }
27
60
  // --- Socket.IO Server Logic ---
28
61
  function startSocketIOServer(port) {
29
62
  return new Promise((resolve, reject) => {
@@ -186,7 +219,10 @@ async function saveSvgAssets(assets, basePath) {
186
219
  async function main() {
187
220
  const { figmaPort } = parseArgs();
188
221
  try {
189
- await startSocketIOServer(figmaPort);
222
+ // Find an available port starting from the specified port
223
+ const availablePort = await findAvailablePort(figmaPort);
224
+ console.error(`Zapcode: ✅ Found available port ${availablePort}`);
225
+ await startSocketIOServer(availablePort);
190
226
  await startMcpServer();
191
227
  }
192
228
  catch (error) {
@@ -195,17 +231,43 @@ async function main() {
195
231
  }
196
232
  }
197
233
  // --- Graceful Shutdown ---
234
+ let isShuttingDown = false;
198
235
  async function shutdown() {
236
+ if (isShuttingDown) {
237
+ // Second Ctrl+C forces immediate exit
238
+ process.exit(0);
239
+ return;
240
+ }
241
+ isShuttingDown = true;
199
242
  console.error("\nZapcode: Gracefully shutting down...");
200
- if (figmaHttpServer) {
201
- figmaHttpServer.close(() => {
202
- console.error("Zapcode: Figma HTTP server closed.");
203
- process.exit(0);
204
- });
243
+ // Cleanup pending Figma context requests
244
+ figmaContextRequests.forEach((request) => {
245
+ request.reject(new Error("Server shutting down"));
246
+ });
247
+ figmaContextRequests.clear();
248
+ // Forcefully disconnect all Socket.IO clients
249
+ if (io) {
250
+ io.disconnectSockets(true);
205
251
  }
206
- else {
207
- process.exit(0);
252
+ if (connectedFigmaClient) {
253
+ connectedFigmaClient.disconnect(true);
254
+ connectedFigmaClient = null;
208
255
  }
256
+ // Force immediate shutdown - don't wait for callbacks
257
+ setImmediate(() => {
258
+ if (io) {
259
+ io.close();
260
+ }
261
+ if (figmaHttpServer) {
262
+ figmaHttpServer.close();
263
+ }
264
+ console.error("Zapcode: Server shutdown complete.");
265
+ process.exit(0);
266
+ });
267
+ // Safety timeout - exit after 500ms no matter what
268
+ setTimeout(() => {
269
+ process.exit(0);
270
+ }, 500);
209
271
  }
210
272
  process.on("SIGINT", shutdown);
211
273
  process.on("SIGTERM", shutdown);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zapcode-figma-mcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "An MCP server that exposes Figma context via a plugin and saves assets, from Zapcode.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
11
- "start": "node build/index.js",
11
+ "start": "node build/index.j npm publishs",
12
12
  "prepublishOnly": "npm run build"
13
13
  },
14
14
  "keywords": [
@@ -32,4 +32,4 @@
32
32
  "@types/node": "^20.12.12",
33
33
  "typescript": "^5.4.5"
34
34
  }
35
- }
35
+ }