web-search
Search webpages using plain text, with options to filter results by site, timeframe, and page number. Ideal for targeted queries and accessing specific content quickly.
Instructions
Search webpages and get a specific page of results (each page has ~10 results). Optionally filter by site and timeframe.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pageNumber | No | Which page of results to fetch (1-5). Each page contains ~10 results | |
| query_text | Yes | Plain text to search for (no Google operators plain text only - use other parameters for site/date filtering) | |
| site | No | Limit search to specific domain (e.g. 'github.com' or 'docs.python.org') | |
| timeframe | No | Time range filter (h=hour, d=day, w=week, m=month, y=year) |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"pageNumber": {
"default": 1,
"description": "Which page of results to fetch (1-5). Each page contains ~10 results",
"maximum": 5,
"minimum": 1,
"type": "number"
},
"query_text": {
"description": "Plain text to search for (no Google operators plain text only - use other parameters for site/date filtering)",
"minLength": 1,
"type": "string"
},
"site": {
"description": "Limit search to specific domain (e.g. 'github.com' or 'docs.python.org')",
"type": "string"
},
"timeframe": {
"description": "Time range filter (h=hour, d=day, w=week, m=month, y=year)",
"enum": [
"h",
"d",
"w",
"m",
"y"
],
"type": "string"
}
},
"required": [
"query_text"
],
"type": "object"
}
Implementation Reference
- src/tools/search.ts:6-39 (registration)Primary registration of the 'web-search' tool using server.tool(), including description, Zod schema, and inline handler function.server.tool( "web-search", "Search webpages and get a specific page of results (each page has ~10 results). Optionally filter by site and timeframe.", { query_text: z.string().min(1).describe("Plain text to search for (no Google operators plain text only - use other parameters for site/date filtering)"), site: z.string().optional().describe("Limit search to specific domain (e.g. 'github.com' or 'docs.python.org')"), timeframe: z.enum(['h', 'd', 'w', 'm', 'y']).optional().describe("Time range filter (h=hour, d=day, w=week, m=month, y=year)"), pageNumber: z.number().min(1).max(5).optional().default(1).describe( "Which page of results to fetch (1-5). Each page contains ~10 results" ) }, async ({ query_text, site, timeframe, pageNumber }) => { console.error(`Executing Google search for: ${query_text} (page ${pageNumber})`); try { const searchParams = { query_text, site, timeframe }; const results = await performGoogleSearch(searchParams, pageNumber); return { content: [{ type: "text" as const, text: results }] }; } catch (error) { return { content: [{ type: "text" as const, text: `Search failed - please try again: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
- src/tools/search.ts:17-38 (handler)The async handler function passed to server.tool that executes the web-search logic by calling performGoogleSearch and handling response/error formatting.async ({ query_text, site, timeframe, pageNumber }) => { console.error(`Executing Google search for: ${query_text} (page ${pageNumber})`); try { const searchParams = { query_text, site, timeframe }; const results = await performGoogleSearch(searchParams, pageNumber); return { content: [{ type: "text" as const, text: results }] }; } catch (error) { return { content: [{ type: "text" as const, text: `Search failed - please try again: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } }
- src/tools/search.ts:9-16 (schema)Zod schema defining input parameters for the web-search tool.{ query_text: z.string().min(1).describe("Plain text to search for (no Google operators plain text only - use other parameters for site/date filtering)"), site: z.string().optional().describe("Limit search to specific domain (e.g. 'github.com' or 'docs.python.org')"), timeframe: z.enum(['h', 'd', 'w', 'm', 'y']).optional().describe("Time range filter (h=hour, d=day, w=week, m=month, y=year)"), pageNumber: z.number().min(1).max(5).optional().default(1).describe( "Which page of results to fetch (1-5). Each page contains ~10 results" ) },
- Core helper function that orchestrates fetching multiple pages of Google search results using fetchSearchPage, collects and formats them as text.export async function performGoogleSearch(searchParams: SearchParams, pages: number = 1): Promise<string> { try { const allResults: SearchResult[] = []; // Fetch results from multiple pages for (let page = 1; page <= pages; page++) { const pageResults = await fetchSearchPage(searchParams, page); allResults.push(...pageResults); // Add a small delay between page fetches if (page < pages) { await new Promise(resolve => setTimeout(resolve, 1000)); } } return allResults.map(r => `${r.url}\n${r.description}`).join('\n\n'); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); throw new Error(`Failed to perform Google search: ${errorMessage}`); } }
- src/types/search.ts:1-10 (schema)TypeScript interfaces defining SearchParams (input) and SearchResult (output items) used throughout the search implementation.export interface SearchParams { query_text: string; site?: string; timeframe?: 'h' | 'd' | 'w' | 'm' | 'y'; } export interface SearchResult { url: string; description: string; }
- src/index.ts:13-13 (registration)Top-level call to register the search tools on the MCP server instance.registerSearchTool(server);