关于 Fetch MCP Server
Fetch MCP Server 让 AI 助手通过 stdio 服务发送 HTTP 请求并提取网页内容。它提供 HTML 转换和站点元数据工具,并默认启用 SSRF 防护,包括检查重定向目标和解析出的地址。
主要功能
- 01支持带请求头、认证和重试的 HTTP 方法
- 02将 HTML 转为 Markdown 或结构化文本
- 03提取正文、元数据和链接
- 04解析站点地图、RSS/Atom 源和 robots.txt
- 05检查请求及重定向以防 SSRF
适用场景
- 01获取网页内容供 AI 助手参考
- 02提取文章正文和页面元数据
- 03检查站点地图、订阅源或爬取规则
MCP 相关
它以 stdio MCP 服务运行,向兼容 MCP 的客户端提供 HTTP 请求和网页提取工具。默认启用 SSRF 防护,并逐跳检查重定向目标。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
15收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 目标 URL(http:// 或 https://) |
| headers | object | 否 | 额外请求标头,采用键值对象格式 |
| retries | integer | 否 | 遇到 408/425/429/500/502/503/504 时采用指数退避重试(默认 0) |
| max_bytes | integer | 否 | 响应正文截断前的最大大小(字节)(默认 5MiB,上限 100MiB) |
| basic_auth | object | 否 | HTTP Basic 身份验证凭据 |
| basic_auth.password | string | 是 | |
| basic_auth.username | string | 是 | |
| timeout_ms | integer | 否 | 每次尝试的超时时间(毫秒),涵盖 DNS、每次重定向跳转和正文传输(默认 10000,最大 120000)。重试时会重新分配完整时限;整个调用最长为 5 分钟。 |
| user_agent | string | 否 | 覆盖 User-Agent(默认标识为 @yawlabs/fetch-mcp) |
| decode_text | boolean | 否 | 强制文本解码(true)或二进制 base64(false)。默认自动选择:text/*、json、xml 等使用文本;其他情况使用二进制。 |
| bearer_token | string | 否 | 作为 Authorization: Bearer <token> 发送的 Bearer 令牌 |
| max_redirects | integer | 否 | 要跟随的最大重定向跳数(默认 5) |
| allow_private_hosts | boolean | 否 | 允许此调用访问环回/私有/链路本地目标(默认 false)。除非服务器操作员使用 FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 启动 fetch-mcp,否则会拒绝访问——无论如何,默认都会启用 SSRF 防护。 |
详细介绍
@yawlabs/fetch-mcp
一键即可将其添加到本地 Yaw MCP 配置中,以便在每个 Yaw Terminal 会话中使用。也可以按照下方说明手动安装。
这是一款功能全面的 HTTP 抓取 MCP 服务,适用于 AI 助手。客户端由你选择:它以 stdio MCP 服务的形式运行,因此任何兼容 MCP 的客户端(Claude Code、Claude Desktop、Cursor、mcph 等)都可以安全地抓取网页内容。
它能为模型提供什么
| 工具 | 功能 |
|---|---|
http_get / http_head / http_options | 基础 HTTP 请求,支持请求头、身份验证、超时、大小限制和重试 |
http_post / http_put / http_patch / http_delete | 写入类 HTTP 请求,支持 JSON 或原始请求体 |
fetch_html_to_markdown | GET 页面并转换为简洁的 Markdown(比原始 HTML 小 3–8 倍) |
fetch_html_to_text | GET 页面并转换为纯文本,同时保留区块结构 |
fetch_reader | 阅读模式提取——分离文章正文并返回标题和 Markdown |
fetch_meta | 提取 <head> 元数据:标题、描述、OpenGraph、Twitter 卡片、JSON-LD、订阅源、图标 |
fetch_links | 提取所有外链,将其解析为绝对 URL,并分类为站内或站外链接 |
fetch_sitemap | 解析 sitemap.xml(包括 gzip 压缩文件和 sitemap 索引链) |
fetch_feed | 将 RSS 2.0 或 Atom 1.0 订阅源解析为条目 |
fetch_robots | 解析网站的 robots.txt,并返回指定路径和用户代理对应的判定结果 |
安全性
默认启用 SSRF 防护。服务会拒绝以下请求:
- 环回地址(
127.0.0.0/8、::1) - RFC1918 私有地址范围(
10/8、172.16/12、192.168/16) - 链路本地地址(
169.254/16、fe80::/10),包括云元数据端点169.254.169.254` - CGNAT(
100.64/10) - IPv6 唯一本地地址(
fc00::/7) - 多播 / 广播地址
- IPv4 映射的 IPv6 地址(
::ffff:0:0/96)会根据 IPv4 规则再次检查;IPv4 兼容地址(::/96)、IPv4 转换地址(::ffff:0:0:0/96)和 6to4(2002::/16)中嵌入的 IPv4 地址也会进行同样的检查 - Teredo(
2001::/32)、NAT64(64:ff9b::/96、64:ff9b:1::/48)、站点本地地址(fec0::/10)和仅丢弃地址(100::/64) - 全局单播范围(
2000::/3)之外的所有其他 IPv6 地址,以及其中的非全局地址块(3fff::/20、2001:2::/48、2001:10::/28) - Azure WireServer 地址
168.63.129.16 - 非
http/https协议(file://、gopher://、javascript:等) - 主机名
localhost和任何*.localhost
每一跳重定向都会在建立连接前,根据上述所有规则重新验证协议、字面 IP 地址和 localhost*,因此从公共主机重定向到 http://127.0.0.1、http://169.254.169.254 或 ftp://… 的 302 响应都会被拦截。对于主机名,每一跳只解析一次 DNS,并检查返回的所有地址;经过验证的 IP 会固定到 HTTP 调度器中,确保后续 TCP 连接连接到该确切地址,从而消除 DNS 重绑定 TOCTOU 窗口。跨源重定向时会剥离 Authorization、Cookie 和 Proxy-Authorization 请求头。
连接到私有主机(开发)
模型会选择工具参数,而模型并不可信:通过抓取的页面注入的提示词可以要求执行任何操作。因此,除非操作人员通过使用 FETCH_MCP_ALLOW_PRIVATE_HOSTS=1 启动服务来启用,否则每次调用中的 allow_private_hosts: true 选项都会被拒绝(true/yes/on 也有效;任何无法识别的值都会按关闭处理,并在 stderr 中说明)。设置该变量后,调用仍须主动请求此权限:未设置 allow_private_hosts 的请求仍会受到防护。
{
"mcpServers": {
"fetch": {
"command": "npx",
"args": ["-y", "@yawlabs/fetch-mcp@latest"],
"env": { "FETCH_MCP_ALLOW_PRIVATE_HOSTS": "1" }
}
}
}
仅在模型确实需要访问内部网络的环境中设置此项——例如本地开发机,而不是带有元数据端点的云虚拟机。
安装并运行
# One-off (auto-updates each spawn via @latest)
npx -y @yawlabs/fetch-mcp@latest
# Or globally
npm i -g @yawlabs/fetch-mcp
fetch-mcp
在 Node 上运行时,需要 Node 22.19 或更高版本(这是其 HTTP 客户端 undici 8 的最低版本要求;启动器会清楚地提示并拒绝使用较旧的 Node,而不是直接崩溃)。在 oam 下运行时(启动器优先使用已安装的 oam),Node 版本没有影响。
在 Claude Code / Claude Desktop 中配置
将以下内容添加到客户端的 MCP 配置中(通常是 claude_desktop_config.json 或 ~/.claude.json):
{
"mcpServers": {
"fetch": {
"command": "npx",
"args": ["-y", "@yawlabs/fetch-mcp@latest"]
}
}
}
也可以通过 mcph 配置:
mcph add fetch
工具参考
http_get、http_post、http_put、http_patch、http_delete、http_head、http_options
通用参数:
| 字段 | 类型 | 默认值 | 含义 |
|---|---|---|---|
url | string | — | 绝对 URL |
headers | object | — | 自定义请求标头 |
timeout_ms | int | 10000 | 每次尝试的超时时间,涵盖 DNS、每次重定向跳转以及响应正文。重试时会重新计时;整个调用最长为 5 分钟。取消工具调用会停止请求 |
max_bytes | int | 5242880 (5 MiB) | 如果响应正文更大,则截断 |
max_redirects | int | 5 | 允许的重定向跳转次数 |
retries | int | 0 | 遇到 408/425/429/5xx 时的重试次数,采用退避策略(遵循 Retry-After) |
user_agent | string | @yawlabs/fetch-mcp/<v> | 覆盖 User-Agent |
basic_auth | {username,password} | — | 注入 Authorization: Basic … |
bearer_token | string | — | 注入 Authorization: Bearer … |
allow_private_hosts | bool | false | 允许本次调用访问环回、私有或链路本地目标。除非运维人员设置了 FETCH_MCP_ALLOW_PRIVATE_HOSTS=1,否则会被拒绝(详情) |
decode_text | bool | 自动 | 未设置时,根据响应的 Content-Type 自动判断(text/*、JSON、XML、JS、form-urlencoded 为文本;其他为二进制)。显式设置为 true 可强制解码为文本,设为 false 则强制将正文以 base64 格式放入 body_base64。 |
支持正文的工具(POST/PUT/PATCH/DELETE)还接受:
| 字段 | 类型 | 含义 |
|---|---|---|
body | string | 原始请求正文 |
body_json | any | 结构化正文,以 JSON 编码,并自动设置 Content-Type: application/json |
content_type | string | 覆盖 Content-Type |
响应格式:
{
ok: boolean;
status: number;
statusText: string;
url: string; // final URL after redirects
headers: Record<string,string>;
body_text?: string;
body_base64?: string; // when decode_text=false
json?: unknown; // auto-parsed when response is application/json
truncated?: boolean; // set when max_bytes hit
redirects?: string[]; // chain of intermediate URLs
duration_ms: number;
error?: string;
}
fetch_html_to_markdown
对 URL 发起 GET 请求,移除脚本、样式、iframe、svg、canvas 以及 <nav>、<footer>、<aside>,并转换为使用 atx 标题、围栏代码块和短横线项目符号的 Markdown。适用于将网页内容提供给大模型,同时避免超出上下文预算。
fetch_html_to_text
执行相同的抓取,但输出纯文本,并以换行保留块级结构。适用于模型不需要 Markdown 格式的情况。
fetch_reader
按以下顺序提取正文主体:<article>、<main>、itemprop="articleBody"、常见 CMS 类名(post-content、entry-content 等),最后以 <body> 作为回退选项。返回:
{
url: string; // final URL after redirects
title?: string; // og:title, then <title>, then <h1>
byline?: string; // meta[name=author] / article:author
wordCount: number;
markdown: string; // main content converted to markdown
}
fetch_meta
对 URL 发起 GET 请求并返回页面头部元数据,不下载完整正文(默认上限为 2 MiB):
{
url: string;
title?: string;
description?: string;
canonical?: string;
language?: string;
robots?: string;
og: Record<string, string>; // first value per key (og:title, og:image, og:type, ...)
twitter: Record<string, string>; // first value per key
article: Record<string, string>; // first value per key
ogAll: Record<string, string[]>; // only keys that appear > once (e.g. multiple og:image)
twitterAll: Record<string, string[]>;
articleAll: Record<string, string[]>;
icons: Array<{ rel: string; href: string; sizes?: string }>;
feeds: Array<{ href: string; title?: string; type?: string }>; // RSS/Atom
jsonLd: unknown[]; // parsed application/ld+json blocks
}
fetch_links
抓取页面并返回每个 <a href> 链接及其文本,将链接解析为绝对 URL。遵循 <base href>。跳过 #、javascript:、mailto:、tel:、data:、file:。根据链接与页面主机的关系,将每个链接分类为 internal 或 external。可选参数包括 filter、dedupe 和 limit。
fetch_sitemap
获取 sitemap.xml 或站点地图索引,并返回 URL 列表:
{
sitemaps: string[]; // indexes followed, in order
urlCount: number;
truncated: boolean; // hit max_urls
childSitemaps: string[]; // listed but not fetched (past max_depth or max_sitemaps)
warnings: Array<{ url: string; error: string }>;
urls: Array<{
loc: string;
lastmod?: string;
changefreq?: string;
priority?: number;
}>;
}
.xml.gz 格式的 gzip 站点地图会自动解压。max_depth 控制要跟进的站点地图索引层数(默认值为 1)。在站点地图索引上将 max_depth: 0,会返回索引的 childSitemaps 列表,而不会获取任何子项(有助于低成本地了解结构)。部分失败(例如一个子站点地图返回 500,而其他站点地图成功)会通过 warnings 返回,不会导致整个调用中止。max_sitemaps(默认值为 50,最大值为 1000)限制单次调用获取的站点地图文档数量,索引也计入其中;超出限制的子项会列在 childSitemaps 下,并附带警告。整个调用最多持续 5 分钟。max_bytes(默认值为 20 MiB)限制每个站点地图的大小,以及 gzip 站点地图解压后的大小;超过限制的站点地图会报错(子站点地图则会产生警告),而不会静默返回不完整的 URL 列表。
fetch_feed
解析 RSS 2.0 或 Atom 1.0 订阅源:
{
kind: "rss" | "atom" | "unknown";
title?: string;
description?: string;
link?: string;
updated?: string;
entryCount: number;
truncated: boolean; // hit limit
entries: Array<{
title?: string;
link?: string;
id?: string;
published?: string;
updated?: string;
author?: string;
summary?: string;
content?: string;
categories?: string[];
}>;
}
fetch_robots
获取 <origin>/robots.txt,解析并返回:
{
robotsUrl: string;
status: number;
userAgent: string;
path: string;
allowed: boolean;
matchedRule: string | null; // the longest-match Allow/Disallow that decided it
crawlDelay: number | null; // from the matched group
sitemaps: string[]; // top-level Sitemap: declarations
rawRobotsText: string; // first 512KB
note?: string; // only when robots.txt 404s
}
/robots.txt 返回 404 表示没有规则,因此判定结果为 allowed: true。响应保持相同结构:status: 404、matchedRule: null、crawlDelay: null、sitemaps: []、rawRobotsText: "",以及 note。其他任何非 2xx 状态都会作为错误返回。
解析器遵循 Google 的规则:最长匹配优先;* 是通配符片段;$ 锚定路径末尾;当 UA 匹配时,特定用户代理组优先于 * 通配符组(比较时使用实际匹配的代理令牌长度,而不是组中第一个代理的长度)。长度相同时,Allow 优先于 Disallow。
开发
npm install
npm run build
npm test # vitest
npm run lint # biome
npm run typecheck
测试会在 127.0.0.1:0 上启动本地环回 HTTP 服务,以测试真实的请求/响应路径,不会模拟 HTTP。SSRF 测试会验证:除非启用了运营者开关,且请求选择启用 allow_private_hosts,否则默认拒绝策略仍适用于该本地服务。
许可证
MIT © Yaw Labs
链接
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。