Skip to main content
Glama
Tom-Chencao

Tavily MCP Key Pool

by Tom-Chencao

Tavily MCP 密钥池

简体中文版 README: README.zh.md

为什么? 如果你有多个 Tavily API 密钥(多个账户、团队预算、批量购买的积分等)并通过 AI 编码代理使用它们,你会很快遇到三个问题:

  1. 单密钥瓶颈 — 一个密钥的速率限制会拖慢一切。

  2. 静默失败 — 密钥过期、达到配额或被撤销,你的搜索就会……停止工作。

  3. 缺乏可见性 — 你不知道哪些密钥正在被使用,以及使用了多少。

本项目解决了这三个问题:一个微型 MCP 服务器,轮询你的密钥池,自动停用失效密钥,并暴露使用统计信息 — 你可以直接将其放入 Claude Desktop、Cursor、DeepSeek Harness 或任何 MCP 客户端,而无需改变你的工作流程。

一个基于 SQLite 的轮询 API 密钥池的 Tavily MCP 服务器,内置使用追踪、自动健康故障转移,以及一个独立的 FastAPI 仪表盘。标准 MCP 协议 — 适用于任何兼容 MCP 的客户端(Claude Desktop、Cursor、DeepSeek Harness 等)。

亮点

  • 🔄 轮询密钥轮换,适用于 N 个 Tavily API 密钥(SQLite,零启动成本)。

  • 📊 使用追踪:每个密钥的请求次数、错误次数、消耗的积分。

  • 🩺 自动健康检查:通过轻量搜索探测所有密钥,自动停用失效密钥;通过 tavily_pool_status 暴露结果。

  • 🛠️ 六个核心 MCP 工具(与 Tavily 一致:搜索、提取、爬取、地图、研究)外加 tavily_pool_statustavily_research_status(异步获取)。

  • 🌐 独立的 FastAPI 仪表盘(启用 CORS,仅回环地址)包含统计信息、每个密钥的视图、添加/删除/停用/激活,以及一键健康探测。

  • 🔌 即插即用,适用于任何 MCP 客户端,通过 stdio;DSH 集成只需一页补丁 + 一个示例客户端插件(参见 examples/dsh-integration/)。

与官方 tavily-mcp 的区别

功能

官方 tavily-mcp

本仓库

单个 API 密钥环境变量

多个密钥,轮询

✅ SQLite 池

每个密钥的使用统计

✅ 请求次数 + 积分 + 错误

健康探测 + 自动停用

独立仪表盘

✅ FastAPI 运行在 127.0.0.1:8000

MCP 工具功能一致(搜索/提取/爬取/地图/研究)

✅(外加池状态 / 研究状态额外工具)

异步研究轮询

(手动)

✅ 内置 tavily_research + tavily_research_status

架构

+--------------------------------------------------+
|  MCP clients (Claude Desktop / Cursor / DSH …)   |
+--------+---------------------+-------------------+
         | stdio (JSON-RPC)     | HTTPS / CORS
+--------▼--------------+     +▼-----------------------+
|  mcp_server.py (FastMCP)|     |  dashboard.py (FastAPI) |
|  + key_pool.py (SQLite) |     |  uvicorn 127.0.0.1:8000 |
+----------------------+--+     +-----+----------------+
                       |              |
                       v              v
                tavily_keys.db  <— SQLite-backed pool
                       |
                       v
              Tavily REST API (round-robin over N keys)

快速开始

1. 安装依赖

python -m venv .venv
. .venv/bin/activate        # Linux/macOS
# or:  .venv\Scripts\Activate.ps1   (Windows PowerShell)
pip install -r requirements.txt

requirements.txt 中固定的 mcp 约束是 <2.0:参见 DSH 集成 / 陷阱 #1 — FastMCP 导入路径在 mcp 2.x 中已更改。

2. 添加 API 密钥

创建一个 keys.txt,每行一个密钥:

tvly-xxxxxxxxxxxxxxxx
tvly-yyyyyyyyyyyyyyyy

然后导入它们:

python cli.py add --from-file keys.txt

或者启动仪表盘(下一步)并将它们粘贴到 添加 API 密钥 表单中。密钥以明文形式存储在 tavily_keys.db(SQLite)中,这样池子可以零启动成本轮询 — 参见 安全

3. 启动 MCP 服务器

