search
Perform web searches via Google without needing an API key, retrieving structured results including titles, URLs, and descriptions. Specify queries and set result limits up to 10.
Instructions
Search the web using Google (no API key required)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results to return (default: 5) | |
| query | Yes | Search query |
Input Schema (JSON Schema)
{
"properties": {
"limit": {
"description": "Maximum number of results to return (default: 5)",
"maximum": 10,
"minimum": 1,
"type": "number"
},
"query": {
"description": "Search query",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
}
Implementation Reference
- src/index.ts:121-152 (handler)Core execution logic of the 'search' tool: performs web scraping of Google search results using axios for HTTP request and cheerio for HTML parsing to extract titles, URLs, and descriptions.private async performSearch(query: string, limit: number): Promise<SearchResult[]> { const response = await axios.get('https://www.google.com/search', { params: { q: query }, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } }); const $ = cheerio.load(response.data); const results: SearchResult[] = []; $('div.g').each((i, element) => { if (i >= limit) return false; const titleElement = $(element).find('h3'); const linkElement = $(element).find('a'); const snippetElement = $(element).find('.VwiC3b'); if (titleElement.length && linkElement.length) { const url = linkElement.attr('href'); if (url && url.startsWith('http')) { results.push({ title: titleElement.text(), url: url, description: snippetElement.text() || '', }); } } }); return results; }
- src/index.ts:51-74 (registration)Registers the 'search' tool with the MCP server via the listTools handler, including name, description, and input schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'search', description: 'Search the web using Google (no API key required)', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 5)', minimum: 1, maximum: 10, }, }, required: ['query'], }, }, ], }));
- src/index.ts:76-118 (handler)MCP callTool request handler specifically for the 'search' tool: validates tool name and arguments, invokes performSearch, and formats the response as MCP content or error.this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'search') { throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } if (!isValidSearchArgs(request.params.arguments)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid search arguments' ); } const query = request.params.arguments.query; const limit = Math.min(request.params.arguments.limit || 5, 10); try { const results = await this.performSearch(query, limit); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2), }, ], }; } catch (error) { if (axios.isAxiosError(error)) { return { content: [ { type: 'text', text: `Search error: ${error.message}`, }, ], isError: true, }; } throw error; } });
- src/index.ts:19-23 (schema)Type guard for validating the input arguments of the 'search' tool against the expected schema.const isValidSearchArgs = (args: any): args is { query: string; limit?: number } => typeof args === 'object' && args !== null && typeof args.query === 'string' && (args.limit === undefined || typeof args.limit === 'number');
- src/index.ts:13-17 (schema)TypeScript interface defining the output format of search results from the tool.interface SearchResult { title: string; url: string; description: string; }