mcpick 0.0.18 → 0.0.19
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/.vscode/settings.json +5 -0
- package/CHANGELOG.md +7 -0
- package/dist/add-B9nVyh8T.js +113 -0
- package/dist/add-json-CXNDl3al.js +58 -0
- package/dist/atomic-write-BqEykHp9.js +26 -0
- package/dist/backup-DSDhHI5f.js +64 -0
- package/dist/cache-D6kd7qE8.js +226 -0
- package/dist/claude-cli-BeA-bmoW.js +394 -0
- package/dist/cli-DNNZjJYL.js +84 -0
- package/dist/clone-DLFLewBY.js +88 -0
- package/dist/config-DijVdEFn.js +176 -0
- package/dist/dev-DRJRNp7y.js +265 -0
- package/dist/disable-BA8tXPJN.js +39 -0
- package/dist/enable-Bdnnn_Cq.js +40 -0
- package/dist/get-BPjMXTMc.js +41 -0
- package/dist/hook-state-Di8lUsPr.js +171 -0
- package/dist/hooks-Bmn7pUZa.js +280 -0
- package/dist/index.js +1230 -305
- package/dist/list-B8YeDWt6.js +64 -0
- package/dist/marketplace-Br89Tg-Z.js +168 -0
- package/dist/output-BchYq0mR.js +15 -0
- package/dist/paths-BPISiJi4.js +124 -0
- package/dist/plugin-cache-Bby9Dxm9.js +405 -0
- package/dist/plugins-DHYJF5CP.js +212 -0
- package/dist/profile-CX97sMGp.js +120 -0
- package/dist/profile-DkY_lBEm.js +70 -0
- package/dist/redact-O35tjnRD.js +26 -0
- package/dist/registry-CfUKT7_C.js +92 -0
- package/dist/reload-CYDhkCVZ.js +31 -0
- package/dist/remove-DIPWYMpk.js +31 -0
- package/dist/reset-project-choices-DRM5KByw.js +28 -0
- package/dist/restore-DdMfUljI.js +84 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/settings-DEcWtzLE.js +201 -0
- package/dist/validation-xMlbgGCF.js +44 -0
- package/package.json +20 -19
- package/dist/cli/commands/add-json.js +0 -60
- package/dist/cli/commands/add.js +0 -135
- package/dist/cli/commands/backup.js +0 -83
- package/dist/cli/commands/cache.js +0 -296
- package/dist/cli/commands/clone.js +0 -108
- package/dist/cli/commands/dev.js +0 -167
- package/dist/cli/commands/disable.js +0 -36
- package/dist/cli/commands/enable.js +0 -39
- package/dist/cli/commands/get.js +0 -45
- package/dist/cli/commands/hooks.js +0 -314
- package/dist/cli/commands/list.js +0 -64
- package/dist/cli/commands/marketplace.js +0 -211
- package/dist/cli/commands/plugins.js +0 -265
- package/dist/cli/commands/profile.js +0 -134
- package/dist/cli/commands/reload.js +0 -36
- package/dist/cli/commands/remove.js +0 -35
- package/dist/cli/commands/reset-project-choices.js +0 -32
- package/dist/cli/commands/restore.js +0 -105
- package/dist/cli/index.js +0 -29
- package/dist/cli/output.js +0 -21
- package/dist/commands/add-server.js +0 -310
- package/dist/commands/backup.js +0 -60
- package/dist/commands/edit-config.js +0 -109
- package/dist/commands/edit-plugins.js +0 -201
- package/dist/commands/manage-cache.js +0 -155
- package/dist/commands/manage-hooks.js +0 -99
- package/dist/commands/manage-marketplace.js +0 -293
- package/dist/commands/restore.js +0 -118
- package/dist/core/config.js +0 -200
- package/dist/core/dev-override.js +0 -155
- package/dist/core/hook-state.js +0 -220
- package/dist/core/plugin-cache.js +0 -506
- package/dist/core/profile.js +0 -94
- package/dist/core/registry.js +0 -121
- package/dist/core/settings.js +0 -243
- package/dist/core/validation.js +0 -49
- package/dist/types.js +0 -2
- package/dist/utils/atomic-write.js +0 -27
- package/dist/utils/claude-cli.js +0 -485
- package/dist/utils/paths.js +0 -114
- package/dist/utils/redact.js +0 -28
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
//#region src/utils/claude-cli.ts
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
/**
|
|
6
|
+
* Check if Claude CLI is available
|
|
7
|
+
*/
|
|
8
|
+
async function check_claude_cli() {
|
|
9
|
+
try {
|
|
10
|
+
await execAsync("claude --version");
|
|
11
|
+
return true;
|
|
12
|
+
} catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Escape a string for shell usage
|
|
18
|
+
*/
|
|
19
|
+
function shell_escape(str) {
|
|
20
|
+
return `'${str.replace(/'/g, "'\\''")}'`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validate environment variable key
|
|
24
|
+
* Must start with letter or underscore, contain only alphanumeric and underscores
|
|
25
|
+
*/
|
|
26
|
+
function is_valid_env_key(key) {
|
|
27
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build the claude mcp add command for a server
|
|
31
|
+
*/
|
|
32
|
+
function build_add_command(server, scope) {
|
|
33
|
+
const parts = [
|
|
34
|
+
"claude",
|
|
35
|
+
"mcp",
|
|
36
|
+
"add"
|
|
37
|
+
];
|
|
38
|
+
parts.push(shell_escape(server.name));
|
|
39
|
+
const transport = server.type || "stdio";
|
|
40
|
+
if (transport !== "stdio") parts.push("--transport", transport);
|
|
41
|
+
parts.push("--scope", scope);
|
|
42
|
+
if (transport === "stdio") {
|
|
43
|
+
if (server.env) {
|
|
44
|
+
for (const [key, value] of Object.entries(server.env)) if (is_valid_env_key(key)) parts.push("-e", `${key}=${shell_escape(value)}`);
|
|
45
|
+
}
|
|
46
|
+
if ("command" in server && server.command) {
|
|
47
|
+
parts.push("--");
|
|
48
|
+
parts.push(shell_escape(server.command));
|
|
49
|
+
if (server.args && server.args.length > 0) parts.push(...server.args.map((arg) => shell_escape(arg)));
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
if ("url" in server && server.url) parts.push(shell_escape(server.url));
|
|
53
|
+
if ("headers" in server && server.headers) for (const [key, value] of Object.entries(server.headers)) parts.push("-H", shell_escape(`${key}: ${value}`));
|
|
54
|
+
}
|
|
55
|
+
return parts.join(" ");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add an MCP server using Claude CLI
|
|
59
|
+
*/
|
|
60
|
+
async function add_mcp_via_cli(server, scope) {
|
|
61
|
+
if (!await check_claude_cli()) return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
64
|
+
};
|
|
65
|
+
const command = build_add_command(server, scope);
|
|
66
|
+
try {
|
|
67
|
+
await execAsync(command);
|
|
68
|
+
return { success: true };
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: `Failed to add server via CLI: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Remove an MCP server using Claude CLI
|
|
78
|
+
*/
|
|
79
|
+
async function remove_mcp_via_cli(name) {
|
|
80
|
+
if (!await check_claude_cli()) return {
|
|
81
|
+
success: false,
|
|
82
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
83
|
+
};
|
|
84
|
+
try {
|
|
85
|
+
await execAsync(`claude mcp remove ${shell_escape(name)}`);
|
|
86
|
+
return { success: true };
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: `Failed to remove server via CLI: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Install a plugin via Claude CLI
|
|
96
|
+
*/
|
|
97
|
+
async function install_plugin_via_cli(key, scope = "user") {
|
|
98
|
+
if (!await check_claude_cli()) return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
await execAsync(`claude plugin install ${shell_escape(key)} --scope ${scope}`);
|
|
104
|
+
return { success: true };
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
error: `Failed to install plugin: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Uninstall a plugin via Claude CLI
|
|
114
|
+
*/
|
|
115
|
+
async function uninstall_plugin_via_cli(key, scope = "user") {
|
|
116
|
+
if (!await check_claude_cli()) return {
|
|
117
|
+
success: false,
|
|
118
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
119
|
+
};
|
|
120
|
+
try {
|
|
121
|
+
await execAsync(`claude plugin uninstall ${shell_escape(key)} --scope ${scope}`);
|
|
122
|
+
return { success: true };
|
|
123
|
+
} catch (error) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: `Failed to uninstall plugin: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Update a plugin via Claude CLI
|
|
132
|
+
*/
|
|
133
|
+
async function update_plugin_via_cli(key, scope = "user") {
|
|
134
|
+
if (!await check_claude_cli()) return {
|
|
135
|
+
success: false,
|
|
136
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
137
|
+
};
|
|
138
|
+
try {
|
|
139
|
+
await execAsync(`claude plugin update ${shell_escape(key)} --scope ${scope}`);
|
|
140
|
+
return { success: true };
|
|
141
|
+
} catch (error) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
error: `Failed to update plugin: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Add a marketplace via Claude CLI
|
|
150
|
+
*/
|
|
151
|
+
/**
|
|
152
|
+
* Extract GitHub owner/repo from various source formats.
|
|
153
|
+
* Returns null if not a recognizable GitHub reference.
|
|
154
|
+
*/
|
|
155
|
+
function parse_github_repo(source) {
|
|
156
|
+
const https_match = source.match(/^https?:\/\/github\.com\/([^/]+)\/([^/.]+)(?:\.git)?$/);
|
|
157
|
+
if (https_match) return {
|
|
158
|
+
owner: https_match[1],
|
|
159
|
+
repo: https_match[2]
|
|
160
|
+
};
|
|
161
|
+
const ssh_match = source.match(/^git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?$/);
|
|
162
|
+
if (ssh_match) return {
|
|
163
|
+
owner: ssh_match[1],
|
|
164
|
+
repo: ssh_match[2]
|
|
165
|
+
};
|
|
166
|
+
const shorthand_match = source.match(/^([^/\s]+)\/([^/\s]+)$/);
|
|
167
|
+
if (shorthand_match) return {
|
|
168
|
+
owner: shorthand_match[1],
|
|
169
|
+
repo: shorthand_match[2]
|
|
170
|
+
};
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Validate that a GitHub repository exists and is accessible.
|
|
175
|
+
* Returns an error message if validation fails, null if OK.
|
|
176
|
+
*/
|
|
177
|
+
async function validate_github_repo(owner, repo) {
|
|
178
|
+
try {
|
|
179
|
+
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
|
|
180
|
+
method: "GET",
|
|
181
|
+
headers: { Accept: "application/vnd.github.v3+json" }
|
|
182
|
+
});
|
|
183
|
+
if (response.status === 200) return null;
|
|
184
|
+
if (response.status === 404) return `Repository '${owner}/${repo}' not found on GitHub. Check the name or ensure it's not private.`;
|
|
185
|
+
if (response.status === 403) return `Access denied for '${owner}/${repo}'. The repository may be private — configure a GitHub token or use SSH.`;
|
|
186
|
+
return `GitHub API returned status ${response.status} for '${owner}/${repo}'.`;
|
|
187
|
+
} catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function marketplace_add_via_cli(source) {
|
|
192
|
+
if (!await check_claude_cli()) return {
|
|
193
|
+
success: false,
|
|
194
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
195
|
+
};
|
|
196
|
+
const gh = parse_github_repo(source);
|
|
197
|
+
const is_shorthand = gh && !source.startsWith("http") && !source.startsWith("git@");
|
|
198
|
+
if (gh && is_shorthand) {
|
|
199
|
+
const validation_error = await validate_github_repo(gh.owner, gh.repo);
|
|
200
|
+
if (validation_error) return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: validation_error
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
await execAsync(`claude plugin marketplace add ${shell_escape(source)}`);
|
|
207
|
+
return { success: true };
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
210
|
+
if (message.includes("SSH") || message.includes("Permission denied (publickey)")) return {
|
|
211
|
+
success: false,
|
|
212
|
+
error: `SSH authentication failed for '${source}'. Either:\n - Configure SSH keys: https://docs.github.com/en/authentication/connecting-to-github-with-ssh\n - Use HTTPS URL instead: https://github.com/${gh ? `${gh.owner}/${gh.repo}` : source}`
|
|
213
|
+
};
|
|
214
|
+
if (message.includes("not found") || message.includes("does not exist")) return {
|
|
215
|
+
success: false,
|
|
216
|
+
error: `Repository '${source}' not found. Check the name and your access permissions.`
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
success: false,
|
|
220
|
+
error: `Failed to add marketplace: ${message}`
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Remove a marketplace via Claude CLI
|
|
226
|
+
*/
|
|
227
|
+
async function marketplace_remove_via_cli(name) {
|
|
228
|
+
if (!await check_claude_cli()) return {
|
|
229
|
+
success: false,
|
|
230
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
231
|
+
};
|
|
232
|
+
try {
|
|
233
|
+
await execAsync(`claude plugin marketplace remove ${shell_escape(name)}`);
|
|
234
|
+
return { success: true };
|
|
235
|
+
} catch (error) {
|
|
236
|
+
return {
|
|
237
|
+
success: false,
|
|
238
|
+
error: `Failed to remove marketplace: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Update marketplace(s) via Claude CLI
|
|
244
|
+
*/
|
|
245
|
+
async function marketplace_update_via_cli(name) {
|
|
246
|
+
if (!await check_claude_cli()) return {
|
|
247
|
+
success: false,
|
|
248
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
249
|
+
};
|
|
250
|
+
try {
|
|
251
|
+
await execAsync(name ? `claude plugin marketplace update ${shell_escape(name)}` : "claude plugin marketplace update");
|
|
252
|
+
return { success: true };
|
|
253
|
+
} catch (error) {
|
|
254
|
+
return {
|
|
255
|
+
success: false,
|
|
256
|
+
error: `Failed to update marketplace: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* List marketplaces via Claude CLI
|
|
262
|
+
*/
|
|
263
|
+
async function marketplace_list_via_cli() {
|
|
264
|
+
if (!await check_claude_cli()) return {
|
|
265
|
+
success: false,
|
|
266
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
267
|
+
};
|
|
268
|
+
try {
|
|
269
|
+
const { stdout } = await execAsync("claude plugin marketplace list");
|
|
270
|
+
return {
|
|
271
|
+
success: true,
|
|
272
|
+
stdout: stdout.trim()
|
|
273
|
+
};
|
|
274
|
+
} catch (error) {
|
|
275
|
+
return {
|
|
276
|
+
success: false,
|
|
277
|
+
error: `Failed to list marketplaces: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get the scope description for display
|
|
283
|
+
*/
|
|
284
|
+
function get_scope_description(scope) {
|
|
285
|
+
switch (scope) {
|
|
286
|
+
case "local": return "This project only (default)";
|
|
287
|
+
case "project": return "Shared via .mcp.json (version controlled)";
|
|
288
|
+
case "user": return "Global - all projects";
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Validate a plugin or marketplace manifest via Claude CLI
|
|
293
|
+
*/
|
|
294
|
+
async function validate_plugin_via_cli(path) {
|
|
295
|
+
if (!await check_claude_cli()) return {
|
|
296
|
+
success: false,
|
|
297
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
298
|
+
};
|
|
299
|
+
try {
|
|
300
|
+
const { stdout } = await execAsync(`claude plugin validate ${shell_escape(path)}`);
|
|
301
|
+
return {
|
|
302
|
+
success: true,
|
|
303
|
+
stdout: stdout.trim()
|
|
304
|
+
};
|
|
305
|
+
} catch (error) {
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
error: `Validation failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Get details about an MCP server via Claude CLI
|
|
314
|
+
*/
|
|
315
|
+
async function mcp_get_via_cli(name) {
|
|
316
|
+
if (!await check_claude_cli()) return {
|
|
317
|
+
success: false,
|
|
318
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
319
|
+
};
|
|
320
|
+
try {
|
|
321
|
+
const { stdout } = await execAsync(`claude mcp get ${shell_escape(name)}`);
|
|
322
|
+
return {
|
|
323
|
+
success: true,
|
|
324
|
+
stdout: stdout.trim()
|
|
325
|
+
};
|
|
326
|
+
} catch (error) {
|
|
327
|
+
return {
|
|
328
|
+
success: false,
|
|
329
|
+
error: `Failed to get server details: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Add an MCP server from raw JSON via Claude CLI
|
|
335
|
+
*/
|
|
336
|
+
async function mcp_add_json_via_cli(name, json, scope = "local") {
|
|
337
|
+
if (!await check_claude_cli()) return {
|
|
338
|
+
success: false,
|
|
339
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
340
|
+
};
|
|
341
|
+
try {
|
|
342
|
+
await execAsync(`claude mcp add-json ${shell_escape(name)} ${shell_escape(json)} --scope ${scope}`);
|
|
343
|
+
return { success: true };
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return {
|
|
346
|
+
success: false,
|
|
347
|
+
error: `Failed to add server from JSON: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Reset project-scoped MCP server choices via Claude CLI
|
|
353
|
+
*/
|
|
354
|
+
async function mcp_reset_project_choices_via_cli() {
|
|
355
|
+
if (!await check_claude_cli()) return {
|
|
356
|
+
success: false,
|
|
357
|
+
error: "Claude CLI not found. Please install Claude Code CLI."
|
|
358
|
+
};
|
|
359
|
+
try {
|
|
360
|
+
await execAsync("claude mcp reset-project-choices");
|
|
361
|
+
return { success: true };
|
|
362
|
+
} catch (error) {
|
|
363
|
+
return {
|
|
364
|
+
success: false,
|
|
365
|
+
error: `Failed to reset project choices: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Get scope options for select prompt
|
|
371
|
+
*/
|
|
372
|
+
function get_scope_options() {
|
|
373
|
+
return [
|
|
374
|
+
{
|
|
375
|
+
value: "local",
|
|
376
|
+
label: "Local",
|
|
377
|
+
hint: "This project only (default)"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
value: "project",
|
|
381
|
+
label: "Project",
|
|
382
|
+
hint: "Shared via .mcp.json (git)"
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
value: "user",
|
|
386
|
+
label: "User (Global)",
|
|
387
|
+
hint: "Available in all projects"
|
|
388
|
+
}
|
|
389
|
+
];
|
|
390
|
+
}
|
|
391
|
+
//#endregion
|
|
392
|
+
export { install_plugin_via_cli as a, marketplace_remove_via_cli as c, mcp_get_via_cli as d, mcp_reset_project_choices_via_cli as f, validate_plugin_via_cli as g, update_plugin_via_cli as h, get_scope_options as i, marketplace_update_via_cli as l, uninstall_plugin_via_cli as m, check_claude_cli as n, marketplace_add_via_cli as o, remove_mcp_via_cli as p, get_scope_description as r, marketplace_list_via_cli as s, add_mcp_via_cli as t, mcp_add_json_via_cli as u };
|
|
393
|
+
|
|
394
|
+
//# sourceMappingURL=claude-cli-BeA-bmoW.js.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { defineCommand, renderUsage, runMain } from "citty";
|
|
2
|
+
//#region src/cli/index.ts
|
|
3
|
+
const main = defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "mcpick",
|
|
6
|
+
description: "Claude Code extension manager — MCP servers, plugins (skills, hooks, agents), and marketplaces"
|
|
7
|
+
},
|
|
8
|
+
subCommands: {
|
|
9
|
+
list: () => import("./list-B8YeDWt6.js").then((m) => m.default),
|
|
10
|
+
enable: () => import("./enable-Bdnnn_Cq.js").then((m) => m.default),
|
|
11
|
+
disable: () => import("./disable-BA8tXPJN.js").then((m) => m.default),
|
|
12
|
+
remove: () => import("./remove-DIPWYMpk.js").then((m) => m.default),
|
|
13
|
+
add: () => import("./add-B9nVyh8T.js").then((m) => m.default),
|
|
14
|
+
"add-json": () => import("./add-json-CXNDl3al.js").then((m) => m.default),
|
|
15
|
+
clone: () => import("./clone-DLFLewBY.js").then((m) => m.default),
|
|
16
|
+
get: () => import("./get-BPjMXTMc.js").then((m) => m.default),
|
|
17
|
+
"reset-project-choices": () => import("./reset-project-choices-DRM5KByw.js").then((m) => m.default),
|
|
18
|
+
backup: () => import("./backup-DSDhHI5f.js").then((m) => m.default),
|
|
19
|
+
restore: () => import("./restore-DdMfUljI.js").then((m) => m.default),
|
|
20
|
+
profile: () => import("./profile-CX97sMGp.js").then((m) => m.default),
|
|
21
|
+
plugins: () => import("./plugins-DHYJF5CP.js").then((m) => m.default),
|
|
22
|
+
hooks: () => import("./hooks-Bmn7pUZa.js").then((m) => m.default),
|
|
23
|
+
cache: () => import("./cache-D6kd7qE8.js").then((m) => m.default),
|
|
24
|
+
dev: () => import("./dev-DRJRNp7y.js").then((m) => m.default),
|
|
25
|
+
marketplace: () => import("./marketplace-Br89Tg-Z.js").then((m) => m.default),
|
|
26
|
+
reload: () => import("./reload-CYDhkCVZ.js").then((m) => m.default)
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Custom help renderer that appends workflow guidance and examples
|
|
31
|
+
* after citty's standard help output. This is critical for LLM agents
|
|
32
|
+
* that rely on --help output to understand multi-step workflows.
|
|
33
|
+
*/
|
|
34
|
+
async function show_usage_with_examples(cmd, parent) {
|
|
35
|
+
const base = await renderUsage(cmd, parent);
|
|
36
|
+
if ((await (typeof cmd.meta === "function" ? cmd.meta() : cmd.meta))?.name === "mcpick") console.log(base + "\n" + WORKFLOW_SECTION + "\n" + CONCEPTS_SECTION + "\n" + EXAMPLES_SECTION + "\n");
|
|
37
|
+
else console.log(base + "\n");
|
|
38
|
+
}
|
|
39
|
+
const WORKFLOW_SECTION = `
|
|
40
|
+
\x1b[4m\x1b[1mWORKFLOW\x1b[22m\x1b[24m Marketplaces contain plugins. Plugins contain skills (/slash-commands), hooks, agents, and MCP servers.
|
|
41
|
+
|
|
42
|
+
To install skills from a marketplace, follow these steps:
|
|
43
|
+
|
|
44
|
+
1. Add a marketplace: mcpick marketplace add <source>
|
|
45
|
+
2. Install a plugin: mcpick plugins install <name>@<marketplace>
|
|
46
|
+
3. Skills are now available as /slash-commands in Claude Code`;
|
|
47
|
+
const CONCEPTS_SECTION = `
|
|
48
|
+
\x1b[4m\x1b[1mCONCEPTS\x1b[22m\x1b[24m
|
|
49
|
+
|
|
50
|
+
Marketplace A catalog of plugins, hosted on GitHub, GitLab, or locally
|
|
51
|
+
Plugin A bundle containing any mix of: skills, hooks, agents, MCP servers
|
|
52
|
+
Skill A SKILL.md file that extends Claude's behaviour, invocable as /slash-command
|
|
53
|
+
MCP server A tool server providing external capabilities to Claude Code
|
|
54
|
+
Hook An event handler that runs on tool use, session start, etc.
|
|
55
|
+
Profile A saved snapshot of your MCP server and plugin configuration`;
|
|
56
|
+
const EXAMPLES_SECTION = `
|
|
57
|
+
\x1b[4m\x1b[1mEXAMPLES\x1b[22m\x1b[24m
|
|
58
|
+
|
|
59
|
+
Add a marketplace from GitHub (owner/repo):
|
|
60
|
+
mcpick marketplace add spences10/claude-code-toolkit
|
|
61
|
+
|
|
62
|
+
Add a marketplace from a full URL:
|
|
63
|
+
mcpick marketplace add https://github.com/spences10/claude-code-toolkit
|
|
64
|
+
|
|
65
|
+
Install a plugin from a marketplace:
|
|
66
|
+
mcpick plugins install my-plugin@claude-code-toolkit
|
|
67
|
+
|
|
68
|
+
List all installed plugins and their status:
|
|
69
|
+
mcpick plugins list
|
|
70
|
+
|
|
71
|
+
Toggle an MCP server on or off:
|
|
72
|
+
mcpick enable my-server
|
|
73
|
+
mcpick disable my-server
|
|
74
|
+
|
|
75
|
+
List all MCP servers:
|
|
76
|
+
mcpick list
|
|
77
|
+
|
|
78
|
+
All commands support --json for machine-readable output.
|
|
79
|
+
Run without arguments to launch the interactive TUI (not suitable for LLM agents).`;
|
|
80
|
+
const run = () => runMain(main, { showUsage: show_usage_with_examples });
|
|
81
|
+
//#endregion
|
|
82
|
+
export { run };
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=cli-DNNZjJYL.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { n as validate_mcp_server } from "./validation-xMlbgGCF.js";
|
|
2
|
+
import { t as add_server_to_registry } from "./registry-CfUKT7_C.js";
|
|
3
|
+
import { t as add_mcp_via_cli } from "./claude-cli-BeA-bmoW.js";
|
|
4
|
+
import { i as find_server_in_scope, r as detect_server_scope } from "./config-DijVdEFn.js";
|
|
5
|
+
import { n as output, t as error } from "./output-BchYq0mR.js";
|
|
6
|
+
import { t as redact_server } from "./redact-O35tjnRD.js";
|
|
7
|
+
import { defineCommand } from "citty";
|
|
8
|
+
//#region src/cli/commands/clone.ts
|
|
9
|
+
var clone_default = defineCommand({
|
|
10
|
+
meta: {
|
|
11
|
+
name: "clone",
|
|
12
|
+
description: "Clone an existing MCP server config with a new name, optionally overriding command/args"
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
source: {
|
|
16
|
+
type: "positional",
|
|
17
|
+
description: "Source server name to clone from",
|
|
18
|
+
required: true
|
|
19
|
+
},
|
|
20
|
+
name: {
|
|
21
|
+
type: "positional",
|
|
22
|
+
description: "New server name",
|
|
23
|
+
required: true
|
|
24
|
+
},
|
|
25
|
+
command: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Override command (e.g. \"node\" for local dev)"
|
|
28
|
+
},
|
|
29
|
+
args: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Override comma-separated arguments"
|
|
32
|
+
},
|
|
33
|
+
scope: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Scope for new server (default: same as source)"
|
|
36
|
+
},
|
|
37
|
+
json: {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
description: "Output as JSON",
|
|
40
|
+
default: false
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
async run({ args }) {
|
|
44
|
+
if (args.scope && ![
|
|
45
|
+
"local",
|
|
46
|
+
"project",
|
|
47
|
+
"user"
|
|
48
|
+
].includes(args.scope)) error(`Invalid scope: ${args.scope}. Use local, project, or user.`);
|
|
49
|
+
const scope = args.scope;
|
|
50
|
+
let found;
|
|
51
|
+
if (scope) found = await find_server_in_scope(args.source, scope);
|
|
52
|
+
else found = await detect_server_scope(args.source);
|
|
53
|
+
if (!found) error(`Server '${args.source}' not found${scope ? ` in ${scope} scope` : " in any scope"}`);
|
|
54
|
+
const target_scope = args.scope || found.scope;
|
|
55
|
+
const cloned = {
|
|
56
|
+
...found.server,
|
|
57
|
+
name: args.name
|
|
58
|
+
};
|
|
59
|
+
if (args.command) {
|
|
60
|
+
cloned.command = args.command;
|
|
61
|
+
delete cloned.url;
|
|
62
|
+
if (cloned.type === "sse" || cloned.type === "http") delete cloned.type;
|
|
63
|
+
}
|
|
64
|
+
if (args.args) cloned.args = args.args.split(",");
|
|
65
|
+
let server;
|
|
66
|
+
try {
|
|
67
|
+
server = validate_mcp_server(cloned);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
error(`Invalid cloned config: ${err instanceof Error ? err.message : "validation failed"}`);
|
|
70
|
+
}
|
|
71
|
+
await add_server_to_registry(server);
|
|
72
|
+
const result = await add_mcp_via_cli(server, target_scope);
|
|
73
|
+
if (args.json) output({
|
|
74
|
+
cloned: server.name,
|
|
75
|
+
from: args.source,
|
|
76
|
+
scope: target_scope,
|
|
77
|
+
server: redact_server(server),
|
|
78
|
+
cli: result.success,
|
|
79
|
+
error: result.error
|
|
80
|
+
}, true);
|
|
81
|
+
else if (result.success) console.log(`Cloned '${args.source}' → '${server.name}' (scope: ${target_scope})`);
|
|
82
|
+
else console.log(`Cloned '${args.source}' → '${server.name}' to registry but CLI failed: ${result.error}`);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//#endregion
|
|
86
|
+
export { clone_default as default };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=clone-DLFLewBY.js.map
|