mcpField
S
sonde

sonde

本地服务
github.com/anishmoncivarghese开发工具43 周前更新

关于 sonde

sonde 是面向编码 Agent 的本地代码上下文引擎,将 TypeScript、Python 或 Swift 仓库索引为 SQLite 符号图。它通过 MCP 工具提供调用关系、依赖图和变更影响分析,并按令牌预算限制响应。

主要功能

  1. 01索引 TypeScript、Python 和 Swift
  2. 02构建 SQLite 符号图
  3. 03查找符号及图关系
  4. 04分析变更影响范围
  5. 05生成架构文档

适用场景

  1. 01查找符号的调用方
  2. 02评估代码变更影响
  3. 03定位相关测试
  4. 04生成并检查架构文档

MCP 相关

sonde 提供 find_symbols、query_graph 和 get_impact_radius 三个 MCP 工具,供 Agent 查询仓库符号、关系和影响范围。sonde init 可为项目索引代码并注册 MCP 服务。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"anishmoncivarghese-sonde": {
"command": "npx",
"args": [
"-y",
"@cheppulabs/sonde"
]
}
}
}
启动命令npx -y @cheppulabs/sonde

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@cheppulabs/sonde0.4.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Sonde

ci npm license

面向 AI 编码 Agent 的本地代码上下文引擎。Sonde 会将 TypeScript、 Python 或 Swift 仓库索引为 SQLite 中的符号级图,并提供三个 MCP 工具—— find_symbols、query_graph 和 get_impact_radius——让 Agent 通过一次调用而不是反复搜索,就能回答谁调用了这个符号、修改后会破坏什么以及哪些 测试与它相关。

基准测试实际展示了什么

我们并不声称“能找到 grep 找不到的内容”。能力出色的 Agent 搜索 循环也能找到相同的结构证据——我们在一个真实的 19,409 行仓库上进行了测试,每项任务的召回率 都达到 1.000。

我们的主张是:在预算范围内,以极低成本获得相同答案:

在真实的生产 TypeScript 项目中SondeAgent 搜索
结构任务的召回率1.001.00
工具调用次数1.08.0
上下文 token 数1,2623,621
延迟263 ms38,602 ms
超出 token 预算的运行次数0 of 63 of 6

Sonde 在每项结构任务上的答案都与基线相同,同时使用的上下文约少 3 倍、 调用次数少 8 倍,耗时少约 147 倍;并且它绝不会超出调用方的 token 预算,因为打包器的设计 就是按预算截断。这正是我们提供的取舍。

Sonde 的不足。 对于没有共同词汇的行为查询——“重试退避在哪里决定?”——得分为 0.00。我们构建并测试了本地语义检索,但它并不能解决这个问题(见设计文档 §2.2);因此我们不声称 具备这项能力。如果你的问题大多属于这种类型,那么目前 Agent 搜索循环是更好的工具。

数据可复现:npm run bench:fixture && npm run bench:large。 完整结果见 BENCHMARK-LARGE.md 和 BENCHMARK.md。

安装和运行

npm install -g @cheppulabs/sonde
cd your-project
sonde init

sonde init 会为仓库建立索引,并在此项目的 .mcp.json 中将 sonde 注册为 MCP 服务; 在写入任何内容前会先询问(使用 sonde init --yes 可跳过提示)。如果 .mcp.json 无法安全合并, 它绝不会修改该文件——如果现有的 sonde 条目与 init 将写入的内容不同,就会保留原样并报告, 不会覆盖。

对于 Python 仓库,请使用 sonde init --resolve;默认的 tree-sitter 级别未通过该项目针对结构查询的准入门槛。

如果你想手动执行并查看每个步骤,也可以按以下方式操作:

sonde index .
# then add to .mcp.json:
# { "mcpServers": { "sonde": { "command": "sonde", "args": ["mcp", "serve", "."] } } }

无需账户或托管服务。

架构文档

sonde doc 会生成 ARCHITECTURE.md,描述仓库的模块、模块之间的依赖关系以及各模块公开的内容——文档由依赖图生成,因此反映的是代码的实际行为,而不是某人的记忆。

sonde doc            # write ARCHITECTURE.md
sonde doc --stdout   # print it instead
sonde doc --check    # fail if it is out of date (for CI)
sonde doc --module src/store   # symbol-level detail, never committed

该文档旨在提交并重新生成,而非手动编辑。如果内容没有变化,重新生成后的字节内容完全相同,因此不会造成差异文件膨胀;如果两个分支都重新生成了该文档,请再次运行 sonde doc 解决冲突,而不要手动合并。它会拒绝覆盖并非由它生成的 ARCHITECTURE.md。

