@actions-json/bridge 0.1.118
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 +55 -0
- package/bin/cli.js +43 -0
- package/lib/install.js +114 -0
- package/lib/platform.js +35 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @actions-json/bridge
|
|
2
|
+
|
|
3
|
+
Run the [actions.json](https://yaniv256.github.io/actions.json/) MCP bridge with
|
|
4
|
+
`npx` — no Rust toolchain required. On first run this downloads the prebuilt
|
|
5
|
+
`actions-json-mcp` binary for your platform from the GitHub release, caches it,
|
|
6
|
+
and runs it with the arguments you pass.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx @actions-json/bridge mcp \
|
|
12
|
+
--bind 0.0.0.0:17345 \
|
|
13
|
+
--actions /abs/path/to/overlay.actions.json \
|
|
14
|
+
--storage-root /abs/path/to/actions.json.storage
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Register it with a coding agent the same way — for Claude Code:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
claude mcp add actions-json -- \
|
|
21
|
+
npx -y @actions-json/bridge mcp \
|
|
22
|
+
--bind 0.0.0.0:17345 \
|
|
23
|
+
--actions /abs/path/to/overlay.actions.json \
|
|
24
|
+
--storage-root /abs/path/to/actions.json.storage
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For Codex (`~/.codex/config.toml`):
|
|
28
|
+
|
|
29
|
+
```toml
|
|
30
|
+
[mcp_servers.actions-json]
|
|
31
|
+
command = "npx"
|
|
32
|
+
args = [
|
|
33
|
+
"-y", "@actions-json/bridge", "mcp",
|
|
34
|
+
"--bind", "0.0.0.0:17345",
|
|
35
|
+
"--actions", "/abs/path/to/overlay.actions.json",
|
|
36
|
+
"--storage-root", "/abs/path/to/actions.json.storage",
|
|
37
|
+
]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
All arguments after the binary are passed straight through to `actions-json-mcp`.
|
|
41
|
+
See [Getting Started](https://yaniv256.github.io/actions.json/getting-started.html).
|
|
42
|
+
|
|
43
|
+
## Platforms
|
|
44
|
+
|
|
45
|
+
Prebuilt binaries are published for **linux-x64**. On other platforms the wrapper
|
|
46
|
+
prints build-from-source instructions (clone the repo and
|
|
47
|
+
`cargo build --release --manifest-path mcp/actions-json-mcp/Cargo.toml`).
|
|
48
|
+
|
|
49
|
+
## How it works
|
|
50
|
+
|
|
51
|
+
The package ships no binary. On first invocation it downloads
|
|
52
|
+
`actions-json-mcp-<version>-<platform>.tar.gz` from the matching
|
|
53
|
+
`extension-v<version>` GitHub release, extracts the binary into a local cache
|
|
54
|
+
(`.bin/<version>-<slug>/`), and execs it. Subsequent runs reuse the cached
|
|
55
|
+
binary.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Thin launcher: ensure the prebuilt actions-json-mcp binary is present
|
|
5
|
+
// (downloading it on first run), then exec it with whatever args were passed.
|
|
6
|
+
// Example:
|
|
7
|
+
// npx @actions-json/bridge mcp --bind 0.0.0.0:17345 --actions ... --storage-root ...
|
|
8
|
+
|
|
9
|
+
const { spawn } = require('node:child_process');
|
|
10
|
+
const { ensureBinary } = require('../lib/install');
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
let bin;
|
|
14
|
+
try {
|
|
15
|
+
bin = await ensureBinary();
|
|
16
|
+
} catch (err) {
|
|
17
|
+
process.stderr.write(`${err.message}\n`);
|
|
18
|
+
process.exit(err.code === 'UNSUPPORTED_PLATFORM' ? 2 : 1);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const args = process.argv.slice(2);
|
|
23
|
+
const child = spawn(bin, args, { stdio: 'inherit' });
|
|
24
|
+
|
|
25
|
+
// Forward termination signals so the bridge shuts down cleanly.
|
|
26
|
+
for (const sig of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
|
|
27
|
+
process.on(sig, () => child.kill(sig));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
child.on('exit', (code, signal) => {
|
|
31
|
+
if (signal) {
|
|
32
|
+
process.kill(process.pid, signal);
|
|
33
|
+
} else {
|
|
34
|
+
process.exit(code == null ? 0 : code);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
child.on('error', (err) => {
|
|
38
|
+
process.stderr.write(`failed to launch actions-json-mcp: ${err.message}\n`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
main();
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
const https = require('node:https');
|
|
7
|
+
const { execFileSync } = require('node:child_process');
|
|
8
|
+
const { assetSlug, downloadUrl, BINARY_NAME } = require('./platform');
|
|
9
|
+
|
|
10
|
+
// Resolve the package version (used to pick the matching release).
|
|
11
|
+
function packageVersion() {
|
|
12
|
+
const pkg = require('../package.json');
|
|
13
|
+
return pkg.version;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Where we cache the downloaded binary: alongside the package, keyed by version
|
|
17
|
+
// + slug so a version bump re-downloads rather than running a stale binary.
|
|
18
|
+
function binaryDir(version, slug) {
|
|
19
|
+
return path.join(__dirname, '..', '.bin', `${version}-${slug}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function binaryPath(version, slug) {
|
|
23
|
+
return path.join(binaryDir(version, slug), BINARY_NAME);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function follow(url, redirectsLeft, cb) {
|
|
27
|
+
https
|
|
28
|
+
.get(url, { headers: { 'User-Agent': 'actions-json-bridge-npx' } }, (res) => {
|
|
29
|
+
if (
|
|
30
|
+
res.statusCode >= 300 &&
|
|
31
|
+
res.statusCode < 400 &&
|
|
32
|
+
res.headers.location
|
|
33
|
+
) {
|
|
34
|
+
if (redirectsLeft <= 0) {
|
|
35
|
+
cb(new Error('too many redirects'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
res.resume();
|
|
39
|
+
follow(res.headers.location, redirectsLeft - 1, cb);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (res.statusCode !== 200) {
|
|
43
|
+
cb(new Error(`download failed: HTTP ${res.statusCode} for ${url}`));
|
|
44
|
+
res.resume();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
cb(null, res);
|
|
48
|
+
})
|
|
49
|
+
.on('error', cb);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Download the tarball to a temp file, extract the binary into binaryDir, chmod
|
|
53
|
+
// it executable, and return its path. Synchronous-feeling via a callback the CLI
|
|
54
|
+
// awaits.
|
|
55
|
+
function download(version, slug) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const url = downloadUrl(version, slug);
|
|
58
|
+
const dir = binaryDir(version, slug);
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
const tmpTar = path.join(os.tmpdir(), `actions-json-mcp-${version}-${slug}.tar.gz`);
|
|
61
|
+
const out = fs.createWriteStream(tmpTar);
|
|
62
|
+
|
|
63
|
+
follow(url, 5, (err, res) => {
|
|
64
|
+
if (err) {
|
|
65
|
+
reject(err);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
res.pipe(out);
|
|
69
|
+
out.on('finish', () => {
|
|
70
|
+
out.close(() => {
|
|
71
|
+
try {
|
|
72
|
+
// Extract just the binary from the tarball into dir.
|
|
73
|
+
execFileSync('tar', ['-xzf', tmpTar, '-C', dir, BINARY_NAME], {
|
|
74
|
+
stdio: 'inherit',
|
|
75
|
+
});
|
|
76
|
+
const bin = binaryPath(version, slug);
|
|
77
|
+
fs.chmodSync(bin, 0o755);
|
|
78
|
+
fs.rmSync(tmpTar, { force: true });
|
|
79
|
+
resolve(bin);
|
|
80
|
+
} catch (e) {
|
|
81
|
+
reject(e);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
out.on('error', reject);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Ensure the binary exists locally; download it on first run. Returns the path.
|
|
91
|
+
async function ensureBinary() {
|
|
92
|
+
const version = packageVersion();
|
|
93
|
+
const slug = assetSlug(process.platform, process.arch);
|
|
94
|
+
if (!slug) {
|
|
95
|
+
const msg =
|
|
96
|
+
`No prebuilt actions-json-mcp binary for ${process.platform}-${process.arch} yet.\n` +
|
|
97
|
+
'Build it from source instead:\n' +
|
|
98
|
+
' git clone https://github.com/yaniv256/actions.json.git\n' +
|
|
99
|
+
' cd actions.json\n' +
|
|
100
|
+
' cargo build --release --manifest-path mcp/actions-json-mcp/Cargo.toml\n' +
|
|
101
|
+
'then run mcp/actions-json-mcp/target/release/actions-json-mcp.';
|
|
102
|
+
const e = new Error(msg);
|
|
103
|
+
e.code = 'UNSUPPORTED_PLATFORM';
|
|
104
|
+
throw e;
|
|
105
|
+
}
|
|
106
|
+
const bin = binaryPath(version, slug);
|
|
107
|
+
if (fs.existsSync(bin)) {
|
|
108
|
+
return bin;
|
|
109
|
+
}
|
|
110
|
+
process.stderr.write(`Downloading actions-json-mcp ${version} (${slug})...\n`);
|
|
111
|
+
return download(version, slug);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = { ensureBinary, binaryPath, packageVersion };
|
package/lib/platform.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Maps the current Node process platform/arch to the release asset slug used by
|
|
4
|
+
// scripts/package-mcp-bridge.sh (e.g. "linux-x64"). Returns null for platforms
|
|
5
|
+
// that have no prebuilt binary yet, so the CLI can fall back to a clear
|
|
6
|
+
// build-from-source message instead of downloading the wrong file.
|
|
7
|
+
|
|
8
|
+
const SUPPORTED = {
|
|
9
|
+
'linux-x64': 'linux-x64',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function assetSlug(platform, arch) {
|
|
13
|
+
const key = `${platform}-${arch}`;
|
|
14
|
+
// Node arch "x64" matches the release slug; map the few aliases we care about.
|
|
15
|
+
const normalized = key
|
|
16
|
+
.replace('linux-x64', 'linux-x64')
|
|
17
|
+
.replace('linux-amd64', 'linux-x64');
|
|
18
|
+
return SUPPORTED[normalized] || null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// The binary name inside the tarball.
|
|
22
|
+
const BINARY_NAME = 'actions-json-mcp';
|
|
23
|
+
|
|
24
|
+
// Build the release asset filename for a version + slug.
|
|
25
|
+
function assetFileName(version, slug) {
|
|
26
|
+
return `${BINARY_NAME}-${version}-${slug}.tar.gz`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Build the GitHub release download URL for a given version tag + asset.
|
|
30
|
+
function downloadUrl(version, slug) {
|
|
31
|
+
const file = assetFileName(version, slug);
|
|
32
|
+
return `https://github.com/yaniv256/actions.json/releases/download/extension-v${version}/${file}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = { assetSlug, assetFileName, downloadUrl, BINARY_NAME, SUPPORTED };
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@actions-json/bridge",
|
|
3
|
+
"version": "0.1.118",
|
|
4
|
+
"description": "Run the actions.json MCP bridge with npx — no Rust toolchain required. Downloads the prebuilt actions-json-mcp binary for your platform and runs it.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/yaniv256/actions.json.git",
|
|
9
|
+
"directory": "adapters/npm-bridge"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://yaniv256.github.io/actions.json/getting-started.html",
|
|
12
|
+
"bin": {
|
|
13
|
+
"actions-json-bridge": "bin/cli.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin/",
|
|
17
|
+
"lib/",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"actions.json",
|
|
25
|
+
"mcp",
|
|
26
|
+
"bridge",
|
|
27
|
+
"browser",
|
|
28
|
+
"agent"
|
|
29
|
+
]
|
|
30
|
+
}
|