@yawlabs/fetch-mcp is a comprehensive HTTP fetch MCP server for AI assistants. Bring your own client: it runs as a stdio MCP server, so Claude Code, Claude Desktop, Cursor and anything else that speaks the protocol can fetch web content safely. MIT licensed, from Yaw Labs, published on npm.

npx -y @yawlabs/fetch-mcp@latest

GitHub · npm · Add to Yaw MCP

Who it is for

Anyone who wants an agent that can read the web, and would rather that ability not double as a blind-SSRF probe against their own network. Giving a model a raw HTTP client is easy; giving it one that refuses to dial your metadata endpoint, and hands pages back small enough to fit in context, is the work:

Install

1. No API key. There is nothing to provision and no account to create.

2. Add the server to your client. In your client's MCP config - usually claude_desktop_config.json or ~/.claude.json:

{ "mcpServers": { "fetch": { "command": "npx", "args": ["-y", "@yawlabs/fetch-mcp@latest"] } } }

The @latest tag means each spawn picks up the current release. If you would rather pin it yourself, install it globally and point your client at the binary instead:

npm i -g @yawlabs/fetch-mcp fetch-mcp

3. Restart and approve. Restart Claude Code (or your MCP client) and approve the Fetch server when prompted. Then ask it something: "Fetch this page in reader mode and summarize it."

Running Yaw MCP? One click adds it to your local config, and it is then available in every Yaw Terminal session.

What it covers

ToolWhat it does
http_get / http_head / http_optionsBare HTTP requests with headers, auth, timeout, size cap and retry
http_post / http_put / http_patch / http_deleteWrite-method HTTP with a JSON or raw body
fetch_html_to_markdownGET a page and convert it to clean markdown - 3-8x smaller than the raw HTML
fetch_html_to_textGET a page and convert it to plain text with block structure preserved
fetch_readerReader-mode extraction - isolates the article body and returns title plus markdown
fetch_metaExtract head metadata: title, description, canonical, OpenGraph, Twitter cards, JSON-LD, feeds, icons
fetch_linksEvery outbound link, resolved to absolute URLs and classified internal or external
fetch_sitemapParse sitemap.xml, including gzipped sitemaps and sitemap-index chaining
fetch_feedParse an RSS 2.0 or Atom 1.0 feed into entries
fetch_robotsParse a site's robots.txt and return the verdict for a given path and user-agent

The HTTP tools share a common parameter set: custom headers, request timeout, a byte cap that truncates oversized bodies and flags the response as truncated, a redirect-hop limit, and a retry count that backs off on 408, 425, 429 and 5xx while honoring Retry-After. Text decoding is auto-detected from the response Content-Type and can be forced either way; binary bodies come back base64-encoded. JSON responses are parsed for you, and the response carries the final URL after redirects along with the chain of intermediate ones.

The structured parsers are deliberately more than regex. fetch_reader tries <article>, then <main>, then itemprop="articleBody", then common CMS class names, falling back to <body>. fetch_sitemap returns a partial failure - one child sitemap returning a 500 while the others succeed - under warnings rather than aborting the whole call, and can list an index's children without fetching any of them when you only want to discover structure. fetch_robots follows Google's rules: longest match wins, * is a wildcard segment, $ anchors the end of the path, a specific user-agent group beats the wildcard group, and Allow beats Disallow on equal-length ties.

Safety and control

SSRF protection is on by default. The server refuses requests to:

Blocking a list of ranges is the easy half. The harder half is that a hostname can resolve to a public address when you check it and a private one when you connect - so DNS is resolved once per redirect hop, every returned address is checked, and the verified IP is pinned into the HTTP dispatcher so the subsequent TCP connection dials that exact address. That closes the DNS-rebinding time-of-check-to-time-of-use window. Redirects are checked at every hop too: a 302 to http://127.0.0.1 served through a public host gets caught rather than followed. Authorization headers are stripped on cross-origin redirects, so a credential you pass for one host does not leak to whatever it redirects you to.

When you genuinely do need internal access - a development server on your own machine - set allow_private_hosts: true on that request. It is per-request rather than a global switch on purpose: opting in names the one call that needs it instead of turning the protection off for everything the agent does afterwards.

The repo's own tests take the same line. They spin up a real loopback HTTP server and exercise the actual request and response path rather than mocking HTTP, and the SSRF tests verify that the default-deny still applies to that local server unless the request explicitly opts in.

Frequently asked questions

What does the Fetch MCP server do?

It gives a model the web in shapes it can actually use. Bare HTTP methods with headers, auth, timeouts, a size cap and retries; page conversion to clean markdown or plain text; reader-mode extraction that isolates the article body; head metadata including OpenGraph, Twitter cards and JSON-LD; every outbound link resolved to an absolute URL; sitemap, RSS and Atom parsing; and a robots.txt verdict for a given path and user-agent.

Does it stop an agent reaching my internal network?

Yes, by default. Requests to loopback, RFC1918 private ranges, link-local including the cloud metadata endpoint, CGNAT, unique-local IPv6, multicast and broadcast are refused, as are non-http schemes and localhost by name. DNS is resolved once per redirect hop, every returned address is checked, and the verified IP is pinned into the dispatcher so the TCP connection dials that exact address, which closes the DNS-rebinding window. Authorization headers are stripped on cross-origin redirects.

Can I fetch from a private host when I really need to?

Yes. Set allow_private_hosts to true on the individual request, for example when fetching from a development server on your own machine. It is per-request rather than a global switch on purpose: opting in names the one call that needs internal access instead of disabling the protection for everything the agent does afterwards.

Why convert pages to markdown instead of sending raw HTML?

Context budget. The markdown conversion strips scripts, styles, iframes, svg and canvas along with nav, footer and aside, and comes out 3-8x smaller than the raw HTML. Reader mode goes further by isolating just the article body and returning the title with it, so a long page costs a fraction of the tokens it otherwise would.

Do I need an API key?

No. There is no key and no account. It runs as a stdio MCP server, so any MCP-compatible client can use it: add the config block, restart your client, approve the server. Per-request basic auth and bearer tokens are available for sites that need them, and those credentials are stripped on cross-origin redirects.

Related MCP servers

Further reading

Published by Yaw Labs.