Skip to main content
Glama
JoaoPedroLanca

MCP Web Tools Server

search_web

Search the web to find information using DuckDuckGo or SerpAPI. Enter a query to get relevant web results and content.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
limitNo

Implementation Reference

  • The main execution handler for the 'search_web' tool. It first tries SerpAPI search, falls back to DuckDuckGo scraping if that fails, formats the top results as numbered list with titles and URLs, and returns as text content.
    async (input) => {
        const limit = input.limit ?? SEARCH_RESULTS_LIMIT_DEFAULT;
        let results = null;
        try {
            results = await serpApiSearch(input.query, limit);
        } catch (e) {
    
        }
        if (!results) {
            results = await ddgSearch(input.query, limit);
        }
        const text = results
            .map((r, i) => `${i + 1}. ${r.title}\n${r.url}`)
            .join("\n\n");
        return {
            content: [{ type: "text", text: text || "No results" }],
        };
    }
  • Zod schema for input validation: required 'query' string and optional 'limit' integer between 1 and 10.
    {
        query: z.string().min(1),
        limit: z.number().int().min(1).max(10).optional(),
    },
  • src/server.js:69-93 (registration)
    Registers the 'search_web' tool on the MCP server with its schema and handler function.
    server.tool(
        "search_web",
        {
            query: z.string().min(1),
            limit: z.number().int().min(1).max(10).optional(),
        },
        async (input) => {
            const limit = input.limit ?? SEARCH_RESULTS_LIMIT_DEFAULT;
            let results = null;
            try {
                results = await serpApiSearch(input.query, limit);
            } catch (e) {
    
            }
            if (!results) {
                results = await ddgSearch(input.query, limit);
            }
            const text = results
                .map((r, i) => `${i + 1}. ${r.title}\n${r.url}`)
                .join("\n\n");
            return {
                content: [{ type: "text", text: text || "No results" }],
            };
        }
    );
  • Helper function for scraping DuckDuckGo search results as fallback when SerpAPI is unavailable.
    async function ddgSearch(query, limit) {
        const params = new URLSearchParams({ q: query, kl: "us-en" });
        const res = await fetch(`https://duckduckgo.com/html/?${params.toString()}`, {
            headers: {
                "User-Agent": "Mozilla/5.0 (compatible; MCP-Web-Tools/0.1; +https://example.com)",
                "Accept-Language": "en-US,en;q=0.9",
            },
        });
        const html = await res.text();
        const dom = new JSDOM(html);
        const doc = dom.window.document;
        const results = [];
        const nodes = doc.querySelectorAll(".result__title a.result__a");
        for (const a of nodes) {
            const title = a.textContent?.trim() || "";
            let href = a.getAttribute("href") || "";
            if (!href) continue;
            let url = href;
            try {
                if (href.startsWith("/l/?") || href.includes("duckduckgo.com/l/?")) {
                    const full = href.startsWith("http") ? href : `https://duckduckgo.com${href}`;
                    const u = new URL(full);
                    const target = u.searchParams.get("uddg");
                    if (target) url = decodeURIComponent(target);
                } else if (href.startsWith("//")) {
                    url = `https:${href}`;
                } else if (href.startsWith("/")) {
                    url = `https://duckduckgo.com${href}`;
                }
            } catch { }
            if (!url) continue;
            results.push({ title, url });
            if (results.length >= limit) break;
        }
        return results;
    }
  • Primary helper for web search using SerpAPI (requires SERPAPI_KEY env var), returns top organic Google results.
    async function serpApiSearch(query, limit) {
        const apiKey = process.env.SERPAPI_KEY;
        if (!apiKey) return null;
        const params = new URLSearchParams({
            engine: "google",
            q: query,
            num: String(Math.min(limit, 10)),
            api_key: apiKey,
        });
        const res = await fetch(`https://serpapi.com/search.json?${params.toString()}`);
        if (!res.ok) throw new Error(`SerpAPI error: ${res.status}`);
        const data = await res.json();
        const organic = Array.isArray(data.organic_results) ? data.organic_results : [];
        return organic.slice(0, limit).map((r) => ({ title: r.title || "", url: r.link || "" }));
    }
Install Server

Other 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/JoaoPedroLanca/mcp-web-tools'

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