# DuckDuckGo MCP Server Model Context Protocol (MCP) server that exposes **DuckDuckGo** search as a tool for LLM clients (Claude Desktop, Cursor, VS Code, ...), backed by a self-hosted [SearXNG](https://github.com/searxng/searxng) metasearch instance. SearXNG aggregates results from DuckDuckGo, Google, Brave, Wikipedia, and more with its own request handling — no browser fingerprinting, no API keys, fully self-hosted. Part of the MCP Search Servers project: | Repo | What it is | |------|------------| | [google-mcp](https://git.jarianc.com/jarianc/google-mcp) | Same design for Google search | ## Service | Service | Port | MCP tool | Description | |------------------|------|--------------------|------------------------------------| | `duckduckgo-mcp` | 3002 | `duckduckgo_search`| DuckDuckGo results via SearXNG | | `searxng` | — | — | Internal metasearch engine (not published) | The server exposes: - `/sse` + `/messages/` — MCP SSE transport - `/search?q=...&num=N` — plain HTTP JSON endpoint - `/health` — liveness probe ## Quick Start ```bash cp .env.example .env # fill in SEARXNG_SECRET docker compose up -d --build ``` Generate a SearXNG secret: ```bash python3 -c "import secrets; print(secrets.token_hex(32))" ``` Verify: ```bash curl http://localhost:3002/health curl "http://localhost:3002/search?q=python&num=3" ``` Then point your LLM client at `http://localhost:3002/sse`. ## Tool Contract ```json { "name": "duckduckgo_search", "arguments": { "query": "Python programming language", "num_results": 5 } } ``` Returns numbered results with title, URL, and snippet (max 20 results, queries capped at 500 characters). ## Project Structure ``` . ├── duckduckgo-mcp/ # MCP server (SSE transport + tools) │ ├── server.py │ └── Dockerfile ├── lib/ # Shared search engine implementations │ ├── duckduckgo_search.py │ ├── google_search.py # also used by the google-mcp sibling repo │ ├── playwright_manager.py │ └── rate_limiter.py ├── searxng-settings.yml ├── test_client.py └── docker-compose.yml ```