对于直接 stdio MCP 服务器(任何 MCP 客户端):

./run_mcp.sh                                # Linux/macOS
# or:  .venv\Scripts\python.exe mcp_server.py   (Windows)

服务器宣布七个工具;在支持 MCP 的客户端中,公共名称看起来像 tavily_searchtavily_extract 等。

4. 启动仪表盘(可选,独立进程)

./run_dashboard.sh                          # default port 8000
# or:  .venv\Scripts\python.exe -m uvicorn dashboard:app --host 127.0.0.1 --port 8000

在浏览器中打开 http://127.0.0.1:8000。仪表盘启用 CORS,仅允许回环源,因此其他 UI 中的嵌入设置面板可以调用它。

MCP 工具

工具

用途

tavily_search

网页搜索(基础/高级、主题、时间范围、包含/排除域名、国家等)

tavily_extract

从 URL 提取干净内容

tavily_crawl

爬取网站并从多个页面提取内容

tavily_map

发现网站上的 URL(比爬取更快)

tavily_research

AI 深度研究(30–120 秒+;内部使用后台轮询 — 参见 陷阱 #2

tavily_pool_status

池子统计数据:活跃密钥、总请求数/错误数/积分、最近 24 小时细分

tavily_research_status(request_id)

获取超时的异步研究任务的结果

命令行

python cli.py list                 # all keys
python cli.py list --active        # only active
python cli.py stats                # JSON dump of pool state
python cli.py health               # probe every active key; deactivate dead ones
python cli.py recent -n 20         # recent request log
python cli.py add tvly-... [...]   # add one or more keys
python cli.py add --from-file keys.txt
python cli.py activate tvly-xx****yy     # masked id, see `list`
python cli.py deactivate tvly-xx****yy --reason "manually disabled"
python cli.py remove tvly-xx****yy

与 Claude Desktop / Cursor / 其他通用 MCP 客户端一起使用

对于任何接受 MCP stdio 命令的客户端:

{
  "mcpServers": {
    "tavily": {
      "command": "/absolute/path/to/.venv/bin/python3",
      "args": ["mcp_server.py"],
      "cwd": "/absolute/path/to/this/repo"
    }
  }
}

或者可流式 HTTP,如果你的客户端支持且你已自己将服务器包装在 HTTP 传输中 — 这不在本仓库的范围之内。


DeepSeek Harness(DSH)集成

已在 @deepseek-ai/dsh 0.1.0-rc.6(web 配置)上测试。

DeepSeek Harness(dsh)使用 Cordis 插件框架,并附带官方 MCP 客户端桥接器(@deepseek-ai/dsh-mcp-client)。因此集成非常薄:一个用户补丁层 + 一个示例浏览器端插件(本仓库的 examples/dsh-integration/client-tavily-panel/)。

A. 在 DSH 中注册 Tavily MCP 服务器

编辑 ~/.dsh/profiles/web/cordis.patch.yml(用户补丁层,应用于每个包之后)。添加一个新的 insert 块 — 下面的值假设仓库位于 C:\Users\ASUS\.dsh\tavily-pool\

- insert:
    - id: mcp-tavily
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        transport: stdio
        serverName: tavily
        command: 'C:\Users\ASUS\.dsh\tavily-pool\.venv\Scripts\python.exe'
        args: ['mcp_server.py']
        cwd: 'C:\Users\ASUS\.dsh\tavily-pool'
        # research can take >2 minutes on big topics; the default 30s is too tight
        toolCallTimeoutMs: 600000
        failOnStartupError: false

在重启之前,使用 dsh --profile web --dump-config 验证合并。然后 MCP 服务器在代理的工具列表中显示为 mcp__tavily__tavily_search(等)。

B. (可选)将仪表盘嵌入 DSH 设置中

examples/dsh-integration/client-tavily-panel/ 复制到磁盘上的任意位置。该示例使用 @deepseek-ai/dsh-client-ui-slotssettings.section 插槽 — 插件注册了一个 Tavily 号池 面板,通过 fetch 调用仪表盘。安装方法:

  1. 放置包(例如 ~/.dsh/plugins/client-tavily-panel/)。

  2. 将其链接到配置文件的 node_modules,以便 require.resolve 可以找到它(DSH 通过其包名解析链加载客户端插件):

    New-Item -ItemType Junction `
      -Path "$env:DSH_HOME\profiles\node_modules\dsh-client-tavily-panel" `
      -Target "C:\Users\ASUS\.dsh\plugins\client-tavily-panel"

    使用连接点(非符号链接)可以避免需要管理员权限。如果跳过此步骤并在本地 pnpm add 包也可以,但要注意:pnpm 可能会因为配置文件中其他无关的 file: / GitHub 源依赖而卡住。

  3. cordis.patch.yml 中添加一个 roster 条目

    - insert:
        - id: client-tavily-panel
          name: 'dsh-client-tavily-panel'
  4. 重启 dsh web。(参见陷阱 #6 — 故意禁用了 web 配置文件的 HMR;补丁更改仅在完全重启后加载。)

重启后,打开 ⚙️ 设置 — Tavily 号池 条目出现在左侧导航中。

DeepSeek 集成过程中遇到的陷阱

以下是我(原始集成者)遇到的实际错误。在开始之前按以下顺序阅读 —— 每个都浪费了时间。

陷阱 #1:mcp SDK 版本

mcp_server.py 执行 from mcp.server.fastmcp import FastMCP。该模块mcp 2.0 中被移除(FastMCP 实现移到了单独的 fastmcp 包中,API 不同)。如果你运行 pip install mcp 并获取最新版本,MCP 服务器将拒绝启动:

ModuleNotFoundError: No module named 'mcp.server.fastmcp'

固定版本:

# requirements.txt
mcp>=1.0.0,<2.0.0

已在 mcp 1.29.0 上测试。

陷阱 #2:tavily_research 是异步的,并且绑定到创建它的密钥

这包含三个子错误:

  • tavily-python SDK 将 research() 的第一个位置参数从 query 重命名为 input。调用 client.research(query=…) 会失败,提示 missing 1 required positional argument: 'input'

  • SDK 在运行时强制 model ∈ {"mini", "pro", "auto"},但 Tavily REST API 本身接受 model=standard|pro。传递 standard 会引发 model must be one of: mini, pro or auto

  • research() 立即返回一个 status: pending 的封装 — 实际结果在 30–120 秒后到达。你必须轮询 get_research(request_id) 直到 status == "completed"。否则工具总是返回“pending”,你的模型会认为调用失败。

  • 研究任务绑定到创建它的 API 密钥。 池中的其他密钥无法获取结果(返回 404)。始终使用同一个 TavilyClient 实例进行轮询 — 不要在每次轮询迭代中重新调用 pool.next_key(),否则你会不断命中错误的密钥。

本仓库的 tavily_research 已经封装了完整的生命周期:轮询最多约 570 秒,然后返回一个 status: timeout 的封装,其中包含 request_id,以便调用者稍后获取。第二个工具 tavily_research_status(request_id) 遍历活动密钥列表,找到正确的密钥进行临时获取 — 这是因为工具调用可能已在不同进程上超时。

陷阱 #3:Windows 上的 dashboard.py UTF-8 读取错误

dashboard.py 执行:

DASHBOARD_HTML = TPL.read_text()

Path.read_text() 默认使用 locale.getpreferredencoding(),在 Windows(zh-CN)上是 GBK。捆绑的 templates/dashboard.html 是 UTF-8 格式并包含中文字符,因此仪表盘会抛出:

UnicodeDecodeError: 'gbk' codec can't decode byte 0xb6 in position 4308

修复:

DASHBOARD_HTML = TPL.read_text(encoding="utf-8")

陷阱 #4:run_*.sh 中的跨平台路径

run_mcp.shrun_dashboard.sh 硬编码了 .venv/bin/python3(Linux 约定),且从未在 Windows 上测试过。脚本作者还附带了一个使用 /home/user/code/Tavilysystemd 单元 — 显然是仅限 Linux 的。

在 Windows 上你完全不需要这些脚本;只需直接调用 .venv\Scripts\python.exe(参见上面的 YAML)。它们保留在仓库中是为了原来的 Linux 用例。

陷阱 #5:DSH 补丁配置仅在启动时加载

cordis.patch.ymlweb 配置文件启动时读取。更改不会热重载 — web 应用包补丁中的 hmr 行被故意禁用:

- id: hmr
  disabled: true
# TODO: Re-enable shared HMR for Web after its reload lifecycle is tested.

因此,每次编辑 cordis.patch.yml 后,重启 dsh web(参见陷阱 #6 如何安全地执行此操作)。

使用 dsh --profile web --dump-config 验证你的补丁是否正确合并,而无需实际启动 GUI。这比启动、检查 GUI、杀死、修复、重复要快得多。

陷阱 #6:如何安全地重启 dsh web 而不自毁

dsh web运行此会话的主机进程,包括你的工具进程。如果你天真地运行

Stop-Process -Id <dsh-web-pid> -Force
Start-Process dsh.cmd web

从同一个 dsh web 生成的 pwsh 中,你会在新实例启动之前就在命令中途自毁。我第一次尝试时,PowerShell 会话以 exit code 4294967295 终止,什么也没发生。

修复方法:将重启任务交给 Windows 任务计划程序,它会在 svchost(而非 dsh web 下)运行脚本:

$script = "$env:TEMP\dsh_restart.ps1"
@"
Start-Sleep -Seconds 8
Stop-Process -Id <dsh-web-pid> -Force
Get-CimInstance Win32_Process |
  Where-Object { `$_.CommandLine -match 'dsh web' } |
  ForEach-Object { Stop-Process -Id `$_.ProcessId -Force }
Start-Sleep -Seconds 3
Start-Process 'C:\…\dsh.cmd' web -WorkingDirectory 'H:\…' -WindowStyle Hidden
"@ | Out-File $script -Encoding utf8

schtasks /create /tn dsh-restart /tr "powershell -NoProfile -File $script" /sc once /st 23:59 /f
schtasks /run /tn dsh-restart
schtasks /delete /tn dsh-restart /f

然后你大约有 8 秒时间返回最终答案,然后旧实例才会终止。告诉用户在 20–30 秒后刷新 http://127.0.0.1:3080

陷阱 #7:在 MCP 服务器运行时迁移工具目录

在 MCP 服务器运行时迁移工具目录...

DSH 的 mcp-client 在连接丢失时会以指数退避方式重新连接 (initialDelayMs 500maxAttempts 10)。杀死 Python 子进程 会触发重新连接——这会立即生成一个新的子进程。如果你随后 尝试使用 Move-Item 移动该目录,新的 .venv\Scripts\python.exe 会 锁定文件,导致 robocopy 失败,返回 [Result: 32] / "正在被另一个进程使用"。

两种可行的策略:

  • 先复制,再删除源文件。 Copy-Item 通过 Windows 文件共享读取锁定的文件; 它不需要独占访问。复制成功后,杀死旧的 MCP 服务器并删除源文件。只要 pyvenv.cfg 中的 home = 行仍然指向同一个基础 Python 安装,.venv 就是 完全可重定位的。

  • 循环执行 kill + robocopy /MOVE,直到它在退避窗口内成功。 虽然丑陋但有效。

原始迁移使用了:

Copy-Item -Path D:\Downloads\Tavily -Destination C:\Users\ASUS\.dsh\tavily-pool -Recurse -Force
# verify copy
Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'python.exe' -and $_.CommandLine -match 'mcp_server' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
# loop until deletion succeeds
for ($i=0; $i -lt 8; $i++) {
  Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'mcp_server' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
  Start-Sleep -Milliseconds 200
  Remove-Item D:\Downloads\Tavily -Recurse -Force -ErrorAction SilentlyContinue
  if (-not (Test-Path D:\Downloads\Tavily)) { break }
  Start-Sleep -Seconds 2
}

陷阱 #8:pnpm add 可能因无关依赖而卡住

当你运行 dsh plugin --profile web add <dir> 安装本地插件时, pnpm 会解析整个 profile 工作区——包括你的 package.json 中列出的任何 GitHub 来源或 HTTP 来源的包。如果你的 profile 已经包含类似 dsh-files: https://codeload.github.com/...tar.gz/... 的内容,并且该下载 卡住(防火墙、DNS、冷缓存、注册表配额),你的本地插件永远不会安装, pnpm 会挂起直到超时。

解决方法:跳过 pnpm,自己创建解析:

New-Item -ItemType Junction `
  -Path "$env:DSH_HOME\profiles\node_modules\dsh-client-tavily-panel" `
  -Target "<absolute path to your plugin package>"

连接点(不是符号链接)无需管理员权限即可工作,并且对于 require.resolve 的行为完全相同。补丁层随后通过其 name 字段引用该包, 就像 pnpm 已经安装了一样。

陷阱 #9:设置面板客户端插件格式

如果你编写自己的 DSH 客户端插件(浏览器端),运行时格式 不是 ESM,也不是 Cordis-from-source。dsh-client-modules 插件 托管一个小的内存模块加载器,并从 /plugins/<id>/client.js 获取每个客户端包。 该包必须调用:

window.__ModuleLoader__.load({
  id: "your-package-name",   // matches package.json "name"
  factory: (require) => {
    var module = { exports: {} };
    var exports = module.exports;
    var react = require("react");           // available
    var jsx = require("react/jsx-runtime"); // available
    // ... define components ...
    function apply(ctx) {
      ctx.slots.inject("settings.section", () => ctx.slots.register({
        name: "settings.section",
        id: "your-id",
        order: 100,
        label: "Your Label"
      }, YourComponent));
    }
    exports.apply = apply;
    exports.inject = ["slots"];             // services you depend on
    return module.exports;
  }
});

并且你的 package.json 必须包含:

{
  "main": "lib/index.js",
  "exports": { "./client": { "default": "./lib/client.js" } },
  "dsh": { "client": { "inject": ["@deepseek-ai/dsh-client-ui-slots"], "platform": "web" } }
}

lib/index.js主机入口——它在服务器端运行;它可以是一个 空操作(function apply() {}; export { apply };)。


安全

  • 密钥以明文存储。 tavily_keys.db 以明文形式存储你的 Tavily API 密钥, 因为基于 SQLite 的池在每次请求时都会被查询。使用文件系统权限保护该文件 (Linux:chmod 600)。 切勿提交 tavily_keys.db(参见 .gitignore)。

  • 默认仅回环仪表板。 dashboard.py 绑定 127.0.0.1:8000。 如果你在局域网中暴露它,请立即添加身份验证。

  • CORS 故意保持开放——仪表板旨在由同一主机上的嵌入式 UI 调用。 由于回环绑定,这是安全的,但如果你更改绑定地址,请缩小 CORSMiddleware.allow_origins 以匹配。

  • 轮换泄露的密钥python cli.py remove tvly-xxxxxxxx****yyyy, 在 Tavily 仪表板中撤销它,对池中的每一行重复此操作。

故障排除

症状

原因/修复

ModuleNotFoundError: No module named 'mcp.server.fastmcp'

mcp 版本 ≥ 2.0;锁定到 <2.0(陷阱 #1)

TavilyClient.research() missing 1 required positional argument: 'input'

旧式调用——mcp_server.py 已使用 input=(陷阱 #2)

model must be one of: mini, pro or auto

SDK 级别限制,在此仓库中映射到 auto(陷阱 #2)

研究始终返回 pending

是否在 research 之后调用了 get_research?此仓库已为你处理

UnicodeDecodeError: 'gbk' codec can't decode…

仪表板 HTML 读取错误(陷阱 #3);此仓库已修复

node.exepython.exe 文件在移动时被锁定

杀死 MCP 服务器,先复制再删除(陷阱 #7)

工具已注册但 DSH 会话看不到它们

是否重启了 dsh web?补丁仅在启动时加载(陷阱 #5)

__DSH_BOOT__ 未列出你的插件

连接点/require-resolve 问题(陷阱 #8);使用 dsh --profile web --dump-config 验证

致谢

池管理代码(key_pool.pydashboard.py、FastMCP mcp_server.py 骨架、cli.py)最初由一位未署名的作者编写并公开发布。此仓库添加了:

  • mcp 1.x 兼容性(queryinputmodel 映射、研究轮询)。

  • 一个新的 tavily_research_status 工具,用于异步获取。

  • Windows 跨平台修复(dashboard.py 中的 UTF-8 读取)。

  • 一个用于 DSH 的即用型设置面板客户端插件,以及上述集成陷阱日志。

如果你知道原作者,请提出一个 issue,以便我添加致谢。

许可证

MIT。参见 LICENSE

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • One API key for 6 AI models. Pay-per-use. MCP protocol support with web search.

  • Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.

  • Zenrows MCP server — Fetch, Extract, Batch, and Browser Sessions for AI coding assistants

View all MCP Connectors

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/Tom-Chencao/a-beginner-s-warehouse'

If you have feedback or need assistance with the MCP directory API, please join our Discord server