mrmainspring 0.1.4 → 0.1.6
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/dist/cli.js +11 -3
- package/dist/client-setup.d.ts +8 -0
- package/dist/client-setup.js +113 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { loadConfig } from "./config.js";
|
|
6
|
+
import { setupAllClients, formatClientSetupReport } from "./client-setup.js";
|
|
6
7
|
import { ensureGrimoireMasterKey, loadLocalEnvFile, resolveEnvPath } from "./env-file.js";
|
|
7
8
|
import { getDefaultMainspringPaths } from "./paths.js";
|
|
8
9
|
const _pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -15,7 +16,7 @@ Usage:
|
|
|
15
16
|
mainspring --version Show the installed version
|
|
16
17
|
mainspring init Create local config, data, and logs directories
|
|
17
18
|
mainspring config Print MCP client config JSON
|
|
18
|
-
mainspring setup
|
|
19
|
+
mainspring setup Initialize local files and print MCP config
|
|
19
20
|
mainspring doctor Check the local setup
|
|
20
21
|
mainspring update Show how to update to the latest version
|
|
21
22
|
|
|
@@ -58,8 +59,15 @@ export function runCliCommand(args) {
|
|
|
58
59
|
if (command === "setup") {
|
|
59
60
|
const result = initializeLocalSetup();
|
|
60
61
|
process.stdout.write(formatInitResult(result));
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
const clientResults = setupAllClients();
|
|
63
|
+
const report = formatClientSetupReport(clientResults);
|
|
64
|
+
if (report) {
|
|
65
|
+
process.stdout.write(report);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
process.stdout.write("\nNo MCP clients detected. Paste this into your client config manually:\n\n");
|
|
69
|
+
process.stdout.write(`${formatMcpConfig()}\n`);
|
|
70
|
+
}
|
|
63
71
|
return true;
|
|
64
72
|
}
|
|
65
73
|
if (command === "doctor") {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ClientSetupResult = {
|
|
2
|
+
name: string;
|
|
3
|
+
configPath: string;
|
|
4
|
+
status: "written" | "already-set" | "not-installed" | "error";
|
|
5
|
+
error?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function setupAllClients(env?: NodeJS.ProcessEnv): ClientSetupResult[];
|
|
8
|
+
export declare function formatClientSetupReport(results: ClientSetupResult[]): string;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const MAINSPRING_ENTRY = {
|
|
5
|
+
command: "npx",
|
|
6
|
+
args: ["-y", "mrmainspring"]
|
|
7
|
+
};
|
|
8
|
+
const CLIENTS = [
|
|
9
|
+
// Claude Desktop
|
|
10
|
+
{ name: "Claude Desktop", path: "~/Library/Application Support/Claude/claude_desktop_config.json", platforms: ["darwin"], format: "standard" },
|
|
11
|
+
{ name: "Claude Desktop", path: "%APPDATA%/Claude/claude_desktop_config.json", platforms: ["win32"], format: "standard" },
|
|
12
|
+
{ name: "Claude Desktop", path: "~/.config/Claude/claude_desktop_config.json", platforms: ["linux"], format: "standard" },
|
|
13
|
+
// Claude Code CLI
|
|
14
|
+
{ name: "Claude Code", path: "~/.claude/settings.json", platforms: ["darwin", "linux", "win32"], format: "standard" },
|
|
15
|
+
// Cursor
|
|
16
|
+
{ name: "Cursor", path: "~/.cursor/mcp.json", platforms: ["darwin", "linux"], format: "standard" },
|
|
17
|
+
{ name: "Cursor", path: "%USERPROFILE%/.cursor/mcp.json", platforms: ["win32"], format: "standard" },
|
|
18
|
+
// Windsurf
|
|
19
|
+
{ name: "Windsurf", path: "~/.codeium/windsurf/mcp_config.json", platforms: ["darwin", "linux", "win32"], format: "standard" },
|
|
20
|
+
// Zed
|
|
21
|
+
{ name: "Zed", path: "~/.config/zed/settings.json", platforms: ["darwin", "linux"], format: "zed" },
|
|
22
|
+
];
|
|
23
|
+
function expandPath(p, env) {
|
|
24
|
+
return p
|
|
25
|
+
.replace(/^~/, homedir())
|
|
26
|
+
.replace(/%APPDATA%/gi, env.APPDATA ?? "")
|
|
27
|
+
.replace(/%USERPROFILE%/gi, env.USERPROFILE ?? homedir());
|
|
28
|
+
}
|
|
29
|
+
function isInstalled(configPath) {
|
|
30
|
+
return existsSync(dirname(configPath)) || existsSync(configPath);
|
|
31
|
+
}
|
|
32
|
+
function readJson(path) {
|
|
33
|
+
if (!existsSync(path))
|
|
34
|
+
return {};
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function alreadySet(json, format) {
|
|
43
|
+
if (format === "zed") {
|
|
44
|
+
return !!json.context_servers?.mainspring;
|
|
45
|
+
}
|
|
46
|
+
return !!json.mcpServers?.mainspring;
|
|
47
|
+
}
|
|
48
|
+
function mergeConfig(json, format) {
|
|
49
|
+
if (format === "zed") {
|
|
50
|
+
return {
|
|
51
|
+
...json,
|
|
52
|
+
context_servers: {
|
|
53
|
+
...(json.context_servers ?? {}),
|
|
54
|
+
mainspring: { command: { path: "npx", args: ["-y", "mrmainspring"] } }
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
...json,
|
|
60
|
+
mcpServers: {
|
|
61
|
+
...(json.mcpServers ?? {}),
|
|
62
|
+
mainspring: MAINSPRING_ENTRY
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function setupAllClients(env = process.env) {
|
|
67
|
+
const plat = process.platform;
|
|
68
|
+
const results = [];
|
|
69
|
+
const seen = new Set();
|
|
70
|
+
for (const client of CLIENTS) {
|
|
71
|
+
if (!client.platforms.includes(plat))
|
|
72
|
+
continue;
|
|
73
|
+
const configPath = expandPath(client.path, env);
|
|
74
|
+
const key = `${client.name}:${configPath}`;
|
|
75
|
+
if (seen.has(key))
|
|
76
|
+
continue;
|
|
77
|
+
seen.add(key);
|
|
78
|
+
if (!isInstalled(configPath)) {
|
|
79
|
+
results.push({ name: client.name, configPath, status: "not-installed" });
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const json = readJson(configPath);
|
|
84
|
+
if (alreadySet(json, client.format)) {
|
|
85
|
+
results.push({ name: client.name, configPath, status: "already-set" });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
89
|
+
writeFileSync(configPath, JSON.stringify(mergeConfig(json, client.format), null, 2) + "\n", "utf8");
|
|
90
|
+
results.push({ name: client.name, configPath, status: "written" });
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
results.push({ name: client.name, configPath, status: "error", error: String(e) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return results;
|
|
97
|
+
}
|
|
98
|
+
export function formatClientSetupReport(results) {
|
|
99
|
+
const active = results.filter(r => r.status !== "not-installed");
|
|
100
|
+
if (active.length === 0)
|
|
101
|
+
return "";
|
|
102
|
+
const lines = ["\nMCP clients configured:"];
|
|
103
|
+
for (const r of active) {
|
|
104
|
+
if (r.status === "written")
|
|
105
|
+
lines.push(` [ok] ${r.name} → ${r.configPath}`);
|
|
106
|
+
else if (r.status === "already-set")
|
|
107
|
+
lines.push(` [ok] ${r.name} → already configured`);
|
|
108
|
+
else
|
|
109
|
+
lines.push(` [warn] ${r.name} → ${r.error}`);
|
|
110
|
+
}
|
|
111
|
+
lines.push("\nRestart any open MCP clients to load the server.");
|
|
112
|
+
return lines.join("\n") + "\n";
|
|
113
|
+
}
|
package/package.json
CHANGED