MCP Retrieval について
mcp-retrievalはGo製のMCPサーバーで、MCPクライアントに読み取り専用のウェブ検索、画像検索、ページ取得を提供します。APIキーは不要で、検索結果と抽出したページ本文を構造化データやMarkdownで返します。
主な機能
- 01DuckDuckGo Liteによるウェブ検索
- 02Bing Imagesによる画像検索
- 03ページ本文の取得とMarkdown変換
- 04クエリとURL取得の並列実行
- 05stdioまたはストリーミングHTTPに対応
活用シーン
- 01LLMの回答に使うウェブ情報の検索
- 02クエリに関連する画像の検索
- 03ウェブページから記事本文を抽出
- 04ローカルまたはリモートのMCPクライアントに検索機能を提供
MCP 対応
ウェブ検索、画像検索、ページ取得の3種類の読み取り専用ツールをMCPクライアントに公開します。同じツール一式をstdioとストリーミングHTTPで利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ghcr.io/role1776/mcp-retrieval:0.1.10stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
mcp-retrieval
LLM に 3 つのウェブツール(検索、画像検索、ページのスクレイピング)を提供する MCP サーバーです。API キーは不要です。
ツール · クイックスタート · 設定 · 検索エンジン · アーキテクチャ · コントリビューション
概要
mcp-retrieval は、Go で記述された Model Context Protocol サーバーです。ウェブ検索機能を、MCP 対応クライアント(Claude Desktop、IDE エージェント、カスタム LLM アプリ)向けに、読み取り専用の 3 つのツールとして提供します。内部では retrieval-go ライブラリを使用してウェブを検索し、ページを取得します。結果は、モデルにそのまま渡せる整形済み Markdown として返されます。
このライブラリに API キーは不要です。ウェブ検索には DuckDuckGo Lite、画像検索には Bing Images を使用し、ページ取得では HTML を読みやすさ抽出器に通してから Markdown に変換します。ボット対策の影響を受けにくくするため、TLS レベルで実際のブラウザーになりすまし、ブラウザーのフィンガープリントとプロキシの両方を切り替えられます。詳しくは検索エンジンをご覧ください。
MCP SDK がサポートする 2 種類のトランスポートを利用でき、どちらも同一のツールセットを提供します。
- stdio — クライアントがバイナリを起動し、stdin/stdout 経由で通信します(デフォルト。デスクトップクライアントに最適です)。
- http — 長時間稼働するストリーミング可能な HTTP サーバーです(リモート環境や共有環境へのデプロイに便利です)。
ツール
| ツール | 説明 |
|---|---|
web_search | 1 件以上のクエリを並列に実行し、クエリごとに重複を除去して再ランク付けしたスニペットとリンクを返します。 |
web_search_images | 1 件以上の画像クエリを並列に実行し、クエリごとに重複を除去した画像検索結果を返します。 |
web_scrape | 1 件以上のページを並列にダウンロードし、本文を Markdown として返します。 |
3 つのツールはすべて 読み取り専用 として注釈されています。各ツールは出力スキーマに合致する構造化 JSON ペイロードを返します。SDK は、structuredContent を読み取らないクライアント向けに、同じ JSON をテキストコンテンツブロックにも反映します。
web_search
| パラメーター | 型 | デフォルト | 備考 |
|---|---|---|---|
queries | []string | — | 必須。 並列に実行されます。 |
max_results | int | 5 | クエリごとのスニペット数。max_results 設定値(20)が上限です。 |
timeout_ms | int64 | 5000 | 呼び出し全体のタイムアウト。設定の [min, max] の範囲内に制限されます。 |
date | string | — | 鮮度フィルター:d(日)、w(週)、m(月)、y(年)。 |
web_search_images
| パラメーター | 型 | デフォルト | 備考 |
|---|---|---|---|
queries | []string | — | 必須。 並列に実行されます。 |
max_images | int | 5 | クエリごとの画像数。max_images 設定値(10)が上限です。 |
timeout_ms | int64 | 5000 | 呼び出し全体のタイムアウト。設定の [min, max] の範囲内に制限されます。 |
date | string | — | 鮮度フィルター:d / w / m / y。 |
web_scrape
| パラメーター | 型 | デフォルト | 備考 |
|---|---|---|---|
urls | []string | — | 必須。 並列でダウンロードされます。 |
robots_txt | bool | false | ページの robots.txt に従います。 |
timeout_ms | int64 | 5000 | 呼び出し全体のタイムアウトです。設定の [min, max] の範囲内に制限されます。 |
remove_links | bool | false | テキストから Markdown リンクを削除します。 |
max_chars | int | 20000 | ページのテキストを N 文字に切り詰めます。設定の max_document_chars(20000)が上限です。 |
queries/urlsの両リストは、呼び出しごとにmax_queries(10)件までです。クエリは 512 文字以下、URL は 2048 文字以下で、http/httpsのみ使用できます。
結果と件数
各呼び出しでは入力リスト内の各項目が処理され、クエリ/URL ごとに status(success、failed、timeout のいずれか)を含むエントリーが 1 件返されます。そのため、一部で失敗しても、処理に成功した項目は返されます。
count は実際に返された項目数です。要求した max_results/max_images より少なくなる場合があります。上限を適用する前に、1 つのクエリの結果内にある重複項目が削除されるほか、上流から取得できる項目数が少ない場合もあります。count が少なくても通常の結果であり、エラーではありません。
重複排除はクエリごとに行われ、クエリ間では行われません。各エントリーは個別に重複排除されるため、同じ呼び出し内の 2 つのクエリで見つかったリンクは、どちらのエントリーにも表示されます。必要に応じて、結果をまとめる際にご自身で重複を排除してください。
エラー
リクエストレベルの失敗は、JSON-RPC エラーではなく、isError: true とプレーンテキストのメッセージを含むツール結果として返されます。モデルはメッセージを読み取り、呼び出しを修正できます。項目ごとの失敗でこの形式が使われることはありません。これらはペイロード内に status: "failed"/"timeout" として含まれます。
入力が作業の開始前に拒否された場合、またはすべての項目が失敗した場合にのみ、呼び出し全体が失敗します。
| メッセージ | 意味 |
|---|---|
invalid request | 引数が検証に合格しませんでした。 |
too many queries / too many urls | リストが MAX_QUERIES を超えています。この長さのリストは通常、入力スキーマの検証(スキーマには maxItems が設定されています)でそれより前に拒否されるため、クライアントには代わりに validating "arguments": maxItems: ... と表示されます。このメッセージはフォールバックです。 |
query must not be empty | クエリが空、または queries リストが空です。 |
query is too long | クエリが 512 文字を超えています。 |
invalid url | URL の形式が正しくない、2048 文字を超えている、または http/https ではありません。 |
robots.txt denied | robots_txt: true で、ページが取得を許可していません。 |
every url failed to be scraped; the pages may be unreachable or hold no extractable text | タイムアウト以外のエラーですべての URL の取得に失敗しました。個別の原因は stderr に記録され、返されません。 |
every query failed; the search upstream may be unreachable | 上流がリクエストを拒否した場合(たとえば、リクエストが集中した際に DuckDuckGo が返す HTTP 202 のボット判定など)を含め、タイムアウト以外のエラーですべてのクエリが失敗しました。クエリごとの原因は stderr に記録されます。 |
request canceled | クライアントが呼び出しの完了前にキャンセルしました。上流については何も示しません。 |
internal server error | その他、分類されていないエラーです。 |
タイムアウトが呼び出しレベルのエラーになることはありません。時間切れになった項目の status は timeout となり、すべての項目がタイムアウトした場合でも、そのステータスを付けてすべての項目が返されます。全件失敗のメッセージが表示されるのは、成功した項目もタイムアウトした項目もない場合に限られます。
既知の制限事項
web_scrapeは HTML のみを処理します。 ページはリーダビリティ抽出器に通されます。この抽出器は記事のマークアップを必要とするため、text/plainのレスポンスからは何も取得できず、status: "failed"が返されます。よくあるのは、raw.githubusercontent.com、github.com/.../raw/...、cdn.jsdelivr.netなどの生ファイル用ホストです。生ファイルではなく、レンダリングされたページをスクレイピングしてください。web_search_imagesの関連性は保証されません。 クエリによっては、Bing Images が検索結果一覧ではないページを返し、それが検索結果一覧であるかのように解析されます。その場合、ツールは無関係な画像をstatus: "success"とともに返します。画像の検索結果はベストエフォートとして扱い、ユーザーに表示する前に確認してください。- JavaScript には対応していません。 ページは取得した状態のまま処理されます。クライアント側でレンダリングされるコンテンツは抽出器から見えません。
- 検索を並列で集中実行すると、DuckDuckGo のボット対策に引っかかることがあります。 チャレンジは HTTP 202 を返し、クエリは失敗としてカウントされるため、リクエスト頻度が下がるまでクエリは失敗し続けます。ローテーションプロキシ(HTTP クライアントとプロキシを参照)を使うと、出口 IP 間で負荷を分散できます。
クイックスタート
インストール
用途に合う方法を選んでください。どの方法でも同じサーバーを利用できます。
コンテナー(Go ツールチェーンは不要):
docker pull ghcr.io/role1776/mcp-retrieval:latest
ビルド済みバイナリ — 最新リリースからお使いのプラットフォーム用のアーカイブをダウンロードし、展開して mcp-retrieval を PATH に追加します。
MCP Bundle — .mcpb ファイルをインストールするクライアントの場合は、最新リリースから mcp-retrieval_<version>_<os>_<arch>.mcpb をダウンロードし、クライアントで開きます。バンドルにはコンパイル済みバイナリが含まれているため、Docker も Go も必要ありません。お使いの OS と CPU アーキテクチャの両方に一致するファイルを選んでください。バンドルに含まれるネイティブバイナリは 1 つです。
ソースからインストール:
go install github.com/Role1776/mcp-retrieval/app/cmd/mcp-retrieval@latest # needs Go 1.25.5+
または、バイナリをその場でビルドします(Go モジュールは app/ にあります)。
make build # -> bin/mcp-retrieval
実行
# defaults: stdio transport, no configuration needed
./bin/mcp-retrieval
# with an explicit env file
./bin/mcp-retrieval -env /absolute/path/to/.env
フラグは 1 つで、省略可能です。
| フラグ | 意味 |
|---|---|
-env | .env ファイルへのパスです。省略した場合、またはファイルが存在しない場合、サーバーはデフォルト値と、すでに環境に設定されている値で起動します。暗黙的なファイル検索は行いません。stdio では作業ディレクトリが MCP クライアントによって選ばれるため、相対パスのデフォルト値は予測できないためです。 |
MCP クライアントへの接続(stdio)
ビルドしたバイナリをクライアントに指定します。Claude Desktop の設定例:
{
"mcpServers": {
"retrieval": {
"command": "/absolute/path/to/mcp-retrieval",
"env": {
"MAX_RESULTS": "20"
}
}
}
}
env ブロックは省略可能です。"command" だけで十分です。
MCP クライアントへの接続(コンテナー)
イメージを stdio で実行します。設定は引き続き env ブロックを通じて渡しますが、変数をプロセスに渡すには、Docker のコマンドラインで各変数を -e とともに指定する必要があります。
{
"mcpServers": {
"retrieval": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MAX_RESULTS",
"-e", "DEFAULT_TIMEOUT_MS",
"ghcr.io/role1776/mcp-retrieval:latest"
],
"env": {
"MAX_RESULTS": "20",
"DEFAULT_TIMEOUT_MS": "5000"
}
}
}
}
-i は必須です。これがないとコンテナーに stdin が渡らず、クライアントにはサーバーがすぐに停止したように見えます。MCP Registry からインストールするクライアントは、この呼び出しを自動的に構成し、server.json で宣言された変数の入力を求めます。
HTTP での実行
MCP_TRANSPORT=http を設定すると、サーバーは MCP_PATH(デフォルトは http://localhost:8080/mcp)で SERVER_PORT をリッスンします。
設定
すべて環境変数で設定します。各値は起動前に検証され、数値でない値または 0 以下の値を指定すると起動エラーになります(*_IN_FLIGHT の上限には 0 も指定できます)。制限間の関係は起動時には検証されません。制限を参照してください。環境にすでに設定されている変数は .env ファイルより優先されるため、MCP クライアントの env ブロックは常に反映されます。すべての項目に適切なデフォルト値があるため、設定なしでも(stdio トランスポートで)サーバーを実行できます。
デフォルト値を設定済みで、.env にそのままコピーできる全項目については、.env.example を参照してください。
MCP サーバー
| 環境変数 | デフォルト | 備考 |
|---|---|---|
MCP_TRANSPORT | stdio | stdio または http。 |
MCP_NAME | mcp-retrieval | クライアントに通知されるサーバー名。 |
MCP_PATH | /mcp | HTTP ルート(http トランスポートのみ)。 |
クライアントに通知されるバージョンは設定できません。ビルド時に git タグからバイナリに埋め込まれます。
HTTP サーバー(http トランスポートのみ)
| 環境変数 | デフォルト |
|---|---|
SERVER_PORT | 8080 |
SERVER_READ_TIMEOUT | 60s |
SERVER_WRITE_TIMEOUT | 60s |
HTTP クライアントとプロキシ
| 環境変数 | デフォルト | 備考 |
|---|---|---|
MAX_IDLE_CONNS_PER_HOST | 100 | HTTP 接続プーリング。 |
PROXY_HOST | — | 任意。設定すると、リクエストはローテーションセッションプロキシ経由でルーティングされます。 |
PROXY_PORT | — | PROXY_HOST を設定する場合は必須です。 |
PROXY_SCHEME | — | PROXY_HOST を設定する場合は必須です。 |
PROXY_LOGIN | — | PROXY_HOST を設定する場合は必須です。 |
PROXY_PASSWORD | — | PROXY_HOST を設定する場合は必須です。 |
プロキシを設定すると、各送信リクエストのログイン名に一意のセッション ID が追加されるため、上流プロバイダーはリクエストごとに出口 IP を切り替えます。
制限
| 環境変数 | デフォルト |
|---|---|
MAX_QUERIES | 10 |
DEFAULT_RESULTS | 5 |
MAX_RESULTS | 20 |
DEFAULT_TIMEOUT_MS | 5000 |
MAX_TIMEOUT_MS | 10000 |
MIN_TIMEOUT_MS | 1000 |
DEFAULT_IMAGES | 5 |
MAX_IMAGES | 10 |
DEFAULT_DOCUMENT_CHARS | 20000 |
MAX_DOCUMENT_CHARS | 20000 |
MAX_SEARCH_IN_FLIGHT | 2 |
MAX_IMAGES_IN_FLIGHT | 2 |
MAX_SEARCH_IN_FLIGHT と MAX_IMAGES_IN_FLIGHT は、サーバープロセスごとの上流のウェブ検索および画像検索リクエストの同時実行数を制限します。0 を指定すると制限が無効になります。
各値は個別に検証され、*_IN_FLIGHT の上限では 0 で制限が無効になる点を除き、0 より大きい値である必要があります。ただし、起動時に DEFAULT_*、MIN_*、MAX_* の各値が互いに照合されることはありません。値の組み合わせに一貫性がなくてもサーバーは停止せず、リクエストごとに調整されます。
- 呼び出し元が値を省略するか、0 以下の値を渡した場合は、対応する
DEFAULT_*にフォールバックします。 - その後、値は
[MIN_*, MAX_*]の範囲内に収まるよう調整されるため、DEFAULT_*がMAX_*より大きい場合はMAX_*が適用されます。 MIN_*がMAX_*を超える場合は、最大値が優先されます。
したがって、実効制限は常に設定された最大値以内となり、設定ミスがあっても起動に失敗するのではなく、動作するサーバーとして機能します。ただし、その代償として、設定ミスは通知なく影響します。たとえば、20 の代わりに MAX_RESULTS=2 と入力しても警告は出ず、応答がひっそりと小さくなるだけです。結果が途中で切れているように見える場合は、これらの値を再確認してください。
ロギング
| 環境変数 | デフォルト | 備考 |
|---|---|---|
LOG_MODE | local | local → デバッグレベルのテキストハンドラー、prod → 情報レベルの JSON ハンドラー。ログは stderr に出力されます。 |
アーキテクチャ
このプロジェクトは、クリーンな階層構造に従っています。依存関係はドメインに向かって内向きに配置され、各レイヤーはインターフェースを介して次のレイヤーと連携します。
app/ the Go module: sources plus its build files
(Dockerfile, .dockerignore, .goreleaser.yaml)
cmd/mcp-retrieval/main.go entry point: parse flags, load config, run app
internal/
app/ wiring + lifecycle (build server, run, graceful shutdown)
config/ config loading (.env → env vars → validate)
domain/ core types (Query, Link, Document, Snippet, Image) and errors
dto/web/ request/response shapes for the MCP tools
transport/mcp/ MCP layer
router/ registers every tool group on the MCP server
web/ tool handlers
utils/ schema helpers and error → tool-result mapping
usecase/web/ business logic: validation, parallelism, timeouts, dedupe/limit/rerank
adapter/web/ retrieval-go client wiring (search, images, scrape, proxy)
pkg/ reusable building blocks (mcpserver, server, logger, validator)
ツール呼び出しのリクエストフロー:
MCP client → transport/mcp/web (handler) → usecase/web → adapter/web → retrieval-go → the web
↑ maps errors ↑ validates, fans out, limits results
検索とスクレイピングは、どちらも入力リスト全体に対して並行して処理を実行し、各項目の結果を集約します。各項目にはそれぞれのステータス(success、failed、timeout)が設定されます。呼び出しが完全に失敗するのは、その呼び出し内のすべての項目がタイムアウト以外のエラーで失敗した場合に限られます。
検索エンジン
ネットワーク関連の処理はすべて retrieval-go に委任されており、設定は app/internal/adapter/web で行われています。知っておくと役立つ点は次のとおりです。
- ソース。 ウェブ検索には DuckDuckGo Lite、画像検索には Bing Images を使用します。ページの取得では、生の HTML を readability 抽出器に通し、メイン記事を Markdown に変換します(表も含まれます)。検索エンジンの API キーは不要です。
- ブラウザーの偽装。 アダプターでは
WithBrowserRotation()が有効になっているため、リクエストごとに約 11 種類の実際のブラウザープロファイルからランダムに選ばれたものが使用されます。各プロファイルは、実際の TLS/JA3 フィンガープリント(uTLS 経由)と、それに対応するUser-Agentおよびクライアントヒントヘッダーの組み合わせです。対象は Chrome 133/131/120(Windows/macOS/Linux)、Edge 131、Firefox 120(Windows/macOS)、Safari 18.4(macOS)、iOS 18.4 Safari です。これにより、Go の HTTP クライアントではなく一般的なブラウザーからの通信に見えるため、無料のソースに引き続きアクセスできます。 - プロキシのローテーション。
PROXY_HOSTが設定されている場合、アダプターはリクエストごとにプロキシのユーザー名へ一意のsession-<id>を追加するプロキシファクトリーを設定します。セッションベースの住宅用/ローテーション型プロキシプロバイダーを使うと、リクエストごとに 新しい出口 IP が割り当てられ、負荷が分散されてレート制限を回避できます。プロキシを使わない場合、リクエストは直接送信されます。 - レスポンスの処理。 レスポンスは自動的に展開され(
gzip、br、zstd、deflate)、接続の再利用は無効化されます(WithDisableKeepAlive())。そのため、プールされた接続によってリクエスト間で同じフィンガープリント/IP に固定されることはありません。
これらの機能は設定なしで動作し、上記のデフォルトが自動的に適用されます。追加で必要となるのは、任意のプロキシ認証情報のみです。
開発
Go 関連のファイルはすべて app/ にあります。そのため、リポジトリのルートから makefile を使用するか、ツールチェーンに -C app を指定してください。
make build # compile the binary
make test # run tests
go -C app build ./... # compile everything
go -C app test ./... # run tests
go -C app vet ./... # static checks
プルリクエストのガイドラインについては、CONTRIBUTING.md を参照してください。
ライセンス
MIT License の下で公開されています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。