↓

把自架 SearXNG 變成 Claude Code 的搜尋工具:Docker、Cloudflare Tunnel 與自製 MCP Worker

··
資訊科技應用 伺服器管理 SearXNG MCP Cloudflare Docker Claude Code

SearXNG 是開源的元搜尋引擎:它自己不建索引,而是把查詢轉給多個搜尋引擎,再把結果整合起來。自架之後,它提供 JSON 格式的搜尋 API,正好可以包成 MCP 工具,讓 Claude Code 這類 AI 助理直接呼叫。

本文記錄兩種接法與各自的限制。文中的網域、帳號與金鑰都用佔位符。


1. 兩種架構
#

本機版 遠端版
路徑 Claude Code → mcp-searxng(stdio)→ 本機 SearXNG Claude Code → Cloudflare Worker → Cloudflare Tunnel → SearXNG
SearXNG 位置 同一台機器,Docker 另一台 Windows 主機,Docker
適合 單機使用、測試與備援 需要跨裝置存取
設定量 少 多,要處理對外暴露與驗證

遠端版之所以要有 Worker,是因為 Cloudflare Workers 跑不了 SearXNG:它需要一個常駐的 Python 程序。Worker 只負責把 MCP 的呼叫轉送到你自己架的實例。

目前以本機版為主,Windows 上的遠端版已停用。兩種都記錄,因為遠端版的設計與遇到的問題,換到其他環境也適用。


2. 本機版:Docker 加 mcp-searxng
#

啟動 SearXNG
#

docker-compose.yml:

services:
  searxng:
    image: searxng/searxng:latest
    container_name: searxng-local
    restart: unless-stopped
    ports:
      - "8081:8080"
    volumes:
      - ./searxng:/etc/searxng:rw
    environment:
      - SEARXNG_BASE_URL=http://localhost:8081/
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      - DAC_OVERRIDE
    logging:
      driver: json-file
      options:
        max-size: "1m"
        max-file: "1"

先把所有 Linux capability 拿掉,只加回容器啟動真正需要的四個,並限制日誌大小。

注意綁定位址。 "8081:8080" 會把這個埠開在所有網路介面上,同一個區網內的其他裝置也連得到,而 SearXNG 本身沒有登入驗證。只在本機使用的話,建議寫成 "127.0.0.1:8081:8080"。

docker compose up -d

第一次啟動後才會在 ./searxng/ 產生 settings.yml。

一定要打開 JSON 格式
#

SearXNG 預設不開 JSON 輸出,MCP 的呼叫會被拒絕。settings.yml 的 search.formats 要有 json:

search:
  formats:
    - html
    - json

踩坑:設定檔改不動
#

settings.yml 是容器內部的使用者建立的,在主機上用一般帳號編輯或 chown 都會得到 EACCES。要改的話,從容器內部改:

docker exec searxng-local sed -i 's/^\(  formats:\)$/\1\n    - json/' /etc/searxng/settings.yml
docker compose restart

註冊 MCP 並驗證
#

claude mcp add searxng-local --env SEARXNG_URL=http://127.0.0.1:8081 -- npx -y mcp-searxng
claude mcp list

看到 Connected 就成功。不想開完整的 Claude Code 工作階段,也可以直接用 JSON-RPC 測 MCP 伺服器本身:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
  | SEARXNG_URL=http://127.0.0.1:8081 npx -y mcp-searxng

成功會列出工具清單。


3. 遠端版:Worker 的設計
#

Worker 很小,只有一個檔案。重點如下:

  • 使用 agents 套件的 createMcpHandler,無狀態,每個請求獨立處理,不需要保存工作階段
  • 只提供一個工具 searxng_search,參數是 query、count(1 到 20,預設 10)、category
  • category 限定八種:general、science、it、news、images、videos、files、map。其中 science 會用到學術類的引擎(arXiv、Google Scholar、PubMed、Semantic Scholar 等),可以拿來找論文
  • 工具內部呼叫 SearXNG 的 /search?q=…&format=json,只取前 count 筆,整理成「標題、網址、摘要」的純文字回傳
  • 上游回應不成功時,回傳 isError: true 與狀態碼,而不是丟出例外

驗證與金鑰
#

Worker 有兩層驗證:

  1. 呼叫 /mcp 要帶 Authorization: Bearer <MCP_AUTH_TOKEN>,不對就回 401
  2. Worker 呼叫 SearXNG 時,帶上 Cloudflare Access 的 Service Token(CF-Access-Client-Id 與 CF-Access-Client-Secret)

