@geometra/mcp 1.65.6 → 1.65.8

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,16 @@
1
+ /**
2
+ * Custom listbox actions can legitimately spend several seconds opening,
3
+ * filtering, selecting, and verifying a reactive control. Keep the MCP
4
+ * listener alive after the proxy's start deadline so extraction and the
5
+ * correlated terminal acknowledgement cannot lose a race at the boundary.
6
+ */
7
+ export declare const LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS = 15000;
8
+ export declare const LISTBOX_ACK_GRACE_MS = 3000;
9
+ /**
10
+ * Semantic text fills can cross several Playwright operations before the
11
+ * proxy can acknowledge them, especially when a caller enables slowMo for a
12
+ * live form. Keep the correlated listener alive without extending the
13
+ * browser-side start deadline to the same boundary.
14
+ */
15
+ export declare const TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS = 15000;
16
+ export declare const TEXT_FIELD_ACK_GRACE_MS = 3000;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Custom listbox actions can legitimately spend several seconds opening,
3
+ * filtering, selecting, and verifying a reactive control. Keep the MCP
4
+ * listener alive after the proxy's start deadline so extraction and the
5
+ * correlated terminal acknowledgement cannot lose a race at the boundary.
6
+ */
7
+ export const LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS = 15_000;
8
+ export const LISTBOX_ACK_GRACE_MS = 3_000;
9
+ /**
10
+ * Semantic text fills can cross several Playwright operations before the
11
+ * proxy can acknowledge them, especially when a caller enables slowMo for a
12
+ * live form. Keep the correlated listener alive without extending the
13
+ * browser-side start deadline to the same boundary.
14
+ */
15
+ export const TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS = 15_000;
16
+ export const TEXT_FIELD_ACK_GRACE_MS = 3_000;
package/dist/server.js CHANGED
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { performance } from 'node:perf_hooks';
3
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
4
  import { z } from 'zod';
5
+ import { LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS, TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS, } from './action-timeouts.js';
5
6
  import { formatConnectFailureMessage, isHttpUrl, normalizeConnectTarget } from './connect-utils.js';
6
7
  import { REDACTED_STATE_URL, sanitizeUrlToOrigin } from './state-privacy.js';
7
8
  import { SERVER_IMPLEMENTATION } from './version.js';
