搜索又花钱了
我的 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
两个入口点:
- MCP Server(stdio 协议)—
claude mcp add gemini-search -- gemini-search-mcp - 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(),导航了就被判自动化。
为什么试试就逝世
这个项目在三个假设上成立:
- 你的 Chrome 环境是无头的但指纹不太像自动化 — ubuntu desktop 系统 Chrome 通过
- 你的代理/网络环境稳定,CDP websocket 通信顺畅 — 跨时区代理可能通不过
- 你有一个”干净”的 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,不是备选而是推荐路径
最后,项目已经验证的两个技术洞察是实打实的:
- “免费”不是商业模式,是技术洞察——这不是薅羊毛,是用真实的浏览器身份调用 Google 的公开服务
- TLS 指纹是关键的区分维度——IP 限速是粗粒度策略,指纹限速是细粒度策略,但粗粒度的绕过手段有时候反而更有效
对我而言,这次测试的最大收获不是项目本身能否跑通,而是明白了什么条件下它才能跑通。