Skip to main content
Glama
README.md
# Ax MCP — 遠端網頁爬蟲 MCP Server

> 💡 **去 AI 味聲明**:本專案文檔使用台灣在地化繁體中文去 AI 味工具 [opencode-speak-human-tw](https://github.com/cawa0505/opencode-speak-human-tw) 進行校對與語感微調,拒絕罐頭套話與空泛修辭。

基於 Node.js 的 MCP Server,封裝 [yusukebe/ax](https://github.com/yusukebe/ax)(「AI 時代的 curl」),
透過 [supergateway](https://github.com/supercorp-ai/supergateway) 橋接為 **遠端 Streamable HTTP(`/mcp`)** 介面,供 OpenCode Interpreter 呼叫(SSE 亦可)。

> ⚠️ **關於 ax 的重要說明**:規格書假設 ax 是「Playwright 爬蟲」並有 `--selector` / `--format` / `--wait` 參數。
> 實際上 ax **不是** Playwright 工具——它是用 Bun + linkedom 做的**非瀏覽器**快速爬蟲,不執行 JavaScript。
> 它的真實參數是 `--md`(markdown)、`--json`、`--row`、`--outline`、positional selector、`-m <secs>`(逾時)等。
> 本專案已把規格的 `scrape_web` 介面**對應到 ax 真實 CLI**(見下方參數對照),因此可正常運作。
> 若你需要抓取 JS 重度渲染的 SPA,請改用瀏覽器型工具(Playwright / playwright-cli MCP),ax 不適用。

## 專案結構

```
├── src/
│   └── index.ts        # MCP Server 核心邏輯
├── build/              # tsc 編譯產物(node build/index.js)
├── package.json        # 依賴(@modelcontextprotocol/sdk, supergateway, zod)
├── tsconfig.json
├── Dockerfile          # ax-mcp: node + bun + supergateway
├── docker-compose.yml  # 單個 service: ax-mcp(3014)
└── README.md
```

## 工具:`scrape_web`

| 參數 | 類型 | 預設 | 說明 | 對應 ax |
|------|------|------|------|---------|
| `url` | string (必填) | — | 目標網址 | positional |
| `selector` | string (選填) | — | CSS selector 精確擷取 | positional + `--text` |
| `format` | `"text"` \| `"json"` | `"text"` | 輸出格式 | `text`→`--md`;`json`→`--json` |
| `wait` | number (選填) | — | 秒數預算 | 對應 ax `-m`(請求逾時);ax 無瀏覽器等待 |

- 有 `selector`:擷取該 selector 匹配元素的文字(`--text`)。
- 無 `selector` + `format:"text"`:整頁可讀 markdown(`--md`)。
- 無 `selector` + `format:"json"`:結構化抓取報告(`{status, ok, ms, headers, body}`)。
- 輸出會經正則濾除 ANSI color codes,確保 LLM 收到純淨文字。
- 執行失敗回傳 `{ isError: true, content: [...] }`(含 stderr)。

## 傳輸協定與架構說明(SSE vs Streamable HTTP)

### SSE (`http://localhost:8000/sse`) 與 Streamable HTTP (`/mcp`) 的底層差異

標準的 MCP 伺服器大多使用 `SSE (Server-Sent Events)` 傳輸。不過,當你在跨主機、遠端或 Homelab 叢集部署(例如讓 OpenCode Interpreter 跨網連線遠端 MCP)時,這兩種協定在底層運作上有決定性的差別:

1. **`http://localhost:8000/sse` (標準 SSE 協定)**
   * **缺點**:標準 SSE 是有狀態(Stateful)的協定。當 OpenCode 這類用戶端連線時,必須維持一條長連線。一旦跨越外網或經過反向代理(如 Caddy、Nginx),這條長連線很容易因為逾時、網路抖動或代理伺服器的快取限制而斷線,造成 MCP 連線不穩定。
   * **適用場景**:完全在本地端(Localhost)跑 stdio 的開發環境,或用戶端與伺服器位於同一個安全且無代理阻擋的區域網路。

2. **`http://<host>:3014/mcp` (Streamable HTTP 協定)**
   * **優點**:透過 [supergateway](https://github.com/supercorp-ai/supergateway),將 MCP 伺服器轉換為無狀態(Stateless)的標準 HTTP POST 請求。
   * **特色**:
     * **穿透力強**:每次工具呼叫都是獨立的短 HTTP 連線,能輕鬆穿透 CDN、反向代理、WAF 與 VPN,不會被防火牆或代理伺服器阻擋。
     * **維護簡單**:不需維持 TCP 長連線,自然沒有逾時斷連、需要重連的問題。這正是 OpenCode `type: "remote"` 的原生運作方式。
     * **專案定位**:本專案直接將 supergateway 整合進 Docker,並預設輸出為 `streamableHttp`,提供跨主機、跨網段穩定的遠端連線配置範例。

---

## Docker 部署

本專案支援兩種 Docker 部署方式:**直接從 GitHub Registry 拉取預建映像檔**(最快、免下載原始碼),或 **Clone 專案本機編譯建置**(適合客製化與二次開發)。

### 方式一:直接使用 GitHub Registry 部署(免 Clone)

若您僅需使用服務,無需下載專案原始碼,只需在主機的部署目錄(例如 `$HOME/ax-mcp`)建立一個 `docker-compose.yml` 檔案:

```yaml
services:
  ax-mcp:
    image: ghcr.io/cawa0505/ax-mcp:latest
    container_name: ax-mcp
    restart: unless-stopped
    ports:
      - "3014:8000"
```

並於該目錄執行以下指令拉取並啟動:

```bash
docker compose up -d
```

---

### 方式二:Clone 專案本機編譯部署(適合二次開發)

如果您想自訂或擴充功能,可以進行二次開發:
- **調整爬蟲邏輯**:希望自訂 `ax` 的抓取細節或前處理規則。
- **擴充 MCP 工具**:在 `src/index.ts` 內增加自訂的 MCP Tool。
- **效能調優**:修改 `Dockerfile` 內的快取與編譯設定。

請複製本專案,並依以下步驟建置:

```bash
# 複製專案
git clone https://github.com/cawa0505/ax-mcp.git
cd ax-mcp

# 啟動並於本機編譯建置
docker compose up -d --build
```

#### 本機測試與偵錯步驟

如果不使用 Docker,想在本機直接編譯、修改與測試,請執行以下指令:

```bash
# 1. 安裝套件
npm install

# 2. 本地編譯(tsc -> build/index.js)
npm run build

# 3. 測試執行 stdio 協定(可供標準 MCP client 連線)
node build/index.js
```

本地透過 `supergateway` 進行橋接與協定轉換測試:

```bash
# 預設啟動為 SSE(端點:http://localhost:8000/sse)
npx supergateway --stdio "node build/index.js" --port 8000

# 啟動為 Streamable HTTP(端點:http://localhost:8000/mcp,對應 OpenCode "type: remote")
npx supergateway --stdio "node build/index.js" --port 8000 --outputTransport streamableHttp
```

---

### 服務說明

啟動後:
- `ax-mcp` 將於 `http://<host>:3014/mcp` 提供 Streamable HTTP 介面(容器內監聽 8000)。
- 內部透過 `supergateway` 將 `node build/index.js`(stdio)包裝為遠端 MCP 介面。
- 建置時已將 `bunx` 快取預熱完畢(原生處理 `yusukebe/ax` 的 git 依賴),因此運行期無需額外聯網下載 `ax`。

> 💡 **關於瀏覽器型爬蟲 (Playwright)**:
>
> 由於 Playwright MCP 是微軟官方維護的成熟標準工具 (`@modelcontextprotocol/server-playwright` / `mcp/playwright`),本專案定位是基於 `yusukebe/ax` 的輕量、超高速非瀏覽器 HTML/XML 擷取。
> 
> 若你仍需要動態網頁渲染 (SPA) 與瀏覽器自動化,建議直接使用 Microsoft 官方 Playwright MCP。你可透過 `supergateway` 以 `--stateful` 模式橋接官方 stdio 程序以實現遠端 Streamable HTTP:
> ```bash
> npx supergateway --stdio "npx -y @modelcontextprotocol/server-playwright" --port 3015 --stateful
> ```

### 環境變數

| 變數 | 預設 | 說明 |
|------|------|------|
| `AX_COMMAND` | `bunx yusukebe/ax` | 覆寫 ax 呼叫方式。允許 git fetch 的環境可用 `npx -y yusukebe/ax`;若有靜態 `ax` 可用 `ax`。 |

## OpenCode 連線

請在 OpenCode 設定檔 `~/.config/opencode/opencode.json` 的 `"mcp"` 區段中加入本服務。本服務以 **Streamable HTTP** 暴露(路徑 `/mcp`),對應 OpenCode 的 `type: "remote"`:

```json
{
  "mcp": {
    "ax-mcp": {
      "type": "remote",
      "url": "http://<ax-mcp-host>:3014/mcp"
    }
  }
}
```

> 本機部署將容器 8000 對應到 host 的 **3014**(8000 已被佔用)。若你改了 `docker-compose.yml` 的 ports 對應,請同步修改此處的 port。

若 OpenCode 與容器不在同網段 / 需跨網,請在 `docker-compose.yml` 用 `--cors` 限制來源,
並視情況以反向代理(Caddy/Pangolin)加上 TLS 與驗證。

TDQS

A4.7/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no possibility of confusion between tools. The single tool's purpose is clearly described as scraping web pages.

Naming Consistency5/5

The tool name 'scrape_web' follows a clear verb_noun pattern. Since there is only one tool, the naming is inherently consistent.

Tool Count4/5

While one tool is on the low end of the typical range, it is appropriate for a narrowly focused server dedicated to a single scraping action. The tool is well-scoped and does not feel overly thin for its stated purpose.

Completeness4/5

The tool covers the core scraping workflow: fetching and parsing a page into clean text or JSON. The only notable gap is the lack of JavaScript execution, which is explicitly documented and hints at using a browser tool for SPAs, but that seems like a reasonable limitation rather than an incomplete surface.

Maintenance

ActivitySlowing
ResponsivenessNo issues