search
Search the web for Web3 and crypto information using queries to find news, images, videos, and general content for research purposes.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query | |
| searchType | No | Type of search | web |
Implementation Reference
- src/tools/researchTools.ts:43-79 (handler)Handler function for the 'search' MCP tool. Logs the action, performs the search using performSearch utility, stores results in ResearchStorage, and returns markdown-formatted top 5 results or an error message.async ({ query, searchType }: { query: string; searchType: string }) => { storage.addLogEntry(`Performing ${searchType} search for: "${query}"`); try { const results = await performSearch(query, searchType as any); storage.addToSection("searchResults", { [searchType]: { [query]: results, }, }); return { content: [ { type: "text", text: `Search results for "${query}" (${searchType}):\n\n${JSON.stringify( results.results ? results.results.slice(0, 5) : [], null, 2 )}`, }, ], }; } catch (error) { storage.addLogEntry(`Error searching for "${query}": ${error}`); return { isError: true, content: [ { type: "text", text: `Error performing search: ${error}`, }, ], }; } }
- src/tools/researchTools.ts:36-42 (schema)Zod input schema for the 'search' tool defining 'query' (string) and 'searchType' (enum: web, news, images, videos with default 'web').{ query: z.string().describe("Search query"), searchType: z .enum(["web", "news", "images", "videos"]) .default("web") .describe("Type of search"), },
- src/tools/researchTools.ts:34-80 (registration)Registration of the 'search' tool on the McpServer instance within registerResearchTools function.server.tool( "search", { query: z.string().describe("Search query"), searchType: z .enum(["web", "news", "images", "videos"]) .default("web") .describe("Type of search"), }, async ({ query, searchType }: { query: string; searchType: string }) => { storage.addLogEntry(`Performing ${searchType} search for: "${query}"`); try { const results = await performSearch(query, searchType as any); storage.addToSection("searchResults", { [searchType]: { [query]: results, }, }); return { content: [ { type: "text", text: `Search results for "${query}" (${searchType}):\n\n${JSON.stringify( results.results ? results.results.slice(0, 5) : [], null, 2 )}`, }, ], }; } catch (error) { storage.addLogEntry(`Error searching for "${query}": ${error}`); return { isError: true, content: [ { type: "text", text: `Error performing search: ${error}`, }, ], }; } } );
- src/utils/searchUtils.ts:8-59 (helper)Core helper function performSearch that implements the actual searching logic using duck-duck-scrape (DDG) library for different search types, with retry logic for anomalies.export async function performSearch( query: string, type: "web" | "news" | "images" | "videos" = "web", retries = 2 ): Promise<any> { try { await sleep(3000); let results; switch (type) { case "news": if (typeof DDG.news !== "function") { results = await DDG.search(`${query} news`, { safeSearch: DDG.SafeSearchType.MODERATE, }); } else { results = await DDG.news(query); } break; case "images": if (typeof DDG.images !== "function") { results = await DDG.search(`${query} images`, { safeSearch: DDG.SafeSearchType.MODERATE, }); } else { results = await DDG.images(query); } break; case "videos": if (typeof DDG.videos !== "function") { results = await DDG.search(`${query} videos`, { safeSearch: DDG.SafeSearchType.MODERATE, }); } else { results = await DDG.videos(query); } break; default: results = await DDG.search(query, { safeSearch: DDG.SafeSearchType.MODERATE, }); } return results; } catch (error) { if (retries > 0 && String(error).includes("anomaly")) { await sleep(10000); return performSearch(query, type, retries - 1); } throw error; } }