@ebowwa/claude-code-config-mcp 1.0.0

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/src/index.js ADDED
@@ -0,0 +1,2171 @@
1
+ #!/usr/bin/env bun
2
+ "use strict";
3
+ // ============================================================================
4
+ // Claude Code Config MCP Server
5
+ // ============================================================================
6
+ // Manage Claude Code configuration files with atomic writes, validation,
7
+ // and comprehensive error handling.
8
+ // ============================================================================
9
+ var __assign = (this && this.__assign) || function () {
10
+ __assign = Object.assign || function(t) {
11
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
12
+ s = arguments[i];
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
14
+ t[p] = s[p];
15
+ }
16
+ return t;
17
+ };
18
+ return __assign.apply(this, arguments);
19
+ };
20
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
21
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
22
+ return new (P || (P = Promise))(function (resolve, reject) {
23
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
24
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
25
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
26
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
27
+ });
28
+ };
29
+ var __generator = (this && this.__generator) || function (thisArg, body) {
30
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
31
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
32
+ function verb(n) { return function (v) { return step([n, v]); }; }
33
+ function step(op) {
34
+ if (f) throw new TypeError("Generator is already executing.");
35
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
36
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
37
+ if (y = 0, t) op = [op[0] & 2, t.value];
38
+ switch (op[0]) {
39
+ case 0: case 1: t = op; break;
40
+ case 4: _.label++; return { value: op[1], done: false };
41
+ case 5: _.label++; y = op[1]; op = [0]; continue;
42
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
43
+ default:
44
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
45
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
46
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
47
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
48
+ if (t[2]) _.ops.pop();
49
+ _.trys.pop(); continue;
50
+ }
51
+ op = body.call(thisArg, _);
52
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
53
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
54
+ }
55
+ };
56
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
57
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
58
+ if (ar || !(i in from)) {
59
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
60
+ ar[i] = from[i];
61
+ }
62
+ }
63
+ return to.concat(ar || Array.prototype.slice.call(from));
64
+ };
65
+ Object.defineProperty(exports, "__esModule", { value: true });
66
+ var index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
67
+ var stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
68
+ var types_js_1 = require("@modelcontextprotocol/sdk/types.js");
69
+ var zod_1 = require("zod");
70
+ var node_path_1 = require("node:path");
71
+ var path = require("./utils/path.js");
72
+ var path_js_1 = require("./utils/path.js");
73
+ var file = require("./utils/file.js");
74
+ var errors = require("./utils/errors.js");
75
+ // ============================================================================
76
+ // MCP Server Setup
77
+ // ============================================================================
78
+ var server = new index_js_1.Server({
79
+ name: '@mcp/claude-code-config',
80
+ version: '1.0.0',
81
+ }, {
82
+ capabilities: {
83
+ tools: {},
84
+ },
85
+ });
86
+ // ============================================================================
87
+ // Tool Definitions
88
+ // ============================================================================
89
+ /**
90
+ * List all available tools
91
+ */
92
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, function () { return __awaiter(void 0, void 0, void 0, function () {
93
+ return __generator(this, function (_a) {
94
+ return [2 /*return*/, ({
95
+ tools: [
96
+ // CLAUDE.md tools
97
+ {
98
+ name: 'read_global_claude_md',
99
+ description: 'Read the global CLAUDE.md file (~/.claude/CLAUDE.md)',
100
+ inputSchema: {
101
+ type: 'object',
102
+ properties: {},
103
+ },
104
+ },
105
+ {
106
+ name: 'write_global_claude_md',
107
+ description: 'Write to the global CLAUDE.md file (~/.claude/CLAUDE.md). Creates backup before writing.',
108
+ inputSchema: {
109
+ type: 'object',
110
+ properties: {
111
+ content: {
112
+ type: 'string',
113
+ description: 'Content to write to CLAUDE.md',
114
+ },
115
+ createBackup: {
116
+ type: 'boolean',
117
+ description: 'Create backup before writing (default: true)',
118
+ default: true,
119
+ },
120
+ },
121
+ required: ['content'],
122
+ },
123
+ },
124
+ {
125
+ name: 'read_project_claude_md',
126
+ description: 'Read the project-local CLAUDE.md file (.claude/CLAUDE.md)',
127
+ inputSchema: {
128
+ type: 'object',
129
+ properties: {
130
+ projectPath: {
131
+ type: 'string',
132
+ description: 'Project directory path (default: current working directory)',
133
+ },
134
+ },
135
+ },
136
+ },
137
+ {
138
+ name: 'write_project_claude_md',
139
+ description: 'Write to the project-local CLAUDE.md file (.claude/CLAUDE.md). Creates backup before writing.',
140
+ inputSchema: {
141
+ type: 'object',
142
+ properties: {
143
+ content: {
144
+ type: 'string',
145
+ description: 'Content to write to CLAUDE.md',
146
+ },
147
+ projectPath: {
148
+ type: 'string',
149
+ description: 'Project directory path (default: current working directory)',
150
+ },
151
+ createBackup: {
152
+ type: 'boolean',
153
+ description: 'Create backup before writing (default: true)',
154
+ default: true,
155
+ },
156
+ },
157
+ required: ['content'],
158
+ },
159
+ },
160
+ // Keybindings tools
161
+ {
162
+ name: 'read_keybindings',
163
+ description: 'Read the keybindings.json file',
164
+ inputSchema: {
165
+ type: 'object',
166
+ properties: {},
167
+ },
168
+ },
169
+ {
170
+ name: 'write_keybindings',
171
+ description: 'Write to keybindings.json. Validates the structure before writing.',
172
+ inputSchema: {
173
+ type: 'object',
174
+ properties: {
175
+ keybindings: {
176
+ type: 'object',
177
+ description: 'Keybindings configuration object',
178
+ },
179
+ createBackup: {
180
+ type: 'boolean',
181
+ description: 'Create backup before writing (default: true)',
182
+ default: true,
183
+ },
184
+ },
185
+ required: ['keybindings'],
186
+ },
187
+ },
188
+ {
189
+ name: 'add_keybinding',
190
+ description: 'Add or update a single keybinding',
191
+ inputSchema: {
192
+ type: 'object',
193
+ properties: {
194
+ key: {
195
+ type: 'string',
196
+ description: 'Key combination (e.g., "ctrl+s", "cmd+k")',
197
+ },
198
+ command: {
199
+ type: 'string',
200
+ description: 'Command to execute',
201
+ },
202
+ when: {
203
+ type: 'string',
204
+ description: 'Optional context condition',
205
+ },
206
+ },
207
+ required: ['key', 'command'],
208
+ },
209
+ },
210
+ {
211
+ name: 'remove_keybinding',
212
+ description: 'Remove a keybinding by key combination',
213
+ inputSchema: {
214
+ type: 'object',
215
+ properties: {
216
+ key: {
217
+ type: 'string',
218
+ description: 'Key combination to remove',
219
+ },
220
+ },
221
+ required: ['key'],
222
+ },
223
+ },
224
+ // Settings tools
225
+ {
226
+ name: 'read_settings',
227
+ description: 'Read the settings.json file',
228
+ inputSchema: {
229
+ type: 'object',
230
+ properties: {},
231
+ },
232
+ },
233
+ {
234
+ name: 'write_settings',
235
+ description: 'Write to settings.json',
236
+ inputSchema: {
237
+ type: 'object',
238
+ properties: {
239
+ settings: {
240
+ type: 'object',
241
+ description: 'Settings object',
242
+ },
243
+ createBackup: {
244
+ type: 'boolean',
245
+ description: 'Create backup before writing (default: true)',
246
+ default: true,
247
+ },
248
+ },
249
+ required: ['settings'],
250
+ },
251
+ },
252
+ // Hooks tools
253
+ {
254
+ name: 'list_hooks',
255
+ description: 'List all configured hooks',
256
+ inputSchema: {
257
+ type: 'object',
258
+ properties: {},
259
+ },
260
+ },
261
+ {
262
+ name: 'read_hook',
263
+ description: 'Read a specific hook file',
264
+ inputSchema: {
265
+ type: 'object',
266
+ properties: {
267
+ name: {
268
+ type: 'string',
269
+ description: 'Hook file name (without extension)',
270
+ },
271
+ },
272
+ required: ['name'],
273
+ },
274
+ },
275
+ {
276
+ name: 'write_hook',
277
+ description: 'Write or update a hook file',
278
+ inputSchema: {
279
+ type: 'object',
280
+ properties: {
281
+ name: {
282
+ type: 'string',
283
+ description: 'Hook file name',
284
+ },
285
+ event: {
286
+ type: 'string',
287
+ description: 'Hook event (SessionStart, SessionEnd, PreToolUse, PostToolUse, etc.)',
288
+ },
289
+ content: {
290
+ type: 'string',
291
+ description: 'Hook script content',
292
+ },
293
+ enabled: {
294
+ type: 'boolean',
295
+ description: 'Whether the hook is enabled',
296
+ default: true,
297
+ },
298
+ },
299
+ required: ['name', 'event', 'content'],
300
+ },
301
+ },
302
+ // Utility tools
303
+ {
304
+ name: 'list_config_files',
305
+ description: 'List all Claude Code config files with metadata',
306
+ inputSchema: {
307
+ type: 'object',
308
+ properties: {
309
+ includeProject: {
310
+ type: 'boolean',
311
+ description: 'Include project-local config files',
312
+ default: true,
313
+ },
314
+ },
315
+ },
316
+ },
317
+ {
318
+ name: 'get_config_path',
319
+ description: 'Get the path to a specific config file',
320
+ inputSchema: {
321
+ type: 'object',
322
+ properties: {
323
+ fileType: {
324
+ type: 'string',
325
+ enum: [
326
+ 'CLAUDE_MD_GLOBAL',
327
+ 'CLAUDE_MD_PROJECT',
328
+ 'KEYBINDINGS',
329
+ 'SETTINGS',
330
+ 'HOOKS_DIR',
331
+ ],
332
+ description: 'Type of config file',
333
+ },
334
+ },
335
+ required: ['fileType'],
336
+ },
337
+ },
338
+ {
339
+ name: 'backup_config',
340
+ description: 'Create a backup of a config file',
341
+ inputSchema: {
342
+ type: 'object',
343
+ properties: {
344
+ fileType: {
345
+ type: 'string',
346
+ enum: ['CLAUDE_MD', 'KEYBINDINGS', 'SETTINGS'],
347
+ description: 'Type of config file to backup',
348
+ },
349
+ },
350
+ required: ['fileType'],
351
+ },
352
+ },
353
+ // MCP Server management tools
354
+ {
355
+ name: 'mcp_list',
356
+ description: 'List all configured MCP servers from config files. Supports CLI (~/.claude.json) and app (~/.config/claude-code/config.json) configs.',
357
+ inputSchema: {
358
+ type: 'object',
359
+ properties: {
360
+ target: {
361
+ type: 'string',
362
+ enum: ['cli', 'app', 'both'],
363
+ description: 'Which config to read (default: both)',
364
+ default: 'both',
365
+ },
366
+ includeHealth: {
367
+ type: 'boolean',
368
+ description: 'Check server health status by running claude mcp list',
369
+ default: false,
370
+ },
371
+ },
372
+ },
373
+ },
374
+ {
375
+ name: 'mcp_get',
376
+ description: 'Get details about a specific MCP server from config files',
377
+ inputSchema: {
378
+ type: 'object',
379
+ properties: {
380
+ name: {
381
+ type: 'string',
382
+ description: 'MCP server name',
383
+ },
384
+ target: {
385
+ type: 'string',
386
+ enum: ['cli', 'app', 'both'],
387
+ description: 'Which config to read (default: both)',
388
+ default: 'both',
389
+ },
390
+ },
391
+ required: ['name'],
392
+ },
393
+ },
394
+ {
395
+ name: 'mcp_add',
396
+ description: 'Add a new MCP server configuration. Supports stdio, HTTP, SSE, and WebSocket transports. Can add to CLI config, app config, or both.',
397
+ inputSchema: {
398
+ type: 'object',
399
+ properties: {
400
+ name: {
401
+ type: 'string',
402
+ description: 'Unique name for the MCP server',
403
+ },
404
+ command: {
405
+ type: 'string',
406
+ description: 'Command to run (for stdio transport, e.g., "node", "bun", "npx")',
407
+ },
408
+ args: {
409
+ type: 'array',
410
+ items: { type: 'string' },
411
+ description: 'Arguments for the command (e.g., ["/path/to/server.js"])',
412
+ },
413
+ url: {
414
+ type: 'string',
415
+ description: 'URL for HTTP/SSE/WebSocket transport',
416
+ },
417
+ transport: {
418
+ type: 'string',
419
+ enum: ['stdio', 'sse', 'http', 'ws', 'websocket'],
420
+ description: 'Transport type (default: stdio)',
421
+ },
422
+ env: {
423
+ type: 'object',
424
+ additionalProperties: { type: 'string' },
425
+ description: 'Environment variables for the server',
426
+ },
427
+ headers: {
428
+ type: 'object',
429
+ additionalProperties: { type: 'string' },
430
+ description: 'HTTP headers for HTTP/SSE/WebSocket transport',
431
+ },
432
+ description: {
433
+ type: 'string',
434
+ description: 'Human-readable description of the server',
435
+ },
436
+ alwaysAllow: {
437
+ type: 'boolean',
438
+ description: 'Always allow this server (bypass project-scoped approval)',
439
+ },
440
+ timeout: {
441
+ type: 'number',
442
+ description: 'Timeout in milliseconds',
443
+ },
444
+ target: {
445
+ type: 'string',
446
+ enum: ['cli', 'app', 'both'],
447
+ description: 'Which config(s) to add to (default: both - adds to both CLI and app configs)',
448
+ default: 'both',
449
+ },
450
+ },
451
+ required: ['name'],
452
+ },
453
+ },
454
+ {
455
+ name: 'mcp_install',
456
+ description: 'Download and configure an MCP server from npm, GitHub, or a local path. Automatically detects configuration from package.json. Can add to CLI config, app config, or both.',
457
+ inputSchema: {
458
+ type: 'object',
459
+ properties: {
460
+ source: {
461
+ type: 'string',
462
+ enum: ['npm', 'github', 'local', 'url'],
463
+ description: 'Source type (auto-detected if not specified)',
464
+ },
465
+ package: {
466
+ type: 'string',
467
+ description: 'Package name (npm), repo URL (github), local path, or direct URL',
468
+ },
469
+ name: {
470
+ type: 'string',
471
+ description: 'Name for the MCP server (defaults to package name)',
472
+ },
473
+ version: {
474
+ type: 'string',
475
+ description: 'Version to install (for npm packages, e.g., "latest", "1.2.3")',
476
+ },
477
+ env: {
478
+ type: 'object',
479
+ additionalProperties: { type: 'string' },
480
+ description: 'Environment variables for the server',
481
+ },
482
+ description: {
483
+ type: 'string',
484
+ description: 'Description for the server',
485
+ },
486
+ args: {
487
+ type: 'array',
488
+ items: { type: 'string' },
489
+ description: 'Additional arguments to pass to the server',
490
+ },
491
+ installDir: {
492
+ type: 'string',
493
+ description: 'Global MCP packages directory (defaults to ~/.claude/mcp-servers)',
494
+ },
495
+ force: {
496
+ type: 'boolean',
497
+ description: 'Force reinstallation even if already installed',
498
+ },
499
+ target: {
500
+ type: 'string',
501
+ enum: ['cli', 'app', 'both'],
502
+ description: 'Which config(s) to add to (default: both - adds to both CLI and app configs)',
503
+ default: 'both',
504
+ },
505
+ },
506
+ required: ['package'],
507
+ },
508
+ },
509
+ {
510
+ name: 'mcp_remove',
511
+ description: 'Remove an MCP server configuration from config file(s)',
512
+ inputSchema: {
513
+ type: 'object',
514
+ properties: {
515
+ name: {
516
+ type: 'string',
517
+ description: 'MCP server name to remove',
518
+ },
519
+ target: {
520
+ type: 'string',
521
+ enum: ['cli', 'app', 'both'],
522
+ description: 'Which config(s) to remove from (default: both)',
523
+ default: 'both',
524
+ },
525
+ },
526
+ required: ['name'],
527
+ },
528
+ },
529
+ {
530
+ name: 'mcp_update',
531
+ description: 'Update an existing MCP server configuration',
532
+ inputSchema: {
533
+ type: 'object',
534
+ properties: {
535
+ name: {
536
+ type: 'string',
537
+ description: 'MCP server name to update',
538
+ },
539
+ command: {
540
+ type: 'string',
541
+ description: 'New command to run',
542
+ },
543
+ args: {
544
+ type: 'array',
545
+ items: { type: 'string' },
546
+ description: 'New arguments for the command',
547
+ },
548
+ url: {
549
+ type: 'string',
550
+ description: 'New URL for HTTP/SSE/WebSocket transport',
551
+ },
552
+ env: {
553
+ type: 'object',
554
+ additionalProperties: { type: 'string' },
555
+ description: 'New environment variables',
556
+ },
557
+ headers: {
558
+ type: 'object',
559
+ additionalProperties: { type: 'string' },
560
+ description: 'New HTTP headers',
561
+ },
562
+ description: {
563
+ type: 'string',
564
+ description: 'New description',
565
+ },
566
+ alwaysAllow: {
567
+ type: 'boolean',
568
+ description: 'Update always allow flag',
569
+ },
570
+ timeout: {
571
+ type: 'number',
572
+ description: 'New timeout in milliseconds',
573
+ },
574
+ target: {
575
+ type: 'string',
576
+ enum: ['cli', 'app', 'both'],
577
+ description: 'Which config(s) to update (default: both)',
578
+ default: 'both',
579
+ },
580
+ },
581
+ required: ['name'],
582
+ },
583
+ },
584
+ {
585
+ name: 'mcp_sync',
586
+ description: 'Synchronize MCP servers between CLI and app configs. Ensures both configs have the same servers.',
587
+ inputSchema: {
588
+ type: 'object',
589
+ properties: {
590
+ source: {
591
+ type: 'string',
592
+ enum: ['cli', 'app'],
593
+ description: 'Source config to sync from (default: app - syncs from app to CLI)',
594
+ default: 'app',
595
+ },
596
+ dryRun: {
597
+ type: 'boolean',
598
+ description: 'Show what would be synced without making changes',
599
+ default: false,
600
+ },
601
+ },
602
+ },
603
+ },
604
+ ],
605
+ })];
606
+ });
607
+ }); });
608
+ // ============================================================================
609
+ // Tool Handlers
610
+ // ============================================================================
611
+ /**
612
+ * Handle tool execution
613
+ */
614
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, function (request) { return __awaiter(void 0, void 0, void 0, function () {
615
+ var _a, name, args, _b, error_1, mcpError;
616
+ return __generator(this, function (_c) {
617
+ switch (_c.label) {
618
+ case 0:
619
+ _a = request.params, name = _a.name, args = _a.arguments;
620
+ _c.label = 1;
621
+ case 1:
622
+ _c.trys.push([1, 50, , 51]);
623
+ _b = name;
624
+ switch (_b) {
625
+ case 'read_global_claude_md': return [3 /*break*/, 2];
626
+ case 'write_global_claude_md': return [3 /*break*/, 4];
627
+ case 'read_project_claude_md': return [3 /*break*/, 6];
628
+ case 'write_project_claude_md': return [3 /*break*/, 8];
629
+ case 'read_keybindings': return [3 /*break*/, 10];
630
+ case 'write_keybindings': return [3 /*break*/, 12];
631
+ case 'add_keybinding': return [3 /*break*/, 14];
632
+ case 'remove_keybinding': return [3 /*break*/, 16];
633
+ case 'read_settings': return [3 /*break*/, 18];
634
+ case 'write_settings': return [3 /*break*/, 20];
635
+ case 'list_hooks': return [3 /*break*/, 22];
636
+ case 'read_hook': return [3 /*break*/, 24];
637
+ case 'write_hook': return [3 /*break*/, 26];
638
+ case 'list_config_files': return [3 /*break*/, 28];
639
+ case 'get_config_path': return [3 /*break*/, 30];
640
+ case 'backup_config': return [3 /*break*/, 32];
641
+ case 'mcp_list': return [3 /*break*/, 34];
642
+ case 'mcp_get': return [3 /*break*/, 36];
643
+ case 'mcp_add': return [3 /*break*/, 38];
644
+ case 'mcp_install': return [3 /*break*/, 40];
645
+ case 'mcp_remove': return [3 /*break*/, 42];
646
+ case 'mcp_update': return [3 /*break*/, 44];
647
+ case 'mcp_sync': return [3 /*break*/, 46];
648
+ }
649
+ return [3 /*break*/, 48];
650
+ case 2: return [4 /*yield*/, handleReadGlobalClaudeMd()];
651
+ case 3: return [2 /*return*/, _c.sent()];
652
+ case 4: return [4 /*yield*/, handleWriteGlobalClaudeMd(args)];
653
+ case 5: return [2 /*return*/, _c.sent()];
654
+ case 6: return [4 /*yield*/, handleReadProjectClaudeMd(args)];
655
+ case 7: return [2 /*return*/, _c.sent()];
656
+ case 8: return [4 /*yield*/, handleWriteProjectClaudeMd(args)];
657
+ case 9: return [2 /*return*/, _c.sent()];
658
+ case 10: return [4 /*yield*/, handleReadKeybindings()];
659
+ case 11: return [2 /*return*/, _c.sent()];
660
+ case 12: return [4 /*yield*/, handleWriteKeybindings(args)];
661
+ case 13: return [2 /*return*/, _c.sent()];
662
+ case 14: return [4 /*yield*/, handleAddKeybinding(args)];
663
+ case 15: return [2 /*return*/, _c.sent()];
664
+ case 16: return [4 /*yield*/, handleRemoveKeybinding(args)];
665
+ case 17: return [2 /*return*/, _c.sent()];
666
+ case 18: return [4 /*yield*/, handleReadSettings()];
667
+ case 19: return [2 /*return*/, _c.sent()];
668
+ case 20: return [4 /*yield*/, handleWriteSettings(args)];
669
+ case 21: return [2 /*return*/, _c.sent()];
670
+ case 22: return [4 /*yield*/, handleListHooks()];
671
+ case 23: return [2 /*return*/, _c.sent()];
672
+ case 24: return [4 /*yield*/, handleReadHook(args)];
673
+ case 25: return [2 /*return*/, _c.sent()];
674
+ case 26: return [4 /*yield*/, handleWriteHook(args)];
675
+ case 27: return [2 /*return*/, _c.sent()];
676
+ case 28: return [4 /*yield*/, handleListConfigFiles(args)];
677
+ case 29: return [2 /*return*/, _c.sent()];
678
+ case 30: return [4 /*yield*/, handleGetConfigPath(args)];
679
+ case 31: return [2 /*return*/, _c.sent()];
680
+ case 32: return [4 /*yield*/, handleBackupConfig(args)];
681
+ case 33: return [2 /*return*/, _c.sent()];
682
+ case 34: return [4 /*yield*/, handleMCPList(args)];
683
+ case 35: return [2 /*return*/, _c.sent()];
684
+ case 36: return [4 /*yield*/, handleMCPGet(args)];
685
+ case 37: return [2 /*return*/, _c.sent()];
686
+ case 38: return [4 /*yield*/, handleMCPAdd(args)];
687
+ case 39: return [2 /*return*/, _c.sent()];
688
+ case 40: return [4 /*yield*/, handleMCPInstall(args)];
689
+ case 41: return [2 /*return*/, _c.sent()];
690
+ case 42: return [4 /*yield*/, handleMCPRemove(args)];
691
+ case 43: return [2 /*return*/, _c.sent()];
692
+ case 44: return [4 /*yield*/, handleMCPUpdate(args)];
693
+ case 45: return [2 /*return*/, _c.sent()];
694
+ case 46: return [4 /*yield*/, handleMCPSync(args)];
695
+ case 47: return [2 /*return*/, _c.sent()];
696
+ case 48: throw new Error("Unknown tool: ".concat(name));
697
+ case 49: return [3 /*break*/, 51];
698
+ case 50:
699
+ error_1 = _c.sent();
700
+ mcpError = errors.createMCPError(error_1);
701
+ return [2 /*return*/, {
702
+ content: [
703
+ {
704
+ type: 'text',
705
+ text: JSON.stringify(mcpError, null, 2),
706
+ },
707
+ ],
708
+ isError: true,
709
+ }];
710
+ case 51: return [2 /*return*/];
711
+ }
712
+ });
713
+ }); });
714
+ // ============================================================================
715
+ // CLAUDE.md Handlers
716
+ // ============================================================================
717
+ function handleReadGlobalClaudeMd() {
718
+ return __awaiter(this, void 0, void 0, function () {
719
+ var filePath, validatedPath, content, stats;
720
+ return __generator(this, function (_a) {
721
+ switch (_a.label) {
722
+ case 0:
723
+ filePath = path.getConfigPaths().globalClaudeMd;
724
+ validatedPath = path.validatePath(filePath);
725
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
726
+ case 1:
727
+ content = _a.sent();
728
+ return [4 /*yield*/, getFileInfo(validatedPath)];
729
+ case 2:
730
+ stats = _a.sent();
731
+ return [2 /*return*/, {
732
+ content: [
733
+ {
734
+ type: 'text',
735
+ text: content,
736
+ },
737
+ ],
738
+ }];
739
+ }
740
+ });
741
+ });
742
+ }
743
+ function handleWriteGlobalClaudeMd(args) {
744
+ return __awaiter(this, void 0, void 0, function () {
745
+ var schema, _a, content, _b, createBackup, filePath, validatedPath, normalized, stripped;
746
+ return __generator(this, function (_c) {
747
+ switch (_c.label) {
748
+ case 0:
749
+ schema = zod_1.z.object({
750
+ content: zod_1.z.string(),
751
+ createBackup: zod_1.z.boolean().optional(),
752
+ });
753
+ _a = schema.parse(args), content = _a.content, _b = _a.createBackup, createBackup = _b === void 0 ? true : _b;
754
+ filePath = path.getConfigPaths().globalClaudeMd;
755
+ validatedPath = path.validatePath(filePath);
756
+ normalized = file.normalizeLineEndings(content);
757
+ stripped = file.stripBOM(normalized);
758
+ return [4 /*yield*/, file.atomicWrite(validatedPath, stripped, { createBackup: createBackup })];
759
+ case 1:
760
+ _c.sent();
761
+ return [2 /*return*/, {
762
+ content: [
763
+ {
764
+ type: 'text',
765
+ text: "Successfully wrote global CLAUDE.md to ".concat(path.getDisplayPath(validatedPath)),
766
+ },
767
+ ],
768
+ }];
769
+ }
770
+ });
771
+ });
772
+ }
773
+ function handleReadProjectClaudeMd(args) {
774
+ return __awaiter(this, void 0, void 0, function () {
775
+ var schema, projectPath, cwd, filePath, validatedPath, content;
776
+ return __generator(this, function (_a) {
777
+ switch (_a.label) {
778
+ case 0:
779
+ schema = zod_1.z.object({
780
+ projectPath: zod_1.z.string().optional(),
781
+ });
782
+ projectPath = schema.parse(args).projectPath;
783
+ cwd = projectPath || process.cwd();
784
+ filePath = path.getConfigPaths(cwd).projectClaudeMd;
785
+ validatedPath = path.validatePath(filePath, cwd);
786
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
787
+ case 1:
788
+ content = _a.sent();
789
+ return [2 /*return*/, {
790
+ content: [
791
+ {
792
+ type: 'text',
793
+ text: content,
794
+ },
795
+ ],
796
+ }];
797
+ }
798
+ });
799
+ });
800
+ }
801
+ function handleWriteProjectClaudeMd(args) {
802
+ return __awaiter(this, void 0, void 0, function () {
803
+ var schema, _a, content, projectPath, _b, createBackup, cwd, filePath, validatedPath, normalized, stripped;
804
+ return __generator(this, function (_c) {
805
+ switch (_c.label) {
806
+ case 0:
807
+ schema = zod_1.z.object({
808
+ content: zod_1.z.string(),
809
+ projectPath: zod_1.z.string().optional(),
810
+ createBackup: zod_1.z.boolean().optional(),
811
+ });
812
+ _a = schema.parse(args), content = _a.content, projectPath = _a.projectPath, _b = _a.createBackup, createBackup = _b === void 0 ? true : _b;
813
+ cwd = projectPath || process.cwd();
814
+ filePath = path.getConfigPaths(cwd).projectClaudeMd;
815
+ validatedPath = path.validatePath(filePath, cwd);
816
+ normalized = file.normalizeLineEndings(content);
817
+ stripped = file.stripBOM(normalized);
818
+ return [4 /*yield*/, file.atomicWrite(validatedPath, stripped, { createBackup: createBackup })];
819
+ case 1:
820
+ _c.sent();
821
+ return [2 /*return*/, {
822
+ content: [
823
+ {
824
+ type: 'text',
825
+ text: "Successfully wrote project CLAUDE.md to ".concat(path.getDisplayPath(validatedPath)),
826
+ },
827
+ ],
828
+ }];
829
+ }
830
+ });
831
+ });
832
+ }
833
+ // ============================================================================
834
+ // Keybindings Handlers
835
+ // ============================================================================
836
+ function handleReadKeybindings() {
837
+ return __awaiter(this, void 0, void 0, function () {
838
+ var filePath, validatedPath, content, config;
839
+ return __generator(this, function (_a) {
840
+ switch (_a.label) {
841
+ case 0:
842
+ filePath = path.getConfigPaths().keybindings;
843
+ validatedPath = path.validatePath(filePath);
844
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
845
+ case 1:
846
+ content = _a.sent();
847
+ config = file.safeJSONParse(content, validatedPath);
848
+ return [2 /*return*/, {
849
+ content: [
850
+ {
851
+ type: 'text',
852
+ text: JSON.stringify(config, null, 2),
853
+ },
854
+ ],
855
+ }];
856
+ }
857
+ });
858
+ });
859
+ }
860
+ function handleWriteKeybindings(args) {
861
+ return __awaiter(this, void 0, void 0, function () {
862
+ var schema, _a, keybindings, _b, createBackup, filePath, validatedPath, content;
863
+ return __generator(this, function (_c) {
864
+ switch (_c.label) {
865
+ case 0:
866
+ schema = zod_1.z.object({
867
+ keybindings: zod_1.z.object({
868
+ $schema: zod_1.z.string().optional(),
869
+ keybindings: zod_1.z.record(zod_1.z.string(), zod_1.z.object({
870
+ key: zod_1.z.string(),
871
+ command: zod_1.z.string(),
872
+ when: zod_1.z.string().optional(),
873
+ })),
874
+ }),
875
+ createBackup: zod_1.z.boolean().optional(),
876
+ });
877
+ _a = schema.parse(args), keybindings = _a.keybindings, _b = _a.createBackup, createBackup = _b === void 0 ? true : _b;
878
+ filePath = path.getConfigPaths().keybindings;
879
+ validatedPath = path.validatePath(filePath);
880
+ content = file.formatJSON(keybindings);
881
+ return [4 /*yield*/, file.atomicWrite(validatedPath, content, { createBackup: createBackup })];
882
+ case 1:
883
+ _c.sent();
884
+ return [2 /*return*/, {
885
+ content: [
886
+ {
887
+ type: 'text',
888
+ text: "Successfully wrote keybindings to ".concat(path.getDisplayPath(validatedPath)),
889
+ },
890
+ ],
891
+ }];
892
+ }
893
+ });
894
+ });
895
+ }
896
+ function handleAddKeybinding(args) {
897
+ return __awaiter(this, void 0, void 0, function () {
898
+ var schema, _a, key, command, when, filePath, validatedPath, config, content_1, _b, content;
899
+ return __generator(this, function (_c) {
900
+ switch (_c.label) {
901
+ case 0:
902
+ schema = zod_1.z.object({
903
+ key: zod_1.z.string(),
904
+ command: zod_1.z.string(),
905
+ when: zod_1.z.string().optional(),
906
+ });
907
+ _a = schema.parse(args), key = _a.key, command = _a.command, when = _a.when;
908
+ filePath = path.getConfigPaths().keybindings;
909
+ validatedPath = path.validatePath(filePath);
910
+ _c.label = 1;
911
+ case 1:
912
+ _c.trys.push([1, 3, , 4]);
913
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
914
+ case 2:
915
+ content_1 = _c.sent();
916
+ config = file.safeJSONParse(content_1, validatedPath);
917
+ return [3 /*break*/, 4];
918
+ case 3:
919
+ _b = _c.sent();
920
+ // Create new config if file doesn't exist
921
+ config = { keybindings: {} };
922
+ return [3 /*break*/, 4];
923
+ case 4:
924
+ // Add/update keybinding
925
+ config.keybindings[key] = __assign({ key: key, command: command }, (when && { when: when }));
926
+ content = file.formatJSON(config);
927
+ return [4 /*yield*/, file.atomicWrite(validatedPath, content, { createBackup: true })];
928
+ case 5:
929
+ _c.sent();
930
+ return [2 /*return*/, {
931
+ content: [
932
+ {
933
+ type: 'text',
934
+ text: "Successfully added keybinding: ".concat(key, " -> ").concat(command),
935
+ },
936
+ ],
937
+ }];
938
+ }
939
+ });
940
+ });
941
+ }
942
+ function handleRemoveKeybinding(args) {
943
+ return __awaiter(this, void 0, void 0, function () {
944
+ var schema, key, filePath, validatedPath, content, config, newContent;
945
+ return __generator(this, function (_a) {
946
+ switch (_a.label) {
947
+ case 0:
948
+ schema = zod_1.z.object({
949
+ key: zod_1.z.string(),
950
+ });
951
+ key = schema.parse(args).key;
952
+ filePath = path.getConfigPaths().keybindings;
953
+ validatedPath = path.validatePath(filePath);
954
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
955
+ case 1:
956
+ content = _a.sent();
957
+ config = file.safeJSONParse(content, validatedPath);
958
+ // Remove keybinding
959
+ delete config.keybindings[key];
960
+ newContent = file.formatJSON(config);
961
+ return [4 /*yield*/, file.atomicWrite(validatedPath, newContent, { createBackup: true })];
962
+ case 2:
963
+ _a.sent();
964
+ return [2 /*return*/, {
965
+ content: [
966
+ {
967
+ type: 'text',
968
+ text: "Successfully removed keybinding: ".concat(key),
969
+ },
970
+ ],
971
+ }];
972
+ }
973
+ });
974
+ });
975
+ }
976
+ // ============================================================================
977
+ // Settings Handlers
978
+ // ============================================================================
979
+ function handleReadSettings() {
980
+ return __awaiter(this, void 0, void 0, function () {
981
+ var filePath, validatedPath, content;
982
+ return __generator(this, function (_a) {
983
+ switch (_a.label) {
984
+ case 0:
985
+ filePath = path.getConfigPaths().settings;
986
+ validatedPath = path.validatePath(filePath);
987
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
988
+ case 1:
989
+ content = _a.sent();
990
+ return [2 /*return*/, {
991
+ content: [
992
+ {
993
+ type: 'text',
994
+ text: content,
995
+ },
996
+ ],
997
+ }];
998
+ }
999
+ });
1000
+ });
1001
+ }
1002
+ function handleWriteSettings(args) {
1003
+ return __awaiter(this, void 0, void 0, function () {
1004
+ var schema, _a, settings, _b, createBackup, filePath, validatedPath, content;
1005
+ return __generator(this, function (_c) {
1006
+ switch (_c.label) {
1007
+ case 0:
1008
+ schema = zod_1.z.object({
1009
+ settings: zod_1.z.object({
1010
+ $schema: zod_1.z.string().optional(),
1011
+ }).passthrough(),
1012
+ createBackup: zod_1.z.boolean().optional(),
1013
+ });
1014
+ _a = schema.parse(args), settings = _a.settings, _b = _a.createBackup, createBackup = _b === void 0 ? true : _b;
1015
+ filePath = path.getConfigPaths().settings;
1016
+ validatedPath = path.validatePath(filePath);
1017
+ content = file.formatJSON(settings);
1018
+ return [4 /*yield*/, file.atomicWrite(validatedPath, content, { createBackup: createBackup })];
1019
+ case 1:
1020
+ _c.sent();
1021
+ return [2 /*return*/, {
1022
+ content: [
1023
+ {
1024
+ type: 'text',
1025
+ text: "Successfully wrote settings to ".concat(path.getDisplayPath(validatedPath)),
1026
+ },
1027
+ ],
1028
+ }];
1029
+ }
1030
+ });
1031
+ });
1032
+ }
1033
+ // ============================================================================
1034
+ // Hooks Handlers
1035
+ // ============================================================================
1036
+ function handleListHooks() {
1037
+ return __awaiter(this, void 0, void 0, function () {
1038
+ var hooksDir, validatedPath, hooks;
1039
+ return __generator(this, function (_a) {
1040
+ switch (_a.label) {
1041
+ case 0:
1042
+ hooksDir = path.getConfigPaths().hooksDir;
1043
+ validatedPath = path.validatePath(hooksDir);
1044
+ return [4 /*yield*/, listHookFiles(validatedPath)];
1045
+ case 1:
1046
+ hooks = _a.sent();
1047
+ return [2 /*return*/, {
1048
+ content: [
1049
+ {
1050
+ type: 'text',
1051
+ text: JSON.stringify(hooks, null, 2),
1052
+ },
1053
+ ],
1054
+ }];
1055
+ }
1056
+ });
1057
+ });
1058
+ }
1059
+ function handleReadHook(args) {
1060
+ return __awaiter(this, void 0, void 0, function () {
1061
+ var schema, name, hooksDir, validatedPath, hookPath, validatedHookPath, content;
1062
+ return __generator(this, function (_a) {
1063
+ switch (_a.label) {
1064
+ case 0:
1065
+ schema = zod_1.z.object({
1066
+ name: zod_1.z.string(),
1067
+ });
1068
+ name = schema.parse(args).name;
1069
+ hooksDir = path.getConfigPaths().hooksDir;
1070
+ validatedPath = path.validatePath(hooksDir);
1071
+ hookPath = "".concat(validatedPath, "/").concat(name);
1072
+ validatedHookPath = path.validatePath(hookPath);
1073
+ return [4 /*yield*/, file.safeReadFile(validatedHookPath)];
1074
+ case 1:
1075
+ content = _a.sent();
1076
+ return [2 /*return*/, {
1077
+ content: [
1078
+ {
1079
+ type: 'text',
1080
+ text: content,
1081
+ },
1082
+ ],
1083
+ }];
1084
+ }
1085
+ });
1086
+ });
1087
+ }
1088
+ function handleWriteHook(args) {
1089
+ return __awaiter(this, void 0, void 0, function () {
1090
+ var schema, _a, name, event, content, _b, enabled, hooksDir, validatedPath, hookPath, validatedHookPath;
1091
+ return __generator(this, function (_c) {
1092
+ switch (_c.label) {
1093
+ case 0:
1094
+ schema = zod_1.z.object({
1095
+ name: zod_1.z.string(),
1096
+ event: zod_1.z.string(),
1097
+ content: zod_1.z.string(),
1098
+ enabled: zod_1.z.boolean().optional(),
1099
+ });
1100
+ _a = schema.parse(args), name = _a.name, event = _a.event, content = _a.content, _b = _a.enabled, enabled = _b === void 0 ? true : _b;
1101
+ hooksDir = path.getConfigPaths().hooksDir;
1102
+ validatedPath = path.validatePath(hooksDir);
1103
+ hookPath = "".concat(validatedPath, "/").concat(name);
1104
+ validatedHookPath = path.validatePath(hookPath);
1105
+ return [4 /*yield*/, file.atomicWrite(validatedHookPath, content, { createBackup: true })];
1106
+ case 1:
1107
+ _c.sent();
1108
+ return [2 /*return*/, {
1109
+ content: [
1110
+ {
1111
+ type: 'text',
1112
+ text: "Successfully wrote hook: ".concat(name),
1113
+ },
1114
+ ],
1115
+ }];
1116
+ }
1117
+ });
1118
+ });
1119
+ }
1120
+ // ============================================================================
1121
+ // Utility Handlers
1122
+ // ============================================================================
1123
+ function handleListConfigFiles(args) {
1124
+ return __awaiter(this, void 0, void 0, function () {
1125
+ var schema, _a, includeProject, paths, cwd, files;
1126
+ return __generator(this, function (_b) {
1127
+ schema = zod_1.z.object({
1128
+ includeProject: zod_1.z.boolean().optional(),
1129
+ });
1130
+ _a = schema.parse(args).includeProject, includeProject = _a === void 0 ? true : _a;
1131
+ paths = path.getConfigPaths();
1132
+ cwd = process.cwd();
1133
+ files = [
1134
+ {
1135
+ type: 'CLAUDE_MD_GLOBAL',
1136
+ path: path.getDisplayPath(paths.globalClaudeMd),
1137
+ exists: path.pathExists(paths.globalClaudeMd),
1138
+ },
1139
+ {
1140
+ type: 'KEYBINDINGS',
1141
+ path: path.getDisplayPath(paths.keybindings),
1142
+ exists: path.pathExists(paths.keybindings),
1143
+ },
1144
+ {
1145
+ type: 'SETTINGS',
1146
+ path: path.getDisplayPath(paths.settings),
1147
+ exists: path.pathExists(paths.settings),
1148
+ },
1149
+ {
1150
+ type: 'HOOKS_DIR',
1151
+ path: path.getDisplayPath(paths.hooksDir),
1152
+ exists: path.pathExists(paths.hooksDir),
1153
+ },
1154
+ ];
1155
+ if (includeProject) {
1156
+ files.push({
1157
+ type: 'CLAUDE_MD_PROJECT',
1158
+ path: path.getDisplayPath(paths.projectClaudeMd),
1159
+ exists: path.pathExists(paths.projectClaudeMd),
1160
+ });
1161
+ }
1162
+ return [2 /*return*/, {
1163
+ content: [
1164
+ {
1165
+ type: 'text',
1166
+ text: JSON.stringify(files, null, 2),
1167
+ },
1168
+ ],
1169
+ }];
1170
+ });
1171
+ });
1172
+ }
1173
+ function handleGetConfigPath(args) {
1174
+ return __awaiter(this, void 0, void 0, function () {
1175
+ var schema, fileType, paths, filePathMap, resolvedPath, displayPath;
1176
+ return __generator(this, function (_a) {
1177
+ schema = zod_1.z.object({
1178
+ fileType: zod_1.z.enum([
1179
+ 'CLAUDE_MD_GLOBAL',
1180
+ 'CLAUDE_MD_PROJECT',
1181
+ 'KEYBINDINGS',
1182
+ 'SETTINGS',
1183
+ 'HOOKS_DIR',
1184
+ ]),
1185
+ });
1186
+ fileType = schema.parse(args).fileType;
1187
+ paths = path.getConfigPaths();
1188
+ filePathMap = {
1189
+ CLAUDE_MD_GLOBAL: paths.globalClaudeMd,
1190
+ CLAUDE_MD_PROJECT: paths.projectClaudeMd,
1191
+ KEYBINDINGS: paths.keybindings,
1192
+ SETTINGS: paths.settings,
1193
+ HOOKS_DIR: paths.hooksDir,
1194
+ };
1195
+ resolvedPath = filePathMap[fileType];
1196
+ displayPath = path.getDisplayPath(resolvedPath);
1197
+ return [2 /*return*/, {
1198
+ content: [
1199
+ {
1200
+ type: 'text',
1201
+ text: JSON.stringify({
1202
+ type: fileType,
1203
+ path: displayPath,
1204
+ absolutePath: resolvedPath,
1205
+ exists: path.pathExists(resolvedPath),
1206
+ }, null, 2),
1207
+ },
1208
+ ],
1209
+ }];
1210
+ });
1211
+ });
1212
+ }
1213
+ function handleBackupConfig(args) {
1214
+ return __awaiter(this, void 0, void 0, function () {
1215
+ var schema, fileType, paths, filePathMap, filePath, validatedPath, backupPath;
1216
+ return __generator(this, function (_a) {
1217
+ switch (_a.label) {
1218
+ case 0:
1219
+ schema = zod_1.z.object({
1220
+ fileType: zod_1.z.enum(['CLAUDE_MD', 'KEYBINDINGS', 'SETTINGS']),
1221
+ });
1222
+ fileType = schema.parse(args).fileType;
1223
+ paths = path.getConfigPaths();
1224
+ filePathMap = {
1225
+ CLAUDE_MD: paths.globalClaudeMd,
1226
+ KEYBINDINGS: paths.keybindings,
1227
+ SETTINGS: paths.settings,
1228
+ };
1229
+ filePath = filePathMap[fileType];
1230
+ validatedPath = path.validatePath(filePath);
1231
+ if (!path.pathExists(validatedPath)) {
1232
+ throw new Error("File does not exist: ".concat(fileType));
1233
+ }
1234
+ return [4 /*yield*/, createBackup(validatedPath)];
1235
+ case 1:
1236
+ backupPath = _a.sent();
1237
+ return [2 /*return*/, {
1238
+ content: [
1239
+ {
1240
+ type: 'text',
1241
+ text: "Backup created: ".concat(path.getDisplayPath(backupPath)),
1242
+ },
1243
+ ],
1244
+ }];
1245
+ }
1246
+ });
1247
+ });
1248
+ }
1249
+ // ============================================================================
1250
+ // Helper Functions
1251
+ // ============================================================================
1252
+ function getFileInfo(filePath) {
1253
+ return __awaiter(this, void 0, void 0, function () {
1254
+ var stat, stats;
1255
+ return __generator(this, function (_a) {
1256
+ switch (_a.label) {
1257
+ case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require('node:fs/promises'); })];
1258
+ case 1:
1259
+ stat = (_a.sent()).stat;
1260
+ return [4 /*yield*/, stat(filePath)];
1261
+ case 2:
1262
+ stats = _a.sent();
1263
+ return [2 /*return*/, {
1264
+ size: stats.size,
1265
+ modified: stats.mtime,
1266
+ }];
1267
+ }
1268
+ });
1269
+ });
1270
+ }
1271
+ function listHookFiles(hooksDir) {
1272
+ return __awaiter(this, void 0, void 0, function () {
1273
+ var readdir, existsSync, files, hooks, _i, files_1, file_1, name_1, event_1;
1274
+ return __generator(this, function (_a) {
1275
+ switch (_a.label) {
1276
+ case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require('node:fs/promises'); })];
1277
+ case 1:
1278
+ readdir = (_a.sent()).readdir;
1279
+ return [4 /*yield*/, Promise.resolve().then(function () { return require('node:fs'); })];
1280
+ case 2:
1281
+ existsSync = (_a.sent()).existsSync;
1282
+ if (!existsSync(hooksDir)) {
1283
+ return [2 /*return*/, []];
1284
+ }
1285
+ return [4 /*yield*/, readdir(hooksDir, { withFileTypes: true })];
1286
+ case 3:
1287
+ files = _a.sent();
1288
+ hooks = [];
1289
+ for (_i = 0, files_1 = files; _i < files_1.length; _i++) {
1290
+ file_1 = files_1[_i];
1291
+ if (file_1.isFile()) {
1292
+ name_1 = file_1.name;
1293
+ event_1 = name_1.replace(/\.(ts|js|sh)$/, '');
1294
+ hooks.push({ name: name_1, event: event_1, enabled: true });
1295
+ }
1296
+ }
1297
+ return [2 /*return*/, hooks];
1298
+ }
1299
+ });
1300
+ });
1301
+ }
1302
+ function createBackup(filePath) {
1303
+ return __awaiter(this, void 0, void 0, function () {
1304
+ var timestamp, backupPath, _a, readFile, writeFile, content;
1305
+ return __generator(this, function (_b) {
1306
+ switch (_b.label) {
1307
+ case 0:
1308
+ timestamp = new Date().toISOString().replace(/[:.]/g, '-');
1309
+ backupPath = "".concat(filePath, ".backup.").concat(timestamp);
1310
+ return [4 /*yield*/, Promise.resolve().then(function () { return require('node:fs/promises'); })];
1311
+ case 1:
1312
+ _a = _b.sent(), readFile = _a.readFile, writeFile = _a.writeFile;
1313
+ return [4 /*yield*/, readFile(filePath)];
1314
+ case 2:
1315
+ content = _b.sent();
1316
+ return [4 /*yield*/, writeFile(backupPath, content)];
1317
+ case 3:
1318
+ _b.sent();
1319
+ return [2 /*return*/, backupPath];
1320
+ }
1321
+ });
1322
+ });
1323
+ }
1324
+ // ============================================================================
1325
+ // MCP Management Handlers
1326
+ // ============================================================================
1327
+ function handleMCPList(args) {
1328
+ return __awaiter(this, void 0, void 0, function () {
1329
+ var schema, _a, _b, target, _c, includeHealth, configPaths, results, validatedPath, content, _d, validatedPath, content, _e, healthInfo, exec_1, result, lines, _i, lines_1, line, match, name_2, status_1, _f, output, cliServers, appServers;
1330
+ return __generator(this, function (_g) {
1331
+ switch (_g.label) {
1332
+ case 0:
1333
+ schema = zod_1.z.object({
1334
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1335
+ includeHealth: zod_1.z.boolean().optional(),
1336
+ });
1337
+ _a = schema.parse(args), _b = _a.target, target = _b === void 0 ? 'both' : _b, _c = _a.includeHealth, includeHealth = _c === void 0 ? false : _c;
1338
+ configPaths = (0, path_js_1.getMCPConfigPaths)(target);
1339
+ results = {};
1340
+ if (!configPaths.cli) return [3 /*break*/, 4];
1341
+ _g.label = 1;
1342
+ case 1:
1343
+ _g.trys.push([1, 3, , 4]);
1344
+ validatedPath = path.validatePath(configPaths.cli);
1345
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1346
+ case 2:
1347
+ content = _g.sent();
1348
+ results.cli = {
1349
+ config: file.safeJSONParse(content, validatedPath),
1350
+ source: 'cli',
1351
+ };
1352
+ return [3 /*break*/, 4];
1353
+ case 3:
1354
+ _d = _g.sent();
1355
+ results.cli = { config: { mcpServers: {} }, source: 'cli' };
1356
+ return [3 /*break*/, 4];
1357
+ case 4:
1358
+ if (!configPaths.app) return [3 /*break*/, 8];
1359
+ _g.label = 5;
1360
+ case 5:
1361
+ _g.trys.push([5, 7, , 8]);
1362
+ validatedPath = path.validatePath(configPaths.app);
1363
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1364
+ case 6:
1365
+ content = _g.sent();
1366
+ results.app = {
1367
+ config: file.safeJSONParse(content, validatedPath),
1368
+ source: 'app',
1369
+ };
1370
+ return [3 /*break*/, 8];
1371
+ case 7:
1372
+ _e = _g.sent();
1373
+ results.app = { config: { mcpServers: {} }, source: 'app' };
1374
+ return [3 /*break*/, 8];
1375
+ case 8:
1376
+ healthInfo = {};
1377
+ if (!includeHealth) return [3 /*break*/, 13];
1378
+ _g.label = 9;
1379
+ case 9:
1380
+ _g.trys.push([9, 12, , 13]);
1381
+ return [4 /*yield*/, Promise.resolve().then(function () { return require('node:child_process'); })];
1382
+ case 10:
1383
+ exec_1 = (_g.sent()).exec;
1384
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
1385
+ exec_1('claude mcp list 2>&1', function (error, stdout, stderr) {
1386
+ if (error) {
1387
+ resolve(stderr || stdout);
1388
+ }
1389
+ else {
1390
+ resolve(stdout);
1391
+ }
1392
+ });
1393
+ })];
1394
+ case 11:
1395
+ result = _g.sent();
1396
+ lines = result.split('\n');
1397
+ for (_i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
1398
+ line = lines_1[_i];
1399
+ match = line.match(/^([^:]+):\s+.*?-\s+([✓✗])/);
1400
+ if (match) {
1401
+ name_2 = match[1].trim();
1402
+ status_1 = match[2] === '✓' ? 'connected' : 'error';
1403
+ healthInfo[name_2] = status_1;
1404
+ }
1405
+ }
1406
+ return [3 /*break*/, 13];
1407
+ case 12:
1408
+ _f = _g.sent();
1409
+ return [3 /*break*/, 13];
1410
+ case 13:
1411
+ output = {};
1412
+ if (results.cli) {
1413
+ cliServers = Object.entries(results.cli.config.mcpServers || {}).map(function (_a) {
1414
+ var name = _a[0], serverConfig = _a[1];
1415
+ return (__assign(__assign({}, serverConfig), { name: name, source: 'cli', health: healthInfo[name] }));
1416
+ });
1417
+ output.cli = { mcpServers: cliServers };
1418
+ }
1419
+ if (results.app) {
1420
+ appServers = Object.entries(results.app.config.mcpServers || {}).map(function (_a) {
1421
+ var name = _a[0], serverConfig = _a[1];
1422
+ return (__assign(__assign({}, serverConfig), { name: name, source: 'app', health: healthInfo[name] }));
1423
+ });
1424
+ output.app = { mcpServers: appServers };
1425
+ }
1426
+ return [2 /*return*/, {
1427
+ content: [
1428
+ {
1429
+ type: 'text',
1430
+ text: JSON.stringify(output, null, 2),
1431
+ },
1432
+ ],
1433
+ }];
1434
+ }
1435
+ });
1436
+ });
1437
+ }
1438
+ function handleMCPGet(args) {
1439
+ return __awaiter(this, void 0, void 0, function () {
1440
+ var schema, _a, name, _b, target, configPaths, results, found, validatedPath, content, config, serverConfig, _c, validatedPath, content, config, serverConfig, _d;
1441
+ var _e, _f;
1442
+ return __generator(this, function (_g) {
1443
+ switch (_g.label) {
1444
+ case 0:
1445
+ schema = zod_1.z.object({
1446
+ name: zod_1.z.string(),
1447
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1448
+ });
1449
+ _a = schema.parse(args), name = _a.name, _b = _a.target, target = _b === void 0 ? 'both' : _b;
1450
+ configPaths = (0, path_js_1.getMCPConfigPaths)(target);
1451
+ results = {};
1452
+ found = false;
1453
+ if (!configPaths.cli) return [3 /*break*/, 4];
1454
+ _g.label = 1;
1455
+ case 1:
1456
+ _g.trys.push([1, 3, , 4]);
1457
+ validatedPath = path.validatePath(configPaths.cli);
1458
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1459
+ case 2:
1460
+ content = _g.sent();
1461
+ config = file.safeJSONParse(content, validatedPath);
1462
+ serverConfig = (_e = config.mcpServers) === null || _e === void 0 ? void 0 : _e[name];
1463
+ if (serverConfig) {
1464
+ results.cli = __assign(__assign({ name: name }, serverConfig), { source: 'cli' });
1465
+ found = true;
1466
+ }
1467
+ return [3 /*break*/, 4];
1468
+ case 3:
1469
+ _c = _g.sent();
1470
+ return [3 /*break*/, 4];
1471
+ case 4:
1472
+ if (!configPaths.app) return [3 /*break*/, 8];
1473
+ _g.label = 5;
1474
+ case 5:
1475
+ _g.trys.push([5, 7, , 8]);
1476
+ validatedPath = path.validatePath(configPaths.app);
1477
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1478
+ case 6:
1479
+ content = _g.sent();
1480
+ config = file.safeJSONParse(content, validatedPath);
1481
+ serverConfig = (_f = config.mcpServers) === null || _f === void 0 ? void 0 : _f[name];
1482
+ if (serverConfig) {
1483
+ results.app = __assign(__assign({ name: name }, serverConfig), { source: 'app' });
1484
+ found = true;
1485
+ }
1486
+ return [3 /*break*/, 8];
1487
+ case 7:
1488
+ _d = _g.sent();
1489
+ return [3 /*break*/, 8];
1490
+ case 8:
1491
+ if (!found) {
1492
+ throw new Error("MCP server not found: ".concat(name));
1493
+ }
1494
+ return [2 /*return*/, {
1495
+ content: [
1496
+ {
1497
+ type: 'text',
1498
+ text: JSON.stringify(results, null, 2),
1499
+ },
1500
+ ],
1501
+ }];
1502
+ }
1503
+ });
1504
+ });
1505
+ }
1506
+ function handleMCPAdd(args) {
1507
+ return __awaiter(this, void 0, void 0, function () {
1508
+ var schema, options, configPaths, results, serverConfig, validatedPath, config, content_2, _a, content, validatedPath, config, content_3, _b, content;
1509
+ return __generator(this, function (_c) {
1510
+ switch (_c.label) {
1511
+ case 0:
1512
+ schema = zod_1.z.object({
1513
+ name: zod_1.z.string().min(1),
1514
+ command: zod_1.z.string().optional(),
1515
+ args: zod_1.z.array(zod_1.z.string()).optional(),
1516
+ url: zod_1.z.string().optional(),
1517
+ transport: zod_1.z.enum(['stdio', 'sse', 'http', 'ws', 'websocket']).optional(),
1518
+ env: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
1519
+ headers: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
1520
+ description: zod_1.z.string().optional(),
1521
+ alwaysAllow: zod_1.z.boolean().optional(),
1522
+ timeout: zod_1.z.number().optional(),
1523
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1524
+ });
1525
+ options = schema.parse(args);
1526
+ configPaths = (0, path_js_1.getMCPConfigPaths)(options.target || 'both');
1527
+ results = [];
1528
+ serverConfig = {};
1529
+ if (options.command)
1530
+ serverConfig.command = options.command;
1531
+ if (options.args)
1532
+ serverConfig.args = options.args;
1533
+ if (options.url)
1534
+ serverConfig.url = options.url;
1535
+ if (options.transport)
1536
+ serverConfig.transport = options.transport;
1537
+ if (options.env)
1538
+ serverConfig.env = options.env;
1539
+ if (options.headers)
1540
+ serverConfig.headers = options.headers;
1541
+ if (options.description)
1542
+ serverConfig.description = options.description;
1543
+ if (options.alwaysAllow !== undefined)
1544
+ serverConfig.alwaysAllow = options.alwaysAllow;
1545
+ if (options.timeout)
1546
+ serverConfig.timeout = options.timeout;
1547
+ if (!configPaths.cli) return [3 /*break*/, 6];
1548
+ validatedPath = path.validatePath(configPaths.cli);
1549
+ config = void 0;
1550
+ _c.label = 1;
1551
+ case 1:
1552
+ _c.trys.push([1, 3, , 4]);
1553
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1554
+ case 2:
1555
+ content_2 = _c.sent();
1556
+ config = file.safeJSONParse(content_2, validatedPath);
1557
+ return [3 /*break*/, 4];
1558
+ case 3:
1559
+ _a = _c.sent();
1560
+ config = { mcpServers: {} };
1561
+ return [3 /*break*/, 4];
1562
+ case 4:
1563
+ if (!config.mcpServers) {
1564
+ config.mcpServers = {};
1565
+ }
1566
+ if (config.mcpServers[options.name]) {
1567
+ throw new Error("MCP server already exists in CLI config: ".concat(options.name));
1568
+ }
1569
+ config.mcpServers[options.name] = serverConfig;
1570
+ content = file.formatJSON(config);
1571
+ return [4 /*yield*/, file.atomicWrite(validatedPath, content, { createBackup: true })];
1572
+ case 5:
1573
+ _c.sent();
1574
+ results.push("CLI config (".concat(path.getDisplayPath(configPaths.cli), ")"));
1575
+ _c.label = 6;
1576
+ case 6:
1577
+ if (!configPaths.app) return [3 /*break*/, 12];
1578
+ validatedPath = path.validatePath(configPaths.app);
1579
+ config = void 0;
1580
+ _c.label = 7;
1581
+ case 7:
1582
+ _c.trys.push([7, 9, , 10]);
1583
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1584
+ case 8:
1585
+ content_3 = _c.sent();
1586
+ config = file.safeJSONParse(content_3, validatedPath);
1587
+ return [3 /*break*/, 10];
1588
+ case 9:
1589
+ _b = _c.sent();
1590
+ config = { mcpServers: {} };
1591
+ return [3 /*break*/, 10];
1592
+ case 10:
1593
+ if (!config.mcpServers) {
1594
+ config.mcpServers = {};
1595
+ }
1596
+ if (config.mcpServers[options.name]) {
1597
+ throw new Error("MCP server already exists in app config: ".concat(options.name));
1598
+ }
1599
+ config.mcpServers[options.name] = serverConfig;
1600
+ content = file.formatJSON(config);
1601
+ return [4 /*yield*/, file.atomicWrite(validatedPath, content, { createBackup: true })];
1602
+ case 11:
1603
+ _c.sent();
1604
+ results.push("App config (".concat(path.getDisplayPath(configPaths.app), ")"));
1605
+ _c.label = 12;
1606
+ case 12: return [2 /*return*/, {
1607
+ content: [
1608
+ {
1609
+ type: 'text',
1610
+ text: "Successfully added MCP server: ".concat(options.name, "\nAdded to: ").concat(results.join(', ')),
1611
+ },
1612
+ ],
1613
+ }];
1614
+ }
1615
+ });
1616
+ });
1617
+ }
1618
+ function handleMCPRemove(args) {
1619
+ return __awaiter(this, void 0, void 0, function () {
1620
+ var schema, _a, name, _b, target, configPaths, results, found, validatedPath, content, config, newContent, _c, validatedPath, content, config, newContent, _d;
1621
+ return __generator(this, function (_e) {
1622
+ switch (_e.label) {
1623
+ case 0:
1624
+ schema = zod_1.z.object({
1625
+ name: zod_1.z.string(),
1626
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1627
+ });
1628
+ _a = schema.parse(args), name = _a.name, _b = _a.target, target = _b === void 0 ? 'both' : _b;
1629
+ configPaths = (0, path_js_1.getMCPConfigPaths)(target);
1630
+ results = [];
1631
+ found = false;
1632
+ if (!configPaths.cli) return [3 /*break*/, 6];
1633
+ _e.label = 1;
1634
+ case 1:
1635
+ _e.trys.push([1, 5, , 6]);
1636
+ validatedPath = path.validatePath(configPaths.cli);
1637
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1638
+ case 2:
1639
+ content = _e.sent();
1640
+ config = file.safeJSONParse(content, validatedPath);
1641
+ if (!(config.mcpServers && config.mcpServers[name])) return [3 /*break*/, 4];
1642
+ delete config.mcpServers[name];
1643
+ newContent = file.formatJSON(config);
1644
+ return [4 /*yield*/, file.atomicWrite(validatedPath, newContent, { createBackup: true })];
1645
+ case 3:
1646
+ _e.sent();
1647
+ results.push("CLI config (".concat(path.getDisplayPath(configPaths.cli), ")"));
1648
+ found = true;
1649
+ _e.label = 4;
1650
+ case 4: return [3 /*break*/, 6];
1651
+ case 5:
1652
+ _c = _e.sent();
1653
+ return [3 /*break*/, 6];
1654
+ case 6:
1655
+ if (!configPaths.app) return [3 /*break*/, 12];
1656
+ _e.label = 7;
1657
+ case 7:
1658
+ _e.trys.push([7, 11, , 12]);
1659
+ validatedPath = path.validatePath(configPaths.app);
1660
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1661
+ case 8:
1662
+ content = _e.sent();
1663
+ config = file.safeJSONParse(content, validatedPath);
1664
+ if (!(config.mcpServers && config.mcpServers[name])) return [3 /*break*/, 10];
1665
+ delete config.mcpServers[name];
1666
+ newContent = file.formatJSON(config);
1667
+ return [4 /*yield*/, file.atomicWrite(validatedPath, newContent, { createBackup: true })];
1668
+ case 9:
1669
+ _e.sent();
1670
+ results.push("App config (".concat(path.getDisplayPath(configPaths.app), ")"));
1671
+ found = true;
1672
+ _e.label = 10;
1673
+ case 10: return [3 /*break*/, 12];
1674
+ case 11:
1675
+ _d = _e.sent();
1676
+ return [3 /*break*/, 12];
1677
+ case 12:
1678
+ if (!found) {
1679
+ throw new Error("MCP server not found: ".concat(name));
1680
+ }
1681
+ return [2 /*return*/, {
1682
+ content: [
1683
+ {
1684
+ type: 'text',
1685
+ text: "Successfully removed MCP server: ".concat(name, "\nRemoved from: ").concat(results.join(', ')),
1686
+ },
1687
+ ],
1688
+ }];
1689
+ }
1690
+ });
1691
+ });
1692
+ }
1693
+ function handleMCPUpdate(args) {
1694
+ return __awaiter(this, void 0, void 0, function () {
1695
+ var schema, options, configPaths, results, found, validatedPath, content, config, serverConfig, newContent, _a, validatedPath, content, config, serverConfig, newContent, _b;
1696
+ return __generator(this, function (_c) {
1697
+ switch (_c.label) {
1698
+ case 0:
1699
+ schema = zod_1.z.object({
1700
+ name: zod_1.z.string(),
1701
+ command: zod_1.z.string().optional(),
1702
+ args: zod_1.z.array(zod_1.z.string()).optional(),
1703
+ url: zod_1.z.string().optional(),
1704
+ env: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
1705
+ headers: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
1706
+ description: zod_1.z.string().optional(),
1707
+ alwaysAllow: zod_1.z.boolean().optional(),
1708
+ timeout: zod_1.z.number().optional(),
1709
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1710
+ });
1711
+ options = schema.parse(args);
1712
+ configPaths = (0, path_js_1.getMCPConfigPaths)(options.target || 'both');
1713
+ results = [];
1714
+ found = false;
1715
+ if (!configPaths.cli) return [3 /*break*/, 6];
1716
+ _c.label = 1;
1717
+ case 1:
1718
+ _c.trys.push([1, 5, , 6]);
1719
+ validatedPath = path.validatePath(configPaths.cli);
1720
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1721
+ case 2:
1722
+ content = _c.sent();
1723
+ config = file.safeJSONParse(content, validatedPath);
1724
+ if (!(config.mcpServers && config.mcpServers[options.name])) return [3 /*break*/, 4];
1725
+ serverConfig = config.mcpServers[options.name];
1726
+ if (options.command !== undefined)
1727
+ serverConfig.command = options.command;
1728
+ if (options.args !== undefined)
1729
+ serverConfig.args = options.args;
1730
+ if (options.url !== undefined)
1731
+ serverConfig.url = options.url;
1732
+ if (options.env !== undefined)
1733
+ serverConfig.env = options.env;
1734
+ if (options.headers !== undefined)
1735
+ serverConfig.headers = options.headers;
1736
+ if (options.description !== undefined)
1737
+ serverConfig.description = options.description;
1738
+ if (options.alwaysAllow !== undefined)
1739
+ serverConfig.alwaysAllow = options.alwaysAllow;
1740
+ if (options.timeout !== undefined)
1741
+ serverConfig.timeout = options.timeout;
1742
+ newContent = file.formatJSON(config);
1743
+ return [4 /*yield*/, file.atomicWrite(validatedPath, newContent, { createBackup: true })];
1744
+ case 3:
1745
+ _c.sent();
1746
+ results.push("CLI config (".concat(path.getDisplayPath(configPaths.cli), ")"));
1747
+ found = true;
1748
+ _c.label = 4;
1749
+ case 4: return [3 /*break*/, 6];
1750
+ case 5:
1751
+ _a = _c.sent();
1752
+ return [3 /*break*/, 6];
1753
+ case 6:
1754
+ if (!configPaths.app) return [3 /*break*/, 12];
1755
+ _c.label = 7;
1756
+ case 7:
1757
+ _c.trys.push([7, 11, , 12]);
1758
+ validatedPath = path.validatePath(configPaths.app);
1759
+ return [4 /*yield*/, file.safeReadFile(validatedPath)];
1760
+ case 8:
1761
+ content = _c.sent();
1762
+ config = file.safeJSONParse(content, validatedPath);
1763
+ if (!(config.mcpServers && config.mcpServers[options.name])) return [3 /*break*/, 10];
1764
+ serverConfig = config.mcpServers[options.name];
1765
+ if (options.command !== undefined)
1766
+ serverConfig.command = options.command;
1767
+ if (options.args !== undefined)
1768
+ serverConfig.args = options.args;
1769
+ if (options.url !== undefined)
1770
+ serverConfig.url = options.url;
1771
+ if (options.env !== undefined)
1772
+ serverConfig.env = options.env;
1773
+ if (options.headers !== undefined)
1774
+ serverConfig.headers = options.headers;
1775
+ if (options.description !== undefined)
1776
+ serverConfig.description = options.description;
1777
+ if (options.alwaysAllow !== undefined)
1778
+ serverConfig.alwaysAllow = options.alwaysAllow;
1779
+ if (options.timeout !== undefined)
1780
+ serverConfig.timeout = options.timeout;
1781
+ newContent = file.formatJSON(config);
1782
+ return [4 /*yield*/, file.atomicWrite(validatedPath, newContent, { createBackup: true })];
1783
+ case 9:
1784
+ _c.sent();
1785
+ results.push("App config (".concat(path.getDisplayPath(configPaths.app), ")"));
1786
+ found = true;
1787
+ _c.label = 10;
1788
+ case 10: return [3 /*break*/, 12];
1789
+ case 11:
1790
+ _b = _c.sent();
1791
+ return [3 /*break*/, 12];
1792
+ case 12:
1793
+ if (!found) {
1794
+ throw new Error("MCP server not found: ".concat(options.name));
1795
+ }
1796
+ return [2 /*return*/, {
1797
+ content: [
1798
+ {
1799
+ type: 'text',
1800
+ text: "Successfully updated MCP server: ".concat(options.name, "\nUpdated in: ").concat(results.join(', ')),
1801
+ },
1802
+ ],
1803
+ }];
1804
+ }
1805
+ });
1806
+ });
1807
+ }
1808
+ function handleMCPInstall(args) {
1809
+ return __awaiter(this, void 0, void 0, function () {
1810
+ var schema, options, target, source, installDir, mkdir, serverName, serverConfig, installPath, _a, packageName, version, execSync, packageJsonPath, packageJsonContent, packageJson, entryPoint, binName, repo, repoName, execSync, packageJsonPath, packageJsonContent, packageJson, entryPoint, distPath, packageJsonPath, packageJsonContent, packageJson, entryPoint, entryPath, configPaths, results, validatedConfigPath, config, content_4, _b, content, validatedConfigPath, config, content_5, _c, content;
1811
+ var _d;
1812
+ return __generator(this, function (_e) {
1813
+ switch (_e.label) {
1814
+ case 0:
1815
+ schema = zod_1.z.object({
1816
+ source: zod_1.z.enum(['npm', 'github', 'local', 'url']).optional(),
1817
+ package: zod_1.z.string(),
1818
+ name: zod_1.z.string().optional(),
1819
+ version: zod_1.z.string().optional(),
1820
+ env: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
1821
+ description: zod_1.z.string().optional(),
1822
+ args: zod_1.z.array(zod_1.z.string()).optional(),
1823
+ installDir: zod_1.z.string().optional(),
1824
+ force: zod_1.z.boolean().optional(),
1825
+ target: zod_1.z.enum(['cli', 'app', 'both']).optional(),
1826
+ });
1827
+ options = schema.parse(args);
1828
+ target = options.target || 'both';
1829
+ source = options.source;
1830
+ if (!source) {
1831
+ if (options.package.startsWith('http') || options.package.startsWith('git+')) {
1832
+ source = 'github';
1833
+ }
1834
+ else if (options.package.startsWith('/') || options.package.startsWith('./') || options.package.startsWith('../')) {
1835
+ source = 'local';
1836
+ }
1837
+ else if (options.package.includes('/')) {
1838
+ // Could be npm scoped package or GitHub - default to npm for @scope/name pattern
1839
+ source = options.package.startsWith('@') ? 'npm' : 'github';
1840
+ }
1841
+ else {
1842
+ source = 'npm';
1843
+ }
1844
+ }
1845
+ installDir = options.installDir || (0, node_path_1.join)(path.getHomeDir(), '.claude', 'mcp-servers');
1846
+ return [4 /*yield*/, Promise.resolve().then(function () { return require('node:fs/promises'); })];
1847
+ case 1:
1848
+ mkdir = (_e.sent()).mkdir;
1849
+ return [4 /*yield*/, mkdir(installDir, { recursive: true })];
1850
+ case 2:
1851
+ _e.sent();
1852
+ serverName = options.name;
1853
+ serverConfig = {};
1854
+ _a = source;
1855
+ switch (_a) {
1856
+ case 'npm': return [3 /*break*/, 3];
1857
+ case 'github': return [3 /*break*/, 8];
1858
+ case 'local': return [3 /*break*/, 12];
1859
+ case 'url': return [3 /*break*/, 14];
1860
+ }
1861
+ return [3 /*break*/, 15];
1862
+ case 3:
1863
+ packageName = options.package;
1864
+ version = options.version || 'latest';
1865
+ serverName = serverName || packageName.replace(/^@[^/]+\//, '').replace(/^mcp-server-/, '').replace(/^server-/, '');
1866
+ installPath = (0, node_path_1.join)(installDir, 'node_modules', packageName);
1867
+ if (!(!options.force && path.pathExists((0, node_path_1.join)(installPath, 'package.json')))) return [3 /*break*/, 4];
1868
+ return [3 /*break*/, 6];
1869
+ case 4: return [4 /*yield*/, Promise.resolve().then(function () { return require('node:child_process'); })];
1870
+ case 5:
1871
+ execSync = (_e.sent()).execSync;
1872
+ execSync("bun install ".concat(packageName, "@").concat(version), {
1873
+ cwd: installDir,
1874
+ stdio: 'inherit',
1875
+ });
1876
+ _e.label = 6;
1877
+ case 6:
1878
+ packageJsonPath = (0, node_path_1.join)(installPath, 'package.json');
1879
+ return [4 /*yield*/, file.safeReadFile(packageJsonPath)];
1880
+ case 7:
1881
+ packageJsonContent = _e.sent();
1882
+ packageJson = JSON.parse(packageJsonContent);
1883
+ entryPoint = packageJson.bin || packageJson.main || 'index.js';
1884
+ if (typeof entryPoint === 'string') {
1885
+ serverConfig.command = 'node';
1886
+ serverConfig.args = __spreadArray([(0, node_path_1.join)(installPath, entryPoint)], (options.args || []), true);
1887
+ }
1888
+ else if (typeof entryPoint === 'object') {
1889
+ binName = Object.keys(entryPoint)[0];
1890
+ serverConfig.command = 'node';
1891
+ serverConfig.args = __spreadArray([(0, node_path_1.join)(installPath, entryPoint[binName])], (options.args || []), true);
1892
+ }
1893
+ serverConfig.description = options.description || packageJson.description;
1894
+ return [3 /*break*/, 16];
1895
+ case 8:
1896
+ repo = options.package.replace(/\.git$/, '');
1897
+ repoName = repo.split('/').pop() || 'mcp-server';
1898
+ serverName = serverName || repoName.replace(/^mcp-/, '').replace(/^server-/, '');
1899
+ installPath = (0, node_path_1.join)(installDir, repoName);
1900
+ if (!(options.force || !path.pathExists((0, node_path_1.join)(installPath, '.git')))) return [3 /*break*/, 10];
1901
+ return [4 /*yield*/, Promise.resolve().then(function () { return require('node:child_process'); })];
1902
+ case 9:
1903
+ execSync = (_e.sent()).execSync;
1904
+ execSync("git clone ".concat(options.package, " \"").concat(installPath, "\""), {
1905
+ stdio: 'inherit',
1906
+ });
1907
+ _e.label = 10;
1908
+ case 10:
1909
+ packageJsonPath = (0, node_path_1.join)(installPath, 'package.json');
1910
+ return [4 /*yield*/, file.safeReadFile(packageJsonPath)];
1911
+ case 11:
1912
+ packageJsonContent = _e.sent();
1913
+ packageJson = JSON.parse(packageJsonContent);
1914
+ entryPoint = packageJson.main || 'dist/index.js';
1915
+ distPath = (0, node_path_1.join)(installPath, entryPoint);
1916
+ serverConfig.command = 'node';
1917
+ serverConfig.args = __spreadArray([distPath], (options.args || []), true);
1918
+ serverConfig.description = options.description || packageJson.description;
1919
+ return [3 /*break*/, 16];
1920
+ case 12:
1921
+ // Link local package
1922
+ installPath = (0, node_path_1.resolve)(options.package);
1923
+ if (!path.pathExists(installPath)) {
1924
+ throw new Error("Local path does not exist: ".concat(installPath));
1925
+ }
1926
+ packageJsonPath = (0, node_path_1.join)(installPath, 'package.json');
1927
+ return [4 /*yield*/, file.safeReadFile(packageJsonPath)];
1928
+ case 13:
1929
+ packageJsonContent = _e.sent();
1930
+ packageJson = JSON.parse(packageJsonContent);
1931
+ serverName = serverName || ((_d = packageJson.name) === null || _d === void 0 ? void 0 : _d.replace(/^@[^/]+\//, '').replace(/^mcp-server-/, '').replace(/^server-/, '')) || 'local-mcp';
1932
+ entryPoint = packageJson.bin || packageJson.main || 'dist/index.js';
1933
+ entryPath = typeof entryPoint === 'string' ? (0, node_path_1.join)(installPath, entryPoint) : installPath;
1934
+ serverConfig.command = 'node';
1935
+ serverConfig.args = __spreadArray([entryPath], (options.args || []), true);
1936
+ serverConfig.description = options.description || packageJson.description;
1937
+ return [3 /*break*/, 16];
1938
+ case 14:
1939
+ {
1940
+ // Download from URL and install
1941
+ throw new Error('URL source not yet implemented');
1942
+ }
1943
+ _e.label = 15;
1944
+ case 15:
1945
+ {
1946
+ throw new Error("Unknown source type: ".concat(source));
1947
+ }
1948
+ _e.label = 16;
1949
+ case 16:
1950
+ // Add environment variables
1951
+ if (options.env) {
1952
+ serverConfig.env = options.env;
1953
+ }
1954
+ configPaths = (0, path_js_1.getMCPConfigPaths)(target);
1955
+ results = [];
1956
+ if (!configPaths.cli) return [3 /*break*/, 22];
1957
+ validatedConfigPath = path.validatePath(configPaths.cli);
1958
+ config = void 0;
1959
+ _e.label = 17;
1960
+ case 17:
1961
+ _e.trys.push([17, 19, , 20]);
1962
+ return [4 /*yield*/, file.safeReadFile(validatedConfigPath)];
1963
+ case 18:
1964
+ content_4 = _e.sent();
1965
+ config = file.safeJSONParse(content_4, validatedConfigPath);
1966
+ return [3 /*break*/, 20];
1967
+ case 19:
1968
+ _b = _e.sent();
1969
+ config = { mcpServers: {} };
1970
+ return [3 /*break*/, 20];
1971
+ case 20:
1972
+ if (!config.mcpServers) {
1973
+ config.mcpServers = {};
1974
+ }
1975
+ config.mcpServers[serverName] = serverConfig;
1976
+ content = file.formatJSON(config);
1977
+ return [4 /*yield*/, file.atomicWrite(validatedConfigPath, content, { createBackup: true })];
1978
+ case 21:
1979
+ _e.sent();
1980
+ results.push("CLI config (".concat(path.getDisplayPath(configPaths.cli), ")"));
1981
+ _e.label = 22;
1982
+ case 22:
1983
+ if (!configPaths.app) return [3 /*break*/, 28];
1984
+ validatedConfigPath = path.validatePath(configPaths.app);
1985
+ config = void 0;
1986
+ _e.label = 23;
1987
+ case 23:
1988
+ _e.trys.push([23, 25, , 26]);
1989
+ return [4 /*yield*/, file.safeReadFile(validatedConfigPath)];
1990
+ case 24:
1991
+ content_5 = _e.sent();
1992
+ config = file.safeJSONParse(content_5, validatedConfigPath);
1993
+ return [3 /*break*/, 26];
1994
+ case 25:
1995
+ _c = _e.sent();
1996
+ config = { mcpServers: {} };
1997
+ return [3 /*break*/, 26];
1998
+ case 26:
1999
+ if (!config.mcpServers) {
2000
+ config.mcpServers = {};
2001
+ }
2002
+ config.mcpServers[serverName] = serverConfig;
2003
+ content = file.formatJSON(config);
2004
+ return [4 /*yield*/, file.atomicWrite(validatedConfigPath, content, { createBackup: true })];
2005
+ case 27:
2006
+ _e.sent();
2007
+ results.push("App config (".concat(path.getDisplayPath(configPaths.app), ")"));
2008
+ _e.label = 28;
2009
+ case 28: return [2 /*return*/, {
2010
+ content: [
2011
+ {
2012
+ type: 'text',
2013
+ text: JSON.stringify({
2014
+ success: true,
2015
+ message: "Successfully installed MCP server: ".concat(serverName),
2016
+ addedTo: results,
2017
+ server: {
2018
+ name: serverName,
2019
+ source: source,
2020
+ package: options.package,
2021
+ installPath: installPath,
2022
+ config: serverConfig,
2023
+ },
2024
+ }, null, 2),
2025
+ },
2026
+ ],
2027
+ }];
2028
+ }
2029
+ });
2030
+ });
2031
+ }
2032
+ function handleMCPSync(args) {
2033
+ return __awaiter(this, void 0, void 0, function () {
2034
+ var schema, _a, _b, source, _c, dryRun, sourcePath, targetPath, sourceLabel, targetLabel, sourceConfig, validatedSourcePath, content_6, _d, sourceServers, targetConfig, validatedTargetPath_1, content_7, _e, sourceServerNames, targetServerNames, toAdd, toUpdate, toRemove, summary, results, _i, toAdd_1, name_3, _f, toUpdate_1, name_4, _g, toRemove_1, name_5, validatedTargetPath, content;
2035
+ return __generator(this, function (_h) {
2036
+ switch (_h.label) {
2037
+ case 0:
2038
+ schema = zod_1.z.object({
2039
+ source: zod_1.z.enum(['cli', 'app']).optional(),
2040
+ dryRun: zod_1.z.boolean().optional(),
2041
+ });
2042
+ _a = schema.parse(args), _b = _a.source, source = _b === void 0 ? 'app' : _b, _c = _a.dryRun, dryRun = _c === void 0 ? false : _c;
2043
+ sourcePath = source === 'cli' ? path.getClaudeCliConfigPath() : path.getConfigPaths().appConfig;
2044
+ targetPath = source === 'cli' ? path.getConfigPaths().appConfig : path.getClaudeCliConfigPath();
2045
+ sourceLabel = source === 'cli' ? 'CLI' : 'App';
2046
+ targetLabel = source === 'cli' ? 'App' : 'CLI';
2047
+ _h.label = 1;
2048
+ case 1:
2049
+ _h.trys.push([1, 3, , 4]);
2050
+ validatedSourcePath = path.validatePath(sourcePath);
2051
+ return [4 /*yield*/, file.safeReadFile(validatedSourcePath)];
2052
+ case 2:
2053
+ content_6 = _h.sent();
2054
+ sourceConfig = file.safeJSONParse(content_6, validatedSourcePath);
2055
+ return [3 /*break*/, 4];
2056
+ case 3:
2057
+ _d = _h.sent();
2058
+ return [2 /*return*/, {
2059
+ content: [
2060
+ {
2061
+ type: 'text',
2062
+ text: "Source ".concat(sourceLabel, " config not found or empty"),
2063
+ },
2064
+ ],
2065
+ }];
2066
+ case 4:
2067
+ sourceServers = sourceConfig.mcpServers || {};
2068
+ _h.label = 5;
2069
+ case 5:
2070
+ _h.trys.push([5, 7, , 8]);
2071
+ validatedTargetPath_1 = path.validatePath(targetPath);
2072
+ return [4 /*yield*/, file.safeReadFile(validatedTargetPath_1)];
2073
+ case 6:
2074
+ content_7 = _h.sent();
2075
+ targetConfig = file.safeJSONParse(content_7, validatedTargetPath_1);
2076
+ return [3 /*break*/, 8];
2077
+ case 7:
2078
+ _e = _h.sent();
2079
+ targetConfig = { mcpServers: {} };
2080
+ return [3 /*break*/, 8];
2081
+ case 8:
2082
+ if (!targetConfig.mcpServers) {
2083
+ targetConfig.mcpServers = {};
2084
+ }
2085
+ sourceServerNames = new Set(Object.keys(sourceServers));
2086
+ targetServerNames = new Set(Object.keys(targetConfig.mcpServers));
2087
+ toAdd = __spreadArray([], sourceServerNames, true).filter(function (name) { return !targetServerNames.has(name); });
2088
+ toUpdate = __spreadArray([], sourceServerNames, true).filter(function (name) {
2089
+ return targetServerNames.has(name) &&
2090
+ JSON.stringify(sourceServers[name]) !== JSON.stringify(targetConfig.mcpServers[name]);
2091
+ });
2092
+ toRemove = __spreadArray([], targetServerNames, true).filter(function (name) { return !sourceServerNames.has(name); });
2093
+ summary = {
2094
+ source: sourceLabel,
2095
+ target: targetLabel,
2096
+ toAdd: toAdd,
2097
+ toUpdate: toUpdate,
2098
+ toRemove: toRemove,
2099
+ totalChanges: toAdd.length + toUpdate.length + toRemove.length,
2100
+ };
2101
+ if (dryRun) {
2102
+ return [2 /*return*/, {
2103
+ content: [
2104
+ {
2105
+ type: 'text',
2106
+ text: JSON.stringify(__assign(__assign({ mode: 'dry-run' }, summary), { message: "Would sync ".concat(summary.totalChanges, " changes from ").concat(sourceLabel, " to ").concat(targetLabel) }), null, 2),
2107
+ },
2108
+ ],
2109
+ }];
2110
+ }
2111
+ results = [];
2112
+ // Add new servers
2113
+ for (_i = 0, toAdd_1 = toAdd; _i < toAdd_1.length; _i++) {
2114
+ name_3 = toAdd_1[_i];
2115
+ targetConfig.mcpServers[name_3] = sourceServers[name_3];
2116
+ results.push("Added: ".concat(name_3));
2117
+ }
2118
+ // Update existing servers
2119
+ for (_f = 0, toUpdate_1 = toUpdate; _f < toUpdate_1.length; _f++) {
2120
+ name_4 = toUpdate_1[_f];
2121
+ targetConfig.mcpServers[name_4] = sourceServers[name_4];
2122
+ results.push("Updated: ".concat(name_4));
2123
+ }
2124
+ // Remove servers not in source
2125
+ for (_g = 0, toRemove_1 = toRemove; _g < toRemove_1.length; _g++) {
2126
+ name_5 = toRemove_1[_g];
2127
+ delete targetConfig.mcpServers[name_5];
2128
+ results.push("Removed: ".concat(name_5));
2129
+ }
2130
+ validatedTargetPath = path.validatePath(targetPath);
2131
+ content = file.formatJSON(targetConfig);
2132
+ return [4 /*yield*/, file.atomicWrite(validatedTargetPath, content, { createBackup: true })];
2133
+ case 9:
2134
+ _h.sent();
2135
+ return [2 /*return*/, {
2136
+ content: [
2137
+ {
2138
+ type: 'text',
2139
+ text: JSON.stringify(__assign(__assign({ mode: 'sync' }, summary), { changes: results, message: "Synced ".concat(summary.totalChanges, " changes from ").concat(sourceLabel, " to ").concat(targetLabel) }), null, 2),
2140
+ },
2141
+ ],
2142
+ }];
2143
+ }
2144
+ });
2145
+ });
2146
+ }
2147
+ // ============================================================================
2148
+ // Server Startup
2149
+ // ============================================================================
2150
+ function main() {
2151
+ return __awaiter(this, void 0, void 0, function () {
2152
+ var transport;
2153
+ return __generator(this, function (_a) {
2154
+ switch (_a.label) {
2155
+ case 0:
2156
+ transport = new stdio_js_1.StdioServerTransport();
2157
+ return [4 /*yield*/, server.connect(transport)];
2158
+ case 1:
2159
+ _a.sent();
2160
+ console.error('Claude Code Config MCP Server running');
2161
+ console.error('Version: 1.0.0');
2162
+ console.error('Runtime: Bun');
2163
+ return [2 /*return*/];
2164
+ }
2165
+ });
2166
+ });
2167
+ }
2168
+ main().catch(function (error) {
2169
+ console.error('Fatal error:', error);
2170
+ process.exit(1);
2171
+ });