Skip to main content
Glama

searxng-mcp

Built with Claude Code CI License: MIT npm

自己ホスト型の SearXNG インスタンスを介したプライベート Web 検索のための MCP サーバーです。結果はローカル ML モデルで再ランク付けされ、全ページのコンテンツは Firecrawl で取得され、オプションの Ollama インスタンスがクエリ拡張と LLM による要約を提供します。

サードパーティの検索 API にクエリを送信せずに Web 検索を必要とする Claude Code および LibreChat エージェントでの使用を想定しています。

Claude Codehomelab-agent のマルチエージェントワークフローを使用して構築されています。このプラットフォームは、AI 支援リサーチのために searxng-mcp を本番環境で使用しているのと同じものです。

クイックスタート

実行中の SearXNG インスタンスが必要です。キャッシュバックエンドを強く推奨します。

最小構成 — Dragonfly/Valkey キャッシュバックエンドを起動し、searxng-mcp を実行します:

docker compose -f docker-compose.example.yml up -d
SEARXNG_URL=http://localhost:8081 CACHE_URL=redis://localhost:6381 npx @tadmstr/searxng-mcp

Firecrawl、Crawl4AI、Ollama、Kiwix、アドブロックプロキシ、NATS を含む完全なローカルトポロジーについては、docker-compose.full.yml を参照してください。

Related MCP server: searxng-mcp-bridge

ツール

ツール

説明

主要パラメータ

search

ローカル再ランク付けを伴う SearXNG 経由の検索。より広い結果プールを取得し、関連性で再ランク付けして上位 N 件を返します。SearXNG のネイティブな直接回答、インフォボックス、スペル修正、関連提案は、リストの上と structuredContent に表示されます。

querynum_results(1〜20)、categorytime_rangedomain_profileexpandlanguageenginessite

search_and_fetch

検索、再ランク付け、その後フェッチカスケード(Firecrawl → Crawl4AI → 生 HTTP)を使用して上位結果の完全なコンテンツを取得します。

querycategorytime_rangefetch_count(1〜3)、domain_profileexpandlanguageenginessite

search_and_summarize

検索、上位結果の取得、その後 Ollama(OLLAMA_SUMMARIZE_MODEL)を介して引用付きの要約を合成します。Ollama が利用できない場合は、取得した生のコンテンツにフォールバックします。

queryfetch_count(1〜5)、categorytime_rangedomain_profileexpandlanguageenginessite

fetch_url

任意の公開 URL から読み取り可能な Markdown を取得して抽出します。GitHub ホストは GitHub 高速パスを利用し、YouTube ビデオ URL はトランスクリプトを返し、Reddit スレッド URL は投稿とコメントを返します(いずれも robots 経由でオプトイン、下記参照)。その他はすべてフェッチカスケード(Firecrawl → Crawl4AI → 生 HTTP)を使用します。トークン予算(デフォルト約 8,000 文字)に切り詰められます。

urldomain_profilemax_tokenstarget_selectorwait_for_selector

crawl_site

サイト全体をクロールし、各ページの URL/タイトル/スニペットのマニフェストを返します。最初に Firecrawl クロールを試み、次にサイトマップ解析、その後オプションの BFS にフォールバックします。ページの完全なコンテンツは Valkey にキャッシュされるため、後続の fetch_url 呼び出しはコストゼロです。

urlmax_pages(デフォルト: CRAWL_MAX_PAGES_DEFAULT)、bfs(ブール値、オプトイン BFS)

clear_cache

検索キャッシュ、フェッチキャッシュ、クロールマニフェストキャッシュ、またはすべてを消去します。キャッシュされた結果が古くなる可能性のある急速に変化するトピックを調査するときに便利です。

targetsearchfetchcrawlall

domain_stats

ドメイン機能データベース の読み取り専用ビュー。hostname を指定すると、1 つのドメインのティア別成功率と機能フラグが表示されます。指定しない場合は、追跡されているすべてのドメインにわたる集計(ティア別成功率、最悪の失敗ドメイン、表示されたがフェッチされていない数)が表示されます。プログラムによるしきい値設定のための MCP 構造化出力(structuredContent)を返します。

hostname(オプション)

パラメータ

categorygeneral(デフォルト)、newsitscience

time_rangedayweekmonthyear — 公開日で結果を制限します。全期間の結果が必要な場合は省略します。

fetch_count — 完全なコンテンツを取得する上位再ランク付け結果の数(search_and_fetch のデフォルトは 1、最大 3search_and_summarize のデフォルトは 3、最大 5)。

domain_profile — 名前付きドメインフィルタープロファイルを適用します: homelab(自己ホスト型/Linux ドキュメントを表示)または dev(Stack Overflow、MDN、npm を表示)。デフォルトのフィルターを使用する場合は省略します。

expandtrue の場合、検索前に Ollama(OLLAMA_EXPAND_MODEL)を介してクエリを書き換え、再現率を向上させます。OLLAMA_URL が必要です。デフォルトは EXPAND_QUERIES 環境変数の値です。

language — BCP-47 言語コード(例: ende)または all で特定の言語に制限します。省略すると SearXNG インスタンスのデフォルトを使用します。searchsearch_and_fetchsearch_and_summarize で利用できます。

engines — 検索を制限するカンマ区切りの SearXNG エンジン名(例: google,duckduckgo)。そのまま転送されます。不明または無効なエンジンは、エラーになる代わりに結果が少なくなります。3 つの検索ツールすべてで利用できます。

site — 結果を 1 つのドメインまたはリストに制限します(例: github.com または ["github.com", "gitlab.com"])。site: クエリ演算子としてベストエフォートで適用されます。ほとんどのエンジン(Google、Bing、DDG、Brave)はこれを尊重しますが、一部は無視します。3 つの検索ツールすべてで利用できます。

max_tokensfetch_url)— 返されるコンテンツのおおよそのトークン予算(文字 ≈ トークン × 4)。省略するとデフォルトの約 2,000 トークン / 8,000 文字になります。最大 10,000 トークン。

target_selectorfetch_url)— 抽出を特定の要素に限定する CSS セレクター(例: articlemain .content)。Firecrawl/Crawl4AI ではネイティブに尊重され、生 HTTP 層ではクライアント側で適用されます。高速パスや一致するものがない場合は無視されます。

wait_for_selectorfetch_url)— JS レンダリングページで抽出前に待機する CSS セレクター。レンダリング層(Firecrawl/Crawl4AI)で尊重されます。生 HTTP(JS なし)では無視されます。

アーキテクチャ

