Skip to main content
Glama
La0bALanG

tavily_mcp_server_for_all_tools

by La0bALanG
README.md
# Tavily Web Search MCP Server

基于 [Tavily 智搜官方 Python SDK](https://docs.tavily.com/) 开发的联网搜索 MCP 服务,使用标准 [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) 实现,采用 **Streamable HTTP** 传输协议,通过 FastAPI + uvicorn 对外提供服务。

## 功能

服务提供 8 个 MCP 工具,覆盖 Tavily 官方 SDK 的主要能力:

| 工具名 | 说明 | 底层 Tavily 接口 |
| --- | --- | --- |
| `web_search` | 根据查询关键字执行联网搜索,返回标题、链接、摘要、相关性得分,并可选生成总结答案 | `search` |
| `web_fetch` | 抓取指定 URL 网页,返回其正文文本内容(markdown / text) | `extract` |
| `web_crawl` | 从根 URL 出发按图遍历整个网站,批量抓取多个页面正文,适合系统性收集某网站内容 | `crawl` |
| `web_map` | 遍历网站结构,只发现页面 URL 不抓正文,适合先摸清站点范围 | `map` |
| `qna_search` | 针对一个具体问题直接返回一句话式答案 | `qna_search` |
| `search_context` | 返回适合直接喂给 LLM / RAG 流程的压缩检索上下文(自动做 token 限额与截断) | `get_search_context` |
| `deep_research_start` | 提交一个深度研究任务(Tavily 自动多轮搜索 + 生成综合报告),任务异步执行,立即返回 `request_id` | `research` |
| `deep_research_result` | 根据 `request_id` 轮询查询深度研究任务的状态与最终结果(报告正文 + 引用来源) | `get_research` |

> `deep_research_start` / `deep_research_result` 对应的研究任务在 Tavily 服务端异步执行,可能耗时数分钟,请先调用 `deep_research_start` 拿到 `request_id`,再用 `deep_research_result` 轮询直到 `status` 变为 `completed`(或 `failed`)。

## 目录结构

```
tavily-mcp-server/
├── app/
│   ├── config.py       # 环境变量配置加载(.env)
│   ├── tavily_tools.py # TavilyToolkit:封装 web_search / web_fetch
│   ├── server.py        # FastMCP 实例与工具注册
│   └── main.py          # FastAPI 应用 + uvicorn 入口,挂载 Streamable HTTP
├── client/
│   └── test_client.py   # 本地测试客户端(连接 MCP 服务并调用工具)
├── deploy/
│   ├── deploy.sh                # 一键同步 + 部署到远程服务器
│   └── tavily-mcp.service       # systemd 服务单元
├── requirements.txt
├── .env.example
└── .gitignore
```

## 环境要求

- Python 3.12(本地通过 conda 环境 `llm_factory_envs` 开发,远程服务器使用 `llm_env`)
- Tavily API Key([app.tavily.com](https://app.tavily.com) 申请)

## 本地开发与测试

### 1. 准备环境变量

```bash
cp .env.example .env
# 编辑 .env,填入 TAVILY_API_KEY;本地测试保持 MCP_HOST=127.0.0.1
```

### 2. 安装依赖(conda 环境 llm_factory_envs)

```bash
conda activate llm_factory_envs
pip install -r requirements.txt
```

### 3. 启动 MCP 服务

```bash
python -m app.main
# 服务启动后监听 http://127.0.0.1:20260/mcp
# 健康检查: curl http://127.0.0.1:20260/health
```

### 4. 使用测试客户端验证

另开一个终端:

```bash
conda activate llm_factory_envs
python -m client.test_client --url http://127.0.0.1:20260/mcp
```

测试客户端会依次:连接服务 → 列出可用工具 → 调用 `web_search` / `web_fetch` / `web_crawl` / `web_map` / `qna_search` / `search_context`,并打印结果。

深度研究任务耗时较长(可能数分钟),默认不测试,如需一并验证 `deep_research_start` / `deep_research_result`:

```bash
python -m client.test_client --url http://127.0.0.1:20260/mcp --deep-research
# 也可自定义研究任务描述:
python -m client.test_client --url http://127.0.0.1:20260/mcp --deep-research "近期国产大模型有哪些重要发布"
```

该模式会提交任务后每 10 秒轮询一次 `deep_research_result`,直到状态变为 `completed` / `failed`。

## 部署到远程服务器

远程服务器信息:`101.47.67.15`,通过 SSH(已配置免密登录)部署,使用远程 conda 环境 `llm_env`,服务端口固定为 **20260**。

### 1. 配置远程 .env

本地 `.env` 中把 `MCP_HOST` 改为 `0.0.0.0`(对公网监听),`MCP_PORT` 保持 `20260`,再执行部署脚本会自动通过 `scp` 同步 `.env`(如需远程与本地使用不同的 key,可直接在远程手动维护 `/opt/tavily-mcp-server/.env`)。

### 2. 一键部署

```bash
bash deploy/deploy.sh
```

该脚本会:

1. `rsync` 项目文件到 `root@101.47.67.15:/opt/tavily-mcp-server`(排除 `.git`、`__pycache__` 等)
2. 同步 `.env`(如本地存在)
3. 在远程 `llm_env` 环境中安装依赖
4. 安装/更新 `systemd` 服务并重启

### 3. 服务器防火墙 / 安全组

请确认云服务商控制台的安全组规则已放行 TCP **20260** 端口(`deploy.sh` 不会自动修改云安全组,需要在服务商控制台手动开放)。若服务器本机启用了 `firewalld`/`ufw`,也需放行该端口,例如:

```bash
# firewalld
ssh root@101.47.67.15 "firewall-cmd --permanent --add-port=20260/tcp && firewall-cmd --reload"
```

### 4. 验证远程部署

```bash
curl http://101.47.67.15:20260/health
python -m client.test_client --url http://101.47.67.15:20260/mcp
```

### 常用运维命令

```bash
ssh root@101.47.67.15 "systemctl status tavily-mcp.service --no-pager"
ssh root@101.47.67.15 "journalctl -u tavily-mcp.service -f"
ssh root@101.47.67.15 "systemctl restart tavily-mcp.service"
```

## MCP 客户端配置

部署完成后,可在任意支持 Streamable HTTP 的 MCP 客户端中通过以下 JSON 配置接入本服务:

```json
{
  "mcpServers": {
    "tavily-web-search": {
      "type": "streamable_http",
      "url": "http://101.47.67.15:20260/mcp"
    }
  }
}
```

如需本地联调,将 `url` 替换为 `http://127.0.0.1:20260/mcp` 即可。

## 环境变量说明

| 变量名 | 说明 | 默认值 |
| --- | --- | --- |
| `TAVILY_API_KEY` | Tavily 官方 API Key(必填) | 无 |
| `MCP_HOST` | 服务监听地址 | `127.0.0.1`(部署到服务器改为 `0.0.0.0`) |
| `MCP_PORT` | 服务监听端口 | `20260` |
| `MCP_SERVER_NAME` | MCP Server 名称 | `tavily-web-search` |
| `MCP_STREAMABLE_PATH` | Streamable HTTP 挂载路径 | `/mcp` |
| `MCP_STATELESS_HTTP` | 是否无状态 HTTP 模式 | `false` |
| `MCP_JSON_RESPONSE` | 是否强制 JSON 响应(而非 SSE 流) | `false` |
| `TAVILY_REQUEST_TIMEOUT` | 调用 Tavily search/extract/qna/context/research 等接口的超时时间(秒) | `30` |
| `TAVILY_CRAWL_TIMEOUT` | 调用 Tavily crawl/map 接口的超时时间(秒),站点遍历通常耗时更久 | `150` |
| `LOG_LEVEL` | 日志级别 | `INFO` |

## 安全说明

- `.env` 文件已在 `.gitignore` 中排除,切勿提交到 GitHub 仓库。
- 请勿在代码中硬编码任何密钥,所有敏感信息均通过环境变量注入(`python-dotenv` 动态加载)。
- 提交代码前请再次确认 `git status` 中不包含 `.env` 或其他包含密钥的文件。