docbrain-mcp 1.5.9 → 1.5.11
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/install.js +22 -5
- package/package.json +3 -3
- package/run.js +41 -2
package/install.js
CHANGED
|
@@ -40,14 +40,31 @@ function download(url) {
|
|
|
40
40
|
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// Download to a scratch path and rename into place. rename() is atomic
|
|
44
|
+
// within a filesystem, so a download that is interrupted — or two that
|
|
45
|
+
// race, now that run.js can trigger one on first use — can never leave a
|
|
46
|
+
// half-written file at `dest`. A truncated binary is the worst outcome
|
|
47
|
+
// available here: it exists, so nothing re-downloads it, and it fails at
|
|
48
|
+
// exec with an error that says nothing about the real cause.
|
|
49
|
+
const tmp = `${dest}.tmp-${process.pid}`;
|
|
50
|
+
const file = fs.createWriteStream(tmp);
|
|
44
51
|
res.pipe(file);
|
|
45
52
|
file.on("finish", () => {
|
|
46
|
-
file.close()
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
file.close(() => {
|
|
54
|
+
try {
|
|
55
|
+
fs.chmodSync(tmp, 0o755);
|
|
56
|
+
fs.renameSync(tmp, dest);
|
|
57
|
+
resolve();
|
|
58
|
+
} catch (err) {
|
|
59
|
+
try { fs.unlinkSync(tmp); } catch {}
|
|
60
|
+
reject(err);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
file.on("error", (err) => {
|
|
65
|
+
try { fs.unlinkSync(tmp); } catch {}
|
|
66
|
+
reject(err);
|
|
49
67
|
});
|
|
50
|
-
file.on("error", reject);
|
|
51
68
|
})
|
|
52
69
|
.on("error", reject);
|
|
53
70
|
});
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docbrain-mcp",
|
|
3
|
-
"version": "1.5.
|
|
4
|
-
"description": "DocBrain MCP server
|
|
3
|
+
"version": "1.5.11",
|
|
4
|
+
"description": "DocBrain MCP server \u2014 query your documentation from Claude Code, Cursor, and any MCP-compatible editor",
|
|
5
5
|
"homepage": "https://github.com/docbrain-ai/docbrain",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/docbrain-ai/docbrain.git"
|
|
9
9
|
},
|
|
10
|
-
"license": "
|
|
10
|
+
"license": "MIT",
|
|
11
11
|
"bin": {
|
|
12
12
|
"docbrain-mcp": "run.js"
|
|
13
13
|
},
|
package/run.js
CHANGED
|
@@ -1,11 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
-
const { spawn } = require("child_process");
|
|
4
|
+
const { spawn, execFileSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
5
6
|
const path = require("path");
|
|
6
7
|
|
|
7
8
|
const binary = path.join(__dirname, "bin", "docbrain-mcp");
|
|
8
9
|
|
|
10
|
+
// npm 12 turned lifecycle scripts off by default, so the postinstall hook that
|
|
11
|
+
// fetches this binary may never have run — and `npx -y docbrain-mcp@latest`,
|
|
12
|
+
// which is how the MCP setup instructions tell people to launch this, goes
|
|
13
|
+
// through exactly that path. Fetching on first use covers it.
|
|
14
|
+
//
|
|
15
|
+
// Deliberately synchronous, before the spawn below. This runs once, at startup,
|
|
16
|
+
// before any MCP traffic exists to delay; doing it asynchronously would mean
|
|
17
|
+
// wiring the signal forwarding and exit plumbing around a pending download for
|
|
18
|
+
// no benefit.
|
|
19
|
+
//
|
|
20
|
+
// Note that stderr is used for the progress line, never stdout: stdout is the
|
|
21
|
+
// MCP stdio transport, and a stray byte there corrupts the protocol stream.
|
|
22
|
+
function ensureBinary() {
|
|
23
|
+
if (fs.existsSync(binary)) return;
|
|
24
|
+
|
|
25
|
+
console.error("DocBrain MCP binary not found — downloading it now (one-time).");
|
|
26
|
+
try {
|
|
27
|
+
execFileSync(process.execPath, [path.join(__dirname, "install.js")], {
|
|
28
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
console.error("");
|
|
32
|
+
console.error(`Could not place the binary at: ${binary}`);
|
|
33
|
+
console.error(
|
|
34
|
+
"If that path is not writable, run this once as the user that installed the package,"
|
|
35
|
+
);
|
|
36
|
+
console.error(
|
|
37
|
+
"or download the binary manually from https://github.com/docbrain-ai/docbrain/releases"
|
|
38
|
+
);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ensureBinary();
|
|
44
|
+
|
|
9
45
|
const child = spawn(binary, process.argv.slice(2), {
|
|
10
46
|
stdio: "inherit",
|
|
11
47
|
env: process.env,
|
|
@@ -25,7 +61,10 @@ child.on("exit", (code, signal) => {
|
|
|
25
61
|
});
|
|
26
62
|
|
|
27
63
|
child.on("error", (err) => {
|
|
64
|
+
// ensureBinary already guaranteed the file exists, so this is no longer a
|
|
65
|
+
// missing-binary case — it is a permissions or exec-format problem, and
|
|
66
|
+
// suggesting a reinstall would send the user down the wrong path.
|
|
28
67
|
console.error(`Failed to run DocBrain MCP server: ${err.message}`);
|
|
29
|
-
console.error(
|
|
68
|
+
console.error(`Binary: ${binary}`);
|
|
30
69
|
process.exit(1);
|
|
31
70
|
});
|