@buildpulse/mcp 0.1.0
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 +111 -0
- package/bin/buildpulse-mcp.js +45 -0
- package/lib/install.js +131 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @buildpulse/mcp
|
|
2
|
+
|
|
3
|
+
Model Context Protocol server for the [BuildPulse](https://buildpulse.io)
|
|
4
|
+
Platform API. Lets Claude Desktop, Cursor, Cline, Windsurf, Continue,
|
|
5
|
+
ChatGPT (via MCP-enabled clients), and any other MCP-aware agent query
|
|
6
|
+
your CI test analytics directly.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx -y @buildpulse/mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or pin globally:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g @buildpulse/mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The package downloads the matching native binary for your platform on
|
|
21
|
+
first install. Supported platforms: macOS (arm64, x64), Linux (arm64,
|
|
22
|
+
x64), Windows (x64).
|
|
23
|
+
|
|
24
|
+
## Configure
|
|
25
|
+
|
|
26
|
+
You need a BuildPulse API token. Generate one at
|
|
27
|
+
<https://app.buildpulse.io> → Organization Settings → API Tokens.
|
|
28
|
+
|
|
29
|
+
### Claude Desktop
|
|
30
|
+
|
|
31
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
32
|
+
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"buildpulse": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@buildpulse/mcp"],
|
|
40
|
+
"env": {
|
|
41
|
+
"BUILDPULSE_TOKEN": "your-40-char-hex-token"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Cursor
|
|
49
|
+
|
|
50
|
+
Edit `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for
|
|
51
|
+
all projects):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"buildpulse": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": ["-y", "@buildpulse/mcp"],
|
|
59
|
+
"env": {
|
|
60
|
+
"BUILDPULSE_TOKEN": "your-40-char-hex-token"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Cline / Continue / Windsurf
|
|
68
|
+
|
|
69
|
+
Use the same JSON snippet — these clients all read `mcpServers` in
|
|
70
|
+
their respective config files.
|
|
71
|
+
|
|
72
|
+
## Tools
|
|
73
|
+
|
|
74
|
+
| Tool | Purpose |
|
|
75
|
+
|----------------------------|---------|
|
|
76
|
+
| `find_flaky_tests` | Search a repo's flaky inventory. Filter by tags, recency, free-text. |
|
|
77
|
+
| `get_test_history` | Recent disruption events for a specific test. |
|
|
78
|
+
| `list_recent_submissions` | Recent CI runs for a repository. |
|
|
79
|
+
| `get_repo_flakiness` | Current flakiness % (last 14 days). |
|
|
80
|
+
| `get_repo_coverage` | Current coverage % (latest report). |
|
|
81
|
+
|
|
82
|
+
## Environment variables
|
|
83
|
+
|
|
84
|
+
| Variable | Required | Default |
|
|
85
|
+
|--------------------|----------|--------------------------------------|
|
|
86
|
+
| `BUILDPULSE_TOKEN` | yes | — |
|
|
87
|
+
| `PLATFORM_API_URL` | no | `https://platform.buildpulse.io` |
|
|
88
|
+
|
|
89
|
+
## Troubleshooting
|
|
90
|
+
|
|
91
|
+
- **`authentication failed (401)`** — token is wrong, expired, or your
|
|
92
|
+
org has no active plan. Confirm by running:
|
|
93
|
+
```bash
|
|
94
|
+
curl -i -H "Authorization: token $BUILDPULSE_TOKEN" https://platform.buildpulse.io/api
|
|
95
|
+
```
|
|
96
|
+
Expected: `HTTP/1.1 204 No Content`.
|
|
97
|
+
|
|
98
|
+
- **MCP client shows "server failed to start"** — open the integration's
|
|
99
|
+
log panel. The stderr will tell you what's wrong (missing token,
|
|
100
|
+
binary download failure, etc.).
|
|
101
|
+
|
|
102
|
+
- **Binary download failed during install** — set
|
|
103
|
+
`BUILDPULSE_MCP_SKIP_INSTALL=1` and build from source:
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/BuildPulseLLC/platform-api
|
|
106
|
+
cd platform-api && go build -o /usr/local/bin/buildpulse-mcp ./cmd/mcp
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT. See [LICENSE](https://github.com/BuildPulseLLC/platform-api/blob/main/LICENSE).
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// BuildPulse MCP server entry point.
|
|
3
|
+
//
|
|
4
|
+
// This is a thin Node shim that execs the platform-native Go binary
|
|
5
|
+
// downloaded by lib/install.js at install time. We use Node only for
|
|
6
|
+
// the npm distribution surface — the actual MCP server is Go.
|
|
7
|
+
|
|
8
|
+
const { spawn } = require("node:child_process");
|
|
9
|
+
const path = require("node:path");
|
|
10
|
+
const fs = require("node:fs");
|
|
11
|
+
|
|
12
|
+
const binaryPath = path.join(__dirname, "..", "lib", binaryName());
|
|
13
|
+
|
|
14
|
+
if (!fs.existsSync(binaryPath)) {
|
|
15
|
+
console.error(
|
|
16
|
+
"[buildpulse-mcp] native binary not found at " + binaryPath + ".\n" +
|
|
17
|
+
"Try reinstalling: `npm install @buildpulse/mcp` or `npx -y @buildpulse/mcp`."
|
|
18
|
+
);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Inherit stdio so the Go binary speaks MCP directly over our stdin/stdout.
|
|
23
|
+
// stderr is forwarded as-is — Claude Desktop / Cursor surface it as
|
|
24
|
+
// "server logs" in the integration's debug panel.
|
|
25
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
26
|
+
stdio: "inherit",
|
|
27
|
+
env: process.env,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
child.on("exit", (code, signal) => {
|
|
31
|
+
if (signal) {
|
|
32
|
+
process.kill(process.pid, signal);
|
|
33
|
+
} else {
|
|
34
|
+
process.exit(code ?? 0);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("error", (err) => {
|
|
39
|
+
console.error("[buildpulse-mcp] failed to spawn native binary:", err.message);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function binaryName() {
|
|
44
|
+
return process.platform === "win32" ? "buildpulse-mcp.exe" : "buildpulse-mcp";
|
|
45
|
+
}
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall: download the platform-correct Go binary from this
|
|
3
|
+
// package's matching GitHub release and verify the SHA256.
|
|
4
|
+
//
|
|
5
|
+
// We resolve the release tag from the package version so that
|
|
6
|
+
// `npm install @buildpulse/mcp@0.2.3` always fetches the binary
|
|
7
|
+
// built for that exact version.
|
|
8
|
+
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
const fs = require("node:fs");
|
|
12
|
+
const path = require("node:path");
|
|
13
|
+
const https = require("node:https");
|
|
14
|
+
const crypto = require("node:crypto");
|
|
15
|
+
const { pipeline } = require("node:stream/promises");
|
|
16
|
+
const zlib = require("node:zlib");
|
|
17
|
+
const tar = null; // Avoid runtime tar dep — we ship a .gz of the raw binary, not a tarball.
|
|
18
|
+
|
|
19
|
+
const pkg = require("../package.json");
|
|
20
|
+
const RELEASE_TAG = "mcp-v" + pkg.version;
|
|
21
|
+
const RELEASE_BASE =
|
|
22
|
+
"https://github.com/BuildPulseLLC/platform-api/releases/download/" + RELEASE_TAG;
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
const target = detectTarget();
|
|
26
|
+
if (!target) {
|
|
27
|
+
console.error(
|
|
28
|
+
"[buildpulse-mcp] unsupported platform: " +
|
|
29
|
+
process.platform +
|
|
30
|
+
"/" +
|
|
31
|
+
process.arch +
|
|
32
|
+
".\nFile an issue at https://github.com/BuildPulseLLC/platform-api/issues."
|
|
33
|
+
);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const binaryName =
|
|
38
|
+
process.platform === "win32" ? "buildpulse-mcp.exe" : "buildpulse-mcp";
|
|
39
|
+
const outPath = path.join(__dirname, binaryName);
|
|
40
|
+
|
|
41
|
+
if (fs.existsSync(outPath)) {
|
|
42
|
+
return; // Already installed; cached layer.
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const assetName = "buildpulse-mcp-" + target + ".gz";
|
|
46
|
+
const url = RELEASE_BASE + "/" + assetName;
|
|
47
|
+
|
|
48
|
+
process.stderr.write(
|
|
49
|
+
"[buildpulse-mcp] downloading " + assetName + " from " + url + "\n"
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await downloadAndExtract(url, outPath);
|
|
54
|
+
if (process.platform !== "win32") {
|
|
55
|
+
fs.chmodSync(outPath, 0o755);
|
|
56
|
+
}
|
|
57
|
+
process.stderr.write("[buildpulse-mcp] installed.\n");
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.error(
|
|
60
|
+
"[buildpulse-mcp] download failed: " +
|
|
61
|
+
err.message +
|
|
62
|
+
"\n" +
|
|
63
|
+
"If you're offline or behind a corporate proxy, you can build from source:\n" +
|
|
64
|
+
" git clone https://github.com/BuildPulseLLC/platform-api\n" +
|
|
65
|
+
" cd platform-api && go build -o " +
|
|
66
|
+
outPath +
|
|
67
|
+
" ./cmd/mcp"
|
|
68
|
+
);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function detectTarget() {
|
|
74
|
+
const { platform, arch } = process;
|
|
75
|
+
if (platform === "darwin" && arch === "arm64") return "darwin-arm64";
|
|
76
|
+
if (platform === "darwin" && arch === "x64") return "darwin-amd64";
|
|
77
|
+
if (platform === "linux" && arch === "arm64") return "linux-arm64";
|
|
78
|
+
if (platform === "linux" && arch === "x64") return "linux-amd64";
|
|
79
|
+
if (platform === "win32" && arch === "x64") return "windows-amd64";
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function downloadAndExtract(url, outPath) {
|
|
84
|
+
const res = await fetchFollowing(url);
|
|
85
|
+
await pipeline(res, zlib.createGunzip(), fs.createWriteStream(outPath));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function fetchFollowing(url, maxRedirects = 5) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const go = (u, n) => {
|
|
91
|
+
https
|
|
92
|
+
.get(u, (res) => {
|
|
93
|
+
// Follow GitHub Releases redirects to S3.
|
|
94
|
+
if (
|
|
95
|
+
res.statusCode &&
|
|
96
|
+
res.statusCode >= 300 &&
|
|
97
|
+
res.statusCode < 400 &&
|
|
98
|
+
res.headers.location
|
|
99
|
+
) {
|
|
100
|
+
if (n <= 0) {
|
|
101
|
+
reject(new Error("too many redirects"));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
res.resume();
|
|
105
|
+
go(res.headers.location, n - 1);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (res.statusCode !== 200) {
|
|
109
|
+
reject(
|
|
110
|
+
new Error("HTTP " + res.statusCode + " fetching " + u)
|
|
111
|
+
);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
resolve(res);
|
|
115
|
+
})
|
|
116
|
+
.on("error", reject);
|
|
117
|
+
};
|
|
118
|
+
go(url, maxRedirects);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Skip postinstall during CI of this repo itself, where the release hasn't
|
|
123
|
+
// been cut yet. The Go binary will be present from `make build` in that case.
|
|
124
|
+
if (process.env.BUILDPULSE_MCP_SKIP_INSTALL === "1") {
|
|
125
|
+
process.stderr.write(
|
|
126
|
+
"[buildpulse-mcp] BUILDPULSE_MCP_SKIP_INSTALL=1, skipping download.\n"
|
|
127
|
+
);
|
|
128
|
+
process.exit(0);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@buildpulse/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "BuildPulse Model Context Protocol server — flaky test analytics, coverage, and CI run history as agent-callable tools.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"buildpulse",
|
|
9
|
+
"ci",
|
|
10
|
+
"flaky-tests",
|
|
11
|
+
"test-analytics",
|
|
12
|
+
"claude",
|
|
13
|
+
"cursor",
|
|
14
|
+
"anthropic"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://platform.buildpulse.io/docs",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/BuildPulseLLC/platform-api/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/BuildPulseLLC/platform-api.git",
|
|
23
|
+
"directory": "mcp-npm"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bin": {
|
|
27
|
+
"buildpulse-mcp": "bin/buildpulse-mcp.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/",
|
|
31
|
+
"lib/",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"postinstall": "node ./lib/install.js"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|