@geometra/mcp 1.63.0 → 1.63.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.
@@ -18,16 +18,59 @@ function resolveSessionStateFile() {
18
18
  mkdirSync(dir, { recursive: true });
19
19
  return path.join(dir, `parallel-mcp-${process.pid}-${threadId}.sqlite`);
20
20
  }
21
- const orchestrator = new ParallelMcpOrchestrator(new SqliteParallelMcpStore({ filename: resolveSessionStateFile() }), { defaultLeaseMs: SESSION_LEASE_MS });
22
- const leaseSweep = setInterval(() => {
21
+ function isSessionLifecycleDisabled() {
22
+ const raw = process.env.GEOMETRA_MCP_DISABLE_SESSION_LIFECYCLE?.trim().toLowerCase();
23
+ return raw === '1' || raw === 'true' || raw === 'yes' || raw === 'on';
24
+ }
25
+ function formatSessionLifecycleInitError(error) {
26
+ if (error instanceof Error) {
27
+ if (error.code === 'ERR_DLOPEN_FAILED' &&
28
+ error.message.includes('better_sqlite3.node')) {
29
+ return `${error.message}. Rebuild the native module with \`npm rebuild better-sqlite3\` in the MCP package directory, or reinstall dependencies for the current Node.js version.`;
30
+ }
31
+ return error.message;
32
+ }
33
+ return String(error);
34
+ }
35
+ function createSessionLifecycleRegistry() {
36
+ if (isSessionLifecycleDisabled()) {
37
+ process.stderr.write('[geometra-mcp] durable session lifecycle disabled via GEOMETRA_MCP_DISABLE_SESSION_LIFECYCLE\n');
38
+ return {
39
+ available: false,
40
+ orchestrator: null,
41
+ close: () => { },
42
+ };
43
+ }
23
44
  try {
24
- orchestrator.expireLeases();
45
+ const orchestrator = new ParallelMcpOrchestrator(new SqliteParallelMcpStore({ filename: resolveSessionStateFile() }), { defaultLeaseMs: SESSION_LEASE_MS });
46
+ const leaseSweep = setInterval(() => {
47
+ try {
48
+ orchestrator.expireLeases();
49
+ }
50
+ catch {
51
+ /* ignore background lease sweep failures */
52
+ }
53
+ }, SESSION_SWEEP_MS);
54
+ leaseSweep.unref();
55
+ return {
56
+ available: true,
57
+ orchestrator,
58
+ close: () => {
59
+ clearInterval(leaseSweep);
60
+ orchestrator.close();
61
+ },
62
+ };
25
63
  }
26
- catch {
27
- /* ignore background lease sweep failures */
64
+ catch (error) {
65
+ process.stderr.write(`[geometra-mcp] durable session lifecycle disabled: ${formatSessionLifecycleInitError(error)}\n`);
66
+ return {
67
+ available: false,
68
+ orchestrator: null,
69
+ close: () => { },
70
+ };
28
71
  }
29
- }, SESSION_SWEEP_MS);
30
- leaseSweep.unref();
72
+ }
73
+ const lifecycleRegistry = createSessionLifecycleRegistry();
31
74
  function extractPageUrl(target) {
32
75
  const cached = target.cachedA11y?.meta?.pageUrl;
33
76
  if (typeof cached === 'string' && cached.length > 0)
@@ -86,6 +129,15 @@ function workerIdFor(sessionId) {
86
129
  return `${SESSION_WORKER_PREFIX}:${sessionId}`;
87
130
  }
88
131
  export function initializeSessionLifecycle(target, options) {
132
+ if (!lifecycleRegistry.available || !lifecycleRegistry.orchestrator) {
133
+ target.lifecycleFinalized = true;
134
+ target.lifecycleTaskId = undefined;
135
+ target.lifecycleTaskKind = undefined;
136
+ target.lifecycleLeaseId = undefined;
137
+ target.lifecycleWorkerId = undefined;
138
+ return;
139
+ }
140
+ const orchestrator = lifecycleRegistry.orchestrator;
89
141
  const sessionId = target.id;
90
142
  const taskId = liveTaskIdFor(sessionId);
91
143
  const taskKind = liveTaskKindFor(sessionId);
@@ -131,6 +183,9 @@ export function initializeSessionLifecycle(target, options) {
131
183
  target.lifecycleFinalized = false;
132
184
  }
133
185
  export function heartbeatSessionLifecycle(target) {
186
+ if (!lifecycleRegistry.orchestrator)
187
+ return;
188
+ const orchestrator = lifecycleRegistry.orchestrator;
134
189
  if (target.lifecycleFinalized || !target.lifecycleTaskId || !target.lifecycleLeaseId || !target.lifecycleWorkerId)
135
190
  return;
136
191
  orchestrator.heartbeatLease({
@@ -141,6 +196,9 @@ export function heartbeatSessionLifecycle(target) {
141
196
  });
142
197
  }
143
198
  export function recordSessionSnapshot(target, label, extra) {
199
+ if (!lifecycleRegistry.orchestrator)
200
+ return;
201
+ const orchestrator = lifecycleRegistry.orchestrator;
144
202
  if (!target.lifecycleTaskId)
145
203
  return;
146
204
  orchestrator.appendContextSnapshot({
@@ -152,6 +210,9 @@ export function recordSessionSnapshot(target, label, extra) {
152
210
  });
153
211
  }
154
212
  export function completeSessionLifecycle(target, reason, extra) {
213
+ if (!lifecycleRegistry.orchestrator)
214
+ return;
215
+ const orchestrator = lifecycleRegistry.orchestrator;
155
216
  if (target.lifecycleFinalized || !target.lifecycleTaskId || !target.lifecycleLeaseId || !target.lifecycleWorkerId)
156
217
  return;
157
218
  orchestrator.completeTask({
@@ -171,6 +232,9 @@ export function completeSessionLifecycle(target, reason, extra) {
171
232
  target.lifecycleFinalized = true;
172
233
  }
173
234
  export function failSessionLifecycle(target, error, extra) {
235
+ if (!lifecycleRegistry.orchestrator)
236
+ return;
237
+ const orchestrator = lifecycleRegistry.orchestrator;
174
238
  if (target.lifecycleFinalized || !target.lifecycleTaskId || !target.lifecycleLeaseId || !target.lifecycleWorkerId)
175
239
  return;
176
240
  recordSessionSnapshot(target, 'session.failed', {
@@ -187,6 +251,5 @@ export function failSessionLifecycle(target, error, extra) {
187
251
  target.lifecycleFinalized = true;
188
252
  }
189
253
  export function shutdownSessionLifecycleRegistry() {
190
- clearInterval(leaseSweep);
191
- orchestrator.close();
254
+ lifecycleRegistry.close();
192
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geometra/mcp",
3
- "version": "1.63.0",
3
+ "version": "1.63.2",
4
4
  "description": "MCP server for Geometra — interact with running Geometra apps via the geometry protocol, no browser needed",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,7 +32,7 @@
32
32
  "ui-testing"
33
33
  ],
34
34
  "dependencies": {
35
- "@geometra/proxy": "^1.63.0",
35
+ "@geometra/proxy": "^1.63.2",
36
36
  "@modelcontextprotocol/sdk": "^1.12.1",
37
37
  "@razroo/parallel-mcp": "^0.1.0",
38
38
  "ws": "^8.18.0",