MCP client (stdio)
      │
      ▼
  searxng-mcp ──────────────→ cache ($CACHE_URL)           → result cache (search 1h, fetch 24h, crawl 6h)
      │
      ├── expand (optional) →  Ollama ($OLLAMA_URL)        → rewritten query (qwen3:4b)
      ├── search ───────────→ SearXNG ($SEARXNG_URL)      → raw results
      ├── rerank ───────────→ Reranker ($RERANKER_URL)    → ranked results
      │                       (fallback: SearXNG order if reranker unavailable)
      ├── fetch content ────┬→ GitHub API (github.com)    → markdown
      │                     ├→ Kiwix ($KIWIX_URL)         → ZIM content (Wikipedia/SO/Arch Wiki, fast path)
      │                     ├→ Hister ($HISTER_URL)       → browsing-history index (login-walled/JS-heavy fast path)
      │                     ├→ Firecrawl ($FIRECRAWL_URL) → page markdown (tier 1)
      │                     ├→ Crawl4AI ($CRAWL4AI_URL)  → page markdown (tier 2, optional; via $ADBLOCK_PROXY_URL if set)
      │                     ├→ Raw HTTP + Readability     → page markdown (tier 3 fallback; via $ADBLOCK_PROXY_URL if set)
      │                     └→ Wayback Machine (opt-in)  → archived page markdown (tier 4, $WAYBACK_ENABLED)
      ├── crawl_site ───────┬→ Firecrawl crawl           → page manifest (phase 1)
      │                     ├→ Sitemap parsing           → page manifest (phase 2 fallback, fast-xml-parser)
      │                     └→ BFS crawl (opt-in)        → page manifest (phase 3, $CRAWL_BFS_ENABLED)
      └── summarize (opt.) →  Ollama ($OLLAMA_URL)        → synthesized summary ($OLLAMA_SUMMARIZE_MODEL)
flowchart TD
    entry["fetchPage(url)"]
    cache{"Valkey cache hit?"}
    cached["→ return cached { title, url, text }"]
    github{"GitHub host?\ngithub.com · raw · api"}
    gh_fetch["GitHub API / raw.githubusercontent.com / api.github.com\n→ return"]
    llms{"llms.txt domain?"}
    llms_fetch["Probe /llms-full.txt\nextract matching section\n→ return"]
    kiwix{"Kiwix host?\nKIWIX_URL set"}
    kiwix_fetch["Local Kiwix ZIM\nWikipedia · Stack Overflow · Arch Wiki\n→ cache + return"]
    pdf{".pdf URL?"}
    robots["robots.txt pre-check — tiers 1–3\ndisallowed → RobotsDisallowedError (cached 24h)"]
    tier_skip(["Per-domain tier skip\nsuccess rate <30% over ≥10 tries\nor tier_skip operator override"])
    t1["Tier 1 — Firecrawl\n$FIRECRAWL_URL"]
    t2["Tier 2 — Crawl4AI\n$CRAWL4AI_URL · optional\nadblock proxy if $ADBLOCK_PROXY_URL"]
    t3["Tier 3 — Raw HTTP + Readability\nfallback: raw HTML slice\nadblock proxy if $ADBLOCK_PROXY_URL"]
    t4["Tier 4 — Wayback Machine CDX API\narchived snapshot · WAYBACK_ENABLED=true"]
    post["Post-extraction\nJSON-LD Article · title cascade\nog:title → twitter:title → title → h1 → URL"]
    result["→ return { title, url, text }"]

    entry --> cache
    cache -->|hit| cached
    cache -->|miss| github
    github -->|yes| gh_fetch
    github -->|no| llms
    llms -->|yes| llms_fetch
    llms -->|no| kiwix
    kiwix -->|yes| kiwix_fetch
    kiwix -->|no| pdf
    pdf -->|"yes — skip tier 1"| t2
    pdf -->|no| robots
    robots --> tier_skip
    tier_skip --> t1
    t1 -->|success| post
    t1 -->|"empty / error"| t2
    t2 -->|success| post
    t2 -->|"empty / error"| t3
    t3 -->|success| post
    t3 -->|"empty / error"| t4
    t4 -->|success| result
    post --> result

    style entry fill:#ffffff,stroke:#333333,color:#000000
    style cache fill:#ffffff,stroke:#333333,color:#000000
    style cached fill:#ffffff,stroke:#333333,color:#000000
    style github fill:#dae8fc,stroke:#6c8ebf,color:#000000
    style gh_fetch fill:#dae8fc,stroke:#6c8ebf,color:#000000
    style llms fill:#dae8fc,stroke:#6c8ebf,color:#000000
    style llms_fetch fill:#dae8fc,stroke:#6c8ebf,color:#000000
    style kiwix fill:#fff9c4,stroke:#b8860b,color:#000000
    style kiwix_fetch fill:#fff9c4,stroke:#b8860b,color:#000000
    style pdf fill:#ffffff,stroke:#333333,color:#000000
    style robots fill:#ffffff,stroke:#333333,color:#000000
    style tier_skip fill:#f5f5f5,stroke:#666666,color:#000000
    style t1 fill:#d5e8d4,stroke:#5a8a4a,color:#000000
    style t2 fill:#d5e8d4,stroke:#5a8a4a,color:#000000
    style t3 fill:#d5e8d4,stroke:#5a8a4a,color:#000000
    style t4 fill:#f8cecc,stroke:#a03030,color:#000000
    style post fill:#e1d5e7,stroke:#7a5a8a,color:#000000
    style result fill:#ffffff,stroke:#333333,color:#000000

SearXNG と Firecrawl は必須です。Crawl4AI、Valkey、Ollama、Kiwix、および再ランク付けはオプションです。サーバーは、これらのいずれかが利用できない場合でもグレースフルに劣化します。

アドブロッキング

searxng-mcp は、フェッチ層グループごとに 1 つずつ、2 つの独立したアドブロッキングサイドカーを使用します:

サイドカー

メカニズム

docker/puppeteer-adblock/

層 1(Firecrawl)

CDP レベルのインターセプト — 完全な HTTPS フィルタリング、同じブラウザプロセス

docker/adblock-proxy/

層 2+3(Crawl4AI、生フェッチ)

HTTP フォワードプロキシ — プレーン HTTP 広告ドメインをフィルタリング

層 1 — Puppeteer アドブロック

Firecrawl が使用する firecrawl-puppeteer サービスは、@ghostery/adblocker-puppeteer をアップストリームの trieve/puppeteer-service-ts に重ねるカスタムイメージ(docker/puppeteer-adblock/)を実行します。EasyList + EasyPrivacy は起動時にロードされ、168 時間ごとに更新されます。ブロッカーは Firecrawl が作成するすべてのページに適用されます。広告の多いサイトのフェッチを高速化し、レンダリングされた DOM サイズを縮小します。

環境変数:

変数

デフォルト

説明

ADBLOCK_DISABLE

未設定

true に設定すると、フィルターのロードを完全にスキップします。

ADBLOCK_FILTERS_URL

EasyList + EasyPrivacy

フィルターリスト URL のカンマ区切りリスト。

ADBLOCK_REFRESH_HOURS

168

ブロッカーが設定された URL から再構築する頻度。

ベースイメージは SHA256 ダイジェストで固定されています。変更をデプロイするには、サービスを再構築して再起動します:

docker compose -f ~/docker/firecrawl-simple/docker-compose.yml up -d --build firecrawl-puppeteer

ドメインごとのバイパス: domains.json は、将来のオペレーターオーバーライドのために adblock_skip スロットを予約しています。配線はまだ実装されていません。Firecrawl がカスタムヘッダーを puppeteer-service に転送する必要がありますが、これは現在の API の一部ではありません。スコープクリープ項目 I として追跡されています。

層 2+3 — アドブロックプロキシ

