parallel_search
Execute multiple Google searches simultaneously to save time and gather comprehensive results, enabling efficient deep web research and enhanced data extraction.
Instructions
Perform multiple Google searches in parallel
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| maxParallel | No | Maximum number of parallel searches | |
| queries | Yes | Array of search queries to execute in parallel |
Input Schema (JSON Schema)
{
"properties": {
"maxParallel": {
"description": "Maximum number of parallel searches",
"maximum": 5,
"minimum": 1,
"type": "number"
},
"queries": {
"description": "Array of search queries to execute in parallel",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"queries"
],
"type": "object"
}
Implementation Reference
- src/parallel-search.ts:196-266 (handler)Core handler function implementing parallel Google searches using multiple browser contexts with Playwright. Splits queries into chunks, performs searches with staggered starts, extracts titles/URLs/snippets with relevance scoring, handles errors, saves JSON results, and returns aggregated results with success/failure summary and timings.public async parallelSearch(queries: string[]): Promise<{ results: ParallelSearchResult[]; summary: { totalQueries: number; successful: number; failed: number; totalExecutionTime?: number; averageExecutionTime?: number; }; }> { const startTime = this.options.includeTimings ? Date.now() : undefined; await this.initialize(); const results: ParallelSearchResult[] = []; const chunks: string[][] = []; // Split queries into chunks of maxParallel size for (let i = 0; i < queries.length; i += this.options.maxParallel) { chunks.push(queries.slice(i, i + this.options.maxParallel)); } // Process each chunk for (const chunk of chunks) { const chunkPromises = chunk.map((query, index) => { const searchId = `search_${Date.now()}_${index + 1}_of_${chunk.length}`; // Stagger the searches return new Promise<ParallelSearchResult>(async (resolve) => { await new Promise(r => setTimeout(r, index * this.options.delayBetweenSearches)); const result = await this.singleSearch( this.contexts[index % this.contexts.length], query, searchId ); resolve(result); }); }); const chunkResults = await Promise.all(chunkPromises); results.push(...chunkResults); // Add a small delay between chunks if (chunks.indexOf(chunk) < chunks.length - 1) { await new Promise(r => setTimeout(r, 1000)); } } const endTime = Date.now(); const successful = results.filter(r => !r.error).length; const failed = results.filter(r => r.error).length; const summary = { totalQueries: queries.length, successful, failed, ...(this.options.includeTimings && startTime ? { totalExecutionTime: endTime - startTime, averageExecutionTime: Math.round((endTime - startTime) / queries.length) } : {}) }; // Add individual execution times to results if timing is enabled const timedResults = this.options.includeTimings ? results.map(r => ({ ...r, executionTime: r.executionTime || 0 })) : results; return { results: timedResults, summary }; }
- src/index.ts:126-147 (registration)MCP tool registration for 'parallel_search', defining the tool name, description, and input schema for the ListTools response.name: 'parallel_search', description: 'Perform multiple Google searches in parallel', inputSchema: { type: 'object', properties: { queries: { type: 'array', items: { type: 'string' }, description: 'Array of search queries to execute in parallel' }, maxParallel: { type: 'number', description: 'Maximum number of parallel searches', minimum: 1, maximum: 5 } }, required: ['queries'] } },
- src/index.ts:317-335 (handler)Top-level MCP CallToolRequest handler for 'parallel_search' tool. Validates input, limits queries to 5, delegates execution to DeepResearch.parallelSearch.parallelSearch instance, and formats result as MCP content response.case 'parallel_search': { const args = request.params.arguments as unknown as ParallelSearchArgs; if (!args?.queries) { throw new McpError(ErrorCode.InvalidParams, 'Queries array is required'); } const limitedQueries = args.queries.slice(0, 5); console.log(`Starting parallel search with ${limitedQueries.length} queries`); const result = await deepResearch.parallelSearch.parallelSearch(limitedQueries); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; }
- src/index.ts:23-26 (schema)TypeScript interface defining the expected input arguments for the parallel_search tool handler.interface ParallelSearchArgs { queries: string[]; maxParallel?: number; }
- src/deep-research.ts:54-60 (helper)Instantiation of ParallelSearch class as a public property in DeepResearch class, used by the tool handler.public parallelSearch: ParallelSearch; private searchQueue: SearchQueue; private activeSessions: Map<string, ResearchSession>; constructor() { this.parallelSearch = new ParallelSearch(); this.searchQueue = new SearchQueue();