@geometra/mcp 1.19.16 → 1.19.17
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/dist/proxy-spawn.d.ts +11 -0
- package/dist/proxy-spawn.js +46 -19
- package/dist/server.js +1 -1
- package/dist/session.d.ts +2 -0
- package/dist/session.js +104 -32
- package/package.json +2 -2
package/dist/proxy-spawn.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
export interface EmbeddedProxyRuntime {
|
|
3
|
+
wsUrl: string;
|
|
4
|
+
closed: boolean;
|
|
5
|
+
close: () => Promise<void>;
|
|
6
|
+
}
|
|
2
7
|
/** Resolve bundled @geometra/proxy CLI entry (dist/index.js). */
|
|
3
8
|
export declare function resolveProxyScriptPath(): string;
|
|
4
9
|
export declare function resolveProxyScriptPathWith(customRequire: NodeRequire, moduleDir?: string): string;
|
|
10
|
+
export declare function resolveProxyRuntimePath(): string;
|
|
11
|
+
export declare function resolveProxyRuntimePathWith(customRequire: NodeRequire, moduleDir?: string): string;
|
|
5
12
|
export interface SpawnProxyParams {
|
|
6
13
|
pageUrl: string;
|
|
7
14
|
port: number;
|
|
@@ -10,6 +17,10 @@ export interface SpawnProxyParams {
|
|
|
10
17
|
height?: number;
|
|
11
18
|
slowMo?: number;
|
|
12
19
|
}
|
|
20
|
+
export declare function startEmbeddedGeometraProxy(opts: SpawnProxyParams): Promise<{
|
|
21
|
+
runtime: EmbeddedProxyRuntime;
|
|
22
|
+
wsUrl: string;
|
|
23
|
+
}>;
|
|
13
24
|
export declare function parseProxyReadySignalLine(line: string): string | undefined;
|
|
14
25
|
export declare function formatProxyStartupFailure(message: string, opts: SpawnProxyParams): string;
|
|
15
26
|
/**
|
package/dist/proxy-spawn.js
CHANGED
|
@@ -2,7 +2,7 @@ import { spawn, spawnSync } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, realpathSync, rmSync } from 'node:fs';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
7
|
const READY_SIGNAL_TYPE = 'geometra-proxy-ready';
|
|
8
8
|
const READY_TIMEOUT_MS = 45_000;
|
|
@@ -12,21 +12,30 @@ export function resolveProxyScriptPath() {
|
|
|
12
12
|
return resolveProxyScriptPathWith(require);
|
|
13
13
|
}
|
|
14
14
|
export function resolveProxyScriptPathWith(customRequire, moduleDir = MODULE_DIR) {
|
|
15
|
+
return resolveProxyDistPathWith(customRequire, moduleDir, 'index.js');
|
|
16
|
+
}
|
|
17
|
+
export function resolveProxyRuntimePath() {
|
|
18
|
+
return resolveProxyRuntimePathWith(require);
|
|
19
|
+
}
|
|
20
|
+
export function resolveProxyRuntimePathWith(customRequire, moduleDir = MODULE_DIR) {
|
|
21
|
+
return resolveProxyDistPathWith(customRequire, moduleDir, 'runtime.js');
|
|
22
|
+
}
|
|
23
|
+
function resolveProxyDistPathWith(customRequire, moduleDir, entryFile) {
|
|
15
24
|
const errors = [];
|
|
16
|
-
const workspaceDist = path.resolve(moduleDir,
|
|
25
|
+
const workspaceDist = path.resolve(moduleDir, `../../packages/proxy/dist/${entryFile}`);
|
|
17
26
|
const bundledDependencyDir = path.resolve(moduleDir, '../node_modules/@geometra/proxy');
|
|
18
27
|
const packageDir = resolveProxyPackageDir(customRequire);
|
|
19
28
|
if (packageDir) {
|
|
20
29
|
if (shouldPreferWorkspaceDist(packageDir, bundledDependencyDir) && existsSync(workspaceDist)) {
|
|
21
30
|
return workspaceDist;
|
|
22
31
|
}
|
|
23
|
-
const packagedDist = path.join(packageDir, 'dist
|
|
32
|
+
const packagedDist = path.join(packageDir, 'dist', entryFile);
|
|
24
33
|
if (existsSync(packagedDist))
|
|
25
34
|
return packagedDist;
|
|
26
|
-
const builtLocalDist = buildLocalProxyDistIfPossible(packageDir, errors);
|
|
35
|
+
const builtLocalDist = buildLocalProxyDistIfPossible(packageDir, entryFile, errors);
|
|
27
36
|
if (builtLocalDist)
|
|
28
37
|
return builtLocalDist;
|
|
29
|
-
errors.push(`Resolved @geometra/proxy package at ${packageDir}, but dist
|
|
38
|
+
errors.push(`Resolved @geometra/proxy package at ${packageDir}, but dist/${entryFile} was missing`);
|
|
30
39
|
}
|
|
31
40
|
else {
|
|
32
41
|
errors.push('Could not find @geometra/proxy/package.json via Node module search paths');
|
|
@@ -34,24 +43,26 @@ export function resolveProxyScriptPathWith(customRequire, moduleDir = MODULE_DIR
|
|
|
34
43
|
try {
|
|
35
44
|
const pkgJson = customRequire.resolve('@geometra/proxy/package.json');
|
|
36
45
|
const exportPackageDir = path.dirname(pkgJson);
|
|
37
|
-
const packagedDist = path.join(exportPackageDir, 'dist
|
|
46
|
+
const packagedDist = path.join(exportPackageDir, 'dist', entryFile);
|
|
38
47
|
if (existsSync(packagedDist))
|
|
39
48
|
return packagedDist;
|
|
40
|
-
const builtLocalDist = buildLocalProxyDistIfPossible(exportPackageDir, errors);
|
|
49
|
+
const builtLocalDist = buildLocalProxyDistIfPossible(exportPackageDir, entryFile, errors);
|
|
41
50
|
if (builtLocalDist)
|
|
42
51
|
return builtLocalDist;
|
|
43
|
-
errors.push(`Resolved @geometra/proxy/package.json at ${pkgJson}, but dist
|
|
52
|
+
errors.push(`Resolved @geometra/proxy/package.json at ${pkgJson}, but dist/${entryFile} was missing`);
|
|
44
53
|
}
|
|
45
54
|
catch (err) {
|
|
46
55
|
errors.push(err instanceof Error ? err.message : String(err));
|
|
47
56
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
if (entryFile === 'index.js') {
|
|
58
|
+
try {
|
|
59
|
+
return customRequire.resolve('@geometra/proxy');
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
63
|
+
}
|
|
53
64
|
}
|
|
54
|
-
const packagedSiblingDist = path.resolve(moduleDir,
|
|
65
|
+
const packagedSiblingDist = path.resolve(moduleDir, `../../proxy/dist/${entryFile}`);
|
|
55
66
|
if (existsSync(packagedSiblingDist)) {
|
|
56
67
|
return packagedSiblingDist;
|
|
57
68
|
}
|
|
@@ -60,7 +71,7 @@ export function resolveProxyScriptPathWith(customRequire, moduleDir = MODULE_DIR
|
|
|
60
71
|
return workspaceDist;
|
|
61
72
|
}
|
|
62
73
|
errors.push(`Workspace fallback not found at ${workspaceDist}`);
|
|
63
|
-
throw new Error(`Could not resolve @geometra/proxy. Install it with the MCP package: npm install @geometra/proxy. Resolution errors: ${errors.join(' | ')}`);
|
|
74
|
+
throw new Error(`Could not resolve @geometra/proxy dist/${entryFile}. Install it with the MCP package: npm install @geometra/proxy. Resolution errors: ${errors.join(' | ')}`);
|
|
64
75
|
}
|
|
65
76
|
function resolveProxyPackageDir(customRequire) {
|
|
66
77
|
const searchRoots = customRequire.resolve.paths('@geometra/proxy') ?? [];
|
|
@@ -79,8 +90,8 @@ function shouldPreferWorkspaceDist(packageDir, bundledDependencyDir) {
|
|
|
79
90
|
return false;
|
|
80
91
|
}
|
|
81
92
|
}
|
|
82
|
-
function buildLocalProxyDistIfPossible(packageDir, errors) {
|
|
83
|
-
const distEntry = path.join(packageDir, 'dist
|
|
93
|
+
function buildLocalProxyDistIfPossible(packageDir, entryFile, errors) {
|
|
94
|
+
const distEntry = path.join(packageDir, 'dist', entryFile);
|
|
84
95
|
const sourceEntry = path.join(packageDir, 'src/index.ts');
|
|
85
96
|
const tsconfigPath = path.join(packageDir, 'tsconfig.build.json');
|
|
86
97
|
if (!existsSync(sourceEntry) || !existsSync(tsconfigPath)) {
|
|
@@ -104,16 +115,32 @@ function buildLocalProxyDistIfPossible(packageDir, errors) {
|
|
|
104
115
|
}
|
|
105
116
|
if (existsSync(distEntry))
|
|
106
117
|
return distEntry;
|
|
107
|
-
const realDistEntry = path.join(realPackageDir, 'dist
|
|
118
|
+
const realDistEntry = path.join(realPackageDir, 'dist', entryFile);
|
|
108
119
|
if (existsSync(realDistEntry))
|
|
109
120
|
return realDistEntry;
|
|
110
|
-
errors.push(`Built local @geometra/proxy at ${realPackageDir}, but dist
|
|
121
|
+
errors.push(`Built local @geometra/proxy at ${realPackageDir}, but dist/${entryFile} is still missing`);
|
|
111
122
|
}
|
|
112
123
|
catch (err) {
|
|
113
124
|
errors.push(err instanceof Error ? err.message : String(err));
|
|
114
125
|
}
|
|
115
126
|
return undefined;
|
|
116
127
|
}
|
|
128
|
+
export async function startEmbeddedGeometraProxy(opts) {
|
|
129
|
+
const runtimePath = resolveProxyRuntimePath();
|
|
130
|
+
const runtimeModule = await import(pathToFileURL(runtimePath).href);
|
|
131
|
+
if (typeof runtimeModule.launchProxyRuntime !== 'function') {
|
|
132
|
+
throw new Error(`Resolved ${runtimePath}, but it did not export launchProxyRuntime()`);
|
|
133
|
+
}
|
|
134
|
+
const runtime = await runtimeModule.launchProxyRuntime({
|
|
135
|
+
url: opts.pageUrl,
|
|
136
|
+
port: opts.port,
|
|
137
|
+
width: opts.width,
|
|
138
|
+
height: opts.height,
|
|
139
|
+
headed: opts.headless !== true,
|
|
140
|
+
slowMo: opts.slowMo,
|
|
141
|
+
});
|
|
142
|
+
return { runtime, wsUrl: runtime.wsUrl };
|
|
143
|
+
}
|
|
117
144
|
export function parseProxyReadySignalLine(line) {
|
|
118
145
|
const trimmed = line.trim();
|
|
119
146
|
if (!trimmed)
|
package/dist/server.js
CHANGED
|
@@ -175,7 +175,7 @@ const batchActionSchema = z.discriminatedUnion('type', [
|
|
|
175
175
|
}),
|
|
176
176
|
]);
|
|
177
177
|
export function createServer() {
|
|
178
|
-
const server = new McpServer({ name: 'geometra', version: '1.19.
|
|
178
|
+
const server = new McpServer({ name: 'geometra', version: '1.19.17' }, { capabilities: { tools: {} } });
|
|
179
179
|
// ── connect ──────────────────────────────────────────────────
|
|
180
180
|
server.tool('geometra_connect', `Connect to a Geometra WebSocket peer, or start \`geometra-proxy\` automatically for a normal web page.
|
|
181
181
|
|
package/dist/session.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ChildProcess } from 'node:child_process';
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
|
+
import { type EmbeddedProxyRuntime } from './proxy-spawn.js';
|
|
3
4
|
/**
|
|
4
5
|
* Parsed accessibility node from the UI tree + computed layout.
|
|
5
6
|
* Mirrors the shape of @geometra/core's AccessibilityNode without importing it
|
|
@@ -325,6 +326,7 @@ export interface Session {
|
|
|
325
326
|
updateRevision: number;
|
|
326
327
|
/** Present when this session owns a child geometra-proxy process (pageUrl connect). */
|
|
327
328
|
proxyChild?: ChildProcess;
|
|
329
|
+
proxyRuntime?: EmbeddedProxyRuntime;
|
|
328
330
|
proxyReusable?: boolean;
|
|
329
331
|
cachedA11y?: A11yNode | null;
|
|
330
332
|
cachedA11yRevision?: number;
|
package/dist/session.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import WebSocket from 'ws';
|
|
2
|
-
import { spawnGeometraProxy } from './proxy-spawn.js';
|
|
2
|
+
import { spawnGeometraProxy, startEmbeddedGeometraProxy } from './proxy-spawn.js';
|
|
3
3
|
let activeSession = null;
|
|
4
4
|
let reusableProxy = null;
|
|
5
5
|
const ACTION_UPDATE_TIMEOUT_MS = 2000;
|
|
@@ -19,14 +19,42 @@ function invalidateSessionCaches(session) {
|
|
|
19
19
|
session.cachedFormSchemas?.clear();
|
|
20
20
|
}
|
|
21
21
|
function clearReusableProxyIfExited() {
|
|
22
|
-
if (!reusableProxy
|
|
22
|
+
if (!reusableProxy)
|
|
23
|
+
return;
|
|
24
|
+
if (reusableProxy.child) {
|
|
25
|
+
if (!reusableProxy.child.killed && reusableProxy.child.exitCode === null && reusableProxy.child.signalCode === null) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
reusableProxy = null;
|
|
23
29
|
return;
|
|
24
30
|
}
|
|
31
|
+
if (!reusableProxy.runtime.closed)
|
|
32
|
+
return;
|
|
25
33
|
reusableProxy = null;
|
|
26
34
|
}
|
|
27
|
-
function setReusableProxy(
|
|
35
|
+
function setReusableProxy(proxy, wsUrl, opts) {
|
|
36
|
+
if ('child' in proxy) {
|
|
37
|
+
const child = proxy.child;
|
|
38
|
+
reusableProxy = {
|
|
39
|
+
child,
|
|
40
|
+
wsUrl,
|
|
41
|
+
headless: opts.headless === true,
|
|
42
|
+
slowMo: opts.slowMo ?? 0,
|
|
43
|
+
width: opts.width ?? 1280,
|
|
44
|
+
height: opts.height ?? 720,
|
|
45
|
+
pageUrl: opts.pageUrl,
|
|
46
|
+
};
|
|
47
|
+
const clear = () => {
|
|
48
|
+
if (reusableProxy?.child === child)
|
|
49
|
+
reusableProxy = null;
|
|
50
|
+
};
|
|
51
|
+
child.once('exit', clear);
|
|
52
|
+
child.once('close', clear);
|
|
53
|
+
child.once('error', clear);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
28
56
|
reusableProxy = {
|
|
29
|
-
|
|
57
|
+
runtime: proxy.runtime,
|
|
30
58
|
wsUrl,
|
|
31
59
|
headless: opts.headless === true,
|
|
32
60
|
slowMo: opts.slowMo ?? 0,
|
|
@@ -34,13 +62,6 @@ function setReusableProxy(child, wsUrl, opts) {
|
|
|
34
62
|
height: opts.height ?? 720,
|
|
35
63
|
pageUrl: opts.pageUrl,
|
|
36
64
|
};
|
|
37
|
-
const clear = () => {
|
|
38
|
-
if (reusableProxy?.child === child)
|
|
39
|
-
reusableProxy = null;
|
|
40
|
-
};
|
|
41
|
-
child.once('exit', clear);
|
|
42
|
-
child.once('close', clear);
|
|
43
|
-
child.once('error', clear);
|
|
44
65
|
}
|
|
45
66
|
function closeReusableProxy() {
|
|
46
67
|
clearReusableProxyIfExited();
|
|
@@ -48,12 +69,16 @@ function closeReusableProxy() {
|
|
|
48
69
|
reusableProxy = null;
|
|
49
70
|
if (!proxy)
|
|
50
71
|
return;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
if (proxy.child) {
|
|
73
|
+
try {
|
|
74
|
+
proxy.child.kill('SIGTERM');
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* ignore */
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
56
80
|
}
|
|
81
|
+
void proxy.runtime.close().catch(() => { });
|
|
57
82
|
}
|
|
58
83
|
function rememberReusableProxyPageUrl(session) {
|
|
59
84
|
const pageUrl = session.cachedA11y?.meta?.pageUrl;
|
|
@@ -61,6 +86,10 @@ function rememberReusableProxyPageUrl(session) {
|
|
|
61
86
|
return;
|
|
62
87
|
if (session.proxyChild && reusableProxy?.child === session.proxyChild) {
|
|
63
88
|
reusableProxy.pageUrl = pageUrl;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (session.proxyRuntime && reusableProxy?.runtime === session.proxyRuntime) {
|
|
92
|
+
reusableProxy.pageUrl = pageUrl;
|
|
64
93
|
}
|
|
65
94
|
}
|
|
66
95
|
function shutdownPreviousSession(opts) {
|
|
@@ -87,6 +116,16 @@ function shutdownPreviousSession(opts) {
|
|
|
87
116
|
catch {
|
|
88
117
|
/* ignore */
|
|
89
118
|
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (prev.proxyRuntime) {
|
|
122
|
+
const shouldKeepProxy = prev.proxyReusable && opts?.closeProxy === false;
|
|
123
|
+
rememberReusableProxyPageUrl(prev);
|
|
124
|
+
if (shouldKeepProxy)
|
|
125
|
+
return;
|
|
126
|
+
if (reusableProxy?.runtime === prev.proxyRuntime)
|
|
127
|
+
reusableProxy = null;
|
|
128
|
+
void prev.proxyRuntime.close().catch(() => { });
|
|
90
129
|
}
|
|
91
130
|
}
|
|
92
131
|
/**
|
|
@@ -173,6 +212,9 @@ export function connect(url, opts) {
|
|
|
173
212
|
/* ignore */
|
|
174
213
|
}
|
|
175
214
|
}
|
|
215
|
+
if (session.proxyRuntime && !session.proxyReusable) {
|
|
216
|
+
void session.proxyRuntime.close().catch(() => { });
|
|
217
|
+
}
|
|
176
218
|
}
|
|
177
219
|
if (!resolved) {
|
|
178
220
|
resolved = true;
|
|
@@ -193,7 +235,8 @@ export async function connectThroughProxy(options) {
|
|
|
193
235
|
if (reusableProxy &&
|
|
194
236
|
reusableProxy.headless === desiredHeadless &&
|
|
195
237
|
reusableProxy.slowMo === desiredSlowMo) {
|
|
196
|
-
const session = activeSession?.proxyChild === reusableProxy.child
|
|
238
|
+
const session = ((reusableProxy.child && activeSession?.proxyChild === reusableProxy.child) ||
|
|
239
|
+
(reusableProxy.runtime && activeSession?.proxyRuntime === reusableProxy.runtime))
|
|
197
240
|
? activeSession
|
|
198
241
|
: await connect(reusableProxy.wsUrl, {
|
|
199
242
|
skipInitialResize: true,
|
|
@@ -204,6 +247,7 @@ export async function connectThroughProxy(options) {
|
|
|
204
247
|
throw new Error('Failed to attach to reusable proxy session');
|
|
205
248
|
}
|
|
206
249
|
session.proxyChild = reusableProxy.child;
|
|
250
|
+
session.proxyRuntime = reusableProxy.runtime;
|
|
207
251
|
session.proxyReusable = true;
|
|
208
252
|
const desiredWidth = options.width ?? reusableProxy.width;
|
|
209
253
|
const desiredHeight = options.height ?? reusableProxy.height;
|
|
@@ -220,7 +264,8 @@ export async function connectThroughProxy(options) {
|
|
|
220
264
|
const currentUrl = session.cachedA11y?.meta?.pageUrl ?? reusableProxy.pageUrl;
|
|
221
265
|
if (currentUrl !== options.pageUrl) {
|
|
222
266
|
await sendNavigate(session, options.pageUrl, 15_000);
|
|
223
|
-
if (reusableProxy?.child === session.proxyChild)
|
|
267
|
+
if ((session.proxyChild && reusableProxy?.child === session.proxyChild) ||
|
|
268
|
+
(session.proxyRuntime && reusableProxy?.runtime === session.proxyRuntime)) {
|
|
224
269
|
reusableProxy.pageUrl = options.pageUrl;
|
|
225
270
|
}
|
|
226
271
|
}
|
|
@@ -228,23 +273,23 @@ export async function connectThroughProxy(options) {
|
|
|
228
273
|
return session;
|
|
229
274
|
}
|
|
230
275
|
closeReusableProxy();
|
|
231
|
-
const { child, wsUrl } = await spawnGeometraProxy({
|
|
232
|
-
pageUrl: options.pageUrl,
|
|
233
|
-
port: options.port ?? 0,
|
|
234
|
-
headless: options.headless,
|
|
235
|
-
width: options.width,
|
|
236
|
-
height: options.height,
|
|
237
|
-
slowMo: options.slowMo,
|
|
238
|
-
});
|
|
239
276
|
try {
|
|
277
|
+
const { runtime, wsUrl } = await startEmbeddedGeometraProxy({
|
|
278
|
+
pageUrl: options.pageUrl,
|
|
279
|
+
port: options.port ?? 0,
|
|
280
|
+
headless: options.headless,
|
|
281
|
+
width: options.width,
|
|
282
|
+
height: options.height,
|
|
283
|
+
slowMo: options.slowMo,
|
|
284
|
+
});
|
|
240
285
|
const session = await connect(wsUrl, {
|
|
241
286
|
skipInitialResize: true,
|
|
242
287
|
closePreviousProxy: false,
|
|
243
288
|
awaitInitialFrame: options.awaitInitialFrame,
|
|
244
289
|
});
|
|
245
|
-
session.
|
|
290
|
+
session.proxyRuntime = runtime;
|
|
246
291
|
session.proxyReusable = true;
|
|
247
|
-
setReusableProxy(
|
|
292
|
+
setReusableProxy({ runtime }, wsUrl, {
|
|
248
293
|
headless: options.headless,
|
|
249
294
|
slowMo: options.slowMo,
|
|
250
295
|
width: options.width,
|
|
@@ -254,13 +299,40 @@ export async function connectThroughProxy(options) {
|
|
|
254
299
|
return session;
|
|
255
300
|
}
|
|
256
301
|
catch (e) {
|
|
302
|
+
const { child, wsUrl } = await spawnGeometraProxy({
|
|
303
|
+
pageUrl: options.pageUrl,
|
|
304
|
+
port: options.port ?? 0,
|
|
305
|
+
headless: options.headless,
|
|
306
|
+
width: options.width,
|
|
307
|
+
height: options.height,
|
|
308
|
+
slowMo: options.slowMo,
|
|
309
|
+
});
|
|
257
310
|
try {
|
|
258
|
-
|
|
311
|
+
const session = await connect(wsUrl, {
|
|
312
|
+
skipInitialResize: true,
|
|
313
|
+
closePreviousProxy: false,
|
|
314
|
+
awaitInitialFrame: options.awaitInitialFrame,
|
|
315
|
+
});
|
|
316
|
+
session.proxyChild = child;
|
|
317
|
+
session.proxyReusable = true;
|
|
318
|
+
setReusableProxy({ child }, wsUrl, {
|
|
319
|
+
headless: options.headless,
|
|
320
|
+
slowMo: options.slowMo,
|
|
321
|
+
width: options.width,
|
|
322
|
+
height: options.height,
|
|
323
|
+
pageUrl: options.pageUrl,
|
|
324
|
+
});
|
|
325
|
+
return session;
|
|
259
326
|
}
|
|
260
|
-
catch {
|
|
261
|
-
|
|
327
|
+
catch (fallbackError) {
|
|
328
|
+
try {
|
|
329
|
+
child.kill('SIGTERM');
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
/* ignore */
|
|
333
|
+
}
|
|
334
|
+
throw fallbackError instanceof Error ? fallbackError : e;
|
|
262
335
|
}
|
|
263
|
-
throw e;
|
|
264
336
|
}
|
|
265
337
|
}
|
|
266
338
|
export function getSession() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geometra/mcp",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.17",
|
|
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",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"ui-testing"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@geometra/proxy": "^1.19.
|
|
33
|
+
"@geometra/proxy": "^1.19.17",
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
35
35
|
"ws": "^8.18.0",
|
|
36
36
|
"zod": "^3.23.0"
|