ADBLOCK_PROXY_URL(例: http://adblock-proxy:8118)を設定すると、Crawl4AI と生の Node fetch リクエストが、広告とトラッカーリクエストをフィルタリングする HTTP フォワードプロキシを経由します。HTTPS CONNECT トンネルは変更されずに通過します。MITM はないため、フィルタリングはプレーン HTTP 広告ドメインにのみ適用されます。層 1 の puppeteer フックは、その層の完全な HTTPS フィルタリングをすでに処理しています。プロキシは、層 2 と 3 で漏れるものをカバーします。

サービス定義、構成オプション、デプロイ手順については、docker/adblock-proxy/ を参照してください(docker-compose.full.yml に含まれています)。

データ駆動型層ルーティング

フェッチカスケードを呼び出す前に、searxng-mcp はドメインの tier_stats_30dドメイン機能データベース を参照)を読み取り、少なくとも 10 回の試行で成功率が 30% 未満の層をスキップします。コールドスタートドメイン(10 回未満の試行)はデフォルトのカスケードを維持します。各スキップは reason: low_success_rate を含む searxng.fetch.tier.skipped NATS イベントを発行し、searxng_fetch_total{outcome=skipped} をインクリメントします。

オペレーターオーバーライド。 domains.jsontier_skip マップを追加して、統計に関係なく層を強制的にスキップします:

{
  "tier_skip": {
    "example-bot-blocked.com": ["tier1"],
    "another-site.example": ["tier1", "tier2"]
  }
}

tier_skip キーは、ベアドメイン(example.com はドメインとすべてのサブドメインに一致)またはドメイン + パスプレフィックス(example.com/api/)にできます。ファイルはホットリロードされます。再起動は不要です。手動オーバーライドは reason: operator_override を発行します。

コンテンツタイプ高速パス

構造化された非HTMLコンテンツ(application/json、任意の*+json、XML、YAML、TOML、CSV、またはtext/plain)を提供するURLは、HEADプローブで検出され、完全なFirecrawl/Crawl4AIカスケードではなく、生のHTTP層に直接ルーティングされます。JSONはフェンス付きコードブロック内でプリティプリントされて返されます。以前は、ヘッドレスブラウザにJSON APIレスポンスやCDNアセットをレンダリングするよう依頼すると空のマークダウンが返されたため、APIおよびCDNエンドポイント(registry.npmjs.orgapi.osv.devcdn.jsdelivr.netなど)は単に失敗していました。

保証事項:

  • プローブはフェイルオープンです。到達不能なホスト、HEADを拒否するサーバー、または読み取り不能/解析不能なContent-Typeヘッダーはすべて、通常のカスケードにそのままフォールスルーします。

  • application/xhtml+xmlは意図的に除外されています。これはブラウザ向けのマークアップであり、構造化データではありません。

  • サーバーがtext/plainと誤ってラベル付けしたHTMLは、生のテキストブロックとしてダンプされるのではなく、HTMLとして解析されます。

ドメイン機能データベース

各フェッチは、searxng-mcpがターゲットドメインについて学習した内容をValkeyのdomain:<hostname>(90日TTL、schema_version 5)に記録します。レコードごとにキャプチャされるもの:

  • tier_stats_30d.{tier1,tier2,tier3,tier4,github}.{attempts, ok, fail, last_fail_reason, window_start_ms} — 30日間のローリングウィンドウにおけるティアごとのフェッチ成功率。カットオフは読み取り時に適用され、ティアルーティングの決定とdomain_statsレポートの両方で共有されるため、両者が矛盾することはありません。一度フェッチされてからアイドル状態のままのドメインは、次の書き込みまで古い数値が残るのではなく、実際に空のウィンドウを報告します。tier4(Wayback Machine)スロットは、WAYBACK_ENABLED=trueの場合にのみ記録されます。githubスロットは、GitHub高速パスraw.githubusercontent.com / api.github.com / github.com READMEフェッチ)を記録します。これはティアカスケードをバイパスしますが、ここでは追跡されます。schema_versionのバンプは既存のレコードを新規に再構築します。現在アイドル状態のドメインの累積ウィンドウは破棄されます(1→2、2→3、3→4、4→5のバンプ全体で前例があります)。

  • capabilities.metadata_fetch.{attempts, ok, fail, last_fail_reason} — メタデータサイドチャネルフェッチ(fetchRawHtmlForMetadata、JSON-LD/og:titleサンプリングに使用)の成功/失敗。これは「このドメインにそもそも到達可能か」に答えるものであり、「フルコンテンツ配信が成功したか」ではないため、tier_stats_30dとは別に追跡されます。

  • capabilities.seen_in_search.{count, last_seen_ms} — ドメインがsearch結果にどのくらい頻繁に現れるか。searxSearch()によってすべてのリターンパス(キャッシュヒットを含む)でファイアアンドフォーゲットで書き込まれ、フェッチは実行されないため、ドメインはフェッチされる前に追跡できます。

  • capabilities.robots_txt.{present, fetched, allows_us} — robots.txtの存在と、それが私たちを許可するかどうか

  • capabilities.llms_full_txt.{present, size_bytes, last_checked} — ドメインが/llms-full.txtを提供するかどうか

  • capabilities.json_ld_article.{sampled, present, last_sampled_at} — ページがArticleスキーマのJSON-LDをまったく持っているかどうか(Schema.orgのArticle/NewsArticle/BlogPosting/TechArticleおよびScholarlyArticle/OpinionNewsArticle/LiveBlogPostingなどのサブタイプ。ベア名または完全修飾されたhttps://schema.org/... @typeで一致)。そのスキーマに抽出可能な本文テキストがあるかどうかとは無関係です。多くのサイトはarticleBodyのない見出し/メタデータJSON-LDを公開しており、これは抽出後処理が実際にそれを使用するかどうかとは別の懸念事項です。

  • capabilities.og_title.{sampled, present, last_sampled_at}<meta property="og:title">についても同様

  • preferred_strategy — 現在は、存在するプローブが着地したときにllms_full_txtに設定されます。将来のフェーズではこれを使用してティアカスケードをスキップします。

バンドルされたCLIでレコードを検査するか、エージェントからdomain_statsツール(単一ドメインまたは集計、ツールを参照)を介してクエリします:

pnpm dump-domain docs.anthropic.com

dump-domainは、ウィンドウが期限切れになった場合と、ティアにデータがまったくない場合を区別し、両方を同じように表示することはありません。

同じホスト名に対する同時更新(1回のフェッチ中に並行して発火するティア試行、robotsプローブ、抽出後サンプルレコーダー)は、サーバー側のLua compare-and-setと、単一プロセス自身のライター間の競合を除去するプロセス内のキーごとのキューを組み合わせて直列化され、CASはプロセス間の真に同時の書き込みのみを調停する必要があります。v3.17.0より前のバージョンでは、共有接続に対するWATCH/MULTI/EXECの読み取り-変更-書き込みを使用していましたが、これは実際には同時ライターを直列化しません。その結果、v3.17.0より前に収集されたデータは大幅に不完全でした。アップグレードすると、スキーマバンプを介して既存のティア統計が破棄されます。アップグレード直後はdomain_statsがほぼ空に読み取られ、その後数日かけて再充填されると予想されます。

ドメインDBの永続化

ドメインDBは90日TTLと30日間のローリングウィンドウの下でValkeyにのみ存在するため、キャッシュフラッシュまたはTTLの期限切れにより、再取得にコストがかかる機能学習が消去されます。2つのCLIがそれを永続化します:

pnpm domain-db-maintenance   # SCAN all domain:* records → write a dated JSON snapshot (+ prune) and emit OTel gauges
pnpm restore-domain-db       # re-seed the domain-db from the newest snapshot after a flush
  • domain-db-maintenance はスタンドアロンのジョブです(cronまたはPM2 cron-restartを介してスケジュールで実行します。searxng-mcpはそれぞれが発火する複数の並行するエージェントごとのstdio子プロセスとして実行されるため、プロセス内タイマーとしては実行しないでください)。1つの境界付きSCANが両方の出力を供給します:永続的な日付付きスナップショットと、OTEL_EXPORTER_OTLP_ENDPOINTが設定されている場合は、終了前に強制フラッシュされるゲージ(searxng_domains_trackedsearxng_domains_failingsearxng_domain_tier_success_ratio{tier})。

  • restore-domain-db は、欠落しているキー、またはライブレコードがスナップショットよりも厳密に古いキー(last_fetchを比較)のみを再シードします。より新しいか等しいライブレコードを上書きすることはないため、ライブで部分的に入力されたValkey(例:自動フラッシュリカバリのためのサービス起動シーケンス内)に対して実行しても安全です。

環境変数

デフォルト

目的

DOMAIN_DB_SNAPSHOT_DIR

./domain-db-snapshots

日付付きスナップショットが書き込まれる/読み取られる場所。デプロイメントでは永続パス(appdataまたはNFSマウント)に設定します。

DOMAIN_DB_SNAPSHOT_RETENTION

14

保持するスナップショットの数。古いものはメンテナンス実行ごとに削除されます。

llms.txt高速パス

domains.jsonllms_txt配列)のホワイトリスト登録されたドキュメントドメインに対して、fetchPageは最初に<origin>/llms-full.txtを試し、任意のティアを呼び出す前に要求されたURLに一致するセクションを抽出します。これにより、十分に計装されたドキュメントサイトに対してpuppeteerを実行することを回避し、クリーンなマークダウンセクションを直接返します。プローブの結果と完全な本文はValkey(llms:<origin>:full、存在する/存在しないで24時間/7日)にキャッシュされます。デフォルトのホワイトリスト:docs.anthropic.comdocs.openai.comdocs.stripe.comdocs.crawl4ai.comdocs.firecrawl.devdocs.cursor.comdomains.jsonを編集して拡張します。ファイルはホットリロードされます。

