l8bin-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 +60 -0
- package/bin/l8bin-mcp.mjs +116 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# l8bin-mcp
|
|
2
|
+
|
|
3
|
+
[LiteBin](https://l8bin.com) MCP server — deploy and operate your self-hosted projects from any MCP client.
|
|
4
|
+
|
|
5
|
+
Your agent gets deploy, logs, health checks, and runtime secrets as first-class tools over [MCP](https://modelcontextprotocol.io). No dashboard visits, no memorized commands, no pasted passwords.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"mcpServers": {
|
|
10
|
+
"litebin": {
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": ["-y", "l8bin-mcp"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Claude Code one-liner:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
claude mcp add litebin -- npx -y l8bin-mcp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## How it works
|
|
25
|
+
|
|
26
|
+
This package is a thin shim: it runs `l8b mcp` (the MCP server ships inside the
|
|
27
|
+
`l8b` CLI) and downloads the platform binary from
|
|
28
|
+
[GitHub releases](https://github.com/mtsandeep/l8bin/releases) on first use. If
|
|
29
|
+
`l8b` is already on your PATH, the shim uses your install as-is. Set `L8B_BIN`
|
|
30
|
+
to point at a specific binary.
|
|
31
|
+
|
|
32
|
+
## Getting started
|
|
33
|
+
|
|
34
|
+
1. **A server running LiteBin** — one command on any VPS with Docker:
|
|
35
|
+
`curl -fsSL https://l8b.in | bash` ([quickstart](https://l8bin.com/quickstart))
|
|
36
|
+
2. **Authenticate** — tell your agent *"set up litebin mcp"*, or run it yourself:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npx -y l8bin-mcp # first run fetches l8b (also verifies the download)
|
|
40
|
+
l8b login --server https://your-l8bin.example.com --pair
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
A short code prints; approve it at `/connect` in your dashboard and pick the
|
|
44
|
+
token scope. Agents can run the pairing themselves and relay the code.
|
|
45
|
+
|
|
46
|
+
## Tools
|
|
47
|
+
|
|
48
|
+
14 tools over one stdio server: `deploy`, `status` (wait/healthy), `list`,
|
|
49
|
+
`logs`, `env_list`, `env_push`, `url`, `stop`, `start`, `restart`,
|
|
50
|
+
`domain_set`, `domain_remove`, `delete` (confirm-gated), `doctor`.
|
|
51
|
+
|
|
52
|
+
Tokens are scoped (`read → deploy → manage → admin`, optionally locked to one
|
|
53
|
+
project), secrets are write-only, and everything is revocable and audited.
|
|
54
|
+
|
|
55
|
+
- Docs: <https://l8bin.com/docs/>
|
|
56
|
+
- Agent guide: <https://l8bin.com/agents>
|
|
57
|
+
- llms.txt: <https://l8bin.com/llms.txt>
|
|
58
|
+
- GitHub: <https://github.com/mtsandeep/l8bin>
|
|
59
|
+
|
|
60
|
+
MIT © Sandeep MT
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// l8bin-mcp — npm shim for the LiteBin MCP server.
|
|
3
|
+
//
|
|
4
|
+
// Runs `l8b mcp`, installing the platform binary on first use:
|
|
5
|
+
// 1. L8B_BIN env var, if set (explicit override)
|
|
6
|
+
// 2. an existing l8b on PATH (respects manual installs)
|
|
7
|
+
// 3. cached download in ~/.l8b/shim/, fetching the latest GitHub release
|
|
8
|
+
//
|
|
9
|
+
// All diagnostics go to stderr — stdout belongs to the MCP protocol.
|
|
10
|
+
|
|
11
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
12
|
+
import { pipeline } from "node:stream/promises";
|
|
13
|
+
import { createWriteStream } from "node:fs";
|
|
14
|
+
import fs from "node:fs/promises";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { Readable } from "node:stream";
|
|
17
|
+
import os from "node:os";
|
|
18
|
+
|
|
19
|
+
const REPO = "mtsandeep/l8bin";
|
|
20
|
+
const SHIM_DIR = path.join(os.homedir(), ".l8b", "shim");
|
|
21
|
+
|
|
22
|
+
const say = (msg) => process.stderr.write(`l8bin-mcp: ${msg}\n`);
|
|
23
|
+
|
|
24
|
+
function platformAsset() {
|
|
25
|
+
const arch = process.arch === "x64" ? "x86_64" : process.arch === "arm64" ? "aarch64" : null;
|
|
26
|
+
if (!arch) throw new Error(`unsupported architecture: ${process.arch}`);
|
|
27
|
+
const exeSuffix = process.platform === "win32" ? ".exe" : "";
|
|
28
|
+
let osName;
|
|
29
|
+
if (process.platform === "linux") osName = "linux";
|
|
30
|
+
else if (process.platform === "darwin") osName = "macos";
|
|
31
|
+
else if (process.platform === "win32") osName = "windows";
|
|
32
|
+
else throw new Error(`unsupported platform: ${process.platform}`);
|
|
33
|
+
return { asset: `l8b-${arch}-${osName}${exeSuffix}`, exe: `l8b${exeSuffix}` };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function onPath(exe) {
|
|
37
|
+
const probe = process.platform === "win32" ? spawnSync("where", [exe]) : spawnSync("which", [exe]);
|
|
38
|
+
if (probe.status !== 0 || !probe.stdout) return null;
|
|
39
|
+
const found = probe.stdout.toString().trim().split(/\r?\n/)[0];
|
|
40
|
+
return found || null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function latestTag() {
|
|
44
|
+
const res = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`, {
|
|
45
|
+
headers: { "user-agent": "l8bin-mcp-shim" },
|
|
46
|
+
});
|
|
47
|
+
if (!res.ok) throw new Error(`could not resolve the latest LiteBin release (HTTP ${res.status})`);
|
|
48
|
+
const tag = (await res.json()).tag_name;
|
|
49
|
+
if (!tag) throw new Error("latest release carries no tag");
|
|
50
|
+
return tag;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function download(url, dest) {
|
|
54
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
55
|
+
if (!res.ok || !res.body) throw new Error(`download failed (HTTP ${res.status}) for ${url}`);
|
|
56
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
57
|
+
const tmp = `${dest}.tmp`;
|
|
58
|
+
await pipeline(Readable.fromWeb(res.body), createWriteStream(tmp));
|
|
59
|
+
await fs.rename(tmp, dest);
|
|
60
|
+
if (process.platform !== "win32") await fs.chmod(dest, 0o755);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function resolveBinary() {
|
|
64
|
+
if (process.env.L8B_BIN) {
|
|
65
|
+
await fs.access(process.env.L8B_BIN);
|
|
66
|
+
return process.env.L8B_BIN;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { asset, exe } = platformAsset();
|
|
70
|
+
|
|
71
|
+
const existing = onPath(exe);
|
|
72
|
+
if (existing) return existing;
|
|
73
|
+
|
|
74
|
+
let tag;
|
|
75
|
+
try {
|
|
76
|
+
tag = await latestTag();
|
|
77
|
+
} catch (e) {
|
|
78
|
+
// Offline with no cache is fatal; offline with a cache still works.
|
|
79
|
+
try {
|
|
80
|
+
const cached = path.join(SHIM_DIR, "current");
|
|
81
|
+
await fs.access(cached);
|
|
82
|
+
return path.join(cached, exe);
|
|
83
|
+
} catch {
|
|
84
|
+
throw e;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const dest = path.join(SHIM_DIR, tag, exe);
|
|
89
|
+
try {
|
|
90
|
+
await fs.access(dest);
|
|
91
|
+
} catch {
|
|
92
|
+
say(`fetching l8b ${tag} for ${process.platform}/${process.arch}...`);
|
|
93
|
+
await download(`https://github.com/${REPO}/releases/download/${tag}/${asset}`, dest);
|
|
94
|
+
const current = path.join(SHIM_DIR, "current");
|
|
95
|
+
await fs.rm(current, { recursive: true, force: true }).catch(() => {});
|
|
96
|
+
await fs.symlink(path.join(SHIM_DIR, tag), current, process.platform === "win32" ? "junction" : "dir").catch(() => {});
|
|
97
|
+
}
|
|
98
|
+
return dest;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const bin = await resolveBinary();
|
|
103
|
+
const child = spawn(bin, ["mcp", ...process.argv.slice(2)], { stdio: "inherit" });
|
|
104
|
+
child.on("error", (e) => {
|
|
105
|
+
say(`failed to start l8b: ${e.message}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
child.on("exit", (code, signal) => {
|
|
109
|
+
if (signal) process.kill(process.pid, signal);
|
|
110
|
+
else process.exit(code ?? 1);
|
|
111
|
+
});
|
|
112
|
+
} catch (e) {
|
|
113
|
+
say(e.message);
|
|
114
|
+
say("install l8b manually with: curl -fsSL https://l8b.in | bash -s cli");
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "l8bin-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "l8bin (pronounced LiteBin) MCP server — deploy and operate your self-hosted projects from any MCP client. Wraps the l8b CLI, installing the platform binary on first use.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Sandeep MT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/mtsandeep/l8bin.git",
|
|
11
|
+
"directory": "npm"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://l8bin.com/agents",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/mtsandeep/l8bin/issues"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"l8bin-mcp": "bin/l8bin-mcp.mjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin/",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"model-context-protocol",
|
|
30
|
+
"litebin",
|
|
31
|
+
"l8bin",
|
|
32
|
+
"l8b",
|
|
33
|
+
"deploy",
|
|
34
|
+
"paas",
|
|
35
|
+
"self-hosted",
|
|
36
|
+
"docker"
|
|
37
|
+
]
|
|
38
|
+
}
|