Klavis 项目中的 Brave Search MCP 服务器:TypeScript 实现的工具定义、双传输模式与智能回退机制解析
2026/9/17 13:41:05 网站建设 项目流程

Klavis 项目中的 Brave Search MCP 服务器:TypeScript 实现的工具定义、双传输模式与智能回退机制解析

【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis

本文围绕 Klavis 仓库中 mcp_servers/brave_search_atlas/README.md 展开,完整介绍该 MCP 服务器提供的brave_web_searchbrave_local_search两个工具的参数语义、Claude Desktop 接入配置与 API Key 获取流程,并结合 index.ts 源码深入剖析其 stdio / Streamable HTTP 双传输模式、按请求注入凭据的 AsyncLocalStorage 机制,以及本地搜索“无结果自动回退网页搜索”的完整调用链,帮助读者理解并部署一个可复用的搜索类 MCP 服务器。

1. 服务器定位与核心能力

brave_search_atlas是一个用 TypeScript 实现的 MCP(Model Context Protocol)服务器,将 Brave Search API 封装为 AI 客户端可直接调用的工具。根据 README 的归纳,它提供四项核心能力:

  • Web Search(网页搜索):面向通用查询、新闻、文章类需求,支持分页与新鲜度控制;
  • Local Search(本地搜索):检索商铺、餐厅、服务类本地信息,返回地址、电话、评分等详情;
  • Flexible Filtering(灵活过滤):可控制结果类型、安全级别与内容时效;
  • Smart Fallbacks(智能回退):本地搜索在没有结果时自动降级为网页搜索,保证调用方总能拿到可用内容。

该实现属于 Klavis 对上游 MCP 参考服务器的二次集成版本:从 package.json 可见,包名仍为@modelcontextprotocol/server-brave-search(版本 0.6.2),但仓库内实现为单文件index.ts(约 480 行),并额外加入了 Klavis 平台所需的按请求鉴权与 HTTP 传输支持。仓库中另有一个 Python 版本的 mcp_servers/brave_search 目录(提供 web/news/video/image 四类搜索),二者是同一 API 的不同技术栈实现,本文聚焦 TypeScript 版。

2. 工具定义与参数详解

服务器通过 MCP 的ListToolsRequestSchema处理器注册了两个工具,完整定义见 index.ts。

2.1 brave_web_search

执行带分页与过滤的网页搜索。源码中的工具描述明确其适用场景:通用查询、新闻、文章、广域信息收集,单请求最多 20 条结果。

参数类型必填默认值说明
querystring搜索词,源码注明上限 400 字符 / 50 词
countnumber10每页结果数,取值 1–20
offsetnumber0分页偏移量,最大 9

需要指出一个源码层面的细节:offset虽然在 inputSchema 中声明并在 README 中列出,但从 CallTool 处理分支 看,当前版本的参数解构只取出了querycountoffset未被传入performWebSearch),即该参数在此构建中已声明但未在调用链中生效。集成方在做分页规划时应以count为主,并留意这一实现现状。

2.2 brave_local_search

检索本地商户与地点,适用于隐含“near me”或提及具体地点的查询。源码中的工具描述承诺返回商户名称地址、评分与评论数、电话与营业时间。

参数类型必填默认值说明
querystring本地搜索词,如pizza near Central Park
countnumber5结果数量,取值 1–20

两个工具都有对应的参数类型守卫(isBraveWebSearchArgs/isBraveLocalSearchArgs),在 参数校验处 确认query为字符串后才放行,否则返回isError: true的错误文本,避免把非法参数直接透传给 Brave API。

3. 配置与接入

3.1 获取 API Key

按 README 的流程,接入方需要:

  1. 注册 Brave Search API 账号(Brave 官网提供每月 2000 次查询额度的免费层);
  2. 在 Brave 开发者仪表盘中生成 API Key。

3.2 Claude Desktop 配置

README 给出的标准接入方式是将以下内容加入claude_desktop_config.json

