Web Search
web-searchSearch the web using DuckDuckGo to find current information, articles, documentation, and web content. Returns titles, URLs, and snippets for research and fact-finding.
Instructions
Search the web for information using DuckDuckGo. Returns titles, URLs, and snippets of search results. Useful for finding current information, articles, documentation, and general web content.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The search query to look up on the web | |
| max_results | No | Maximum number of results to return (1-10, default: 5) |
Implementation Reference
- src/tools/web-search.ts:115-139 (handler)The main execution handler for the 'web-search' tool. It calls performWebSearch, formats the results, and returns them as text content or an error message.
async ({ query, max_results = 5 }) => { try { const results = await performWebSearch(query, max_results); const formattedResults = formatSearchResults(query, results); return { content: [ { type: "text" as const, text: formattedResults, }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error performing web search: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], isError: true, }; } }, - src/tools/web-search.ts:104-113 (schema)Zod-based input schema for the web-search tool, defining 'query' (required string) and optional 'max_results' (1-10).
inputSchema: { query: z.string().min(1).describe("The search query to look up on the web"), max_results: z .number() .int() .min(1) .max(10) .optional() .describe("Maximum number of results to return (1-10, default: 5)"), }, - src/tools/web-search.ts:98-140 (registration)The server.registerTool call within registerWebSearchTool that defines and registers the 'web-search' tool including name, metadata, schema, and handler.
server.registerTool( "web-search", { title: "Web Search", description: "Search the web for information using DuckDuckGo. Returns titles, URLs, and snippets of search results. Useful for finding current information, articles, documentation, and general web content.", inputSchema: { query: z.string().min(1).describe("The search query to look up on the web"), max_results: z .number() .int() .min(1) .max(10) .optional() .describe("Maximum number of results to return (1-10, default: 5)"), }, }, async ({ query, max_results = 5 }) => { try { const results = await performWebSearch(query, max_results); const formattedResults = formatSearchResults(query, results); return { content: [ { type: "text" as const, text: formattedResults, }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error performing web search: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], isError: true, }; } }, ); - src/tools/index.ts:33-34 (registration)Invocation of registerWebSearchTool in the central tools registration function, followed by logging.
registerWebSearchTool(server); logger.tool("web-search", "registered"); - src/tools/web-search.ts:48-73 (helper)Helper function that performs the web search by fetching DuckDuckGo HTML results and parsing up to maxResults.
async function performWebSearch(query: string, maxResults = 5): Promise<SearchResult[]> { try { // Use DuckDuckGo HTML endpoint const searchUrl = new URL("https://html.duckduckgo.com/html/"); searchUrl.searchParams.append("q", query); searchUrl.searchParams.append("kl", "us-en"); const response = await fetch(searchUrl.toString(), { headers: { "User-Agent": "Mozilla/5.0 (compatible; DuyetMCP/0.1; +https://duyet.net/)", }, }); if (!response.ok) { throw new Error(`Search request failed with status: ${response.status}`); } const html = await response.text(); const results = parseDuckDuckGoResults(html); return results.slice(0, maxResults); } catch (error) { console.error("Web search error:", error); throw new Error("Failed to perform web search"); } }