内容
# hledit-mcp
`hledit-mcp` 是一个MCP服务器,暴露 [`hledit`](https://github.com/dabito/hledit) 的哈希锚定文件编辑功能,适用于标准MCP客户端,如Claude Code、Claude Desktop和Cursor。
与 [`pi-hledit`](https://github.com/dabito/pi-hledit)(Pi原生集成)的理念相同,但使用MCP代替Pi的扩展API,因此可以使用相同的编辑原语从MCP兼容的客户端访问。
官方MCP注册表: [`io.github.dabito/hledit-mcp`](https://registry.modelcontextprotocol.io/?search=hledit).
不要求代理人完全重现旧文本,`hledit read`为每行添加一个稳定的锚点:
```text
5#K7Q:func main() {
6#M9A: fmt.Println("hello")
7#R2C:}
```
写入命令引用诸如 `6#M9A` 的锚点。在更改文件之前,`hledit` 会重新计算该行的哈希值。如果文件自读取以来已更改,则锚点将被拒绝,不会发生写入 — 代理人会收到 `stale` 错误和重新映射提示,而不是静默损坏错误行。
## 演示
参见 [`docs/demo/transcript.md`](docs/demo/transcript.md),了解在实际 `hledit-mcp` 工具表面上通过MCP stdio传输的确定性MCP stale-write拒绝演示。
该转录由 [`docs/demo/hledit-mcp-demo.mjs`](docs/demo/hledit-mcp-demo.mjs) 生成,该脚本通过 `@modelcontextprotocol/sdk` 的stdio客户端驱动 `dist/index.js`。它不直接调用 `hledit`。
## MCP服务器,用于防止写入过时文件的 安全文件编辑
`hledit-mcp` 为MCP兼容的编码代理提供了一个文件编辑工具,该工具读取行锚点,验证这些锚点是否与当前文件内容匹配,并在触摸磁盘之前拒绝过时写入。它适用于本地工作区编辑,您希望显式失败防止过时上下文,而不是盲目文本替换。
## 为什么使用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+](https://go.dev/) 安装 `hledit` CLI(或 `PATH` 上的预编译二进制文件)
- Node.js 18+
- MCP兼容的客户端
## 安装
首先安装 `hledit` CLI:
```bash
go install github.com/dabito/hledit@latest
```
然后配置您的MCP客户端以运行 `hledit-mcp`。对于Claude Code,请使用 `claude mcp add --help` 验证当前的CLI语法;最近的版本使用:
```bash
claude mcp add hledit -- npx -y hledit-mcp
```
Claude Desktop和其他MCP客户端可以使用相同的stdio服务器形状:
```json
{
"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`
一个工具,三个操作,与 `pi-hledit` 的合约完全匹配:
| `op` | 目的 |
| ------- | --------------------------------------------------- |
| `edit` | 应用单个替换/插入/删除/替换范围 |
| `batch` | 在一次调用中应用多个锚点引用的编辑 |
| 名称 | 类型 | 必需 | 描述 |
| ----------- | ------- | ------------------ | ---------------------------------------------------------------------- |
| `op` | 字符串 | ✓ | `"read"`、`"edit"` 或 `"batch"` |
| `path` | 字符串 | ✓ | 文件路径 |
| `offset` | 数字 | | 1索引起始行(`read`) |
| `limit` | 数字 | | 要返回的最大行数(`read`);默认为 `2000` |
| `grep` | 字符串 | | 按子字符串过滤行(`read`) |
| `action` | 字符串 | | `replace`、`insert`、`delete` 或 `replace-range`(`edit`) |
| `end_anchor`| 字符串 | | `replace-range`/范围删除的结束锚点 |
| `content` | 字符串 | | 替换/插入内容;空 = 删除 |
| `after` | 布尔值 | | 对于 `action:"insert"`,在锚点后插入 |
| `edits` | 字符串 | 对于 `batch` | JSON格式的批量编辑操作数组 |
工作流程:`read` 获取锚点 → `edit`(单个更改)或 `batch`(多个)。如果编辑返回 `stale`,请重新读取以获取新的锚点,然后重试 — 自从读取以来,锚点所在的行已移动或更改。
默认 `read` 调用是有界限的:当省略 `offset`/`limit` 时,服务器使用 `offset=1` 和 `limit=2000`。
## 开发
```bash
npm install
npm test # 类型检查 + 构建 + 单元/端到端测试 + lint
npm run build # 编译 index.ts + core.ts 到 dist/index.js
npm start # 直接从源代码运行服务器,通过 tsx(stdio 传输)
```
`core.test.ts` 中的单元测试涵盖了与 `pi-hledit` 测试套件相同的合约,但不包括Pi特定的渲染断言(此处没有渲染层)。`e2e.test.ts` 通过 `@modelcontextprotocol/sdk` 自己的 `Client`/`StdioClientTransport` 驱动已构建的 `dist/index.js`,实现真正的MCP stdio握手 — 与 `npx hledit-mcp` 运行的工件相同,而不仅仅是TypeScript源代码。
已发布的 `bin`/`main` 指向 `dist/index.js`,使用esbuild(`build.mjs`)构建,并通过纯 `node` 运行 — 这保持了 `>=18` 的Node要求。直接使用 `node` 运行 `index.ts` 仅适用于Node ≥22.6,它具有内置的TypeScript类型剥离;较旧的LTS版本根本不支持此功能。
## 致谢与前沿艺术
哈希行编辑的想法来自Can Bölük / @can1357的编码代理人搭建工作,特别是 [“我在一个下午改进了15个LLM的编码能力。只有一个Harness发生了变化。”](https://blog.can.ac/2026/02/12/the-harness-problem/) 和 [`oh-my-pi`](https://github.com/can1357/oh-my-pi)。有关更多前沿艺术,请参见 [`hledit`](https://github.com/dabito/hledit#credits-and-prior-art) 的致谢。
## 相关软件包
- [`hledit`](https://github.com/dabito/hledit) — 两个集成都包装的独立CLI。
- [`pi-hledit`](https://github.com/dabito/pi-hledit) — Pi原生集成,相同的工具合约。