Kiwix高速パス

KIWIX_URLが設定されている場合、既知のオフライン対応ホストに対するフェッチリクエストはFirecrawl/Crawl4AIカスケードの前にインターセプトされ、ローカルのKiwix ZIMアーカイブから提供されます。これにより、Wikipediaのようなサイト(ヘッドレススクレイパーをブロックする)の100%のティア1失敗率が排除され、外部ネットワークトラフィックゼロでクリーンで読み取り可能なコンテンツが返されます。

サポートされているホストとZIMブック(kiwix-serveは--nodatealiases / -zで実行する必要があります):

ホスト

ZIMブック

en.wikipedia.orgwikipedia.org

wikipedia_en_all_mini

stackoverflow.com

stackoverflow.com_en_all

wiki.archlinux.org

archlinux_en_all_maxi

Kiwixパスはllms-txt高速パスの後、robotsゲートの前に実行されます。Kiwixリクエストが失敗するか空を返した場合、完全なティアカスケードが通常どおり実行されます。KIWIX_URLが設定されていない場合、この機能はオーバーヘッドを追加しません。isKiwixHost()は即座にfalseを返します。

KIWIX_URLをkiwix-serveのベースURL(例:http://localhost:8292)に設定します。

YouTubeおよびReddit高速パス

fetch_urlはYouTubeビデオURL(youtube.comyoutu.be)とRedditスレッドURLを認識し、レンダリングされたページをスクレイピングする代わりに直接提供できます:

  • YouTube — ウォッチページからビデオのキャプショントラックを抽出し、トランスクリプトを返します。YOUTUBE_TRANSCRIPT_ENABLED(デフォルトオン)で有効になります。

  • Reddit — 公開.jsonビューをフェッチし、投稿とトップコメントを標準の{title, url, text}形式で返します。HTTP 429ではフォールスルーします。REDDIT_FASTPATH_ENABLED(デフォルトオン)で有効になります。

どちらも非公式で文書化されていないエンドポイント(YouTubeのtimedtext API、Redditの.json)に依存しています。ベストエフォートでSLAはありません。どちらも上流の変更で壊れる可能性があるため、キルスイッチがあります。ミスが発生すると、リクエストは通常のティアカスケードにフォールスルーします(それでもYouTubeページのタイトル/説明を取得できます)。

robots.txt: 両方のエンドポイントはサイトのrobots.txtによって禁止されています(Redditはすべてを禁止し、YouTubeはトランスクリプトが存在する/api/を禁止します)。デフォルトでは、これらの高速パスはそれを尊重して休止状態のままで、カスケードにフォールスルーします。独自のインスタンスでは、YOUTUBE_IGNORE_ROBOTS=true / REDDIT_IGNORE_ROBOTS=trueで直接フェッチをオプトインできます。

サイトクローリング

crawl_siteはサイト全体をクロールし、見つかった各ページのURL/タイトル/スニペットのマニフェストを返します。3フェーズの戦略カスケードを使用します:

  1. Firecrawlクロール — Firecrawlにクロールジョブを送信し(/crawlエンドポイント)、完了するまでポーリングし、完全なページリストを返します。FIRECRAWL_CRAWL_POLL_INTERVAL_MSFIRECRAWL_CRAWL_MAX_WAIT_MSによって制御されます。

  2. サイトマップ解析 — Firecrawlが失敗するか空を返した場合、/sitemap.xml(およびリンクされたサイトマップ)をフェッチし、タイトル/スニペット付きのURLを抽出します。サイトマップXML解析にはfast-xml-parserを使用します。

  3. BFSクロール(オプトイン) — サイトマップ解析も失敗した場合、指定されたURLからCRAWL_BFS_MAX_DEPTHリンクホップまで幅優先クロールを実行します。CRAWL_BFS_ENABLED=trueまたはbfsツールパラメータがtrueの場合にのみ実行されます。

クロール中にフェッチされた完全なページコンテンツはValkeyにキャッシュされます(TTL:CRAWL_MANIFEST_TTL_SECONDS、デフォルト6時間)。マニフェスト内の任意のURLに対する後続のfetch_url呼び出しは、キャッシュから即座に返されます。フォローアップ読み取りのフェッチオーバーヘッドはゼロです。

マニフェストキャッシュはclear_cache(target="crawl")でクリアできます。

Wayback Machineフォールバック

WAYBACK_ENABLED=trueの場合、3つの主要なティアすべてが失敗したときに、4番目のティアがWayback Machine CDX APIにアーカイブされたスナップショットを照会します。返されたコンテンツには、発信元ヘッダー([Archived snapshot – <timestamp> – <original_url>])がプレフィックスとして付けられ、呼び出し元はコンテンツが現在のページ状態を反映していない可能性があることを認識できます。

フェッチ品質

任意のティアが生のHTMLを含むコンテンツを返した後、抽出後パスがタイトルと本文の品質を向上させます:

  • JSON-LD Article抽出 — Schema.orgのArticle / NewsArticle / BlogPosting / TechArticleブロックは、ティア1のクロームスクレイピングよりもクリーンなheadlinearticleBodyを提供します(スクリプトタグごとに1 MBのサイズ上限)。

  • タイトルカスケードog:titletwitter:title<title>(パブリッシャーサフィックス削除付き)→ 最初の<h1> → URLの順にフォールバックします。

  • ティア2 Readability比較 — Crawl4AIがマークダウンを返す場合、JSDOM+Readabilityもその生のHTMLに対して実行され、そのテキストがより長い場合(またはCrawl4AIが500文字未満を返す場合は無条件に)優先されます。

回復力

  • キャッシュは検索を決してハングさせません。 Valkey クライアントは CACHE_COMMAND_TIMEOUT_MS/CACHE_CONNECT_TIMEOUT_MS/CACHE_MAX_RETRIES_PER_REQUEST によって制限されます(設定 を参照)。ストールまたは CPU スパイクしたキャッシュバックエンドは、永久にハングする代わりにコマンドを拒否します。既存のフェイルソフト処理は、その拒否をスローではなくキャッシュミス(ライブで提供)に格下げします。キャッシュ接続失敗、クライアントエラー、コマンドごとのエラーは、スロットルされた [searxng-mcp] stderr 行を出力します(キーごとに重複排除されるため、持続的な障害は洪水ではなく定期的なパンくずリストを残します)。stderr は、デプロイされた PM2 プロセスに配線された唯一のテレメトリシンクです。

  • プロセスクラッシュハンドラuncaughtException はログを記録してから終了コード 1 で終了します(クリーンな PM2 再起動)。unhandledRejection はログを記録して続行し、共有プロセスを静かにクラッシュさせません。

  • グレースフルデグラデーション警告 — リランカーのフォールバックと Ollama/LLM の expand + summarize フォールバックは、品質を静かに低下させるとき(リランカーが利用不可、LLM バックエンドに到達不能)に、それぞれスロットルされた stderr 行を 1 行出力します。

  • バージョンは単一ソース で、実行時に package.json から取得されます(src/version.ts)。McpServer のバージョン、OTel トレーサー/メーターのバージョン、および送信 USER_AGENT はすべてそれを追跡するため、独立してドリフトすることはありません。

可観測性(オプトイン)

トレーシング、メトリクス、イベント公開は完全にオプトインです。以下の環境変数が設定されていない場合、サーバーは可観測性のオーバーヘッドがゼロで、実行時に OpenTelemetry や NATS パッケージを読み込むことはありません。

OpenTelemetry(トレース + メトリクス)OTEL_EXPORTER_OTLP_ENDPOINT をコレクターの HTTP エンドポイントに設定すると、サーバーは以下を出力します:

  • スパン(リクエストごと):tool.<name>expand_query? → searxng_requestrerankfetch(×N)→ tier1_firecrawl | tier2_crawl4ai | tier3_rawfetchpost_extract。さらに search_and_summarize 用の summarize_llm

  • カウンター:searxng_search_total{profile, expand}searxng_fetch_total{tier, outcome}searxng_cache_total{namespace, outcome}searxng_errors_total{stage, error_type}

  • ヒストグラム:searxng_search_duration_seconds{profile}searxng_fetch_duration_seconds{tier, outcome}

標準の OTEL 環境変数が適用されます(OTEL_SERVICE_NAME はデフォルトで searxng-mcp)。

NATS イベントNATS_URL(例:nats://localhost:4222)を設定すると、サーバーはすべての検索、フェッチ、キャッシュヒット/ミス、robots スキップ、エラーに対して構造化イベントを公開します。認証は NATS_CREDS(JWT クレデンシャルファイル)または NATS_USER/NATS_PASSWORD(bcrypt ユーザー名/パスワード)を介して行われます。両方が設定されている場合はクレデンシャルファイル認証が優先されます。サブジェクト:

Subject

When

searxng.search.requested

検索ツールが呼び出されたとき

searxng.search.completed

検索が返されたとき(ソース、レイテンシ、リランク適用を含む)

searxng.fetch.requested

fetchPage が呼び出されたとき

searxng.fetch.tier.miss

ティアが空を返したか例外を投げたとき

searxng.fetch.tier.skipped

robots.txt で禁止されたとき

searxng.fetch.completed

フェッチが解決したとき(tier_servedtext_len、レイテンシを含む)

searxng.cache.hit / .miss

Valkey ルックアップのたびに

searxng.error

ステージタグ付きエラー

各エンベロープには request_id と(OTel が有効な場合)trace_id が含まれるため、サブスクライバーは 2 つのストリームを結合できます。サブジェクトプレフィックスは NATS_SUBJECT_PREFIX で上書き可能です。検索クエリは search.* イベントを通じて流れます。下流のコンシューマーは PII のスクラビングに責任があります。

ポライトネス

  • 正直な User-Agent — 送信リクエストは searxng-mcp/<version> (+https://github.com/TadMSTR/searxng-mcp; personal research) として識別されます。

  • robots.txt 準拠/robots.txt はオリジンごとに 1 回取得され、Valkey の robots:<origin> キーで 24 時間キャッシュされます。禁止されたパスはティアが実行される前にスキップされ、skipped_robots url=… reason=… としてログに記録されます。

トランスポート

stdio(デフォルト)— Claude Code MCP プラグインおよび LibreChat の stdio 設定と互換性があります。

HTTPSEARXNG_MCP_TRANSPORT=http を設定すると、マルチクライアントデプロイメントや Docker ベースのセットアップに適した共有 HTTP/SSE サーバーとして実行されます。SEARXNG_MCP_HOST:SEARXNG_MCP_PORT(デフォルト 127.0.0.1:3001)にバインドします:

SEARXNG_MCP_TRANSPORT=http SEARXNG_MCP_PORT=3001 npx @tadmstr/searxng-mcp

Claude Code を HTTP サーバーに対して登録する:

claude mcp add-json searxng --scope user '{
  "type": "http",
  "url": "http://localhost:3001/mcp"
}'

セッションは Mcp-Session-Id ヘッダーでキー付けされるため、複数のクライアントが同じ共有プロセスに同時に接続できます。アイドルセッションは HTTP_SESSION_IDLE_TIMEOUT_MS 後に掃除され、HTTP_MAX_SESSIONS でハードキャップされます — 設定 を参照してください。

HTTP トランスポート認証

HTTP トランスポートはデフォルトでは認証なしです。これはデフォルトで 127.0.0.1 にバインドするため安全です。SEARXNG_MCP_HOST を他の値(コンテナで実行するために必要な 0.0.0.0 を含む)に変更する場合は、SEARXNG_MCP_AUTH_TOKEN も設定してください:

SEARXNG_MCP_AUTH_TOKEN=$(openssl rand -hex 32)

設定されている場合、GET /health を除くすべてのリクエストは、RFC 6750 のベアラークレデンシャルとしてトークンを保持する必要があります:

Authorization: Bearer <token>

それ以外のもの(ヘッダーなし、異なるスキーム、間違ったトークン)は、WWW-Authenticate: Bearer と JSON-RPC エラーボディを伴う 401 を受け取ります。応答は 3 つのケースすべてで同一であり、提示されたクレデンシャルを決してエコーしません。トークンは SHA-256 ダイジェストとして比較されるため、比較は定数時間であり、長さ情報を漏らしません。

認証済みサーバーを Claude Code に登録する:

claude mcp add-json searxng --scope user '{
  "type": "http",
  "url": "http://localhost:3001/mcp",
  "headers": {"Authorization": "Bearer <token>"}
}'

変数を未設定のままにすると、以前の動作が正確に維持されるため、stdio ユーザーと既存のループバックバインド HTTP デプロイメントは変更を必要としません。呼び出し元ごとの認可モデルはありません。単一のトークンはサーバーへのアクセスを認証し、特定のクライアント ID を認証するわけではありません。起動時に、トークンなしの非ループバックバインドは警告をログに記録します。

GET /health は意図的にチェックから除外されています。 これはコンテナのヘルスチェックとモニタリングの liveness プローブであり、入力を受け取らず、その応答(statuscachesessions)には秘密情報が含まれません。

GET /health — 認証なしの liveness プローブで、MCP エンドポイントとともに localhost にバインドされています。制限付きキャッシュコマンドタイムアウトを通じて Valkey に ping を送信し(チェック自体がハングすることはありません)、以下を返します:

{"status": "ok", "cache": "up", "sessions": 3}

または、キャッシュバックエンドに到達できない場合:

{"status": "degraded", "cache": "degraded", "sessions": 3}

sessions はライブ HTTP セッション数です。キャッシュバックエンドを直接計測せずに MCP 側から劣化したキャッシュを検出するためのシステム管理者モニタリングに役立ちます。

前提条件

  • Node.js 20+

  • pnpm(または npm)

  • 実行中の SearXNG インスタンス

  • 実行中の Firecrawl インスタンス

  • Jina 互換の /v1/rerank エンドポイントを公開する実行中のリランカー(オプション)

  • 実行中の Valkey または Redis 互換インスタンス(オプション、結果キャッシュ用)

  • qwen3:4b および/または qwen3:14b をプルした実行中の Ollama インスタンス(オプション、クエリ拡張と要約用)

SearXNG

SearXNG は JSON 出力形式を有効にする必要があります。settings.yml で:

search:
  formats:
    - html
    - json

リランカー

リランカーは Jina 互換の /v1/rerank エンドポイントを公開する必要があります。軽量な FlashRank ラッパーが適しています — homelab-agentdocker/reranker/ リファレンスを参照してください。

Firecrawl

Firecrawl 互換のインスタンスならどれでも動作します。ローカルの firecrawl-simple デプロイメントで十分です。インスタンスが認証を必要とする場合は FIRECRAWL_API_KEY を設定してください(認証をスキップするローカルデプロイメントではデフォルトで placeholder-local になります)。

Crawl4AI

Crawl4AI は、Firecrawl が空のコンテンツを返す場合(ボットブロックされたページ、JS 多用サイト)に使用されるオプションの第 2 ティアフェッチフォールバックです。有効にするには CRAWL4AI_URL を設定します。未設定の場合、カスケードは生の HTTP フェッチにスキップします。

docker run -d -p 11235:11235 unclecode/crawl4ai:0.8.6

インスタンスが API トークン認証を必要とする場合は、CRAWL4AI_API_TOKEN を設定します。

search_and_summarize パスでは、Crawl4AI リクエストはノイズフィルタリングされたコンテンツ抽出に fit_markdown を使用します。他の呼び出し元(search_and_fetchfetch_url)は raw_markdown を使用します。

Kiwix(オプション)

kiwix-serve は ZIM アーカイブを HTTP で提供します。必要な ZIM ファイルをダウンロードし、--nodatealiases-z)を付けて kiwix-serve を実行して、ブック名を安定させてください:

