NetLens について
NetLensは、ウェブページと検索結果を必要とするエージェント向けのMCPサーバーです。ページ全体を整形済みMarkdownに変換し、検索リンクを返すほか、セクションやページ概要を指定できます。
主な機能
- 01ページ全体を整形済みMarkdownで取得
- 02検索エンジンを選んで検索
- 03ページのセクションや概要を選択
- 04広告やページの定型部分を除去
- 05要約ではなく検索リンクを返却
活用シーン
- 01標準ツールで取得できない記事を読む
- 02ページを検索して内容を確認
- 03長いページから指定セクションを抽出
MCP 対応
MCPクライアントにweb_searchとweb_fetchツールを提供し、検索エンジン、ページ形式、セクションを指定できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y netlens-mcpNETLENS_SEARCH_ENGINEDefault search backend: auto, duckduckgo, bing, mojeek, or searxngNETLENS_SEARXNG_URLBase URL of a SearXNG instance to use when engine=searxng (e.g. https://searx.example.org)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
2掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| page | integer | いいえ | 結果ページ番号(1 始まり)。SearXNG のみ対応。スクレイピング対象のエンジンは 1 ページのみを提供するため、この機能は無視されず、非対応として報告されます。 |
| limit | integer | いいえ | 結果数の上限(省略可)。デフォルトでは最初のページの全結果(約 10 件)を返します。 |
| query | string | はい | 検索クエリ |
| engine | enum | いいえ | 検索バックエンド。'auto'(デフォルト)は、設定されている場合にまず SearXNG を試し、その後 DuckDuckGo、Mojeek、Bing を試します。'searxng' には NETLENS_SEARXNG_URL が必要です。auto | duckduckgo | bing | mojeek | searxng |
| categories | string | いいえ | SearXNG のカテゴリーフィルター。例:'it'、'science'、'news'。SearXNG のみ対応。 |
| time_range | enum | いいえ | 最近の結果に限定します。SearXNG のみ対応。day | week | month | year |
詳細
NetLens
制限のないウェブ閲覧を実現する MCP サーバーです。ブラウザーのようなヘッダーを使って任意の URL を直接取得し、
robots.txt や単純なボットブロックを回避して、要約ではなく広告を除去したクリーンな Markdown として
ページ全体を返します。実際のリンクを返すウェブ検索機能も備えています。依存関係はゼロで、Python 標準ライブラリのみを使用します。
AI エージェント向けに構築
AI エージェントは、組み込みツールでは読み取れないページに頻繁に遭遇します。NetLens は、取得結果が空または役に立たない状態になる主な 3 つの原因を解決します。
| ネイティブのウェブツール | NetLens |
|---|---|
robots.txt に従うため、クローラーが許可されていないページは何も返さない | 自分で開くブラウザーと同じように読み取ります。robots.txt は参照しません |
ヘッダーや User-Agent によるボットフィルターでブロックされる(ブラウザー以外のクライアントには 403/202 が返る) | システムの curl を使って実際のブラウザーヘッダーを送信します。一般に 403 → 200 に変わります |
| ページの要約を返す | Markdown でページの全コンテンツを返します |
| 広告、Cookie バナー、ナビゲーション、関連リンクなどが出力に残る | 定型要素をローカルで取り除き、コンテンツのみをコンテキストに渡します |
JavaScript/Cloudflare のチャレンジページや CAPTCHA の突破は試みません。これは意図的に対象外としています。ページが強固にブロックされている場合は、HTTP ステータスを偽らず、そのまま提示します。
インストール
npm(npx 経由):
{
"mcpServers": {
"netlens": {
"command": "npx",
"args": ["-y", "netlens-mcp"]
}
}
}
PyPI(uvx 経由):
{
"mcpServers": {
"netlens": {
"command": "uvx",
"args": ["netlens-mcp"]
}
}
}
いずれかを MCP クライアントの設定(Claude Code の .mcp.json など)に追加し、
ツールを読み込むためにセッションを再起動してください。
ツール
web_search
ウェブを検索し、実際の検索結果リンク(タイトル、URL、スニペット)をローカルで解析して返します。
返すのはリンクであり、要約ではありません。検索結果を読むには、続けて web_fetch を使用してください。
| 引数 | 型 | 説明 |
|---|---|---|
query | string(必須) | 検索クエリ |
limit | integer | 任意の上限。デフォルトでは最初のページ全体(約 10 件)を返します |
engine | string | auto(デフォルト)、duckduckgo、bing、mojeek、searxng |
page | integer | 検索結果のページ番号(1 から開始)。SearXNG のみ |
time_range | string | day、week、month、year。SearXNG のみ |
categories | string | 例:it、science、news。SearXNG のみ |
結果には、応答した検索エンジンと、スキップされた検索エンジンで発生した内容が示されます。そのため、別のバックエンドへのフォールバックも隠されずに確認できます。
{
"query": "…",
"engine": "mojeek",
"results": [ … ],
"engines_skipped": [ { "engine": "duckduckgo", "outcome": "HTTP 202" } ]
}
結果は観測された内容であり、結論ではありません。HTTP 202 はサーバーが送信したものであり、それがスロットリング、マークアップの変更、または本当に一致する結果がないことを意味するかは、応答から判断できません。SearXNG を設定すると、直接の answers、infoboxes、suggestions も検索結果とともに表示されます。
検索では単一の検索結果ページ(約 10 件)を取得し、位置 9/10 の結果も漏れないよう、デフォルトですべて返します。ページをまたぐ詳細なページネーションには対応していません。答えが最初のページにない場合は、クエリを絞り込んでください。
web_fetch
任意のページを取得し、クリーンな Markdown として全コンテンツを返します。
| 引数 | 型 | 説明 |
|---|---|---|
url | string(必須) | 取得する URL(スキームは省略可能。省略時は https を使用) |
mode | string | article(メインコンテンツのみ。デフォルト)、full(本文全体)、raw(変換前の HTML)、outline(見出し構造) |
section | string | この見出しの内容のみを返します。配下にネストされた内容も含みます |
links | string | inline(デフォルト)ではリンク先を保持します。none ではリンクテキストを保持し、URL を除外します |
max_chars | integer | 返す文字数の任意の上限(上限を超えた場合は注記とともに切り詰めます) |
長いページの一部を読む
ページの一部だけを読みたい場合でも、大きな記事は数万文字に及ぶことがあります。mode="outline" は記事の構成を返し、section はその部分だけを返します。たとえば、大きな百科事典の記事は全文で153,000文字、アウトラインで1,000文字、目的のセクションだけなら7,400文字です。
web_fetch(url=…, mode="outline") → headings with each section's size
web_fetch(url=…, section="Gameplay") → that section and its subsections
リンクの多いページでは、URL自体が出力の大きな割合を占めます。大きな百科事典の記事では約40%に達するため、本文だけが必要な場合は links="none" で出力をおよそ半分にできます。同じページ内を指すリンクは、常にプレーンテキストとして表示されます。
ページがクライアント側でレンダリングされるシェルだと判明した場合、web_fetch は空の結果を成功として返すのではなく、そのことを通知します。
(注:6,856文字のHTML内で、読み取り可能なテキストは10文字しか見つかりませんでした。 このページはJavaScriptによってクライアント側でレンダリングされているようです……)
ワークフロー: web_search でページを見つけてから、web_fetch で読み取ります。
検索エンジン
検索エンジンは、プラグインとして追加でき、選択可能なレジストリになっています。auto モードでは、NetLens は順番に検索エンジンを試し、結果が得られた最初のエンジンの結果を返します。そのため、あるエンジンでレート制限やチャレンジページが発生しても、次のエンジンに切り替わります。
| エンジン | 説明 |
|---|---|
duckduckgo | デフォルト。html.duckduckgo.com エンドポイント |
bing | 自動フォールバック |
mojeek | 独立したインデックス。自動フォールバック |
searxng | セルフホスト可能/公開SearXNG JSON API — NETLENS_SEARXNG_URL を設定 |
呼び出しごとに engine 引数で選択するか、NETLENS_SEARCH_ENGINE でデフォルトを設定します。
設定
| 環境変数 | デフォルト | 説明 |
|---|---|---|
NETLENS_SEARCH_ENGINE | auto | デフォルトの検索バックエンド |
NETLENS_SEARXNG_URL | — | SearXNG のベースURL。例:http://192.168.1.10:8888 |
NETLENS_SEARXNG_TIMEOUT | 8 | 到達不能なSearXNGをスキップするまでの秒数 |
NETLENS_USER_AGENT | Chrome UA | リクエストのUser-Agentを上書き |
NETLENS_MAX_BYTES | 10485760 | 1回のレスポンスの上限。超過分は切り捨て |
NETLENS_CACHE_TTL | 300 | 取得したページを再利用する秒数。0 にするとキャッシュを無効化 |
NETLENS_HOST_DELAY | 0.5 | 同じホストへのリクエスト間に設ける最小間隔(秒) |
NETLENS_REQUEST_TIMEOUT | 120 | 1回のツール呼び出しの最大時間 |
SearXNG のセルフホスト
JSON API が有効になっているインスタンスを NETLENS_SEARXNG_URL に指定します(settings.yml の search.formats に json を含める必要があります)。設定すると、auto モードで最初に試されるため、一般的な処理経路からHTMLスクレイピングと、それに伴うレート制限をなくせます。
最初に試されるため、インスタンスが停止している場合はすぐに失敗する必要があります。到達不能なインスタンスが毎回の検索を停滞させることなく数秒でスキップされるよう、接続タイムアウトは個別に制限されており、スキップされたことは結果に報告されます。
仕組み
- 直接取得。 システムの
curlを使って、リクエストを対象サイトへ直接送信します (TLS/HTTP-2/圧縮の処理に優れているため、実際のブラウザーのように見えます)。利用できない場合はurllibにフォールバックします。サードパーティのプロキシやリーダーは使用しません。 - ローカル変換。 HTML から Markdown への変換は、独自実装の
html.parserコンバーターを使ってプロセス内で行います。見出し、リスト、リンク(相対 URL は解決)、 コードブロック、colspan/rowspan に対応した GFM テーブルを処理します。 - 削除ではなくコンテンツ選択。 NetLens はページのメインコンテンツ領域を選択します。HTML5 のランドマーク
(
<main>/<article>/[role=main])があればそれを使い、なければリンク密度に対する文章量が最も多いサブツリーを選び、 その部分だけを変換します。名前のパターンに一致する要素を削除するのではなく、候補から最適なものを 選択 するため、抽出結果が気付かないうちに空のページになることはありません。何をコンテンツとするかの判定に、 CSS クラス名や id 名を調べることはありません。 - 測定に基づく刈り込み。 その領域内では、リンク密度に基づいて、ほとんどがリンクアンカーで構成されるブロック
(ナビゲーションボックス、タグクラウド、「このサイトのその他の記事」のグリッド)を除外します。描画されない要素
(
<script>、<style>など)、明示的に非表示にされた要素、サードパーティの広告ネットワーク枠 (実際の文章と衝突しないadsbygoogleなどのベンダー名で識別)も完全に削除します。 - レスポンスの文字セット を尊重します(
Content-Typeまたは<meta>から取得)。そのため、UTF-8 以外の ページも文字化けせずに返されます。
CLI からの使い方
このサーバーは通常のスクリプトとしても実行できます。クライアントから読み込む前のテストに便利です。
python -m netlens_mcp.server search "http caching best practices"
python -m netlens_mcp.server fetch https://example.com/article
python -m netlens_mcp.server full https://example.com # whole body
python -m netlens_mcp.server raw https://example.com # unconverted HTML
python -m netlens_mcp は stdio MCP サーバーを実行し、python -m netlens_mcp.server <cmd> は CLI を実行します。
開発
pip install -e ".[dev]"
python -m pytest # run the test suite
ruff check . # lint
要件
- Python 3.10 以降、およびシステムの
curl(最新の Windows/macOS/Linux に付属しています。 存在しない場合はurllibにフォールバックします)
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。