mcpick 0.0.17 → 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 +15 -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 -303
- 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/dev.js +0 -161
- 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 -63
- 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 -28
- 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 -146
- package/dist/core/dev-override.js +0 -210
- 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 -483
- package/dist/utils/paths.js +0 -114
package/dist/core/registry.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { access, readdir, readFile, writeFile, } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { ensure_directory_exists, get_backups_dir, get_mcpick_dir, get_server_registry_path, } from '../utils/paths.js';
|
|
4
|
-
import { validate_server_registry } from './validation.js';
|
|
5
|
-
export async function read_server_registry() {
|
|
6
|
-
const registry_path = get_server_registry_path();
|
|
7
|
-
try {
|
|
8
|
-
await access(registry_path);
|
|
9
|
-
const registry_content = await readFile(registry_path, 'utf-8');
|
|
10
|
-
const parsed_registry = JSON.parse(registry_content);
|
|
11
|
-
return validate_server_registry(parsed_registry);
|
|
12
|
-
}
|
|
13
|
-
catch (error) {
|
|
14
|
-
if (error instanceof Error &&
|
|
15
|
-
'code' in error &&
|
|
16
|
-
error.code === 'ENOENT') {
|
|
17
|
-
await ensure_directory_exists(get_mcpick_dir());
|
|
18
|
-
const default_registry = { servers: [] };
|
|
19
|
-
await write_server_registry(default_registry);
|
|
20
|
-
return default_registry;
|
|
21
|
-
}
|
|
22
|
-
throw error;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
export async function write_server_registry(registry) {
|
|
26
|
-
const registry_path = get_server_registry_path();
|
|
27
|
-
await ensure_directory_exists(get_mcpick_dir());
|
|
28
|
-
const registry_content = JSON.stringify(registry, null, 2);
|
|
29
|
-
await writeFile(registry_path, registry_content, 'utf-8');
|
|
30
|
-
}
|
|
31
|
-
export async function add_server_to_registry(server) {
|
|
32
|
-
const registry = await read_server_registry();
|
|
33
|
-
const existing_index = registry.servers.findIndex((s) => s.name === server.name);
|
|
34
|
-
if (existing_index >= 0) {
|
|
35
|
-
registry.servers[existing_index] = server;
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
registry.servers.push(server);
|
|
39
|
-
}
|
|
40
|
-
await write_server_registry(registry);
|
|
41
|
-
}
|
|
42
|
-
export async function get_all_available_servers() {
|
|
43
|
-
const { get_enabled_servers, read_claude_config } = await import('./config.js');
|
|
44
|
-
const registry = await read_server_registry();
|
|
45
|
-
const config = await read_claude_config();
|
|
46
|
-
const config_servers = get_enabled_servers(config);
|
|
47
|
-
// Merge: config is the live truth, so update registry entries with config data
|
|
48
|
-
const config_by_name = new Map(config_servers.map((s) => [s.name, s]));
|
|
49
|
-
const known_names = new Set();
|
|
50
|
-
let registry_updated = false;
|
|
51
|
-
for (let i = 0; i < registry.servers.length; i++) {
|
|
52
|
-
const name = registry.servers[i].name;
|
|
53
|
-
known_names.add(name);
|
|
54
|
-
const config_server = config_by_name.get(name);
|
|
55
|
-
if (config_server) {
|
|
56
|
-
registry.servers[i] = config_server;
|
|
57
|
-
registry_updated = true;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
for (const server of config_servers) {
|
|
61
|
-
if (!known_names.has(server.name)) {
|
|
62
|
-
registry.servers.push(server);
|
|
63
|
-
registry_updated = true;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// Persist updated data back to registry so it survives disable/enable cycles
|
|
67
|
-
if (registry_updated) {
|
|
68
|
-
await write_server_registry(registry);
|
|
69
|
-
}
|
|
70
|
-
return registry.servers;
|
|
71
|
-
}
|
|
72
|
-
export async function sync_servers_to_registry(servers) {
|
|
73
|
-
const registry = await read_server_registry();
|
|
74
|
-
servers.forEach((server) => {
|
|
75
|
-
const existing_index = registry.servers.findIndex((s) => s.name === server.name);
|
|
76
|
-
if (existing_index >= 0) {
|
|
77
|
-
registry.servers[existing_index] = server;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
registry.servers.push(server);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
await write_server_registry(registry);
|
|
84
|
-
}
|
|
85
|
-
function parse_backups(prefix, pattern) {
|
|
86
|
-
return async () => {
|
|
87
|
-
const backups_dir = get_backups_dir();
|
|
88
|
-
try {
|
|
89
|
-
await access(backups_dir);
|
|
90
|
-
const files = await readdir(backups_dir);
|
|
91
|
-
const backup_files = files
|
|
92
|
-
.filter((file) => file.startsWith(prefix) && file.endsWith('.json'))
|
|
93
|
-
.map((file) => {
|
|
94
|
-
const timestamp_match = file.match(pattern);
|
|
95
|
-
if (!timestamp_match)
|
|
96
|
-
return null;
|
|
97
|
-
const [, year, month, day, hour, minute, second] = timestamp_match;
|
|
98
|
-
const timestamp = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
99
|
-
return {
|
|
100
|
-
filename: file,
|
|
101
|
-
timestamp,
|
|
102
|
-
path: join(backups_dir, file),
|
|
103
|
-
};
|
|
104
|
-
})
|
|
105
|
-
.filter((backup) => backup !== null)
|
|
106
|
-
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
|
107
|
-
return backup_files;
|
|
108
|
-
}
|
|
109
|
-
catch (error) {
|
|
110
|
-
if (error instanceof Error &&
|
|
111
|
-
'code' in error &&
|
|
112
|
-
error.code === 'ENOENT') {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
export const list_backups = parse_backups('mcp-servers-', /mcp-servers-(\d{4})-(\d{2})-(\d{2})-(\d{2})(\d{2})(\d{2})\.json/);
|
|
120
|
-
export const list_plugin_backups = parse_backups('plugins-', /plugins-(\d{4})-(\d{2})-(\d{2})-(\d{2})(\d{2})(\d{2})\.json/);
|
|
121
|
-
//# sourceMappingURL=registry.js.map
|
package/dist/core/settings.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { access, readFile } from 'node:fs/promises';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
3
|
-
import { atomic_json_write } from '../utils/atomic-write.js';
|
|
4
|
-
import { get_claude_settings_path } from '../utils/paths.js';
|
|
5
|
-
export async function read_claude_settings() {
|
|
6
|
-
const settings_path = get_claude_settings_path();
|
|
7
|
-
try {
|
|
8
|
-
await access(settings_path);
|
|
9
|
-
const content = await readFile(settings_path, 'utf-8');
|
|
10
|
-
return JSON.parse(content);
|
|
11
|
-
}
|
|
12
|
-
catch (error) {
|
|
13
|
-
if (error instanceof Error &&
|
|
14
|
-
'code' in error &&
|
|
15
|
-
error.code === 'ENOENT') {
|
|
16
|
-
return {};
|
|
17
|
-
}
|
|
18
|
-
throw error;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export async function write_claude_settings(updates) {
|
|
22
|
-
await atomic_json_write(get_claude_settings_path(), (existing) => {
|
|
23
|
-
for (const [key, value] of Object.entries(updates)) {
|
|
24
|
-
existing[key] = value;
|
|
25
|
-
}
|
|
26
|
-
return existing;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Parse enabledPlugins into structured list.
|
|
31
|
-
* Keys are in format "plugin-name@marketplace-name"
|
|
32
|
-
*/
|
|
33
|
-
export function get_all_plugins(settings) {
|
|
34
|
-
const enabled_plugins = settings.enabledPlugins || {};
|
|
35
|
-
return Object.entries(enabled_plugins).map(([key, enabled]) => {
|
|
36
|
-
const at_index = key.lastIndexOf('@');
|
|
37
|
-
const name = at_index > 0 ? key.substring(0, at_index) : key;
|
|
38
|
-
const marketplace = at_index > 0 ? key.substring(at_index + 1) : 'unknown';
|
|
39
|
-
return { name, marketplace, enabled };
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Build the enabledPlugins record from a list of PluginInfo
|
|
44
|
-
*/
|
|
45
|
-
export function build_enabled_plugins(plugins) {
|
|
46
|
-
const result = {};
|
|
47
|
-
for (const plugin of plugins) {
|
|
48
|
-
const key = `${plugin.name}@${plugin.marketplace}`;
|
|
49
|
-
result[key] = plugin.enabled;
|
|
50
|
-
}
|
|
51
|
-
return result;
|
|
52
|
-
}
|
|
53
|
-
async function read_settings_file(path) {
|
|
54
|
-
try {
|
|
55
|
-
await access(path);
|
|
56
|
-
const content = await readFile(path, 'utf-8');
|
|
57
|
-
return JSON.parse(content);
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return {};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function get_settings_paths() {
|
|
64
|
-
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
65
|
-
return [
|
|
66
|
-
{
|
|
67
|
-
scope: 'user',
|
|
68
|
-
path: resolve(home, '.claude', 'settings.json'),
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
scope: 'project',
|
|
72
|
-
path: resolve(process.cwd(), '.claude', 'settings.json'),
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
scope: 'project-local',
|
|
76
|
-
path: resolve(process.cwd(), '.claude', 'settings.local.json'),
|
|
77
|
-
},
|
|
78
|
-
];
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Read all hooks across all scopes (settings + plugins), flattened for display.
|
|
82
|
-
*/
|
|
83
|
-
export async function get_all_hooks() {
|
|
84
|
-
const entries = [];
|
|
85
|
-
// Settings-based hooks
|
|
86
|
-
for (const { scope, path } of get_settings_paths()) {
|
|
87
|
-
const data = await read_settings_file(path);
|
|
88
|
-
const hooks = data.hooks;
|
|
89
|
-
if (!hooks)
|
|
90
|
-
continue;
|
|
91
|
-
for (const [event, matchers] of Object.entries(hooks)) {
|
|
92
|
-
if (!Array.isArray(matchers))
|
|
93
|
-
continue;
|
|
94
|
-
for (let mi = 0; mi < matchers.length; mi++) {
|
|
95
|
-
const m = matchers[mi];
|
|
96
|
-
if (!m.hooks?.length)
|
|
97
|
-
continue;
|
|
98
|
-
for (let hi = 0; hi < m.hooks.length; hi++) {
|
|
99
|
-
entries.push({
|
|
100
|
-
event: event,
|
|
101
|
-
matcher: m.matcher,
|
|
102
|
-
handler: m.hooks[hi],
|
|
103
|
-
scope,
|
|
104
|
-
source: scope,
|
|
105
|
-
matcher_index: mi,
|
|
106
|
-
hook_index: hi,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Plugin-based hooks
|
|
113
|
-
const plugin_hooks = await get_all_plugin_hooks();
|
|
114
|
-
entries.push(...plugin_hooks);
|
|
115
|
-
return entries;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Scan all installed plugins for hooks.json and return flattened hook entries.
|
|
119
|
-
* Checks both cache and marketplace source paths since Claude Code reads from both.
|
|
120
|
-
*/
|
|
121
|
-
export async function get_all_plugin_hooks() {
|
|
122
|
-
const { read_installed_plugins } = await import('./plugin-cache.js');
|
|
123
|
-
const { get_marketplaces_dir } = await import('../utils/paths.js');
|
|
124
|
-
const installed = await read_installed_plugins();
|
|
125
|
-
const entries = [];
|
|
126
|
-
const seen_hooks = new Set();
|
|
127
|
-
for (const [plugin_key, installs] of Object.entries(installed.plugins)) {
|
|
128
|
-
if (!installs?.length)
|
|
129
|
-
continue;
|
|
130
|
-
const install = installs[0];
|
|
131
|
-
const at_index = plugin_key.lastIndexOf('@');
|
|
132
|
-
const plugin_name = at_index > 0 ? plugin_key.substring(0, at_index) : plugin_key;
|
|
133
|
-
const marketplace_name = at_index > 0 ? plugin_key.substring(at_index + 1) : '';
|
|
134
|
-
// Collect all hooks.json paths for this plugin (cache + marketplace source)
|
|
135
|
-
const hooks_paths = [
|
|
136
|
-
join(install.installPath, 'hooks', 'hooks.json'),
|
|
137
|
-
];
|
|
138
|
-
// Also check marketplace source path
|
|
139
|
-
if (marketplace_name) {
|
|
140
|
-
hooks_paths.push(join(get_marketplaces_dir(), marketplace_name, 'plugins', plugin_name, 'hooks', 'hooks.json'));
|
|
141
|
-
}
|
|
142
|
-
for (const hooks_path of hooks_paths) {
|
|
143
|
-
let hooks_data;
|
|
144
|
-
try {
|
|
145
|
-
const content = await readFile(hooks_path, 'utf-8');
|
|
146
|
-
hooks_data = JSON.parse(content);
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
const hooks = (hooks_data.hooks || hooks_data);
|
|
152
|
-
for (const [event, matchers] of Object.entries(hooks)) {
|
|
153
|
-
if (!Array.isArray(matchers))
|
|
154
|
-
continue;
|
|
155
|
-
for (let mi = 0; mi < matchers.length; mi++) {
|
|
156
|
-
const m = matchers[mi];
|
|
157
|
-
if (!m.hooks?.length)
|
|
158
|
-
continue;
|
|
159
|
-
for (let hi = 0; hi < m.hooks.length; hi++) {
|
|
160
|
-
// Deduplicate: same plugin + event + handler type + command
|
|
161
|
-
const h = m.hooks[hi];
|
|
162
|
-
const dedup_key = `${plugin_key}:${event}:${h.type}:${h.command || h.url || h.prompt}`;
|
|
163
|
-
if (seen_hooks.has(dedup_key))
|
|
164
|
-
continue;
|
|
165
|
-
seen_hooks.add(dedup_key);
|
|
166
|
-
entries.push({
|
|
167
|
-
event: event,
|
|
168
|
-
matcher: m.matcher,
|
|
169
|
-
handler: h,
|
|
170
|
-
scope: 'user',
|
|
171
|
-
source: 'plugin',
|
|
172
|
-
matcher_index: mi,
|
|
173
|
-
hook_index: hi,
|
|
174
|
-
plugin_key,
|
|
175
|
-
hooks_json_path: hooks_path,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return entries;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Remove a specific hook entry by scope/event/indices.
|
|
186
|
-
*/
|
|
187
|
-
export async function remove_hook(entry) {
|
|
188
|
-
const scope_path = get_settings_paths().find((s) => s.scope === entry.scope);
|
|
189
|
-
if (!scope_path)
|
|
190
|
-
throw new Error(`Unknown scope: ${entry.scope}`);
|
|
191
|
-
await atomic_json_write(scope_path.path, (existing) => {
|
|
192
|
-
const hooks = existing.hooks;
|
|
193
|
-
if (!hooks)
|
|
194
|
-
return existing;
|
|
195
|
-
const matchers = hooks[entry.event];
|
|
196
|
-
if (!matchers?.[entry.matcher_index])
|
|
197
|
-
return existing;
|
|
198
|
-
const matcher = matchers[entry.matcher_index];
|
|
199
|
-
matcher.hooks.splice(entry.hook_index, 1);
|
|
200
|
-
// Clean up empty matchers
|
|
201
|
-
if (matcher.hooks.length === 0) {
|
|
202
|
-
matchers.splice(entry.matcher_index, 1);
|
|
203
|
-
}
|
|
204
|
-
// Clean up empty events
|
|
205
|
-
if (matchers.length === 0) {
|
|
206
|
-
delete hooks[entry.event];
|
|
207
|
-
}
|
|
208
|
-
// Clean up empty hooks object
|
|
209
|
-
if (Object.keys(hooks).length === 0) {
|
|
210
|
-
delete existing.hooks;
|
|
211
|
-
}
|
|
212
|
-
return existing;
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Add a hook to a specific scope.
|
|
217
|
-
*/
|
|
218
|
-
export async function add_hook(scope, event, matcher, handler) {
|
|
219
|
-
const scope_path = get_settings_paths().find((s) => s.scope === scope);
|
|
220
|
-
if (!scope_path)
|
|
221
|
-
throw new Error(`Unknown scope: ${scope}`);
|
|
222
|
-
await atomic_json_write(scope_path.path, (existing) => {
|
|
223
|
-
if (!existing.hooks)
|
|
224
|
-
existing.hooks = {};
|
|
225
|
-
const hooks = existing.hooks;
|
|
226
|
-
if (!hooks[event])
|
|
227
|
-
hooks[event] = [];
|
|
228
|
-
const matchers = hooks[event];
|
|
229
|
-
// Find existing matcher group or create new
|
|
230
|
-
const existing_matcher = matchers.find((m) => (m.matcher || undefined) === matcher);
|
|
231
|
-
if (existing_matcher) {
|
|
232
|
-
existing_matcher.hooks.push(handler);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
const new_matcher = { hooks: [handler] };
|
|
236
|
-
if (matcher)
|
|
237
|
-
new_matcher.matcher = matcher;
|
|
238
|
-
matchers.push(new_matcher);
|
|
239
|
-
}
|
|
240
|
-
return existing;
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
//# sourceMappingURL=settings.js.map
|
package/dist/core/validation.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import * as v from 'valibot';
|
|
2
|
-
export const mcp_server_schema_stdio = v.object({
|
|
3
|
-
type: v.optional(v.literal('stdio')),
|
|
4
|
-
command: v.pipe(v.string(), v.minLength(1)),
|
|
5
|
-
args: v.optional(v.array(v.string())),
|
|
6
|
-
env: v.optional(v.record(v.string(), v.string())),
|
|
7
|
-
description: v.optional(v.string()),
|
|
8
|
-
});
|
|
9
|
-
export const mcp_server_schema_sse = v.object({
|
|
10
|
-
type: v.literal('sse'),
|
|
11
|
-
env: v.optional(v.record(v.string(), v.string())),
|
|
12
|
-
url: v.pipe(v.string(), v.minLength(1)),
|
|
13
|
-
headers: v.optional(v.record(v.string(), v.string())),
|
|
14
|
-
description: v.optional(v.string()),
|
|
15
|
-
});
|
|
16
|
-
export const mcp_server_schema_http = v.object({
|
|
17
|
-
type: v.literal('http'),
|
|
18
|
-
env: v.optional(v.record(v.string(), v.string())),
|
|
19
|
-
url: v.pipe(v.string(), v.minLength(1)),
|
|
20
|
-
headers: v.optional(v.record(v.string(), v.string())),
|
|
21
|
-
description: v.optional(v.string()),
|
|
22
|
-
});
|
|
23
|
-
export const mcp_server_schema_base = v.union([
|
|
24
|
-
mcp_server_schema_stdio,
|
|
25
|
-
mcp_server_schema_sse,
|
|
26
|
-
mcp_server_schema_http,
|
|
27
|
-
]);
|
|
28
|
-
export const mcp_server_schema = v.intersect([
|
|
29
|
-
v.object({
|
|
30
|
-
name: v.pipe(v.string(), v.minLength(1)),
|
|
31
|
-
}),
|
|
32
|
-
mcp_server_schema_base,
|
|
33
|
-
]);
|
|
34
|
-
export const claude_config_schema = v.object({
|
|
35
|
-
mcpServers: v.optional(v.record(v.string(), mcp_server_schema_base)),
|
|
36
|
-
});
|
|
37
|
-
export const server_registry_schema = v.object({
|
|
38
|
-
servers: v.array(mcp_server_schema),
|
|
39
|
-
});
|
|
40
|
-
export function validate_mcp_server(data) {
|
|
41
|
-
return v.parse(mcp_server_schema, data);
|
|
42
|
-
}
|
|
43
|
-
export function validate_claude_config(data) {
|
|
44
|
-
return v.parse(claude_config_schema, data);
|
|
45
|
-
}
|
|
46
|
-
export function validate_server_registry(data) {
|
|
47
|
-
return v.parse(server_registry_schema, data);
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=validation.js.map
|
package/dist/types.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { readFile, rename, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
3
|
-
/**
|
|
4
|
-
* Atomically write a JSON file with fresh-read merging.
|
|
5
|
-
*
|
|
6
|
-
* 1. Re-reads the file right before writing to pick up concurrent changes
|
|
7
|
-
* 2. Applies the merge function to the freshest data
|
|
8
|
-
* 3. Writes to a temp file, then renames (atomic on same filesystem)
|
|
9
|
-
*/
|
|
10
|
-
export async function atomic_json_write(file_path, merge) {
|
|
11
|
-
// Read the freshest version right before writing
|
|
12
|
-
let existing = {};
|
|
13
|
-
try {
|
|
14
|
-
const content = await readFile(file_path, 'utf-8');
|
|
15
|
-
existing = JSON.parse(content);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
// File doesn't exist or invalid — start fresh
|
|
19
|
-
}
|
|
20
|
-
const merged = merge(existing);
|
|
21
|
-
const content = JSON.stringify(merged, null, 2);
|
|
22
|
-
// Write to temp file then rename for atomicity
|
|
23
|
-
const tmp_path = join(dirname(file_path), `.${Date.now()}.tmp`);
|
|
24
|
-
await writeFile(tmp_path, content, 'utf-8');
|
|
25
|
-
await rename(tmp_path, file_path);
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=atomic-write.js.map
|