@@ -248,7 +249,12 @@ function timeoutCapFromDeadline(deadlineAt, reserveMs = HOST_SAFE_TIMEOUT_RESERV
248
249
  function capTimeoutMs(timeoutMs, capMs, fallbackMs) {
249
250
  return Math.max(MIN_ACTION_TIMEOUT_MS, Math.min(timeoutMs ?? fallbackMs, Math.max(MIN_ACTION_TIMEOUT_MS, Math.floor(capMs))));
250
251
  }
251
- function capFillFieldTimeout(field, capMs, fallbackMs = 5_000) {
252
+ function capFillFieldTimeout(field, capMs) {
253
+ const fallbackMs = field.kind === 'text'
254
+ ? TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS
255
+ : field.kind === 'file'
256
+ ? 8_000
257
+ : 5_000;
252
258
  return {
253
259
  ...field,
254
260
  timeoutMs: capTimeoutMs(field.timeoutMs, capMs, fallbackMs),
@@ -272,7 +278,7 @@ function capBatchActionTimeouts(action, capMs) {
272
278
  case 'upload_files':
273
279
  return { ...action, timeoutMs: capTimeoutMs(action.timeoutMs, capMs, 8_000) };
274
280
  case 'pick_listbox_option':
275
- return { ...action, timeoutMs: capTimeoutMs(action.timeoutMs, capMs, 4_500) };
281
+ return { ...action, timeoutMs: capTimeoutMs(action.timeoutMs, capMs, LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS) };
276
282
  case 'wait_for':
277
283
  return { ...action, timeoutMs: capTimeoutMs(action.timeoutMs, capMs, 10_000) };
278
284
  case 'fill_fields':
@@ -2825,7 +2831,7 @@ fieldLabel is required so Geometra can confirm which control committed the selec
2825
2831
  fieldKey,
2826
2832
  fieldLabel,
2827
2833
  query,
2828
- }, timeoutMs);
2834
+ }, timeoutMs ?? LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS);
2829
2835
  const summary = postActionSummary(session, before, wait, detail);
2830
2836
  const fieldSummary = fieldLabel ? summarizeFieldLabelState(session, fieldLabel, fieldKey) : undefined;
2831
2837
  const summaryText = [
package/dist/session.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
2
  import { performance } from 'node:perf_hooks';
3
3
  import WebSocket from 'ws';
4
+ import { LISTBOX_ACK_GRACE_MS, LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS, TEXT_FIELD_ACK_GRACE_MS, TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS, } from './action-timeouts.js';
4
5
  import { resolveStealthMode, spawnGeometraProxy, startEmbeddedGeometraProxy, } from './proxy-spawn.js';
5
6
  import { completeSessionLifecycle, failSessionLifecycle, heartbeatSessionLifecycle, initializeSessionLifecycle, recordSessionSnapshot, } from './session-state.js';
6
7
  import { REDACTED_STATE_URL, sanitizeUrlToOrigin } from './state-privacy.js';
@@ -38,7 +39,8 @@ let idleProxyTimer = null;
38
39
  const trackedReusableProxyChildren = new WeakSet();
39
40
  const embeddedProxyClosePromises = new WeakMap();
40
41
  const ACTION_UPDATE_TIMEOUT_MS = 2000;
41
- const LISTBOX_UPDATE_TIMEOUT_MS = 4500;
42
+ const MIN_PROXY_ACTION_TIMEOUT_MS = 50;
43
+ const FIELD_CHOICE_UPDATE_TIMEOUT_MS = 4500;
42
44
  const FILL_BATCH_BASE_TIMEOUT_MS = 2500;
43
45
  const FILL_BATCH_TEXT_FIELD_TIMEOUT_MS = 275;
44
46
  const FILL_BATCH_TEXT_LENGTH_TIMEOUT_MS = 120;
@@ -241,6 +243,12 @@ function actionTimeoutFor(session, message, timeoutMs) {
241
243
  !isMutatingProxyAction(message)) {
242
244
  return undefined;
243
245
  }
246
+ if (message.type === 'listboxPick') {
247
+ return Math.max(MIN_PROXY_ACTION_TIMEOUT_MS, timeoutMs - LISTBOX_ACK_GRACE_MS);
248
+ }
249
+ if (message.type === 'setFieldText') {
250
+ return Math.max(MIN_PROXY_ACTION_TIMEOUT_MS, timeoutMs - TEXT_FIELD_ACK_GRACE_MS);
251
+ }
244
252
  return timeoutMs;
245
253
  }
246
254
  function ambiguousOperationFor(session, fingerprint) {
@@ -2110,7 +2118,7 @@ export function sendFileUpload(session, paths, opts, timeoutMs) {
2110
2118
  return sendAndWaitForUpdate(session, payload, timeoutMs);
2111
2119
  }
2112
2120
  /** Set a labeled text-like field (`input`, `textarea`, contenteditable, ARIA textbox) semantically. */
2113
- export function sendFieldText(session, fieldLabel, value, opts, timeoutMs) {
2121
+ export function sendFieldText(session, fieldLabel, value, opts, timeoutMs = TEXT_FIELD_CORRELATED_RESPONSE_TIMEOUT_MS) {
2114
2122
  const payload = {
2115
2123
  type: 'setFieldText',
2116
2124
  fieldLabel,
@@ -2129,7 +2137,7 @@ export function sendFieldText(session, fieldLabel, value, opts, timeoutMs) {
2129
2137
  return sendAndWaitForUpdate(session, payload, timeoutMs);
2130
2138
  }
2131
2139
  /** Choose a value for a labeled choice field (select, custom combobox, or radio-style group). */
2132
- export function sendFieldChoice(session, fieldLabel, value, opts, timeoutMs = LISTBOX_UPDATE_TIMEOUT_MS) {
2140
+ export function sendFieldChoice(session, fieldLabel, value, opts, timeoutMs = FIELD_CHOICE_UPDATE_TIMEOUT_MS) {
2133
2141
  const payload = {
2134
2142
  type: 'setFieldChoice',
2135
2143
  fieldLabel,
@@ -2173,7 +2181,7 @@ export function sendFillOtp(session, value, opts, timeoutMs) {
2173
2181
  return sendAndWaitForUpdate(session, payload, budget);
2174
2182
  }
2175
2183
  /** ARIA `role=option` listbox (e.g. React Select). Optional click opens the list. */
2176
- export function sendListboxPick(session, label, opts, timeoutMs = LISTBOX_UPDATE_TIMEOUT_MS) {
2184
+ export function sendListboxPick(session, label, opts, timeoutMs = LISTBOX_CORRELATED_RESPONSE_TIMEOUT_MS) {
2177
2185
  const payload = { type: 'listboxPick', label };
2178
2186
  if (opts?.exact !== undefined)
2179
2187
  payload.exact = opts.exact;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geometra/mcp",
3
- "version": "1.65.6",
3
+ "version": "1.65.8",
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.65.6",
35
+ "@geometra/proxy": "^1.65.8",
36
36
  "@modelcontextprotocol/sdk": "^1.12.1",
37
37
  "@razroo/parallel-mcp": "^0.1.0",
38
38
  "ws": "^8.21.0",