用 Chrome CDP 搭建零成本 Gemini Search MCP

2026-07-01

搜索又花钱了

我的 AI Agent 每个月都要花不少钱在搜索上。Tavily 每次调用约 $0.01,高频场景一个月下来几十美元不是问题。即使订了 Claude Pro,每次搜索还是要额外付费。

直到我看到一个项目——gemini-search-mcp,号称「零成本无限搜索」。

先不说靠不靠谱,它的思路很有意思:把 Google AI Mode(搜索页面上方的 AI 综合答案功能)包装成 MCP 工具,让 Agent 能直接调用,不需要 API Key,没有速率限制。

一句话技术原理

“Google 按 TLS 指纹质量限速,不是按 IP 地址。”

你不是用代码发 HTTP 请求(特征明显,容易被限),而是启动一个真实 Chrome 浏览器,在页面内执行 fetch()——从 Google 的视角看,这就是一个真实用户在正常搜索。

项目长什么样

项目地址:github.com/Sophomoresty/gemini-search-mcp(MIT 协议,上线 1 天 55 星)

核心架构:

Agent 调用 web_search("query")
  → Chrome CDP: Runtime.evaluate(fetch)
    → 第1步: fetch Google.com.hk 搜索页 → 提取 tokens
    → 第2步: fetch async/folwr endpoint → 获取 AI Mode 合成答案
    → 解析 HTML → 返回纯文本给 Agent

两个入口点:

  1. MCP Server(stdio 协议)— claude mcp add gemini-search -- gemini-search-mcp
  2. OpenAI 兼容 API(REST)— POST /v1/chat/completions

场景示例:

# OpenAI 兼容 API 模式
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"gemini-search","messages":[{"role":"user","content":"Bitcoin price today"}]}'

# 返回:{"choices":[{"message":{"content":"Bitcoin price today is $59,687 USD ..."}}]}

不是”免费 100 次/天”那种噱头。技术上限是每分钟 60+ 请求,平均 1.5 秒响应——因为每个请求走的都是真实浏览器的 TLS 指纹,Google 对它无条件信任。

动手测试

环境准备

环境是 Hermes Agent LXC 容器(systemd-nspawn),Chromium 147(Playwright 内置),Python 3.11.15,clash 代理。

安装过程很顺利——克隆、装依赖、项目自动发现 Chromium:

git clone https://github.com/Sophomoresty/gemini-search-mcp.git
uv venv --python 3.11 .venv
uv pip install -e .

_find_chrome() 自动扫描到 ~/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome

CDP 端口也正常监听,WebSocket 能连接。

然后第一个拦路虎出现了。

拦路虎 1:CAPTCHA

Chrome 命令行启动带 --headless=new --proxy-server 能正常访问 Google。但只要 CDP 连上,在页面执行 Page.navigate 跳转到 Google——11 秒后 URL 变为 google.com/sorry/...,验证码页面。

项目的 _warmup() 逻辑就是检查 URL 中是否含 /sorry/,失败后直接认为环境不可用。

原因:CDP 的 Page.navigate 在 TLS 指纹上与正常 Chrome 启动有细微差异。Google 把它识别为自动化操作。

项目其实内置了一个方案——undetected-chromedriver 后端

pip install -e '.[undetected]'

# 首次:有界面模式 + 手动过验证码,保存 cookie
gemini-search --no-headless --user-data-dir "$HOME/.local/share/gemini-search-mcp/chrome-profile"

# 后续:复用持久 profile,无头运行
GEMINI_SEARCH_USER_DATA_DIR="$HOME/.local/share/gemini-search-mcp/chrome-profile" gemini-search

第一次手动过验证码,之后通过持久化的 cookie + profile 绕过。这是已有的轮子,但显然我踩坑后才发现。

拦路虎 2:CDP fetch() 全盘失败

即使页面已经加载了 Google.com.hk(通过命令行走过去,没经过 CDP navigate),Runtime.evaluate 里的 fetch() 始终返回 Failed to fetch

