mcp-web-research について
mcp-web-researchは、ウェブ検索とページ内容の取得・抽出・比較を行う、エージェント向けのMCPサーバーです。取得先とすべてのリダイレクトでSSRFを検査します。
主な機能
- 01Brave Searchによるウェブ検索
- 02テキストとリンクの取得
- 03検索結果を使ったトピック調査
- 04項目名によるページ内容の抽出
- 05複数ページの比較
- 06取得時とリダイレクト時のSSRF検査
活用シーン
- 01トピック調査の情報源集め
- 02指定ページのテキスト確認
- 03価格などの項目の検索
- 04特定の観点で複数ページを比較
MCP 対応
ウェブ検索、ページ取得、抽出、比較、サーバー情報をMCPツールとして提供し、ステータスとキャッシュのリソースも公開します。検索ツールには検索プロバイダーの設定が必要ですが、ページツールは単独で使えます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @opafex/mcp-web-researchBRAVE_SEARCH_API_KEYシークレットBrave Search API key; enables web_search and research_topic (recommended)WEB_RESEARCH_SEARCH_PROVIDERSearch provider: "brave" or "duckduckgo" (unofficial HTML scraper, explicit opt-in only)USER_AGENTUser-Agent sent with every request (default identifies the bot and links to the repo)SEARCH_CACHE_TTLSearch result cache TTL in seconds (default: 900)PAGE_CACHE_TTLFetched page cache TTL in seconds (default: 3600)FETCH_TIMEOUT_MSPer-request timeout in milliseconds, across all redirect hops (default: 10000)MAX_HTML_SIZEMaximum bytes read from a page body (default: 1000000)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
6掲載時のツール一覧 · 3 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| query | string | はい | 検索クエリ文字列 |
| domain | string | いいえ | 任意のドメインフィルター(例:"example.com")。結果をこのドメインに限定します。 |
| maxResults | number | いいえ | 結果の最大件数(1~20、デフォルト 10) |
詳細
@opafex/mcp-web-research
ウェブ調査用の MCP サーバーです。ウェブを検索し、ページを整形されたテキストとして取得したり、ページから名前を指定したセクションを抽出したり、複数のページを並べて比較したり、「検索して上位の結果を読む」という2段階の処理を実行したりできます。
LLM は使用しません。research_topic と compare_pages は抽出したテキストを整理するものであり、テキストを生成するものではありません。リダイレクトのすべての段階を含め、ページを取得するたびにSSRFチェックを行います。
検索には Brave Search API を使用します(無料プランも利用できます)。APIキーがなくても4つのページツールは動作しますが、2つの検索ツールは設定する変数名を示すエラーを返します。
インストール
npx -y @opafex/mcp-web-research
Node.js 20+ が必要です。ほかにインストールが必要な依存関係はありません。
クイックスタート
Claude Code
claude mcp add web-research -e BRAVE_SEARCH_API_KEY=your-key -- npx -y @opafex/mcp-web-research
または、プロジェクトのルートにある .mcp.json に追加します。
{
"mcpServers": {
"web-research": {
"command": "npx",
"args": ["-y", "@opafex/mcp-web-research"],
"env": {
"BRAVE_SEARCH_API_KEY": "your-key"
}
}
}
}
Claude Desktop
同じブロックを claude_desktop_config.json に追加します(設定 → 開発者 → 設定を編集)。
{
"mcpServers": {
"web-research": {
"command": "npx",
"args": ["-y", "@opafex/mcp-web-research"],
"env": {
"BRAVE_SEARCH_API_KEY": "your-key"
}
}
}
}
ページツールのみを使用する場合は、BRAVE_SEARCH_API_KEY を省略します。
ツール
| ツール | 機能 | 検索プロバイダーが必要 |
|---|---|---|
web_search | ウェブを検索し、結果ごとにタイトル、URL、スニペットを返します | はい |
fetch_webpage | URLを取得し、タイトルと整形されたテキスト、リンク、またはその両方を返します | いいえ |
research_topic | トピックを検索し、上位の結果を取得して、ソースごとに重要な文をまとめます | はい |
extract_structured_data | ページを取得し、指定した各フィールド(例:pricing、contact)の周辺セクションを返します | いいえ |
compare_pages | 2~5件のページを取得して比較します。必要に応じて、1つの注目領域に絞ることもできます | いいえ |
server_info | サーバー名、バージョン、ツール、リソースを返します(@opafex/mcp-shared に組み込み済み) | いいえ |
web_search
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
query | string | はい | 検索クエリ |
maxResults | number | いいえ | 1~20。デフォルトは10 |
domain | string | いいえ | このドメインに結果を制限します(例:"example.com")。site: を追加し、結果URLをフィルタリングします |
SSRFチェック(下記)に失敗した結果URLは、返される前に除外されます。
レスポンスの例
[
{
"title": "Model Context Protocol",
"url": "https://modelcontextprotocol.io/",
"snippet": "An open protocol that enables seamless integration between LLM applications and external data sources and tools."
}
]
fetch_webpage
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
url | string | はい | http または https のURL |
extractMode | "text" | "links" | "all" | いいえ | デフォルトは "text" |
maxLength | number | いいえ | 返すテキストの最大文字数。デフォルトは4000 |
スクリプト、スタイル、<nav>、<footer> は削除されます。リダイレクトを経由してページに到達した場合は、finalUrl が含まれます。
レスポンスの例
{
"title": "Example Domain",
"text": "Example Domain\nThis domain is for use in illustrative examples in documents.",
"url": "http://example.com/",
"fetchedAt": "2026-10-24T12:00:00.000Z"
}
research_topic
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
topic | string | はい | 調査する内容 |
depth | "quick" | "standard" | "deep" | いいえ | 検索結果3件/5件/10件を対象に、それぞれ2,000/4,000/8,000文字を読み込みます。デフォルトは "standard" |
maxSources | number | いいえ | 取得するソース数(1~10)。デフォルトは5 |
重要なポイントとは、トピックに含まれる語句に言及している文のことで、ソースごとに最大5件までです。取得できないソースについては、検索スニペットを代わりに使用します。
extract_structured_data
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
url | string | はい | 読み込むページ |
fields | string[] | はい | 検索するフィールド名(例:["pricing", "features", "contact"]) |
各フィールドについて、そのフィールドに言及している最初の行と、その後の10行を、最大1,000文字まで返します。該当するセクションがない場合は No "<field>" section found on page. を返します。これは見出しを照合するものであり、スキーマ抽出ではありません。
compare_pages
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
urls | string[] | はい | 2~5 個の URL |
focus | string | いいえ | 各ページから抽出する項目(例:"pricing") |
取得に失敗したページは、理由とともに "(fetch failed)" と表示されます。それ以外のページは引き続き比較されます。
リソース
| リソース | 説明 |
|---|---|
web-research://status | 使用中の検索プロバイダー(または検索を利用できない理由)、キャッシュの統計情報と設定 |
web-research://cache | 現在キャッシュされている検索クエリ |
検索プロバイダー
| プロバイダー | 選択方法 | 備考 |
|---|---|---|
| Brave Search API(推奨) | BRAVE_SEARCH_API_KEY を設定 | 無料プランのある公式 API です。クエリごとに最大 20 件の結果を取得します。 |
| DuckDuckGo HTML スクレーパー | WEB_RESEARCH_SEARCH_PROVIDER=duckduckgo を設定 | オプトインのみです。詳細は以下をご覧ください。 |
| なし | 上記のいずれも設定されていない場合 | web_search と research_topic は BRAVE_SEARCH_API_KEY を示すエラーを返します。それ以外のツールは動作します。 |
DuckDuckGo オプションについて。 html.duckduckgo.com の検索結果ページを解析します。これは API ではありません。DuckDuckGo がマークアップを変更すると動作しなくなり、レート制限やブロックの対象となる可能性があります。また、DuckDuckGo の利用規約では自動クエリが許可されていません。このサーバーはブラウザーを装うことなく、正直なユーザーエージェントを送信するため、ブロックされる可能性が高くなります。個人的な実験用に用意されています。有効にする場合は、DuckDuckGo の利用規約を遵守する責任を負います。依存する用途には Brave を使用してください。
環境変数
| 変数 | 型 | デフォルト | 説明 |
|---|---|---|---|
BRAVE_SEARCH_API_KEY | string | — | Brave Search API キー。web_search と research_topic を有効にします |
WEB_RESEARCH_SEARCH_PROVIDER | brave | duckduckgo | キーが設定されている場合は Brave、そうでない場合はなし | 検索プロバイダーを明示的に選択します |
USER_AGENT | string | opafex-mcp-web-research/<version> (+https://github.com/Opafex/opafex-mcps) | すべてのリクエストで送信する User-Agent |
FETCH_TIMEOUT_MS | number | 10000 | ページごとのタイムアウト。リダイレクトの各段階にも適用されます |
MAX_HTML_SIZE | number (bytes) | 1000000 | ページ本文から読み込むバイト数。ここでダウンロードを停止します |
SEARCH_CACHE_TTL | number (seconds) | 900 (15 min) | 検索結果をキャッシュする期間 |
PAGE_CACHE_TTL | number (seconds) | 3600 (1 h) | 取得したページをキャッシュする期間 |
セキュリティ
ページツールは、モデルが選んだ URL をサーバーの実行マシンから取得します。保護がなければ、そのマシンのプライベートネットワークやクラウドのメタデータサービスに、ツール呼び出し 1 回でアクセスできてしまいます(サーバーサイドリクエストフォージェリ)。取得前にすべてのリクエストをチェックし、次の場合は拒否します。
- スキームが
httpまたはhttpsではない場合。 - ホストが
localhost、*.localhost、またはクラウドのメタデータ名(metadata.google.internal)の場合。 - ホストが、プライベート範囲にあるリテラル IP(IPv4 または角括弧で囲まれた IPv6)の場合。特殊な IPv4 表記(
http://2130706433/、http://0x7f.1/)はチェック前に正規化されます。 - ホスト名が解決するアドレス(IPv4(A)または IPv6(AAAA))のいずれかがプライベート範囲にある場合。パブリックな A レコードが 1 つあっても、プライベートな AAAA レコードがあれば許可されません。
- ホスト名を解決できない場合。**チェックはフェイルクローズで動作します。**チェックできなかったアドレスは取得されません。
ブロック対象の範囲:
| IPv4 | IPv6 |
|---|---|
0.0.0.0/8 このネットワーク | :: 未指定、::1 ループバック |
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 プライベート | fc00::/7 ユニークローカル |
100.64.0.0/10 キャリアグレード NAT | fe80::/10 リンクローカル、fec0::/10 サイトローカル |
127.0.0.0/8 ループバック | ff00::/8 マルチキャスト |
169.254.0.0/16 リンクローカル。クラウドのメタデータ 169.254.169.254 を含む | ::ffff:0:0/96 IPv4 マップド — 内部の IPv4 アドレスに基づいて判定 |
192.0.0.0/24、198.18.0.0/15 予約済み/ベンチマーク用 | 64:ff9b::/96 NAT64、2002::/16 6to4 — 内部の IPv4 アドレスに基づいて判定 |
192.0.2.0/24、198.51.100.0/24、203.0.113.0/24 ドキュメント用 | ::/96 IPv4 互換、64:ff9b:1::/48、2001::/32 Teredo、2001:db8::/32 |
224.0.0.0/4 マルチキャスト、240.0.0.0/4 予約済み、ブロードキャスト | グローバルユニキャスト 2000::/3 の範囲外すべて |
リダイレクトは手動でたどり、各ホップを再チェックします(最大 5 ホップ)。パブリックページが http://169.254.169.254/ にリダイレクトする場合、2 回目のリクエストを行う前に拒否されます。検索結果の URL もチェックされ、条件を満たさないものは除外されます。
**既知の制限 — DNS リバインディング。**チェック時にホスト名を解決し、その後 fetch が接続のために再度解決します。TTL が非常に短い悪意ある DNS サーバーは、2 回の名前解決に異なる応答を返す可能性があります。この隙間をなくすには、チェック済みアドレスに接続を固定する必要がありますが、Node の組み込み fetch では追加の依存関係なしにそれを指定できません。このサーバーを機密性の高い内部サービスがある場所で実行する場合は、ネットワークレベルでもアクセス可能な範囲を制限してください(コンテナのネットワークポリシー、送信ファイアウォール)。
制限事項
- **テキストのみ。**ページの MIME タイプは
text/*、application/xhtml+xml、またはapplication/jsonである必要があります。PDF、画像、その他のバイナリ形式は拒否されます。 - **JavaScript は実行されません。**ページは配信された状態のまま取得されます。クライアント側でレンダリングされるコンテンツは含まれません。
- **正規表現ベースの HTML 解析。**高速で依存関係も不要ですが、完全な HTML パーサーではないため、特殊なマークアップがテキストに混入することがあります。
- ヒューリスティックによる抽出。
research_topicの要点とextract_structured_dataのセクションは、理解に基づくものではなくキーワード照合です。 - メモリ内キャッシュはプロセスごとに保持され、再起動時に失われます。
- **UTF-8 を前提としています。**それ以外のエンコーディングのページは、置換文字を使ってデコードされる場合があります。
- **クローラーではありません。**robots.txt は処理せず、指定された URL を取得します。
開発
npm run build # Compile TypeScript
npm run dev # Run with tsx (no build needed)
npm test # Run tests (no network — fetch and DNS are faked)
npm start # Run compiled server
貢献
バグを見つけた場合や機能のリクエストがある場合は、issue を作成してください。
プルリクエストも歓迎します。開発環境のセットアップについては、メインリポジトリをご覧ください。
ライセンス
MIT — LICENSE をご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。