kiwix-serve --port 8292 --nodatealiases /path/to/zims/

サポートされている各ホストに必要な ZIM ファイル:

  • Wikipedia: wikipedia_en_all_mini(または maxi

  • Stack Overflow: stackoverflow.com_en_all

  • Arch Wiki: archlinux_en_all_maxi

ZIM ファイルは library.kiwix.org からダウンロードできます。

Hister(オプション)

Hister は Firefox 拡張機能によって入力されるブラウジング履歴インデックスです。HISTER_URL が設定されている場合、fetchPage はティアカスケードを呼び出す前に履歴インデックスをチェックします。ログイン壁や JS 多用ページでスクレイパーが失敗する場合に役立ちます。

HISTER_URL に Hister インスタンスのベース URL を設定し、ベアラートークン認証が必要な場合は HISTER_TOKEN を設定します。

Valkey / Redis

Redis 互換のインスタンスならどれでも動作します。Valkey が推奨されます。検索結果は 1 時間キャッシュされ、フェッチされたページは 24 時間キャッシュされます。利用できない場合、サーバーはキャッシュなしで動作します。

Ollama

expandsearch_and_summarize に必要です。必要なモデルをプルしてください:

ollama pull qwen3:4b   # query expansion
ollama pull qwen3:14b  # summarization

think: false の動作は自動的に処理されます — 追加の Ollama 設定は不要です。

設定

すべてのサービス URL は環境変数で設定可能です。

Variable

Default

Description

SEARXNG_URL

http://localhost:8081

SearXNGインスタンスのURL

FIRECRAWL_URL

http://localhost:3002

FirecrawlインスタンスのURL

RERANKER_URL

http://localhost:8787

RerankerインスタンスのURL

FIRECRAWL_API_KEY

placeholder-local

Firecrawl APIキー(必要な場合)

GITHUB_TOKEN

(unset)

GitHub個人アクセストークン — レート制限を60から5,000リクエスト/時に引き上げます

OLLAMA_URL

(unset)

Ollama APIベースURL — expandsearch_and_summarizeに必要です

OLLAMA_API_KEY

(unset)

認証付きOllamaプロキシ用のBearerトークン — 設定するとAuthorization: Bearer <key>ヘッダーを追加します

OLLAMA_EXPAND_MODEL

qwen3:4b

クエリ拡張(expandパラメータ)で使用されるモデル。再ビルドせずに上書きできます。

OLLAMA_SUMMARIZE_MODEL

qwen3:14b

search_and_summarizeで使用されるモデル。再ビルドせずに上書きできます。

LLM_BASE_URL

(unset)

expand + search_and_summarize用のOpenAI互換チャットエンドポイント(例:vLLM、llama.cpp、LM Studio)。APIパスを含める必要があります — 例:http://host:8000/v1 — サーバーは/chat/completionsを追加します。設定するとOLLAMA_URLより優先されるため、別のOllamaモデルを実行する代わりに、すでに読み込まれているモデルを再利用できます。

LLM_MODEL

(unset)

OpenAI互換バックエンドのモデルID。設定するとOLLAMA_EXPAND_MODEL / OLLAMA_SUMMARIZE_MODELを上書きします。

LLM_API_KEY

(unset)

OpenAI互換バックエンド用のBearerトークン — 設定するとAuthorization: Bearer <key>を追加します。

LLM_DISABLE_THINKING

true

chat_template_kwargs.enable_thinking: falseを送信して、推論モデル(例:Qwen3)が直接出力を返すようにします。そのフィールドを拒否するサーバーの場合はfalseに設定します。

CACHE_URL

redis://localhost:6381

Redis互換URL — 結果のキャッシュを有効にします。エイリアスとしてVALKEY_URLまたはREDIS_URLも受け付けます。Redis、Valkey、Dragonflyで動作します。利用できない場合はサーバーはグレースフルに劣化します。

CACHE_COMMAND_TIMEOUT_MS

2500

Valkeyコマンドタイムアウト — 停止/CPUスパイクしたキャッシュバックエンドはハングせずに拒否します(cacheGet()はすべての検索で最初のawaitです)。無効/非正の値はタイムアウトを無効にするNaNになる代わりにデフォルトにフォールバックします。

CACHE_CONNECT_TIMEOUT_MS

3000

Valkey接続タイムアウト。CACHE_COMMAND_TIMEOUT_MSと同じフォールバック動作。

CACHE_MAX_RETRIES_PER_REQUEST

2

Valkeyコマンドが拒否するまでの最大再試行回数。CACHE_COMMAND_TIMEOUT_MSと同じフォールバック動作。

CACHE_TTL_SECONDS

3600

検索結果キャッシュのTTL(秒)

FETCH_CACHE_TTL_SECONDS

86400

取得したページキャッシュのTTL(秒)

CRAWL_MANIFEST_TTL_SECONDS

21600

クロールマニフェストとページコンテンツキャッシュのTTL(秒)(6時間)

CRAWL_MAX_PAGES_DEFAULT

20

max_pagesが渡されない場合にcrawl_siteが返すデフォルトの最大ページ数

CRAWL_BFS_ENABLED

false

crawl_siteでBFSフォールバックをグローバルに有効にするにはtrueに設定します。bfsパラメータで呼び出しごとに有効にすることもできます。

CRAWL_BFS_MAX_DEPTH

3

BFSクロールの最大リンクホップ深度

FIRECRAWL_CRAWL_POLL_INTERVAL_MS

2000

Firecrawlクロールジョブの完了を待つときのポーリング間隔

FIRECRAWL_CRAWL_MAX_WAIT_MS

120000

サイトマップにフォールバックする前にFirecrawlクロールジョブを待つ最大時間

EXPAND_QUERIES

false

クエリ拡張をグローバルに有効にするにはtrueに設定します

CRAWL4AI_URL

(unset)

Crawl4AIインスタンスURL — Firecrawlが失敗した場合の第2層フェッチフォールバックを有効にします

CRAWL4AI_API_TOKEN

(unset)

APIトークン保護付きのCrawl4AIインスタンス用のオプションのBearerトークン

WAYBACK_ENABLED

false

Wayback Machine第4層フォールバックを有効にするにはtrueに設定します — 3つの層すべてが失敗した場合にアーカイブされたスナップショットを取得します

ADBLOCK_PROXY_URL

(unset)

第2層(Crawl4AI)と第3層(生のNode fetch)の広告ブロック用HTTPプロキシURL — 例:http://adblock-proxy:8118docker/adblock-proxy/を参照してください。

KIWIX_URL

(unset)

kiwix-serveベースURL(例:http://localhost:8292)— Wikipedia、Stack Overflow、Arch WikiのKiwix高速パスを有効にします。未設定の場合は機能が無効になり、オーバーヘッドはゼロです。

HISTER_URL

(unset)

Hister閲覧履歴インデックスのベースURL — ログイン必須ページやJS多用ページに対して、層カスケードの前にHister高速パスを有効にします。未設定の場合は機能が無効になり、オーバーヘッドはゼロです。

HISTER_TOKEN

(unset)

Hister API認証用のBearerトークン。HISTER_URLが設定され、インスタンスでトークン認証が有効な場合に必要です。

YOUTUBE_TRANSCRIPT_ENABLED

true

fetch_urlでYouTubeトランスクリプト高速パスを有効にします。無効にするにはfalseに設定します(例:非公式のtimedtextエンドポイントが上流で壊れた場合)。

YOUTUBE_IGNORE_ROBOTS

false

YouTubeのrobots.txt/api/を禁止していても、YouTubeトランスクリプトの取得をオプトインします。デフォルトはrobotsを尊重します(高速パスは休止状態のまま、カスケードにフォールスルーします)。

REDDIT_FASTPATH_ENABLED

true

fetch_urlでReddit .json高速パスを有効にします。無効にするにはfalseに設定します。

REDDIT_IGNORE_ROBOTS

false

Redditのrobots.txtDisallow: /)にもかかわらず、Reddit .jsonの取得をオプトインします。デフォルトはrobotsを尊重します(高速パスは休止状態のまま、カスケードにフォールスルーします)。

SEARXNG_MCP_TRANSPORT

stdio

トランスポートモード:stdio(デフォルト、シングルクライアント)またはhttp(共有HTTP/SSEサーバー)。

SEARXNG_MCP_PORT

3001

HTTPリッスンポート(HTTPトランスポートモードのみ)。

SEARXNG_MCP_HOST

127.0.0.1

HTTPリッスンアドレス(HTTPトランスポートモードのみ)。

SEARXNG_MCP_AUTH_TOKEN

(unset)

HTTPトランスポートのみ。設定すると、GET /healthを除くすべてのリクエストはAuthorization: Bearer <token>を送信するか401を受け取る必要があります。未設定(デフォルト)の場合はチェックが完全に無効になります。SEARXNG_MCP_HOSTがループバックでない場合は必ず設定してくださいHTTPトランスポート認証を参照してください。

HTTP_SESSION_IDLE_TIMEOUT_MS

600000

HTTPトランスポートのみ。これより長くアイドル状態のセッションはバックグラウンドスイープによって追い出されます(処理中のリクエストがあるセッションは除外されるため、長時間のcrawl_site呼び出しがリクエスト中に閉じられることはありません)。ターン途中で強制終了され、transport.oncloseを発火しないクライアントによるセッションマップの増加を制限します。

HTTP_MAX_SESSIONS

256

HTTPトランスポートのみ。ハードキャップのバックストップ — セッションマップがこれを超えた場合、アイドルタイムアウトに関係なく、最も最近使用されていないアイドルセッションが追い出されます。

NATS_USER

(unset)

bcryptユーザー名/パスワード認証用のNATSユーザー名。NATS_PASSWORDと一緒に使用します。NATS_CREDSも設定されている場合は無視されます(credsファイルJWT認証が優先されます)。

NATS_PASSWORD

(unset)

NATSパスワード — NATS_USERを参照してください。

インストール

npm(推奨)

npm install -g @tadmstr/searxng-mcp

または npx で直接実行する:

npx @tadmstr/searxng-mcp

ソースから

git clone https://github.com/TadMSTR/searxng-mcp.git
cd searxng-mcp
pnpm install
pnpm build

出力: build/src/index.js

MCP クライアント設定

Claude Code (CLI)

推奨される方法は、claude mcp add-json を使用して、完全な環境変数サポートでサーバーを登録することです:

claude mcp add-json searxng --scope user '{
  "command": "npx",
  "args": ["-y", "@tadmstr/searxng-mcp"],
  "env": {
    "SEARXNG_URL": "http://localhost:8081",
    "FIRECRAWL_URL": "http://localhost:3002",
    "RERANKER_URL": "http://localhost:8787",
    "OLLAMA_URL": "http://localhost:11434",
    "CACHE_URL": "redis://localhost:6379",
    "CACHE_TTL_SECONDS": "3600",
    "FETCH_CACHE_TTL_SECONDS": "86400",
    "EXPAND_QUERIES": "false",
    "CRAWL4AI_URL": "http://localhost:11235"
  }
}'

