mcpick 0.0.10 → 0.0.11
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/CHANGELOG.md +10 -0
- package/README.md +114 -4
- package/dist/cli/commands/backup.js +50 -22
- package/dist/cli/commands/plugins.js +110 -1
- package/dist/cli/commands/profile.js +31 -9
- package/dist/cli/commands/restore.js +75 -26
- package/dist/commands/backup.js +28 -22
- package/dist/commands/edit-plugins.js +192 -47
- package/dist/commands/restore.js +85 -34
- package/dist/core/profile.js +32 -8
- package/dist/core/registry.js +34 -30
- package/dist/index.js +48 -19
- package/dist/utils/claude-cli.js +69 -0
- package/dist/utils/paths.js +8 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { manage_cache } from './commands/manage-cache.js';
|
|
|
8
8
|
import { restore_config } from './commands/restore.js';
|
|
9
9
|
import { write_claude_config } from './core/config.js';
|
|
10
10
|
import { list_profiles, load_profile, save_profile, } from './core/profile.js';
|
|
11
|
+
import { write_claude_settings } from './core/settings.js';
|
|
11
12
|
function parse_args() {
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
const result = {};
|
|
@@ -29,10 +30,17 @@ function parse_args() {
|
|
|
29
30
|
async function apply_profile(name) {
|
|
30
31
|
intro(`MCPick - Loading profile: ${name}`);
|
|
31
32
|
try {
|
|
32
|
-
const
|
|
33
|
-
await write_claude_config(
|
|
34
|
-
const server_count = Object.keys(
|
|
35
|
-
|
|
33
|
+
const profile = await load_profile(name);
|
|
34
|
+
await write_claude_config(profile.config);
|
|
35
|
+
const server_count = Object.keys(profile.config.mcpServers || {}).length;
|
|
36
|
+
const parts = [`${server_count} servers`];
|
|
37
|
+
if (profile.enabledPlugins) {
|
|
38
|
+
await write_claude_settings({
|
|
39
|
+
enabledPlugins: profile.enabledPlugins,
|
|
40
|
+
});
|
|
41
|
+
parts.push(`${Object.keys(profile.enabledPlugins).length} plugins`);
|
|
42
|
+
}
|
|
43
|
+
log.success(`Profile '${name}' applied (${parts.join(', ')})`);
|
|
36
44
|
outro('Done!');
|
|
37
45
|
}
|
|
38
46
|
catch (error) {
|
|
@@ -62,8 +70,12 @@ async function show_profiles() {
|
|
|
62
70
|
async function create_profile(name) {
|
|
63
71
|
intro(`MCPick - Saving profile: ${name}`);
|
|
64
72
|
try {
|
|
65
|
-
const
|
|
66
|
-
|
|
73
|
+
const counts = await save_profile(name);
|
|
74
|
+
const parts = [`${counts.serverCount} servers`];
|
|
75
|
+
if (counts.pluginCount > 0) {
|
|
76
|
+
parts.push(`${counts.pluginCount} plugins`);
|
|
77
|
+
}
|
|
78
|
+
log.success(`Profile '${name}' saved (${parts.join(', ')})`);
|
|
67
79
|
outro('Done!');
|
|
68
80
|
}
|
|
69
81
|
catch (error) {
|
|
@@ -85,18 +97,31 @@ async function handle_load_profile() {
|
|
|
85
97
|
}
|
|
86
98
|
const profile_name = await select({
|
|
87
99
|
message: 'Select a profile to load:',
|
|
88
|
-
options: profiles.map((p) =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
options: profiles.map((p) => {
|
|
101
|
+
const parts = [`${p.serverCount} servers`];
|
|
102
|
+
if (p.pluginCount > 0) {
|
|
103
|
+
parts.push(`${p.pluginCount} plugins`);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
value: p.name,
|
|
107
|
+
label: p.name,
|
|
108
|
+
hint: parts.join(', '),
|
|
109
|
+
};
|
|
110
|
+
}),
|
|
93
111
|
});
|
|
94
112
|
if (isCancel(profile_name))
|
|
95
113
|
return;
|
|
96
|
-
const
|
|
97
|
-
await write_claude_config(
|
|
98
|
-
const server_count = Object.keys(
|
|
99
|
-
|
|
114
|
+
const profile = await load_profile(profile_name);
|
|
115
|
+
await write_claude_config(profile.config);
|
|
116
|
+
const server_count = Object.keys(profile.config.mcpServers || {}).length;
|
|
117
|
+
const parts = [`${server_count} servers`];
|
|
118
|
+
if (profile.enabledPlugins) {
|
|
119
|
+
await write_claude_settings({
|
|
120
|
+
enabledPlugins: profile.enabledPlugins,
|
|
121
|
+
});
|
|
122
|
+
parts.push(`${Object.keys(profile.enabledPlugins).length} plugins`);
|
|
123
|
+
}
|
|
124
|
+
log.success(`Profile '${profile_name}' applied (${parts.join(', ')})`);
|
|
100
125
|
}
|
|
101
126
|
async function handle_save_profile() {
|
|
102
127
|
const name = await text({
|
|
@@ -113,8 +138,12 @@ async function handle_save_profile() {
|
|
|
113
138
|
});
|
|
114
139
|
if (isCancel(name))
|
|
115
140
|
return;
|
|
116
|
-
const
|
|
117
|
-
|
|
141
|
+
const counts = await save_profile(name);
|
|
142
|
+
const parts = [`${counts.serverCount} servers`];
|
|
143
|
+
if (counts.pluginCount > 0) {
|
|
144
|
+
parts.push(`${counts.pluginCount} plugins`);
|
|
145
|
+
}
|
|
146
|
+
log.success(`Profile '${name}' saved (${parts.join(', ')})`);
|
|
118
147
|
}
|
|
119
148
|
async function main() {
|
|
120
149
|
const args = parse_args();
|
|
@@ -146,8 +175,8 @@ async function main() {
|
|
|
146
175
|
},
|
|
147
176
|
{
|
|
148
177
|
value: 'edit-plugins',
|
|
149
|
-
label: '
|
|
150
|
-
hint: 'Toggle
|
|
178
|
+
label: 'Manage plugins',
|
|
179
|
+
hint: 'Toggle, install, uninstall, or update plugins',
|
|
151
180
|
},
|
|
152
181
|
{
|
|
153
182
|
value: 'manage-cache',
|
package/dist/utils/claude-cli.js
CHANGED
|
@@ -115,6 +115,75 @@ export async function remove_mcp_via_cli(name) {
|
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Install a plugin via Claude CLI
|
|
120
|
+
*/
|
|
121
|
+
export async function install_plugin_via_cli(key, scope = 'user') {
|
|
122
|
+
const cli_available = await check_claude_cli();
|
|
123
|
+
if (!cli_available) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
await execAsync(`claude plugin install ${shell_escape(key)} --scope ${scope}`);
|
|
131
|
+
return { success: true };
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
error: `Failed to install plugin: ${message}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Uninstall a plugin via Claude CLI
|
|
143
|
+
*/
|
|
144
|
+
export async function uninstall_plugin_via_cli(key, scope = 'user') {
|
|
145
|
+
const cli_available = await check_claude_cli();
|
|
146
|
+
if (!cli_available) {
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
await execAsync(`claude plugin uninstall ${shell_escape(key)} --scope ${scope}`);
|
|
154
|
+
return { success: true };
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
158
|
+
return {
|
|
159
|
+
success: false,
|
|
160
|
+
error: `Failed to uninstall plugin: ${message}`,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Update a plugin via Claude CLI
|
|
166
|
+
*/
|
|
167
|
+
export async function update_plugin_via_cli(key, scope = 'user') {
|
|
168
|
+
const cli_available = await check_claude_cli();
|
|
169
|
+
if (!cli_available) {
|
|
170
|
+
return {
|
|
171
|
+
success: false,
|
|
172
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
await execAsync(`claude plugin update ${shell_escape(key)} --scope ${scope}`);
|
|
177
|
+
return { success: true };
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
181
|
+
return {
|
|
182
|
+
success: false,
|
|
183
|
+
error: `Failed to update plugin: ${message}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
118
187
|
/**
|
|
119
188
|
* Get the scope description for display
|
|
120
189
|
*/
|
package/dist/utils/paths.js
CHANGED
|
@@ -45,7 +45,7 @@ export function get_profile_path(name) {
|
|
|
45
45
|
const filename = name.endsWith('.json') ? name : `${name}.json`;
|
|
46
46
|
return join(get_profiles_dir(), filename);
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
function format_backup_timestamp() {
|
|
49
49
|
const now = new Date();
|
|
50
50
|
const year = now.getFullYear();
|
|
51
51
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
@@ -53,7 +53,13 @@ export function get_backup_filename() {
|
|
|
53
53
|
const hour = String(now.getHours()).padStart(2, '0');
|
|
54
54
|
const minute = String(now.getMinutes()).padStart(2, '0');
|
|
55
55
|
const second = String(now.getSeconds()).padStart(2, '0');
|
|
56
|
-
return
|
|
56
|
+
return `${year}-${month}-${day}-${hour}${minute}${second}`;
|
|
57
|
+
}
|
|
58
|
+
export function get_backup_filename() {
|
|
59
|
+
return `mcp-servers-${format_backup_timestamp()}.json`;
|
|
60
|
+
}
|
|
61
|
+
export function get_plugin_backup_filename() {
|
|
62
|
+
return `plugins-${format_backup_timestamp()}.json`;
|
|
57
63
|
}
|
|
58
64
|
export async function ensure_directory_exists(dir_path) {
|
|
59
65
|
try {
|