@fractalizer/mcp-cli 0.3.18 → 1.0.1

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 (120) hide show
  1. package/README.md +158 -266
  2. package/dist/commands/connect.command.d.ts +18 -15
  3. package/dist/commands/connect.command.d.ts.map +1 -1
  4. package/dist/commands/connect.command.js +66 -40
  5. package/dist/commands/connect.command.js.map +1 -1
  6. package/dist/commands/disconnect.command.d.ts +5 -17
  7. package/dist/commands/disconnect.command.d.ts.map +1 -1
  8. package/dist/commands/disconnect.command.js +4 -15
  9. package/dist/commands/disconnect.command.js.map +1 -1
  10. package/dist/commands/doctor.command.d.ts +34 -0
  11. package/dist/commands/doctor.command.d.ts.map +1 -0
  12. package/dist/commands/doctor.command.js +321 -0
  13. package/dist/commands/doctor.command.js.map +1 -0
  14. package/dist/commands/index.d.ts +1 -0
  15. package/dist/commands/index.d.ts.map +1 -1
  16. package/dist/commands/index.js +2 -0
  17. package/dist/commands/index.js.map +1 -1
  18. package/dist/commands/list.command.d.ts +4 -9
  19. package/dist/commands/list.command.d.ts.map +1 -1
  20. package/dist/commands/list.command.js +1 -5
  21. package/dist/commands/list.command.js.map +1 -1
  22. package/dist/commands/status.command.d.ts +6 -13
  23. package/dist/commands/status.command.d.ts.map +1 -1
  24. package/dist/commands/status.command.js +18 -12
  25. package/dist/commands/status.command.js.map +1 -1
  26. package/dist/commands/validate.command.d.ts +6 -11
  27. package/dist/commands/validate.command.d.ts.map +1 -1
  28. package/dist/commands/validate.command.js +15 -19
  29. package/dist/commands/validate.command.js.map +1 -1
  30. package/dist/connectors/base/base-connector.d.ts +31 -55
  31. package/dist/connectors/base/base-connector.d.ts.map +1 -1
  32. package/dist/connectors/base/base-connector.js +71 -57
  33. package/dist/connectors/base/base-connector.js.map +1 -1
  34. package/dist/connectors/base/configurable-connector.d.ts +89 -24
  35. package/dist/connectors/base/configurable-connector.d.ts.map +1 -1
  36. package/dist/connectors/base/configurable-connector.js +266 -23
  37. package/dist/connectors/base/configurable-connector.js.map +1 -1
  38. package/dist/connectors/base/connector.interface.d.ts +29 -20
  39. package/dist/connectors/base/connector.interface.d.ts.map +1 -1
  40. package/dist/connectors/base/index.d.ts +0 -1
  41. package/dist/connectors/base/index.d.ts.map +1 -1
  42. package/dist/connectors/base/index.js +0 -1
  43. package/dist/connectors/base/index.js.map +1 -1
  44. package/dist/connectors/claude-code/claude-code.connector.d.ts +171 -21
  45. package/dist/connectors/claude-code/claude-code.connector.d.ts.map +1 -1
  46. package/dist/connectors/claude-code/claude-code.connector.js +368 -43
  47. package/dist/connectors/claude-code/claude-code.connector.js.map +1 -1
  48. package/dist/connectors/connector-factory.d.ts +15 -15
  49. package/dist/connectors/connector-factory.d.ts.map +1 -1
  50. package/dist/connectors/connector-factory.js +61 -18
  51. package/dist/connectors/connector-factory.js.map +1 -1
  52. package/dist/connectors/index.d.ts +0 -4
  53. package/dist/connectors/index.d.ts.map +1 -1
  54. package/dist/connectors/index.js +2 -8
  55. package/dist/connectors/index.js.map +1 -1
  56. package/dist/connectors/registry.d.ts +20 -27
  57. package/dist/connectors/registry.d.ts.map +1 -1
  58. package/dist/connectors/registry.js +34 -34
  59. package/dist/connectors/registry.js.map +1 -1
  60. package/dist/tsconfig.tsbuildinfo +1 -1
  61. package/dist/types/{base.types.d.ts → client.types.d.ts} +37 -30
  62. package/dist/types/client.types.d.ts.map +1 -0
  63. package/dist/types/client.types.js +6 -0
  64. package/dist/types/client.types.js.map +1 -0
  65. package/dist/types/doctor.types.d.ts +91 -0
  66. package/dist/types/doctor.types.d.ts.map +1 -0
  67. package/dist/types/doctor.types.js +12 -0
  68. package/dist/types/doctor.types.js.map +1 -0
  69. package/dist/types/launch.types.d.ts +59 -0
  70. package/dist/types/launch.types.d.ts.map +1 -0
  71. package/dist/types/launch.types.js +6 -0
  72. package/dist/types/launch.types.js.map +1 -0
  73. package/dist/types.d.ts +23 -14
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +9 -2
  76. package/dist/types.js.map +1 -1
  77. package/dist/utils/command-executor.d.ts +39 -3
  78. package/dist/utils/command-executor.d.ts.map +1 -1
  79. package/dist/utils/command-executor.js +95 -8
  80. package/dist/utils/command-executor.js.map +1 -1
  81. package/dist/utils/config-manager.d.ts +25 -42
  82. package/dist/utils/config-manager.d.ts.map +1 -1
  83. package/dist/utils/config-manager.js +21 -49
  84. package/dist/utils/config-manager.js.map +1 -1
  85. package/dist/utils/index.d.ts +1 -0
  86. package/dist/utils/index.d.ts.map +1 -1
  87. package/dist/utils/index.js +1 -0
  88. package/dist/utils/index.js.map +1 -1
  89. package/dist/utils/interactive-prompter.d.ts +16 -64
  90. package/dist/utils/interactive-prompter.d.ts.map +1 -1
  91. package/dist/utils/interactive-prompter.js +12 -65
  92. package/dist/utils/interactive-prompter.js.map +1 -1
  93. package/dist/utils/launch-spec-helpers.d.ts +38 -0
  94. package/dist/utils/launch-spec-helpers.d.ts.map +1 -0
  95. package/dist/utils/launch-spec-helpers.js +131 -0
  96. package/dist/utils/launch-spec-helpers.js.map +1 -0
  97. package/package.json +2 -2
  98. package/dist/connectors/base/file-based-connector.d.ts +0 -97
  99. package/dist/connectors/base/file-based-connector.d.ts.map +0 -1
  100. package/dist/connectors/base/file-based-connector.js +0 -185
  101. package/dist/connectors/base/file-based-connector.js.map +0 -1
  102. package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts +0 -38
  103. package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts.map +0 -1
  104. package/dist/connectors/claude-desktop/claude-desktop.connector.js +0 -68
  105. package/dist/connectors/claude-desktop/claude-desktop.connector.js.map +0 -1
  106. package/dist/connectors/codex/codex.connector.d.ts +0 -51
  107. package/dist/connectors/codex/codex.connector.d.ts.map +0 -1
  108. package/dist/connectors/codex/codex.connector.js +0 -76
  109. package/dist/connectors/codex/codex.connector.js.map +0 -1
  110. package/dist/connectors/gemini/gemini.connector.d.ts +0 -41
  111. package/dist/connectors/gemini/gemini.connector.d.ts.map +0 -1
  112. package/dist/connectors/gemini/gemini.connector.js +0 -61
  113. package/dist/connectors/gemini/gemini.connector.js.map +0 -1
  114. package/dist/connectors/qwen/qwen.connector.d.ts +0 -41
  115. package/dist/connectors/qwen/qwen.connector.d.ts.map +0 -1
  116. package/dist/connectors/qwen/qwen.connector.js +0 -61
  117. package/dist/connectors/qwen/qwen.connector.js.map +0 -1
  118. package/dist/types/base.types.d.ts.map +0 -1
  119. package/dist/types/base.types.js +0 -6
  120. package/dist/types/base.types.js.map +0 -1
