search_google
Search the web using Google to find current information, news, websites, and general knowledge. Returns structured results with titles, URLs, and snippets.
Instructions
Performs a web search using Google, ideal for finding current information, news, websites, and general knowledge. Use this tool when you need to research topics, find recent information, or gather data from the web. Returns structured search results with titles, URLs, and snippets.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query |
Implementation Reference
- index.ts:144-154 (registration)Tool registration/schema for 'search_google' - defines the tool name, description, and input schema expecting a 'query' string parameter.
{ name: "search_google", description: "Performs a web search using Google, ideal for finding current information, news, websites, and general knowledge. Use this tool when you need to research topics, find recent information, or gather data from the web. Returns structured search results with titles, URLs, and snippets.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query" }, }, required: ["query"], }, }, - index.ts:144-154 (schema)Input schema for search_google tool - defines the 'query' string property as required.
{ name: "search_google", description: "Performs a web search using Google, ideal for finding current information, news, websites, and general knowledge. Use this tool when you need to research topics, find recent information, or gather data from the web. Returns structured search results with titles, URLs, and snippets.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query" }, }, required: ["query"], }, }, - index.ts:794-989 (handler)Handler implementation for search_google - navigates to Google, fills search query, extracts result titles/URLs/snippets, and returns JSON results.
case "search_google": { // Extract search query from request parameters const { query } = request.params.arguments as { query: string }; try { // Execute search with retry mechanism const results = await withRetry(async () => { // Step 1: Navigate to Google search page await safePageNavigation(page, 'https://www.google.com'); // Simulate human behavior await randomDelay(800, 1500); await simulateHumanBehavior(page); // Step 2: Find and interact with search input await withRetry(async () => { // Wait for any search input element to appear await Promise.race([ // Try multiple possible selectors for search input page.waitForSelector('input[name="q"]', { timeout: 5000 }), page.waitForSelector('textarea[name="q"]', { timeout: 5000 }), page.waitForSelector('input[type="text"]', { timeout: 5000 }) ]).catch(() => { throw new Error('Search input not found - no matching selectors'); }); // Random delay before interacting await randomDelay(300, 700); // Find the actual search input element const searchInput = await page.$('input[name="q"]') || await page.$('textarea[name="q"]') || await page.$('input[type="text"]'); // Verify search input was found if (!searchInput) { throw new Error('Search input element not found after waiting'); } // Step 3: Enter search query with human-like typing await searchInput.click(); await randomDelay(100, 300); await searchInput.click({ clickCount: 3 }); // Select all existing text await randomDelay(50, 150); await searchInput.press('Backspace'); // Clear selected text await randomDelay(200, 400); // Type query with random delays between characters for (const char of query) { await searchInput.type(char); await randomDelay(50, 150); } }, 3, 2000); // Allow 3 retries with 2s delay // Random delay before submitting await randomDelay(400, 900); // Step 4: Submit search and wait for results await withRetry(async () => { await Promise.all([ page.keyboard.press('Enter'), page.waitForLoadState('networkidle', { timeout: 15000 }), ]); }); // Simulate human behavior after results load await randomDelay(500, 1000); await simulateHumanBehavior(page); // Step 5: Check for bot detection before extracting results const pageCheck = await page.evaluate(() => { // Check for results using multiple selectors const hasResults = document.querySelectorAll('div.g').length > 0 || document.querySelectorAll('div[data-hveid]').length > 0 || document.querySelectorAll('.MjjYud').length > 0 || document.querySelectorAll('div.Gx5Zad').length > 0; return { title: document.title, hasCaptcha: !!document.querySelector('#captcha-form') || !!document.querySelector('iframe[src*="recaptcha"]') || document.body.innerText.includes('unusual traffic'), hasResults: hasResults, bodyText: document.body.innerText.substring(0, 500) }; }); if (pageCheck.hasCaptcha) { throw new Error('Bot detection triggered - CAPTCHA detected'); } if (!pageCheck.hasResults) { throw new Error(`No search results found. Page title: "${pageCheck.title}". Body preview: ${pageCheck.bodyText}`); } // Step 6: Extract search results const searchResults = await withRetry(async () => { const results = await page.evaluate(() => { // Try multiple selectors for search result containers (Google changes these frequently) const possibleSelectors = [ 'div.g', // Classic selector 'div[data-hveid]', // Modern selector with tracking ID 'div.Gx5Zad', // Alternative container '.MjjYud', // Another common container ]; let elements: NodeListOf<Element> | null = null; for (const selector of possibleSelectors) { elements = document.querySelectorAll(selector); if (elements && elements.length > 0) { break; } } if (!elements || elements.length === 0) { throw new Error('No search results found with any known selector'); } // Extract data from each result return Array.from(elements).map((el) => { // Find title - try multiple selectors const titleEl = el.querySelector('h3') || el.querySelector('h2') || el.querySelector('[role="heading"]'); // Find link - look for main link const linkEl = el.querySelector('a[href]'); // Find snippet - try multiple selectors const snippetEl = el.querySelector('div.VwiC3b') || el.querySelector('.IsZvec') || el.querySelector('[data-content-feature]') || el.querySelector('div[style*="line-clamp"]'); // Skip results missing required elements if (!titleEl || !linkEl) { return null; } const url = linkEl.getAttribute('href') || ''; // Skip non-http URLs (like javascript:, data:, etc.) if (!url.startsWith('http')) { return null; } // Return structured result data return { title: titleEl.textContent?.trim() || '', url: url, snippet: snippetEl?.textContent?.trim() || '', }; }).filter(result => result !== null); // Remove invalid results }); // Verify we found valid results if (!results || results.length === 0) { throw new Error('No valid search results found'); } // Return compiled list of results return results; }); // Step 6: Store results in session searchResults.forEach((result) => { addResult({ url: result.url, title: result.title, content: result.snippet, timestamp: new Date().toISOString(), }); }); // Return compiled list of results return searchResults; }); // Step 7: Return formatted results return { content: [{ type: "text", text: JSON.stringify(results, null, 2) // Pretty-print JSON results }] }; } catch (error) { // Handle and format search errors return { content: [{ type: "text", text: `Failed to perform search: ${(error as Error).message}` }], isError: true }; } }