
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
·
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
uvx duckduckgo-mcp-serverref:// tokens that fetch_content accepts directly, saving contextInstall from PyPI using uv:
uv pip install duckduckgo-mcp-server~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonAdd the following configuration:
Basic Configuration (No SafeSearch, No Default Region):
{
"mcpServers": {
"ddg-search": {
"command": "uvx",
"args": ["duckduckgo-mcp-server"]
}
}
}With SafeSearch and Region Configuration:
{
"mcpServers": {
"ddg-search": {
"command": "uvx",
"args": ["duckduckgo-mcp-server"],
"env": {
"DDG_SAFE_SEARCH": "STRICT",
"DDG_REGION": "cn-zh"
}
}
}
}Configuration Options:
DDG_SAFE_SEARCH: SafeSearch filtering level (optional)
STRICT: Maximum content filtering (kp=1)MODERATE: Balanced filtering (kp=-1, default if not specified)OFF: No content filtering (kp=-2)DDG_REGION: Default region/language code (optional, examples below)
us-en: United States (English)cn-zh: China (Chinese)jp-ja: Japan (Japanese)wt-wt: No specific regionDDG_CA_CERTS: Path to a PEM CA bundle used to verify TLS certificates on outbound requests (optional). Needed behind TLS-intercepting proxies — see Running behind a TLS-intercepting proxy.DDG_RATE_LIMIT_STRATEGY: sliding (default, historical 60s window) or token_bucket (burst, then smooth).DDG_SEARCH_RPM: Search requests per minute (default: 30).DDG_FETCH_RPM: Global fetch_content requests per minute (default: 20).DDG_FETCH_HOST_RPM: Optional per-host fetch cap (default: 0, off). Set a positive number to enable.DDG_CACHE_TTL: Seconds to keep a parsed page in the in-memory fetch_content cache (default: 300). Paginated reads of the same URL reuse one download. Set 0 to disable.DDG_CACHE_MAX_ENTRIES: Maximum pages kept in that cache (default: 64). Least-recently-used eviction. Set 0 to disable.DDG_PARSE_MODE: Default fetch_content extractor (text, main, or markdown). Default is text (historical flattened page). Per-call parse_mode overrides this.DDG_REF_URL_THRESHOLD: Search-result URLs longer than this many characters are replaced with short ref://<id> tokens (default: 120). Set 0 to always show full URLs. Also --ref-url-threshold.uvenv is installed and the uvx command is availableclaude mcp add ddg-search uvx duckduckgo-mcp-serverThe server supports alternative transports for use with other MCP clients:
# SSE transport
uvx duckduckgo-mcp-server --transport sse
# Streamable HTTP transport
uvx duckduckgo-mcp-server --transport streamable-httpThe default transport is stdio, which is used by Claude Desktop and Claude Code.
When running with sse or streamable-http, override the default bind address (127.0.0.1:8000) with the --host and --port flags:
uvx duckduckgo-mcp-server --transport streamable-http --host 0.0.0.0 --port 7070The MCP SDK enables DNS-rebinding protection for the HTTP transports and, by default, only accepts Host/Origin headers for localhost. Behind a reverse proxy or in a container the client's Host header won't match, so requests fail with 421 Misdirected Request.
Fix it by allow-listing the host(s) and origin(s) clients actually use (preferred over disabling protection). Values support host, host:port, and wildcard-port host:*:
uvx duckduckgo-mcp-server --transport streamable-http --host 0.0.0.0 --port 7070 \
--allowed-hosts ddg-mcp.example.com "ddg-mcp.example.com:*" \
--allowed-origins "https://ddg-mcp.example.com"Equivalent environment variables (comma-separated) are also available: DDG_ALLOWED_HOSTS, DDG_ALLOWED_ORIGINS.
As a last resort you can turn the check off entirely with --disable-dns-rebinding-protection (or DDG_DISABLE_DNS_REBINDING_PROTECTION=1). Prefer an allow-list — disabling protection removes a defense against DNS-rebinding attacks. When nothing is configured, the secure localhost-only default is preserved.
Corporate proxies that re-sign HTTPS traffic with their own CA (via HTTPS_PROXY) cause outbound requests to fail with certificate verification errors, because the HTTP clients don't trust the proxy's self-signed CA (and httpx no longer reads the SSL_CERT_FILE environment variable). Point the server at your proxy's CA bundle:
uvx duckduckgo-mcp-server --ca-certs /path/to/proxy-ca.pemOr set DDG_CA_CERTS=/path/to/proxy-ca.pem. The bundle is used by both the search and fetch_content tools, on the httpx and curl backends alike.
As a last resort, --no-ssl-verify (or DDG_SSL_VERIFY=0) disables certificate verification entirely. This exposes traffic to interception by anyone on the network path — prefer --ca-certs.
Some sites — and, as of recently, DuckDuckGo's own search endpoint (html.duckduckgo.com) — block the default httpx client because of its distinctive TLS fingerprint, regardless of User-Agent. Cloudflare Bot Management and similar filters key on the JA3/TLS handshake, not on headers, so html.duckduckgo.com may answer httpx with an empty HTTP 202 page (silently yielding "no results"). An opt-in backend, curl (implemented via curl_cffi), impersonates a real Chrome browser's TLS handshake and passes through those checks.
Both the search tool and the fetch_content tool support these backends.
Installation:
# Default install (httpx only)
uv pip install duckduckgo-mcp-server
# With the optional browser backend
uv pip install "duckduckgo-mcp-server[browser]"Backend options:
| Value | Behavior | Needs [browser] |
|---|---|---|
httpx | Lightweight async HTTP. Default. Works on most sites. | no |
curl | Uses curl_cffi with Chrome 131 TLS impersonation. Passes TLS-fingerprint-based filters. | yes |
auto | Tries httpx first; on 403 or a Cloudflare challenge response, retries with curl. | yes |
Two ways to configure the backend:
Server-wide default via the --fetch-backend CLI flag (applies to every fetch_content call):
# Default behavior — uses httpx
uvx duckduckgo-mcp-server
# Force curl for every fetch (requires the [browser] extra)
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --fetch-backend curl
# Try httpx first, fall back to curl on 403 / Cloudflare challenge
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --fetch-backend autoPer-call override via the backend argument on the fetch_content tool (overrides the CLI default for that single call). The tool exposes backend in its input schema, so an MCP client can choose "httpx", "curl", or "auto" on a fetch-by-fetch basis.
For fetch_content, the default stays httpx so users who don't need the impersonation don't pay for the extra dependency.
Because DuckDuckGo's search endpoint now fingerprint-blocks plain httpx, the search tool defaults to auto: it tries httpx first and falls back to curl when it detects a block (HTTP 202/403). The fallback only works if the [browser] extra is installed; otherwise search returns a message telling you to install it.
Configure the search backend with the --search-backend CLI flag or the DDG_SEARCH_BACKEND environment variable (auto (default) / httpx / curl):
# Recommended: install the browser extra so the auto fallback can impersonate Chrome
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server
# Force curl for every search
uvx --with "duckduckgo-mcp-server[browser]" duckduckgo-mcp-server --search-backend curl
# Opt out of the fallback (legacy behavior — may return no results while blocked)
uvx duckduckgo-mcp-server --search-backend httpxFor local development:
# Install dependencies
uv sync
# Run with the MCP Inspector
mcp dev src/duckduckgo_mcp_server/server.py
# Install locally for testing with Claude Desktop
mcp install src/duckduckgo_mcp_server/server.py
# Run all tests
uv run python -m pytest src/duckduckgo_mcp_server/ -v
# Run only unit tests
uv run python -m pytest src/duckduckgo_mcp_server/test_server.py -v
# Run only e2e tests
uv run python -m pytest src/duckduckgo_mcp_server/test_e2e.py -vasync def search(query: str, max_results: int = 10, region: str = "") -> strPerforms a web search on DuckDuckGo and returns formatted results.
Parameters:
query: Search query stringmax_results: Maximum number of results to return (default: 10)region: (Optional) Region/language code to override the default. Leave empty to use the configured default region.Region Code Examples:
us-en: United States (English)cn-zh: China (Chinese)jp-ja: Japan (Japanese)de-de: Germany (German)fr-fr: France (French)wt-wt: No specific regionReturns: Formatted string containing search results with titles, URLs, and snippets.
Example Usage:
search("python tutorial")search("latest news", region="jp-ja") for Japanese newsasync def fetch_content(
url: str,
start_index: int = 0,
max_length: int = 8000,
backend: Optional[str] = None,
parse_mode: Optional[str] = None,
) -> strFetches and parses content from a webpage.
Parameters:
url: The webpage URL to fetch content from, or a ref://<id> token from search resultsstart_index: Character offset to start reading from (for pagination)max_length: Maximum number of characters to returnbackend: Optional per-call override of the default fetch backend ("httpx", "curl", or "auto"). When omitted, uses whatever was set via --fetch-backend at server startup.parse_mode: Optional per-call extractor ("text", "main", or "markdown"). When omitted, uses DDG_PARSE_MODE / --parse-mode (default text).Returns:
Cleaned and formatted text content from the webpage. The parsed full page is cached in memory (default 5 minutes) so later pages via start_index do not re-download. Metadata includes cache=hit or cache=miss when the cache is enabled.
SSRF protection: By default
fetch_contentrefuses URLs that resolve to loopback, private (RFC1918), link-local (including the169.254.169.254cloud metadata endpoint), reserved, multicast, or unspecified addresses, and it re-validates every redirect hop. Onlyhttp/httpsURLs are allowed. For trusted local deployments that need to fetch internal hosts, disable the guard withDDG_ALLOW_PRIVATE_URLS=1or--allow-private-urls. See SECURITY.md for details.
async def expand_link(token: str) -> strSearch results replace URLs longer than DDG_REF_URL_THRESHOLD characters (default 120) with short, stable ref://<id> tokens so long tracking-laden links do not eat context. fetch_content accepts a token in place of a URL, so the model only needs this tool when it has to show or cite the real link.
Parameters:
token: A ref://<id> token exactly as it appeared in search results (the bare id also works)Returns: The full original URL, or an error if the token is unknown. Tokens live in memory for the lifetime of the server process (bounded by an LRU cap), so they are forgotten on restart.
DDG_SEARCH_RPM / --search-rpm)DDG_FETCH_RPM / --fetch-rpm)DDG_FETCH_HOST_RPM / --fetch-host-rpm)sliding (default) or token_bucket via DDG_RATE_LIMIT_STRATEGY / --rate-limit-strategyRetry-After (capped at 30s) and retry oncefetch_content skip both the download and the fetch rate limiterDDG_CACHE_TTL / DDG_CACHE_MAX_ENTRIES or --cache-ttl / --cache-max-entries0 to disablefetch_content accepts parse_mode:
| Mode | Behavior |
|---|---|
text | Historical default. Strip chrome, return flattened page text. |
main | Keep the primary article / main / content container only. |
markdown | Same primary content, rendered as lightweight markdown (headings, lists, links, code). |
SafeSearch Filtering: Configured at server startup via DDG_SAFE_SEARCH environment variable
kp parameterRegion Localization:
DDG_REGION environment variableIssues and pull requests are welcome!
This project is licensed under the MIT License.
Pick your client and paste the snippet. Each one is the same server, written the way that client expects it.
claude mcp add ddg-search -- uvx duckduckgo-mcp-server{
"mcpServers": {
"ddg-search": {
"args": [
"duckduckgo-mcp-server"
],
"command": "uvx"
}
}
}code --add-mcp '{"name":"ddg-search","args":["duckduckgo-mcp-server"],"command":"uvx"}'[mcp_servers.ddg-search]
command = "uvx"
args = ["duckduckgo-mcp-server"]Runs locally on your device. Your client starts the server itself, so nothing has to be hosted.
Paste this prompt into your agent. It reads this page and does the setup for you.
Read https://aiagentslisting.com/mcp/duckduckgo-mcp-server to learn what the "DuckDuckGo MCP Server" MCP server does and how to install it. Add it to my coding agent's MCP configuration as documented on that page, then confirm the server connects and list the tools it exposes.Agents can also browse this directory over MCP at https://aiagentslisting.com/api/mcp
uvx duckduckgo-mcp-server
uvx duckduckgo-mcp-server --transport sse
uvx duckduckgo-mcp-server --transport streamable-http
uvx duckduckgo-mcp-server --transport streamable-http --host 0.0.0.0 --port 7070
uvx duckduckgo-mcp-server --ca-certs /path/to/proxy-ca.pem
uvx duckduckgo-mcp-server --search-backend httpxThis server runs locally, so we can't read its tool list over the web yet.
Maintain this server? Claiming proves you own the listing and earns the last 4 points.
Claim this listingPaste this line near the top of your repository's README. The badge always renders the current score.
[](https://aiagentslisting.com/mcp/duckduckgo-mcp-server)The Elasticsearch MCP Server connects your AI agents to Elasticsearch data using the Model Context P
An MCP server implementation that integrates the Brave Search API, providing comprehensive search ca
v0.7.0Release notesv0.6.1Release notesv0.6.0Release notesv0.5.0Release notesv0.4.0Release notesv0.3.0Release notesConnect to the AI Agents Listing MCP server at https://aiagentslisting.com/api/mcp using the HTTP transport and complete the sign-in when it asks. Then call the submit_review tool for the listing "duckduckgo-mcp-server" with a rating from 1 to 5 and a short note on what worked and what did not.No reviews yet
Be the first to share your experience with this tool.
The Elasticsearch MCP Server connects your AI agents to Elasticsearch data using the Model Context P
Databases
An MCP server implementation that integrates the Brave Search API, providing comprehensive search ca
Search & Web
One email a week. New agents, MCP servers and skills, and what is actually getting traction.