search_parallel
Execute multiple Google searches concurrently, retrieving titles, URLs, and snippets for each result. Submit up to 10 queries at once with adjustable result limits per query.
Instructions
Run multiple Google searches in parallel (pool of 4). Returns title/url/snippet per result. First call adds 5–10s setup.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | Queries | |
| limit | No | Max results per query |
Implementation Reference
- src/index.ts:199-210 (registration)Tool registration for 'search_parallel' in the ListToolsRequestSchema handler. Defines name, description, and inputSchema (queries array + limit).
{ name: 'search_parallel', description: 'Run multiple Google searches in parallel (pool of 4). Returns title/url/snippet per result. First call adds 5–10s setup.', inputSchema: { type: 'object', properties: { queries: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 10, description: 'Queries' }, limit: { type: 'number', minimum: 1, maximum: 20, description: 'Max results per query' }, }, required: ['queries'], }, }, - src/index.ts:280-304 (handler)Main handler for 'search_parallel' tool in CallToolRequestSchema. Parses args, calls ensurePool() then p.runMany(queries, limit) within trackPool() and withCaptchaFallback(). Returns JSON results with elapsed time.
if (name === 'search_parallel') { const queries = (args?.queries as string[] || []).map(q => String(q).trim()).filter(Boolean); if (queries.length === 0) throw new McpError(ErrorCode.InvalidParams, 'queries required'); const limit = Math.min(Math.max(Number(args?.limit) || 10, 1), 20); const t0 = Date.now(); try { const results = await trackPool(() => withCaptchaFallback( async () => { const p = await ensurePool(); return await withTimeout(p.runMany(queries, limit), REQUEST_TIMEOUT_MS * 2, 'search_parallel'); }, resetPool, )); return { content: [{ type: 'text', text: JSON.stringify({ results, elapsed_ms: Date.now() - t0 }, null, 2), }], }; } catch (e) { console.error('[google-surf-mcp] search_parallel error:', e); return { content: [{ type: 'text', text: `Error: ${(e as Error).message}` }], isError: true }; } } - src/pool.ts:61-64 (helper)SearchPool.runMany() method — the core execution logic. Runs multiple Google searches in parallel by Promise.all-mapping each query to searchOne(), which acquires a worker from the pool, runs search() on a page, and releases the worker.
async runMany(queries: string[], limit = 10): Promise<PoolSearchResult[]> { if (!this.warmed) await this.warm(); return Promise.all(queries.map((q) => this.searchOne(q, limit))); } - src/pool.ts:66-79 (helper)SearchPool.searchOne() — acquires a pool worker, runs a single Google search via the search() function, and releases the worker. Returns PoolSearchResult with query, results, and optional error.
async searchOne(query: string, limit: number): Promise<PoolSearchResult> { if (!this.warmed) await this.warm(); const w = await this.acquire(); try { const page = await getPage(w.ctx); const results = await search(page, query, limit); return { query, results }; } catch (e) { if (e instanceof CaptchaError) throw e; return { query, results: [], error: (e as Error).message }; } finally { this.release(w); } } - src/index.ts:202-209 (schema)Input schema for search_parallel: requires 'queries' (array of strings, 1-10 items) and optional 'limit' (1-20).
inputSchema: { type: 'object', properties: { queries: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 10, description: 'Queries' }, limit: { type: 'number', minimum: 1, maximum: 20, description: 'Max results per query' }, }, required: ['queries'], },