Model Context Protocol
Connect Crawllr once and Claude can pull any site into the conversation — following
links, reading sitemaps, or going straight through the WordPress REST API — and hand
it back as Markdown, llms.txt or JSON.
https://crawller.dev/api/mcp.php No account, no API key. Rate limited to 150 requests per hour per IP.
Pick whichever matches how you use Claude. All three end up with the same three tools.
One command in your terminal. Add --scope user
to make it available in every project rather than just the current one.
claude mcp add --transport http crawllr https://crawller.dev/api/mcp.php Confirm it registered:
claude mcp list Added as a custom connector — no config file to edit.
On older desktop builds without a Connectors screen, edit
claude_desktop_config.json instead —
~/Library/Application Support/Claude/ on macOS,
%APPDATA%\Claude\ on Windows — and
bridge the HTTP server through mcp-remote:
{
"mcpServers": {
"crawllr": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://crawller.dev/api/mcp.php"]
}
}
} Restart the app fully after editing — reopening the window is not enough.
If you would rather not send URLs through a hosted service, run the STDIO server yourself. Needs PHP 8.1+ and Python 3.9+. The source is not public yet — get in touch if you want a copy.
# from your Crawllr checkout
# PHP side (the MCP server itself)
composer install --ignore-platform-req=ext-fileinfo
# Python side (the crawler engine)
pip install trafilatura beautifulsoup4 requests lxml_html_clean
# register it
claude mcp add crawllr -- php "$(pwd)/mcp/server.php"
The --ignore-platform-req flag is there because
the MCP SDK lists ext-fileinfo as a requirement it
never actually exercises. Drop the flag if your PHP has the extension.
Three tools. Claude picks between them on its own, but knowing what they do helps you ask for the right thing.
inspect_site Call this first. Checks what a site exposes before you crawl it: whether it publishes a sitemap, whether the WordPress REST API is open, and how many pages each strategy would reach. Returns a recommended crawl_mode to pass straight to crawl_website.
| Parameter | Type | Default | Description |
|---|---|---|---|
url
req
| string | — | The site to inspect. Must be http or https. |
crawl_website The main one. Crawls a site and returns its content. Three strategies, and six output formats — set output_format to markdown or llms-full when the result is going straight into a prompt.
| Parameter | Type | Default | Description |
|---|---|---|---|
url
req
| string | — | The site to crawl. |
crawl_mode | string | "normal" | One of "normal", "sitemap", "wordpress". Use what inspect_site recommends. |
output_format | string | "json" | "json", "clean-json", "markdown", "llms", "llms-full", or "text". |
max_pages | integer | 100 | 1–1000. |
depth | integer | 2 | Link levels to follow, 1–5. Ignored in wordpress mode. |
wp_types | string | "posts,pages" | WordPress mode only. Comma-separated REST bases, or "all" for every public post type. |
include_paths | string | "" | Restrict to these path prefixes, e.g. "/blog,/docs". |
exclude_paths | string | "" | Skip these paths, e.g. "/tag,/author". |
include_subdomains | boolean | false | Follow links onto subdomains of the same site. |
crawl_page One URL, nothing else. Extracts a single page without following any links. Much faster than crawl_website when you only need one URL.
| Parameter | Type | Default | Description |
|---|---|---|---|
url
req
| string | — | The page to fetch. |
markdown_only | boolean | false | Return just the markdown text instead of the full JSON object. |
The mode decides how pages are found, and it is the single biggest factor in how much
of a site you actually get. inspect_site
works this out for you.
normal Any site. The fallback when there is nothing better.
Walks internal links breadth-first from the start page. Only reaches pages that something links to.
sitemap Static sites, and anywhere with orphan pages.
Reads robots.txt and every common sitemap location, follows sitemap indexes, and handles gzipped sitemaps. Finds pages no menu links to.
wordpress Any WordPress site with an open REST API.
Enumerates published content directly through /wp-json/wp/v2/. The most complete option, and several times faster — there is no HTML to parse. Falls back to fetching the live page when a page builder leaves the REST content empty.
Once it is connected, plain English is enough — but naming the tool or mode makes Claude go straight there.
Pull the whole docs site into context
“Use crawllr to inspect docs.example.com, then crawl it with whatever mode it recommends and give me the result as llms-full.”
Audit a client site for broken links
“Crawl example.com from its sitemap with crawllr and list every page that returned an error.”
Grab one page, cleanly
“Use crawl_page on https://example.com/blog/post and give me just the markdown.”
Everything a WordPress site has published
“example.com is WordPress — crawl it with crawl_mode wordpress and wp_types all.”
With the default output_format: "json"
you get a summary plus one object per page. A page that fails to load is reported in
pages[].error rather than aborting
the crawl — which makes a crawl double as a broken-link report. Ask for
markdown or
llms-full instead when you just want
the text.
{
"summary": {
"startUrl": "https://example.com/",
"baseDomain": "example.com",
"totalPages": 42,
"successPages": 40,
"errorPages": 2,
"crawlMode": "sitemap",
"crawlTime": "18.6s",
"truncated": false
},
"pages": [
{
"url": "https://example.com/pricing",
"title": "Pricing",
"description": "Simple per-seat pricing.",
"content": "## Pricing\n\nSimple per-seat pricing...",
"wordCount": 612,
"extraction_method": "trafilatura",
"metadata": { "canonical": "...", "openGraph": { } },
"schema": { "jsonLd": [ ], "microdata": [ ] },
"links": { "internal": [ ], "external": [ ] },
"error": null
}
]
} The tools do not show up
Start a new conversation — existing ones do not pick up newly added servers. In Claude Code, run claude mcp list to confirm it registered and shows as connected.
A crawl returns far fewer pages than the site has
It probably ran in normal mode on a site whose pages are not all linked. Ask for inspect_site first, then crawl with the mode it recommends — sitemap and wordpress both reach pages that link-following cannot.
Pages come back with no content
The page is likely rendered client-side in JavaScript. Crawllr reads the HTML the server sends, so a site that ships an empty shell and fills it in with JS will extract as blank.
The crawl timed out
Lower max_pages, or switch to wordpress or sitemap mode — both are much faster than link-following because they know every URL up front.
Rate limited
150 requests per hour per IP on the hosted endpoint. Run the STDIO server locally if you need more than that.
Prefer a browser? The same engine runs the web crawler.
Open the web crawler →