npm package: @lmcc-dev/mult-fetch-mcp-server
Description: An MCP protocol-based web content fetching tool that supports multiple modes and formats, can be integrated with AI assistants like Claude
Author: Martin
Latest version: 1.3.2

# mult-fetch-mcp-server

[![npm 版本](https://img.shields.io/npm/v/@lmcc-dev/mult-fetch-mcp-server.svg)](https://www.npmjs.com/package/@lmcc-dev/mult-fetch-mcp-server)
[![许可证: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js 版本](https://img.shields.io/node/v/@lmcc-dev/mult-fetch-mcp-server)](https://nodejs.org/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue.svg)](https://www.typescriptlang.org/)
[![MCP SDK](https://img.shields.io/badge/MCP%20SDK-1.7.0-brightgreen.svg)](https://github.com/modelcontextprotocol/typescript-sdk)
[![GitHub Stars](https://img.shields.io/github/stars/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/stargazers)
[![GitHub Forks](https://img.shields.io/github/forks/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/network/members)
[![GitHub Issues](https://img.shields.io/github/issues/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/issues)
[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/pulls)
[![npm 下载量](https://img.shields.io/badge/下载量-即将更新-lightgrey)](https://www.npmjs.com/package/@lmcc-dev/mult-fetch-mcp-server)
[![GitHub 最后提交](https://img.shields.io/github/last-commit/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/commits/main)
[![GitHub 贡献者](https://img.shields.io/github/contributors/lmcc-dev/mult-fetch-mcp-server)](https://github.com/lmcc-dev/mult-fetch-mcp-server/graphs/contributors)
[![codecov](https://codecov.io/gh/lmcc-dev/mult-fetch-mcp-server/branch/main/graph/badge.svg)](https://codecov.io/gh/lmcc-dev/mult-fetch-mcp-server)
[![CodeFactor](https://www.codefactor.io/repository/github/lmcc-dev/mult-fetch-mcp-server/badge)](https://www.codefactor.io/repository/github/lmcc-dev/mult-fetch-mcp-server)


<!-- 未来可考虑添加的徽章:
[![Maintainability](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/lmcc-dev/mult-fetch-mcp-server/maintainability)
-->

本项目实现了一个符合MCP规范的客户端和服务器，用于在AI助手和外部工具之间进行通信。

[English](./README.md) | [中文文档](./README.zh.md)

## 项目结构

```
fetch-mcp/
├── src/                         # 源代码目录
│   ├── lib/                     # 库文件
│   │   ├── fetchers/            # 网页获取实现
│   │   │   ├── browser/         # 基于浏览器的获取
│   │   │   │   ├── BrowserFetcher.ts      # 浏览器获取实现
│   │   │   │   ├── BrowserInstance.ts     # 浏览器实例管理
│   │   │   │   └── PageOperations.ts      # 页面交互操作
│   │   │   ├── node/            # 基于Node.js的获取
│   │   │   └── common/          # 共享获取工具
│   │   ├── utils/               # 工具模块
│   │   │   ├── ChunkManager.ts        # 内容分块功能
│   │   │   ├── ContentProcessor.ts    # HTML到文本转换
│   │   │   ├── ContentExtractor.ts    # 内容智能提取
│   │   │   ├── ContentSizeManager.ts  # 内容大小限制
│   │   │   └── ErrorHandler.ts        # 错误处理
│   │   ├── server/              # 服务器相关模块
│   │   │   ├── index.ts         # 服务器入口
│   │   │   ├── browser.ts       # 浏览器管理
│   │   │   ├── fetcher.ts       # 网页获取逻辑
│   │   │   ├── tools.ts         # 工具注册和处理
│   │   │   ├── resources.ts     # 资源处理
│   │   │   ├── prompts.ts       # 提示模板
│   │   │   └── types.ts         # 服务器类型定义
│   │   ├── i18n/                # 国际化支持
│   │   └── types.ts             # 通用类型定义
│   ├── client.ts                # MCP 客户端实现
│   └── mcp-server.ts            # MCP 服务器主入口
├── index.ts                     # 服务器入口点
├── tests/                       # 测试文件
└── dist/                        # 编译后的文件
```

## MCP规范

模型上下文协议（Model Context Protocol, MCP）定义了两种主要的传输方式：

1. **标准输入输出（Stdio）**：客户端将MCP服务器作为子进程启动，双方通过标准输入（stdin）和标准输出（stdout）进行通信。
2. **服务器发送事件（Server-Sent Events, SSE）**：用于在客户端和服务器之间传递消息。

本项目实现了基于标准输入输出（Stdio）的传输方式。

## 特性

- 基于官方 MCP SDK 的实现
- 支持标准输入输出（Stdio）传输方式
- 提供了多种网页抓取方法（HTML、JSON、文本、Markdown、纯文本转换）
- 智能模式切换：自动在标准请求和浏览器模式之间切换
- 内容大小管理：自动将大型内容分割成可管理的块，以解决AI模型上下文大小限制问题
- 分块内容检索：能够请求大型内容的特定块，同时保持上下文连续性
- 详细的调试日志输出到标准错误流
- 支持中英文双语国际化
- 模块化设计，便于维护和扩展
- **智能内容提取**：基于Mozilla Readability库，能够从网页中提取有意义的主要内容，过滤广告和导航元素
- **元数据支持**：能够提取网页元数据，如标题、作者、发布日期、站点信息等
- **智能内容分析**：自动检测页面是否包含有意义的内容，过滤登录页、错误页等无实质内容的页面
- **浏览器自动化增强**：支持页面滚动、Cookie管理、选择器等待等高级浏览器交互

## 安装

### 通过 Smithery 安装

要通过 [Smithery](https://smithery.ai/server/@lmcc-dev/mult-fetch-mcp-server) 自动为 Claude 桌面版安装 Mult Fetch MCP Server：

```bash
npx -y @smithery/cli install @lmcc-dev/mult-fetch-mcp-server --client claude
```

### 本地安装

```bash
pnpm install
```

### 全局安装

```bash
pnpm add -g @lmcc-dev/mult-fetch-mcp-server
```

或者直接使用 npx 运行（无需安装）：

```bash
npx @lmcc-dev/mult-fetch-mcp-server
```

## 与 Claude 集成

要将此工具与 Claude 桌面版集成，需要添加服务器配置：

### 配置文件位置

- **MacOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`

### 配置示例

#### 方式一：使用 npx（推荐）

这种方式最简单，不需要指定完整路径，适合全局安装或直接使用 npx：

```json
{
  "mcpServers": {
    "mult-fetch-mcp-server": {
      "command": "npx",
      "args": ["mult-fetch-mcp-server"],
      "env": {
        "MCP_LANG": "zh"  // 设置语言为中文，可选值: "zh" 或 "en"
      }
    }
  }
}
```

#### 方式二：指定完整路径

如果您需要使用特定位置的安装，可以指定完整路径：

```json
{
  "mcpServers": {
    "mult-fetch-mcp-server": {
      "command": "path-to/bin/node",
      "args": ["path-to/@lmcc-dev/mult-fetch-mcp-server/dist/index.js"],
      "env": {
        "MCP_LANG": "zh"  // 设置语言为中文，可选值: "zh" 或 "en"
      }
    }
  }
}
```

请将 `path-to/bin/node` 替换为您系统上 Node.js 可执行文件的路径，将 `path-to/@lmcc-dev/mult-fetch-mcp-server` 替换为此项目的实际路径。

### 使用示例

以下是在 Claude 桌面客户端中使用此工具的示例：

![Claude 桌面客户端示例](./images/example_zh.png)

图片展示了 Claude 如何使用 fetch 工具获取网页内容并根据您的指令进行处理。

### 使用方法

配置完成后，重启 Claude 桌面版，然后您可以在对话中使用以下工具：

- `fetch_html`: 获取网页 HTML 内容
- `fetch_json`: 获取 JSON 数据
- `fetch_txt`: 获取纯文本内容
- `fetch_markdown`: 获取 Markdown 格式内容
- `fetch_plaintext`: 获取从HTML转换的纯文本内容（去除HTML标签）

## 构建

```bash
pnpm run build
```

## 运行服务器

```bash
pnpm run server
# 或者
node dist/index.js
# 如果全局安装，可以直接运行
mult-fetch-mcp-server
# 或者使用 npx
npx mult-fetch-mcp-server
```

## 客户端演示工具

> **注意**：以下 client.js 功能仅供演示和测试使用。当与 Claude 或其他 AI 助手一起使用时，MCP 服务器由 AI 驱动，它会自动管理分块处理过程。

### 命令行客户端

本项目包含一个命令行客户端，用于测试和开发目的：

```bash
pnpm run client <method> <params_json>
# 例如
pnpm run client fetch_html '{"url": "https://example.com", "debug": true}'
```

### 演示客户端分块控制参数

在使用命令行客户端进行测试时，可以使用这些参数来演示内容分块功能：

- `--all-chunks`：命令行标志，用于自动按顺序获取所有块（仅用于演示目的）
- `--max-chunks`：命令行标志，用于限制要获取的最大块数（可选，默认为10）

#### 实时输出演示

client.js 演示工具提供实时输出功能：

```bash
node dist/src/client.js fetch_html '{"url":"https://example.com", "startCursor": 0, "contentSizeLimit": 500}' --all-chunks --debug
```

演示客户端将自动按顺序获取所有块并立即显示它们，展示大型内容如何能够实时处理。

## 运行测试

```bash
# 运行 MCP 功能测试
npm run test:mcp

# 运行 mini4k.com 网站测试
npm run test:mini4k

# 运行直接客户端调用测试
npm run test:direct
```

## 语言设置

本项目支持中英文双语国际化。您可以使用环境变量设置语言：

### 使用环境变量

设置 `MCP_LANG` 环境变量来控制语言：

```bash
# 设置为英文
export MCP_LANG=en
npm run server

# 设置为中文
export MCP_LANG=zh
npm run server

# Windows 系统
set MCP_LANG=zh
npm run server
```

使用环境变量的方式可以确保所有相关进程（包括 MCP 服务器）都使用相同的语言设置。

### 默认语言

默认情况下，系统会按照以下优先级选择语言：
1. `MCP_LANG` 环境变量
2. 操作系统语言（如果以 "zh" 开头，则使用中文）
3. 英文（作为最终回退选项）

## 调试

本项目遵循 MCP 协议的规范，默认情况下不会输出任何日志，以避免干扰 JSON-RPC 通信。调试信息通过调用参数控制：

### 使用 debug 参数

在调用工具时，设置 `debug: true` 参数：

```json
{
  "url": "https://example.com",
  "debug": true
}
```

调试消息会发送到标准错误流（stderr），使用以下格式：

```
[MCP-SERVER] MCP 服务器启动中...
[CLIENT] 正在获取URL: https://example.com
```

### 调试日志文件

当启用调试模式时，所有调试消息也会写入到位于以下位置的日志文件：

```
~/.mult-fetch-mcp-server/debug.log
```

可以通过 MCP 资源 API 访问此日志文件：

```typescript
// 访问调试日志文件
const result = await client.readResource({ uri: "file:///logs/debug" });
console.log(result.contents[0].text);

// 清除调试日志文件
const clearResult = await client.readResource({ uri: "file:///logs/clear" });
console.log(clearResult.contents[0].text);
```

日志文件包含来自所有组件（服务器、客户端、获取器）的带时间戳的条目，可用于排查问题。

## 代理设置

本工具支持多种配置代理设置的方法：

### 1. 使用 `proxy` 参数

最直接的方式是在请求参数中指定代理：

```json
{
  "url": "https://example.com",
  "proxy": "http://your-proxy-server:port",
  "debug": true
}
```

### 2. 使用环境变量

工具会自动检测并使用标准环境变量中的代理设置：

```bash
# 设置代理环境变量
export HTTP_PROXY=http://your-proxy-server:port
export HTTPS_PROXY=http://your-proxy-server:port

# 运行服务器
npm run server
```

### 3. 系统代理检测

工具会根据您的操作系统尝试检测系统代理设置：

- **Windows**：使用 `set` 命令从环境变量中读取代理设置
- **macOS/Linux**：使用 `env` 命令从环境变量中读取代理设置

### 4. 代理故障排除

如果您在代理检测方面遇到问题：

1. 使用 `debug: true` 参数查看有关代理检测的详细日志
2. 使用 `proxy` 参数明确指定代理
3. 确保您的代理 URL 格式正确：`http://host:port` 或 `https://host:port`
4. 对于需要浏览器功能的网站，设置 `useBrowser: true` 使用浏览器模式

### 5. 浏览器模式和代理

当使用浏览器模式（`useBrowser: true`）时，工具将：

1. 首先尝试使用明确指定的代理（如果提供）
2. 然后尝试使用系统代理设置
3. 最后，如果没有找到代理，则不使用代理继续

浏览器模式对于实现了反爬虫措施或需要 JavaScript 执行的网站特别有用。

## 参数处理

本项目采用以下方式处理参数：

- **debug**: 通过调用参数传递，每个请求可以单独控制是否启用调试输出
- **MCP_LANG**: 通过环境变量获取，控制整个服务器的语言设置

## 使用方法

### 创建客户端

```typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import path from 'path';
import { fileURLToPath } from 'url';

// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 创建客户端传输层
const transport = new StdioClientTransport({
  command: 'node',
  args: [path.resolve(__dirname, 'dist/index.js')],
  stderr: 'inherit',
  env: {
    ...process.env  // 传递所有环境变量，包括MCP_LANG
  }
});

// 创建客户端
const client = new Client({
  name: "example-client",
  version: "1.0.0"
});

// 连接到传输层
await client.connect(transport);

// 使用客户端
const result = await client.callTool({
  name: 'fetch_html',
  arguments: {
    url: 'https://example.com',
    debug: true  // 通过参数控制调试输出
  }
});

if (result.isError) {
  console.error('获取失败:', result.content[0].text);
} else {
  console.log('获取成功!');
  console.log('内容预览:', result.content[0].text.substring(0, 500));
}
```

### 支持的工具

- `fetch_html`: 获取网页HTML内容
- `fetch_json`: 获取JSON数据
- `fetch_txt`: 获取纯文本内容
- `fetch_markdown`: 获取Markdown格式内容
- `fetch_plaintext`: 获取从HTML转换的纯文本内容（去除HTML标签）

### 资源支持

服务器包含对 resources/list 和 resources/read 方法的支持，但当前实现中没有定义任何资源。资源系统设计用于提供对项目文件和文档的访问，但此功能尚未完全实现。

#### 资源使用示例

```typescript
// 示例：列出可用资源
const resourcesResult = await client.listResources({});
console.log('可用资源:', resourcesResult);

// 注意：目前这将返回空的资源列表和资源模板列表
```

### 支持的提示模板

服务器提供以下提示模板：

- `fetch-website`: 获取网站内容，支持不同格式和浏览器模式
- `extract-content`: 从网站提取特定内容，支持CSS选择器和数据类型指定
- `debug-fetch`: 调试网站获取问题，分析可能的原因并提供解决方案

#### 提示模板使用方法

1. 使用 `prompts/list` 获取可用提示模板列表
2. 使用 `prompts/get` 获取特定提示模板内容

```typescript
// 示例：列出可用提示模板
const promptsResult = await client.listPrompts({});
console.log('可用提示模板:', promptsResult);

// 示例：获取网站内容提示
const fetchPrompt = await client.getPrompt({
  name: "fetch-website",
  arguments: {
    url: "https://example.com",
    format: "html",
    useBrowser: "false"
  }
});
console.log('获取网站提示:', fetchPrompt);

// 示例：调试网站获取问题
const debugPrompt = await client.getPrompt({
  name: "debug-fetch",
  arguments: {
    url: "https://example.com",
    error: "连接超时"
  }
});
console.log('调试获取提示:', debugPrompt);
```

### 参数选项

每个工具支持以下参数：

#### 基本参数
- `url`: 要获取的URL（必需）
- `headers`: 自定义请求头（可选，默认为{}）
- `proxy`: 代理服务器URL，格式为http://host:port或https://host:port（可选）

#### 网络控制参数
- `timeout`: 超时时间（毫秒）（可选，默认为30000）
- `maxRedirects`: 最大重定向次数（可选，默认为10）
- `noDelay`: 是否禁用请求间的随机延迟（可选，默认为false）
- `useSystemProxy`: 是否使用系统代理（可选，默认为true）

#### 内容大小控制参数
- `enableContentSplitting`: 是否将大内容分割成多个块（可选，默认为true）
- `contentSizeLimit`: 内容分割前的最大字节数（可选，默认为50000）
- `startCursor`: 字节级偏移量，用于从特定位置开始获取内容（可选，默认为0）

这些参数有助于管理超出AI模型上下文大小限制的大型内容，允许您以可管理的块获取网页内容，同时保持处理完整信息的能力。

#### 分块管理
- `chunkId`: 内容分割时的块集唯一标识符（用于请求后续块）

当内容被分割成多个块时，响应中包含元数据，允许AI使用`chunkId`和`startCursor`参数请求后续块。系统使用字节级分块管理提供对内容检索的精确控制，实现从内容中任何位置无缝处理。

#### 模式控制参数
- `useBrowser`: 是否使用浏览器模式（可选，默认为false）
- `useNodeFetch`: 是否强制使用Node.js模式（可选，默认为false，与`useBrowser`互斥）
- `autoDetectMode`: 是否在标准模式失败（出现403/Forbidden错误）时自动检测并切换到浏览器模式（可选，默认为true）。设置为false可以严格使用指定的模式，不进行自动切换。

#### 浏览器模式特有参数
- `waitForSelector`: 浏览器模式下等待的选择器（可选，默认为'body'）
- `waitForTimeout`: 浏览器模式下等待的超时时间（毫秒）（可选，默认为5000）
- `scrollToBottom`: 浏览器模式下是否滚动到页面底部（可选，默认为false）
- `saveCookies`: 浏览器模式下是否保存cookies（可选，默认为true）
- `closeBrowser`: 是否关闭浏览器实例（可选，默认为false）

#### 内容提取参数
- `extractContent`: 是否使用Readability算法提取主要内容（可选，默认为false）
- `includeMetadata`: 是否在提取的内容中包含元数据（可选，默认为false，仅当`extractContent`为true时有效）
- `fallbackToOriginal`: 当提取失败时是否回退到原始内容（可选，默认为true，仅当`extractContent`为true时有效）

#### 调试参数
- `debug`: 是否启用调试输出（可选，默认为false）

### 内容提取特性

使用内容提取功能可以获取网页的核心内容，过滤掉导航栏、广告、侧边栏等干扰元素：

```json
{
  "url": "https://example.com/article",
  "extractContent": true,
  "includeMetadata": true
}
```

提取的内容将包括以下元数据（如果可用）：
- 标题 (title)
- 作者 (byline)
- 站点名称 (siteName)
- 摘要 (excerpt)
- 内容长度 (length)
- 可读性标志 (isReaderable)

### 特殊用法

#### 不获取内容直接关闭浏览器
要关闭浏览器实例而不执行任何获取操作：
```json
{
  "url": "about:blank",
  "closeBrowser": true
}
```

#### 代理优先级
代理的确定顺序如下：
1. 命令行指定的代理
2. 请求中的`proxy`参数
3. 环境变量中的代理（如果`useSystemProxy`为true）
4. Git配置中的代理（如果`useSystemProxy`为true）

如果设置了`proxy`参数，`useSystemProxy`将自动设置为false。

### 调试输出

当设置`debug: true`时，日志将输出到stderr，带有以下前缀：
- `[MCP-SERVER]`: MCP服务器的日志
- `[NODE-FETCH]`: Node.js获取器的日志
- `[BROWSER-FETCH]`: 浏览器获取器的日志
- `[CLIENT]`: 客户端的日志
- `[TOOLS]`: 工具实现的日志
- `[FETCHER]`: 主获取器接口的日志
- `[CONTENT]`: 内容处理相关的日志
- `[CONTENT-PROCESSOR]`: HTML内容处理器的日志
- `[CONTENT-SIZE]`: 内容大小管理相关的日志
- `[CHUNK-MANAGER]`: 内容分块操作相关的日志
- `[ERROR-HANDLER]`: 错误处理相关的日志
- `[BROWSER-MANAGER]`: 浏览器实例管理器的日志
- `[CONTENT-EXTRACTOR]`: 内容提取器的日志


## 许可证

MIT