{ "mcpServers": { "brave-search": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-brave-search" ], "env": { "BRAVE_API_KEY": "YOUR_API_KEY_HERE" } } } }

该配置通过npx以 stdio 模式拉起服务器,并用BRAVE_API_KEY环境变量注入密钥。

3.3 源码级的凭据解析优先级

Klavis 集成版在密钥管理上比标准版更丰富。extractApiKey 函数 实现了三级回退:

  1. AUTH_DATA环境变量:内容为一段 JSON,解析后依次取api_keyBRAVE_API_KEY字段;解析失败时把原始字符串直接作为 key 返回;
  2. BRAVE_API_KEY环境变量:本地 stdio 部署时的默认路径,与上面 Claude Desktop 配置对应;
  3. x-auth-dataHTTP 请求头:值为 base64 编码的 JSON,解码逻辑与AUTH_DATA相同——这正是 Klavis 平台侧向容器化部署的服务器按会话下发用户凭据的通道。

一个值得注意的设计:AUTH_DATA是进程级全局变量,而x-auth-data是请求级头,二者混用时若每个 HTTP 请求都用同一个进程状态,会出现凭据串扰。源码通过 AsyncLocalStorage 解决这个问题——每个 HTTP 请求在 POST /mcp 处理中 先调用extractApiKey(req)解析该请求携带的 key,再在asyncLocalStorage.run({ apiKey }, ...)的上下文中处理 MCP 消息;工具执行时的getApiKey()优先从当前异步上下文取 key,取不到才回落到环境变量路径。这样同一进程内可以并发服务多个携带不同 Brave Key 的租户,互不干扰。日志中对 key 做了前4位***后4位的打码处理(mask 函数),避免凭据明文出现在启动日志中。

4. 双传输模式:stdio 与 Streamable HTTP

服务器在 入口判断处 通过环境变量TRANSPORT决定运行形态:

  • TRANSPORT=stdio:使用StdioServerTransport,通过标准输入输出与宿主客户端(如 Claude Desktop)通信,适合本地开发;
  • 默认(HTTP):基于 Express 5 启动一个 Streamable HTTP 服务,监听PORT(默认5000),MCP 消息端点为POST /mcp。对GET /mcpDELETE /mcp返回 405 及 JSON-RPC 风格的Method not allowed错误体。

HTTP 模式下的每个POST /mcp请求都会新建一个BraveSearchServer实例并连接一个StreamableHTTPServerTransportsessionIdGenerator: undefined,即无会话状态),请求结束后通过res.on('close')关闭 transport 与 server。从源码结构看,这是“每请求一服务器”的轻量模型:进程常驻,但每个请求拥有独立的 MCP Server 对象与凭据上下文,天然规避了会话粘连问题,也便于在容器环境中以无状态方式水平扩展。

MCP 服务器在初始化握手时上报的名字是example-servers/brave-search,版本0.1.0(构造函数),而 npm 包版本为 0.6.2——二者分属 MCP 层标识与发布版本,排查协议问题时注意区分。

5. 网页搜索实现:API 调用与输出格式化

brave_web_search的执行入口是 performWebSearch,调用链非常直接:

  1. 请求https://api.search.brave.com/res/v1/web/search,查询参数为q(搜索词)、count(经Math.min(count, 20)截断)、offset
  2. 请求头携带Accept: application/jsonAccept-Encoding: gzip与鉴权头X-Subscription-Token: <apiKey>
  3. 非 2xx 响应直接抛出Brave API error: <status> <statusText>并附上响应体文本,最终由 MCP 层捕获后以isError: true的形式返回给客户端;
  4. 成功时只保留web.results中的title/description/url三个字段,格式化为如下纯文本块后拼接返回:
Title: ... Description: ... URL: ...

这种“压缩为三字段 + 纯文本”的输出策略是面向 LLM 的:丢弃 rank、language、published 等元数据可以显著降低 token 消耗,而结构化分行格式让模型容易逐条解析。

6. 本地搜索与智能回退:三步调用链

brave_local_search是 README 中“Smart Fallbacks”特性的载体,其实现 performLocalSearch 分为三个阶段:

第一步:定位地点 ID。先调用网页搜索接口,但附加search_lang=enresult_filter=locations参数,从响应的locations.results中提取地点id列表。这里复用 Web Search 端点做“地点发现”,而不是直接调本地搜索 API,意味着一次请求即可拿到候选 POI 的标识。

智能回退点:如果locationIds为空(比如查询与实体地点无关),代码直接return performWebSearch(query, count),把查询降级为普通网页搜索——这就是 README 承诺的“无本地结果时自动回退”。对上层工具调用方而言,行为是透明的:总是返回结果,只是内容从 POI 详情变为网页列表。

第二步:并行拉取详情。对地点 ID 列表用Promise.all并发请求两个端点(getPoisData / getDescriptionsData):

  • /res/v1/local/pois:按ids重复参数批量取 POI 主数据(名称、地址、坐标、电话、评分、营业时间、价格区间);
  • /res/v1/local/descriptions:按同样 ID 批量取文字描述。

两个请求相互独立,并行化使最坏延迟等于较慢者的耗时而非两者之和。

第三步:格式化输出。formatLocalResults 将每个 POI 渲染为固定字段文本,缺省值统一为N/A,条目之间以---分隔:

Name: ... Address: 街道, 城市, 州, 邮编 Phone: ... Rating: 4.5 (128 reviews) Price Range: ... Hours: ... Description: ...

地址由streetAddressaddressLocalityaddressRegionpostalCode四个字段过滤空值后拼接,任一缺失不会破坏整体格式;若无 POI 则返回No local results found

错误路径上,任何一步的 HTTP 非 2xx 都会抛错,被 CallTool 统一 catch 捕获后以Error: <message>文本返回,isError置真,保证协议层的错误语义一致。

7. 构建与容器化部署

7.1 工程配置

package.json 声明了运行时依赖@modelcontextprotocol/sdk(^1.12.1)与express(^5.1.0),可执行入口为mcp-server-brave-searchbuild/index.js;tsconfig.json 采用ES2022+Node16模块解析并开启strict模式,构建产物输出到build/目录。overrides中对body-parser做了>=2.2.1的版本锁定,属于依赖安全加固。

7.2 Dockerfile 多阶段构建

Dockerfile 采用两阶段构建:

  • builder 阶段:基于node:22-alpine,先只拷贝package.json执行npm install --ignore-scripts利用层缓存,再拷贝源码执行npm run build
  • release 阶段:基于更小的node:22-slim,仅从 builder 复制build/产物与package.json,以npm ci --omit=dev --ignore-scripts安装生产依赖;
  • 最终镜像EXPOSE 5000ENTRYPOINTnode build/index.js

由于TRANSPORT缺省即 HTTP,容器默认以 Streamable HTTP 模式监听 5000 端口;若要改跑 stdio 模式,需在启动时注入TRANSPORT=stdio。容器化部署配合AUTH_DATA环境变量或x-auth-data请求头即可接入 Klavis 平台的凭据下发链路,与第 3.3 节的 AsyncLocalStorage 机制配套工作。

8. 小结与适用前提

brave_search_atlas是一个体量很小但结构完整的参考实现:约 480 行单文件覆盖了工具注册、参数校验、双传输、按请求鉴权与完整的 Brave API 集成。结合源码可以归纳其适用前提与限制:

  • 需要有效的 Brave Search API Key(免费层 2000 次/月),网页搜索与本地搜索共用同一 key;
  • stdio 模式适合本地客户端直连(BRAVE_API_KEY环境变量),HTTP 模式适合容器化 / 多租户部署(AUTH_DATAx-auth-data);
  • count上限 20 由Math.min(count, 20)在客户端侧强制截断;offset参数当前构建中已声明但未在调用链中生效,做深分页时需另行处理;
  • 本地搜索回退为网页搜索是静默发生的,调用方从输出内容(POI 文本块 vs Title/Description/URL 文本块)可以区分实际命中的搜索类型。

该服务器以 MIT License 许可(见 package.json 与 README 说明),README 声明可自由使用、修改与分发。对于需要在 Klavis 平台或自建环境中让 AI 代理具备“网页 + 本地”双重检索能力的团队,这套实现既是可直接运行的服务,也是研究 MCP 服务器鉴权与传输模式取舍的紧凑样本。

【免费下载链接】klavisKlavis AI: MCP integration platforms that let AI agents use tools reliably at any scale项目地址: https://gitcode.com/GitHub_Trending/kl/klavis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询