uni-diff-patch
MCP server + CLI tool for generating valid unified diff patches deterministically.
LLM provides content or search/replace pairs, the tool computes correct diffs via mpatch (Rust) — no more broken hunks, no more git apply failures.
MCP 服务器 + CLI 工具,确定性生成合法的 unified diff patch。
LLM 只需提供文件内容或搜索替换对,工具通过 mpatch (Rust) 计算正确的 diff — 不再有坏掉的 hunk,git apply 不再失败。
Install / 安装
uv add uni-diff-patch # as dependency / 作为依赖
uvx uni-diff-patch --help # run directly / 直接运行
CLI / 命令行
# Generate patch from JSON spec / 从 JSON spec 生成 patch
uni-diff-patch generate --spec changes.json -o output.diff
# Generate with work_dir (for absolute paths) / 指定工作目录(用于绝对路径)
uni-diff-patch generate --spec changes.json --work-dir /path/to/project
# Validate a patch / 验证 patch
uni-diff-patch validate output.diff
uni-diff-patch validate output.diff --git-check --work-dir /path/to/repo
# Start MCP server / 启动 MCP 服务器
uni-diff-patch serve
MCP Configuration / MCP 配置
{
"mcpServers": {
"uni-diff-patch": {
"command": "uvx",
"args": ["uni-diff-patch", "serve"]
}
}
}
JSON Spec Format / JSON Spec 格式
All modes are specified in a changes array. Each change requires file_path and mode.
所有模式通过 changes 数组指定,每个变更需要 file_path 和 mode。
file_content — Full new content / 完整新内容
Tool reads original from disk and diffs. / 工具从磁盘读取原文件并生成 diff。
{
"changes": [{
"file_path": "src/main.py",
"mode": "file_content",
"new_content": "def main():\n print('hello')\n"
}]
}
search_replace — Targeted replacements / 精准替换(最省 token)
{
"changes": [{
"file_path": "src/main.py",
"mode": "search_replace",
"replacements": [
{"search": "print('hello')", "replace": "print('world')"},
{"search": "old_func()", "replace": "new_func()", "line_hint": 42}
]
}]
}
line_hint: approximate line number for disambiguation when search matches multiple locations.
line_hint:当 search 匹配多处时,用大致行号消歧(选最近的匹配)。
create_file — New file / 新建文件
{
"changes": [{
"file_path": "src/new_module.py",
"mode": "create_file",
"new_content": "# New module\ndef init():\n pass\n"
}]
}
delete_file — Remove file / 删除文件
{
"changes": [{
"file_path": "src/deprecated.py",
"mode": "delete_file"
}]
}
text_pair — Both old and new text / 直接传入新旧文本(不读磁盘)
{
"changes": [{
"file_path": "virtual/path.py",
"mode": "text_pair",
"old_text": "x = 1\n",
"new_text": "x = 2\n"
}]
}
rename_file — Rename/move / 重命名/移动文件
Optionally with content change. / 可同时修改内容。
{
"changes": [{
"file_path": "src/old_name.py",
"mode": "rename_file",
"new_path": "src/new_name.py",
"new_content": "# Optional modified content\n"
}]
}
chmod — Permission change / 权限变更
Optionally with content change. / 可同时修改内容。
{
"changes": [{
"file_path": "scripts/deploy.sh",
"mode": "chmod",
"old_mode": "100644",
"new_mode": "100755"
}]
}
Multi-file patch / 多文件合并 patch
{
"changes": [
{"file_path": "src/a.py", "mode": "file_content", "new_content": "..."},
{"file_path": "src/b.py", "mode": "search_replace", "replacements": [{"search": "old", "replace": "new"}]},
{"file_path": "src/c.py", "mode": "create_file", "new_content": "..."}
],
"output_path": "changes.diff"
}
Optional Fields / 可选字段
| Field / 字段 | Default / 默认值 | Description / 说明 |
|---|---|---|
encoding |
"utf-8" |
File encoding for disk-read modes / 磁盘读取模式的文件编码 |
context_lines |
3 |
Context lines in diff / diff 中的上下文行数 |
output_path |
— | Top-level, writes patch to file / 顶层字段,将 patch 写入文件 |
Development / 开发
uv sync
uv run pytest tests/ -v
Metadata
Release files for uni-diff-patch 0.0.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| uni_diff_patch-0.0.5.tar.gz | 14.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| uni_diff_patch-0.0.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.0 kB
Release files / uni_diff_patch-0.0.5.tar.gz
| Download URL | uni_diff_patch-0.0.5.tar.gz |
|---|---|
| Size | 14.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
af8d4fb10cbe391014cb3d33c0451b2573d259acc519b70c8f0311d34cb6dda9
|
|
BLAKE2b-256 checksum How to use checksums |
e270f1aca0cd46ac1b9dc7eac394f99b0db8a26554db8a38605675c37404c1b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / uni_diff_patch-0.0.5-py3-none-any.whl
| Download URL | uni_diff_patch-0.0.5-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b0cf7166df1ef4f691a7231f9e986719498a6c6d1cfc876e9521360254918300
|
|
BLAKE2b-256 checksum How to use checksums |
c00d61761ec1b65a9d7785c4c616bced84fff951cdff426ff5098f0cee735a70
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|