Skip to main content
Glama
arvindg4u

DuckDuckGo Search MCP Server

by arvindg4u

DuckDuckGo Search MCP Server

An MCP server that brings DuckDuckGo search to any MCP-compatible AI client (Claude Desktop, Cursor, VS Code, Copilot, etc.).

No API key required — DuckDuckGo is free and public.

Tools

Tool

Description

ddg_search

General web search (supports filetype:, site:, intitle:, inurl: operators)

ddg_news

Recent news article search

ddg_images

Image search with size, colour, and type filters

ddg_videos

Video search (aggregates YouTube, Bing Videos, etc.)

ddg_fetch

NEW — Fetch a URL and extract readable content (article body, headings, metadata). Uses trafilatura to strip navigation, ads, and boilerplate.

Every search tool supports region (e.g. us-en, uk-en, wt-wt), safesearch (on / moderate / off), time-limit filters, and a backend parameter to pick or force a search engine.

Related MCP server: Search Proxy MCP

Troubleshooting: searches fail on Render / Vercel / Heroku

Symptom: works locally, but deployed searches return errors like 403 Forbidden, 202 Ratelimit, or connection failures.

Cause: search engines — DuckDuckGo especially — routinely block or ratelimit requests from datacenter IPs. Managed platforms (Render, Vercel, Heroku, AWS, GCP…) egress from shared datacenter ranges that are frequently flagged. This is an IP-reputation problem, not a bug in the server.

Fixes, in order of effectiveness:

  1. Check what works from your host — hit the diagnostic endpoint:

    curl -H "Authorization: Bearer $MCP_API_TOKEN" \
         "https://ddg-search-mcp.onrender.com/status?category=text"

    It probes every engine (duckduckgo, brave, google, bing, …) with a 1-result query and reports ok: true/false plus a reason for each.

  2. Use a backend that isn't blocked. Every search tool takes a backend parameter — ask your AI client to retry with backend="bing" (news, images) or another engine reported ok by /status. You can also set a server-wide default with the DDGS_BACKEND env var. With the default backend="auto", the ddgs library already fans out across engines and uses whichever responds.

  3. Route egress through a proxy — set DDGS_PROXY (HTTP/HTTPS/SOCKS5, or "tb" for Tor). A residential or rotating proxy service makes requests look like home users and is the most reliable fix for blocked hosts.

  4. Don't deploy to Vercel. This is a long-running HTTP server; Vercel is serverless with short function timeouts and heavily-shared egress IPs — both the MCP transport and the search engines will misbehave. Use Render, Railway, Fly.io, or run it locally.

When a search fails, tools return a single-entry list with error, reason (e.g. ip_blocked, timeout, network), and a hint your AI client can read and relay — instead of an opaque stack trace.

Quick Start

# Install
pip install -r requirements.txt

# Run (no auth — local dev only)
python server.py

The server starts at http://localhost:10000.
MCP endpoint: http://localhost:10000/mcp
Health check: http://localhost:10000/health

Connect from AI Clients

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "ddg-search": {
      "type": "streamable-http",
      "url": "https://ddg-search-mcp.onrender.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "ddg-search": {
      "url": "https://ddg-search-mcp.onrender.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

VS Code / Copilot

Add to your MCP configuration:

{
  "inputs": [
    {
      "type": "mcp",
      "name": "ddg-search",
      "url": "https://ddg-search-mcp.onrender.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  ]
}

Deploy to Render

One-click with Blueprint

  1. Push this repo to GitHub.

  2. In the Render Dashboard, click New → Blueprint.

  3. Connect your repo — the included render.yaml auto-configures everything.

Render auto-generates an MCP_API_TOKEN. Find it under Dashboard → your service → Environment.

Manual deploy

  1. Push to GitHub.

  2. Render Dashboard → New → Web Service.

  3. Connect repo, set:

    • Build command: pip install -r requirements.txt

    • Start command: python server.py

    • Health check: /health

  4. Deploy.

After deploy, find your auto-generated token in Environment or generate one:

openssl rand -base64 32

Free plan & keep-alive

Render's free services spin down after 15 minutes of inactivity, causing 30–60s cold starts. This repo includes a GitHub Actions keep-alive cron (.github/workflows/keep-alive.yml) that pings the health endpoint every 10 minutes to prevent spin-down.

To enable it:

  1. Go to your repo on GitHub → Actions tab.

  2. Enable GitHub Actions (if prompted).

  3. The Keep Render Alive workflow runs automatically on the */10 * * * * schedule.

Note: GitHub Actions has a usage limit on free plans (2,000 minutes/month). This workflow uses ~4,500 minutes/year (~375 min/month) — well within the free tier. For guaranteed zero latency, upgrade to Render's Starter plan ($7/mo).

Environment Variables

Variable

Default

Description

PORT

10000

Server port

MCP_API_TOKEN

(none)

Bearer token for authentication (unset = no auth)

DDGS_TIMEOUT

10

Search request timeout in seconds

DDGS_PROXY

(none)

Proxy URL (http/https/socks5) or "tb" for Tor — use this when the host IP is blocked

DDGS_BACKEND

auto

Default search engine for all tools (auto, duckduckgo, bing, brave, …)

Diagnostic endpoints: GET /health (public, for platform health checks) and GET /status (auth-protected; probes every engine from the host — see Troubleshooting).

Architecture

┌──────────────────────────────────────────────┐
│  Starlette ASGI app                          │
│                                              │
│  ┌──────────┐  ┌──────────────────────────┐  │
│  │ /health  │  │ /mcp                     │  │
│  │ (no auth)│  │ (FastMCP Streamable HTTP)│  │
│  └──────────┘  │                          │  │
│                 │  ddg_search()            │  │
│  Middleware:    │  ddg_news()              │  │
│  • CORS        │  ddg_images()            │  │
│  • Auth (JWT)  │  ddg_videos()            │  │
│                 └──────────────────────────┘  │
└──────────────────────────────────────────────┘

Development

pip install -r requirements.txt
python server.py

Testing

pytest tests/ -v

Adding a new tool

See AGENTS.md for full conventions — the short version:

  1. Add a decorated function in server.py:

    @mcp.tool()
    def ddg_my_tool(query: str, max_results: int = 10) -> list[dict]:
        """Description for LLMs."""
        ddgs = _make_ddgs()
        results = ddgs.some_method(query=query, max_results=_clamp(max_results, 1, 50))
        return [_safe_result(r) for r in results]

    For web-fetch tools, use httpx + trafilatura (see ddg_fetch for the pattern).

  2. Add tests in tests/test_server.py.

License

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables web search capabilities using DuckDuckGo's free API without requiring authentication or API keys.
    -
  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables AI agents to search the web, find news, and read page content via DuckDuckGo without an API key.
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server that provides web search scraping from DuckDuckGo (with Mojeek fallback) and URL content fetching as markdown/text or raw HTML.
    1
    -
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for DuckDuckGo web search, enabling AI agents to perform real-time text, news, and image searches without an API key.
    3
    MIT