← 返回列表
✓ 可直接安装
Node.js 22.13+
自动检查通过:npm 包已发布且 engines 声明满足基线(声明 Node >=22.13.0);该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/25 · 已提供中文文档
面向正确性的 MCP 服务器和批量 CLI,用于紧凑的结构化读取和经过审查的 TypeScript/JavaScript 编辑。
综合分
33
GitHub 分
33
用户评分
—
★ Stars
4
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/yailPeralta/ast-mcp-server.git信任档位:已验证本站已于 4 天前真实安装成功(L4 · 真实安装)
- 是什么
- 生态插件(可安装,未声明 dsh 能力)
- 装得上吗
- 本站已真实安装成功(L4 · 真实安装,非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 1 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/22
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/25(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包ast-mcp-server @ 0.13.1
✓Node 引擎要求 >=22.13.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/20 02:15:58
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成ast-mcp-server
CI
npm version
Node.js 22.13+
License: ISC
ast-mcp-server 为编码代理提供对 TypeScript 和 JavaScript 项目的紧凑、类型感知访问。它通过 ts-morph 使用真实的编译器项目模型,因此声明、引用、重命名位置和诊断信息都来自 AST,而不是文本搜索的猜测。
读取是有界且结构化的。写入遵循显式的 prepare → review → apply 协议,并带有不可变哈希、工作区新鲜度检查、诊断防护和幂等回执。
问题
编码代理常常退回到两种通用操作:将文件作为纯文本读取,以及写入文本补丁。这可以工作,但会带来三种可预见的成本:
1. 上下文过多。 代理可能加载数百行,而它只需要一个签名或方法体。这会消耗模型上下文和 token,却不会改进答案。
2. 脆弱的编辑。 文本补丁本身并不理解声明、作用域、重载或 TypeScript 诊断。一个看起来合理的编辑可能针对错误的构造,或引入新的编译器错误。
3. 跨文件推理能力薄弱。 文本搜索可以找到匹配的单词,但无法可靠地区分两个名称相同但互不相关的符号。项目范围的引用和重命名需要编译器对程序的理解。
这个工具改为做什么
这个 MCP 服务器为代理提供结构化代码工具,以及通用文件读写。在底层,ts-morph 使用 TypeScript 编译器项目模型,因此服务器可以将声明和引用作为代码来推理,而不是将其视为无差别的文本。
| 需求 | 结构化操作 | 返回范围 |
| ------------------------------ | -------------------------- | ----------------------------------------------------------- |
| 读取有界文件 | ast_get_file | 精确选定的源代码行、哈希和有界新鲜度 |
| 探索有界上下文 | ast_explore | 排序后的选择器,以及可选的源代码和引用 |
| 理解一个文件 | ast_get_outline | 不包含实现体的签名 |
| 检查一个声明 | ast_get_symbol_source | 一个函数、方法、类或类型的精确源代码 |
| 在整个项目中查找用法 | ast_find_references | 编译器解析的引用位置 |
| 理解符号影响 | ast_get_impact | 有界的直接/传递编译器支持关系 |
| 选择受影响的测试 | ast_find_test_candidates | 来自传入编译器关系的完整候选证明 |
| 在所有位置重命名符号 | ast_rename_symbol | 经过审查的项目范围重命名计划 |
| 更改一个实现 | ast_replace_symbol_body | 仅更改主体并保留声明的计划 |
读取可以从有界文件切片、紧凑大纲或仅针对需要检查的声明的精确源代码开始。变更会先在内存中准备,与基线诊断进行比较,然后作为不可变的、绑定哈希的计划返回。在调用方审查并明确应用该计划之前,不会写入任何内容。
选择读取工具
- 当文件路径已知且代理需要精确的源代码行时,使用 ast_get_file。它是只读的,使用从零开始的 offset 和有界的 limit,返回从 1 开始的行记录、SHA-256 字节哈希、文件级 snapshot_state 以及有界的项目 freshness 元数据(fresh、pending、stale、rebuilding 或 degraded)。
- 当只需要从一个已知文件中获取选择器和无主体签名时,使用带 symbols_only: true 的 ast_get_file。
- 当问题跨越发现和证据时,使用 ast_explore。其默认摘要是有界的;使用 detail: "context" 获取选定的源代码,使用 detail: "full" 获取源代码加编译器引用。
- 使用 ast_get_outline 获取已知文件的紧凑无主体视图,而不包含源代码行。
- 当一个声明或实现是所需证据时,使用 ast_get_symbol_source。
- 当确切符号已知且需要有界的直接/传递编译器关系时,使用 ast_get_impact。检查 coverage、work、truncation、incomplete 和 proven_empty;这是只读证据,不是变更计划。
- 当确切符号应映射到保守测试时,使用 ast_find_test_candidates。它只接受完整的传入 reference、import、export、extends、implements 和 call 证据,返回完整路径,并且从不执行测试。
snapshot_state: "fresh" 表示返回的文件字节与同步的编译器快照匹配。单独的 freshness 对象描述项目/会话状态,并保留源代码更改或监视器故障等原因。这两个字段都不意味着项目具有零个 TypeScript 诊断;使用 ast_get_diagnostics 获取编译器错误和警告。
信任、新鲜度和完整性
服务器公开证据标签,而不是将每个结果都归结为未经限定的置信度分数:
| 标签 | 含义 | 安全使用 |
| ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| provenance: "compiler"、confidence: "exact"、resolution: "resolved"、freshness.state: "fresh" | 由活动 TypeScript 编译器快照解析出的关系。这是唯一会将 compiler_authoritative: true 置位的组合。 | 可支持有界的影响证据以及编译器支持的测试候选。 |
| provenance: "syntax" | 没有语义符号解析的语法或 AST 结构。 | 仅用于导航和结构上下文;不能证明两个符号相关。 |
| provenance: "heuristic" | 基于约定或名称的建议。 | 仅用于发现提示;绝不作为变更授权或编译器支持的测试候选。 |
| 索引证据 | 一种派生的查询加速器,而非编译器权威。当持久化缺失或为 enabled 时,生产默认使用原生 SQLite;每个索引选择器仍需要编译器验证和编译器回退。 | 仅用于更快的路由;过期、缺失或不匹配的条目必须失败关闭或回退到编译器。 |
新鲜度与 TypeScript 诊断正交。fresh 表示证据与已同步的快照匹配;pending、rebuilding、stale 或 degraded 表示该响应不得作为当前编译器证据呈现。读取工具会暴露状态、原因(source_change、config_change、index_failure、watcher_failure 或 compiler_rebuild)以及有界的 checked_at 时间戳。ast_get_impact 会拒绝非新鲜的编译器关系。ast_explore 会返回状态以及 completeness、unresolved、budget 和 truncation 元数据,而不是静默丢弃证据。
所有读取都有预算限制。调用方控制分页,并在适用时控制 max_bytes、reference_limit、max_depth、max_nodes 和 max_edges;响应会报告生效的限制。有界停止是不完整的证据,而不是空的否定结果。
影响有两个独立的完整性通道:
| 通道 | 证据 | 不完整条件 |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| 语义覆盖 | 每个请求的种类、方向和端点类别对应一个规范单元:not_applicable、completed、unsupported 或 unfinished | 任何适用的单元为 unsupported 或 unfinished |
| 遍历/工作量 | truncation 加上 work.work_limit_reached 及其计数器 | 深度/节点/边/工作量限制阻止完成 |
当任一通道不完整时,incomplete 为 true。仅当边数为零、每个适用单元都已完成且没有耗尽任何限制时,proven_empty 才为 true。公开的七种类别/默认影响请求包含 contains;由于不存在有作用域的 contains 生产者,适用的默认或显式包含关系为 unsupported,因此即使遍历未被截断,结果也是不完整的。
ast_find_test_candidates 有意排除 contains,并将准入范围固定为六种入向类别:reference、import、export、extends、implements 和 call。对于陈旧、不精确、未解析、被截断、工作量耗尽、不支持或未完成的证据,它会在分页之前返回 INCOMPLETE_EVIDENCE。只有完整的六种类别权威才能返回 candidates: [] 并带有 completeness.proven_empty: true;分页会切分确定性候选,而每个证明以及未分页的 coverage、work 和遍历元数据保持完整。
这些字段是增量式的:现有的边形状、kind 字符串、默认值和公开错误保持稳定。MCP ast_get_impact JSON 和 TOON 表示相同的逻辑覆盖/工作结果;候选 MCP 输出仍为规范 JSON,而只读批处理输出可以将同一候选结果编码为 TOON。属性、元素、动态、计算键和外部替代分派仍是无边的且未完成——此契约不认证延迟的 #219 或 #220 分类器。
为什么这有帮助
- 更少的上下文: 代理检索能回答该问题的最小结构单元,而不是默认加载整个文件。
- 更安全的更改: 精确的符号选择、诊断增量、工作区新鲜度检查以及 prepare → review → apply 减少了临时文本编辑的失败模式。
- 准确的项目级操作: 引用和重命名使用编译器解析,而不是用 grep 匹配标识符文本。
AST 感知编辑并不能证明更改在语义上是正确的。安全性来自将结构选择与诊断、精确预览、已审查哈希、新鲜度检查和故障关闭的应用语义相结合。
随附的批处理基准记录显示,在其搜索到源代码场景中,模型往返次数减少了 50%,序列化上下文减少了 94.67%。结果整形语料库记录显示,在保持声明的选择器/引用坐标且使用相同的六次逻辑调用的情况下,面向模型的 TOON 令牌总量减少了 68.80%。单独的格式基准在其符合条件的集合语料库中记录为 25.87%。上下文工作流基准验证了全文件、原语和 ast_explore 工作流的证据保留和调用边界。这些是可复现的本地 o200k_base 估计值,并非通用的令牌、计费、缓存或延迟声明。
要求
- Node.js 22.13.0 或更高版本
- 带有 Yarn 4.15.0 的 Corepack(由 packageManager 固定)
- 具有 tsconfig.json 的目标项目
支持的环境和信任边界
已发布的 v0.12.0 要求 Node.js >=22.13.0;其不可变证据矩阵针对确切的 Node.js 22.13.0 和当前 Node.js 24 系列。结构应用和托管设置文件发布仅在 Linux x64 上验证,要求 GNU coreutils 9.7 mv 支持 --update=none-fail、--exchange、--no-copy 和 --no-target-directory,GNU coreutils ln -L -T,位于 /proc/self/fd 的 procfs 描述符路径,O_DIRECTORY/O_NOFOLLOW,以及通过自有链接/交换身份探测的目标文件系统。失败或被拒绝的原语会在源效果之前阻止变更;没有重命名、复制/删除或仅路径名的回退。其他 Linux 架构或没有此完整矩阵的系统、macOS 和 Windows 仍未验证。
这是一个本地 stdio 服务器。它以调用用户的文件系统权限运行,客户端可以请求该用户能够访问的任何 project_root。它不提供 HTTP 认证、沙箱、租户隔离或远程服务安全边界。不支持远程、不受信任和多租户操作。
可选的受监督编译器工作进程
编译器默认在进程内运行。Linux 运维人员可以显式保持 stdio 父进程连接,同时允许空闲的编译器子进程退出并延迟重新生成:
AST_COMPILER_WORKER_MODE=supervised ast-mcp-server
父进程在重放有界初始化状态之前等待子进程就绪。请求和取消保持代际亲和性;变更历史、实时操作租约和完成关键的应用工作可防止不安全的回收。设置 AST_COMPILER_WORKER_MODE=in_process 以进行完整回滚,或设置 AST_COMPILER_WORKER_IDLE_TTL_MS=0 以保留中继而禁用空闲回收。
限定范围的 Linux 金丝雀测试在确切的 Node.js 22.13.0 和 Node.js 24 上通过,具有可重复的 PSS 回收、稳定的编译器指纹、不变的 SQLite 复用、有界的脱敏诊断,以及父进程死亡后无孤儿进程。这是每个连接一个子进程,而不是共享守护进程、池或新的默认值。参见 ADR 0014。
在已发布的 v0.12.0 中,缺失的 AST_SYMBOL_INDEX_PERSISTENCE 或显式的 enabled 会选择私有 SQLite 符号索引缓存。disabled 是立即的仅内存回滚。canary 需要显式的绝对规范化 AST_SYMBOL_INDEX_CACHE_ROOT。无效的策略或存储会故障关闭到编译器权威的内存读取,并带有有界的无路径状态。
默认缓存根按以下顺序选择:AST_SYMBOL_INDEX_CACHE_ROOT,然后是 XDG_CACHE_HOME,然后是 HOME。仅通过有界 CLI 检查或清除派生的缓存产物:
ast-tool cache inspect
ast-tool cache clear --yes
清除需要精确确认,拒绝不安全或活动的 SQLite 产物,并保留未知的常规文件。未启用自动缓存 GC。
有关完整的平台、运行时、持久性和操作契约,请参见支持策略。通过 SECURITY.md 报告安全问题。
安装
全局安装已发布的 CLI,同时保持依赖生命周期脚本禁用:
npm install --global ast-mcp-server --ignore-scripts
ast-tool setup
--ignore-scripts 阻止依赖运行 preinstall、install 或 postinstall 钩子。该包及其当前运行时依赖不需要这些钩子。
从源代码安装
要改为构建当前源代码:
git clone https://github.com/yailPeralta/ast-mcp-server.git
cd ast-mcp-server
corepack enable
yarn install --immutable
yarn build
该仓库固定使用 Yarn 4,并在 .yarnrc.yml 中提交了 enableScripts: false。因此,在安装期间依赖项的生命周期脚本被禁用;若在没有此设置的情况下从 npm 切换过来,只会更换标识,而风险依旧存在。
安装后,该包会暴露两个可执行文件:
- ast-mcp-server:MCP stdio 服务器。
- ast-tool:批处理、技能安装和代理设置 CLI。
诊断当前安装
ast-tool doctor [--project ]
Doctor 复用 CLI 项目发现和现有运行时权威,而不改变项目、代理、包或技能状态。它会输出有界 JSON;退出码 0 表示健康,1 表示降级,2 表示失败。当仅派生的 SQLite 索引降级时,健康的编译器仍可使用。独立诊断会将仅注册会话的索引和队列证据标记为 not_run,而不是伪造健康状态。
升级已安装的包
在不写入的情况下检查当前全局安装,或立即更新它:
ast-tool upgrade --check
ast-tool upgrade
升级仅支持经证实属于当前 npm 全局前缀或 Volta 的直接包。它会拒绝链接/源码安装和有歧义的安装,绝不使用 sudo、从 PATH 猜测或接受 --yes。npm 通过当前 Node 运行其经证实的 npm-cli.js,并禁用生命周期脚本,同时使用一次性缓存/配置副本;清理会被验证,若无法证明不存在残留,则会阻止成功。Volta 使用其原生集成。随后,更新后的 CLI 会通过该 Node 协调受管理的设置。自定义的技能字节保持不变,并会生成 ast-tool setup --agents all --yes --force-skill。任何包更新后,请重启 MCP 客户端;已在运行的服务器不会就地更改。
引导式代理设置
已安装的包会通过以下命令打开交互式向导:
ast-tool setup
从源码检出中使用 Yarn 脚本;它会先构建,然后打开同一个向导:
yarn setup
该向导按此顺序恰好支持六个 CLI 客户端:Claude Code、Hermes、OpenCode、Codex CLI、Gemini CLI 和 GitHub Copilot CLI。Cursor、Windsurf、Cline 以及其他编辑器集成客户端被有意排除。检测到的兼容客户端默认勾选;不可用或不兼容的客户端会被禁用并显示原因。使用 Up/Down 移动,Space 切换,Enter 提交,或 Escape/Ctrl-C 取消。
1. 预检每个所选客户端现有的 ast MCP 注册、技能目标位置和有效的受管理指导目标位置;
2. 安装或安全升级捆绑的 structural-code-editing 技能;
3. 向每个已验证的全局指令表面添加一个由标记拥有的激活块,同时保留所有用户拥有的字节;
4. 通过代理的官方 CLI 注册此包的 MCP 服务器;
5. 重新连接并验证预期的工具。
现有匹配的注册、技能文件与受管块保持不变。冲突的 MCP 注册或格式错误/未知的受管指引会在任何写入之前失败;请显式解决它们,而不是让安装脚本猜测。仅当已安装的字节与从已发布的 npm tarball 中认可的精确 SHA-256 匹配时,技能升级才会自动进行。未知或自定义的技能字节会默认失败关闭,除非显式指定 --force-skill。该标志仅适用于技能,不能覆盖指引冲突、不安全路由或文件系统竞态。
指引使用每个客户端经过验证的全局指令契约,而不是一个通用文件名:
| 客户端 | 受管指引目标 |
| -------- | --------------------------------------------------------------------------------------------------------------------- |
| Claude | $CLAUDE_CONFIG_DIR/CLAUDE.md,或 ~/.claude/CLAUDE.md |
| OpenCode | 有效的原生 AGENTS.md;当 OpenCode 没有原生文件时,可以共享或保留现有的 Claude 回退文件 |
| Codex | 非空的 $CODEX_HOME/AGENTS.override.md,否则为 $CODEX_HOME/AGENTS.md;CODEX_HOME 默认为 ~/.codex |
| Gemini | 来自 ~/.gemini/settings.json 的唯一受支持的安全 context.fileName,否则为 ~/.gemini/GEMINI.md |
| Hermes | skill_only;安装不会修改 SOUL.md,也不会凭空创建全局指令目标 |
| Copilot | skill_only;安装不会凭空创建个人全局指令目标 |
受管范围由 ast-tool:structural-code-editing guidance v1 开始/结束标记界定。安装仅更新该范围,保留文件的 UTF-8 BOM、换行风格、模式以及范围之外的所有内容,并拒绝重复、部分、重排序、未知、符号链接或非普通目标。写入会固定父链、前像、持有的临时 inode 和目标。新文件使用描述符绑定的无覆盖发布;替换使用原子同目录交换,验证两个交换后的身份以及固定的前像字节和模式,并在检测到调用内替换或同一 inode 编辑时回滚精确配对。每个完成的后像都会在后续资产或 MCP 变更之前重新认证。跨客户端安装是收敛的,而不是全局事务性的。
成功的设置输出使用 schema version: 2。每个 agent 报告 mcp、skill 和 guidance;物理写入包含 skill、guidance 或 mcp_config 的 asset。完整的重放会将每个适用项返回为 unchanged/skill_only,并返回一个空的 physical_writes 数组。失败的托管发布将 completed_writes、possibly_committed、rolled_back、rollback_failed 和 pending 分开;不确定的提交或失败的回滚绝不会被报告为未受影响,需要检查并重新规划。
对于自动化,请明确目标集和确认:
ast-tool setup --agents all --yes
ast-tool setup --agents claude,codex --yes
在源码检出中,请将这些命令中的 ast-tool 替换为 yarn setup。
--agents all 仅在检测之后解析,表示每个检测到的兼容客户端。如果任何检测到的客户端具有未知或不兼容的输出,设置会在写入之前失败。显式 ID 是严格的,并会拒绝不可用的客户端。非交互式设置需要同时提供 --agents 和 --yes。
需要 OpenCode 1.18.18 或更高版本。由于 opencode mcp add 忽略自定义配置路由,设置仅更新 OPENCODE_CONFIG 中的 mcp.ast,然后是 OPENCODE_CONFIG_DIR/opencode.json,再然后是 ~/.config/opencode/opencode.json。JSONC 注释、无关键和文件模式会被保留。OpenCode 名义上的诊断配置命令会规范化两个路由配置文件,因此设置会针对一次性副本运行发现和验证,同时保留选定的配置字节,并且如果计划的真实目标发生变化则安全失败。Gemini 设置可能需要先信任当前文件夹才能注册。诊断使用关联 ID,并省略命令参数、环境、凭据和原始提供程序输出;设置失败可能包含有界的目标路径,以便操作员检查不确定或待处理的写入。
安装 agent skill
该包捆绑了一个 structural-code-editing skill,用于教导 agent 何时使用 AST 工具、如何最小化上下文以及如何安全地审查变更。使用一条命令为 Claude Code 和 Hermes 安装它:
ast-tool install-skill all
或者一次安装一个目标:
ast-tool install-skill claude
ast-tool install-skill hermes
默认是用户范围。它会写入 Claude Code 的个人 skill 目录以及活动的 HERMES_HOME:
| 目标 | 目标位置 |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Claude Code | $CLAUDE_CONFIG_DIR/skills/structural-code-editing/SKILL.md,或默认的 ~/.claude/skills/... |
| Hermes | $HERMES_HOME/skills/software-development/structural-code-editing/SKILL.md,或默认情况下为 ~/.hermes/... |
| OpenCode、Codex、Gemini、Copilot | ~/.agents/skills/structural-code-editing/SKILL.md(一次物理写入,四种逻辑结果) |
要将该技能提交到某个项目以供 Claude Code 使用,请使用项目作用域:
ast-tool install-skill claude --scope project --project-root /absolute/project
这会在该项目下写入 .claude/skills/structural-code-editing/SKILL.md。项目作用域被有意拒绝用于 Hermes,因为 Hermes 技能属于某个配置文件,而不是源代码仓库。
安装是幂等的。现有的当前字节保持不变;由捆绑的 npm 来源清单所认可的精确前身字节会被安全升级。未知或自定义的字节会默认失败关闭,除非显式指定 --force。install-skill 从不写入全局指导或配置 MCP。在未链接的源代码检出中,将 ast-tool 替换为 yarn node /absolute/path/to/ast-mcp-server/dist/cli.js。
Claude Code 会实时检测现有技能目录中的更改;如果会话启动时顶层技能目录不存在,请重启它。在 Hermes 中,运行 /reload-skills 或启动新会话,然后使用 hermes skills list 进行验证。
install-skill 仅安装技能;它不会配置 MCP 传输。使用引导式 setup 命令来同时完成这两项,或完成下面特定于客户端的 MCP 设置——这些说明很有用,但它们尚未学会通过积极思考来打开 stdio 套接字。
与 Claude Code 一起使用
Claude Code 支持本地 stdio MCP 服务器。构建此仓库后,使用绝对入口点注册服务器:
AST_MCP_DIR="$(pwd)"
claude mcp add --scope user --env AST_MCP_APPLY_GUARD=allow --transport stdio ast -- \
node "$AST_MCP_DIR/dist/index.js"
claude mcp get ast
claude mcp get ast 应报告 Status: ✔ Connected。-- 分隔符是必需的:其后的所有内容都是服务器命令,而不是 Claude Code 选项。
该示例使用 --scope user,这会使服务器在你所有的项目中可用。改用 --scope local 可仅将其注册到你运行该命令的项目中。避免提交包含其他开发者绝对检出路径的项目作用域 .mcp.json。
在任何带有 tsconfig.json 的 TypeScript 项目中启动 Claude Code:
cd /absolute/path/to/your-typescript-project
claude
然后让 Claude 使用 ast 工具。例如:
Use the ast MCP server to inspect this project.
First search for UserService, then fetch only the exact source of its create method.
对于经过审查的重命名:
Use ast_rename_symbol to prepare renaming UserService.create to createUser.
Do not apply it yet. Show me the affected files, diagnostic delta, plan hash,
and the complete operation preview.
审查预览后:
使用 ast_apply_operation 应用该操作,并使用 prepare 步骤返回的精确 operation_id 和
plan_hash。
项目范围的读取和准备工具需要 project_root。Claude 应传入当前项目目录或其显式的 tsconfig.json 路径。预览和应用的调用则使用已准备的操作坐标;MCP 服务器本身不包含任何特定于仓库的路径。
MCP 还是批量 CLI?
| 工作流 | 推荐接口 |
| ------------------------------------------------ | ----------------------------------------- |
| 交互式探索或单次经审查的变更 | Claude Code MCP 工具 |
| 已知的多步骤读取流水线 | 通过 Bash 执行 ast-tool run pipeline.json |
| 现在准备并在后续进程中应用 | ast-tool run,然后 ast-tool apply |
在 Claude Code 内使用 /mcp 检查服务器状态和工具。在会话之外,使用 claude mcp list、claude mcp get ast 或 claude mcp remove ast -s user。
其他 MCP 客户端
Hermes Agent:
hermes mcp add ast --command node --env AST_MCP_APPLY_GUARD=allow --args /absolute/path/to/ast-mcp-server/dist/index.js
hermes mcp test ast
项目范围的工具接受 project_root,可以是项目目录或显式的 tsconfig.json 路径。服务器不包含任何特定于仓库的路径。
DeepSeek Harness(开发者预览版)
本包内附带了一个轻量适配器:cordis.patch.yml 通过官方
@deepseek-ai/dsh-mcp-client
桥接挂载打包的 ast-mcp-server stdio 命令,并通过恰好 "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } 进行声明。
This is a Developer Preview against a pinned, source-built Harness revision
(dsh-v0.1.2-alpha.1 at cd5ef8148158c3a752a658978873241fdf8e2bbc). The published
ast-mcp-server@0.13.0 package is the compatibility baseline:
dsh plugin --profile web add ast-mcp-server@0.13.0
For a local candidate, pack and install its tarball instead:
yarn pack --out ast-mcp-server-%v.tgz
dsh plugin --profile web add ./ast-mcp-server-0.13.1.tgz
The first supported surface is reads + prepare + preview. Every apply path is
denied by a fail-closed guard: ast_apply_operation is not registered unless
AST_MCP_APPLY_GUARD=allow is set explicitly (the shipped patch instead pins deny,
so the Harness surface stays deny-by-default; an unset or invalid value also denies).
The adapter also sets AST_MCP_TEXT_PROJECTION=canonical_json: successful structured
results keep their lossless structuredContent and gain canonical JSON text only when
ordinary MCP text is empty, because the pinned native presenter otherwise exposes only a
non-useful empty-result marker. The projection is adapter-specific, never replaces existing
text, and reports an explicit size-limit marker when the complete supervised frame has room.
If even the unchanged structured-only result exceeds the existing worker frame, supervised mode
fails closed rather than truncating or corrupting it. Known upstream gaps remain non-authoritative:
the official bridge drops MCP tool annotations
(readOnlyHint/destructiveHint) and launches the stdio child outside the Harness sandbox.
yarn test:dsh-adapter is the mandatory verification. It binds the public 0.13.0 npm
integrity, packs the candidate, builds the pinned Harness and bridge from source, and proves
tools.mode: native, the 15-tool scoped catalog, complete executable input schemas,
read/prepare/preview, all three invalid ast_explore combinations, apply absence, and rejected direct apply.
The schema gate freezes the public empty ast_explore contract as RED, requires the candidate
registry/native definitions to match, and hashes all 14 unaffected model schemas. A deterministic
two-step model then invokes
mcp__ast__ast_get_project_status through a real headless Agent/Session: the public baseline
must reproduce the empty-result marker, while the corrected candidate must deliver lossless
canonical JSON to the next model request, the durable tool/result, and a cold Agent
resume/replay reconstructed from persistence. The smoke removes and read-backs its disposable
profile/workspace state and fails
(never skips) on an identity mismatch, missing prerequisite, lifecycle leak, or evidence gap.
MCP tools
| Tool | Purpose | Mutates files |
| --------------------------- | -------------------------------------------------------------------- | ------------- |
| ast_list_files | Paginated, project-relative source file inventory | No |
| ast_get_project_status | Read-only compiler, freshness, index, and operation status | No |
| ast_explore | Bounded composed selectors, source evidence, and references | No |
| ast_get_file | Bounded exact source lines, byte hash, and snapshot state | No |
| ast_get_outline | Body-free declaration signatures; detailed symbol metadata is opt-in | No |
| ast_get_symbol_source | Exact source for one declaration | No |
| ast_search_symbols | Paginated structural symbol discovery | No |
| ast_find_references | Compiler-resolved references with bounded context | No |
| ast_get_impact | Bounded incoming/outgoing compiler-backed impact evidence | No |
| ast_find_test_candidates | Paginated affected tests with atomic compiler relationship proofs | No |
| ast_get_diagnostics | Project- or file-scoped TypeScript diagnostics | No |
| ast_rename_symbol | Prepare a project-wide rename | No |
| ast_replace_symbol_body | Prepare a body-only replacement while preserving the signature | No |
| ast_scaffold_class | Prepare one new class file with explicit placeholder methods | No |
| ast_get_operation_preview | Retrieve the complete retained diff for a prepared plan | No |
| ast_apply_operation | Apply one reviewed, hash-bound plan | Yes |
Read results use project-relative paths, deterministic ordering, structured MCP output, and pagination where result sets can grow with the project.
Diagnostic aggregates
Set include_aggregates: true on ast_get_diagnostics to summarize the complete normalized diagnostic snapshot independently of the selected raw page. The option defaults to false; disabled responses omit aggregates and keep the existing shape.
Each code and file dimension returns at most 20 ranked groups. groups.length + omitted_group_count = total_group_count, and sum(groups[*].count) = covered_diagnostic_count. Code coverage plus omitted_diagnostic_count equals the diagnostic total; file coverage also adds unfiled_diagnostic_count. File groups contain normalized project-relative paths only, but may disclose a path that is absent from the selected raw page.
ast_explore supports query, exact file, and exact symbol routes. Its default summary profile returns bounded reusable selectors; context adds selected source and full adds compiler references. Whole symbol clusters are admitted under the caller's max_bytes ceiling, so source, reference records, and call paths are never sliced. omissions classifies withheld components as budget, incomplete, or untrusted, and any requested omission keeps completeness false.
Exact file_path plus symbol_path requests may opt into bounded static call_spines. Only fresh, exact, compiler-resolved invocation sites qualify; generic references, dynamic dispatch, and runtime behavior are not inferred. Absence of call_spines performs no call traversal. Every response still reports freshness, completeness, truncation, unresolved selectors, record limits, and canonical serialized-byte accounting. Use the primitive tools when a single exact operation is clearer or when preparing a mutation. See ADR 0013.
Symbol search is relevance-ranked and defaults to at most 20 summary records containing file, a directly reusable selector, kind, and body-free signature. Request detail: "selectors" for routing coordinates only, or detail: "full", limit: 100 for the v0.4.0 fields/page. References default to detail: "locations"; request detail: "context" only when the bounded source line is needed.
Optional TOON results
ast_search_symbols, ast_find_references, ast_get_impact, and ast_get_diagnostics accept output_format: "toon" for collection-heavy results consumed directly by a model. JSON remains the default and preserves the canonical structured object.
MCP TOON is returned once as structured content shaped like { "format": "toon", "data": "..." }; data is the lossless TOON document. The complete JSON result is not duplicated. These four tools validate their canonical Zod result and verify an encode/decode deep-equality round trip before presentation, but do not advertise a single MCP outputSchema because their successful structured content has two representations.
Do not request TOON for source, outlines, file lists, previews, or mutation results. Checked negative controls show that the MCP envelope makes those shapes larger. TOON is an explicit shape-specific optimization, not a new dialect for every object in sight.
Batch CLI
ast-tool lets Claude Code and other Bash-capable clients collapse a known structural pipeline into one shell call:
ast-tool validate pipeline.json
ast-tool run pipeline.json
ast-tool run pipeline.json --output-format toon
cat pipeline.json | ast-tool run -
Example search-to-source pipeline:
{
"version": 1,
"project_root": "/absolute/project",
"steps": [
{
"id": "search",
"tool": "ast_search_symbols",
"input": { "query": "UserService", "limit": 20 }
},
{
"id": "source",
"tool": "ast_get_symbol_source",
"input": {
"file_path": { "$ref": "#/steps/search/symbols/0/file" },
"symbol_path": { "$ref": "#/steps/search/symbols/0/selector" }
}
}
],
"emit": { "$ref": "#/steps/source" }
}
A $ref is an RFC 6901 JSON Pointer rooted at prior step results. References cannot point forward. If emit is omitted, only the final step result is returned; intermediate results remain inside the process.
For CLI batches only, omit project_root or provide a directory to select the nearest tsconfig.json or jsconfig.json from the invocation directory upward. An explicit config file always wins. Discovery stops at a .git or filesystem boundary and rejects same-level ambiguity or symlinked identities; MCP tool calls still require an explicit project_root.
ast_find_test_candidates and ast_explore are admitted as read steps. The batch runner injects the pipeline project_root, rejects a conflicting step root, and invokes the same registered MCP implementation. Candidate relationship proofs and exploration clusters remain whole; final JSON and TOON differ only in serialization, not logical evidence.
Bounded foreach
{
"version": 1,
"project_root": "/absolute/project",
"limits": { "concurrency": 4 },
"steps": [
{ "id": "files", "tool": "ast_list_files", "input": { "limit": 20 } },
{
"id": "outlines",
"tool": "ast_get_outline",
"foreach": { "$ref": "#/steps/files/files" },
"input": { "file_path": { "$item": "" } }
}
]
}
$item accepts an empty pointer for the complete item or /field for one field. Foreach is read-only, order-preserving, fail-fast, and concurrency-bounded.
Batch limits
- Input document: 1 MiB.
- Steps: 50.
- Total tool invocations: 500.
- Foreach items per step: 200.
- Read concurrency: default 4, maximum 16.
- Each retained step result and final serialized output: 10 MiB.
- Total retained intermediate context: 50 MiB.
- One project root per pipeline.
- No branches, eval, embedded JavaScript, while loops, or arbitrary transformations.
Success is one compact JSON value on stdout by default. ast-tool run --output-format toon writes one plain TOON document for a read-only batch; internal steps remain structured JSON, and prepare batches reject TOON before execution. Encoding and output-limit failures write no partial stdout and use stable ENCODING_ERROR or OUTPUT_LIMIT codes. Errors are always structured JSON on stderr. Exit code 0 is success, 1 is execution/apply failure, and 2 is usage or schema failure.
Reviewed mutations
MCP process
Rename, body replacement, and class scaffold never write directly during preparation:
1. Call ast_rename_symbol, ast_replace_symbol_body, or ast_scaffold_class.
2. Review the diagnostic delta, affected files, blocked, and plan_hash.
3. Fetch complete diffs with ast_get_operation_preview when needed.
4. Call ast_apply_operation with both operation_id and plan_hash.
MCP plans live in a bounded in-memory store and do not survive a server restart.
ast_scaffold_class accepts structured imports, heritage, decorators, constructor parameter properties, initialized properties, and one or more method signatures. It creates an in-memory preview for one absent project-relative .ts/.tsx target. Each generated method initially contains only throw new Error("Not implemented: Class.method"). Review the /dev/null creation diff and diagnostics, apply the scaffold, then replace each pending method body with ast_replace_symbol_body. Existing targets and symbolic/traversing parents fail closed.
CLI process boundary
A batch may contain at most one prepare operation. It must be the final step and cannot use foreach. ast_apply_operation and arbitrary preview calls are forbidden inside batch documents.
A CLI prepare writes an exact private plan and returns top-level operation_id, plan_hash, and plan_file even when emit omits them:
ast-tool run prepare-rename.json
ast-tool apply /path/from/plan_file.astplan --plan-hash
The default plan directory is:
${XDG_STATE_HOME:-~/.local/state}/ast-tool/plans
Set AST_TOOL_STATE_DIR to isolate it. Directories are mode 0700; plans are mode 0600, atomically replaced, size-bounded, versioned, and expire with the prepared operation. Plan files contain exact proposed source bytes and must be treated as private code.
Apply loads the exact retained postimages, requires the separately supplied reviewed hash, validates serialized byte hashes and contained paths, rechecks the complete source/config workspace, stages writes, verifies postimages, and persists an applied receipt inside the same cooperative workspace lock. A later CLI invocation can replay that receipt idempotently, including after the preparation TTL.
Guarantee boundary
The server does not claim a filesystem-wide transaction or safety against a continuously mutating writer:
- Each replacement exchanges and authenticates one staged/destination pair. Multi-file apply remains sequential, so earlier postimages may be visible before later files commit.
- Reverse rollback restores only an exact operation-owned pair. Lost ownership preserves the observable entries and returns AMBIGUOUS_APPLY; it never falls back to pathname replacement.
- Creation is no-clobber. Once a created inode is published, a later failure cannot safely infer unlink ownership, so the destination and hidden stage are preserved and rollback fails closed as ambiguous.
- MCP and CLI apply share a fail-closed filesystem lock keyed by canonical tsconfig.json when they use the same state directory. It does not coordinate editors, NFS writers, writers using another configuration, or hostile external processes.
- Deterministic promise barriers prove the tested publication/rollback interleavings. They are a threat-boundary test seam, not a global atomicity or continuous-writer guarantee.
- Receipt persistence runs before that lock is released. If receipt storage fails after source replacement, apply exits non-zero and reports that verified postimages may be present; retry recovers the receipt only when the complete workspace exactly matches the reviewed post-workspace fingerprint.
- A hard process crash can leave a stale lock. Remove it only after inspecting its metadata and proving no apply is running; exact complete postimages can then recover the receipt, while partial or divergent state remains a conflict.
- Source encoding support is UTF-8, with or without BOM. Unsupported encodings are rejected.
Development gates
Add or change an MCP tool
Keep schemas, metadata, annotations, handlers, errors, and serialization in the tool module. Export
one frozen descriptor, add it to the intentional order in src/tools/catalog.ts, and declare only
static effect, batch, compatibility, and direct-format facts. Do not add request state, dynamic
discovery, invocation-by-name, or a generic executor to the catalog.
Update the independent tools/list inventories only after reviewing the complete wire metadata;
they must not import or derive expectations from the catalog. Then run the focused catalog and MCP
integration tests plus the runtime, package, and managed-skill gates below.
yarn vitest run test/tool-catalog.test.ts test/mcp.integration.test.ts
yarn format:check
yarn lint
yarn typecheck
yarn test
yarn build
yarn test:mcp
yarn test:cli
yarn test:package
yarn test:installed-agents
yarn npm audit --all --recursive
yarn pack --dry-run
test:mcp exercises the built stdio server. test:cli runs a read pipeline and a prepare/apply/replay workflow across separate Node processes. test:installed-agents is a host-dependent manual gate: it builds first, detects locally installed supported clients, uses only disposable homes/config roots, verifies deterministic effective discovery without model calls, reports unavailable clients, and removes the disposable state. It is not a portable CI requirement because CI does not install every external client.
Benchmarks
yarn benchmark /absolute/project --sample 20 --output benchmark/results/project.json
yarn benchmark:corpus benchmark/task-corpus.json --output benchmark/results/self-corpus.json
yarn benchmark:batch --iterations 5 --output benchmark/results/self-batch.json
yarn benchmark:formats
yarn benchmark:shapes
The batch benchmark compares two separate client calls with one batch invocation in fresh Node processes, recording model round-trips, actual tool invocations, wall time, maximum RSS, and serialized character counts. Character counts are not model-specific token estimates.
The format benchmark runs real tools against this repository plus deterministic reference/diagnostic fixtures. It checks JSON→TOON→value equality, UTF-8 bytes, gpt-tokenizer o200k_base estimates, encode/decode latency, the actual MCP envelope, tool metadata, and negative controls. Its checked result is benchmark/results/self-formats.json; local tokenizer estimates do not establish provider-side billing or cache savings. See benchmark/README.md for methodology and limitations.
The result-shaping benchmark compares the v0.4.0-compatible full/100/context profiles with the new public defaults across exact-name, exact-path, prefix, broad-substring, and multi-file-reference tasks. It fails on missing evidence, extra required calls, fewer than the benchmark's required minimum tool surface, or less than 35% aggregate TOON token reduction. Its checked result is benchmark/results/self-result-shapes.json.
Scope
- TypeScript and JavaScript projects understood by the TypeScript compiler.
- Structural rename, callable-body replacement, and reviewed creation of one class scaffold.
- Declarative DAG-like pipelines with prior-result references and bounded foreach.
- No arbitrary signature migration, general file creation/deletion, cross-language refactors, or general-purpose scripting language.