markdown-for-agents-mcp
markdown-for-agents-mcp
一个 MCP (Model Context Protocol) 服务器,它通过 完整的 JavaScript 渲染 抓取 URL,并将其转换为适合 AI 智能体的整洁、节省 Token 的 Markdown。
大多数 MCP 抓取工具使用普通的 HTTP —— 它们只能看到服务器发送的内容,而不会运行任何 JavaScript。这对于静态网站有效,但对于 React、Vue、Angular、SPA 以及任何动态加载数据的页面,它们只会静默地返回空内容或损坏的内容。此服务器通过 Playwright 运行真实的 Chromium 浏览器,因此它会在提取前渲染整个页面 —— 这与人类用户看到的内容完全一致。
由 Playwright 和 markdown-for-agents 库提供支持。它会剔除广告、导航和样板代码 —— 相比原始 HTML,Token 消耗减少高达 80%。
为什么选择 Playwright?
功能 | 普通 HTTP 抓取工具 | markdown-for-agents-mcp |
静态 HTML 页面 | ✅ | ✅ |
React / Vue / Angular 应用 | ❌ | ✅ |
JavaScript 渲染内容 | ❌ | ✅ |
单页应用路由 | ❌ | ✅ |
懒加载 / 无限滚动 | ❌ | ✅ |
相比原始 HTML 的 Token 效率 | 中等 | 减少高达 80% |
反爬虫规避 | 无 | UA 轮换、webdriver 伪装 |
Token 缩减示例: 一个典型的网页新闻文章原始 HTML 大约为 150 KB(约 40,000 个 Token)。经过 Playwright 渲染、DOM 修剪和 Markdown 转换后,同一篇文章仅需约 2,000 个 Token —— 减少了 95%。
目录
功能特性
JavaScript 渲染 —— 由 Playwright 驱动的 Chromium 在提取前渲染 React、Vue、Angular 及任何重度依赖 JS 的页面
结构化输出 —— 工具返回类型化的
structuredContent(url、title、markdown、fetchedAt、contentSize)以及文本响应,兼容 MCP SDK 1.11+智能内容提取 —— 对内容块进行评分并选择主要内容(
main>article>#content>body),自动丢弃侧边栏、导航和广告Token 效率 —— 生成紧凑的、适合 LLM 的 Markdown;基准测试显示相比原始 HTML 减少高达 80% 的 Token
网页搜索 —— DuckDuckGo 搜索,并可选择抓取并转换搜索结果页面
LRU 缓存 —— 50 MB 内存缓存,TTL 为 15 分钟,避免重复抓取
域名过滤 —— 内置追踪器/社交域名黑名单;支持按请求设置允许/阻止列表,以及服务器级允许列表模式
批量抓取 —— 支持可配置并发的多 URL 抓取
HTTP 服务器模式 —— 可作为 HTTP 服务器运行(
--http [port]或HTTP_PORT环境变量),支持可选的 Bearer Token 认证代理支持 —— 传入
PLAYWRIGHT_PROXY可通过代理路由 Playwright 流量健康监控 ——
health_check工具可查看缓存和抓取指标零配置 —— Chromium 在首次运行时自动安装
安装
npm install -g markdown-for-agents-mcpChromium 会通过 postinstall 脚本自动下载。如果失败,请参阅 故障排除。
您也可以不进行全局安装,直接使用 npx 运行:
npx markdown-for-agents-mcpMCP 客户端设置
将服务器添加到您的 MCP 客户端配置中。
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) 或 %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}VS Code (Copilot / Continue)
添加到您的工作区或用户 settings.json 中相关的 MCP 扩展键下,例如:
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}Cursor / Windsurf / Zed
任何实现了 MCP 规范 的客户端都可以使用此服务器。命令入口点是 markdown-mcp(全局安装后可在 PATH 中找到),或者使用本地构建的 dist/index.js 的完整路径。
使用环境变量覆盖
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp",
"env": {
"FETCH_TIMEOUT_MS": "60000",
"LOG_LEVEL": "DEBUG"
}
}
}
}HTTP 服务器模式
除了 stdio,您还可以将服务器作为标准 HTTP 端点运行 —— 这对于共享部署、Docker 或任何偏好 Streamable HTTP 传输的客户端非常有用:
# Start on port 3456
markdown-mcp --http 3456
# Or use the env var
HTTP_PORT=3456 markdown-mcp所有 MCP 流量均在 POST|GET|DELETE /mcp 处理。若要要求 Bearer Token,请设置 MCP_AUTH_TOKEN:
MCP_AUTH_TOKEN=mysecrettoken HTTP_PORT=3456 markdown-mcp客户端必须在每个请求中传递 Authorization: Bearer mysecrettoken。
可用工具
fetch_url
抓取单个 URL 并进行完整的 JavaScript 渲染,返回整洁的 Markdown。
参数:
名称 | 类型 | 必需 | 描述 |
| string | 是 | 要抓取并转换的 URL |
| number | 否 | 请求超时时间(毫秒,覆盖 |
示例:
fetch_url(url="https://example.com/blog/post")文本输出(始终存在,向后兼容):
# Blog Post Title
Source: https://example.com/blog/post
This is the main content of the article, stripped of navigation, ads, and boilerplate.
## Related Section
More content here...
---
*Converted by markdown-for-agents-mcp*结构化输出(MCP SDK 1.11+ 客户端可通过 structuredContent 获取):
{
"url": "https://example.com/blog/post",
"title": "Blog Post Title",
"markdown": "# Blog Post Title\n\nSource: ...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2048
}fetch_urls
并发抓取多个 URL 并返回合并后的 Markdown,每个 URL 对应一个部分。
参数:
名称 | 类型 | 必需 | 描述 |
| string[] | 是 | 要抓取的 URL 列表 |
| number | 否 | 每个请求的超时时间(毫秒) |
示例:
fetch_urls(urls=[
"https://example.com/post1",
"https://example.com/post2"
])文本输出:
# Post 1 Title
Source: https://example.com/post1
...
---
# Post 2 Title
Source: https://example.com/post2
...
---结构化输出(通过 structuredContent):
{
"results": [
{
"url": "https://example.com/post1",
"title": "Post 1 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 1820,
"success": true
},
{
"url": "https://example.com/post2",
"title": "Post 2 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2104,
"success": true
}
],
"summary": { "total": 2, "succeeded": 2, "failed": 0 }
}并发性由 MAX_CONCURRENT_FETCHES 控制(默认:5)。
web_search
搜索 DuckDuckGo,并可选择将搜索结果抓取为 Markdown。使用普通 HTTP 端点以避免反爬虫检测 —— 搜索本身不使用 Playwright。
参数:
名称 | 类型 | 必需 | 描述 |
| string | 是 | 搜索查询 |
| number | 否 | 返回的最大结果数(默认:10) |
| string[] | 否 | 仅包含来自这些域名的结果 |
| string[] | 否 | 排除来自这些域名的结果 |
| boolean | 否 | 抓取并将顶部结果页面转换为 Markdown |
| number | 否 | 请求超时时间(毫秒) |
示例 —— 仅搜索:
web_search(
query="typescript tutorials",
maxResults=5,
allowedDomains=["typescriptlang.org", "github.com"]
)示例 —— 搜索并抓取:
web_search(
query="react hooks guide",
fetchResults=true,
maxResults=3
)文本输出:
# Web Search Results
## Query: typescript tutorials
**Found 5 results in 1234ms**
### Results:
1. [TypeScript Handbook](https://www.typescriptlang.org/docs/)
The TypeScript Handbook provides comprehensive documentation...
2. [Best TypeScript Tutorials](https://github.com/danistefanovic/build-your-own-typescript)
Learn TypeScript by building your own compiler...结构化输出(通过 structuredContent):
{
"query": "typescript tutorials",
"results": [
{ "title": "TypeScript Handbook", "url": "https://www.typescriptlang.org/docs/", "snippet": "...", "domain": "typescriptlang.org" }
],
"fetchedContent": [
{ "url": "https://www.typescriptlang.org/docs/", "markdown": "..." }
],
"durationMs": 1234
}注意:
allowedDomains和blockedDomains参数仅适用于搜索结果过滤。当随后抓取这些结果时,服务器级的BLOCKLIST_DOMAINS/USE_ALLOWLIST_MODE设置仍然适用。
download_file
从 URL 下载二进制文件(PDF、图像、ZIP 等)并保存到本地路径。使用普通 HTTP 客户端 —— 无需 Playwright。强制执行 SSRF 防护和域名黑名单。
参数:
名称 | 类型 | 必需 | 描述 |
| string | 是 | 要下载的文件 URL |
| string | 是 | 保存文件的绝对本地路径(父目录必须存在) |
示例:
download_file(
url="https://example.com/report.pdf",
outputPath="/tmp/report.pdf"
)输出:
{
"savedPath": "/tmp/report.pdf",
"sizeBytes": 204800,
"mimeType": "application/pdf",
"filename": "report.pdf"
}注意: 即使
fetch_url阻止了路径如/download/...的 URL(以避免二进制下载链),此工具仍允许下载。请使用fetch_url处理 HTML 页面 ——download_file将拒绝text/html响应。
health_check
返回当前服务器状态、缓存指标和抓取统计信息。对监控和调试非常有用。
参数: 无
输出示例:
{
"status": "healthy",
"cache": {
"hits": 47,
"misses": 15,
"currentSize": 12,
"totalBytes": 4194304,
"maxBytes": 52428800
},
"metrics": {
"totalFetches": 62,
"successCount": 59,
"errorCount": 3,
"avgDuration": 1840,
"cacheUtilization": 76
}
}CLI 使用
包含一个独立的 CLI (markdown-cli),供 MCP 协议之外使用。
单个 URL
markdown-cli https://example.com多个 URL(批量模式)
markdown-cli -b https://example.com https://example.org https://example.net保存到文件
markdown-cli https://example.com/article > article.md下载二进制文件
markdown-cli -d -o /tmp/report.pdf https://example.com/report.pdf命令参考
命令 | 描述 |
| 抓取单个 URL 并打印 Markdown |
| 批量模式抓取多个 URL |
| 将二进制文件下载到本地路径 |
| 显示帮助 |
配置
所有设置在启动时从环境变量读取,并使用 Zod 进行验证。无效值会导致非零退出并显示描述性错误。
将 .env.example 复制到 .env 即可开始:
cp .env.example .env参考
变量 | 默认值 | 描述 |
|
| 每个抓取请求的超时时间(毫秒) |
|
| 批量操作中的最大并行抓取数 |
|
| 报错前的最大重定向跳转次数 |
|
| 截断前的最大内容大小(字符) |
|
|
|
|
|
|
|
| 最大 LRU 缓存大小(50 MB) |
|
| 缓存条目 TTL(15 分钟) |
|
| 若为 |
| (空) | 以逗号分隔的要阻止的域名(或在允许列表模式下要允许的域名) |
| (空) | 以逗号分隔的要按 URL 路径阻止的正则表达式 |
|
| 搜索请求的默认超时时间(毫秒) |
|
| 二进制文件下载的超时时间(毫秒) |
| (未设置) | 设置后,在此端口启动 HTTP 服务器而不是 stdio |
| (未设置) | 所有 HTTP 请求所需的 Bearer Token(仅限 HTTP 模式) |
| (未设置) | Playwright 的代理服务器 URL(例如 |
| (未设置) | 以逗号分隔的绕过代理的域名 |
所有日志均写入 stderr,以保持 stdout 的整洁,供 MCP 协议使用。
安全性
默认域名黑名单
默认阻止以下域名,以防止意外抓取追踪器、广告网络和社交平台,这些平台通常会积极阻止机器人或提供低质量内容:
doubleclick.net, facebook.com, twitter.com, tiktok.com, hotjar.com, mixpanel.com, bit.ly 以及其他约 20 个域名(完整列表请参阅 src/utils/domainBlacklist.ts)。
如果您需要抓取被阻止的域名,请将
USE_ALLOWLIST_MODE=false并将其添加到BLOCKLIST_DOMAINS—— 这会增加到黑名单中,而不会删除现有条目。要允许默认被阻止的域名,您需要 fork 并修改domainBlacklist.ts。
URL 路径阻止
某些 URL 路径模式无论域名如何都会被阻止(例如 OAuth 回调、二进制文件下载、支付/结账路径、管理面板)。这些可以防止意外抓取敏感或非内容 URL。
允许列表模式
设置 USE_ALLOWLIST_MODE=true 和 BLOCKLIST_DOMAINS=yourdomain.com,trusted.org 可将服务器限制为仅从明确列出的域名抓取。建议用于生产部署。
重定向策略
跨域重定向被阻止。服务器仅遵循同源
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/JohnnyFoulds/markdown-for-agents-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server