用 dsh-web-search-exa 给 DeepSeek Harness 接上零配置的 Exa 搜索

前言

DeepSeek Harness(dsh)把联网搜索做成可替换的能力,而不是写死在智能体循环里。模型侧始终调用同一套 web_search / web_fetch,真正去网上查资料的是 ctx.web 上注册的搜索提供方。官方仓库里已经有 @deepseek-ai/dsh-web-search-exa:它走 Exa 的 POST /search REST 接口,但没有 API 密钥时提供方直接不可用

很多本地试用、临时排查、不想先去申请密钥的场景,会卡在这一步。社区维护者 TonyDua 做了 @tonydua/dsh-web-search-exa(仓库名 dsh-web-search-exa):无密钥时走 Exa 托管的匿名 MCP,配了 EXA_API_KEY 再自动切回 REST。本文按插件目录页、GitHub README / package.json、DeepSeek Harness 官方文档和 Exa MCP 说明交叉核对后整理。

DeepSeek Harness 的核心理念是「一切皆插件」。文中用到的 DSH 插件库 是独立社区站点,与 DeepSeek / 幻方没有官方从属关系,不要把它当成官方应用商店。

这是什么

dsh-web-search-exa 是一款 DeepSeek Harness 工具与能力插件,由 TonyDua 维护,许可证 MIT,主要语言 JavaScript,要求 Node.js 18 及以上。GitHub 仓库为 TonyDua/dsh-web-search-exa,npm 包名 @tonydua/dsh-web-search-exa。目录页与 GitHub 在本文核对时均显示 6 颗星;仓库创建于 2026-08-14,目录收录日期同日。

它解决的问题很具体:给 ctx.web 注册一个 Exa 搜索提供方,让已有的模型工具、提示词区和结果卡片不用改,就能用上网页搜索。它不是官方包的替代品,而是官方包的零配置变体——官方实现只走带密钥的 REST;本包补上匿名 MCP 兜底,带密钥时的 REST 行为与官方路径一致。

仓库 package.json 当前版本为 0.1.3。npm 页面在本文检索时列出的最新发布仍是 0.1.2。0.1.3 的变更是:bundle 补丁不再重复定义官方已经占用的 web 行,避免 dsh plugin add 后出现 duplicate loader entry id: web 启动失败。从 GitHub 安装会拿到含该修复的源码。

核心功能

默认免密钥,走匿名 MCP

未配置 apiKey 或环境变量 EXA_API_KEY 时,搜索走 Exa 托管 MCP:https://mcp.exa.ai/mcp,JSON-RPC 2.0 调用 web_search_exa,请求里不带凭据。来源标识放在 x-exa-source: dsh-anything 头里。

Exa 自己的 MCP 页面写明:连接 https://mcp.exa.ai/mcp 不需要 API 密钥。匿名调用有限流;HTTP 429 会以 WEB_PROVIDER_ERROR 返回,并提示去配置密钥。

配了密钥自动切 REST

设置了 EXA_API_KEY(或配置里的字面量 apiKey)之后,提供方改走 https://api.exa.ai/searchPOST /searchAuthorization: Bearer)。仓库说明这条路径额度更高,对模型侧的工具行为没有额外改动。REST 检索模式 searchType 默认为 auto,也可设为 keywordneural

即插即用,不改模型工具

它只向 ctx.web 注册 WebSearchProvider,不拥有 ctx.web 这个键,也不自己注册面向模型的工具。工具名、参数、提示词和结果卡片仍由 @deepseek-ai/dsh-tool-web 负责。返回结果会规范成 seam 的 WebSearchSourceurltitlesnippetpublishedAtmaxResults 由 seam 在返回路径上截断。

DeepSeek Harness 文档对选择规则写得很清楚:没有配置提供方 id、且当时只有一个可用搜索提供方时,seam 会自动选中它。无密钥时官方 DeepSeek 搜索提供方不可用,因此本插件可以在零配置下被自动选中。

可与官方 Exa 包共存

默认 provider id 是 exa,Cordis 插件名是 web-search-exa,和官方 @deepseek-ai/dsh-web-search-exa 相同。seam 遇到重复 id 会抛 WEB_DUPLICATE_PROVIDER两个包直接装进同一个 profile 会在启动时报错,没有静默覆盖。本包可用 providerId 改成例如 exa-anon,再在 web 配置里显式选择。

主要配置项

配置键 默认值 含义
providerId exa 注册到 ctx.web 的提供方 id;与官方包共存时才需要改
apiKey 未设置 Exa 密钥字面值;为空则走匿名 MCP
apiKeyEnv EXA_API_KEY 未写字面 apiKey 时读取的环境变量名
apiURL https://api.exa.ai/search 带密钥时的 REST 端点
mcpURL https://mcp.exa.ai/mcp 匿名 MCP 端点
searchType auto REST 检索模式:auto / keyword / neural
numResults 未设置 请求未带 maxResults 时的默认条数
highlightsPerResult 1 REST 路径每个结果请求的高亮句子数

apiKey 标记了 role('secret'),不会出现在 describe() 响应里。

安装与启用

