mrmainspring 0.2.0 → 0.2.1
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 +64 -39
- package/dist/client-setup.js +76 -10
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -71,14 +71,23 @@ export async function runCliCommand(args) {
|
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
73
|
process.stdout.write("\nNo MCP clients detected automatically.\n" +
|
|
74
|
-
"Add this to your MCP client config
|
|
74
|
+
"Add this to your MCP client config:\n\n");
|
|
75
75
|
process.stdout.write(`${formatMcpConfig()}\n`);
|
|
76
76
|
process.stdout.write("\nConfig file locations:\n" +
|
|
77
|
-
" Claude Desktop
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
77
|
+
" Claude Desktop ~/Library/Application Support/Claude/claude_desktop_config.json\n" +
|
|
78
|
+
" Claude Code ~/.claude/settings.json\n" +
|
|
79
|
+
" Cursor ~/.cursor/mcp.json\n" +
|
|
80
|
+
" Windsurf ~/.codeium/windsurf/mcp_config.json\n" +
|
|
81
|
+
" Zed ~/.config/zed/settings.json (context_servers format)\n" +
|
|
82
|
+
" VS Code ~/.vscode/mcp.json\n" +
|
|
83
|
+
" Cline ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json\n" +
|
|
84
|
+
" Roo Code ~/Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json\n" +
|
|
85
|
+
" Kilo Code ~/Library/Application Support/Code/User/globalStorage/kilocode.kilo-code/settings/cline_mcp_settings.json\n" +
|
|
86
|
+
" OpenCode ~/.config/opencode/config.json\n" +
|
|
87
|
+
" Amazon Q ~/.aws/amazonq/mcp.json\n" +
|
|
88
|
+
" Gemini CLI ~/.gemini/settings.json\n" +
|
|
89
|
+
" Codex CLI ~/.codex/config.json\n" +
|
|
90
|
+
" Continue.dev ~/.continue/config.json (array format)\n\n");
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
return true;
|
|
@@ -98,42 +107,37 @@ export async function runCliCommand(args) {
|
|
|
98
107
|
process.exitCode = 1;
|
|
99
108
|
return true;
|
|
100
109
|
}
|
|
110
|
+
const CLOCK_ART = [
|
|
111
|
+
" ╷ ",
|
|
112
|
+
" ╭────┴────╮ ",
|
|
113
|
+
" ╭╯ 12 ╰╮ ",
|
|
114
|
+
" │ 11 │ 1 │ ",
|
|
115
|
+
" │ │ │ ",
|
|
116
|
+
" 9 ─┤ ──◎ ├─ 3 ",
|
|
117
|
+
" │ │ ",
|
|
118
|
+
" │ 8 4 │ ",
|
|
119
|
+
" ╰╮ 7 5 ╭╯ ",
|
|
120
|
+
" ╰╮ 6 ╭╯ ",
|
|
121
|
+
" ╰────────╯ ",
|
|
122
|
+
" ",
|
|
123
|
+
" Mr Mainspring ",
|
|
124
|
+
" Memory · Anchor · Pay ",
|
|
125
|
+
].join("\n");
|
|
101
126
|
async function runInteractiveSetup() {
|
|
102
|
-
|
|
127
|
+
process.stdout.write(`\n${CLOCK_ART}\n\n`);
|
|
128
|
+
clack.intro("setup");
|
|
103
129
|
const result = initializeLocalSetup();
|
|
104
130
|
clack.log.success(`Local files ready\n Config: ${result.envFile}\n Data: ${result.dataDir}`);
|
|
105
131
|
const clients = detectClients();
|
|
106
132
|
const installed = clients.filter(c => c.installed);
|
|
107
|
-
const notInstalled = clients.filter(c => !c.installed);
|
|
108
|
-
let selected;
|
|
109
|
-
if (installed.length === 0) {
|
|
110
|
-
clack.log.warn("No MCP clients detected on this machine.");
|
|
111
|
-
clack.log.info("Add this JSON to your client config manually:\n\n" +
|
|
112
|
-
formatMcpConfig() + "\n\n" +
|
|
113
|
-
" Claude Desktop ~/Library/Application Support/Claude/claude_desktop_config.json\n" +
|
|
114
|
-
" Cursor ~/.cursor/mcp.json\n" +
|
|
115
|
-
" Windsurf ~/.codeium/windsurf/mcp_config.json\n" +
|
|
116
|
-
" Zed ~/.config/zed/settings.json\n" +
|
|
117
|
-
" VS Code ~/.vscode/mcp.json");
|
|
118
|
-
clack.outro("Restart your client after updating the config.");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
133
|
const choices = await clack.multiselect({
|
|
122
134
|
message: "Which MCP clients should we configure?",
|
|
123
|
-
options:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
})),
|
|
130
|
-
...notInstalled.map(c => ({
|
|
131
|
-
value: c,
|
|
132
|
-
label: c.name,
|
|
133
|
-
hint: "not found",
|
|
134
|
-
selected: false
|
|
135
|
-
}))
|
|
136
|
-
],
|
|
135
|
+
options: clients.map(c => ({
|
|
136
|
+
value: c,
|
|
137
|
+
label: c.name,
|
|
138
|
+
hint: c.installed ? c.configPath : "not detected — config will be created"
|
|
139
|
+
})),
|
|
140
|
+
initialValues: installed,
|
|
137
141
|
required: false
|
|
138
142
|
});
|
|
139
143
|
if (clack.isCancel(choices)) {
|
|
@@ -141,13 +145,34 @@ async function runInteractiveSetup() {
|
|
|
141
145
|
process.exitCode = 1;
|
|
142
146
|
return;
|
|
143
147
|
}
|
|
144
|
-
selected = choices;
|
|
148
|
+
const selected = choices;
|
|
145
149
|
if (selected.length === 0) {
|
|
146
|
-
clack.log.warn("No clients selected
|
|
147
|
-
|
|
150
|
+
clack.log.warn("No clients selected.");
|
|
151
|
+
const customPath = await clack.text({
|
|
152
|
+
message: "Enter a config file path to configure manually (or press Enter to skip):",
|
|
153
|
+
placeholder: "~/.config/myapp/mcp.json",
|
|
154
|
+
validate: () => undefined
|
|
155
|
+
});
|
|
156
|
+
if (!clack.isCancel(customPath) && customPath && customPath.trim()) {
|
|
157
|
+
const expandedPath = customPath.replace(/^~/, process.env.HOME ?? "");
|
|
158
|
+
const configResults = configureClients([
|
|
159
|
+
{ name: "Custom", configPath: expandedPath, installed: true, format: "standard" }
|
|
160
|
+
]);
|
|
161
|
+
const r = configResults[0];
|
|
162
|
+
if (r?.status === "written")
|
|
163
|
+
clack.log.success(`Configured: ${expandedPath}`);
|
|
164
|
+
else if (r?.status === "already-set")
|
|
165
|
+
clack.log.info(`Already configured: ${expandedPath}`);
|
|
166
|
+
else if (r?.error)
|
|
167
|
+
clack.log.error(`Failed: ${r.error}`);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
clack.log.info("Add this JSON to your MCP client config:\n\n" + formatMcpConfig());
|
|
171
|
+
}
|
|
172
|
+
clack.outro("Restart your MCP client after updating the config.");
|
|
148
173
|
return;
|
|
149
174
|
}
|
|
150
|
-
const configResults = configureClients(selected
|
|
175
|
+
const configResults = configureClients(selected);
|
|
151
176
|
const written = configResults.filter(r => r.status === "written").map(r => r.name);
|
|
152
177
|
const alreadySet = configResults.filter(r => r.status === "already-set").map(r => r.name);
|
|
153
178
|
const errors = configResults.filter(r => r.status === "error");
|
package/dist/client-setup.js
CHANGED
|
@@ -17,14 +17,81 @@ const CLIENTS = [
|
|
|
17
17
|
{ name: "Cursor", path: "%USERPROFILE%/.cursor/mcp.json", platforms: ["win32"], format: "standard" },
|
|
18
18
|
// Windsurf
|
|
19
19
|
{ name: "Windsurf", path: "~/.codeium/windsurf/mcp_config.json", platforms: ["darwin", "linux", "win32"], format: "standard" },
|
|
20
|
-
// Windsurf (also on Windows via AppData)
|
|
21
20
|
{ name: "Windsurf", path: "%APPDATA%/Windsurf/User/globalStorage/codeium.windsurf/mcp_config.json", platforms: ["win32"], format: "standard" },
|
|
22
21
|
// Zed
|
|
23
22
|
{ name: "Zed", path: "~/.config/zed/settings.json", platforms: ["darwin", "linux"], format: "zed" },
|
|
24
23
|
// Continue.dev
|
|
25
24
|
{ name: "Continue", path: "~/.continue/config.json", platforms: ["darwin", "linux", "win32"], format: "continue" },
|
|
26
|
-
// VS Code (
|
|
25
|
+
// VS Code (user-level MCP config — requires GitHub Copilot or MCP extension)
|
|
27
26
|
{ name: "VS Code", path: "~/.vscode/mcp.json", platforms: ["darwin", "linux", "win32"], format: "standard" },
|
|
27
|
+
// Cline (VS Code extension by saoudrizwan)
|
|
28
|
+
{
|
|
29
|
+
name: "Cline",
|
|
30
|
+
path: "~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
|
|
31
|
+
detectDir: "~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev",
|
|
32
|
+
platforms: ["darwin"], format: "standard"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "Cline",
|
|
36
|
+
path: "~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
|
|
37
|
+
detectDir: "~/.config/Code/User/globalStorage/saoudrizwan.claude-dev",
|
|
38
|
+
platforms: ["linux"], format: "standard"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "Cline",
|
|
42
|
+
path: "%APPDATA%/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
|
|
43
|
+
detectDir: "%APPDATA%/Code/User/globalStorage/saoudrizwan.claude-dev",
|
|
44
|
+
platforms: ["win32"], format: "standard"
|
|
45
|
+
},
|
|
46
|
+
// Roo Code (VS Code extension, fork of Cline)
|
|
47
|
+
{
|
|
48
|
+
name: "Roo Code",
|
|
49
|
+
path: "~/Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json",
|
|
50
|
+
detectDir: "~/Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline",
|
|
51
|
+
platforms: ["darwin"], format: "standard"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "Roo Code",
|
|
55
|
+
path: "~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json",
|
|
56
|
+
detectDir: "~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline",
|
|
57
|
+
platforms: ["linux"], format: "standard"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "Roo Code",
|
|
61
|
+
path: "%APPDATA%/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json",
|
|
62
|
+
detectDir: "%APPDATA%/Code/User/globalStorage/rooveterinaryinc.roo-cline",
|
|
63
|
+
platforms: ["win32"], format: "standard"
|
|
64
|
+
},
|
|
65
|
+
// Kilo Code (VS Code extension)
|
|
66
|
+
{
|
|
67
|
+
name: "Kilo Code",
|
|
68
|
+
path: "~/Library/Application Support/Code/User/globalStorage/kilocode.kilo-code/settings/cline_mcp_settings.json",
|
|
69
|
+
detectDir: "~/Library/Application Support/Code/User/globalStorage/kilocode.kilo-code",
|
|
70
|
+
platforms: ["darwin"], format: "standard"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "Kilo Code",
|
|
74
|
+
path: "~/.config/Code/User/globalStorage/kilocode.kilo-code/settings/cline_mcp_settings.json",
|
|
75
|
+
detectDir: "~/.config/Code/User/globalStorage/kilocode.kilo-code",
|
|
76
|
+
platforms: ["linux"], format: "standard"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "Kilo Code",
|
|
80
|
+
path: "%APPDATA%/Code/User/globalStorage/kilocode.kilo-code/settings/cline_mcp_settings.json",
|
|
81
|
+
detectDir: "%APPDATA%/Code/User/globalStorage/kilocode.kilo-code",
|
|
82
|
+
platforms: ["win32"], format: "standard"
|
|
83
|
+
},
|
|
84
|
+
// OpenCode (terminal AI coding assistant)
|
|
85
|
+
{ name: "OpenCode", path: "~/.config/opencode/config.json", platforms: ["darwin", "linux"], format: "standard" },
|
|
86
|
+
{ name: "OpenCode", path: "%APPDATA%/opencode/config.json", platforms: ["win32"], format: "standard" },
|
|
87
|
+
// Amazon Q Developer
|
|
88
|
+
{ name: "Amazon Q", path: "~/.aws/amazonq/mcp.json", platforms: ["darwin", "linux"], format: "standard" },
|
|
89
|
+
{ name: "Amazon Q", path: "%USERPROFILE%/.aws/amazonq/mcp.json", platforms: ["win32"], format: "standard" },
|
|
90
|
+
// Gemini CLI (Google)
|
|
91
|
+
{ name: "Gemini CLI", path: "~/.gemini/settings.json", platforms: ["darwin", "linux"], format: "standard" },
|
|
92
|
+
{ name: "Gemini CLI", path: "%USERPROFILE%/.gemini/settings.json", platforms: ["win32"], format: "standard" },
|
|
93
|
+
// Codex CLI (OpenAI)
|
|
94
|
+
{ name: "Codex CLI", path: "~/.codex/config.json", platforms: ["darwin", "linux", "win32"], format: "standard" },
|
|
28
95
|
];
|
|
29
96
|
function expandPath(p, env) {
|
|
30
97
|
const home = env.HOME ?? env.USERPROFILE ?? homedir();
|
|
@@ -33,8 +100,9 @@ function expandPath(p, env) {
|
|
|
33
100
|
.replace(/%APPDATA%/gi, env.APPDATA ?? "")
|
|
34
101
|
.replace(/%USERPROFILE%/gi, env.USERPROFILE ?? home);
|
|
35
102
|
}
|
|
36
|
-
function isInstalled(configPath) {
|
|
37
|
-
|
|
103
|
+
function isInstalled(configPath, detectDir) {
|
|
104
|
+
const dir = detectDir ?? dirname(configPath);
|
|
105
|
+
return existsSync(dir) || existsSync(configPath);
|
|
38
106
|
}
|
|
39
107
|
function readJson(path) {
|
|
40
108
|
if (!existsSync(path))
|
|
@@ -94,17 +162,14 @@ export function detectClients(env = process.env) {
|
|
|
94
162
|
if (seen.has(key))
|
|
95
163
|
continue;
|
|
96
164
|
seen.add(key);
|
|
97
|
-
|
|
165
|
+
const detectDir = client.detectDir ? expandPath(client.detectDir, env) : undefined;
|
|
166
|
+
results.push({ name: client.name, configPath, installed: isInstalled(configPath, detectDir), format: client.format });
|
|
98
167
|
}
|
|
99
168
|
return results;
|
|
100
169
|
}
|
|
101
170
|
export function configureClients(selected, env = process.env) {
|
|
102
171
|
const results = [];
|
|
103
172
|
for (const client of selected) {
|
|
104
|
-
if (!client.installed) {
|
|
105
|
-
results.push({ name: client.name, configPath: client.configPath, status: "not-installed" });
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
173
|
try {
|
|
109
174
|
const json = readJson(client.configPath);
|
|
110
175
|
if (alreadySet(json, client.format)) {
|
|
@@ -133,7 +198,8 @@ export function setupAllClients(env = process.env) {
|
|
|
133
198
|
if (seen.has(key))
|
|
134
199
|
continue;
|
|
135
200
|
seen.add(key);
|
|
136
|
-
|
|
201
|
+
const detectDir = client.detectDir ? expandPath(client.detectDir, env) : undefined;
|
|
202
|
+
if (!isInstalled(configPath, detectDir)) {
|
|
137
203
|
results.push({ name: client.name, configPath, status: "not-installed" });
|
|
138
204
|
continue;
|
|
139
205
|
}
|
package/package.json
CHANGED