内容
# 文档抓取 MCP 服务器
基于 Bun 的模型上下文协议(MCP)服务器,用于抓取文档页面和限定文档爬取。
服务器公开一个 MCP 工具,`fetch_doc_content`。它抓取根 URL,提取可读的 Markdown,排名链接,并在明确的深度、页面、超时和范围限制内抓取链接页面。结果以结构化的 JSON 返回,包含爬取元数据、页面内容、排名链接、截断标志和每页错误。
## 功能
- 使用 `axios` 实现快速静态抓取路径
- 可选的 Puppeteer 渲染,用于客户端渲染或薄页面
- Markdown 提取,支持标题、列表、代码块、表格、引用和链接
- 真实的爬取深度语义:
- `depth: 1` 只返回根页面
- `depth: 2` 包括直接子链接
- `depth: 3` 包括孙链接,最高可达 `5`
- URL 规范化后去重:删除片段、跟踪参数、默认端口和尾部斜杠重复
- 通过相同来源和可选 `pathPrefix` 进行爬取范围限定
- 限定 `maxPages`、`maxConcurrency`、全局超时、每页超时和每页内容截断
- 具有明确每页失败的部分结果
- 与广告工具模式共享的运行时参数验证
## 要求
- Bun `>=1.3.0`
- 如果 `render` 为 `auto` 或 `always`,则需要安装 Puppeteer 浏览器
该项目使用 Bun 进行依赖管理、运行时执行、构建和测试。
## 安装
```bash
bun install
bun run build
```
配置您的 MCP 客户端:
```json
{
"mcpServers": {
"docs-fetch": {
"command": "bun",
"args": ["/path/to/docs-fetch-mcp/build/index.js"]
}
}
}
```
在本地开发时无需构建:
```json
{
"mcpServers": {
"docs-fetch": {
"command": "bun",
"args": ["/path/to/docs-fetch-mcp/src/index.ts"]
}
}
}
```
## 工具
### `fetch_doc_content`
抓取一个 URL,并可选地抓取链接页面。
参数:
| 名称 | 类型 | 默认值 | 限制 | 描述 |
|---|---:|---:|---:|---|
| `url` | 字符串 | 必需 | 仅限 HTTP/HTTPS | 要抓取的根 URL。 |
| `depth` | 数字 | `1` | `1` 至 `5` | 与根链接的距离。 |
| `maxPages` | 数字 | `10` | `1` 至 `50` | 跨越抓取的最大页面数。 |
| `maxConcurrency` | 数字 | `3` | `1` 至 `8` | 同时抓取的最大页面数。 |
| `timeoutMs` | 数字 | `45000` | `5000` 至 `120000` | 全局抓取超时。 |
| `perPageTimeoutMs` | 数字 | `10000` | `1000` 至 `60000` | 每页抓取超时。 |
| `render` | 字符串 | `auto` | `auto`、`always`、`never` | 浏览器渲染策略。 |
| `sameOrigin` | 布尔值 | `true` | 不适用 | 限制抓取的链接到相同的来源。 |
| `pathPrefix` | 字符串 | 省略 | 不适用 | 可选的路径前缀抓取范围,例如 `/docs`。 |
| `contentLimit` | 数字 | `12000` | `1000` 至 `50000` | 每页截断前的 Markdown 字符数。 |
| `includeLinks` | 布尔值 | `true` | 不适用 | 在返回的页面对象中包含排名链接。 |
示例请求:
```json
{
"url": "https://example.com/docs",
"depth": 2,
"maxPages": 8,
"pathPrefix": "/docs",
"render": "auto"
}
```
响应形状:
```json
{
"rootUrl": "https://example.com/docs",
"normalizedRootUrl": "https://example.com/docs",
"explorationDepth": 2,
"maxPages": 8,
"pagesExplored": 3,
"pagesFailed": 1,
"timedOut": false,
"durationMs": 1234,
"crawl": {
"sameOrigin": true,
"pathPrefix": "/docs",
"maxConcurrency": 3,
"render": "auto",
"perPageTimeoutMs": 10000
},
"content": [
{
"url": "https://example.com/docs",
"finalUrl": "https://example.com/docs",
"depth": 0,
"status": 200,
"title": "文档",
"description": "示例文档",
"canonicalUrl": "https://example.com/docs",
"headings": ["文档"],
"content": "# 文档\n\n...",
"contentLength": 2400,
"truncated": false,
"fetchedWith": "http",
"links": [
{
"url": "https://example.com/docs/api",
"text": "API 参考",
"score": 18.5,
"internal": true
}
]
}
],
"errors": [
{
"url": "https://example.com/docs/missing",
"depth": 1,
"error": "请求失败,状态码为 404",
"status": 404
}
]
}
```
## 爬取行为
- 爬取采用广度优先方式。
- URL 在去重和加入队列前会进行规范化。
- `sameOrigin: true` 拒绝与规范化根 URL 来源不同的链接。
- `pathPrefix` 进一步将链接限制在根来源的路径前缀内。
- `includeLinks: false` 隐藏链接在返回的页面对象中,但不会禁用链接发现以进行爬取。
- `render: "never"` 仅使用 HTTP 抓取路径。
- `render: "always"` 对每个抓取的页面都使用 Puppeteer。
- `render: "auto"` 首先尝试 HTTP,然后在 HTTP 失败或提取的内容非常少时使用 Puppeteer。
- 浏览器备用程序目前保留渲染的响应状态,并提取页面正文,即使对于非 2xx 页面也是如此。
## 架构
```text
src/index.ts CLI 入口点
src/server.ts MCP 服务器线路和工具注册
src/config/tool-options.ts 共享工具模式/默认/范围元数据
src/tool/fetch-doc-content-args.ts 运行时参数验证
src/crawler/docs-crawler.ts 爬取协调和队列管理
src/crawler/page-fetcher.ts HTTP 抓取,浏览器备用,提取协调
src/browser/browser-manager.ts 可重用的 Puppeteer 浏览器/页面处理
src/content/content-extractor.ts 页面元数据/内容提取门户
src/content/main-content-selector.ts 主内容选择
src/content/link-extractor.ts 链接规范化,去重和排名
src/content/markdown-renderer.ts HTML 到 Markdown 渲染
src/content/text-cleanup.ts 共享文本规范化助手
src/utils/url.ts URL 规范化和范围实用程序
src/types/index.ts 共享 TypeScript 类型
```
MCP 模式和运行时选项规范化共享相同的元数据来源,位于 `src/config/tool-options.ts`。在添加新选项时,请先在那里添加,然后通过验证和爬虫选项连接行为。
## 开发
```bash
bun install
bun run dev
bun run test
bun run typecheck
bun run build
```
脚本:
- `bun run dev`:从 TypeScript 源代码运行 MCP 服务器。
- `bun run test`:在 `src` 下运行 Bun 测试。
- `bun run typecheck`:运行 TypeScript,禁用发出。
- `bun run build`:使用 Bun shebang 发出 `build/index.js`。
- `bun run start`:运行已构建的 MCP 服务器。
## 测试
测试与它们所覆盖的模块一起存放:
- `src/crawler/docs-crawler.test.ts`:爬取深度、范围、失败和链接可见性。
- `src/crawler/page-fetcher.test.ts`:抓取/渲染备用特性描述。
- `src/content/content-extractor.test.ts`:Markdown 提取和截断。
- `src/tool/fetch-doc-content-args.test.ts`:边界验证和模式/默认同步。
- `src/utils/url.test.ts`:URL 规范化和范围助手。
在更改行为时,请先添加或更新特性测试。对于重构,请保持 `bun run test`、`bun run typecheck` 和 `bun run build` 绿色。
## 备注
- 使用 `render: "never"` 进行快速静态文档爬取和测试。
- 使用 `pathPrefix` 用于文档站点,这些站点与营销页面、博客或应用程序共享一个域名。
- 仅当调用者使用 `render: "never"` 时,才能跳过 Puppeteer 浏览器安装。
- 自定义 Markdown 渲染器故意被特性测试覆盖;除非进行明确的行为更改,否则请保留输出兼容性。
## 许可证
MIT