Skip to main content
Glama

search

Perform parallel Google searches for multiple keywords, retrieve structured results, and handle CAPTCHAs while simulating user browsing patterns with customizable options like search limits and timeouts.

Instructions

Search on Google for multiple keywords and return the results

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
debugNoWhether to enable debug mode (showing browser window), overrides the --debug command line flag if specified
limitNoMaximum number of results to return per query (default: 10)
localeNoLocale setting for search results (default: en-US)
noSaveStateNoWhether to avoid saving browser state (default: false)
queriesYesArray of search queries to perform
timeoutNoPage loading timeout in milliseconds (default: 60000)

Implementation Reference

  • The main handler function `searchGoogle` that executes the 'search' tool logic: validates input, prepares options, calls `multiGoogleSearch`, formats MultiSearchResponse, and returns MCP content.
    export async function searchGoogle(args: any) { const queries = args?.queries || []; if (!Array.isArray(queries) || queries.length === 0) { logger.error(`[Error] At least one search query is required`); throw new Error("At least one search query is required"); } const options: SearchOptions = { limit: Number(args?.limit) || 10, timeout: Number(args?.timeout) || 60000, noSaveState: args?.noSaveState === true, locale: String(args?.locale || "en-US"), debug: args?.debug !== undefined ? args?.debug : isDebugMode // Use tool param if provided, otherwise use command line flag }; // Log search parameters logger.info(`[SearchGoogle] Starting search for ${queries.length} queries with options: ${JSON.stringify(options)}`); logger.info(`[SearchGoogle] Debug mode: ${options.debug ? 'enabled' : 'disabled'} (from CLI flag: ${isDebugMode})`); try { const results = await multiGoogleSearch(queries, options); logger.info(`[SearchGoogle] Search completed successfully for ${results.length} queries`); // Format the response const response: MultiSearchResponse = { searches: results }; return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] }; } catch (error) { logger.error(`[SearchGoogle] Error during search: ${error}`); throw error; } }
  • Tool definition `searchGoogleTool` with name 'search', description, and detailed inputSchema for MCP tool validation.
    export const searchGoogleTool = { name: "search", description: "Search on Google for multiple keywords and return the results", inputSchema: { type: "object", properties: { queries: { type: "array", items: { type: "string" }, description: "Array of search queries to perform", }, limit: { type: "number", description: "Maximum number of results to return per query (default: 10)", }, timeout: { type: "number", description: "Page loading timeout in milliseconds (default: 60000)", }, noSaveState: { type: "boolean", description: "Whether to avoid saving browser state (default: false)", }, locale: { type: "string", description: "Locale setting for search results (default: en-US)", }, debug: { type: "boolean", description: "Whether to enable debug mode (showing browser window), overrides the --debug command line flag if specified", }, }, required: ["queries"], }, };
  • Central tool registry exporting `tools` array (for ListTools) and `toolHandlers` object mapping 'search' to its handler (for CallTool dispatch).
    import { searchGoogleTool, searchGoogle } from './searchGoogle.js'; // Export tool definitions export const tools = [ searchGoogleTool ]; // Export tool implementations export const toolHandlers = { [searchGoogleTool.name]: searchGoogle };
  • src/server.ts:22-43 (registration)
    MCP server request handlers: ListTools returns registered tools; CallTool dispatches to handler by name 'search'.
    server.setRequestHandler(ListToolsRequestSchema, async () => { logger.info("[Tools] List available tools"); return { tools }; }); /** * Handle tool call requests * Dispatch to the appropriate tool implementation */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const toolName = request.params.name; const handler = toolHandlers[toolName]; if (!handler) { logger.error(`[Error] Unknown tool: ${toolName}`); throw new Error(`Unknown tool: ${toolName}`); } return handler(request.params.arguments); });
  • Supporting `multiGoogleSearch` utility invoked by the handler: launches Playwright browser, performs parallel `googleSearch` calls for each query, handles state management.
    export async function multiGoogleSearch( queries: string[], options: SearchOptions = {} ): Promise<SearchResponse[]> { if (!queries || queries.length === 0) { throw new Error("At least one search query is required"); } logger.info(`[MultiSearch] Starting multiple searches for ${queries.length} queries...`); // Launch a single browser instance for all searches const browser = await chromium.launch({ headless: !options.debug, args: [ "--disable-blink-features=AutomationControlled", "--disable-features=IsolateOrigins,site-per-process", "--disable-site-isolation-trials", "--disable-web-security", "--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-accelerated-2d-canvas", "--no-first-run", "--no-zygote", "--disable-gpu", "--hide-scrollbars", "--mute-audio", "--disable-background-networking", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-breakpad", "--disable-component-extensions-with-background-pages", "--disable-extensions", "--disable-features=TranslateUI", "--disable-ipc-flooding-protection", "--disable-renderer-backgrounding", "--enable-features=NetworkService,NetworkServiceInProcess", "--force-color-profile=srgb", "--metrics-recording-only", ], ignoreDefaultArgs: ["--enable-automation"], }); try { // Create a unique state file for each query to avoid conflicts const searches = await Promise.all( queries.map((query, index) => { const searchOptions = { ...options, stateFile: options.stateFile ? `${options.stateFile}-${index}` : `./browser-state-${index}.json`, }; logger.info(`[MultiSearch] Starting search #${index + 1} for query: "${query}"`); return googleSearch(query, searchOptions, browser); }) ); logger.info(`[MultiSearch] All searches completed successfully`); return searches; } finally { // Only close browser if not in debug mode if (!options.debug) { logger.info(`[MultiSearch] Closing main browser instance`); await browser.close(); } else { logger.info(`[MultiSearch] Keeping browser instance open for debug mode`); } } }

Other Tools

Related Tools

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/jae-jae/g-search-mcp'

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