Skip to main content
Glama
README.md
# webfetch-mcp

A minimal **read-only** MCP server that fetches hard-to-scrape web pages via an
anti-detection browser and returns clean, **token-efficient markdown**.

It exposes exactly **one tool** — `fetch(url) → markdown` — annotated
`readOnlyHint: true`, so MCP clients that gate writes behind approval prompts
(such as a Cloudflare OS MCP gatekeeper) run it **without asking**.

## Why

`camofox-mcp` exposes 47 browser-automation tools, none annotated read-only, so
every fetch queues for manual approval. For the common case — *just get me the
page text* — that friction is needless: a fetch reads a page and mutates nothing.
This server declares that honestly and returns the most token-efficient
representation available.

## Extraction strategy

camofox-browser has no markdown or readability endpoint — only Playwright ARIA
snapshots (a role/name tree, not prose) and arbitrary JS evaluation. This server
bundles `@mozilla/readability` + `turndown` (via esbuild into IIFE strings at
build time) and ships them into the page in a single `/evaluate` call:

1. **Readability** — clean main-article markdown (best; ~10× smaller than a snapshot)
2. **innerText** — real prose, falls back here for SPAs / dashboards Readability can't parse
3. **snapshot** — ARIA tree, last resort for canvas-heavy or empty-text pages

The output carries a `Strategy:` marker so the caller knows which ran.

## Usage

```bash
# Build
npm install
npm run build   # bundles libs + compiles TS

# Run (defaults: port 8090, browser at localhost:9377, no auth)
node dist/src/index.js
```

### Configuration (env)

| Var | Default | Purpose |
|---|---|---|
| `CAMOFOX_URL` | `http://localhost:9377` | camofox-browser REST API base URL |
| `WEBFETCH_HTTP_PORT` | `8090` | MCP Streamable HTTP listen port |
| `WEBFETCH_API_KEY` | _(unset)_ | If set, clients must send `Authorization: Bearer <key>` |

### MCP protocol check

```bash
# initialize + tools/list (expect 1 tool, readOnlyHint=true)
curl -X POST localhost:8090/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"0.0.0"}}}'
```

## Deployment

Built by a Komodo Build → `registry.zxcapp.de/docker/webfetch-mcp`, then deployed
as a sibling of `camoufox-mcp` in the `camoufox` stack. Shares netbird-client's
network namespace so it reaches camofox-browser at `localhost:9377`.

See `services/komodo/plans/webfetch-mcp/` in `home-infra` for the full deploy plan.