@@ -5,32 +5,35 @@
5
5
  import { InteractivePrompter } from '../utils/interactive-prompter.js';
6
6
  import { Logger } from '../utils/logger.js';
7
7
  /**
8
- * Команда для подключения MCP сервера к выбранному клиенту
8
+ * Команда подключения MCP сервера к выбранному клиенту.
9
9
  *
10
- * @param options - Опции команды
10
+ * Поток:
11
+ * 1. Найти установленные клиенты (`registry.findInstalled`).
12
+ * 2. Выбрать клиент (через CLI флаг `--client` или интерактивно).
13
+ * 3. Загрузить сохранённую доменную конфигурацию (`configManager.load`).
14
+ * 4. Собрать новую доменную конфигурацию через промпты.
15
+ * 5. Адаптер `buildServerLaunch(config)` → {@link ServerLaunchSpec}.
16
+ * 6. `connector.validateLaunchSpec(spec)`; при ошибках — abort (без `connect`/`save`).
17
+ * 7. `connector.connect(spec)`. При исключении управление прерывается, `save` не достигается.
18
+ * 8. Информационный `getStatus()`.
19
+ * 9. После успешного connect — `configManager.save(domainConfig)` и warning про plaintext-токен.
11
20
  *
12
21
  * @example
13
22
  * ```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
23
  * await connectCommand({
26
24
  * registry,
27
25
  * configManager,
28
26
  * configPrompts,
27
+ * buildServerLaunch: (cfg) => ({
28
+ * command: 'node',
29
+ * args: ['/abs/path/server.bundle.cjs'],
30
+ * env: { API_TOKEN: cfg.token, ORG_ID: cfg.orgId },
31
+ * }),
29
32
  * });
30
33
  * ```
31
34
  */
