Skip to main content
Glama

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
NameRequiredDescriptionDefault
refYesElement ref (@e3) or CSS selector
buttonNoMouse button
double_clickNoDouble-click instead of single click

Implementation Reference

  • 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 };
        }
      }
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TacosyHorchata/Pilot'

If you have feedback or need assistance with the MCP directory API, please join our Discord server