做了多种验证:

  • same-origin fetch(/search?q=test&hl=en&gl=us)→ Failed to fetch
  • cross-origin fetch(https://httpbin.org/get)→ Failed to fetch
  • credentials: 'include' → 失败,不传 → 也失败
  • document.cookie → 正常返回
  • window.location.href → 正常返回当前 URL

这是一个奇怪的行为——JavaScript 上下文能访问 DOM 和全局对象,网络栈却被隔离开了。

在 headless Chrome CDP 环境下,Runtime.evaluate 中的 JavaScript 虽然拥有完整的页面上下文(DOM、cookie、location),但 fetch() 调用的底层网络栈实际上跑在浏览器的未初始化网络层上。项目作者说这是 headless Chrome 的已知限制,需要让浏览器先完成完整的页面加载流程再开始 Runtime.evaluate 调用——而 CDP 的 Page.navigate 在这之前就已经触发了验证码。

死锁了:不导航到 Google 就用不了 fetch(),导航了就被判自动化。

为什么试试就逝世

这个项目在三个假设上成立:

  1. 你的 Chrome 环境是无头的但指纹不太像自动化 — ubuntu desktop 系统 Chrome 通过
  2. 你的代理/网络环境稳定,CDP websocket 通信顺畅 — 跨时区代理可能通不过
  3. 你有一个”干净”的 Google profile(有正常搜索记录和 cookie) — 新建的临时 profile 容易被判机器人

我的环境恰好在这三个假设的边界上:LXC 容器内的 headless Chrome + 国内代理 + 一次性 profile。每个假设都踩了一点,叠加起来就变成系统性不可用。

能跑通的方案

方案 A:undetected-chromedriver(项目原生)

改造量最小。项目已经有完整的 scripts/uc_google_probe.py 探测脚本:

python scripts/uc_google_probe.py --proxy socks5://127.0.0.1:7897 --out-json uc-probe.json

gemini-search --browser-backend undetected --proxy-server socks5://127.0.0.1:7897

代价是需要装 selenium + chromedriver,容器内可能还要处理系统依赖。但这是项目预期的使用方式,文档最完善。

方案 B:Playwright 改造(理论上最优)

系统的 Playwright 已有 Chromium 147,Playwright 的 page.evaluate() 封装了完整的浏览器上下文,fetch() 在这种模式下应该能正常工作。

代价是需要重写 AIModeEngine 用 Playwright API 替代裸 CDP WebSocket 连接。改造量不小,但对于已经用了 Playwright 的环境来说,这是最干净的方案。

方案 C:别折腾(我的最终选择)

评估下来,我现在已经有稳定的 9Router web_search 链路(通过 Firecrawl 免费额度 + Tavily 兜底),每月搜索开销可控。改造成本 vs 收益在当前阶段不值得。先放一放,以后真有需要再说。

一些思考

不是技术不行,是环境条件不匹配。

这个项目解决的问题是:「让 Agent 不依赖任何付费搜索 API」。它的洞察是对的——真实 Chrome 浏览器的 TLS 指纹被 Google 无条件信任。但它要求你的环境满足项目隐含的三个假设。

如果环境满足(海外服务器 / 桌面系统 + 稳定的 Google 访问 + 持久 profile),这就是一个完美的搜索基础设施:
- 零运行成本
- 分钟级部署
- Google 级别的搜索质量
- 天生 MCP 支持

对于国内 Homelab 玩家,有几个点值得注意:
- 代理稳定性直接影响 CDP WebSocket 通信
- 持久 profile(包括 cookie)是绕过验证码的关键,不能偷懒
- undetected-chromedriver 是项目推荐的 fallback,不是备选而是推荐路径

最后,项目已经验证的两个技术洞察是实打实的:

  1. “免费”不是商业模式,是技术洞察——这不是薅羊毛,是用真实的浏览器身份调用 Google 的公开服务
  2. TLS 指纹是关键的区分维度——IP 限速是粗粒度策略,指纹限速是细粒度策略,但粗粒度的绕过手段有时候反而更有效

对我而言,这次测试的最大收获不是项目本身能否跑通,而是明白了什么条件下它才能跑通