关于 PrismSearch
PrismSearch 是面向 AI Agent 的多引擎搜索 MCP 服务,可聚合网页和图片搜索结果,并搜索微信公众号文章。它还可抓取网页与 PDF;引擎自动选择并在不可用时回退。
主要功能
- 01聚合多个引擎的网页搜索
- 02提供图片与微信公众号搜索
- 03抓取网页和 PDF 内容
- 04引擎自动选择与故障回退
- 05支持本地 stdio 和远程 HTTP
适用场景
- 01为编码 Agent 查询多个搜索来源
- 02搜索图片并按类型或尺寸筛选
- 03搜索微信公众号文章并读取网页
- 04抓取长 PDF 并分页获取内容
MCP 相关
向 MCP 客户端提供 `web_search`、`image_search`、`fetch_page`、`wechat_search` 和 `list_engines` 工具。支持本地 stdio 与 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y prismsearchBRAVE_API_KEY密钥Brave Search API key (optional, comma-separated for rotation)GOOGLE_API_KEY密钥Google Custom Search API key (optional, comma-separated for rotation)GOOGLE_CSE_IDGoogle Programmable Search Engine ID (cx), used with GOOGLE_API_KEYPRISMSEARCH_HOMELocal data directory for SQLite cache and default config lookup (optional)PRISMSEARCH_CONFIGPath to a YAML/JSON/TOML config file (optional)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
PrismSearch
简体中文 | English
一款多引擎网页搜索 MCP(Model Context Protocol)服务,可聚合多个搜索引擎的搜索结果。
就像棱镜将光线分解成光谱一样,PrismSearch 会将你的搜索请求分发到多个引擎,提供多角度的结果。
为什么:为 AI Agent 提供网页搜索,无需搜索账号
Claude Code 和 DeepSeek Harness 等 AI 编码 Agent 内置的网页搜索通常依赖官方账号或单独配置的搜索 API 密钥。如果你使用第三方模型、通过自己的网关,或只是跳过搜索账号,内置搜索往往就无法使用——Agent 最终只能在“闭卷”状态下编写代码。
PrismSearch 只需一条命令,就能重新提供这一能力:
- 开箱即用,无需账号或 API 密钥:默认引擎(Bing、Baidu 等)会抓取公开结果页,因此无需注册。启用浏览器抓取功能(
fetcher.browser.enabled: true,需要 Playwright)后,Google 也无需密钥即可使用。若存在 Brave / Google API 密钥,系统会自动使用,以提高可靠性 - 支持任意模型和客户端:基于标准 MCP,可与 Claude Code、DeepSeek Harness、Cursor、VS Code、Cline 及其他任何支持 MCP 的客户端配合使用
- 不止于搜索:
fetch_page可读取网页和 PDF(输出为 Markdown,长文档支持分页),wechat_search可搜索微信公众号文章——补上“找到之后,接着阅读”这一步 - 适用于受限网络:中国来源(Baidu、Sogou、360、WeChat)开箱即用;当某个引擎被屏蔽或触发速率限制时,请求会自动切换到下一个引擎
- 结果干净:移除搜索引擎注入的赞助结果——详见下方“广告过滤”部分
# Claude Code
claude mcp add prismsearch -- npx -y prismsearch
警告
抓取引擎会从公开网页获取结果。你有责任遵守各搜索引擎和目标网站的服务条款、robots 政策及当地法律,并保持合理的请求频率。 关于学习和研究用途的建议,并非对 Apache-2.0 许可证的额外限制。本项目与任何搜索引擎公司均无关联。请参阅末尾的完整免责声明。
功能
- 9 个搜索来源:Google、Bing、百度、Brave、DuckDuckGo、Yandex、搜狗、360 搜索,以及微信公众号文章——支持可扩展的搜索引擎插件系统
- 5 个 MCP 工具:
web_search、image_search、fetch_page、wechat_search、list_engines - 双传输方式:stdio(本地)和 Streamable HTTP(远程)MCP 传输
- 智能引擎选择:根据可用性、延迟、成功率和语言匹配度自动选择最佳引擎,并支持跨引擎回退
- Google 三重策略:自定义搜索 API → 浏览器渲染 → 普通 HTTP,支持自动回退和成功结果记忆
- 广告过滤:移除百度推广、Bing / Google / DuckDuckGo 赞助结果以及 360 / 搜狗付费结果,这些结果不会占用请求的数量;漏网结果还会根据其落地页 URL(付费点击跟踪参数)再次过滤
- 网页抓取:从 URL 抓取并提取 HTML、纯文本或 Markdown 格式的内容;可选使用 Playwright 渲染 JavaScript 密集型网页
- 图片搜索:支持多引擎图片搜索、尺寸/类型过滤和可选的 base64 缩略图
- 缓存:可配置 TTL 和 LRU 淘汰,并支持可插拔后端——
cache.backend: sqlite | memory | redis(默认使用 SQLite) - 安全性:SSRF 防护、速率限制、域名白名单/黑名单,以及远程模式下可选的 Bearer 身份验证
- 热重载:监视配置文件并自动重载
- 灵活配置:支持 YAML/JSON/TOML 配置,并可通过环境变量覆盖
示例
一次 web_search 调用即可返回结构化且去重的结果:
{
"results": [
{
"title": "Model Context Protocol - Introduction",
"url": "https://modelcontextprotocol.io/introduction",
"snippet": "The Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools.",
"source": "brave",
"position": 1
}
],
"totalResults": 10,
"engine": "brave",
"searchTime": 842,
"cached": false,
"page": 1,
"hasMore": true
}
results[] 中的每个条目始终包含 title、url、snippet、source(搜索引擎)和 position,也可能包含 timestamp;使用 mode=aggregate 时,条目还会包含 sources,响应中则会包含 engines。如果引擎忽略了某些参数,响应中会包含 warnings。相同的 JSON 会同时作为 structuredContent 和 content 中的文本返回。
架构
flowchart LR
Client["MCP client<br/>Claude Code / Cursor / …"]
subgraph Transport["Transport src/server"]
Stdio["stdio"]
Http["Streamable HTTP<br/>auth · Host/Origin check · rate limit"]
end
subgraph Tools["Tools src/tools"]
WS["web_search"]
IS["image_search"]
WX["wechat_search"]
FP["fetch_page"]
LE["list_engines"]
end
subgraph Search["Search orchestration"]
Sel["Engine selection / circuit breaker<br/>engine-selector"]
Chain["Fallback chain · aggregate RRF<br/>dedup · ad filter"]
end
Engines["Engine adapters src/engines<br/>Google · Bing · Brave · Baidu · DDG<br/>Yandex · Sogou · 360 · Sogou WeChat"]
Cache[("Cache src/cache<br/>sqlite / memory / redis")]
subgraph Fetch["Fetching src/fetcher"]
SSRF["SSRF guard<br/>src/security/ssrf-guard"]
HF["HTTP fetcher"]
BF["Browser fetcher<br/>Playwright"]
WK["Remote workers<br/>ts-worker / py-worker"]
EX["Content extraction<br/>Readability / PDF"]
end
Client --> Stdio & Http
Stdio & Http --> Tools
WS & IS --> Sel --> Chain --> Engines
WX --> Engines
LE -. status .-> Sel
WS & IS & WX & FP -. read/write .-> Cache
FP --> SSRF --> HF & BF & WK
HF & BF & WK --> EX
在 stdio 模式下只有一个客户端,因此速率限制发生在工具层;在 HTTP 模式下,传输层会按客户端进行速率限制。是否将 fetch_page 委派给工作进程由 workers.useFor 控制;如果没有可用的工作进程,则会回退到本地抓取器,并再次对工作进程返回的最终 URL 进行 SSRF 检查。
要求
- Node.js ≥ 22.19
- 原生模块
better-sqlite3为主流平台(Windows/macOS/Linux,x64/arm64)提供预构建二进制文件;如果你的平台没有可用的预构建版本,则需要 C++ 构建工具链 - 可选:Playwright,用于浏览器渲染。它是一个
optionalDependency——默认安装(安装时会下载浏览器);如需精简安装,请使用npm install --omit=optional。之后也可以通过以下命令添加:npm install playwright && npx playwright install chromium
快速开始
安装
npm install prismsearch
与 Claude Code 搭配使用
claude mcp add prismsearch -- npx -y prismsearch
或者添加到 MCP 设置中:
{
"mcpServers": {
"prismsearch": {
"command": "npx",
"args": ["-y", "prismsearch"],
"env": { "BRAVE_API_KEY": "optional" }
}
}
}
其他客户端
| 客户端 | 配置位置 | 备注 |
|---|---|---|
| Claude Desktop | claude_desktop_config.json | 使用相同的 mcpServers 代码段 |
| Cursor | ~/.cursor/mcp.json 或 .cursor/mcp.json | 使用相同的 mcpServers 代码段 |
| VS Code (Copilot) | .vscode/mcp.json | 顶层键为 servers;添加 "type": "stdio" |
| Windsurf / Cline 等 | 各自的 MCP 配置 | 通用的 command + args 格式 |
| 远程(HTTP) | 任意 Streamable HTTP 客户端 | URL http://host:3000/mcp,请求头 Authorization: Bearer <token> |
在 Windows 上,如果客户端找不到 npx,请将 command 设置为 "cmd",并将 args 设置为 ["/c", "npx", "-y", "prismsearch"]。
用作 Agent 技能
skills/prismsearch/SKILL.md 是一项 Agent 技能,用于指导 Agent 何时使用各个工具:先搜索,再阅读源页面;使用 timeRange / aggregate 模式;必要时回退到浏览器渲染;翻阅较长的文档;以及处理引擎故障。上文的 MCP 服务仍需连接;该技能仅提供使用指导。
若要在 Claude Code 中安装,请将文件夹复制到技能目录:
# All projects
cp -r skills/prismsearch ~/.claude/skills/
# Current project only
cp -r skills/prismsearch .claude/skills/
其他支持 Agent Skills 格式的 Agent 也可以加载同一文件夹。
在 DeepSeek Harness 中使用
dsh-plugin-prismsearch 是一个 DeepSeek Harness 插件,可一步安装 MCP 服务和技能。在 DSH Web GUI 中,打开 Plugins → Add plugin 并输入:
dsh-plugin-prismsearch
该插件通过 npx 启动固定版本的 prismsearch,因此 PATH 中必须有 Node.js >=22.19.0。首次启动时会下载软件包,可能需要几秒钟。工具会显示为 mcp__prismsearch__web_search 等名称。如果启动 DSH 的环境中设置了 BRAVE_API_KEY、GOOGLE_API_KEY 或 GOOGLE_CSE_ID,这些变量会转发给服务。如果你之前手动添加了 serverName: prismsearch 的 MCP 配置项,请先移除或重命名,否则两个配置项会冲突。详情请参阅插件 README。
引擎能力
| 引擎 | 网页 | 图片 | 方法 | 默认启用 | 备注 |
|---|---|---|---|---|---|
| ✅ | ✅ | API / 浏览器 / HTTP | 是 | Custom Search API 最可靠;纯 HTTP 通常会遇到 JS 屏蔽 | |
| Bing | ✅ | ✅ | HTTP 抓取 | 是 | |
| Brave | ✅ | ✅ | 官方 API | 是 | 需要 BRAVE_API_KEY;未设置时会跳过 |
| Baidu | ✅ | ✅ | HTTP 抓取 / JSON API | 是 | 中文内容 |
| DuckDuckGo | ✅ | — | HTTP 抓取 | 否 | 请求过于频繁会触发机器人验证 |
| Yandex | ✅ | — | HTTP 抓取 | 否 | |
| Sogou | ✅ | — | HTTP 抓取 | 否 | 中文内容 |
| 360 Search | ✅ | — | HTTP 抓取 | 否 | 中文内容 |
各引擎的参数支持情况(网页搜索)
web_search 的每个参数在各引擎中的转换方式。“—”表示该引擎没有对应参数;参数会被接受但忽略,响应的 warnings 会列出被舍弃的参数。list_engines 也会在其 capabilities 字段中声明各引擎支持的参数。
| 引擎 | region | language | safeSearch | timeRange | page | count |
|---|---|---|---|---|---|---|
| Google(抓取) | gl | hl | safe=active | tbs=qdr:d/w/m/y | start 偏移量 | num |
| Google(Custom Search API) | gl | hl | safe=active/off | dateRestrict | start 偏移量,总计最多 100 条结果 | 每次请求 10 条;较大的数量会抓取多个页面 |
| Bing | cc(国家/地区,uk → GB)+ mkt(市场) | setlang | adlt=strict | filters=ex1:"ez1/ez2/ez3",年份范围使用自定义范围 | first 偏移量(按实际返回的结果数递增) | 每页约 10 条;较大的数量会合并多个页面的结果 |
| Brave | country(uk → GB) | search_lang | safesearch=strict/moderate | freshness=pd/pw/pm/py | offset,最多 10 页 | 每次请求最多 20 条;较大的数量会抓取多个页面 |
| Baidu | — | — | — | gpc=stf=…(时间范围) | pn 偏移量 | rn |
| DuckDuckGo | kl(地区 + 语言,例如 us-en) | 用于 kl / Accept-Language | kp=1 | df=d/w/m/y | s 偏移量 | 在客户端截断 |
| Yandex | lr(地区 ID) | lang | — | — | p(从 0 开始) | numdoc |
| Sogou | — | — | — | s_from=inttime_* | page | 每页固定 10 条,在客户端截断 |
| 360 Search | — | — | — | adv_t=d/w/m/y | pn | 每页固定 10 条,在客户端截断 |
图片搜索:Google(gl / hl / safe,大小和类型通过 tbs 设置)、Bing(setlang、safesearch=strict,大小和类型通过 qft 设置)、Brave(country / search_lang / safesearch;API 不支持分页,因此从最多 200 条结果中切分页面)、Baidu(通过 z 设置大小,通过 ic 设置 GIF;不支持地区 / 语言 / 安全搜索)。
第 1 页会由服务多抓取一些结果,以便去重后仍能凑足 count;自动选择搜索引擎的后续页面会继续使用提供第 1 页结果的引擎,避免结果在不同引擎之间跳转。
微信公众号文章使用单独的 wechat 配置区段(不是常规引擎),由 wechat_search 工具提供;返回的链接会过期。
抓取类引擎依赖页面结构,搜索引擎改版时可能会短暂失效;项目每天都会运行实时冒烟测试,以便尽早发现问题。
通过 HTTP 传输方式使用
# Start with the bundled HTTP example config
npx prismsearch config/http.yaml
# Or use environment variables
PRISMSEARCH_SERVER_TRANSPORT=http PRISMSEARCH_SERVER_PORT=3000 npx prismsearch
HTTP 端点为 http://127.0.0.1:3000/mcp(健康检查端点为 /health)。将其开放给 localhost 以外的访问时,务必启用身份验证:设置 PRISMSEARCH_AUTH_TOKENS,或在配置中启用 security.auth。
命令行界面
prismsearch [config-file] # start the server; the optional positional argument is a config file (YAML / JSON / TOML)
prismsearch --help # bilingual (English / Chinese) help including common environment variables (-h)
prismsearch --version # print the version (-v)
位置参数的优先级最高,高于 PRISMSEARCH_CONFIG 和默认搜索路径(参见“配置”)。如果指定的文件不存在,服务会报错退出。传输方式、端口等不是命令行标志;请在配置文件中或通过环境变量设置(参见“环境变量”)。该命令行界面有意保持为轻量启动器:它不提供浏览器 UI、托管搜索账号或独立的 Web 控制面板;请使用支持 MCP 的客户端(或 HTTP 传输方式)调用这些工具。
npm 包仅包含此命令行界面 / MCP 服务;它不是 JavaScript 库。请勿 import 'prismsearch' 或深度导入 dist/ 下的文件——导入入口文件会启动服务,内部模块也可能在任何版本中变更。稳定且有版本管理的接口包括 MCP 工具架构、配置文件和 Worker 协议;若要扩展抓取功能,请实现 Worker;若要添加引擎,请向上游贡献代码或创建分支。
隐私和本地数据
PrismSearch 不提供托管数据服务。在默认的本地 stdio 配置中,请求和响应会经过本地进程;缓存条目存储在本地(默认使用 SQLite),日志则写入本地进程的标准错误流。如果启用远程 HTTP 传输、第三方 API 密钥、浏览器抓取、代理、Redis 或 Workers,查询文本、URL、标头和抓取的内容可能会发送给这些提供方或服务。请查看其隐私政策,并为你的部署配置数据保留策略、访问控制和 log.redact。除非你已核实数据传递路径中的每项服务,否则请勿提交密码、私有令牌、个人数据或机密内容。
条款、版权和服务访问
搜索摘要、图片、网页、PDF 和微信公众号文章由第三方提供,可能受版权或其他权利保护。PrismSearch 不授予复制、存储、展示、抓取或再分发第三方内容的权利。你有责任确认权限、署名、robots 指令、适用法律以及各提供方的条款和速率限制。Apache-2.0 许可证仅适用于本仓库的代码;它不授予访问任何搜索服务的权限,不允许绕过身份验证或反机器人控制,也不授予第三方商标或内容的使用许可。
MCP 工具
web_search
使用多个搜索引擎(Google、Bing、Baidu、360、Sogou、DuckDuckGo、Yandex、Brave)搜索网页。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| query | string | 是 | - | 搜索关键词,去除首尾空格后为 1-500 个字符 |
| engine | string | 否 | auto | 搜索引擎:google、bing、baidu、so、sogou、duckduckgo、yandex、brave;未提供时自动选择,并在失败时切换备用引擎 |
| region | string | 否 | - | 地区代码(例如 cn、us、hk),最多 10 个字符 |
| language | string | 否 | - | 语言代码(例如 zh-CN、en),最多 20 个字符 |
| count | integer | 否 | 10 | 结果数量,1-50 |
| page | integer | 否 | 1 | 页码,1-10 |
| safeSearch | boolean | 否 | false | 启用安全搜索 |
| timeRange | string | 否 | - | 时间筛选:day、week、month、year;自动选择时优先使用支持此功能的搜索引擎 |
| mode | string | 否 | fallback | fallback:使用一个搜索引擎,失败时切换备用引擎;aggregate:并发查询排名前 3 的可用搜索引擎,并通过倒数排名融合(Reciprocal Rank Fusion)合并结果(去重后的结果包含 sources,响应包含 engines) |
当客户端传入 _meta.progressToken 时,服务会在每次尝试或启动搜索引擎时发送 notifications/progress。
image_search
使用多个搜索引擎(Google、Bing、Baidu、Brave)搜索图片。
参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| query | string | 是 | - | 搜索关键词,去除首尾空格后为 1-500 个字符 |
| engine | string | 否 | auto | 支持图片搜索的引擎:google、bing、brave、baidu;未提供时自动选择,并在失败时切换备用引擎 |
| region | string | 否 | - | 地区代码,最多 10 个字符 |
| language | string | 否 | - | 语言代码,最多 20 个字符 |
| count | integer | 否 | 10 | 结果数量,1-50 |
| page | integer | 否 | 1 | 页码,1-10 |
| safeSearch | boolean | 否 | false | 启用安全搜索 |
| imageSize | string | 否 | - | 按尺寸筛选:small、medium、large |
| imageType | string | 否 | - | 按类型筛选:photo、clipart、gif、transparent |
| includeThumbnails | boolean | 否 | false | 在结果中内嵌 base64 缩略图(最多 20 张,每张 50KB) |
每个结果包含 title、imageUrl、thumbnailUrl、sourceUrl、position 和 source,也可能包含 sourceTitle、width、height 和 thumbnailBase64;响应还包含 engine、searchTime、cached、page 和 hasMore。
fetch_page
从网页 URL 获取并提取内容。
参数:
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| url | string | 是 | - | 要获取的 URL,仅支持 http/https,最多 4096 个字符 |
| format | string | 否 | markdown | 输出格式:html、text、markdown |
| timeout | integer | 否 | 30000 (fetcher.timeout) | 总超时时间,单位为毫秒,范围为 1000-120000,由所有回退/重新获取尝试共享 |
| method | string | 否 | http (fetcher.defaultMethod) | 获取方式:http 或 browser(用于 JS 渲染页面的 Playwright)。省略时,如果 http 结果看起来像 JS 骨架页面或反机器人挑战页面,则会使用浏览器重新获取(如果可用)。显式指定 http 时不会升级;如果 Playwright 不可用,browser 会回退到 http 并发出警告 |
| waitForSelector | string | 否 | - | 仅限浏览器:提取前等待的 CSS 选择器,最多 500 个字符;如果该选择器始终未出现,则返回截至目前已渲染的内容 |
| maxLength | integer | 否 | 20000 | 每次调用返回的内容最大字符数,范围为 100-1000000;超出时,结果会包含 truncated: true 和 nextStartIndex |
| startIndex | integer | 否 | 0 | 起始字符偏移量(≥ 0);使用 nextStartIndex 读取剩余内容(从同一缓存条目提供,不会重新获取) |
totalLength 是完整内容的长度;bodyTruncated 表示响应正文超出 fetcher.maxBytes,因此只获取了开头部分。使用 format=html 时,HTML 会一次性在 content 中返回。
提取正文内容时会优先使用 Mozilla Readability(@mozilla/readability + linkedom),并在失败时回退到内置启发式方法。PDF 会提取其文本层(使用 unpdf,最多处理前 50 页);没有文本层的扫描版 PDF 会发出警告。所有目标 URL 都会先经过 SSRF 防护检查(参见“安全性”)。
wechat_search
通过搜狗微信搜索微信公众账号文章。返回文章标题、账号名称、发布日期、摘要和带签名的临时文章 URL。
注意:
- 文章 URL 带有签名且有时限(通常几小时内有效)——请及时使用
fetch_page获取完整内容。 - 搜索结果仅缓存 10 分钟(由于 URL 会过期,缓存时间短于网页搜索)。
- 搜狗会实施速率限制;该引擎会自动轮换 Cookie,并采用退避策略重试。
参数:
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| query | string | 是 | - | 搜索关键词(中文效果最佳),去除首尾空格后长度为 1-200 个字符 |
| count | integer | 否 | 10 | 结果数量,范围为 1-10 |
| page | integer | 否 | 1 | 页码,范围为 1-10 |
list_engines
列出所有已注册搜索引擎及其当前状态,包括可用性、延迟和支持的功能。无参数。
配置
PrismSearch 会按以下顺序使用找到的第一个配置文件:
- 作为命令行参数传入的路径(
npx prismsearch ./my-config.yaml) PRISMSEARCH_CONFIG环境变量- 当前工作目录中的
./prismsearch.{yaml,yml,json,toml} ~/.prismsearch/config.{yaml,yml,json,toml}(如果设置了PRISMSEARCH_HOME,则目录遵循该变量)
如果找不到配置文件,则使用内置默认值。环境变量会在优先级最高的配置来源之上应用。
config/default.yaml 是每个选项的注释参考。它不会自动加载——请将其复制到上述某个位置(或将 PRISMSEARCH_CONFIG 指向它),并仅保留你想要更改的键。
启用更多引擎: 默认仅启用 Google、Bing、Brave 和 Baidu。config/default.yaml 中列出了 DuckDuckGo、Yandex、Sogou 和 360 Search,并设置了 enabled: false——在你自己的配置中将其设为 true(或设置 PRISMSEARCH_ENGINES__DUCKDUCKGO__ENABLED=true)。
搜索截止时间: search.deadlineMs(默认值为 45000)限制一次 web_search / image_search 调用在整个回退链上的总耗时;达到此时间后,不会再尝试其他引擎,因此客户端不会在多个引擎依次超时时一直等待。取消 MCP 请求也会中止正在进行的上游请求。
广告过滤: 分为两层。(1)解析时,每个引擎都会跳过带有广告标记的结果(赞助标签、仅用于广告的类 / 属性、广告区域)——始终启用。(2)工具层会丢弃其落地页 URL 看起来像广告的其余结果(广告点击重定向主机,以及 sdclkid、gclid、msclkid、utm_medium=cpc/ppc/sem 等付费跟踪参数)。可通过 search.adFilter: false(或 PRISMSEARCH_SEARCH__ADFILTER=false)关闭第(2)层。百度自有的垂直领域卡片(例如爱采购 / 惠生活)不是广告,会予以保留。
引擎亲和性: 请求携带 region / language 时,选择器会优先选择适合该地区 / 语言的引擎。每个引擎都可以通过 regions 和 languages 覆盖内置默认值(例如,Baidu 默认适用于 cn/hk/tw 和中文);留空以保留内置值,或设置新值以完全替换内置值。地区匹配不区分大小写。
Google 搜索设置
自 2025 年起,Google 要求搜索结果页面使用 JavaScript 渲染——纯 HTTP 抓取只会收到“启用 JavaScript”的过渡页面。PrismSearch 的 Google 引擎支持三种策略,并按顺序尝试,自动回退并记住成功的策略:Custom Search API → 浏览器渲染 → 纯 HTTP。
选项 A:浏览器渲染(Playwright)
npm install playwright
npx playwright install chromium
然后在配置中启用浏览器抓取器:
fetcher:
browser:
enabled: true
browserType: chromium
选项 B:Google Custom Search API(推荐,最稳定)
免费额度:每个 API 密钥每天 100 次查询。需要两项凭据:
| 凭据 | 配置字段 | 环境变量 |
|---|---|---|
| API 密钥 | engines[].apiKey(用逗号分隔,以便轮换) | GOOGLE_API_KEY |
| 搜索引擎 ID(cx) | engines[].searchEngineId | GOOGLE_CSE_ID |
获取方法:
- 打开 Google Cloud Console 并创建或选择一个项目。
- 前往 APIs & Services → Library,搜索 Custom Search API,然后点击 Enable。
- 前往 APIs & Services → Credentials → Create Credentials → API key。 (建议将密钥限制为仅用于“Custom Search API”。)
- 打开 Programmable Search Engine, 点击 Add,选择 Search the entire web,然后复制 Search engine ID(cx)。
- 通过环境变量设置凭据(推荐——切勿将密钥提交到 git):
# Windows (persistent)
setx GOOGLE_API_KEY "AIza..."
setx GOOGLE_CSE_ID "0123456789abcdef0"
# macOS / Linux
export GOOGLE_API_KEY="AIza..."
export GOOGLE_CSE_ID="0123456789abcdef0"
如果两种选项都可用,则优先使用 API;额度耗尽(429/403)时,引擎会自动回退到浏览器渲染。
你可以通过以下方式端到端验证设置:
npm run build
node scripts/dev/verify-google-e2e.mjs "openai"
Brave 搜索设置
Brave 提供免费 API 额度(每月 2,000 次查询,无需信用卡)。 在 https://brave.com/search/api/ 注册,然后:
# Windows
setx BRAVE_API_KEY "BSA..."
# macOS / Linux
export BRAVE_API_KEY="BSA..."
多个以逗号分隔的密钥会在额度耗尽时自动轮换。
环境变量
环境变量会在配置文件的基础上生效(优先级:内置默认值 < 配置文件 < 环境变量)。
| 变量 | 描述 |
|---|---|
PRISMSEARCH_CONFIG | 配置文件路径(YAML / JSON / TOML);CLI 位置参数优先 |
PRISMSEARCH_HOME | 数据目录,默认为 ~/.prismsearch;存放默认缓存数据库 cache.db 和用户配置 config.* |
PRISMSEARCH_AUTH_TOKENS | 逗号分隔的访问令牌;非空值会自动启用 security.auth。HTTP 客户端发送 Authorization: Bearer <token> |
PRISMSEARCH_WORKER_TOKEN | 共享的抓取 Worker 令牌;当 workers.endpoints[].token 为空时使用。Worker 读取同一变量 |
GOOGLE_API_KEY / GOOGLE_CSE_ID | Google Custom Search API 密钥(逗号分隔以便轮换)和搜索引擎 ID(cx) |
BRAVE_API_KEY | Brave Search API 密钥(逗号分隔以便轮换);未设置时会跳过 Brave |
PRISMSEARCH_SERVER_TRANSPORT | stdio(默认)| http |
PRISMSEARCH_SERVER_PORT / PRISMSEARCH_SERVER_HOST | HTTP 端口(默认为 3000)和绑定地址(默认为 127.0.0.1) |
PRISMSEARCH_LOG_LEVEL | error | warn | info | debug |
PRISMSEARCH_<path> | 覆盖任意配置键,见下文 |
配置文件中的非空 apiKey / searchEngineId 优先于 GOOGLE_* / BRAVE_API_KEY;空字符串视为未设置,因此仍会使用环境变量。
任何配置键都可以通过 PRISMSEARCH_ 前缀覆盖。层级之间优先使用双下划线;单个层级内的下划线会被忽略,名称不区分大小写,因此 RATE_LIMIT 和 RATELIMIT 都匹配 rateLimit。在 engines 下一级为引擎名称。旧版单下划线格式(PRISMSEARCH_SERVER_PORT)仍可使用。与现有键不匹配的变量会被忽略,并在启动时发出警告。
PRISMSEARCH_SECURITY__RATE_LIMIT__MAX_REQUESTS=30 # security.rateLimit.maxRequests
PRISMSEARCH_ENGINES__BING__ENABLED=false # engines[name=bing].enabled
PRISMSEARCH_ENGINES__DUCKDUCKGO__ENABLED=true
PRISMSEARCH_CACHE__BACKEND=redis
PRISMSEARCH_CACHE__TTL=7200
PRISMSEARCH_FETCHER__BROWSER__ENABLED=true
# Arrays: JSON or comma-separated
PRISMSEARCH_SECURITY__SSRF__WHITELIST='["intranet.example.com","*.corp.example"]'
PRISMSEARCH_SERVER__ALLOWED_HOSTS=search.example.com,localhost
值会转换为目标键的类型:true / false 会转换为布尔值,数字会转换为数值,数组键接受 JSON 数组或逗号分隔的列表。仓库根目录中的 .env.example 列出了常用变量。
抓取 Worker(可选)
Worker 是可选的抓取后端,不是 MCP 服务,也不是额外的搜索引擎。MCP 客户端只连接主服务;不要将 Worker URL 配置为 MCP 端点,也不要将 Worker 端口公开到公网。委派请求会跨越信任边界:Worker 运营者可以查看请求的 URL、提供的标头以及抓取的内容。仅使用你信任的 Worker;跨主机通信时使用专用网络或 TLS,并设置单独的 Worker 令牌;本地回退可能会将流量转回主服务所在的网络。
有些页面只有通过 JavaScript 渲染才能正常工作,另一些页面则会对 TLS 握手进行指纹识别。对于这些页面,可以将抓取任务转交给单独部署的 Worker。两种 Worker 类型使用相同的 HTTP + JSON 协议(参见 docs/worker-protocol.md);主服务会在它们之间进行负载均衡、检查健康状态、故障转移,并在没有可用 Worker 时回退到本地抓取。
| Worker | 能力 | 最适用场景 |
|---|---|---|
workers/ts-worker | http + browser(Playwright) | 仅支持 JS 的页面、验证码中间页 |
workers/py-worker | http(curl_cffi + trafilatura) | 基于指纹识别的反机器人机制、更整洁的内容提取 |
# Start the server plus both workers (both tokens are required)
export PRISMSEARCH_AUTH_TOKENS=<server access token>
export PRISMSEARCH_WORKER_TOKEN=<shared worker token>
export PRISMSEARCH_WORKERS_ENABLED=true
docker compose -f docker/docker-compose.yml --profile with-workers up -d --build
配置档案只决定启动哪些容器;只有设置 PRISMSEARCH_WORKERS_ENABLED=true 才会在主服务中启用委派(compose 已配置好两个 Worker 端点)。在 compose 之外,请在配置中启用它们:
workers:
enabled: true
strategy: least-busy # or round-robin (smooth weighted)
useFor: browser # browser: delegate render requests only; always: delegate everything
fallbackToLocal: true
endpoints:
- { name: ts-1, url: http://ts-worker:8787, weight: 100 }
- { name: py-1, url: http://py-worker:8788, weight: 50 }
未配置令牌的 Worker 只会绑定到 loopback 地址——它会拒绝向网络开放自身。
Docker
每个版本都会构建三个多架构(amd64 / arm64)镜像:
| 镜像 | 内容 |
|---|---|
ghcr.io/xiaonerner0821/prismsearch | 主服务(HTTP 模式,端口 3000) |
ghcr.io/xiaonerner0821/prismsearch-ts-worker | 浏览器渲染工作器(Playwright,端口 8787) |
ghcr.io/xiaonerner0821/prismsearch-py-worker | 指纹模拟工作器(curl_cffi + trafilatura,端口 8788) |
单独运行主服务:
docker run -d -p 127.0.0.1:3000:3000 \
-e PRISMSEARCH_AUTH_TOKENS=<access token> \
ghcr.io/xiaonerner0821/prismsearch:latest
- 镜像在容器内以 HTTP 模式监听
0.0.0.0,因此必须设置PRISMSEARCH_AUTH_TOKENS;否则服务会拒绝启动。客户端发送Authorization: Bearer <access token> - 示例仅将端口发布到主机的
127.0.0.1;如果需要从主机之外访问,请在前面放置 TLS 反向代理 - 数据目录为
/app/data(PRISMSEARCH_HOME);在此处挂载卷以持久保存缓存。若要使用自己的配置文件,请挂载该文件并将PRISMSEARCH_CONFIG指向它 - 主镜像不包含浏览器(未安装 Playwright,且
fetcher.browser已关闭)。若要进行 JS 渲染,请运行 ts-worker 并在配置中启用workers(参见上一节)
使用 compose(从仓库根目录运行):
export PRISMSEARCH_AUTH_TOKENS=<access token>
docker compose -f docker/docker-compose.yml up -d
# Also start both workers and delegate to them (PRISMSEARCH_WORKER_TOKEN is required too)
export PRISMSEARCH_WORKER_TOKEN=<shared worker token>
PRISMSEARCH_WORKERS_ENABLED=true docker compose -f docker/docker-compose.yml --profile with-workers up -d
# Use the Redis cache (a password is required; the redis container refuses to start without one)
export PRISMSEARCH_REDIS_PASSWORD=<random long string>
PRISMSEARCH_CACHE_BACKEND=redis docker compose -f docker/docker-compose.yml --profile with-redis up -d
可以同时启用这两个配置。各服务的设置请参阅 docker/docker-compose.yml 中的注释。
安全
- 身份验证:在 HTTP 模式下,绑定到非环回地址时必须进行身份验证(Bearer 令牌或
X-API-Key),否则服务会拒绝启动;令牌比较采用恒定时间算法 - 主机 / Origin 检查:防止 DNS 重绑定和跨站请求;如需放宽限制,可使用
server.allowedHosts/server.allowedOrigins - 速率限制:HTTP 模式下按客户端划分速率桶(凭据指纹或地址);stdio 模式下在工具层实施限制
- SSRF 防护:
fetch_page和工作器仅允许 http/https,屏蔽私有、环回、链路本地和其他保留地址,在连接时重新检查解析后的地址(防止 DNS 重绑定),并检查每一跳重定向 - 错误和日志:返回给客户端的错误会经过允许列表筛选,内部详细信息仅写入日志;默认情况下,日志会对查询字符串和搜索词进行脱敏
有关如何报告漏洞,请参阅 SECURITY.md。
SSRF 白名单
security.ssrf.whitelist 仅允许明确配置的主机名,不会绕过 IP 验证。若要允许访问私有目标,请在 security.ssrf.allowedPrivateHosts 中使用精确主机名(不支持通配符),并检查网络边界。非环回 Worker Origin 还需要精确的 workers.allowedOrigins 条目(末尾不带斜杠)、令牌,并且必须使用 HTTPS,除非端点明确设置了本地 / 内网 allowInsecureHttp 例外;环回 Worker(localhost、127.0.0.1、::1)可以使用普通 HTTP。因此:
- 仅将确实需要且其 DNS 由你控制的域名加入白名单;不要使用公共域名或宽泛的通配符
security.ssrf.blacklist的优先级高于白名单- 白名单仅匹配主机名;字面 IP URL 仍会受到 IP 规则检查
- Worker
allowedOrigins条目必须是末尾不带斜杠的精确 Origin;非环回 Origin 需要令牌并使用 HTTPS
开发
# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run dev
# Unit tests (offline)
npm test
# Tests with coverage (enforces minimum thresholds)
npm run test:coverage
# Live smoke tests against real search engines (opt-in, not run by default)
npm run test:live
# Lint and typecheck
npm run lint
npm run typecheck
# Worker tests
npm run test:worker # TS Worker
npm run test:worker:py # Python Worker (create the venv first, see CONTRIBUTING)
# Pre-release self-check: build + artifacts / version / required files / stdio handshake
npm run selfcheck
可选的端到端验证脚本位于 scripts/dev/ 中(脚本会针对构建产物运行并访问真实搜索引擎);用法请参阅 CONTRIBUTING。
项目结构
prismsearch/
├── src/
│ ├── index.ts # Entry point
│ ├── version.ts # Single source of truth for version (reads package.json)
│ ├── server/ # MCP server & transports (stdio / Streamable HTTP)
│ ├── tools/ # MCP tool implementations (5 tools)
│ ├── engines/ # Search engine providers (google/bing/baidu/brave/
│ │ # duckduckgo/yandex/so/sogou/wechat)
│ ├── fetcher/ # HTTP & browser (Playwright) fetchers, content extraction
│ ├── workers/ # Fetch worker client (balancing, health checks, failover)
│ ├── cache/ # Caching layer (SQLite / Redis / in-memory)
│ ├── config/ # Configuration system (YAML/JSON/TOML + env overrides + hot reload)
│ ├── security/ # SSRF guard, rate limiter, auth, content filter
│ └── utils/ # Logger, dedup, API key rotation, proxy pool
├── config/ # Default & example configuration
├── docker/ # Dockerfile & docker-compose
├── docs/ # Protocol and design documents
├── scripts/ # Version / self-check scripts; dev/ holds dev verification scripts (see CONTRIBUTING)
├── tests/ # Unit & integration tests
└── workers/ # Optional remote fetch workers
├── ts-worker/ # Playwright rendering (Node)
└── py-worker/ # curl_cffi impersonation + trafilatura (Python)
路线图
- WebSocket 长连接传输
-
图片搜索支持(v0.3.1) -
无头浏览器抓取器(Playwright)(v0.3.1) -
Docker 部署(v0.3.1) -
API 密钥管理与轮换(v0.3.1) -
远程模式身份验证(v0.3.1) -
Redis 缓存后端(v0.3.1) -
远程抓取工作器(浏览器渲染/指纹模拟)(v0.3.1) -
工作器负载均衡与故障转移(v0.3.1) -
内容安全过滤(v0.3.1)
常见问题
Google 持续失败或返回零条结果。
自 2025 年起,Google 要求使用 JavaScript 渲染结果页面,因此纯 HTTP 抓取通常无法获取任何内容。请选择以下方式之一:配置 GOOGLE_API_KEY + GOOGLE_CSE_ID 使用官方 API(最可靠);启用 fetcher.browser 并安装 Playwright;或启用 ts-worker 来委托渲染。否则,请求会自动回退到其他搜索引擎。
我遇到了速率限制(429)或验证码。
抓取搜索引擎对请求量很敏感。请调低每个引擎的 rateLimit,配置代理池(fetcher.proxy),或优先使用 Brave/Google API。缓存默认启用,因此重复查询不会再次访问搜索引擎。
HTTP 模式下将绑定地址设为 0.0.0.0 后,服务会立即退出。
这是有意设置的安全措施:绑定到非回环地址需要身份验证。请设置 PRISMSEARCH_AUTH_TOKENS,并让客户端发送 Authorization: Bearer <token>。
执行 npm install 构建 better-sqlite3 时失败。
通常是因为平台没有预编译二进制文件,且缺少 C++ 工具链。请安装构建工具,或将 cache.backend 切换为 memory / redis。
缓存和日志存放在哪里?
缓存默认存放在 ~/.prismsearch/cache.db(可通过 PRISMSEARCH_HOME 或 cache.sqlite.path 覆盖);日志默认写入 stderr,因此不会破坏 stdio 协议。
如何检查实际加载的是哪个配置文件?
运行 npm run build && node scripts/check-cwd-config.mjs。该命令会打印生效的配置文件、按优先级排列的所有候选路径、已启用的引擎,以及每个 API 密钥是否已设置(不会显示密钥值)。如果配置更改似乎没有生效,请从这里开始排查。
免责声明
PrismSearch 依据 Apache-2.0 许可提供,你可以根据该许可使用、修改和重新分发。项目建议以学习、研究和个人用途作为更安全的起点,但这项建议并非额外的许可限制。抓取搜索引擎会从公开网页获取结果;用户有责任遵守各搜索引擎和目标网站的服务条款、robots 政策、版权和隐私规则、当地法律以及合理的请求频率。本项目与 Google、Microsoft、Brave、Baidu、Sogou、360、Yandex、DuckDuckGo、Tencent 或任何其他公司均无关联;所有商标均归其各自所有者所有。许可仅涵盖本仓库的代码,不授予第三方内容、商标或服务访问权限。使用本项目造成的任何后果均由用户自行承担。
有关部署、反向代理、资源限制、健康检查/指标、数据清理和维护者交接,请参阅 运维手册。有关依赖项和第三方许可的范围,请参阅 第三方声明。
贡献
欢迎贡献!有关开发环境设置、分支/提交规范以及添加新搜索引擎的分步指南,请参阅 CONTRIBUTING.md(中文)。参与项目即表示你同意遵守行为准则。
需要帮助?请参阅 SUPPORT:使用问题请到 Discussions,错误请到 Issues。
发现安全问题?请按照 SECURITY.md 中的说明私下报告。
许可证
Apache License 2.0 — 另请参阅 NOTICE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。