pilot_page_links
Return all links from a web page as text and URL pairs, with an option to limit the total characters retrieved.
Instructions
Get all links on the page as text + href pairs.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| max_chars | No | Max characters to return (default: 20000) |
Implementation Reference
- src/tools/page.ts:76-103 (handler)The main handler for the pilot_page_links tool. Registers the tool on the MCP server with a max_chars optional parameter, then either uses the browser extension (extSend) to collect links via content script, or falls back to evaluating document.querySelectorAll('a[href]') directly via Playwright. Returns text + href pairs formatted as 'text → href' per line.
server.tool( 'pilot_page_links', 'Get all links on the page as text + href pairs.', { max_chars: z.number().optional().describe('Max characters to return (default: 20000)'), }, async ({ max_chars }) => { await bm.ensureBrowser(); try { const ext = bm.getExtension(); if (ext) { const res = await bm.extSend<{ links: Array<{ text: string; href: string }> }>('page_links'); const result = res.links.map(l => `${l.text} → ${l.href}`).join('\n'); return { content: [{ type: 'text' as const, text: truncate(result || '(no links found)', max_chars) }] }; } const links = await bm.getPage().evaluate(() => [...document.querySelectorAll('a[href]')].map(a => ({ text: a.textContent?.trim().slice(0, 120) || '', href: (a as HTMLAnchorElement).href, })).filter(l => l.text && l.href) ); const result = links.map(l => `${l.text} → ${l.href}`).join('\n'); return { content: [{ type: 'text' as const, text: truncate(result || '(no links found)', max_chars) }] }; } catch (err) { return { content: [{ type: 'text' as const, text: wrapError(err) }], isError: true }; } } ); - src/tools/page.ts:79-81 (schema)Input schema for pilot_page_links: accepts an optional 'max_chars' number parameter (default 20000) to limit output size.
{ max_chars: z.number().optional().describe('Max characters to return (default: 20000)'), }, - src/tools/register.ts:73-87 (registration)Registration entry point: registerAllTools calls registerPageTools (line 80), which registers the pilot_page_links tool. The tool is not in the CORE or STANDARD sets, so it is only available under the 'full' profile.
export function registerAllTools(server: McpServer, bm: BrowserManager, profile: ToolProfile = 'full'): void { const allowed = PROFILE_TOOLS[profile]; const effectiveServer = allowed ? createFilteredServer(server, allowed) : server; registerNavigationTools(effectiveServer, bm); registerSnapshotTools(effectiveServer, bm); registerInteractionTools(effectiveServer, bm); registerPageTools(effectiveServer, bm); registerInspectionTools(effectiveServer, bm); registerVisualTools(effectiveServer, bm); registerTabTools(effectiveServer, bm); registerSettingsTools(effectiveServer, bm); registerIframeTools(effectiveServer, bm); registerAutomationTools(effectiveServer, bm); } - extension/content.js:442-448 (helper)Browser extension content script helper that collects up to 100 links from the page with their text (trimmed to 80 chars) and href. Used when the browser extension is active (ext is truthy).
function pageLinks() { const links = Array.from(document.querySelectorAll('a[href]')).slice(0, 100).map(a => ({ text: a.textContent.trim().slice(0, 80), href: a.href, })); return { links, count: links.length }; } - extension/background.js:124-130 (helper)Background script relay: routes 'page_links' messages to the content script via relayToContent.
case 'page_links': case 'page_forms': case 'element_state': case 'evaluate': case 'page_text': case 'page_html': return await relayToContent(type, payload, tabId);