crukx-mcp 0.1.3 → 0.1.4
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 +11 -1
- package/dist/bin/cli.js +98 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,9 +21,19 @@ crukx login
|
|
|
21
21
|
# Opens crukx.dev in your browser — sign in and return to terminal
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Add to your editor
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
crukx install
|
|
28
|
+
# Auto-detects VS Code, Cursor, Claude Desktop, Kiro, opencode
|
|
29
|
+
# and configures them all in one step
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Restart your editor. Done — your AI agent can now use Crukx tools.
|
|
33
|
+
|
|
24
34
|
---
|
|
25
35
|
|
|
26
|
-
##
|
|
36
|
+
## Manual setup (if needed)
|
|
27
37
|
|
|
28
38
|
### VS Code + GitHub Copilot
|
|
29
39
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -59,7 +59,7 @@ import { fileURLToPath } from "url";
|
|
|
59
59
|
import { join as join2, dirname as pathDirname } from "path";
|
|
60
60
|
var __dirname = pathDirname(fileURLToPath(import.meta.url));
|
|
61
61
|
var program = new Command();
|
|
62
|
-
program.name("crukx").description("Crukx CLI \u2014 reliability control plane for autonomous software engineering").version("0.1.
|
|
62
|
+
program.name("crukx").description("Crukx CLI \u2014 reliability control plane for autonomous software engineering").version("0.1.4");
|
|
63
63
|
program.command("login").description("Authenticate with Crukx via browser").option("--api-url <url>", "Crukx gateway URL", getConfig().CRUKX_API_URL).action(async (opts) => {
|
|
64
64
|
process.stderr.write("Opening browser to complete login\u2026\n");
|
|
65
65
|
let startData;
|
|
@@ -137,6 +137,103 @@ Expires: ${auth.expires_at}
|
|
|
137
137
|
API: ${auth.api_url}
|
|
138
138
|
`);
|
|
139
139
|
});
|
|
140
|
+
program.command("install").description("Auto-install Crukx into all detected MCP-compatible clients").option("--dry-run", "Show what would be changed without writing").action(async (opts) => {
|
|
141
|
+
const { existsSync: existsSync3, readFileSync: readFileSync3, writeFileSync: writeFileSync2 } = await import("fs");
|
|
142
|
+
const { homedir: homedir2 } = await import("os");
|
|
143
|
+
const home = homedir2();
|
|
144
|
+
const SERVER_ENTRY = { command: "crukx", args: ["mcp"] };
|
|
145
|
+
function injectMcpServers(raw, key) {
|
|
146
|
+
const cfg = raw ? JSON.parse(raw) : {};
|
|
147
|
+
cfg.mcpServers = { ...cfg.mcpServers ?? {}, [key]: SERVER_ENTRY };
|
|
148
|
+
return JSON.stringify(cfg, null, 2);
|
|
149
|
+
}
|
|
150
|
+
const clients = [
|
|
151
|
+
{
|
|
152
|
+
name: "VS Code (GitHub Copilot)",
|
|
153
|
+
configPath: join2(home, ".vscode", "mcp.json"),
|
|
154
|
+
detect: () => existsSync3(join2(home, ".vscode")) || existsSync3("/usr/share/code") || existsSync3("/Applications/Visual Studio Code.app"),
|
|
155
|
+
inject: (raw) => {
|
|
156
|
+
const cfg = raw ? JSON.parse(raw) : {};
|
|
157
|
+
cfg.servers = { ...cfg.servers ?? {}, crukx: { type: "stdio", ...SERVER_ENTRY } };
|
|
158
|
+
return JSON.stringify(cfg, null, 2);
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "Cursor",
|
|
163
|
+
configPath: join2(home, ".cursor", "mcp.json"),
|
|
164
|
+
detect: () => existsSync3(join2(home, ".cursor")) || existsSync3("/Applications/Cursor.app"),
|
|
165
|
+
inject: (raw) => injectMcpServers(raw, "crukx")
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "Claude Desktop",
|
|
169
|
+
configPath: process.platform === "darwin" ? join2(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : join2(home, "AppData", "Roaming", "Claude", "claude_desktop_config.json"),
|
|
170
|
+
detect: () => existsSync3("/Applications/Claude.app") || existsSync3(join2(home, "Library", "Application Support", "Claude")) || existsSync3(join2(home, "AppData", "Local", "AnthropicClaude")),
|
|
171
|
+
inject: (raw) => injectMcpServers(raw, "crukx")
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: "Kiro",
|
|
175
|
+
configPath: join2(home, ".kiro", "settings", "mcp.json"),
|
|
176
|
+
detect: () => existsSync3(join2(home, ".kiro")),
|
|
177
|
+
inject: (raw) => injectMcpServers(raw, "crukx")
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "opencode",
|
|
181
|
+
configPath: join2(home, ".config", "opencode", "config.json"),
|
|
182
|
+
detect: () => existsSync3(join2(home, ".config", "opencode")),
|
|
183
|
+
inject: (raw) => {
|
|
184
|
+
const cfg = raw ? JSON.parse(raw) : {};
|
|
185
|
+
cfg.mcp = { ...cfg.mcp ?? {}, crukx: { ...SERVER_ENTRY, type: "local" } };
|
|
186
|
+
return JSON.stringify(cfg, null, 2);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
const detected = clients.filter((c) => c.detect());
|
|
191
|
+
if (detected.length === 0) {
|
|
192
|
+
process.stdout.write(
|
|
193
|
+
"No supported MCP clients detected.\n\nSupported: VS Code, Cursor, Claude Desktop, Kiro, opencode\n\nManual setup: https://crukx.dev/docs/mcp\n"
|
|
194
|
+
);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
process.stdout.write(`Found ${detected.length} client${detected.length > 1 ? "s" : ""}:
|
|
198
|
+
|
|
199
|
+
`);
|
|
200
|
+
let installed = 0;
|
|
201
|
+
for (const client of detected) {
|
|
202
|
+
const raw = existsSync3(client.configPath) ? readFileSync3(client.configPath, "utf-8") : null;
|
|
203
|
+
try {
|
|
204
|
+
const parsed = raw ? JSON.parse(raw) : {};
|
|
205
|
+
if (parsed?.mcpServers?.crukx || parsed?.servers?.crukx || parsed?.mcp?.crukx) {
|
|
206
|
+
process.stdout.write(` \u2705 ${client.name} \u2014 already configured
|
|
207
|
+
`);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
const newContent = client.inject(raw);
|
|
213
|
+
if (opts.dryRun) {
|
|
214
|
+
process.stdout.write(` \u{1F4DD} ${client.name} \u2014 would write: ${client.configPath}
|
|
215
|
+
`);
|
|
216
|
+
} else {
|
|
217
|
+
mkdirSync2(dirname2(client.configPath), { recursive: true });
|
|
218
|
+
writeFileSync2(client.configPath, newContent, "utf-8");
|
|
219
|
+
process.stdout.write(` \u2705 ${client.name} \u2014 configured
|
|
220
|
+
`);
|
|
221
|
+
installed++;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
process.stdout.write("\n");
|
|
225
|
+
if (opts.dryRun) {
|
|
226
|
+
process.stdout.write("Dry run complete. Remove --dry-run to apply.\n");
|
|
227
|
+
} else if (installed > 0) {
|
|
228
|
+
process.stdout.write(
|
|
229
|
+
`Installed in ${installed} client${installed > 1 ? "s" : ""}. Restart your editor, then ask:
|
|
230
|
+
"Run a Crukx audit on this file"
|
|
231
|
+
`
|
|
232
|
+
);
|
|
233
|
+
} else {
|
|
234
|
+
process.stdout.write("All clients already configured.\n");
|
|
235
|
+
}
|
|
236
|
+
});
|
|
140
237
|
program.command("mcp").description("Start the Crukx MCP server (stdio transport)").action(() => {
|
|
141
238
|
const serverPath = join2(__dirname, "server.js");
|
|
142
239
|
const child = spawn(process.execPath, [serverPath], {
|