32
35
  export async function connectCommand(options) {
33
- const { registry, configManager, configPrompts, cliOptions, buildConfig } = options;
36
+ const { registry, configManager, configPrompts, buildServerLaunch, cliOptions } = options;
34
37
  Logger.header('🔌 Подключение MCP сервера');
35
38
  Logger.newLine();
36
39
  // 1. Найти установленные клиенты
@@ -39,11 +42,10 @@ export async function connectCommand(options) {
39
42
  spinner.stop();
40
43
  if (installedClients.length === 0) {
41
44
  Logger.error('Не найдено установленных MCP клиентов');
42
- Logger.info('Поддерживаемые клиенты: Claude Desktop, Claude Code, Codex, Gemini, Qwen');
43
- Logger.info('Установите хотя бы один из них для продолжения');
45
+ Logger.info('Установите хотя бы один поддерживаемый MCP клиент');
44
46
  return;
45
47
  }
46
- Logger.success(`Найдено ${installedClients.length} установленных клиента(ов)`);
48
+ Logger.success(`Найдено ${String(installedClients.length)} установленных клиента(ов)`);
47
49
  Logger.newLine();
48
50
  // 2. Выбрать клиент
49
51
  let connector;
@@ -51,6 +53,14 @@ export async function connectCommand(options) {
51
53
  connector = registry.get(cliOptions.client);
52
54
  if (!connector) {
53
55
  Logger.error(`Клиент "${cliOptions.client}" не найден`);
56
+ const valid = registry.getAll();
57
+ if (valid.length > 0) {
58
+ Logger.info('Доступные клиенты:');
59
+ for (const c of valid) {
60
+ const info = c.getClientInfo();
61
+ Logger.info(` - ${info.name} (${info.displayName})`);
62
+ }
63
+ }
54
64
  return;
55
65
  }
56
66
  const isInstalled = await connector.isInstalled();
@@ -70,49 +80,65 @@ export async function connectCommand(options) {
70
80
  return;
71
81
  }
72
82
  Logger.newLine();
73
- // 3. Собрать конфигурацию
83
+ // 3. Загрузить сохранённую доменную конфигурацию
74
84
  const savedConfig = await configManager.load();
75
85
  if (savedConfig) {
76
86
  Logger.info('Найдена сохраненная конфигурация (секретные поля будут запрошены заново)');
77
87
  }
88
+ // 4. Собрать доменную конфигурацию
78
89
  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
- };
90
+ const domainConfig = await prompter.promptServerConfig(savedConfig);
87
91
  Logger.newLine();
88
- // 4. Валидация
89
- const errors = await connector.validateConfig(config);
92
+ // 5. Построить spec через адаптер
93
+ const spec = buildServerLaunch(domainConfig);
94
+ // 6. Валидация
95
+ const errors = await connector.validateLaunchSpec(spec);
90
96
  if (errors.length > 0) {
91
- Logger.error('Ошибки конфигурации:');
97
+ Logger.error('Ошибки конфигурации запуска:');
92
98
  errors.forEach((err) => Logger.error(` - ${err}`));
93
99
  return;
94
100
  }
95
- // 5. Подключение
101
+ // 7. Подключение (если бросит — save не выполняется)
96
102
  const connectSpinner = Logger.spinner(`Подключаю к ${connector.getClientInfo().displayName}...`);
97
103
  try {
98
- await connector.connect(config);
104
+ await connector.connect(spec);
99
105
  connectSpinner.succeed(`MCP сервер успешно подключен к ${connector.getClientInfo().displayName}!`);
100
- const status = await connector.getStatus();
101
- if (status.details) {
102
- Logger.info(`Конфигурация: ${status.details.configPath}`);
103
- }
104
106
  }
105
107
  catch (error) {
106
108
  const errorMessage = error instanceof Error ? error.message : String(error);
107
109
  connectSpinner.fail(`Ошибка подключения: ${errorMessage}`);
108
110
  return;
109
111
  }
112
+ // 8. Информационный статус
113
+ const status = await connector.getStatus();
114
+ if (status.details?.configPath) {
115
+ Logger.info(`Конфигурация: ${status.details.configPath}`);
116
+ }
110
117
  Logger.newLine();
111
- // 6. Предложить сохранить конфигурацию
112
- const shouldSave = await InteractivePrompter.promptConfirmation('Сохранить конфигурацию для следующего раза?', true);
113
- if (shouldSave) {
114
- await configManager.save(config);
115
- Logger.success('Конфигурация сохранена (секретные поля исключены)');
118
+ // 9. Безусловно сохранить доменную конфигурацию (после успешного connect).
119
+ // Подключение к клиенту уже выполнено успешно; неудача save локального
120
+ // кэша не критична, но информируем пользователя, чтобы при необходимости
121
+ // он мог разобраться (например, нет прав на ~/. dir).
122
+ try {
123
+ await configManager.save(domainConfig);
124
+ Logger.success(`Конфигурация сохранена: ${configManager.getConfigPath()}`);
125
+ }
126
+ catch (saveError) {
127
+ const errMsg = saveError instanceof Error ? saveError.message : String(saveError);
128
+ Logger.error(`Подключение выполнено, но локальный кэш конфига не сохранён: ${errMsg}`);
129
+ Logger.info(`Путь к локальному кэшу: ${configManager.getConfigPath()}`);
130
+ if (status.details?.configPath) {
131
+ Logger.info(`Путь к client config (подключение активно): ${status.details.configPath}`);
132
+ }
133
+ }
134
+ // Предупреждение о plaintext-хранении токена в конфиге клиента
135
+ if (status.details?.configPath) {
136
+ Logger.warn(`⚠️ Токен сохранён в plaintext в ${status.details.configPath}. ` +
137
+ 'Убедитесь, что файл недоступен другим пользователям системы.');
138
+ }
139
+ else {
140
+ Logger.warn('⚠️ Токен сохранён в plaintext в конфиге клиента. ' +
141
+ 'Убедитесь, что файл недоступен другим пользователям системы.');
116
142
  }
117
143
  Logger.newLine();
118
144
  Logger.success('✅ Готово! Теперь вы можете использовать MCP сервер в выбранном клиенте.');
@@ -1 +1 @@
1
- {"version":3,"file":"connect.command.js","sourceRoot":"","sources":["../../src/commands/connect.command.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAuC;IAEvC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEpF,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC;IACtE,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;IACxD,OAAO,CAAC,IAAI,EAAE,CAAC;IAEf,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;QACxF,MAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,WAAW,gBAAgB,CAAC,MAAM,4BAA4B,CAAC,CAAC;IAC/E,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,oBAAoB;IACpB,IAAI,SAAS,CAAC;IACd,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC;QACvB,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,WAAW,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,CAAC;QAClD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,CAAC,WAAW,UAAU,CAAC,MAAM,iBAAiB,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,kBAAkB,SAAS,CAAC,aAAa,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAoC,EAAE,EAAE,CAChF,CAAC,CAAC,aAAa,EAAE,CAClB,CAAC;QACF,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAClF,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,0BAA0B;IAC1B,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAU,aAAa,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAEpE,gCAAgC;IAChC,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;QAC3B,CAAC,CAAE;YACC,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;YAC1B,GAAG,YAAY;SACJ,CAAC;IAElB,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,eAAe;IACf,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,iBAAiB;IACjB,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,SAAS,CAAC,aAAa,EAAE,CAAC,WAAW,KAAK,CAAC,CAAC;IAEjG,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChC,cAAc,CAAC,OAAO,CACpB,kCAAkC,SAAS,CAAC,aAAa,EAAE,CAAC,WAAW,GAAG,CAC3E,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,CAAC;QAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,cAAc,CAAC,IAAI,CAAC,uBAAuB,YAAY,EAAE,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,uCAAuC;IACvC,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,kBAAkB,CAC7D,6CAA6C,EAC7C,IAAI,CACL,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,CAAC;IACjB,MAAM,CAAC,OAAO,CAAC,yEAAyE,CAAC,CAAC;AAC5F,CAAC"}
1
+ {"version":3,"file":"connect.command.js","sourceRoot":"","sources":["../../src/commands/connect.command.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,10 @@
1
1
  import type { ConnectorRegistry } from '../connectors/registry.js';
2
- import type { BaseMCPServerConfig } from '../types.js';
3
2
  /**
4
3
  * Опции для команды disconnect
5
4
  */
6
- export interface DisconnectCommandOptions<TConfig extends BaseMCPServerConfig> {
5
+ export interface DisconnectCommandOptions {
7
6
  /** Реестр MCP коннекторов */
8
- registry: ConnectorRegistry<TConfig>;
7
+ registry: ConnectorRegistry;
9
8
  /** CLI опции из командной строки */
10
9
  cliOptions?: {
11
10
  /** Имя клиента для отключения (опционально, если не указан - будет интерактивный выбор) */
@@ -13,24 +12,13 @@ export interface DisconnectCommandOptions<TConfig extends BaseMCPServerConfig> {
13
12
  };
14
13
  }
15
14
  /**
16
- * Команда для отключения MCP сервера от клиента
17
- *
18
- * @param options - Опции команды
15
+ * Команда для отключения MCP сервера от клиента.
19
16
  *
20
17
  * @example
21
18
  * ```typescript
22
- * const registry = new ConnectorRegistry<YourConfig>();
23
- * // регистрация коннекторов...
24
- *
25
- * // Интерактивный выбор клиента
26
19
  * await disconnectCommand({ registry });
27
- *
28
- * // Или указать клиент явно
29
- * await disconnectCommand({
30
- * registry,
31
- * cliOptions: { client: 'claude-desktop' }
32
- * });
20
+ * await disconnectCommand({ registry, cliOptions: { client: 'claude-desktop' } });
33
21
  * ```
34
22
  */
35
- export declare function disconnectCommand<TConfig extends BaseMCPServerConfig>(options: DisconnectCommandOptions<TConfig>): Promise<void>;
23
+ export declare function disconnectCommand(options: DisconnectCommandOptions): Promise<void>;
36
24
  //# sourceMappingURL=disconnect.command.d.ts.map
@@ -1 +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"}
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;AAInE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,6BAA6B;IAC7B,QAAQ,EAAE,iBAAiB,CAAC;IAE5B,oCAAoC;IACpC,UAAU,CAAC,EAAE;QACX,2FAA2F;QAC3F,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AA4DD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCxF"}
@@ -6,7 +6,7 @@ import { InteractivePrompter } from '../utils/interactive-prompter.js';
6
6
  async function findConnectedConnectors(registry) {
7
7
  const statuses = await registry.checkAllStatuses();
8
8
  return Array.from(statuses.entries())
9
- .filter(([_, status]) => status.connected)
9
+ .filter(([, status]) => status.connected)
10
10
  .map(([name]) => registry.get(name))
11
11
  .filter((c) => c !== undefined);
12
12
  }
@@ -49,23 +49,12 @@ async function performDisconnect(connector) {
49
49
  }
50
50
  }
51
51
  /**
52
- * Команда для отключения MCP сервера от клиента
53
- *
54
- * @param options - Опции команды
52
+ * Команда для отключения MCP сервера от клиента.
55
53
  *
56
54
  * @example
57
55
  * ```typescript
58
- * const registry = new ConnectorRegistry<YourConfig>();
59
- * // регистрация коннекторов...
60
- *
61
- * // Интерактивный выбор клиента
62
56
  * await disconnectCommand({ registry });
63
- *
64
- * // Или указать клиент явно
65
- * await disconnectCommand({
66
- * registry,
67
- * cliOptions: { client: 'claude-desktop' }
68
- * });
57
+ * await disconnectCommand({ registry, cliOptions: { client: 'claude-desktop' } });
69
58
  * ```
70
59
  */
71
60
  export async function disconnectCommand(options) {
@@ -80,7 +69,7 @@ export async function disconnectCommand(options) {
80
69
  Logger.newLine();
81
70
  return;
82
71
  }
83
- Logger.success(`Найдено ${connectedConnectors.length} подключенных клиента(ов)`);
72
+ Logger.success(`Найдено ${String(connectedConnectors.length)} подключенных клиента(ов)`);
84
73
  Logger.newLine();
85
74
  const connector = await selectConnector(registry, connectedConnectors, cliOptions?.client);
86
75
  if (!connector) {
@@ -1 +1 @@
1
- {"version":3,"file":"disconnect.command.js","sourceRoot":"","sources":["../../src/commands/disconnect.command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"disconnect.command.js","sourceRoot":"","sources":["../../src/commands/disconnect.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Команда самодиагностики MCP подключений.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import type { DoctorCommandOptions, DoctorReport } from '../types/doctor.types.js';
7
+ /**
8
+ * Запустить диагностику MCP подключений.
9
+ *
10
+ * Собирает проверки в детерминированном порядке:
11
+ * 1. Для каждого зарегистрированного и установленного клиента
12
+ * (`registry.findInstalled()` в порядке `registry.getAll()`):
13
+ * - `isInstalled` (фактически уже пройдена — отмечается как `ok`);
14
+ * - `getStatus` (запрос статуса через коннектор);
15
+ * - `command-exists` (проверка существования `command` из spec на диске).
16
+ * 2. Доменные `extraChecks` в порядке передачи.
17
+ *
18
+ * Все проверки запускаются параллельно через `Promise.allSettled`. Рендеринг
19
+ * результатов — после завершения всех проверок, чтобы избежать чересполосицы
20
+ * вывода.
21
+ *
22
+ * **Robustness:** исключение внутри `check.run()` перехватывается и трактуется
23
+ * как `fail` с сообщением `'Исключение при выполнении проверки: <message>'`.
24
+ * Одна сломанная проверка не валит весь doctor.
25
+ *
26
+ * **Важно:** функция НЕ вызывает `process.exit`. Caller обязан проверить
27
+ * `report.summary.fail` и при необходимости вызвать `process.exit(1)` — это
28
+ * сохраняет тестируемость функции и оставляет policy решение на CLI entry point.
29
+ *
30
+ * @param options - Опции: `registry` + опциональные доменные `extraChecks`.
31
+ * @returns Агрегированный {@link DoctorReport}.
32
+ */
33
+ export declare function doctorCommand(options: DoctorCommandOptions): Promise<DoctorReport>;
34
+ //# sourceMappingURL=doctor.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.command.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.command.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAGV,oBAAoB,EACpB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAclC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkDxF"}
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Команда самодиагностики MCP подключений.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import * as fs from 'node:fs/promises';
7
+ import * as path from 'node:path';
8
+ import { resolveExecutablePath } from '../utils/launch-spec-helpers.js';
9
+ import { Logger } from '../utils/logger.js';
10
+ /**
11
+ * Internal: ключ группы для проверок без явной group (например, доменные
12
+ * extraChecks без поля group).
13
+ */
14
+ const UNGROUPED_GROUP_KEY = '_ungrouped';
15
+ /**
16
+ * Internal: метка группы для рендера проверок без group.
17
+ */
18
+ const UNGROUPED_GROUP_LABEL = 'Доменные проверки';
19
+ /**
20
+ * Запустить диагностику MCP подключений.
21
+ *
22
+ * Собирает проверки в детерминированном порядке:
23
+ * 1. Для каждого зарегистрированного и установленного клиента
24
+ * (`registry.findInstalled()` в порядке `registry.getAll()`):
25
+ * - `isInstalled` (фактически уже пройдена — отмечается как `ok`);
26
+ * - `getStatus` (запрос статуса через коннектор);
27
+ * - `command-exists` (проверка существования `command` из spec на диске).
28
+ * 2. Доменные `extraChecks` в порядке передачи.
29
+ *
30
+ * Все проверки запускаются параллельно через `Promise.allSettled`. Рендеринг
31
+ * результатов — после завершения всех проверок, чтобы избежать чересполосицы
32
+ * вывода.
33
+ *
34
+ * **Robustness:** исключение внутри `check.run()` перехватывается и трактуется
35
+ * как `fail` с сообщением `'Исключение при выполнении проверки: <message>'`.
36
+ * Одна сломанная проверка не валит весь doctor.
37
+ *
38
+ * **Важно:** функция НЕ вызывает `process.exit`. Caller обязан проверить
39
+ * `report.summary.fail` и при необходимости вызвать `process.exit(1)` — это
40
+ * сохраняет тестируемость функции и оставляет policy решение на CLI entry point.
41
+ *
42
+ * @param options - Опции: `registry` + опциональные доменные `extraChecks`.
43
+ * @returns Агрегированный {@link DoctorReport}.
44
+ */
45
+ export async function doctorCommand(options) {
46
+ const { registry, extraChecks = [] } = options;
47
+ Logger.header('🩺 Диагностика MCP подключений');
48
+ // Per-run cache для getLaunchSpec — connector.getLaunchSpec() читает файл
49
+ // конфигурации (или вызывает CLI) — может быть дорогим. Внутри doctor мы
50
+ // вызываем его для двух проверок (interpretConnectionStatus и
51
+ // checkCommandExistsOnDisk), достаточно одного чтения.
52
+ const launchSpecCache = new Map();
53
+ const getCachedLaunchSpec = (connector) => {
54
+ let p = launchSpecCache.get(connector);
55
+ if (!p) {
56
+ p = connector.getLaunchSpec();
57
+ launchSpecCache.set(connector, p);
58
+ }
59
+ return p;
60
+ };
61
+ // 1. Сбор client-level проверок только для установленных клиентов.
62
+ // Порядок — как в registry.getAll() (стабильный).
63
+ const installed = await registry.findInstalled();
64
+ const installedNames = new Set(installed.map((c) => c.getClientInfo().name));
65
+ const clientChecks = [];
66
+ for (const connector of registry.getAll()) {
67
+ if (!installedNames.has(connector.getClientInfo().name))
68
+ continue;
69
+ clientChecks.push(...buildClientChecks(connector, getCachedLaunchSpec));
70
+ }
71
+ const allChecks = [...clientChecks, ...extraChecks];
72
+ // 2. Параллельное выполнение всех проверок через Promise.allSettled.
73
+ // Исключения внутри check.run() трактуем как fail (см. JSDoc).
74
+ const settled = await Promise.allSettled(allChecks.map((c) => safeRun(c)));
75
+ // 3. Сбор результатов в детерминированном порядке.
76
+ const checks = allChecks.map((check, idx) => {
77
+ const outcome = settled[idx];
78
+ const result = settledToResult(outcome);
79
+ return { check, result };
80
+ });
81
+ const report = buildReport(checks);
82
+ // 4. Рендер после завершения всех проверок.
83
+ renderReport(report);
84
+ return report;
85
+ }
86
+ /**
87
+ * Собрать стандартные client-level проверки для одного коннектора.
88
+ */
89
+ function buildClientChecks(connector, getCachedLaunchSpec) {
90
+ const group = connector.getClientInfo().displayName;
91
+ return [
92
+ buildIsInstalledCheck(connector, group),
93
+ buildGetStatusCheck(connector, group),
94
+ buildCommandExistsCheck(connector, group, getCachedLaunchSpec),
95
+ ];
96
+ }
97
+ function buildIsInstalledCheck(connector, group) {
98
+ return {
99
+ name: 'isInstalled',
100
+ description: 'Проверка установки клиента в системе',
101
+ group,
102
+ run: async () => {
103
+ // findInstalled() уже отфильтровал по этому критерию, но для полноты
104
+ // явно отмечаем как ok.
105
+ const ok = await connector.isInstalled();
106
+ return ok
107
+ ? { status: 'ok', message: 'Клиент установлен' }
108
+ : { status: 'fail', message: 'Клиент не установлен' };
109
+ },
110
+ };
111
+ }
112
+ function buildGetStatusCheck(connector, group) {
113
+ return {
114
+ name: 'getStatus',
115
+ description: 'Запрос статуса подключения через коннектор',
116
+ group,
117
+ run: async () => {
118
+ const status = await connector.getStatus();
119
+ return interpretConnectionStatus(status);
120
+ },
121
+ };
122
+ }
123
+ function buildCommandExistsCheck(connector, group, getCachedLaunchSpec) {
124
+ return {
125
+ name: 'command-exists',
126
+ description: 'Существование исполняемого файла из конфигурации клиента',
127
+ group,
128
+ run: () => checkCommandExistsOnDisk(connector, getCachedLaunchSpec),
129
+ };
130
+ }
131
+ function interpretConnectionStatus(status) {
132
+ if (status.connected && !status.error) {
133
+ return { status: 'ok', message: 'Сервер подключен и отвечает' };
134
+ }
135
+ if (status.connected && status.error) {
136
+ return {
137
+ status: 'warn',
138
+ message: `Подключен, но с предупреждением: ${status.error}`,
139
+ };
140
+ }
141
+ if (status.error) {
142
+ return { status: 'fail', message: status.error };
143
+ }
144
+ return {
145
+ status: 'warn',
146
+ message: 'Сервер не подключен к этому клиенту',
147
+ hint: 'Запустите команду `connect`, чтобы подключить сервер.',
148
+ };
149
+ }
150
+ /**
151
+ * Проверка существования `command` (или скрипта при `command === 'node'`)
152
+ * на диске. Использует {@link resolveExecutablePath} — ту же логику, что и
153
+ * `BaseConnector.validateLaunchSpec`/`ConfigurableConnector.commandExistsOnDisk`.
154
+ *
155
+ * Кейсы:
156
+ * - `spec === null` (сервер не подключен) → `skip`.
157
+ * - Команда — `npx`/`pipx`/`uvx` или относительная — `warn`.
158
+ * - Команда — абсолютный путь или `node` с абсолютным скриптом — `fs.access(R_OK)`.
159
+ */
160
+ async function checkCommandExistsOnDisk(connector, getCachedLaunchSpec) {
161
+ const spec = await getCachedLaunchSpec(connector);
162
+ if (spec === null) {
163
+ return {
164
+ status: 'skip',
165
+ message: 'Сервер не подключен к этому клиенту',
166
+ };
167
+ }
168
+ const filePath = resolveExecutablePath(spec);
169
+ if (filePath === null) {
170
+ // относительная команда или `node` без скрипта в args
171
+ if (path.isAbsolute(spec.command)) {
172
+ // не должно случиться, resolveExecutablePath обрабатывает абсолютные.
173
+ return {
174
+ status: 'fail',
175
+ message: `Не удалось определить путь к исполняемому файлу для команды: ${spec.command}`,
176
+ };
177
+ }
178
+ return {
179
+ status: 'warn',
180
+ message: `Команда '${spec.command}' разрешается через PATH; не можем проверить на диске`,
181
+ hint: 'Работа зависит от текущего PATH клиента. Рекомендуется указывать абсолютный путь.',
182
+ };
183
+ }
184
+ try {
185
+ await fs.access(filePath, fs.constants.R_OK);
186
+ return {
187
+ status: 'ok',
188
+ message: `Файл найден и читаем: ${filePath}`,
189
+ };
190
+ }
191
+ catch {
192
+ return {
193
+ status: 'fail',
194
+ message: `Файл не найден или недоступен: ${filePath}`,
195
+ hint: 'Переподключите сервер командой `connect` (путь к бандлу мог измениться при обновлении пакета).',
196
+ };
197
+ }
198
+ }
199
+ /**
200
+ * Безопасно запустить проверку, перехватывая исключения.
201
+ */
202
+ async function safeRun(check) {
203
+ try {
204
+ return await check.run();
205
+ }
206
+ catch (err) {
207
+ return {
208
+ status: 'fail',
209
+ message: `Исключение при выполнении проверки: ${stringifyError(err)}`,
210
+ };
211
+ }
212
+ }
213
+ function stringifyError(err) {
214
+ if (err instanceof Error)
215
+ return err.message;
216
+ return String(err);
217
+ }
218
+ /**
219
+ * Преобразование одного исхода `Promise.allSettled` в `DoctorCheckResult`.
220
+ * `safeRun` уже перехватывает исключения внутри проверки, поэтому ветка
221
+ * `rejected` — defence-in-depth (например, если safeRun сам кинет).
222
+ */
223
+ function settledToResult(outcome) {
224
+ if (!outcome) {
225
+ return {
226
+ status: 'fail',
227
+ message: 'Внутренняя ошибка: отсутствует результат проверки',
228
+ };
229
+ }
230
+ if (outcome.status === 'fulfilled') {
231
+ return outcome.value;
232
+ }
233
+ return {
234
+ status: 'fail',
235
+ message: `Исключение при выполнении проверки: ${stringifyError(outcome.reason)}`,
236
+ };
237
+ }
238
+ function buildReport(checks) {
239
+ const summary = { ok: 0, warn: 0, fail: 0, skip: 0 };
240
+ for (const { result } of checks) {
241
+ summary[result.status] += 1;
242
+ }
243
+ return { checks, summary };
244
+ }
245
+ /**
246
+ * Отрендерить отчёт через {@link Logger}. Группирует проверки по `group`
247
+ * (если задано) в порядке появления группы.
248
+ */
249
+ function renderReport(report) {
250
+ // Группировка с сохранением порядка появления group.
251
+ const groups = new Map();
252
+ for (const item of report.checks) {
253
+ const group = item.check.group ?? UNGROUPED_GROUP_KEY;
254
+ let arr = groups.get(group);
255
+ if (!arr) {
256
+ arr = [];
257
+ groups.set(group, arr);
258
+ }
259
+ arr.push(item);
260
+ }
261
+ for (const [group, items] of groups) {
262
+ if (group !== UNGROUPED_GROUP_KEY) {
263
+ Logger.info(`\nГруппа: ${group}`);
264
+ }
265
+ else {
266
+ Logger.info(`\n${UNGROUPED_GROUP_LABEL}:`);
267
+ }
268
+ for (const { check, result } of items) {
269
+ renderCheck(check, result);
270
+ }
271
+ }
272
+ Logger.newLine();
273
+ const { ok, warn, fail, skip } = report.summary;
274
+ const summaryLine = `Сводка: ${ok} ok · ${warn} warn · ${fail} fail · ${skip} skip`;
275
+ if (fail > 0) {
276
+ Logger.error(summaryLine);
277
+ }
278
+ else if (warn > 0) {
279
+ Logger.warn(summaryLine);
280
+ }
281
+ else {
282
+ Logger.success(summaryLine);
283
+ }
284
+ }
285
+ function renderCheck(check, result) {
286
+ renderCheckLine(check, result);
287
+ renderCheckDetails(result);
288
+ renderCheckHint(result);
289
+ }
290
+ function renderCheckLine(check, result) {
291
+ const message = `[${check.name}] ${result.message}`;
292
+ switch (result.status) {
293
+ case 'ok':
294
+ Logger.success(message);
295
+ return;
296
+ case 'warn':
297
+ Logger.warn(message);
298
+ return;
299
+ case 'fail':
300
+ Logger.error(message);
301
+ return;
302
+ case 'skip':
303
+ Logger.info(`${message} (пропущено)`);
304
+ return;
305
+ }
306
+ }
307
+ function renderCheckDetails(result) {
308
+ if (!result.details || result.details.length === 0)
309
+ return;
310
+ for (const line of result.details) {
311
+ Logger.info(` ${line}`);
312
+ }
313
+ }
314
+ function renderCheckHint(result) {
315
+ if (!result.hint)
316
+ return;
317
+ if (result.status !== 'warn' && result.status !== 'fail')
318
+ return;
319
+ Logger.info(` Подсказка: ${result.hint}`);
320
+ }
321
+ //# sourceMappingURL=doctor.command.js.map