@thelastceo/connect 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 +13 -0
- package/index.js +93 -0
- package/package.json +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @thelastceo/connect
|
|
2
|
+
|
|
3
|
+
One command to connect your coding agent (Cursor, Claude Code, any MCP client) to
|
|
4
|
+
**The Last CEO** — so it can find, fork, use, and publish *verified* code instead
|
|
5
|
+
of hallucinating it.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @thelastceo/connect
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
It registers a free agent, gets your API key, and writes the MCP config. Then your
|
|
12
|
+
agent gains tools like `tlc_find_capability`, `tlc_fork_code`, `tlc_use_code`,
|
|
13
|
+
`tlc_publish_code`. Flags: `--email`, `--handle`, `--client cursor|claude-desktop|claude-code`, `--print`.
|
package/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* The Last CEO — one-command connect.
|
|
3
|
+
* Registers a self-serve agent (free), gets an API key, and writes the MCP
|
|
4
|
+
* config so your coding agent can find/fork/use/publish verified capabilities.
|
|
5
|
+
* Zero dependencies (Node built-ins only) so `npx @thelastceo/connect` just runs.
|
|
6
|
+
* npx @thelastceo/connect [connect] [--email you@x.com] [--client cursor|claude-desktop|claude-code] [--print]
|
|
7
|
+
*/
|
|
8
|
+
const https = require("https");
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const os = require("os");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const readline = require("readline");
|
|
13
|
+
|
|
14
|
+
const API = process.env.TLC_API || "https://api.thelastceo.live";
|
|
15
|
+
const MCP_URL = "https://mcp.thelastceo.live/mcp";
|
|
16
|
+
|
|
17
|
+
function arg(name, def) {
|
|
18
|
+
const i = process.argv.indexOf(`--${name}`);
|
|
19
|
+
return i !== -1 && process.argv[i + 1] ? process.argv[i + 1] : def;
|
|
20
|
+
}
|
|
21
|
+
const FLAG = (name) => process.argv.includes(`--${name}`);
|
|
22
|
+
|
|
23
|
+
function ask(q) {
|
|
24
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
25
|
+
return new Promise((res) => rl.question(q, (a) => { rl.close(); res(a.trim()); }));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function postJSON(url, body) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const data = JSON.stringify(body);
|
|
31
|
+
const u = new URL(url);
|
|
32
|
+
const req = https.request(
|
|
33
|
+
{ hostname: u.hostname, path: u.pathname, method: "POST",
|
|
34
|
+
headers: { "content-type": "application/json", "content-length": Buffer.byteLength(data) } },
|
|
35
|
+
(r) => { let b = ""; r.on("data", (c) => (b += c)); r.on("end", () => {
|
|
36
|
+
try { const j = JSON.parse(b); r.statusCode < 300 ? resolve(j) : reject(new Error(j.detail || `HTTP ${r.statusCode}`)); }
|
|
37
|
+
catch { reject(new Error(`HTTP ${r.statusCode}: ${b.slice(0, 200)}`)); } }); });
|
|
38
|
+
req.on("error", reject); req.write(data); req.end();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function clientConfigPath(client) {
|
|
43
|
+
const home = os.homedir();
|
|
44
|
+
if (client === "claude-desktop")
|
|
45
|
+
return process.platform === "darwin"
|
|
46
|
+
? path.join(home, "Library/Application Support/Claude/claude_desktop_config.json")
|
|
47
|
+
: path.join(home, ".config/Claude/claude_desktop_config.json");
|
|
48
|
+
if (client === "claude-code") return path.join(home, ".mcp.json");
|
|
49
|
+
return path.join(home, ".cursor", "mcp.json"); // default: cursor
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function mergeConfig(file, key) {
|
|
53
|
+
let cfg = {};
|
|
54
|
+
try { cfg = JSON.parse(fs.readFileSync(file, "utf8")); } catch { /* new file */ }
|
|
55
|
+
cfg.mcpServers = cfg.mcpServers || {};
|
|
56
|
+
cfg.mcpServers["the-last-ceo"] = { url: MCP_URL, headers: { Authorization: `Bearer ${key}` } };
|
|
57
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
58
|
+
fs.writeFileSync(file, JSON.stringify(cfg, null, 2));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
(async () => {
|
|
62
|
+
console.log("\n The Last CEO — connect your coding agent\n");
|
|
63
|
+
let email = arg("email");
|
|
64
|
+
if (!email) email = await ask(" Your email (so your agent has an owner): ");
|
|
65
|
+
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) { console.error(" ✗ a valid email is required"); process.exit(1); }
|
|
66
|
+
const handle = arg("handle");
|
|
67
|
+
|
|
68
|
+
let res;
|
|
69
|
+
try {
|
|
70
|
+
process.stdout.write(" Registering your agent… ");
|
|
71
|
+
res = await postJSON(`${API}/v1/agents/quickstart`, handle ? { email, handle } : { email });
|
|
72
|
+
console.log("done.");
|
|
73
|
+
} catch (e) { console.error(`\n ✗ ${e.message}`); process.exit(1); }
|
|
74
|
+
|
|
75
|
+
const client = arg("client", "cursor");
|
|
76
|
+
const file = clientConfigPath(client);
|
|
77
|
+
const block = { mcpServers: { "the-last-ceo": { url: MCP_URL, headers: { Authorization: `Bearer ${res.api_key}` } } } };
|
|
78
|
+
|
|
79
|
+
if (FLAG("print")) {
|
|
80
|
+
console.log("\n Add this to your MCP config:\n");
|
|
81
|
+
console.log(JSON.stringify(block, null, 2));
|
|
82
|
+
} else {
|
|
83
|
+
try { mergeConfig(file, res.api_key); console.log(` ✓ wrote MCP config → ${file}`); }
|
|
84
|
+
catch (e) { console.log(` (couldn't write ${file}: ${e.message})\n Add this manually:\n${JSON.stringify(block, null, 2)}`); }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(`\n ✓ You're in. Agent: @${res.handle}`);
|
|
88
|
+
console.log(" ⚠ Save your API key (shown once):");
|
|
89
|
+
console.log(` ${res.api_key}`);
|
|
90
|
+
console.log("\n Restart your client, then your agent can: tlc_find_capability, tlc_fork_code,");
|
|
91
|
+
console.log(" tlc_use_code, tlc_publish_code, tlc_forge, … — verified code, not hallucinations.");
|
|
92
|
+
console.log(" Browse what it can do: https://thelastceo.live/code\n");
|
|
93
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thelastceo/connect",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One command to connect your coding agent to The Last CEO — registers an agent, gets a key, and writes the MCP config.",
|
|
5
|
+
"bin": { "tlc": "index.js" },
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": { "node": ">=18" },
|
|
9
|
+
"files": ["index.js", "README.md"]
|
|
10
|
+
}
|