它有意不做以下三件事:

  • 不会绘制无法举证的依赖关系。 仅共享符号名称的模块对会被排除,并单独计数。在此仓库中,两个适配器共享文件名 symbols.ts、parser.ts 和 references.ts,这导致模块之间凭空出现了 62 条启发式“引用”,而这些模块实际上从未相互导入——这曾是图中第二粗的箭头。
  • 不会假装图表完整无缺。 图表展示依赖关系中最重要的部分,并注明省略了多少条;下方的表格展示更多内容,而 --module 则能显示其余内容。包含所有依赖关系的图表难以阅读,因此也就什么都无法展示。
  • 不会在内容过时的时候声称其仍是最新的。 页眉会列出文档描述的提交,并在文件发生更改时发出警告。

保证内容

  • 绝不返回过时的源代码字节。 每当响应包含源代码时,Sonde 都会在返回前重新读取并重新计算已索引字节范围的哈希值(规范 §8.1,保证 A)。
  • 始终报告结构性偏差,而不会声称实现了无法验证的完整性(规范 §8.1,保证 B)。sonde status 会显示相同的偏差情况,以及工具响应封装中包含的层级分布。
  • 每条边都会标注其发现方式对应的层级——COMPILER(由内置类型检查器通过 --resolve 精确解析:TypeScript 使用 TypeScript 编译器,Python 使用 pyright)、LEXICAL(通过导入绑定或词法作用域解析)、HEURISTIC(成员访问或其他需要类型推断的关系)、EXTERNAL(目标位于已索引仓库之外)或 UNRESOLVED(确实无法定位,并附有原因)。
  • 绝不伪造边。 无法解析的引用会归为 EXTERNAL 或 UNRESOLVED——绝不会猜测目标,也绝不会静默丢弃引用。

准确性

Sonde 会在固定测试样本上,将其零配置 tree-sitter 路径与 TypeScript 编译器进行对比,并公布结果,包括不尽如人意的数据(规范 §12)。COMPILER 边直接使用该编译器,因此再用同一权威来源对其进行对比,并非独立的准确性测试。

Sonde 边准确性与 TypeScript 编译器的对比

生成时间:2026-08-23T18:16:41.557Z TypeScript:5.9.3(内置;不会加载仓库中的 TypeScript)

这些数据涵盖的范围。 作为判定基准的预言机衡量的是 tree-sitter 解析路径——这是默认的零配置路径,也是唯一需要评估准确性的层级。COMPILER 层级的边由 TypeScript 编译器本身生成,因此用同一编译器评分毫无意义;这些边在构造时便已精确,因此不纳入这些数据。运行 sonde index --resolve 可生成这些数据。

预言机仅针对仓库内目标进行筛选;node_modules 和 .d.ts 声明均不纳入。仅限类型的引用、JSX 内置元素、export =、装饰器和声明合并,都是已知的预期差异(规范 §10)。各层级行仅将该层级与完整预言机进行比较,以展示各层级的独立贡献;ALL 表示合并后的结果。

为什么这里的精确率低于 1.000 是预期结果

这些差异是结构性的,因此将精确率读作“Son​​de 出错的频率”会夸大错误率:

  1. 对有歧义的成员调用,会输出所有候选项。 对于有两个可见 foo 声明的 x.foo(),Sonde 会将二者都作为带置信度权重的 HEURISTIC 边输出。最多只有一个与编译器结果匹配,因此另一个必然计为假阳性。另一种做法是猜测单一目标,但不变量 1 禁止这样做——一条看似已解析但实际错误的边,比两条如实标记为启发式的边更糟。因此,只要夹具中包含有歧义的调用,精确率就会被限制在 1.000 以下。
  2. 构造函数调用仅由我们处理。 Sonde 会为 new Foo() 输出 CALLS,而 oracle 不对此建模,因此相对于省略该项的真实值,每一项都计为假阳性。
  3. 成员级 IMPLEMENTS 仅由我们处理。 一旦类声明实现了接口,Sonde 就会从 RegExpRouter.add 推导出指向 Router.add 的 IMPLEMENTS 边。tsc 只会在类型层级报告继承子句,因此相对于不对此建模的真实值,每一条成员级边都计为假阳性。正是这项能力使得针对接口方法的影响分析能够生效,因此这里会披露精确率上的代价,而不是移除该功能。

计数为绝对值,并非大型语料库中的百分比。下方列出了夹具的边总数,以便看出单条边对各项数据的影响。

tests/fixtures/repos/small

夹具配置 SHA-256:e02e2d5003f96d1ad22519f04e10d687fe689cf9298e7fcbc588eab525dce1ad

Oracle 边数:9 · Sonde 边数:7 · oracle 中的一条边会使召回率变动 11.1%

边类型层级精确率召回率TPFPFN
CALLSALL0.5001.000220
CALLSLEXICAL0.5000.500111
CALLSHEURISTIC0.5000.500111
IMPLEMENTSALL0.5001.000110
IMPLEMENTSLEXICAL0.5001.000110
IMPLEMENTSHEURISTIC1.0000.000001
INHERITSALL1.0001.000100
INHERITSLEXICAL1.0001.000100
INHERITSHEURISTIC1.0000.000001
REFERENCESALL0.5710.800431
REFERENCESLEXICAL0.8000.800411
REFERENCESHEURISTIC0.0000.000025

