@fractalizer/mcp-cli 0.2.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.
Files changed (115) hide show
  1. package/README.md +438 -0
  2. package/dist/commands/connect.command.d.ts +32 -0
  3. package/dist/commands/connect.command.d.ts.map +1 -0
  4. package/dist/commands/connect.command.js +120 -0
  5. package/dist/commands/connect.command.js.map +1 -0
  6. package/dist/commands/disconnect.command.d.ts +36 -0
  7. package/dist/commands/disconnect.command.d.ts.map +1 -0
  8. package/dist/commands/disconnect.command.js +97 -0
  9. package/dist/commands/disconnect.command.js.map +1 -0
  10. package/dist/commands/index.d.ts +10 -0
  11. package/dist/commands/index.d.ts.map +1 -0
  12. package/dist/commands/index.js +13 -0
  13. package/dist/commands/index.js.map +1 -0
  14. package/dist/commands/list.command.d.ts +23 -0
  15. package/dist/commands/list.command.d.ts.map +1 -0
  16. package/dist/commands/list.command.js +34 -0
  17. package/dist/commands/list.command.js.map +1 -0
  18. package/dist/commands/status.command.d.ts +23 -0
  19. package/dist/commands/status.command.d.ts.map +1 -0
  20. package/dist/commands/status.command.js +61 -0
  21. package/dist/commands/status.command.js.map +1 -0
  22. package/dist/commands/validate.command.d.ts +25 -0
  23. package/dist/commands/validate.command.d.ts.map +1 -0
  24. package/dist/commands/validate.command.js +58 -0
  25. package/dist/commands/validate.command.js.map +1 -0
  26. package/dist/connectors/base/base-connector.d.ts +89 -0
  27. package/dist/connectors/base/base-connector.d.ts.map +1 -0
  28. package/dist/connectors/base/base-connector.js +99 -0
  29. package/dist/connectors/base/base-connector.js.map +1 -0
  30. package/dist/connectors/base/configurable-connector.d.ts +68 -0
  31. package/dist/connectors/base/configurable-connector.d.ts.map +1 -0
  32. package/dist/connectors/base/configurable-connector.js +73 -0
  33. package/dist/connectors/base/configurable-connector.js.map +1 -0
  34. package/dist/connectors/base/connector.interface.d.ts +62 -0
  35. package/dist/connectors/base/connector.interface.d.ts.map +1 -0
  36. package/dist/connectors/base/connector.interface.js +6 -0
  37. package/dist/connectors/base/connector.interface.js.map +1 -0
  38. package/dist/connectors/base/file-based-connector.d.ts +97 -0
  39. package/dist/connectors/base/file-based-connector.d.ts.map +1 -0
  40. package/dist/connectors/base/file-based-connector.js +185 -0
  41. package/dist/connectors/base/file-based-connector.js.map +1 -0
  42. package/dist/connectors/base/index.d.ts +9 -0
  43. package/dist/connectors/base/index.d.ts.map +1 -0
  44. package/dist/connectors/base/index.js +9 -0
  45. package/dist/connectors/base/index.js.map +1 -0
  46. package/dist/connectors/claude-code/claude-code.connector.d.ts +41 -0
  47. package/dist/connectors/claude-code/claude-code.connector.d.ts.map +1 -0
  48. package/dist/connectors/claude-code/claude-code.connector.js +96 -0
  49. package/dist/connectors/claude-code/claude-code.connector.js.map +1 -0
  50. package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts +38 -0
  51. package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts.map +1 -0
  52. package/dist/connectors/claude-desktop/claude-desktop.connector.js +68 -0
  53. package/dist/connectors/claude-desktop/claude-desktop.connector.js.map +1 -0
  54. package/dist/connectors/codex/codex.connector.d.ts +51 -0
  55. package/dist/connectors/codex/codex.connector.d.ts.map +1 -0
  56. package/dist/connectors/codex/codex.connector.js +76 -0
  57. package/dist/connectors/codex/codex.connector.js.map +1 -0
  58. package/dist/connectors/connector-factory.d.ts +42 -0
  59. package/dist/connectors/connector-factory.d.ts.map +1 -0
  60. package/dist/connectors/connector-factory.js +81 -0
  61. package/dist/connectors/connector-factory.js.map +1 -0
  62. package/dist/connectors/gemini/gemini.connector.d.ts +41 -0
  63. package/dist/connectors/gemini/gemini.connector.d.ts.map +1 -0
  64. package/dist/connectors/gemini/gemini.connector.js +61 -0
  65. package/dist/connectors/gemini/gemini.connector.js.map +1 -0
  66. package/dist/connectors/index.d.ts +13 -0
  67. package/dist/connectors/index.d.ts.map +1 -0
  68. package/dist/connectors/index.js +19 -0
  69. package/dist/connectors/index.js.map +1 -0
  70. package/dist/connectors/qwen/qwen.connector.d.ts +41 -0
  71. package/dist/connectors/qwen/qwen.connector.d.ts.map +1 -0
  72. package/dist/connectors/qwen/qwen.connector.js +61 -0
  73. package/dist/connectors/qwen/qwen.connector.js.map +1 -0
  74. package/dist/connectors/registry.d.ts +55 -0
  75. package/dist/connectors/registry.d.ts.map +1 -0
  76. package/dist/connectors/registry.js +75 -0
  77. package/dist/connectors/registry.js.map +1 -0
  78. package/dist/index.d.ts +11 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +15 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/tsconfig.tsbuildinfo +1 -0
  83. package/dist/types/base.types.d.ts +116 -0
  84. package/dist/types/base.types.d.ts.map +1 -0
  85. package/dist/types/base.types.js +6 -0
  86. package/dist/types/base.types.js.map +1 -0
  87. package/dist/types.d.ts +38 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +7 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/utils/command-executor.d.ts +78 -0
  92. package/dist/utils/command-executor.d.ts.map +1 -0
  93. package/dist/utils/command-executor.js +114 -0
  94. package/dist/utils/command-executor.js.map +1 -0
  95. package/dist/utils/config-manager.d.ts +76 -0
  96. package/dist/utils/config-manager.d.ts.map +1 -0
  97. package/dist/utils/config-manager.js +123 -0
  98. package/dist/utils/config-manager.js.map +1 -0
  99. package/dist/utils/file-manager.d.ts +146 -0
  100. package/dist/utils/file-manager.d.ts.map +1 -0
  101. package/dist/utils/file-manager.js +200 -0
  102. package/dist/utils/file-manager.js.map +1 -0
  103. package/dist/utils/index.d.ts +10 -0
  104. package/dist/utils/index.d.ts.map +1 -0
  105. package/dist/utils/index.js +10 -0
  106. package/dist/utils/index.js.map +1 -0
  107. package/dist/utils/interactive-prompter.d.ts +109 -0
  108. package/dist/utils/interactive-prompter.d.ts.map +1 -0
  109. package/dist/utils/interactive-prompter.js +184 -0
  110. package/dist/utils/interactive-prompter.js.map +1 -0
  111. package/dist/utils/logger.d.ts +113 -0
  112. package/dist/utils/logger.d.ts.map +1 -0
  113. package/dist/utils/logger.js +130 -0
  114. package/dist/utils/logger.js.map +1 -0
  115. package/package.json +81 -0