これは ~/.claude.json に書き込まれます。~/.claude/settings.json に searxng を追加しないでください。そのファイルは Claude Code での MCP 環境変数の注入には使用されません。

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "searxng": {
      "command": "npx",
      "args": ["-y", "@tadmstr/searxng-mcp"],
      "env": {
        "SEARXNG_URL": "http://localhost:8081",
        "FIRECRAWL_URL": "http://localhost:3002",
        "RERANKER_URL": "http://localhost:8787",
        "OLLAMA_URL": "http://localhost:11434",
        "CACHE_URL": "redis://localhost:6379",
        "CRAWL4AI_URL": "http://localhost:11235"
      }
    }
  }
}

LibreChat (librechat.yaml)

mcpServers:
  searxng:
    type: stdio
    command: node
    args:
      - /path/to/searxng-mcp/build/src/index.js
    env:
      SEARXNG_URL: http://localhost:8081
      FIRECRAWL_URL: http://localhost:3002
      RERANKER_URL: http://localhost:8787
      OLLAMA_URL: http://localhost:11434
      CACHE_URL: redis://localhost:6379
      CRAWL4AI_URL: http://localhost:11235

GitHub URL

GitHub URL は Firecrawl を使わずにネイティブに処理されます。githubFetch はホスト名に基づいて振り分けます:

  • リポジトリルート (github.com/owner/repo) — GitHub API 経由で README を取得します

  • ファイル blob (github.com/owner/repo/blob/branch/path/to/file) — raw.githubusercontent.com に書き換えて raw コンテンツを取得します

  • Raw ファイル (raw.githubusercontent.com/...) — そのまま直接取得します

  • API (api.github.com/...) — レスポンスをデコード(base64 の content フィールド)または JSON として整形出力します

