# Web Search MCP Server

为 LLM 提供网页搜索能力的 MCP 服务器，支持从网页和新闻文章中获取并提取内容。

## 功能特性

- **双搜索模式**:
  - **常规搜索**: 从博客、文档、文章等获取多样化的搜索结果
  - **新闻搜索**: 从新闻源获取最新新闻文章和突发新闻
- **实时网页搜索**: 搜索任意主题，获取最新结果
- **内容提取**: 自动提取文章主要内容，过滤广告和无关信息
- **多种传输模式**: 支持 stdio、streamable-http、SSE 三种部署方式
- **负载均衡**: 支持多个 API 密钥，自动轮询分配
- **速率限制**: 内置速率限制（每小时 200 次），防止 API 滥用
- **结构化输出**: 返回包含元数据（标题、来源、日期、URL）的格式化内容
- **灵活结果**: 控制返回结果数量（1-20 条）

## 前置要求

1. **Serper API 密钥**: 在 [serper.dev](https://serper.dev) 注册获取 API 密钥
2. **Python 3.10+**: 确保已安装 Python
3. **uv**: Python 包管理器（通过 `curl -LsSf https://astral.sh/uv/install.sh | sh` 安装）
4. **MCP 兼容的 LLM 客户端**: 如 Claude Desktop、Cursor 或任何支持 MCP 的应用

## 安装

1. 克隆或下载此仓库
2. 使用 uv 安装依赖：
   ```bash
   uv sync
   ```

3. 设置 Serper API 密钥：
   ```bash
   export SERPER_API_KEYS="your-api-key-here"
   ```
   支持多密钥负载均衡，用逗号分隔：
   ```bash
   export SERPER_API_KEYS="key1,key2,key3"
   ```

## 使用方法

### 启动 MCP 服务器

服务器支持三种传输模式：

#### stdio 模式（Claude Desktop 默认）
```bash
uv run python main.py --transport stdio
```

#### streamable-http 模式
```bash
uv run python main.py --transport http --port 7860
```

#### SSE 模式
```bash
uv run python main.py --transport sse --port 7860
```

#### 使用已安装的命令
```bash
# 安装后可通过 pip install -e .
web-search-mcp --transport stdio
```

**命令行选项**：
- `--transport`: 传输模式（`stdio`、`http`、`sse`），默认：`stdio`
- `--port`: HTTP/SSE 模式端口，默认：`7860`
- `--log-level`: 日志级别（`DEBUG`、`INFO`、`WARNING`、`ERROR`），默认：`INFO`

**环境变量**：
- `SERPER_API_KEYS`: 逗号分隔的 API 密钥，用于负载均衡
- `PORT`: 覆盖默认端口（7860）
- `LOG_LEVEL`: 覆盖默认日志级别（INFO）

### 连接 LLM 客户端

#### Claude Desktop（stdio 模式）
在 `claude_desktop_config.json` 中添加：
```json
{
  "mcpServers": {
    "web-search": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/web-search-mcp", "python", "main.py", "--transport", "stdio"],
      "env": {
        "SERPER_API_KEYS": "your-api-key-here"
      }
    }
  }
}
```

或使用已安装的命令：
```json
{
  "mcpServers": {
    "web-search": {
      "command": "web-search-mcp",
      "args": ["--transport", "stdio"],
      "env": {
        "SERPER_API_KEYS": "your-api-key-here"
      }
    }
  }
}
```

#### HTTP 客户端（streamable-http 模式）
1. 启动服务器：`uv run python main.py --transport http --port 7860`
2. 连接到：`http://localhost:7860/mcp`

#### SSE 客户端（SSE 模式）
1. 启动服务器：`uv run python main.py --transport sse --port 7860`
2. 连接到：`http://localhost:7860/sse`

## 工具文档

### `search_web` 函数

**用途**: 在网页上搜索信息或最新新闻并提取内容。

**参数**：
- `query` (str, **必需**): 搜索查询词
  - 示例: "OpenAI 新闻", "气候变化 2024", "Python 教程"

- `num_results` (int, **可选**): 获取结果数量
  - 默认: 4
  - 范围: 1-20
  - 更多结果提供更多上下文，但耗时更长

- `search_type` (str, **可选**): 搜索类型
  - 默认: "search"（常规网页搜索）
  - 选项: "search" 或 "news"
  - 使用 "news" 获取最新、时效性强的新闻文章
  - 使用 "search" 获取通用信息、文档、教程

**返回**: 格式化文本，包含：
- 提取结果摘要
- 每篇文章的：
  - 标题
  - 来源和日期
  - URL
  - 提取的主要内容

**何时使用各搜索类型**：
- **使用 "news" 模式**：
  - 突发新闻或非常近期的事件
  - 时效性信息（"今天"、"本周"）
  - 当前时事和最新进展
  - 新闻稿和公告

- **使用 "search" 模式**：
  - 通用信息和研究
  - 技术文档或教程
  - 历史信息
  - 来自各种来源的多样化观点
  - 操作指南和解释

## 开发

### 运行测试
```bash
uv run pytest
```

### 代码格式化
```bash
uv run ruff check
uv run ruff format
```

## 错误处理

工具处理各种错误场景：
- 缺少 API 密钥: 清晰的错误消息和设置说明
- 速率限制: 超限时提示等待
- 提取失败: 报告无法提取的文章
- 网络错误: 优雅的错误消息

## LLM 使用技巧

1. **选择正确的搜索类型**: 用 "news" 获取最新突发新闻，用 "search" 获取通用信息
2. **查询要具体**: 更具体的查询会产生更好的结果
3. **调整结果数量**: 快速搜索用较少结果，综合研究用较多结果
4. **检查日期**: 工具显示文章日期，提供时间上下文
5. **后续追问**: 使用提取的内容进行后续问题提问

## 限制

- 每小时限制 200 次请求
- 提取质量取决于网站结构
- 某些网站可能阻止自动化访问
- 新闻模式专注于新闻源的最新文章
- 搜索模式提供多样化结果但可能包含较旧内容

## 故障排除

1. **"SERPER_API_KEYS is not set"**: 确保已导出环境变量
2. **速率限制错误**: 请等待后再发起请求
3. **未提取到内容**: 某些网站阻止爬虫，尝试不同查询
4. **连接错误**: 检查网络连接和防火墙设置
5. **端口已被占用**: 使用 `--port` 指定其他端口
