ddg-search
ddg-search
単一障害点を持たないことを拒否するDuckDuckGo検索MCPサーバー。 1つのプロセス、多数のバックエンド、自動フェイルオーバー、正直なエラーメッセージ。
アイデア
ウェブ検索はコーディングエージェントにとって基幹インフラであり、退屈な形で失敗します。レート制限、ボット検出、VPSプロバイダーの一時的な障害など。ほとんどのサーバーはHTTPクライアントを1つ持って祈るだけです。このサーバーは各クエリを複数のバックエンド(このマシン上のローカル検索エンジンに加えて、実行している任意の数のリモートduckduckgo-mcp-serverインスタンス)にルーティングし、何かが応答するか予算が尽きるまで試行を続けます。
失敗したバックエンドはタイムアウトになります。正常に動作するバックエンドはより多くのトラフィックを受け取ります。結果は1つのコンパクトなブロックとして、誰が提供したかの1行のメモ付きで届きます。
Related MCP server: DuckDuckGo Search MCP Server
インストール
Python 3.10+とuvが必要です。
git clone <this repo> ~/.local/share/mcp/ddg-search # or anywhere you like
cd ~/.local/share/mcp/ddg-search
uv syncこれで儀式はすべて終わりです。uv syncは.venvを作成し、依存関係をロックし、パッケージを編集可能モードでインストールするため、src/への編集は再起動時に反映されます。
エージェントに接続する
stdioを話すMCPクライアントならどれでも動作します。mcp.jsonスタイルの設定の場合:
{
"mcpServers": {
"ddg-search": {
"type": "stdio",
"command": "/path/to/ddg-search/.venv/bin/python",
"args": ["-m", "ddg_search.server"],
"env": {
"DDG_SAFE_SEARCH": "OFF",
"DDG_SEARCH_BACKEND": "auto"
},
"timeout": 60000
}
}
}DDG_SAFE_SEARCHはコンテンツフィルタリングのみです。ボット検出には何の効果もなく、リサーチを行うエージェントは想起率を求めており chaperone を求めていないため、デフォルトではオフです。
ツール
search
引数 | 型 | デフォルト | 備考 |
| string | 必須 | 曖昧な1語の雰囲気より正確な名詞の方が良い |
| int | 10 | 上流は関係なく約10〜11で上限 |
| string |
| DuckDuckGoのリージョンコード |
|
|
| 手動はヘルスソートをスキップ |
| string |
| 1つのバックエンド名/エイリアス/IP(手動モード) |
| list |
| 順序付きフォールバックチェーン(手動モード) |
結果は意図的にコンパクトに返されます:
via relay-b
3 results:
1. Some Page Title
https://example.com/page
The snippet text, labels stripped, no blank lines eating your tokens.
2. ...すべての応答はどのバックエンドが提供したかを示します。失敗した試行はAttempts:の下に、どこで壊れたかを示すタグ付きでリストされます:
タグ | 意味 |
| DuckDuckGoがゼロ件のマッチを返した — ここからは区別できない、本当の結果なしまたはボットによる空応答 |
| このマシンのクライアントが失敗した。リモートホストのせいにしないでください |
| リモートが不正な応答をした |
| 待機中に25秒の予算を使い切った |
問題が発生したとき、ログパスが得られます
ルーターは「インターネットがいつものように振る舞っている」ことと「このツールが実際に壊れている」ことを区別します。タイムアウトと空の結果セットは単に[タグ]が付くだけです。しかし、試行がこちら側の壊れ方を意味する形で失敗した場合 — ローカル転送エラー、リモートバックエンドの不正な応答など — 応答は次のように終わります:
log: /path/to/ddg-search/logs/20260822T090206-remote-tool-error.jsonそのファイルには、再生と診断に必要なすべてが含まれています。正確なクエリと引数、失敗の詳細を含むすべての試行、およびその時点のバックエンドごとの状態のスナップショットです。必要に応じてDDG_SEARCH_LOGS_DIRを別の場所に指定してください。ログはタイムアウトや空の結果では決して書き込まれません。
status
バックエンドのテーブル: オンラインフラグ、この1分間の観測された試行数、最後のステータス、クールダウン期限。probe: trueを渡すと、キャッシュされた状態を信頼する代わりに実際にリモートバックエンドにpingを送信します。
設定
環境変数、すべてオプション:
変数 | デフォルト | 目的 |
|
|
|
|
| ローカル転送: |
|
| クエリごとの全バックエンドにわたる合計予算 |
|
| バックエンドごとのタイムアウトペナルティ |
|
| バックエンドごとのエラーペナルティ |
|
|
|
|
| ルーターの状態ディレクトリ |
バックエンドはsrc/ddg_search/config.pyにあります。デフォルトのフリートはlocal(このマシン)に加えて2つのリモートリレーです。自分のインフラに合わせてタプルを編集してください。
知っておくべき動作
フェイルオーバーは、最近の試行が最も少ない健全なバックエンドを優先するため、トラフィックが1台の貧弱なボックスに集中するのではなく分散されます。
クールダウンはバックエンドごとで時間制限付きです。タイムアウトはバックエンドを90秒間休ませ、ソフト障害は30秒間休ませます。1回の成功で即座にリセットされます。
状態は
state/router-state.jsonに再起動後も保持されます。記憶喪失にしたい場合は削除してください。サーバーは次回起動時に再作成します。
1つの癖には専用の段落が必要です。DuckDuckGoは信頼しないクライアントに空のページを提供するため、「結果なし」は本当にマッチがないか、静かなボットフラグのどちらかを意味します — ルーターはそれらを区別できず、区別できるふりもしません。空を失敗として扱い、次のバックエンドを試します。すべてのバックエンドが空で返ってきた場合は、その曖昧さを正確に説明するバナーが表示されます。
最後に: 30リクエスト/分の上限は、ここではなく各duckduckgo-mcp-serverインスタンスによって強制されます。ルーターはバックエンド間で負荷を分散しますが、フリートが持っていない容量について嘘をつくことはありません。
独自のリレーを実行する
標準サーバーを実行できる任意のマシンがバックエンドとして機能します:
pip install 'duckduckgo-mcp-server[browser]'
python -m duckduckgo_mcp_server.main --transport streamable-http --host 0.0.0.0 --port 18082BackendConfig(url="http://that-host/ddg-mcp")をそのマシンに向けます。realip/ディレクトリには、systemdユニットがmullvad-excludeの背後で住宅用IP上でそのような出口を1つ実行するために使用するランチャーが含まれています — データセンターの出口が自宅の接続よりもひどいCAPTCHA処理を受ける場合に便利です。
開発
uv sync # install everything including dev tools
uv run pytest # 26 tests, no network needed except one optional live check
uv run ruff check src tests # lint
uv run ruff format src tests # format
uv run pyrefly check # static types完全なルーターを通した簡単な手動スモークテスト:
uv run python -c "import asyncio; from ddg_search.router import SearchRouter; \
print(asyncio.run(SearchRouter().search('crawl4ai', 3, '', 'auto', None, None, None)))"関連項目
fast-webfetch-mcp — もう半分: これらの検索が見つけたURLをローカルのCrawl4AIブラウザ経由で開く
Model Context Protocol — 「MCP」の意味
duckduckgo-mcp-server — 実際のスクレイピングを行う検索ライブラリ
ライセンス
MIT。
Available Tools
2 toolssearchA
Search DuckDuckGo via ddg-search (local + remote backends). Discovery only — titles/URLs/snippets, not page proof. Then open promising URLs with fast-webfetch. Routing: auto = healthy low-use backends; manual = target/targets. On failure, read Attempts tags: [empty] = DDG no matches; [local]/[local-transport] = this machine (do not assume remote VPS missing packages); [remote-rpc]/[remote-tool-error] = remote answered badly; [timeout] = real wait timeout.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | DuckDuckGo query. Prefer exact nouns, error strings, version, site/domain, or API names. Avoid vague one-word searches. | |
| region | No | DuckDuckGo region code. Empty = default/global. | |
| target | No | Manual mode: single backend name, alias, or IP. Empty = all backends. | |
| targets | No | Manual mode: ordered backend names/aliases/IPs. Combined with target; duplicates ignored. | |
| route_mode | No | 'auto' for normal failover; 'manual' only when targeting specific backend(s). | auto |
| max_results | No | Max results. Use 5-10 normally; raise when the first page looks noisy. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden. It discloses the local+remote backend split, that it's read-only discovery, and decodes error tags to distinguish local vs remote failures. It does not mention rate limits, caching, or concurrency behavior, but for a search tool it covers the most critical operational behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense paragraph, but every sentence adds value: purpose, follow-up action, routing modes, and failure decoding. It is slightly long but not verbose; front-loads the core purpose before details. Could be improved with bullet points but is acceptable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 6 parameters (1 required), an output schema exists (not shown), and helper sibling 'status', the description covers all necessary operational context: what it returns (titles/URLs/snippets), when to use each route mode, how to interpret failures, and the follow-up tool (fast-webfetch). Nothing essential is missing—an agent could call this tool correctly without further clarification.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% so baseline is 3. The description does not add meaning beyond the schema; it repeats the routing guidance already in route_mode and the query tips already in the query parameter. The extra notes about backend combinations and error tags are behavioral rather than parameter-specific, so no increment.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Search DuckDuckGo via ddg-search'. It clearly delimits scope with 'Discovery only — titles/URLs/snippets, not page proof', distinguishing it from follow-up fetch tools and giving an agent an unambiguous sense of what it returns and what it does not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit routing rules: 'auto = healthy low-use backends; manual = target/targets' and tells when to use manual mode. It also instructs on failure interpretation: 'read Attempts tags' with specific meanings for [empty], [local]/[local-transport], [remote-rpc]/[remote-tool-error], and [timeout]. This is actionable when-to-use and how-to-handle guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusA
Show ddg-search backend router status (health, cooldowns, last errors). Optional probe pings backends. Use after search failures; if last_error is local/transport, fix the workstation ddg-search process before remote packages.
| Name | Required | Description | Default |
|---|---|---|---|
| probe | No | If true, probe backends before reporting. | |
| target | No | Optional single backend name/alias/IP. | |
| targets | No | Optional ordered backend names/aliases/IPs. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses that probe pings backends, but doesn't detail what the probe does when failures occur or the exact output structure. It does mention cooldowns and last errors as return content, which is useful. There's no contradiction with annotations since none exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: purpose, key optional behavior, and usage context. Front-loads the main purpose and then adds actionable guidance. No wasted words—every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists (not described in detail but signaled), the return value structure need not be explained. Tool complexity is moderate (3 optional params, one boolean). The description explains when to use it and what to check for. It could mention what happens if probe=true and backends fail, but since it focuses on diagnostics, this is adequate. Sibling 'search' is the only other tool, and status is clearly distinct.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with 'probe', 'target', and 'targets' all described in the schema. The description mentions 'Optional probe pings backends' which aligns with the probe field but doesn't add much beyond the schema. It also implies target/targets are optional, consistent with schema defaults. Baseline 3 applies since schema already documents parameters fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb ('Show') and resource ('ddg-search backend router status'). Distinguishes itself from sibling 'search' by explicitly targeting the router health, cooldowns, and errors—a diagnostic role that search does not play.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when to use it ('after search failures') and gives a conditional directive ('if last_error is local/transport, fix the workstation...'). Doesn't explicitly rule out other scenarios, but provides useful decision context. Sibling 'search' is clearly the alternative primary action tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.2.0- First observed
search - First observed
status
TDQS
Scored across 2 tools
Search and status have completely distinct purposes: one performs queries, the other reports backend health. There is no overlap or ambiguity between them.
Both names are short, lowercase, and clear. Search is a verb while status is a noun, which is a minor stylistic deviation but not confusing.
With only two tools, the set feels minimal. However, the server's scope is narrow and the two tools cover its core responsibilities, so the count is reasonable if sparse.
The server covers search and backend status monitoring, and explicitly delegates page fetching to another tool. Minor gaps exist (e.g., no configuration or backend management), but the stated surface is fully supported.
Maintenance
Related MCP Connectors
Search the agentic web. 4,100+ sites, 11 tools incl. check_url + verify_mcp for probe-before-use.
Serper MCP — wraps the Serper Google Search API (serper.dev)
Web MCP: scrape/crawl sites, web search, brand assets, app stores, YouTube, Reddit, Hacker News.
Scrape, crawl and search the web for AI agents via MCP.
Related MCP Servers
- AlicenseAqualityFmaintenanceProvides web search functionality via DuckDuckGo for Claude Code and MCP-compatible clients, featuring advanced content exploration, navigation across search results, and detailed webpage analysis.317MIT
- FlicenseNot gradedqualityCmaintenanceBrings DuckDuckGo search (web, news, images, videos) to any MCP-compatible AI client without requiring an API key.-
- AlicenseAqualityBmaintenanceMCP server for DuckDuckGo web search, enabling AI agents to perform real-time text, news, and image searches without an API key.3MIT
- AlicenseNot gradedqualityDmaintenanceProvides keyless, privacy-focused web search through DuckDuckGo and SearxNG via MCP, with token-efficient tool discovery and caching.MIT