以前は、raw.githubusercontent.comapi.github.com の直接 URL は github.com のみにマッチし、HTML スクレイピングの階層カスケードにフォールスルーしていました。そのカスケードは raw テキストファイルや素の JSON レスポンスをレンダリングできないため、100% 失敗していました。現在は GitHub の高速パスを利用します。

未認証のリクエストは 1 時間あたり 60 回に制限されています。GITHUB_TOKEN を設定すると、1 時間あたり 5,000 回に引き上げられます。

セキュリティ

URL の安全性(SSRF)

呼び出し元が影響を与える、または検出された URL へのすべてのアウトバウンドフェッチ(raw-HTTP 層、robots.txt / llms.txt / Wayback / sitemap プローブ、BFS クロールのリンク取得、GitHub 高速パス)は、2 つの方法で保護されています:

  1. 文字列チェック (assertPublicUrl) — 非 HTTP(S) URL とプライベート/内部 IP リテラル を拒否します: RFC1918 (10.x, 192.168.x, 172.16–31.x)、ループバック (127.x, ::1)、リンクローカル / クラウドメタデータ (169.254.x)、CGNAT (100.64/10)、IPv6 ULA (fc00::/7) とリンクローカル (fe80::/10)、IPv4 マップ、マルチキャスト/予約範囲。

  2. 接続時 DNS 検証 — 共有 undici ディスパッチャーで、その connect.lookup解決された アドレス(ソケットが接続する正確なアドレス)を検証します。これにより、公開ホスト名がプライベートアドレスに解決される DNS リバインディング / TOCTOU のギャップを閉じ、すべてのリダイレクトホップ で再実行されるため、リダイレクトチェーンが内部ネットワークに跳ね返ることはありません。

