Snapshot
pinchtab_snapshotCapture an accessibility tree snapshot of the page, returning element refs for automation. Filter by interactive elements or use compact format to reduce token usage.
Instructions
Get an accessibility tree snapshot of the page. Returns element refs (e0, e1, …) that can be used with click/type/press. Use filter='interactive' for fewer tokens. Use format='compact' for minimal output.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| diff | No | If true, return only changes since last snapshot. Great for multi-step workflows. | |
| filter | No | Filter elements: 'interactive' for buttons/links/inputs only. Default: 'all' | |
| format | No | 'compact' returns minimal refs (~3.6K tokens). Default: 'full' |
Implementation Reference
- src/tools/navigation.ts:77-88 (handler)The actual handler function for pinchtab_snapshot. It builds query params (filter, format, diff) and calls pinch('GET', '/snapshot?...') to get the accessibility tree snapshot from the PinchTab server.
async ({ filter, format, diff }) => { try { const params = new URLSearchParams(); if (filter) params.set("filter", filter); if (format === "compact") params.set("format", "compact"); if (diff) params.set("diff", "true"); const qs = params.toString() ? `?${params.toString()}` : ""; return toolResult(await pinch("GET", `/snapshot${qs}`)); } catch (error) { return toolError(error); } }, - src/tools/navigation.ts:54-89 (registration)Registration of the 'pinchtab_snapshot' tool using server.registerTool(). Defines name, description, input schema (diff, filter, format), and the handler.
server.registerTool( "pinchtab_snapshot", { description: "Get an accessibility tree snapshot of the page. Returns element refs (e0, e1, …) that can be used with click/type/press. Use filter='interactive' for fewer tokens. Use format='compact' for minimal output.", inputSchema: z.object({ diff: z .boolean() .optional() .describe( "If true, return only changes since last snapshot. Great for multi-step workflows.", ), filter: z .enum(["all", "interactive"]) .optional() .describe("Filter elements: 'interactive' for buttons/links/inputs only. Default: 'all'"), format: z .enum(["full", "compact"]) .optional() .describe("'compact' returns minimal refs (~3.6K tokens). Default: 'full'"), }), title: "Snapshot", }, async ({ filter, format, diff }) => { try { const params = new URLSearchParams(); if (filter) params.set("filter", filter); if (format === "compact") params.set("format", "compact"); if (diff) params.set("diff", "true"); const qs = params.toString() ? `?${params.toString()}` : ""; return toolResult(await pinch("GET", `/snapshot${qs}`)); } catch (error) { return toolError(error); } }, ); - src/tools/navigation.ts:59-74 (schema)Input schema for pinchtab_snapshot using Zod. Validates 'diff' (boolean, optional), 'filter' (enum: 'all'|'interactive'), and 'format' (enum: 'full'|'compact').
inputSchema: z.object({ diff: z .boolean() .optional() .describe( "If true, return only changes since last snapshot. Great for multi-step workflows.", ), filter: z .enum(["all", "interactive"]) .optional() .describe("Filter elements: 'interactive' for buttons/links/inputs only. Default: 'all'"), format: z .enum(["full", "compact"]) .optional() .describe("'compact' returns minimal refs (~3.6K tokens). Default: 'full'"), }), - src/tools/shared.ts:6-11 (helper)Helper function waitAndSnapshot used by other tools (navigate, wait) to wait then fetch a compact snapshot. The snapshot tool itself calls pinch directly.
export async function waitAndSnapshot(ms: number): Promise<string> { const clamped = Math.min(ms, MAX_WAIT_MS); await new Promise((resolve) => setTimeout(resolve, clamped)); const snapshot = await pinch("GET", "/snapshot?format=compact"); return typeof snapshot === "string" ? snapshot : JSON.stringify(snapshot, undefined, 2); } - src/pinchtab/client.ts:6-49 (helper)The pinch() HTTP client that makes requests to the PinchTab server. The snapshot handler calls pinch('GET', '/snapshot?...') to retrieve the snapshot.
export async function pinch( method: string, path: string, body?: Record<string, unknown>, ): Promise<unknown> { if (!(await isPinchtabRunning())) { await ensurePinchtabRunning(); } const headers: Record<string, string> = { "Content-Type": "application/json", }; if (PINCHTAB_TOKEN) { headers["Authorization"] = `Bearer ${PINCHTAB_TOKEN}`; } const url = `${PINCHTAB_URL}${path}`; let res: Response; try { res = await fetch(url, { body: body ? JSON.stringify(body) : undefined, headers, method, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }); } catch (error) { if (error instanceof DOMException && error.name === "TimeoutError") { throw new Error(`PinchTab ${method} ${path} timed out after ${REQUEST_TIMEOUT_MS / 1000}s`); } throw error; } if (!res.ok) { const text = await res.text(); throw new Error(`PinchTab ${method} ${path} → ${res.status}: ${text}`); } const contentType = (res.headers.get("content-type") ?? "").split(";")[0].toLowerCase().trim(); if (contentType === "application/json") { return res.json(); } return res.text(); }