mcp-apply-patch 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/bin/run.js +20 -0
- package/package.json +33 -0
- package/scripts/install.js +94 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# mcp-apply-patch
|
|
2
|
+
|
|
3
|
+
MCP server for structured file patching using V4A diffs. Create, update, and delete files in one atomic operation.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
Add to your MCP configuration:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"patch": {
|
|
12
|
+
"command": "npx",
|
|
13
|
+
"args": ["-y", "mcp-apply-patch"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
That's it. The binary is automatically downloaded on first run.
|
|
19
|
+
|
|
20
|
+
## Why Use This?
|
|
21
|
+
|
|
22
|
+
- **One call replaces 5+ separate Edit/Write/Create calls** — saves tokens and round-trips
|
|
23
|
+
- **Multi-file changes land atomically** — no broken intermediate states
|
|
24
|
+
- **Context-based matching** survives code drift; line numbers don't
|
|
25
|
+
- **Standard diff format** — reviewers understand changes instantly
|
|
26
|
+
|
|
27
|
+
## Build from Source
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cargo build --release
|
|
31
|
+
```
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execFileSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const binName = process.platform === "win32" ? "mcp-apply-patch.exe" : "mcp-apply-patch";
|
|
8
|
+
const binPath = path.join(__dirname, "..", "bin", binName);
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(binPath)) {
|
|
11
|
+
console.error("Binary not found. Run 'npm install' to download it.");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Pass through stdio for MCP protocol
|
|
16
|
+
const result = require("child_process").spawn(binPath, process.argv.slice(2), {
|
|
17
|
+
stdio: "inherit",
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
result.on("exit", (code) => process.exit(code ?? 1));
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-apply-patch",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "MCP server for structured file patching using V4A diffs. Create, update, and delete files in one atomic operation.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/_blitzzz/mcp-apply-patch"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"mcp-apply-patch": "bin/run.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin/",
|
|
15
|
+
"scripts/",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"postinstall": "node scripts/install.js"
|
|
20
|
+
},
|
|
21
|
+
"os": [
|
|
22
|
+
"darwin",
|
|
23
|
+
"linux",
|
|
24
|
+
"win32"
|
|
25
|
+
],
|
|
26
|
+
"cpu": [
|
|
27
|
+
"x64",
|
|
28
|
+
"arm64"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=16"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const https = require("https");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { execSync } = require("child_process");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
|
|
7
|
+
const VERSION = require("../package.json").version;
|
|
8
|
+
const REPO = "tuanhung303/apply-patch-mcp";
|
|
9
|
+
|
|
10
|
+
function getPlatformKey() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
|
|
14
|
+
const map = {
|
|
15
|
+
"darwin-arm64": "aarch64-apple-darwin",
|
|
16
|
+
"darwin-x64": "x86_64-apple-darwin",
|
|
17
|
+
"linux-x64": "x86_64-unknown-linux-gnu",
|
|
18
|
+
"linux-arm64": "aarch64-unknown-linux-gnu",
|
|
19
|
+
"win32-x64": "x86_64-pc-windows-msvc",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const key = `${platform}-${arch}`;
|
|
23
|
+
if (!map[key]) {
|
|
24
|
+
console.error(`Unsupported platform: ${key}`);
|
|
25
|
+
console.error(`Supported: ${Object.keys(map).join(", ")}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
return map[key];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function download(url) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const handler = (res) => {
|
|
34
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
35
|
+
return https.get(res.headers.location, handler).on("error", reject);
|
|
36
|
+
}
|
|
37
|
+
if (res.statusCode !== 200) {
|
|
38
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
39
|
+
}
|
|
40
|
+
const chunks = [];
|
|
41
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
42
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
43
|
+
res.on("error", reject);
|
|
44
|
+
};
|
|
45
|
+
https.get(url, { headers: { "User-Agent": "apply-patch-mcp-installer" } }, handler).on("error", reject);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function main() {
|
|
50
|
+
const platformKey = getPlatformKey();
|
|
51
|
+
const isWindows = process.platform === "win32";
|
|
52
|
+
const ext = isWindows ? ".zip" : ".tar.gz";
|
|
53
|
+
const assetName = `apply-patch-mcp-v${VERSION}-${platformKey}${ext}`;
|
|
54
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${assetName}`;
|
|
55
|
+
|
|
56
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
57
|
+
const binName = isWindows ? "apply-patch-mcp.exe" : "apply-patch-mcp";
|
|
58
|
+
const binPath = path.join(binDir, binName);
|
|
59
|
+
|
|
60
|
+
// Skip if binary already exists
|
|
61
|
+
if (fs.existsSync(binPath)) {
|
|
62
|
+
console.log("apply-patch-mcp binary already installed.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(`Downloading apply-patch-mcp v${VERSION} for ${platformKey}...`);
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const data = await download(url);
|
|
70
|
+
const tmpFile = path.join(os.tmpdir(), assetName);
|
|
71
|
+
fs.writeFileSync(tmpFile, data);
|
|
72
|
+
|
|
73
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
74
|
+
|
|
75
|
+
if (isWindows) {
|
|
76
|
+
// For Windows, use PowerShell to extract zip
|
|
77
|
+
execSync(`powershell -Command "Expand-Archive -Path '${tmpFile}' -DestinationPath '${binDir}' -Force"`, { stdio: "inherit" });
|
|
78
|
+
} else {
|
|
79
|
+
execSync(`tar xzf "${tmpFile}" -C "${binDir}"`, { stdio: "inherit" });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fs.chmodSync(binPath, 0o755);
|
|
83
|
+
fs.unlinkSync(tmpFile);
|
|
84
|
+
|
|
85
|
+
console.log(`apply-patch-mcp v${VERSION} installed successfully.`);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error(`Failed to download binary: ${err.message}`);
|
|
88
|
+
console.error(`URL: ${url}`);
|
|
89
|
+
console.error("You can build from source: cargo build --release");
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
main();
|