Skip to main content
Glama
Website Content Crawler MCP Server

Website Content Crawler MCP Server

README.md
# Website Content Crawler MCP Server

MCP wrapper that runs the **apify/website-content-crawler** actor for real via `apify-client`
and returns its pages as JSON. Every call either returns crawled content or a structured
error — it never reports a fake success.

## What it costs

Runs bill **your** Apify account at the rate listed for
[apify/website-content-crawler](https://apify.com/apify/website-content-crawler) — this
server adds nothing on top. No token, no charge: calls return `missing_token` before any
run starts.

Live output demo (same crawl logic, rendered): https://website-content-crawler.vercel.app

## Setup

```bash
npm install
export APIFY_TOKEN=apify_api_...   # https://console.apify.com/settings/integrations
npm start                          # stdio MCP server
```

## Tool: `crawl_website`

Input:

| field       | type   | default            | notes                                  |
|-------------|--------|--------------------|----------------------------------------|
| `url`       | string | required           | http/https URL to crawl                |
| `maxPages`  | number | 10                 | capped at 50                           |
| `crawlerType` | string | `cheerio`        | or `playwright:chrome` for JS-rendered |

Output envelope (same shape every call):

```json
{
  "status": "ok",
  "run": { "id": "<apify run id>", "status": "SUCCEEDED" },
  "page_count": 3,
  "total_in_dataset": 3,
  "pages": [{ "url": "...", "title": "...", "text": "...(≤5000 chars)" }]
}
```

Error codes: `invalid_url`, `missing_token`, `apify_auth_failed`, `actor_run_failed`,
`run_not_succeeded`, `dataset_fetch_failed`.

## Smoke test

```bash
printf '%s\n' \
 '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}' \
 '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
 '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
 '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"crawl_website","arguments":{"url":"https://example.com"}}}' \
 | node index.js
```

With no `APIFY_TOKEN` set, request id 3 must return
`{"status":"error","error":{"code":"missing_token",...}}` — proof the handler reaches the
real Apify boundary instead of inventing a result.

TDQS

A4.1/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool is exposed, so there is no chance of confusing it with another. Its purpose is clear and unambiguous.

Naming Consistency5/5

The single tool name 'crawl_website' uses a consistent verb_noun structure. With no other tools, there are no conflicting naming conventions.

Tool Count3/5

A one-tool server is borderline. The tool covers the core need, but the server feels thin and could reasonably expose additional operations like crawl status or history.

Completeness3/5

The server offers a direct crawl-and-extract action, but lacks supporting operations such as configurable crawling options, job inspection, or the ability to cancel or list previous runs. The surface is functional but minimal.