mrmainspring 0.1.5 → 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 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)));
@@ -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
- process.stdout.write(`\nPaste this into ${formatClientName(target)} MCP config:\n\n`);
62
- process.stdout.write(`${formatMcpConfig()}\n`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mrmainspring",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Mr Mainspring MCP backend with memory, Grimoire policies, audit, Casper anchoring, and x402 settlement boundaries.",
5
5
  "license": "MIT",
6
6
  "type": "module",