Skip to main content
Glama

web-search

Conduct web searches using DuckDuckGo to retrieve real-time results, customize page numbers, and specify the number of outputs for efficient information retrieval.

Instructions

Search the web using DuckDuckGo and return results

Input Schema

NameRequiredDescriptionDefault
numResultsNoNumber of results to return (default: 10)
pageNoPage number (default: 1)
queryYesThe search query

Input Schema (JSON Schema)

{ "properties": { "numResults": { "default": 10, "description": "Number of results to return (default: 10)", "maximum": 20, "minimum": 1, "type": "integer" }, "page": { "default": 1, "description": "Page number (default: 1)", "minimum": 1, "type": "integer" }, "query": { "description": "The search query", "type": "string" } }, "required": [ "query" ], "type": "object" }

Implementation Reference

  • The handler function for the 'web-search' tool. It processes input parameters and delegates to searchDuckDuckGo helper, then formats the response as MCP content.
    export async function searchToolHandler(params) { const { query, numResults = 3, mode = 'short' } = params; console.log(`Searching for: ${query} (${numResults} results, mode: ${mode})`); const results = await searchDuckDuckGo(query, numResults, mode); console.log(`Found ${results.length} results`); return { content: [ { type: 'text', text: JSON.stringify(results) } ] }; }
  • The schema/definition for the 'web-search' tool, including name, description, and input schema validation.
    export const searchToolDefinition = { name: 'web-search', title: 'Web Search', description: 'Perform a web search using DuckDuckGo and receive detailed results including titles, URLs, and summaries.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Enter your search query to find the most relevant web pages.' }, numResults: { type: 'integer', description: 'Specify how many results to display (default: 3, maximum: 20).', default: 3, minimum: 1, maximum: 20 }, mode: { type: 'string', description: "Choose 'short' for basic results (no Description) or 'detailed' for full results (includes Description).", enum: ['short', 'detailed'], default: 'short' } }, required: ['query'] } };
  • src/index.ts:14-18 (registration)
    Registration of the tool definition in the availableTools array, returned by ListToolsRequestSchema handler.
    const availableTools = [ searchToolDefinition, iaskToolDefinition, monicaToolDefinition ];
  • src/index.ts:50-51 (registration)
    Dispatch/registration of the tool handler in the switch statement within CallToolRequestSchema handler.
    case 'web-search': return await searchToolHandler(args);
  • Core helper function implementing the web search logic: fetches DuckDuckGo HTML, parses results with cheerio, extracts direct URLs, optionally fetches summaries via Jina AI, with caching.
    async function searchDuckDuckGo(query, numResults = 10, mode = 'short') { try { // Clear old cache entries clearOldCache(); // Check cache first const cacheKey = getCacheKey(query); const cachedResults = resultsCache.get(cacheKey); if (cachedResults && Date.now() - cachedResults.timestamp < CACHE_DURATION) { return cachedResults.results.slice(0, numResults); } // Get a random user agent const userAgent = getRandomUserAgent(); // Fetch results const response = await axios.get( `https://duckduckgo.com/html/?q=${encodeURIComponent(query)}`, { headers: { 'User-Agent': userAgent }, httpsAgent: httpsAgent } ); if (response.status !== 200) { throw new Error('Failed to fetch search results'); } const html = response.data; // Parse results using cheerio const $ = cheerio.load(html); const results = []; const jinaFetchPromises = []; $('.result').each((i, result) => { const $result = $(result); const titleEl = $result.find('.result__title a'); const linkEl = $result.find('.result__url'); const snippetEl = $result.find('.result__snippet'); const title = titleEl.text()?.trim(); const rawLink = titleEl.attr('href'); const description = snippetEl.text()?.trim(); const displayUrl = linkEl.text()?.trim(); const directLink = extractDirectUrl(rawLink || ''); const favicon = getFaviconUrl(directLink); const jinaUrl = getJinaAiUrl(directLink); if (title && directLink) { if (mode === 'detailed') { jinaFetchPromises.push( axios.get(jinaUrl, { headers: { 'User-Agent': getRandomUserAgent() }, httpsAgent: httpsAgent, timeout: 10000 }) .then(jinaRes => { let jinaContent = ''; if (jinaRes.status === 200 && typeof jinaRes.data === 'string') { const $jina = cheerio.load(jinaRes.data); jinaContent = $jina('body').text() } return { title, url: directLink, snippet: description || '', favicon: favicon, displayUrl: displayUrl || '', Description: jinaContent }; }) .catch(() => { return { title, url: directLink, snippet: description || '', favicon: favicon, displayUrl: displayUrl || '', Description: '' }; }) ); } else { // short mode: omit Description jinaFetchPromises.push( Promise.resolve({ title, url: directLink, snippet: description || '', favicon: favicon, displayUrl: displayUrl || '' }) ); } } }); // Wait for all Jina AI fetches to complete const jinaResults = await Promise.all(jinaFetchPromises); results.push(...jinaResults); // Get limited results const limitedResults = results.slice(0, numResults); // Cache the results resultsCache.set(cacheKey, { results: limitedResults, timestamp: Date.now() }); // If cache is too big, remove oldest entries if (resultsCache.size > MAX_CACHE_PAGES) { const oldestKey = Array.from(resultsCache.keys())[0]; resultsCache.delete(oldestKey); } return limitedResults; } catch (error) { console.error('Error searching DuckDuckGo:', error.message); throw error; } }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/OEvortex/ddg_search'

If you have feedback or need assistance with the MCP directory API, please join our Discord server