package/README.md ADDED
@@ -0,0 +1,438 @@
1
+ # @fractalizer/mcp-cli
2
+
3
+ **Generic CLI фреймворк для управления подключениями MCP серверов к различным клиентам.**
4
+
5
+ ---
6
+
7
+ ## 🎯 Возможности
8
+
9
+ - **Универсальный** — подходит для любого MCP сервера
10
+ - **Поддержка множества клиентов** — Claude Desktop, Claude Code, Codex, Gemini, Qwen
11
+ - **Типобезопасность** — TypeScript generics для конфигурации
12
+ - **Декларативные промпты** — простая настройка через `ConfigPromptDefinition`
13
+ - **Безопасное хранение** — секреты не сохраняются, только безопасные поля
14
+ - **Расширяемость** — легко добавить новый клиент или кастомизировать промпты
15
+ - **Интерактивность** — удобный CLI с выбором из списка, валидацией, спиннерами
16
+
17
+ ---
18
+
19
+ ## 📦 Установка
20
+
21
+ ```bash
22
+ npm install @fractalizer/mcp-cli
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 🚀 Быстрый старт
28
+
29
+ ### Минимальный пример
30
+
31
+ ```typescript
32
+ import { connectCommand, ConnectorRegistry, ConfigManager } from '@fractalizer/mcp-cli';
33
+ import type { BaseMCPServerConfig, ConfigPromptDefinition } from '@fractalizer/mcp-cli';
34
+ import {
35
+ ClaudeDesktopConnector,
36
+ ClaudeCodeConnector,
37
+ } from '@fractalizer/mcp-cli/connectors';
38
+
39
+ // 1. Определяем конфигурацию вашего MCP сервера
40
+ interface MyServerConfig extends BaseMCPServerConfig {
41
+ apiToken: string; // Секрет
42
+ orgId: string; // Безопасное поле
43
+ }
44
+
45
+ // 2. Создаем реестр и регистрируем коннекторы
46
+ const registry = new ConnectorRegistry<MyServerConfig>();
47
+ registry.register(new ClaudeDesktopConnector('my-server', 'dist/index.js'));
48
+ registry.register(new ClaudeCodeConnector('my-server', 'dist/index.js'));
49
+
50
+ // 3. Создаем менеджер конфигурации
51
+ const configManager = new ConfigManager<MyServerConfig>({
52
+ projectName: 'my-mcp-server',
53
+ safeFields: ['orgId', 'logLevel', 'projectPath'], // БЕЗ apiToken!
54
+ });
55
+
56
+ // 4. Определяем промпты для сбора конфигурации
57
+ const configPrompts: ConfigPromptDefinition<MyServerConfig>[] = [
58
+ {
59
+ name: 'apiToken',
60
+ type: 'password',
61
+ message: 'API токен:',
62
+ validate: (value) => (value ? true : 'Токен обязателен'),
63
+ },
64
+ {
65
+ name: 'orgId',
66
+ type: 'input',
67
+ message: 'ID организации:',
68
+ default: (saved) => saved?.orgId, // Используем сохраненное значение
69
+ },
70
+ ];
71
+
72
+ // 5. Запускаем команду подключения
73
+ await connectCommand({
74
+ registry,
75
+ configManager,
76
+ configPrompts,
77
+ });
78
+ ```
79
+
80
+ **Что произойдет:**
81
+ 1. CLI найдет установленные MCP клиенты
82
+ 2. Предложит выбрать клиент из списка
83
+ 3. Соберет конфигурацию через интерактивные промпты
84
+ 4. Провалидирует конфигурацию
85
+ 5. Подключит MCP сервер к выбранному клиенту
86
+ 6. Сохранит безопасные поля (без секретов)
87
+
88
+ ---
89
+
90
+ ## 📚 Основные концепции
91
+
92
+ ### 1. Конфигурация MCP сервера
93
+
94
+ Все MCP серверы должны расширять `BaseMCPServerConfig`:
95
+
96
+ ```typescript
97
+ interface BaseMCPServerConfig {
98
+ projectPath: string; // Путь к проекту
99
+ logLevel?: 'debug' | 'info' | 'warn' | 'error';
100
+ env?: Record<string, string>; // Переменные окружения
101
+ }
102
+
103
+ // Расширяем для своего сервера
104
+ interface YandexTrackerConfig extends BaseMCPServerConfig {
105
+ token: string; // Секрет - НЕ сохраняется
106
+ orgId: string; // Безопасно - сохраняется
107
+ apiBase?: string; // Безопасно - сохраняется
108
+ }
109
+ ```
110
+
111
+ ### 2. Коннекторы
112
+
113
+ **Коннектор** — адаптер для конкретного MCP клиента (Claude Desktop, Claude Code и т.д.).
114
+
115
+ **Встроенные коннекторы:**
116
+ - `ClaudeDesktopConnector` — Claude Desktop (macOS/Windows)
117
+ - `ClaudeCodeConnector` — Claude Code (VSCode extension)
118
+ - `CodexConnector` — Codex IDE
119
+ - `GeminiConnector` — Google Gemini
120
+ - `QwenConnector` — Alibaba Qwen
121
+
122
+ **Использование:**
123
+
124
+ ```typescript
125
+ import { ClaudeDesktopConnector } from '@fractalizer/mcp-cli/connectors';
126
+
127
+ const connector = new ClaudeDesktopConnector(
128
+ 'my-server', // Имя сервера в конфиге клиента
129
+ 'dist/index.js' // Путь к entry point вашего MCP сервера
130
+ );
131
+
132
+ // Проверить установку
133
+ const isInstalled = await connector.isInstalled();
134
+
135
+ // Подключить
136
+ await connector.connect(config);
137
+
138
+ // Отключить
139
+ await connector.disconnect();
140
+
141
+ // Проверить статус
142
+ const status = await connector.getStatus();
143
+ ```
144
+
145
+ ### 3. Реестр коннекторов
146
+
147
+ `ConnectorRegistry` управляет коллекцией коннекторов:
148
+
149
+ ```typescript
150
+ const registry = new ConnectorRegistry<MyServerConfig>();
151
+
152
+ // Регистрация
153
+ registry.register(new ClaudeDesktopConnector('my-server', 'dist/index.js'));
154
+ registry.register(new ClaudeCodeConnector('my-server', 'dist/index.js'));
155
+
156
+ // Получение
157
+ const connector = registry.get('claude-desktop');
158
+
159
+ // Поиск установленных
160
+ const installed = await registry.findInstalled();
161
+
162
+ // Проверка статусов всех
163
+ const statuses = await registry.checkAllStatuses();
164
+ ```
165
+
166
+ ### 4. Менеджер конфигурации
167
+
168
+ `ConfigManager` сохраняет и загружает конфигурацию (только безопасные поля):
169
+
170
+ ```typescript
171
+ const configManager = new ConfigManager<MyServerConfig>({
172
+ projectName: 'my-server',
173
+ safeFields: ['orgId', 'apiBase', 'logLevel'], // БЕЗ token!
174
+ });
175
+
176
+ // Сохранить (только safeFields будут записаны)
177
+ await configManager.save(config);
178
+
179
+ // Загрузить
180
+ const saved = await configManager.load();
181
+ // saved = { orgId: '...', apiBase: '...', logLevel: 'info' }
182
+ // token НЕ сохранен!
183
+ ```
184
+
185
+ **Путь к файлу:** `~/.{projectName}/config.json`
186
+
187
+ ### 5. Интерактивные промпты
188
+
189
+ `ConfigPromptDefinition` определяет, как собирать конфигурацию:
190
+
191
+ ```typescript
192
+ const prompts: ConfigPromptDefinition<MyServerConfig>[] = [
193
+ {
194
+ name: 'token',
195
+ type: 'password',
196
+ message: 'OAuth токен:',
197
+ validate: (value) => value ? true : 'Токен обязателен',
198
+ },
199
+ {
200
+ name: 'orgId',
201
+ type: 'input',
202
+ message: 'ID организации:',
203
+ default: (saved) => saved?.orgId, // Используем сохраненное
204
+ },
205
+ {
206
+ name: 'logLevel',
207
+ type: 'list',
208
+ message: 'Уровень логирования:',
209
+ choices: [
210
+ { name: 'Debug', value: 'debug' },
211
+ { name: 'Info', value: 'info' },
212
+ { name: 'Warn', value: 'warn' },
213
+ { name: 'Error', value: 'error' },
214
+ ],
215
+ default: 'info',
216
+ },
217
+ ];
218
+
219
+ const prompter = new InteractivePrompter<MyServerConfig>(prompts);
220
+ const config = await prompter.promptServerConfig(savedConfig);
221
+ ```
222
+
223
+ **Типы промптов:**
224
+ - `input` — текстовый ввод
225
+ - `password` — скрытый ввод (для секретов)
226
+ - `list` — выбор из списка
227
+ - `confirm` — да/нет
228
+ - `number` — числовой ввод
229
+
230
+ ---
231
+
232
+ ## 🎨 Команды
233
+
234
+ ### connectCommand
235
+
236
+ Подключает MCP сервер к выбранному клиенту.
237
+
238
+ ```typescript
239
+ import { connectCommand } from '@fractalizer/mcp-cli/commands';
240
+
241
+ await connectCommand({
242
+ registry,
243
+ configManager,
244
+ configPrompts,
245
+ cliOptions: {
246
+ client: 'claude-desktop', // Опционально: пропустить выбор клиента
247
+ },
248
+ buildConfig: (serverConfig) => ({
249
+ ...serverConfig,
250
+ projectPath: process.cwd(),
251
+ }),
252
+ });
253
+ ```
254
+
255
+ ### disconnectCommand
256
+
257
+ Отключает MCP сервер от клиента.
258
+
259
+ ```typescript
260
+ import { disconnectCommand } from '@fractalizer/mcp-cli/commands';
261
+
262
+ await disconnectCommand({
263
+ registry,
264
+ cliOptions: {
265
+ client: 'claude-desktop',
266
+ },
267
+ });
268
+ ```
269
+
270
+ ### statusCommand
271
+
272
+ Показывает статус подключений для всех клиентов.
273
+
274
+ ```typescript
275
+ import { statusCommand } from '@fractalizer/mcp-cli/commands';
276
+
277
+ await statusCommand({ registry });
278
+ ```
279
+
280
+ ### listCommand
281
+
282
+ Показывает список всех доступных MCP клиентов.
283
+
284
+ ```typescript
285
+ import { listCommand } from '@fractalizer/mcp-cli/commands';
286
+
287
+ await listCommand({ registry });
288
+ ```
289
+
290
+ ### validateCommand
291
+
292
+ Валидирует текущую конфигурацию для выбранного клиента.
293
+
294
+ ```typescript
295
+ import { validateCommand } from '@fractalizer/mcp-cli/commands';
296
+
297
+ await validateCommand({
298
+ registry,
299
+ configManager,
300
+ configPrompts,
301
+ cliOptions: {
302
+ client: 'claude-desktop',
303
+ },
304
+ });
305
+ ```
306
+
307
+ ---
308
+
309
+ ## 🛠️ Утилиты
310
+
311
+ ### CommandExecutor
312
+
313
+ Выполнение shell команд:
314
+
315
+ ```typescript
316
+ import { CommandExecutor } from '@fractalizer/mcp-cli/utils';
317
+
318
+ const result = await CommandExecutor.execute('ls -la');
319
+ if (result.success) {
320
+ console.log(result.stdout);
321
+ }
322
+ ```
323
+
324
+ ### FileManager
325
+
326
+ Работа с файлами:
327
+
328
+ ```typescript
329
+ import { FileManager } from '@fractalizer/mcp-cli/utils';
330
+
331
+ // Чтение JSON
332
+ const data = await FileManager.readJSON('/path/to/config.json');
333
+
334
+ // Запись JSON
335
+ await FileManager.writeJSON('/path/to/config.json', data);
336
+
337
+ // Проверка существования
338
+ const exists = await FileManager.exists('/path/to/file');
339
+
340
+ // Создание директории
341
+ await FileManager.ensureDir('/path/to/dir');
342
+ ```
343
+
344
+ ### Logger
345
+
346
+ CLI логирование:
347
+
348
+ ```typescript
349
+ import { Logger } from '@fractalizer/mcp-cli/utils';
350
+
351
+ Logger.info('Информация');
352
+ Logger.success('Успех!');
353
+ Logger.error('Ошибка!');
354
+ Logger.warn('Предупреждение');
355
+
356
+ const spinner = Logger.spinner('Загрузка...');
357
+ // ... выполнение операции ...
358
+ spinner.succeed('Готово!');
359
+ ```
360
+
361
+ ---
362
+
363
+ ## 🏗️ Создание кастомного коннектора
364
+
365
+ Если нужно добавить новый MCP клиент:
366
+
367
+ ```typescript
368
+ import { BaseConnector } from '@fractalizer/mcp-cli/connectors';
369
+ import type { MCPClientInfo, ConnectionStatus } from '@fractalizer/mcp-cli';
370
+
371
+ class MyCustomConnector<TConfig extends BaseMCPServerConfig> extends BaseConnector<TConfig> {
372
+ constructor(
373
+ private serverName: string,
374
+ private serverPath: string
375
+ ) {
376
+ super();
377
+ }
378
+
379
+ getClientInfo(): MCPClientInfo {
380
+ return {
381
+ name: 'my-client',
382
+ displayName: 'My Custom Client',
383
+ description: 'My custom MCP client',
384
+ configPath: '/path/to/config',
385
+ platforms: ['darwin', 'linux', 'win32'],
386
+ };
387
+ }
388
+
389
+ async isInstalled(): Promise<boolean> {
390
+ // Проверка установки клиента
391
+ return true;
392
+ }
393
+
394
+ async getStatus(): Promise<ConnectionStatus> {
395
+ // Проверка статуса подключения
396
+ return { connected: true };
397
+ }
398
+
399
+ async connect(config: TConfig): Promise<void> {
400
+ // Логика подключения
401
+ }
402
+
403
+ async disconnect(): Promise<void> {
404
+ // Логика отключения
405
+ }
406
+
407
+ async validateConfig(config: TConfig): Promise<string[]> {
408
+ const errors = await super.validateConfig(config);
409
+ // Добавить свои проверки
410
+ return errors;
411
+ }
412
+ }
413
+
414
+ // Использование
415
+ const connector = new MyCustomConnector('my-server', 'dist/index.js');
416
+ registry.register(connector);
417
+ ```
418
+
419
+ ---
420
+
421
+ ## 📖 Примеры использования
422
+
423
+ ### Реальный пример: Yandex Tracker MCP
424
+
425
+ См. реализацию в [`packages/servers/yandex-tracker/src/cli/`](../../servers/yandex-tracker/src/cli/).
426
+
427
+ ---
428
+
429
+ ## 🔗 См. также
430
+
431
+ - **[Полный API Reference](./API.md)** — детальная документация всех типов и методов
432
+ - **[@fractalizer/mcp-infrastructure](../infrastructure/README.md)** — инфраструктурные утилиты
433
+
434
+ ---
435
+
436
+ ## 📝 Лицензия
437
+
438
+ MIT
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Connect команда для подключения MCP сервера к клиенту
3
+ * @packageDocumentation
4
+ */
5
+ import type { BaseMCPServerConfig, ConnectCommandOptions } from '../types.js';
6
+ /**
7
+ * Команда для подключения MCP сервера к выбранному клиенту
8
+ *
9
+ * @param options - Опции команды
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const registry = new ConnectorRegistry<YourConfig>();
14
+ * const configManager = new ConfigManager<YourConfig>({
15
+ * projectName: 'your-server',
16
+ * safeFields: ['orgId', 'apiBase'],
17
+ * });
18
+ *
19
+ * const configPrompts = [
20
+ * { name: 'token', type: 'password', message: 'OAuth токен:' },
21
+ * { name: 'orgId', type: 'input', message: 'ID организации:' },
22
+ * ];
23
+ *
24
+ * await connectCommand({
25
+ * registry,
26
+ * configManager,
27
+ * configPrompts,
28
+ * });
29
+ * ```
30
+ */
31
+ export declare function connectCommand<TConfig extends BaseMCPServerConfig>(options: ConnectCommandOptions<TConfig>): Promise<void>;
32
+ //# sourceMappingURL=connect.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.command.d.ts","sourceRoot":"","sources":["../../src/commands/connect.command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAI9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,cAAc,CAAC,OAAO,SAAS,mBAAmB,EACtE,OAAO,EAAE,qBAAqB,CAAC,OAAO,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAiHf"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Connect команда для подключения MCP сервера к клиенту
3
+ * @packageDocumentation
4
+ */
5
+ import { InteractivePrompter } from '../utils/interactive-prompter.js';
6
+ import { Logger } from '../utils/logger.js';
7
+ /**
8
+ * Команда для подключения MCP сервера к выбранному клиенту
9
+ *
10
+ * @param options - Опции команды
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const registry = new ConnectorRegistry<YourConfig>();
15
+ * const configManager = new ConfigManager<YourConfig>({
16
+ * projectName: 'your-server',
17
+ * safeFields: ['orgId', 'apiBase'],
18
+ * });
19
+ *
20
+ * const configPrompts = [
21
+ * { name: 'token', type: 'password', message: 'OAuth токен:' },
22
+ * { name: 'orgId', type: 'input', message: 'ID организации:' },
23
+ * ];
24
+ *
25
+ * await connectCommand({
26
+ * registry,
27
+ * configManager,
28
+ * configPrompts,
29
+ * });
30
+ * ```
31
+ */
32
+ export async function connectCommand(options) {
33
+ const { registry, configManager, configPrompts, cliOptions, buildConfig } = options;
34
+ Logger.header('🔌 Подключение MCP сервера');
35
+ Logger.newLine();
36
+ // 1. Найти установленные клиенты
37
+ const spinner = Logger.spinner('Поиск установленных MCP клиентов...');
38
+ const installedClients = await registry.findInstalled();
39
+ spinner.stop();
40
+ if (installedClients.length === 0) {
41
+ Logger.error('Не найдено установленных MCP клиентов');
42
+ Logger.info('Поддерживаемые клиенты: Claude Desktop, Claude Code, Codex, Gemini, Qwen');
43
+ Logger.info('Установите хотя бы один из них для продолжения');
44
+ return;
45
+ }
46
+ Logger.success(`Найдено ${installedClients.length} установленных клиента(ов)`);
47
+ Logger.newLine();
48
+ // 2. Выбрать клиент
49
+ let connector;
50
+ if (cliOptions?.client) {
51
+ connector = registry.get(cliOptions.client);
52
+ if (!connector) {
53
+ Logger.error(`Клиент "${cliOptions.client}" не найден`);
54
+ return;
55
+ }
56
+ const isInstalled = await connector.isInstalled();
57
+ if (!isInstalled) {
58
+ Logger.error(`Клиент "${cliOptions.client}" не установлен`);
59
+ return;
60
+ }
61
+ Logger.info(`Выбран клиент: ${connector.getClientInfo().displayName}`);
62
+ }
63
+ else {
64
+ const clientInfos = installedClients.map((c) => c.getClientInfo());
65
+ const selectedName = await InteractivePrompter.promptClientSelection(clientInfos);
66
+ connector = registry.get(selectedName);
67
+ }
68
+ if (!connector) {
69
+ Logger.error('Не удалось выбрать клиент');
70
+ return;
71
+ }
72
+ Logger.newLine();
73
+ // 3. Собрать конфигурацию
74
+ const savedConfig = await configManager.load();
75
+ if (savedConfig) {
76
+ Logger.info('Найдена сохраненная конфигурация (секретные поля будут запрошены заново)');
77
+ }
78
+ const prompter = new InteractivePrompter(configPrompts);
79
+ const serverConfig = await prompter.promptServerConfig(savedConfig);
80
+ // Построить полную конфигурацию
81
+ const config = buildConfig
82
+ ? buildConfig(serverConfig)
83
+ : {
84
+ projectPath: process.cwd(),
85
+ ...serverConfig,
86
+ };
87
+ Logger.newLine();
88
+ // 4. Валидация
89
+ const errors = await connector.validateConfig(config);
90
+ if (errors.length > 0) {
91
+ Logger.error('Ошибки конфигурации:');
92
+ errors.forEach((err) => Logger.error(` - ${err}`));
93
+ return;
94
+ }
95
+ // 5. Подключение
96
+ const connectSpinner = Logger.spinner(`Подключаю к ${connector.getClientInfo().displayName}...`);
97
+ try {
98
+ await connector.connect(config);
99
+ connectSpinner.succeed(`MCP сервер успешно подключен к ${connector.getClientInfo().displayName}!`);
100
+ const status = await connector.getStatus();
101
+ if (status.details) {
102
+ Logger.info(`Конфигурация: ${status.details.configPath}`);
103
+ }
104
+ }
105
+ catch (error) {
106
+ const errorMessage = error instanceof Error ? error.message : String(error);
107
+ connectSpinner.fail(`Ошибка подключения: ${errorMessage}`);
108
+ return;
109
+ }
110
+ Logger.newLine();
111
+ // 6. Предложить сохранить конфигурацию
112
+ const shouldSave = await InteractivePrompter.promptConfirmation('Сохранить конфигурацию для следующего раза?', true);
113
+ if (shouldSave) {
114
+ await configManager.save(config);
115
+ Logger.success('Конфигурация сохранена (секретные поля исключены)');
116
+ }
117
+ Logger.newLine();
118
+ Logger.success('✅ Готово! Теперь вы можете использовать MCP сервер в выбранном клиенте.');
119
+ }
120
+ //# sourceMappingURL=connect.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.command.js","sourceRoot":"","sources":["../../src/commands/connect.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { ConnectorRegistry } from '../connectors/registry.js';
2
+ import type { BaseMCPServerConfig } from '../types.js';
3
+ /**
4
+ * Опции для команды disconnect
5
+ */
6
+ export interface DisconnectCommandOptions<TConfig extends BaseMCPServerConfig> {
7
+ /** Реестр MCP коннекторов */
8
+ registry: ConnectorRegistry<TConfig>;
9
+ /** CLI опции из командной строки */
10
+ cliOptions?: {
11
+ /** Имя клиента для отключения (опционально, если не указан - будет интерактивный выбор) */
12
+ client?: string;
13
+ };
14
+ }
15
+ /**
16
+ * Команда для отключения MCP сервера от клиента
17
+ *
18
+ * @param options - Опции команды
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const registry = new ConnectorRegistry<YourConfig>();
23
+ * // регистрация коннекторов...
24
+ *
25
+ * // Интерактивный выбор клиента
26
+ * await disconnectCommand({ registry });
27
+ *
28
+ * // Или указать клиент явно
29
+ * await disconnectCommand({
30
+ * registry,
31
+ * cliOptions: { client: 'claude-desktop' }
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function disconnectCommand<TConfig extends BaseMCPServerConfig>(options: DisconnectCommandOptions<TConfig>): Promise<void>;
36
+ //# sourceMappingURL=disconnect.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disconnect.command.d.ts","sourceRoot":"","sources":["../../src/commands/disconnect.command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvD;;GAEG;AACH,MAAM,WAAW,wBAAwB,CAAC,OAAO,SAAS,mBAAmB;IAC3E,6BAA6B;IAC7B,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAErC,oCAAoC;IACpC,UAAU,CAAC,EAAE;QACX,2FAA2F;QAC3F,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAgED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,SAAS,mBAAmB,EACzE,OAAO,EAAE,wBAAwB,CAAC,OAAO,CAAC,GACzC,OAAO,CAAC,IAAI,CAAC,CAgCf"}