Firecrawl(tier1)と Crawl4AI(tier2)はターゲット URL を自分で解決して取得するため、上記の接続時ディスパッチャーではカバーできません。fetchPagecrawlSite は、いずれかのサービスにディスパッチする直前に assertResolvedPublic(url) を呼び出します。これは、プライベートまたは予約済みの結果を拒否する 1 回限りのホスト名解決であり、そのパスでの一般的な DNS リバインディングのケースを閉じます(サービスが再解決するため、接続時ガードよりも TOCTOU ウィンドウが狭い)。

設定された内部サービス(Firecrawl、Crawl4AI、SearXNG、Ollama、Reranker)は、それぞれの URL で到達され、意図的にガードされていません。

リダイレクト保護

raw-HTTP と GitHub 高速パスのフェッチは、さらに redirect: "manual" を使用し、3xx レスポンスを完全に拒否します(Location ヘッダーは呼び出し元にエコーバックされません)。リダイレクトを追跡するプローブ(robots.txt、llms.txt、sitemap)は、上記の接続時 DNS 検証でカバーされ、各ホップを再チェックします。

トランスポートの露出

stdio にはネットワーク面がありません。HTTP トランスポートはデフォルトで 127.0.0.1 にバインドされ、その構成では認証されません。SEARXNG_MCP_AUTH_TOKEN を設定せずにループバックから外すと、任意の URL の fetch_url や破壊的な clear_cache を含むすべてのツールが、そのポートにルーティングできるものに公開されます。HTTP トランスポート認証 を参照してください。

依存関係の監査

CI はプッシュのたびに pnpm audit を実行します。ロックファイル(pnpm-lock.yaml)は、再現可能で監査可能なビルドのためにコミットされています。

資格情報の取り扱い

サーバーは資格情報を保存またはログ記録しません。API キー(FIRECRAWL_API_KEYGITHUB_TOKENCRAWL4AI_API_TOKEN)は環境変数から読み取られ、それぞれのサービスへのアウトバウンドリクエストでのみ使用されます。

入力検証

環境変数は起動時に検証されます。RERANK_RECENCY_WEIGHT は NaN、負の値、または 1.0 を超える値に対して警告します。数値ツールパラメータは、範囲制約付きの z.coerce.number() を使用します。

コントリビューション

セットアップ手順、コミット規約、PR プロセスについては CONTRIBUTING.md を参照してください。

統合テスト

ドメイン DB の並行性をカバーする実際の Valkey 統合スイートは VALKEY_TEST_URL でゲートされ、未設定の場合は完全にスキップされるため、Valkey が存在しなくても通常の pnpm test は動作します:

VALKEY_TEST_URL=redis://:<password>@<host>:<port>/<scratch-db> pnpm test

スクラッチデータベースインデックス を使用してください。スイートは domain:* キーを書き込みおよび削除し、安全ガードとしてインデックス 0 または 1 に対しては実行を拒否します。

ライセンス

MIT

Install Server
A
license - permissive license
A
quality
A
maintenance

Maintenance

Maintainers
Response time
6dRelease cycle
19Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for web search and content extraction using DuckDuckGo or SearXNG, with Playwright-based fetching and LLM-powered data extraction.
    140
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    A minimal MCP server that exposes a private SearXNG instance as a search tool over streamable-HTTP, enabling web search from the llama.cpp WebUI or any compatible MCP client.
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Offline-first MCP server for web search and content fetching. It requires no external API keys and uses local models for intent classification, optional cross-lingual search, semantic re-ranking, and direct-answer extraction.
    ISC
  • A
    license
    Not graded
    quality
    C
    maintenance
    A fully local MCP server that provides web search via self-hosted SearXNG and page-to-markdown conversion (static and JS-rendered), all aggregated behind a single endpoint for use with AI assistants.
    MIT

View all related MCP servers

Related MCP Connectors

  • Serper MCP — wraps the Serper Google Search API (serper.dev)

  • MCP server for Google search results via SERP API

  • Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TadMSTR/searxng-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server