SearXNG 自己沒有登入畫面,Cloudflare Access 就是它的驗證層:政策預設封鎖所有人,只讓帶著 Service Token 的 Worker 通過。所有金鑰都用 wrangler secret put 存進 Worker 的 Secrets,不寫進程式碼或設定檔。

npx wrangler secret put SEARXNG_URL
npx wrangler secret put MCP_AUTH_TOKEN          # 用 openssl rand -hex 24 產生
npx wrangler secret put CF_ACCESS_CLIENT_ID
npx wrangler secret put CF_ACCESS_CLIENT_SECRET
npx wrangler deploy

註冊到 Claude Code:

claude mcp add --transport http searxng \
  https://searxng-mcp.<你的子網域>.workers.dev/mcp \
  --header "Authorization: Bearer <MCP_AUTH_TOKEN>"

暴露 SearXNG 的方式
#

遠端版的 SearXNG 容器只綁定 127.0.0.1,區網與網際網路都連不到。要讓 Worker 連得上,用 Cloudflare Tunnel 在同一台主機上把這個本機埠對外轉送,並且一定要在前面放 Access,否則等於把一個沒有登入的搜尋服務公開出去。

cloudflared tunnel create searxng
cloudflared tunnel route dns searxng searxng.<你的網域>
cloudflared tunnel run --url http://localhost:8080 searxng

4. 在 Windows 上踩到的坑
#

遠端版架在 Windows 主機上,用 SSH 遠端操作,遇到幾個不是 SearXNG 本身、但很容易卡住的問題:

  1. Docker 憑證庫解不開。 以 SYSTEM 或排程工作執行的程序,登入工作階段(LUID)和使用者互動式桌面的不同,受 DPAPI 保護的憑證無法解密,會出現「A specified logon session does not exist」。第一次拉映像的 docker compose up -d,要從使用者自己的互動終端機執行,不要透過 SSH 或排程。
  2. Docker Desktop 拉映像時 EOF。 新版預設的 containerd snapshotter 有已知問題,會出現 failed to copy: httpReadSeeker: failed open … EOF,但用 curl 抓同一個位址又是正常的。完全結束 Docker Desktop,把設定檔裡的 UseContainerdSnapshotter 改成 false 再重啟,可以穩定解決。
  3. cloudflared service install 反覆崩潰。 即使手動執行時一切正常,註冊成 Windows 服務後仍會不定時被終止(事件 ID 7031)。改成建立一個「開機時啟動」、以 SYSTEM 執行、帶重試設定的排程工作,直接執行 cloudflared tunnel run,之後穩定運作。
  4. 服務安裝失敗後留下殘留的登錄檔機碼,會讓之後每次安裝都出現「Cannot install event logger」。要先手動刪除 …\Services\EventLog\Application\Cloudflared 這個機碼再重試。
  5. 透過 SSH 啟動的 GUI 程式會在 Session 0 靜默失敗(例如 Docker Desktop)。要改用「登入時」觸發的排程工作,並指定真正的使用者帳號。
  6. Access 政策的變更要 15 到 20 秒才傳到邊緣節點。 剛建立完立刻驗證,可能看起來沒有受保護,這是傳播延遲,不是設定錯誤。

5. 取捨與限制
#

  • 本機版簡單得多。 只要不需要跨裝置,一個 Docker 加一個 npm 套件就夠,不需要 Tunnel、Access 和 Worker。目前也以本機版為主。
  • 遠端版的每一層都是風險面。 公開的 Worker、Tunnel、Access 政策、三組金鑰,任何一個設定錯,都可能讓搜尋服務暴露。
  • Worker 的驗證還能加強。 Bearer Token 目前是用一般的字串比對,不是恆定時間比較,也沒有做請求次數限制。
  • 本機版的埠綁定要自己收斂,見第 2 節的提示。
  • 搜尋結果的品質取決於上游引擎,它們可能因為驗證碼或請求過多暫時封鎖。SearXNG 設定裡有各種暫停時間(例如遇到驗證碼就暫停 1 小時),但引擎被擋時,結果就是會變少。
  • 這份設定是給單人使用的。 設定檔裡的 limiter 與 public_instance 都是關閉的,如果打算讓別人使用這個實例,要重新評估。

小結
#

把搜尋交給自己架的實例,好處是可以決定它查哪些引擎,也不必綁定單一服務的 API 額度;代價是要自己處理部署與驗證。如果只是想在自己的電腦上用,本機 Docker 加 mcp-searxng 是最短的路;要跨裝置,再考慮 Worker 加 Tunnel 的版本,並且從一開始就把 Access 放在前面。