**总体:**精确率 0.571,召回率 0.889

使用 npm run bench:oracle 重新生成。

CLI

sonde init [path] [--resolve] [--yes]      # index and register project MCP config
sonde index [path] [--resolve]             # full index; optional compiler pass
sonde update [path] [--resolve]            # update; optional compiler pass
sonde status [path]                        # freshness and tier distribution
sonde search <query> [path]                # find_symbols
sonde query <pattern> <symbol> [path]      # query_graph
sonde impact [path] --symbol <name>        # get_impact_radius by symbol
sonde impact [path] --from-git-diff        # impact from working-tree diff
sonde doctor [path]                        # parser/database/tsc health
sonde clean [path]                         # remove the cached index
sonde mcp serve [path]                     # MCP server over stdio

impact 还接受可重复使用的 --symbol 选项以及 --token-budget <n>。init、index、update、status、search、query、impact、doctor 和 clean 命令均接受 --json。

已知限制

  • 需要 Node 22+。 better-sqlite3 需要此版本;在较旧的 Node 上安装会打印 EBADENGINE 警告,但仍会完成。如果之后 sonde 无法运行,原因就在这里——请升级 Node,而不是忽略警告。
  • Python 需要 --resolve,且其边未经 oracle 验证。 不加此参数时,Python 仅在 tree-sitter 层级建立索引;在一个真实的 56 个文件的项目中,测得 62.81% 未解析,在 pydantic 中为 57.39%,远超本项目要求的 30% 上限,因此不适用于结构查询。加上 --resolve 后,内置的 pyright 会驱动 COMPILER 层级,同一批代码的未解析率分别为 27.00% 和 17.42%。该门槛测量的是定位情况——引用是否找到了目标——而非目标是否正确;TypeScript 的边会在 ORACLE.md 中与 tsc 的结果进行评分,Python 则没有同等的 oracle。在表现较差的代码集上,余量很小:校正已知的向上偏差后只有 0.28 个百分点。参见 probes/python-placement/FINDINGS.md。
  • 仅支持 TypeScript、Python 和 Swift;没有其他语言适配器。
  • Swift 解析采用启发式方法,并非由编译器支持,且有一条缩窄规则未经验证。 引用会根据文件可见性和显式的局部类型注解进行缩窄,而非基于完整的类型推断。在一个真实的 376 个文件的 Swift 应用中,定位率达到 74.84%/未解析率为 25.16%——完整测量结果见 probes/swift-narrowing/FINDINGS.md。第三条缩窄规则(SwiftPM 目标边界)从未经过测试:验证所用的代码集是 Xcode 项目,不具备 Package.swift 布局,因而无法提供该信号。精心整理的 Swift SDK 符号表也刻意保持保守——一些有歧义的名称被舍弃,而非猜测,因此某些有效的 SDK 引用仍可能显示为 UNRESOLVED,而不是 EXTERNAL。
  • TypeScript 的编译器解析(--resolve)默认关闭,因为它明显较慢,且会使用更多临时内存。在包含 19,409 行代码的 Hono 测试样例中,默认索引耗时 3.58 秒;--resolve 耗时 13.70 秒,新增了 10,329 个精确定位/提升结果,并将 callers_of Hono.route 从零个图结果变为八个编译器调用方。索引完成后会丢弃 Program;内联刷新不会调用编译器,并会明确降低受影响证据的等级,直到完整运行 sonde update --resolve。
  • 编译器解析使用内置的 TypeScript 5.9.3,而非仓库自身的编译器,因此可能存在版本偏差;doctor 和响应封套中会披露这一点。
  • 存在解析错误的文件仍会贡献 tree-sitter 从中恢复的内容——这是有意为之(参见设计规范 §8)。若错误发生后仍恢复出真实声明,其 parse_state 为 partial;只有完全未能恢复出可用内容时,才为 failed。
  • TESTS 边仅表示结构相关性;绝不代表覆盖情况。
  • 仅限类型的引用、JSX 内建项、export =/import =、装饰器和声明合并都是 tree-sitter 提取路径中已知的缺口。
  • 不推断重命名。 重命名文件会改变所有根据其路径生成的稳定键;任何持有旧键的内容(已保存的查询、Agent 之前的轮次)都将无法继续解析,且不会跟随重命名。
  • 不支持语义/行为搜索。我们曾构建并测量此功能——测试了两种嵌入模型和四种文档配置——但在它旨在解决的任务类别上,它们都不如词法/结构检索。具体数据见设计规范 §2.2。该功能未接入 find_symbols。

完整设计见 docs/superpowers/specs/2026-08-16-sonde-design.md。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。