插件目录页给出的安装命令如下,在 DeepSeek Harness 终端中运行:

dsh plugin add github:TonyDua/dsh-web-search-exa

如需可复现安装,按目录页说明固定 commit 哈希:

dsh plugin add github:TonyDua/dsh-web-search-exa#commit

#commit 换成实际提交哈希。仓库 README 还提供了按 web profile、从 npm 安装的写法(v0.1.3 起带 dsh.bundle manifest,bundle 补丁会插入提供方行):

dsh plugin --profile web add @tonydua/dsh-web-search-exa

装完后重启 dsh web。目录页写明:插件以当前 dsh 进程的权限运行,安装时可能执行代码;安装前应检查源代码仓库和许可证。

典型用法

无密钥、只装这一个搜索提供方时,重启后一般不用再改配置:官方 DeepSeek 搜索不可用,seam 会自动选中本插件。模型继续用原来的 web_search 即可。搜索结果仍由 dsh-tool-web 渲染成来源、摘要、日期卡片,和 DeepSeek 搜索的展示方式相同。

已经配置了密钥、希望明确走 Exa 时,在 $DSH_HOME/profiles/web/cordis.patch.yml 里选中提供方(该文件在 bundle 补丁之后应用):

- id: web
  name: '@deepseek-ai/dsh-web'
  config:
    searchProvider: exa

也可以不改文件,用环境变量在运行时指定:

export DSH_WEB_SEARCH_PROVIDER=exa

本地开发目录可以按 README 直接指向检出路径:

dsh plugin --profile web add ../plugins/dsh-web-search-exa

若要和官方 @deepseek-ai/dsh-web-search-exa 装在同一个 profile,必须改 id。官方包的 id 固定为 exa,给本包一个不同值,例如 exa-anon

- insert:
    - id: web-search-exa
      name: '@tonydua/dsh-web-search-exa'
      config:
        providerId: exa-anon
- id: web
  name: '@deepseek-ai/dsh-web'
  config:
    searchProvider: exa-anon

对应的环境变量是 $DSH_WEB_SEARCH_PROVIDER=exa-anon。更省事的做法是:每个 profile 只装其中一个包,沿用默认 id。

当前版本没有 Web 设置页里的可编辑卡片。Settings → Plugins 清单里会出现 web-search-exa@tonydua/dsh-web-search-exa),服务端也注册了 web-search-exa 配置段,但没有客户端卡片绑定它。内置的 “Web search” 卡片改的是官方 web-search-deepseek 命名空间,和本插件无关。改配置请编辑 cordis.patch.yml 或环境变量,然后重启 dsh web。README 写明下一版本计划补 UI 卡片,本文不把它当作已经交付的功能。

适用场景与注意事项

适合这些情况:

  • 本地试用 DeepSeek Harness 的网页搜索,暂时不想申请 Exa 密钥
  • 已经在用 web_search,只想换搜索后端,不想动工具和提示词
  • 需要和官方 Exa 包对比,或在同一套 profile 里用 providerId 显式切换

使用前注意:

  1. 匿名 MCP 有限流。 频繁搜索遇到 429 时,按仓库说明配置 EXA_API_KEYapiKey,提供方会切到 REST。Exa 托管 MCP 是 Exa 的官方产品,免费匿名可用,但额度由对方控制。
  2. 本插件只提供搜索,不提供抓取。 web_fetch 仍走独立的 fetch 提供方(官方文档里是 dsh-web-fetch-http 这一路),不要指望它顺带读完整网页。
  3. 不要无改动地双装官方包和本包。 默认 id 冲突会直接导致启动失败。
  4. 当前没有设置 UI。searchTypemcpURLproviderId 等只能走补丁文件或环境变量。
  5. 运行时单例。 README 说明 @deepseek-ai/dsh-tools 必须在一个 profile 里解析成同一份物理实例。本插件不依赖它;若其它第三方插件把它装成嵌套普通依赖,agent 循环可能在搜索提供方被调用前就报 Cannot read properties of undefined (reading 'prepare')。应先修那个插件的依赖声明。
  6. 权限与许可证。 插件以当前 dsh 进程权限运行。安装前阅读仓库源码和 MIT 许可证。DeepSeek Harness 本身仍处于开发者预览,官方 README 写明会有破坏兼容性的变更。
  7. 选型。 已有 EXA_API_KEY、希望跟官方实现走:用 @deepseek-ai/dsh-web-search-exa。要零配置试用:用本包。

匿名 MCP 的接入方式,仓库 README 写明参考了 can1357/oh-my-pi 以及 @oh-my-pi/exa:有密钥走 REST、无密钥走 mcp.exa.ai/mcp

小结

dsh-web-search-exa 把 Exa 接到 DeepSeek Harness 的 ctx.web 上:没密钥时用官方托管的匿名 MCP,有密钥时自动升到 REST,模型侧的 web_search 不用改。它是社区维护的零配置变体,不是官方包,也不是 DeepSeek 官方商店里的「认证插件」。

目录页:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-web-search-exa/

GitHub:https://github.com/TonyDua/dsh-web-search-exa

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