关于 hledit MCP
hledit MCP 是供编码 Agent 修改本地工作区文件的 MCP 服务。它为行添加哈希锚点,并在文件自读取后发生变化时拒绝编辑。
主要功能
- 01读取带稳定哈希锚点的行
- 02替换、插入或删除锚定行
- 03一次调用应用多项编辑
- 04写入前拒绝过期锚点
适用场景
- 01避免盲目文本替换,编辑本地代码
- 02编辑过期报错后重新读取文件
- 03批量应用多项锚定修改
MCP 相关
它将 hledit 的 read、edit 和 batch 操作作为工具提供给兼容客户端。服务通过 stdio 运行并调用 hledit CLI。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
1收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| op | enum | 是 | 操作:'read'、'edit' 或 'batch'read | edit | batch |
| grep | string | 否 | 按子字符串筛选行(read) |
| path | string | 是 | 文件路径 |
| after | boolean | 否 | 对于 action:'insert',在锚点之后插入 |
| edits | string | 否 | 批量编辑操作的 JSON 数组(op: read/edit/batch) |
| limit | number | 否 | 要返回的最大行数(read) |
| action | enum | 否 | 编辑操作:replace、insert、delete 或 replace-range。如果未指定 end_anchor 或 after,则默认为 replace。replace | insert | delete | replace-range |
| anchor | string | 否 | LN#HASH 锚点,例如 12#NKT;当前 hledit 接受 2 字符的旧版锚点 |
| offset | number | 否 | 从指定行开始(从 1 开始计数)(read) |
| content | string | 否 | 替换或插入的内容;为空表示删除 |
| end_anchor | string | 否 | replace-range/删除范围的结束锚点 |
详细介绍
hledit-mcp
hledit-mcp 是一个 MCP 服务,可将 hledit 的哈希锚定文件编辑功能提供给 Claude Code、Claude Desktop 和 Cursor 等标准 MCP 客户端。
它与 pi-hledit(Pi 原生集成)的理念相同,但使用 MCP 而非 Pi 的扩展 API,因此 MCP 兼容客户端也能使用相同的编辑原语。
官方 MCP Registry:io.github.dabito/hledit-mcp。
无需让 Agent 精确复现旧文本,hledit read 会为每一行添加稳定的锚点:
5#K7Q:func main() {
6#M9A: fmt.Println("hello")
7#R2C:}
写入命令会引用 6#M9A 之类的锚点。修改文件前,hledit 会重新计算该行的哈希。如果文件自读取后发生了变化,锚点就会被拒绝,不会执行写入——Agent 会收到 stale 错误和重新映射提示,而不会在不知情的情况下错误地修改其他行。
演示
参见 docs/demo/transcript.md,查看确定性的 MCP stdio 记录,其中展示了实际 hledit-mcp 工具接口如何拒绝过期写入。
该记录由 docs/demo/hledit-mcp-demo.mjs 生成,它通过 @modelcontextprotocol/sdk 的 stdio 客户端驱动 dist/index.js。它不会直接调用 hledit。
用于安全处理过期写入的 MCP 服务
hledit-mcp 为 MCP 兼容的编码 Agent 提供一个文件编辑工具:读取行锚点、根据当前文件内容验证这些锚点,并在写入磁盘前拒绝过期写入。它适用于本地工作区编辑,让你可以明确处理上下文过期的情况,而不是盲目替换文本。
为什么要单独提供 MCP 版本,而不是只用 pi-hledit
pi-hledit 和 hledit-mcp 共享相同的工具契约(本仓库中的 core.ts——参数构建、批量转换、结果格式化)和底层 hledit CLI。只有注册和执行的胶合层不同:pi-hledit 将该契约接入 Pi 的 registerTool,而本项目将其接入 @modelcontextprotocol/sdk 的 McpServer。MCP 没有与 Pi 的 renderCall/renderResult 终端渲染功能相当的机制,因此本包也没有这类功能——该层确实是 Pi 专属的界面装饰,并非可移植工具契约的一部分。
如果你希望通过 MCP 工具边界拒绝过期写入,而不是依赖宿主原生的文本替换行为,请使用 hledit-mcp。
要求
- Go 1.21+,用于安装
hleditCLI(或使用PATH中的预编译二进制文件) - Node.js 18+
- MCP 兼容客户端
安装
请先安装 hledit CLI:
go install github.com/dabito/hledit@latest
然后配置 MCP 客户端以运行 hledit-mcp。对于 Claude Code,请通过 claude mcp add --help 确认当前 CLI 语法;近期版本使用:
claude mcp add hledit -- npx -y hledit-mcp
Claude Desktop 和其他 MCP 客户端也可以使用相同的 stdio 服务配置:
{
"mcpServers": {
"hledit": {
"command": "npx",
"args": ["-y", "hledit-mcp"],
"env": {
"HLEDIT_CWD": "/path/to/workspace"
}
}
}
}
将 HLEDIT_CWD 设置为 MCP 客户端允许 hledit 编辑的工作区。
配置
| 变量 | 默认值 | 描述 |
|---|---|---|
HLEDIT_BIN | hledit(位于 PATH 中) | hledit 二进制文件的路径(如果它不在 PATH 中)。 |
HLEDIT_CWD | 服务端的 process.cwd() | hledit 用于解析相对路径的工作目录。请将其限定为你预期 MCP 客户端编辑的工作区。 |
HLEDIT_MCP_DIFF | 0 | 为成功的 edit/batch 调用启用可选的文本差异输出。默认关闭,以保持 MCP/模型上下文简洁。设置为 1、true 或 yes 即可启用。 |
HLEDIT_MCP_DIFF_MAX_LINES | 80 | 启用 HLEDIT_MCP_DIFF 时的最大差异行数,包括省略标记。可接受的最小值:3。 |
HLEDIT_MCP_DIFF_CONTEXT | 2 | 启用差异输出时,变更范围周围的上下文行数。可接受的最小值:0。 |
HLEDIT_MCP_DIFF_MAX_CELLS | 40000 | 省略差异正文前允许的最大 LCS 比较单元格数。可接受的最小值:1。 |
工具
hledit
一个工具,三种操作,与 pi-hledit 的约定完全一致:
op | 用途 |
|---|---|
read | 读取带有 LN#HASH 锚点的注释行 |
edit | 执行一次替换/插入/删除/范围替换操作 |
batch | 在一次调用中应用多个引用锚点的编辑操作 |
| 名称 | 类型 | 必填 | 描述 |
|---|---|---|---|
op | string | ✓ | "read"、"edit" 或 "batch" |
path | string | ✓ | 文件路径 |
offset | number | 起始行(从 1 开始)(read) | |
limit | number | 返回的最大行数(read);默认为 2000 | |
context | number | 每个 grep 匹配项周围的行数;设置 grep 时默认为 2,仅输出匹配项时使用 0 | |
grep | string | 按子字符串筛选行(read) | |
action | string | replace、insert、delete 或 replace-range(edit) | |
end_anchor | string | replace-range/范围删除的结束锚点 | |
content | string | 替换/插入的内容;为空则表示删除 | |
after | boolean | 对于 action:"insert",在锚点之后插入 | |
edits | array or string | batch 必填 | 首选:批量编辑操作的结构化数组(replace/delete/insert)。仍接受旧版 JSON 字符串。 |
工作流:使用 read 获取锚点 → 使用 edit(单次更改)或 batch(多次更改)。如果编辑返回 stale,请重新读取以获取新锚点后再试——锚点所在行自读取后已移动或发生变化。
成功的 edit 和 batch 调用会返回简洁摘要;如果已安装的 hledit CLI 提供行数变化元数据(hledit >= 1.2.4),摘要还会包含 Lines: +N -M。较旧版本的 hledit 仍可正常使用,只是不包含行数变化摘要。
设置 grep 时,上下文 grep 使用较小的默认窗口(context:2);传入 context:0 可仅输出匹配项。
设置 HLEDIT_MCP_DIFF=1,可在成功编辑后附加一个有长度限制的围栏 diff 代码块。若希望 MCP 响应尽可能节省 token,请保持该选项关闭。
首选的批量格式使用结构化 edits,由 MCP/RPC 层处理转义:
{
"op": "batch",
"path": "src/file.ts",
"edits": [
{ "op": "replace", "anchor": "12#NKT", "lines": ["const ok = true;"] }
]
}
上下文 grep 示例:
{ "op": "read", "path": "src/file.ts", "grep": "validateToken" }
仅匹配项的 grep 示例:
{ "op": "read", "path": "src/file.ts", "grep": "validateToken", "context": 0 }
过渡期间仍支持旧版 JSON 字符串格式的 edits。
默认的 read 调用有范围限制:如果未指定 offset/limit,服务端会使用 offset=1 和 limit=2000。
开发
npm install
npm test # typecheck + build + unit/e2e tests + lint
npm run build # compile index.ts+core.ts to dist/index.js
npm start # run the server directly from source via tsx (stdio transport)
core.test.ts 中的单元测试覆盖与 pi-hledit 测试套件相同的约定,但不包括 Pi 专属的渲染断言(这里没有渲染层)。e2e.test.ts 会通过 @modelcontextprotocol/sdk 自带的 Client/StdioClientTransport,使用真实的 MCP stdio 握手来运行构建后的 dist/index.js——也就是 npx hledit-mcp 运行的同一构建产物,而不只是 TypeScript 源码。
已发布版本的 bin/main 指向 dist/index.js,该文件使用 esbuild(build.mjs)构建,并通过纯 node 运行——这样可以确保 >=18 的 Node 要求准确无误。直接使用 node(不带 tsx)运行 index.ts,仅适用于 Node ≥22.6,因为该版本内置了 TypeScript 类型剥离功能;更旧的 LTS 版本完全不支持该功能。
致谢与先例
hashline-edit 的创意源自 Can Bölük / @can1357 在编码 Agent 框架方面的工作,尤其是《我在一个下午内提升了 15 个大模型的编码能力。唯一改变的是框架。》和 oh-my-pi。更多先例请参阅 hledit 的致谢。
相关软件包
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。