Install
$ agentstack add mcp-jdevalk-web-fetch-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
web-fetch-mcp
MCP server that fetches any URL and returns clean Markdown — not raw HTML.
[](https://github.com/jdevalk/web-fetch-mcp/actions/workflows/ci.yml) [](LICENSE) [](https://bun.sh) [](https://www.typescriptlang.org)
Claude Code's built-in WebFetch returns raw HTML. web-fetch-mcp tries two strategies in order:
- Content negotiation — sends
Accept: text/markdownand returns the body if the server honours it (fast, zero browser overhead). - Headless browser — launches Obscura, navigates to the URL, and extracts Markdown via the
LP.getMarkdownCDP method. Falls back toDOM.getOuterHTML+ turndown if the CDP result is too sparse.
Results are cached in-memory for 15 minutes.
Quick start
1. Clone and install
git clone https://github.com/jdevalk/web-fetch-mcp.git
cd web-fetch-mcp
bun install
2. Download the Obscura binary for your platform
bun run setup
3. Register with Claude Code
claude mcp add web-fetch-mcp -- bun run /path/to/web-fetch-mcp/index.ts
To make Claude always prefer this server over the built-in WebFetch, add "denyTools": ["WebFetch"] to ~/.claude/settings.json.
Tool reference
fetch
Fetch a URL and return its content as clean Markdown.
| Parameter | Type | Default | Description | |---|---|---|---| | url | string | — | The URL to fetch | | force_browser | boolean | false | Skip content negotiation and go straight to the headless browser |
Response shape:
{
markdown: string;
url: string; // final URL after redirects
title: string; // page or first H1
contentType: "negotiated" | "browser" | "fallback";
}
How it works
Strategy 1 — content negotiation
Sends Accept: text/markdown, text/plain;q=0.9, */*;q=0.5. If the server responds with content-type: text/markdown or text/plain, the body is returned directly without launching a browser. Most servers don't honour this, but those that do (e.g. joost.blog) get a near-instant response.
Strategy 2 — Obscura CDP
Obscura is launched once as a persistent subprocess on port 9222. Each fetch opens a fresh browser target so pages are fully isolated and don't share cookies or state. After navigation, LP.getMarkdown walks the DOM into structured Markdown. If the result is too sparse (< 50 chars), the server falls back to DOM.getOuterHTML` + turndown.
Cache — 15-minute TTL
A 15-minute in-memory TTL cache (matching Claude Code's built-in WebFetch) avoids duplicate fetches within a session.
Platform support
| Platform | Status | |---|---| | macOS arm64 | ✅ | | macOS x8664 | ✅ | | Linux x8664 | ✅ | | Linux aarch64 | ✅ |
Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
Security
To report a vulnerability, see [SECURITY.md](SECURITY.md).
License
MIT — see [LICENSE](LICENSE).
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jdevalk
- Source: jdevalk/web-fetch-mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.