loading…
Search for a command to run...
loading…
Web search using DuckDuckGo
Web search using DuckDuckGo
PyPI version PyPI downloads Python versions
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
uvx duckduckgo-mcp-server
Install 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 regionuvx 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-http
The 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 7070
Some sites 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. An opt-in backend, curl (implemented via curl_cffi), impersonates a real Chrome browser's TLS handshake and passes through those checks.
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 auto
Per-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.
The search tool always uses httpx — DuckDuckGo's search endpoint doesn't require impersonation.
The default stays httpx so users who don't need the impersonation don't pay for the extra dependency.
For 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 -v
async def search(query: str, max_results: int = 10, region: str = "") -> str
Performs 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,
) -> str
Fetches and parses content from a webpage.
Parameters:
url: The webpage URL to fetch content fromstart_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.Returns: Cleaned and formatted text content from the webpage.
SafeSearch Filtering: Configured at server startup via DDG_SAFE_SEARCH environment variable
kp parameterRegion Localization:
DDG_REGION environment variableIssues and pull requests are welcome! Some areas for potential improvement:
This project is licensed under the MIT License.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"nickclyde-duckduckgo-mcp-server": {
"command": "npx",
"args": []
}
}
}