pilot_click
Click web page elements using element references or CSS selectors to automate browser interactions. Supports different mouse buttons and double-click actions for precise control.
Instructions
Click an element by @ref (from snapshot) or CSS selector. Auto-routes clicks to selectOption.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ref | Yes | Element ref (@e3) or CSS selector | |
| button | No | Mouse button | |
| double_click | No | Double-click instead of single click |
Implementation Reference
- src/tools/interaction.ts:9-63 (handler)The 'pilot_click' tool is defined and implemented in src/tools/interaction.ts. It resolves the element reference, optionally auto-routes to 'selectOption' if the target is an option element, and performs the click using Playwright's locator or page API.
server.tool( 'pilot_click', 'Click an element by @ref (from snapshot) or CSS selector. Auto-routes <option> clicks to selectOption.', { ref: z.string().describe('Element ref (@e3) or CSS selector'), button: z.enum(['left', 'right', 'middle']).optional().describe('Mouse button'), double_click: z.boolean().optional().describe('Double-click instead of single click'), }, async ({ ref, button, double_click }) => { await bm.ensureBrowser(); try { const page = bm.getPage(); // Auto-route: if ref points to a <option>, use selectOption const role = bm.getRefRole(ref); if (role === 'option') { const resolved = await bm.resolveRef(ref); if ('locator' in resolved) { const optionInfo = await resolved.locator.evaluate(el => { if (el.tagName !== 'OPTION') return null; const option = el as HTMLOptionElement; const select = option.closest('select'); if (!select) return null; return { value: option.value, text: option.text }; }); if (optionInfo) { await resolved.locator.locator('xpath=ancestor::select').selectOption(optionInfo.value, { timeout: 5000 }); bm.resetFailures(); return { content: [{ type: 'text' as const, text: `Selected "${optionInfo.text}" (auto-routed from click on <option>) → now at ${page.url()}` }] }; } } } const resolved = await bm.resolveRef(ref); const clickOptions: any = { timeout: 5000 }; if (button) clickOptions.button = button; if (double_click) clickOptions.clickCount = 2; if ('locator' in resolved) { await resolved.locator.click(clickOptions); } else { await page.click(resolved.selector, clickOptions); } await page.waitForLoadState('domcontentloaded').catch(() => {}); bm.resetFailures(); return { content: [{ type: 'text' as const, text: `Clicked ${ref} → now at ${page.url()}` }] }; } catch (err) { bm.incrementFailures(); const hint = bm.getFailureHint(); let msg = wrapError(err); if (hint) msg += '\n' + hint; return { content: [{ type: 'text' as const, text: msg }], isError: true }; } } );