mcp-apply-patch 0.1.5 → 0.1.7

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.
Files changed (2) hide show
  1. package/package.json +3 -10
  2. package/scripts/install.js +37 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-apply-patch",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "MCP server for structured file patching using V4A diffs. Create, update, and delete files in one atomic operation.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,15 +16,8 @@
16
16
  "README.md"
17
17
  ],
18
18
  "scripts": {},
19
- "os": [
20
- "darwin",
21
- "linux",
22
- "win32"
23
- ],
24
- "cpu": [
25
- "x64",
26
- "arm64"
27
- ],
19
+ "os": ["darwin", "linux", "win32"],
20
+ "cpu": ["x64", "arm64"],
28
21
  "engines": {
29
22
  "node": ">=16"
30
23
  }
@@ -3,6 +3,7 @@ const fs = require("fs");
3
3
  const path = require("path");
4
4
  const { execSync } = require("child_process");
5
5
  const os = require("os");
6
+ const crypto = require("crypto");
6
7
 
7
8
  const VERSION = require("../package.json").version;
8
9
  const REPO = "tuanhung303/apply-patch-mcp";
@@ -46,12 +47,25 @@ function download(url) {
46
47
  });
47
48
  }
48
49
 
50
+ function verifySha256(filePath, expectedHex) {
51
+ const hash = crypto.createHash("sha256");
52
+ hash.update(fs.readFileSync(filePath));
53
+ const actual = hash.digest("hex");
54
+ if (actual !== expectedHex) {
55
+ throw new Error(
56
+ `SHA256 mismatch!\n Expected: ${expectedHex}\n Actual: ${actual}\n File: ${filePath}`
57
+ );
58
+ }
59
+ }
60
+
49
61
  async function doInstall() {
50
62
  const platformKey = getPlatformKey();
51
63
  const isWindows = process.platform === "win32";
52
64
  const ext = isWindows ? ".zip" : ".tar.gz";
53
65
  const assetName = `apply-patch-mcp-v${VERSION}-${platformKey}${ext}`;
54
- const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${assetName}`;
66
+ const shaAssetName = `${assetName}.sha256`;
67
+ const assetUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${assetName}`;
68
+ const shaUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${shaAssetName}`;
55
69
 
56
70
  const cacheBinDir = path.join(os.homedir(), ".mcp-apply-patch", "bin");
57
71
  const binName = isWindows ? "apply-patch-mcp.exe" : "apply-patch-mcp";
@@ -66,14 +80,26 @@ async function doInstall() {
66
80
  console.error(`Downloading apply-patch-mcp v${VERSION} for ${platformKey}...`);
67
81
 
68
82
  try {
69
- const data = await download(url);
83
+ // Download the binary and its SHA256 checksum in parallel
84
+ const [binaryData, shaData] = await Promise.all([
85
+ download(assetUrl),
86
+ download(shaUrl),
87
+ ]);
88
+
70
89
  const tmpFile = path.join(os.tmpdir(), assetName);
71
- fs.writeFileSync(tmpFile, data);
90
+ const tmpShaFile = path.join(os.tmpdir(), shaAssetName);
91
+ fs.writeFileSync(tmpFile, binaryData);
92
+ fs.writeFileSync(tmpShaFile, shaData);
93
+
94
+ // Verify SHA256 checksum before extracting
95
+ const expectedSha256 = shaData.toString("utf-8").trim().split(/\s+/)[0];
96
+ console.error("Verifying SHA256 checksum...");
97
+ verifySha256(tmpFile, expectedSha256);
98
+ console.error("SHA256 checksum verified.");
72
99
 
73
100
  fs.mkdirSync(cacheBinDir, { recursive: true });
74
101
 
75
102
  if (isWindows) {
76
- // For Windows, use PowerShell to extract zip
77
103
  execSync(`powershell -Command "Expand-Archive -Path '${tmpFile}' -DestinationPath '${cacheBinDir}' -Force"`, { stdio: "inherit" });
78
104
  } else {
79
105
  execSync(`tar xzf "${tmpFile}" -C "${cacheBinDir}"`, { stdio: "inherit" });
@@ -82,12 +108,17 @@ async function doInstall() {
82
108
  // Ensure executable permissions
83
109
  try { fs.chmodSync(binPath, 0o755); } catch (e) { /* ignore */ }
84
110
  try { fs.unlinkSync(tmpFile); } catch (e) { /* ignore */ }
111
+ try { fs.unlinkSync(tmpShaFile); } catch (e) { /* ignore */ }
85
112
 
86
113
  console.error(`apply-patch-mcp v${VERSION} installed to ${binPath}.`);
87
114
  return binPath;
88
115
  } catch (err) {
89
- console.error(`Failed to download binary: ${err.message}`);
90
- console.error(`URL: ${url}`);
116
+ if (err.message.includes("SHA256 mismatch")) {
117
+ console.error(`SECURITY: ${err.message}`);
118
+ } else {
119
+ console.error(`Failed to download binary: ${err.message}`);
120
+ }
121
+ console.error(`URL: ${assetUrl}`);
91
122
  console.error("You can build from source: cargo build --release");
92
123
  throw err;
93
124
  }