Skip to content

Commit 6c3a7d3

Browse files
fix(mcp): return progress before host timeouts
1 parent cabdebf commit 6c3a7d3

19 files changed

Lines changed: 337 additions & 35 deletions

File tree

mcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@geometra/mcp",
3-
"version": "1.61.1",
3+
"version": "1.61.2",
44
"description": "MCP server for Geometra — interact with running Geometra apps via the geometry protocol, no browser needed",
55
"license": "MIT",
66
"type": "module",

mcp/src/__tests__/server-batch-results.test.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,39 @@ describe('batch MCP result shaping', () => {
345345
expect((final.alerts as unknown[]).length).toBe(1)
346346
})
347347

348+
it('caps run_actions step timeouts under the soft deadline and resumes from an action index', async () => {
349+
const handler = getToolHandler('geometra_run_actions')
350+
351+
const result = await handler({
352+
actions: [
353+
{ type: 'click', x: 10, y: 20, timeoutMs: 60_000 },
354+
{ type: 'click', x: 30, y: 40, timeoutMs: 60_000 },
355+
],
356+
resumeFromIndex: 1,
357+
softTimeoutMs: 1_000,
358+
includeSteps: true,
359+
detail: 'terse',
360+
})
361+
362+
expect(mockState.sendClick).toHaveBeenCalledTimes(1)
363+
const call = mockState.sendClick.mock.calls[0]!
364+
expect(call[1]).toBe(30)
365+
expect(call[2]).toBe(40)
366+
expect(call[3]).toBeGreaterThanOrEqual(50)
367+
expect(call[3]).toBeLessThanOrEqual(300)
368+
369+
const payload = JSON.parse(result.content[0]!.text) as Record<string, unknown>
370+
const steps = payload.steps as Array<Record<string, unknown>>
371+
expect(payload).toMatchObject({
372+
completed: true,
373+
resumedFromIndex: 1,
374+
stepCount: 2,
375+
successCount: 1,
376+
errorCount: 0,
377+
})
378+
expect(steps[0]).toMatchObject({ index: 1, type: 'click', ok: true })
379+
})
380+
348381
it('uses the proxy batch path for fill_fields when step output is omitted', async () => {
349382
const handler = getToolHandler('geometra_fill_fields')
350383

@@ -433,6 +466,38 @@ describe('batch MCP result shaping', () => {
433466
expect(payload).not.toHaveProperty('stepCount')
434467
})
435468

469+
it('caps submit_form submit clicks under the soft deadline', async () => {
470+
const handler = getToolHandler('geometra_submit_form')
471+
472+
mockState.currentA11yRoot = node('group', undefined, {
473+
bounds: { x: 0, y: 0, width: 1280, height: 720 },
474+
meta: { pageUrl: 'https://jobs.example.com/application', scrollX: 0, scrollY: 0 },
475+
children: [
476+
node('button', 'Submit', { path: [0], bounds: { x: 100, y: 180, width: 120, height: 40 } }),
477+
],
478+
})
479+
480+
const result = await handler({
481+
skipFill: true,
482+
submitTimeoutMs: 60_000,
483+
softTimeoutMs: 1_000,
484+
detail: 'terse',
485+
})
486+
487+
expect(mockState.sendClick).toHaveBeenCalledTimes(1)
488+
const call = mockState.sendClick.mock.calls[0]!
489+
expect(call[1]).toBe(160)
490+
expect(call[2]).toBe(200)
491+
expect(call[3]).toBeGreaterThanOrEqual(50)
492+
expect(call[3]).toBeLessThanOrEqual(300)
493+
494+
const payload = JSON.parse(result.content[0]!.text) as Record<string, unknown>
495+
expect(payload).toMatchObject({
496+
completed: true,
497+
submit: { wait: 'updated' },
498+
})
499+
})
500+
436501
it('attaches verifyFills readback results to run_actions fill_fields step', async () => {
437502
const handler = getToolHandler('geometra_run_actions')
438503

@@ -1922,7 +1987,7 @@ describe('query and reveal tools', () => {
19221987
const steps = payload.steps as Array<Record<string, unknown>>
19231988

19241989
expect(mockState.sendWheel).toHaveBeenCalledTimes(1)
1925-
expect(mockState.sendClick).toHaveBeenCalledWith(mockState.session, 150, 340, undefined)
1990+
expect(mockState.sendClick).toHaveBeenCalledWith(mockState.session, 150, 340, expect.any(Number))
19261991
expect(steps[0]).toMatchObject({
19271992
index: 0,
19281993
type: 'click',

0 commit comments

Comments
 (0)