UNPKG

serper-search-scrape-mcp-server

Version:

Serper MCP Server supporting search and webpage scraping

109 lines (108 loc) 3.6 kB
import fetch from "node-fetch"; /** * Implementation of Serper API client. */ export class SerperClient { apiKey; baseUrl; /** * Initialize Serper API client. * @param apiKey - Serper API key for authentication * @param baseUrl - Base URL for Serper API (optional) */ constructor(apiKey, baseUrl = "https://google.serper.dev") { this.apiKey = apiKey; this.baseUrl = baseUrl; } /** * Perform a web search using Serper API. * @param params - Search parameters * @returns Promise resolving to search results * @throws Error if API request fails */ async search(params) { try { const response = await fetch(`${this.baseUrl}/search`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": this.apiKey, }, body: JSON.stringify(params), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Serper API error: ${response.status} ${response.statusText} - ${errorText}`); } const data = (await response.json()); return data; } catch (error) { console.error("Serper search failed:", error); throw error; } } /** * Perform a web search using Serper API. * @param batchParams - Search parameters * @returns Promise resolving to search results * @throws Error if API request fails */ async batchSearch(batchParams) { if (!batchParams.length) { throw new Error("Batch search requires at least one query"); } try { const response = await fetch(`${this.baseUrl}/search`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": this.apiKey, }, body: JSON.stringify(batchParams), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Serper API error: ${response.status} ${response.statusText} - ${errorText}`); } const data = (await response.json()); return data; } catch (error) { console.error("Serper search failed:", error); throw error; } } /** * Scrape a URL using Serper API. * @param params - Scrape parameters * @returns Promise resolving to scrape result * @throws Error if API request fails */ async scrape(params) { if (!params.url) { throw new Error("URL is required for scraping"); } try { const response = await fetch("https://scrape.serper.dev", { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": this.apiKey, }, body: JSON.stringify(params), redirect: "follow", }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Serper API error: ${response.status} ${response.statusText} - ${errorText}`); } const result = (await response.json()); return result; } catch (error) { console.error(error); throw error; } } }