keyless-web-search-mcp
keyless-web-search-mcp
スタンドアロンのMCP stdioサーバーです。鍵不要の2ツール、web_search(自己運用エンジンプール:Bing、360、Baidu、Google、Naver、Yandex、DuckDuckGo)と web_fetch(匿名HTTP(S)ページリーダー)を提供します。各検索では、有効なエンジンを最大2つまでに保ち、クエリ言語に応じてデフォルトの優先順位を振り分け、失敗したエンジンや無関係なエンジンを制限付きの試行予算内で補充し、結果を関連度でランク付けして統合し、正規URLで重複排除します。自己完結ディレクトリで、ビルドステップは不要、ハーネスのパッケージシステムには含まれません。どこへでも移動できます。
存在理由
ハーネス組み込みの web_search(DeepSeekプロバイダー)は DEEPSEEK_API_KEY を必要とし、すべてのクエリをDeepSeekクラウドに送信します。このサーバーはローカルモデル向けの代替です。鍵が不要で、ベンダー製検索APIも不要で、中国本土・香港のネットワークで動作します(中国本土回線ではBing/360/Baidu、検証済みの香港回線ではBing/360/Naver/Yandex。DuckDuckGoはこれらの回線のどれからも到達できません)。
web_fetch も、読み取り側では同じ理由で存在します。webプロファイルには検索プロバイダーはマウントされますが、フェッチプロバイダーはありません。そのため、組み込みの web_fetch ツールは(プリセットで有効化されても)毎回 WEB_PROVIDER_UNAVAILABLE で失敗します。このツールは、同じ鍵不要サーバーを通じてページの全文を読み取ります。
Related MCP server: web-search-mcp
実行
npm install --cache ./.npm-cache # deps: @modelcontextprotocol/sdk, zod
node index.js # speaks MCP over stdio
npm test # run deterministic ranking/fallback testsクライアントなしのクイックプローブ:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| node index.jsClaude Code へのインストール
現在のユーザーにインストールして、すべてのClaude Codeプロジェクトから使えるようにします。サーバー登録時には両方のパスを解決してください。これにより、シェルの作業ディレクトリや後からの PATH に依存しなくなります:
claude mcp add --transport stdio --scope user web-search-self -- "$(command -v node)" "/absolute/path/to/keyless-web-search-mcp/index.js"
claude mcp get web-search-self代わりに --scope local を使うと現在のプロジェクト内だけに限定でき、--scope project を使うと共有可能な .mcp.json に書き込めます。Claude Codeはユーザー/ローカル登録を ~/.claude.json に保存します。MCPサーバー定義は settings.json に置くべきではありません。
登録後、claude mcp list が web-search-self を接続済みとして報告するはずです。ツールは mcp__web-search-self__web_search と mcp__web-search-self__web_fetch として表示されます。
ツール
web_search
web_search({ query, count?, maxSources?, engines? })
パラメーター | デフォルト | 意味 |
| — | 検索クエリ。任意の言語 |
|
| 統合結果の最大数(1〜20) |
|
| 検索ごとに使えるエンジンの最大数(上限は2。フォールバック試行は制約された範囲内) |
| クエリ言語依存 | 優先順位付きの明示的なプール(任意)。省略時は、中国語・韓国語・日本語・ロシア語のクエリに対して地域に適した優先順位を使用 |
2ソースポリシー。 engines が省略された場合、プールはクエリ言語で振り分けられます。中国語は360/Baidu/Bing、英語はBing/Google/Naver/360から始まるため、検証済みの中国本土/香港ネットワークでも、4回の試行予算の中で動作するフォールバックを維持できます。明示的な engines リストは常に優先されます。候補は並列ラウンドで実行され、エンジンがソーススロットを消費するのは、パースできて保守的な語彙的関連性フィルタを通過した結果を返したときに限ります。失敗したエンジン、チャレンジされたエンジン、空結果のエンジン、無関係なエンジンは、試行予算と収集予算の範囲内で補充され、診断は "Engine note" 行に表示されます。結果はクエリとの重なりに加えて、ソース品質の小さな調整を加えてランク付けされます。明らかな転載・コンテンツファームの兆候は減点され、公式・ドキュメント・教育・GitHub の兆候は加点されますが、通常のサイトを強制的にブロックすることはありません。マージはラウンドロビン交互(エンジンAの1番目、エンジンBの1番目、Aの2番目、...)のままであり、正規URLの重複排除により、フラグメント、一般的な追跡パラメータ、安全な www. の違いを除去します。
結果:title [engine] / 実際の転送先URL / スニペットの番号付きリスト。リンクのクリーンアップはエンジンごとに実行します。Bingのクリックトラッカーリンクはローカルでデコード(base64 u パラメータ)。360は data-mdurl 属性を読み、Baiduはブロックの mu 属性を読みます(直接URLですが、レガシー link?url= ラッパーの場合のみ1回だけベストエフォートのリダイレクトGETを行います)。NaverとYandexのタイトルはアンカー内の直接URLを保持します。Googleの /url?q= ラッパーは展開されます。DuckDuckGoの /l/?uddg= トラッカーは展開されます。エンジンごとのプローブ予算は、Bing・Baidu が10秒、360・Naver・Yandex が8秒、Google・DuckDuckGo が5秒です。すべて並列で実行されるため、ラウンド全体の所要時間は最も遅いメンバーの処理時間になります。
web_fetch
web_fetch({ url, maxChars? })
パラメーター | デフォルト | 意味 |
| — | 絶対 |
|
| 返すコンテンツの最大文字数(1000〜100000) |
匿名でのパブリックWeb読み取りです。認証なし、ブラウザーのUser-Agent、リダイレクトは最大5回、ヘッダーとボディを含め壁時計で20秒の制限内です。レスポンスボディは正確に5MBで切り詰めます。DNS解決後、最初のURLとリダイレクト先のすべてをチェックし、ループバック・プライベート・リンクローカル・キャリアグレードNAT・予約済みアドレス・マルチキャスト・ローカルホスト名を拒否して、マシンやクラウドメタデータサービスへのSSRFを防ぎます。HTMLは表示可能テキストに削られ(script/style/noscript/svg/head/iframe/canvas/form は削除し、ブロック境界は改行にし、<title> はヘッダーに残します)。テキスト型・JSON型・XML型のメディアタイプは、宣言された文字セットを使ってエンティティデコードされて通ります。バイナリ系メディアタイプは拒否されます。出力は、status、リダイレクト後の最終 url、content-type、切り詰め情報をはじめとするステータスヘッダーと、その後に続くコンテンツ本体です。2xx以外の応答は、本体冒頭と注記(403/429はボットチェックまたはペイウォールと解釈)を返します。捏造されたページを返すことはありません。
エンジンとその状態
2026年7月に、3つの回線(中国本土回線、上海電信回線、香港Zenlayerデータセンター回線)から検証しました:
Engine | Endpoint | これらのネットワークからのステータス |
|
| ✅ 両回線で~10個のオーガニックブロック。回線によっては、 |
|
| ✅ クリーンな200;オーガニックブロックは |
|
| 到達可能(200)だが、このクライアント/IPはプレーンHTMLのSERPに対して信頼されていない:ボディはオーガニック結果がゼロの、JS無効の |
|
| ✅ 上海と香港の回線で:リスクコントロールがスクリプト形状のリクエストをゲートする(クッキーに関係なくUAのみの302で |
|
| ✅ HK回線で(200、~10個の |
|
| ✅ HK 回線で:Baidu と同じナビゲーションシグネチャの教訓 — スクリプト形状のリクエストは SmartCaptcha の「ロボットではありません」チェックボックスを受けるが、完全なドキュメントナビゲーションヘッダーセットに加えてホームページのクッキーセッション(yandexuid など)があれば、プレーンHTMLのSERP(~50個の |
|
| ❌ テストした3つの回線すべて(HKを含む)でTCP到達不能;それが機能するネットワークのための最後の手段エンジン |
意図的にプールに含めていない:Sogou — sogou.com/antispider/ に302リダイレクト、Baidu がカバーするのと同じIP壁クラス。また、HK 回線からスキャンして拒否されたもの:Mojeek(キャプチャページを提供)、Ecosia(403「Ecosia Firewall」)、MetaGer(非結果ページにリダイレクト)、および Yahoo/Brave/Qwant/Startpage/goo.ne.jp(本土とHKの両方の回線からTCP到達不能)。
Google の壁:試みられたこと
このIPからの200応答はブロックではなく、JSチャレンジインタースティシャル(~90 KBの難読化/暗号化されたJavaScript;JS無効パスはメタリフレッシュで行き止まりになる)。壁は2層であることが判明:
JSチャレンジ(計算) — デコードすると、証明値を計算して
SG_SSクッキー(5分の有効期限)を設定し、リロードする。この層はブラウザ外で解決可能:プレーンなNode.jsでページのスクリプトを軽量なDOMシム(クッキージャー、navigator、Image、document)で実行すると計算が完了し、結果のSG_SSクッキーが一度受け入れられた — Google は200で応答し、このIPには通常送信しないNID/AECトラストクッキーを発行した。セッションパターン層(行動) — その後のプレーンHTTPフォローアップ(スクリプト自身のリロードフローの正確なレプリカ(
emsg=SG_REL+ 一致するsei、ジャー統合クッキー、ブラウザヘッダー)を含む)は、google.com/sorry429 異常壁にエスカレーションする。この層はセッション全体(TLS/HTTP2フィンガープリント、リクエストペーシング、メソッドミックス)を判断するが、Node の OpenSSL/undici スタックはそれに一致しない。
テストされ、層1の回答を変更しなかったクライアント側のレバー:gbv=1 パラメータ、クッキーのウォームアップ、完全なブラウザフィンガープリントヘッダー、retry/enablejs フロー、/m エントリ、テキストブラウザ/フィーチャーフォン/IE6/旧Android UA、偽装された Googlebot UA(Google はそれを検証する)、CONSENT クッキー、POST送信(405)、代替TLD、およびクッキーなしの「ここをクリック」 emsg=SG_REL リンク。Google プロキシの代替もこのネットワークからは到達不能または壁に遮られた:Startpage と Qwant はタイムアウト、Mojeek はキャプチャページを提供、Ecosia は403。
結論:層1はNodeで解決可能(実証済み);層2は非ブラウザネットワークスタックからは解決不可能。このマシンから Google への信頼できる唯一の経路は、クリーンIPプロキシまたは実際のブラウザコンテキスト(ヘッドレス Chromium)である;どちらもスクレイパーが正直に議論できない同じIP/トラフィックパターン層にあり、繰り返しのプロービングはIPの異常ウィンドウを延長するリスクがある — そのためこのサーバーはそれらを試みない。Google は、プレーンHTMLのSERPを提供するネットワークでアクティブになるバックフィルエンジンとして残る。
DeepSeek ハーネスへのマウント
cordis.yml に追加する(MCPブリッジはこのエントリをホットリロードする):
- id: mcp-search
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: search
transport: stdio
command: node
args: ['/absolute/path/to/keyless-web-search-mcp/index.js']モデルはその後、ツールを mcp__search__web_search と mcp__search__web_fetch として見る。
制限事項
検索品質はヒューリスティック:語彙的関連性は明らかなオフトピック結果と中国語のn-gramを処理する;内部検索エンジンページは除外される;コンテンツファーム/再投稿シグナルは順序を調整するだけで、普遍的な信頼判断ではない。関連する結果がその主張が正しいことを証明するものではない — 重要な事実はフェッチしてクロスチェックすること。
APIではなくスクレイピング:レイアウトの変更がパーサーを壊す可能性がある;失敗は明確(「パース可能なオーガニック結果がない」)であり、決して捏造されない。Google と DuckDuckGo のパーサーは文書化されたSERP構造から書かれており、このネットワークからはライブ検証できない — エンジンが実際に応答する最初の機会にそれらを調整する。
レート制御:両方の公開エンジンはカジュアルな使用を許容する;ハンマリングはボットチャレンジを引き起こす。
クエリはマシンを離れる(キーレス検索の代償);2ソースキャップにより、検索ごとに最大2つのエンジンがクエリを見る。
フェッチはキーレスの公開ページリーダーであり、ブラウザやイントラネットクライアントではない:JSレンダリングされたコンテンツはそれには見えない(検索パーサーと同じクラスの制限);匿名クライアントに403/429を返すページは報告され、バイパスされない。ローカル/プライベート/予約済みネットワークターゲットは、リダイレクト先を含めて意図的にブロックされる。
Available Tools
2 toolsweb_fetchWeb Fetch (keyless anonymous HTTP(S) reader)A
Fetch one HTTP(S) URL anonymously and return the page as readable text: HTML is stripped to visible text with block structure preserved; text/markdown/JSON/XML pass through decoded. No credentials: browser User-Agent, up to five validated redirects, bounded output. Local, private, link-local, and reserved network targets are blocked, including after DNS resolution and redirects. The result is a status header (status code, final URL, content-type, truncation) followed by the content. Use it to read full page content for a URL, e.g. one found by web_search.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL to fetch. | |
| maxChars | No | Maximum content characters to return (default 20000, hard cap 100000). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full responsibility. It discloses anonymous access, no credentials, browser User-Agent, redirect limits, target blocking, and truncation behavior, which is strong transparency for a network tool.
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 purposeful sentences: main behavior, safety boundaries, and output/usage context. No filler, no redundant schema echoing, and key constraints are front-loaded.
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?
With no output schema or annotations, the description still explains output format, status header components, redirects, target restrictions, and content conversion. This is an unusually complete one-paragraph contract for a fetch tool.
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?
The schema already clearly documents both parameters at 100% coverage, with maxChars including a default and limits. The description affirms bounded output but does not add substantial meaning about parameter formats beyond the schema.
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, resource, and output: fetches one HTTP(S) URL and returns readable text. It also references web_search, making the distinction between search and fetch explicit without ambiguity.
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?
Description explicitly says to use it to read page content for a URL and gives a web_search output as an example, naming the sibling tool. It does not explicitly state when not to use it, so it stops short of a full when/when-not map.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
web_searchWeb Search (self pool: Bing / 360 / Baidu / Google / Naver / Yandex / DuckDuckGo)A
Search the web without any API key from a self-operated pool: Bing, 360, Baidu, Google, Naver, Yandex, and DuckDuckGo. Each search keeps at most two usable engines — the pool is routed by query language when no explicit pool is given, failed or irrelevant engines are back-filled within a bounded attempt budget, and results are relevance-ranked, quality-adjusted, and deduplicated by canonical URL. Each result includes a title, the real destination URL, a snippet, and its engine. Engines unreachable from the local network, or walled by captcha/JS/bot checks, are skipped and reported in an engine note; the remaining engines still answer.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Maximum merged results to return (default 8). | |
| query | Yes | Search query in any language. | |
| engines | No | Optional explicit engine pool in priority order; omitted uses query-language routing. | |
| maxSources | No | Maximum usable engines per search (default 2, hard cap 2; fallback attempts are bounded). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly discloses behavioral details: no API key needed, engine pool self-operated, at most two usable engines, back-fill on failures, relevance/quality ranking, deduplication, skipping unreachable or walled engines, and reporting an engine note. This exceeds the baseline and compensates for the absence of annotations. No contradiction with annotations since none are provided.
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 concise and front-loaded with the primary purpose (search the web without API key) and then provides relevant behavioral details in a structured manner. Each sentence adds value; it is not overly verbose. Slight redundancy with the engines list in the title but overall well-structured.
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?
The description covers key aspects: purpose, engine selection, failure handling, result format, and edge cases (captcha/JS/bot walls). No output schema exists, but the description mentions what each result includes (title, URL, snippet, engine), which partially compensates. The absence of annotations is mitigated by the detailed description. Minor gaps remain about the return structure of the full response, but the information is sufficient for an agent to invoke the tool correctly.
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?
The input schema already has complete (100% coverage) descriptions for all four parameters: count, query, engines, and maxSources. The description adds contextual insight on routing by query language and back-fill behavior but does not add substantial new parameter semantics beyond what the schema provides. Per the guideline, high schema coverage means baseline 3 is appropriate.
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?
The description clearly states the tool performs a web search using a self-operated engine pool, listing the supported engines and the result characteristics (title, URL, snippet, engine). It does not explicitly contrast with the sibling tool web_fetch, but the purpose is distinct and clear.
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?
The description explains how the engine pool is selected (query-language routing when no explicit pool), how failures are handled (back-filling, bounded attempts), and how results are ranked and deduplicated. It does not explicitly state 'when to use' versus 'when not to use' but provides contextual routing guidance. The sibling tool web_fetch is not referenced, so no alternative routing is mentioned.
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
v1.1.0- First observed
web_fetch - First observed
web_search
TDQS
Scored across 2 tools
The two tools are completely distinct: web_search performs web searches across multiple engines, while web_fetch retrieves the content of a specific URL. There is no overlap or ambiguity between them.
Both tool names follow the same verb_noun pattern: web_search and web_fetch. The naming is clear, consistent, and predictable.
The server has only two tools, which is slightly below the typical well-scoped range of 3-15. However, each tool is essential and covers the core functionality of keyless web search and fetching, so the count is reasonable for the narrow scope.
The tool surface fully covers the stated purpose of keyless web search: web_search finds relevant results and web_fetch retrieves full page content. There are no obvious missing operations for this domain.
Maintenance
Related MCP Connectors
Google, Bing, DuckDuckGo and Google Maps search results, free without an API key.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Keyless web, GitHub, YouTube and Reddit search and read. Delegated shop, booking and signup.
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables web search without API keys using DuckDuckGo and Bing search engines, and retrieves webpage content. Supports multiple search engines simultaneously with privacy protection and asynchronous processing.263 PyPI10MIT
- FlicenseNot gradedqualityDmaintenanceProvides free web search, content fetching, image search, and deep research via SearXNG, no API keys required.-
- AlicenseAqualityCmaintenanceEnables keyless multi-engine web, news, image, and video metasearch plus full-page markdown extraction for AI agents over MCP, with resilient fallback across DuckDuckGo, Bing, Brave, Google, and other backends.6MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to perform free web search and read web pages as markdown without paid APIs, Docker, or a background service, by querying multiple free search engines in parallel with optional fallbacks and extracting clean page content. Also supports fetching a site's llms.txt documentation files.MIT