@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
@@ -1,13 +1,23 @@
1
1
  /**
2
2
  * Конфигурируемый file-based коннектор
3
3
  *
4
- * Заменяет дублирование в GeminiConnector, QwenConnector, CodexConnector
5
- * путём передачи конфигурации через конструктор вместо наследования.
4
+ * Универсальная реализация для всех клиентов, хранящих MCP-конфигурацию в JSON/TOML
5
+ * файлах (Claude Desktop, Gemini, Qwen, Codex и т.п.). Параметризуется через
6
+ * {@link ConnectorClientConfig}, передаваемый в конструктор — без наследования.
6
7
  */
7
- import { FileBasedConnector, type ConfigFormat } from './file-based-connector.js';
8
- import type { BaseMCPServerConfig, MCPClientInfo } from '../../types.js';
8
+ import { BaseConnector } from './base-connector.js';
9
+ import type { ConnectionStatus, MCPClientInfo } from '../../types/client.types.js';
10
+ import type { ServerLaunchSpec } from '../../types/launch.types.js';
9
11
  /**
10
- * Конфигурация клиента для ConfigurableConnector
12
+ * Формат конфигурационного файла клиента
13
+ */
14
+ export type ConfigFormat = 'json' | 'toml';
15
+ /**
16
+ * Конфигурация клиента для {@link ConfigurableConnector}.
17
+ *
18
+ * `configPath` может быть строкой или функцией: функция позволяет ленивое
19
+ * platform-aware вычисление пути (например, для Claude Desktop, где путь
20
+ * различается на darwin/linux/win32).
11
21
  */
12
22
  export interface ConnectorClientConfig {
13
23
  /** Уникальное имя клиента (например, 'gemini', 'qwen', 'codex') */
@@ -16,8 +26,8 @@ export interface ConnectorClientConfig {
16
26
  displayName: string;
17
27
  /** Описание клиента */
18
28
  description: string;
19
- /** Путь к конфигурационному файлу */
20
- configPath: string;
29
+ /** Путь к конфигурационному файлу или функция, возвращающая такой путь */
30
+ configPath: string | (() => string);
21
31
  /** Поддерживаемые платформы */
22
32
  platforms: Array<'darwin' | 'linux' | 'win32'>;
23
33
  /** Команда проверки установки (опционально) */
@@ -28,41 +38,96 @@ export interface ConnectorClientConfig {
28
38
  configFormat?: ConfigFormat;
29
39
  }
30
40
  /**
31
- * Конфигурируемый file-based коннектор
41
+ * Конфигурируемый file-based коннектор.
32
42
  *
33
- * Позволяет создавать коннекторы без наследования, передавая конфигурацию
34
- * в конструктор. Устраняет дублирование кода между похожими коннекторами.
43
+ * Поддерживает JSON и TOML форматы, произвольные ключи для серверов
44
+ * (`mcpServers`, `mcp_servers`). Запись/чтение/удаление выполняются напрямую
45
+ * над `{ command, args, env }` из {@link ServerLaunchSpec}; framework не
46
+ * знает доменных полей.
35
47
  *
36
48
  * @example
37
49
  * ```typescript
38
- * const geminiConnector = new ConfigurableConnector(
50
+ * const connector = new ConfigurableConnector(
39
51
  * 'mcp-server-yandex-tracker',
40
- * 'dist/yandex-tracker.bundle.cjs',
41
52
  * {
42
53
  * name: 'gemini',
43
54
  * displayName: 'Gemini CLI',
44
- * description: 'Gemini CLI для разработки с MCP серверами',
55
+ * description: 'Gemini CLI для MCP',
45
56
  * configPath: path.join(os.homedir(), '.gemini/settings.json'),
46
57
  * platforms: ['darwin', 'linux', 'win32'],
47
58
  * }
48
59
  * );
60
+ * await connector.connect({ command: 'node', args: ['/abs/path.cjs'], env: {} });
49
61
  * ```
50
62
  */
51
- export declare class ConfigurableConnector<TConfig extends BaseMCPServerConfig = BaseMCPServerConfig> extends FileBasedConnector<TConfig, string, ConfigFormat> {
63
+ export declare class ConfigurableConnector extends BaseConnector {
52
64
  private readonly _serverName;
53
- private readonly _entryPoint;
54
65
  private readonly _clientConfig;
55
66
  /**
56
- * @param serverName - Имя MCP сервера для записи в конфигурацию
57
- * @param entryPoint - Относительный путь к точке входа сервера от projectPath
58
- * @param clientConfig - Конфигурация клиента
67
+ * @param serverName - Имя MCP сервера для записи в конфигурацию клиента
68
+ * @param clientConfig - Конфигурация клиента (имя, путь, формат и т.п.)
59
69
  */
60
- constructor(serverName: string, entryPoint: string, clientConfig: ConnectorClientConfig);
70
+ constructor(serverName: string, clientConfig: ConnectorClientConfig);
61
71
  getClientInfo(): MCPClientInfo;
62
- protected getConfigPath(): string;
63
- protected getServerName(): string;
64
- protected getEntryPoint(): string;
65
- protected getServerKey(): string;
66
- protected getConfigFormat(): ConfigFormat;
72
+ /**
73
+ * Проверить, установлен ли клиент.
74
+ *
75
+ * Если в {@link ConnectorClientConfig.checkCommand} задана команда — пробуем
76
+ * выполнить её с таймаутом {@link CHECK_COMMAND_TIMEOUT_MS}. Успех (exit 0)
77
+ * клиент установлен. Любая ошибка/таймаут → fallback на dir-check.
78
+ *
79
+ * Если `checkCommand` не задана — единственная проверка: наличие директории
80
+ * конфига.
81
+ *
82
+ * Поведение fallback мотивировано тем, что директория конфига может остаться
83
+ * после удаления клиента (false positive); checkCommand даёт более надёжный
84
+ * сигнал, но при его недоступности dir-check всё ещё лучше чем ничего.
85
+ */
86
+ isInstalled(): Promise<boolean>;
87
+ /**
88
+ * Запустить `checkCommand` с таймаутом. Команда парсится по whitespace:
89
+ * первый токен — бинарь, остальное — аргументы. Выполняется через
90
+ * {@link CommandExecutor.execFile} (без shell-интерпретации).
91
+ *
92
+ * @returns `true` если команда успешно выполнилась (exit 0); `false` иначе.
93
+ */
94
+ private tryCheckCommand;
95
+ /**
96
+ * Получить статус подключения. Дополнительно к наличию записи в конфиге проверяет
97
+ * существование `command` на диске (для абсолютных путей и `node` со скриптом
98
+ * в args).
99
+ */
100
+ getStatus(): Promise<ConnectionStatus>;
101
+ /**
102
+ * Подключить MCP сервер: записать spec в файл конфигурации клиента.
103
+ */
104
+ connect(spec: ServerLaunchSpec): Promise<void>;
105
+ /**
106
+ * Отключить MCP сервер: удалить запись из конфигурации.
107
+ */
108
+ disconnect(): Promise<void>;
109
+ /**
110
+ * Прочитать spec, записанную в конфиге клиента.
111
+ *
112
+ * @returns spec, если сервер присутствует в конфиге; `null` иначе.
113
+ */
114
+ getLaunchSpec(): Promise<ServerLaunchSpec | null>;
115
+ private resolveConfigPath;
116
+ private getServerKey;
117
+ private getConfigFormat;
118
+ private readConfig;
119
+ private writeConfig;
120
+ private createDefaultConfig;
121
+ /**
122
+ * Проверка существования команды на диске. Логика выровнена с
123
+ * {@link BaseConnector.validateLaunchSpec}:
124
+ * - абсолютный путь команды → `fs.access`;
125
+ * - `node` + первый абсолютный путь в args → `fs.access`;
126
+ * - всё остальное (`npx`, `pipx`, относительная команда из PATH) → считаем OK,
127
+ * не пытаемся резолвить PATH.
128
+ */
129
+ private commandExistsOnDisk;
130
+ private describeCommand;
131
+ private pathExists;
67
132
  }
68
133
  //# sourceMappingURL=configurable-connector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configurable-connector.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/configurable-connector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC;IAC/C,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAqB,CAChC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB,CACzD,SAAQ,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IAEtD;;;;OAIG;gBACS,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,qBAAqB;IAOvF,aAAa,IAAI,aAAa;IAc9B,SAAS,CAAC,aAAa,IAAI,MAAM;IAIjC,SAAS,CAAC,aAAa,IAAI,MAAM;IAIjC,SAAS,CAAC,aAAa,IAAI,MAAM;cAId,YAAY,IAAI,MAAM;cAItB,eAAe,IAAI,YAAY;CAGnD"}
1
+ {"version":3,"file":"configurable-connector.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/configurable-connector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAkCpE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACpC,+BAA+B;IAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC;IAC/C,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AASD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,qBAAsB,SAAQ,aAAa;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IAEtD;;;OAGG;gBACS,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,qBAAqB;IAMnE,aAAa,IAAI,aAAa;IAc9B;;;;;;;;;;;;;OAaG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAcrC;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAavB;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA4C5C;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BpD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAgCvD,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;YAIT,UAAU;YAQV,WAAW;IAUzB,OAAO,CAAC,mBAAmB;IAI3B;;;;;;;OAOG;YACW,mBAAmB;IAcjC,OAAO,CAAC,eAAe;YAST,UAAU;CAQzB"}
@@ -1,44 +1,62 @@
1
1
  /**
2
2
  * Конфигурируемый file-based коннектор
3
3
  *
4
- * Заменяет дублирование в GeminiConnector, QwenConnector, CodexConnector
5
- * путём передачи конфигурации через конструктор вместо наследования.
4
+ * Универсальная реализация для всех клиентов, хранящих MCP-конфигурацию в JSON/TOML
5
+ * файлах (Claude Desktop, Gemini, Qwen, Codex и т.п.). Параметризуется через
6
+ * {@link ConnectorClientConfig}, передаваемый в конструктор — без наследования.
6
7
  */
7
- import { FileBasedConnector } from './file-based-connector.js';
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import { BaseConnector } from './base-connector.js';
11
+ import { CommandExecutor } from '../../utils/command-executor.js';
12
+ import { FileManager } from '../../utils/file-manager.js';
13
+ import { resolveExecutablePath } from '../../utils/launch-spec-helpers.js';
8
14
  /**
9
- * Конфигурируемый file-based коннектор
15
+ * Таймаут для проверки `checkCommand` в {@link ConfigurableConnector.isInstalled}.
16
+ *
17
+ * 2 секунды — компромисс между быстрой проверкой и допуском медленных
18
+ * стартующих CLI (gemini, codex могут грузиться 300-500ms на старте).
19
+ */
20
+ const CHECK_COMMAND_TIMEOUT_MS = 2000;
21
+ /**
22
+ * Type guard для проверки Error
23
+ */
24
+ function isError(error) {
25
+ return error instanceof Error;
26
+ }
27
+ /**
28
+ * Конфигурируемый file-based коннектор.
10
29
  *
11
- * Позволяет создавать коннекторы без наследования, передавая конфигурацию
12
- * в конструктор. Устраняет дублирование кода между похожими коннекторами.
30
+ * Поддерживает JSON и TOML форматы, произвольные ключи для серверов
31
+ * (`mcpServers`, `mcp_servers`). Запись/чтение/удаление выполняются напрямую
32
+ * над `{ command, args, env }` из {@link ServerLaunchSpec}; framework не
33
+ * знает доменных полей.
13
34
  *
14
35
  * @example
15
36
  * ```typescript
16
- * const geminiConnector = new ConfigurableConnector(
37
+ * const connector = new ConfigurableConnector(
17
38
  * 'mcp-server-yandex-tracker',
18
- * 'dist/yandex-tracker.bundle.cjs',
19
39
  * {
20
40
  * name: 'gemini',
21
41
  * displayName: 'Gemini CLI',
22
- * description: 'Gemini CLI для разработки с MCP серверами',
42
+ * description: 'Gemini CLI для MCP',
23
43
  * configPath: path.join(os.homedir(), '.gemini/settings.json'),
24
44
  * platforms: ['darwin', 'linux', 'win32'],
25
45
  * }
26
46
  * );
47
+ * await connector.connect({ command: 'node', args: ['/abs/path.cjs'], env: {} });
27
48
  * ```
28
49
  */
29
- export class ConfigurableConnector extends FileBasedConnector {
50
+ export class ConfigurableConnector extends BaseConnector {
30
51
  _serverName;
31
- _entryPoint;
32
52
  _clientConfig;
33
53
  /**
34
- * @param serverName - Имя MCP сервера для записи в конфигурацию
35
- * @param entryPoint - Относительный путь к точке входа сервера от projectPath
36
- * @param clientConfig - Конфигурация клиента
54
+ * @param serverName - Имя MCP сервера для записи в конфигурацию клиента
55
+ * @param clientConfig - Конфигурация клиента (имя, путь, формат и т.п.)
37
56
  */
38
- constructor(serverName, entryPoint, clientConfig) {
57
+ constructor(serverName, clientConfig) {
39
58
  super();
40
59
  this._serverName = serverName;
41
- this._entryPoint = entryPoint;
42
60
  this._clientConfig = clientConfig;
43
61
  }
44
62
  getClientInfo() {
@@ -46,7 +64,7 @@ export class ConfigurableConnector extends FileBasedConnector {
46
64
  name: this._clientConfig.name,
47
65
  displayName: this._clientConfig.displayName,
48
66
  description: this._clientConfig.description,
49
- configPath: this._clientConfig.configPath,
67
+ configPath: this.resolveConfigPath(),
50
68
  platforms: this._clientConfig.platforms,
51
69
  };
52
70
  if (this._clientConfig.checkCommand) {
@@ -54,14 +72,181 @@ export class ConfigurableConnector extends FileBasedConnector {
54
72
  }
55
73
  return info;
56
74
  }
57
- getConfigPath() {
58
- return this._clientConfig.configPath;
75
+ /**
76
+ * Проверить, установлен ли клиент.
77
+ *
78
+ * Если в {@link ConnectorClientConfig.checkCommand} задана команда — пробуем
79
+ * выполнить её с таймаутом {@link CHECK_COMMAND_TIMEOUT_MS}. Успех (exit 0) →
80
+ * клиент установлен. Любая ошибка/таймаут → fallback на dir-check.
81
+ *
82
+ * Если `checkCommand` не задана — единственная проверка: наличие директории
83
+ * конфига.
84
+ *
85
+ * Поведение fallback мотивировано тем, что директория конфига может остаться
86
+ * после удаления клиента (false positive); checkCommand даёт более надёжный
87
+ * сигнал, но при его недоступности dir-check всё ещё лучше чем ничего.
88
+ */
89
+ async isInstalled() {
90
+ const checkCommand = this._clientConfig.checkCommand;
91
+ if (checkCommand && checkCommand.trim().length > 0) {
92
+ const installed = this.tryCheckCommand(checkCommand);
93
+ if (installed) {
94
+ return true;
95
+ }
96
+ // Fallback на dir-check (например, бинарь временно недоступен в PATH,
97
+ // но клиент явно установлен — есть конфиг).
98
+ }
99
+ const configDir = path.dirname(this.resolveConfigPath());
100
+ return FileManager.exists(configDir);
101
+ }
102
+ /**
103
+ * Запустить `checkCommand` с таймаутом. Команда парсится по whitespace:
104
+ * первый токен — бинарь, остальное — аргументы. Выполняется через
105
+ * {@link CommandExecutor.execFile} (без shell-интерпретации).
106
+ *
107
+ * @returns `true` если команда успешно выполнилась (exit 0); `false` иначе.
108
+ */
109
+ tryCheckCommand(checkCommand) {
110
+ const tokens = checkCommand.split(/\s+/).filter((t) => t.length > 0);
111
+ const bin = tokens[0];
112
+ if (!bin)
113
+ return false;
114
+ const args = tokens.slice(1);
115
+ try {
116
+ CommandExecutor.execFile(bin, args, { timeout: CHECK_COMMAND_TIMEOUT_MS });
117
+ return true;
118
+ }
119
+ catch {
120
+ return false;
121
+ }
122
+ }
123
+ /**
124
+ * Получить статус подключения. Дополнительно к наличию записи в конфиге проверяет
125
+ * существование `command` на диске (для абсолютных путей и `node` со скриптом
126
+ * в args).
127
+ */
128
+ async getStatus() {
129
+ try {
130
+ const configPath = this.resolveConfigPath();
131
+ if (!(await FileManager.exists(configPath))) {
132
+ return { connected: false, error: 'Конфигурационный файл не найден' };
133
+ }
134
+ const config = await this.readConfig();
135
+ const servers = config[this.getServerKey()];
136
+ const serverEntry = servers?.[this._serverName];
137
+ if (!serverEntry) {
138
+ return { connected: false };
139
+ }
140
+ const commandOk = await this.commandExistsOnDisk(serverEntry);
141
+ if (!commandOk) {
142
+ return {
143
+ connected: false,
144
+ error: `Команда сервера не найдена на диске: ${this.describeCommand(serverEntry)}`,
145
+ details: {
146
+ configPath,
147
+ metadata: { serverConfig: serverEntry },
148
+ },
149
+ };
150
+ }
151
+ return {
152
+ connected: true,
153
+ details: {
154
+ configPath,
155
+ metadata: { serverConfig: serverEntry },
156
+ },
157
+ };
158
+ }
159
+ catch (error) {
160
+ const errorMessage = isError(error) ? error.message : String(error);
161
+ return {
162
+ connected: false,
163
+ error: `Ошибка чтения конфига: ${errorMessage}`,
164
+ };
165
+ }
166
+ }
167
+ /**
168
+ * Подключить MCP сервер: записать spec в файл конфигурации клиента.
169
+ */
170
+ async connect(spec) {
171
+ const configPath = this.resolveConfigPath();
172
+ const configDir = path.dirname(configPath);
173
+ await FileManager.ensureDir(configDir);
174
+ let config;
175
+ if (await FileManager.exists(configPath)) {
176
+ config = await this.readConfig();
177
+ }
178
+ else {
179
+ config = this.createDefaultConfig();
180
+ }
181
+ const serverKey = this.getServerKey();
182
+ const servers = (config[serverKey] ??= {});
183
+ const entry = {
184
+ command: spec.command,
185
+ args: [...spec.args],
186
+ env: spec.env,
187
+ };
188
+ if (spec.cwd !== undefined) {
189
+ entry.cwd = spec.cwd;
190
+ }
191
+ if (spec.disabled !== undefined) {
192
+ entry.disabled = spec.disabled;
193
+ }
194
+ servers[this._serverName] = entry;
195
+ await this.writeConfig(config);
196
+ }
197
+ /**
198
+ * Отключить MCP сервер: удалить запись из конфигурации.
199
+ */
200
+ async disconnect() {
201
+ const configPath = this.resolveConfigPath();
202
+ if (!(await FileManager.exists(configPath))) {
203
+ return;
204
+ }
205
+ const config = await this.readConfig();
206
+ const serverKey = this.getServerKey();
207
+ const servers = config[serverKey];
208
+ if (servers?.[this._serverName]) {
209
+ delete servers[this._serverName];
210
+ await this.writeConfig(config);
211
+ }
59
212
  }
60
- getServerName() {
61
- return this._serverName;
213
+ /**
214
+ * Прочитать spec, записанную в конфиге клиента.
215
+ *
216
+ * @returns spec, если сервер присутствует в конфиге; `null` иначе.
217
+ */
218
+ async getLaunchSpec() {
219
+ try {
220
+ const configPath = this.resolveConfigPath();
221
+ if (!(await FileManager.exists(configPath))) {
222
+ return null;
223
+ }
224
+ const config = await this.readConfig();
225
+ const entry = config[this.getServerKey()]?.[this._serverName];
226
+ if (!entry) {
227
+ return null;
228
+ }
229
+ const spec = {
230
+ command: entry.command,
231
+ args: entry.args,
232
+ env: entry.env,
233
+ };
234
+ if (entry.cwd !== undefined) {
235
+ spec.cwd = entry.cwd;
236
+ }
237
+ if (entry.disabled !== undefined) {
238
+ spec.disabled = entry.disabled;
239
+ }
240
+ return spec;
241
+ }
242
+ catch {
243
+ return null;
244
+ }
62
245
  }
63
- getEntryPoint() {
64
- return this._entryPoint;
246
+ // ----- internal -----
247
+ resolveConfigPath() {
248
+ const value = this._clientConfig.configPath;
249
+ return typeof value === 'function' ? value() : value;
65
250
  }
66
251
  getServerKey() {
67
252
  return this._clientConfig.serverKey ?? 'mcpServers';
@@ -69,5 +254,63 @@ export class ConfigurableConnector extends FileBasedConnector {
69
254
  getConfigFormat() {
70
255
  return this._clientConfig.configFormat ?? 'json';
71
256
  }
257
+ async readConfig() {
258
+ const configPath = this.resolveConfigPath();
259
+ const format = this.getConfigFormat();
260
+ return format === 'json'
261
+ ? FileManager.readJSON(configPath)
262
+ : FileManager.readTOML(configPath);
263
+ }
264
+ async writeConfig(config) {
265
+ const configPath = this.resolveConfigPath();
266
+ const format = this.getConfigFormat();
267
+ if (format === 'json') {
268
+ await FileManager.writeJSON(configPath, config);
269
+ }
270
+ else {
271
+ await FileManager.writeTOML(configPath, config);
272
+ }
273
+ }
274
+ createDefaultConfig() {
275
+ return { [this.getServerKey()]: {} };
276
+ }
277
+ /**
278
+ * Проверка существования команды на диске. Логика выровнена с
279
+ * {@link BaseConnector.validateLaunchSpec}:
280
+ * - абсолютный путь команды → `fs.access`;
281
+ * - `node` + первый абсолютный путь в args → `fs.access`;
282
+ * - всё остальное (`npx`, `pipx`, относительная команда из PATH) → считаем OK,
283
+ * не пытаемся резолвить PATH.
284
+ */
285
+ async commandExistsOnDisk(entry) {
286
+ const filePath = resolveExecutablePath({
287
+ command: entry.command,
288
+ args: entry.args,
289
+ env: entry.env,
290
+ });
291
+ if (filePath === null) {
292
+ // npx/pipx/relative-from-PATH или `node` без абсолютного пути в args —
293
+ // на диске проверить нечего, считаем OK.
294
+ return true;
295
+ }
296
+ return this.pathExists(filePath);
297
+ }
298
+ describeCommand(entry) {
299
+ const filePath = resolveExecutablePath({
300
+ command: entry.command,
301
+ args: entry.args,
302
+ env: entry.env,
303
+ });
304
+ return filePath ?? entry.command;
305
+ }
306
+ async pathExists(p) {
307
+ try {
308
+ await fs.access(p);
309
+ return true;
310
+ }
311
+ catch {
312
+ return false;
313
+ }
314
+ }
72
315
  }
73
316
  //# sourceMappingURL=configurable-connector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"configurable-connector.js","sourceRoot":"","sources":["../../../src/connectors/base/configurable-connector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAqB,MAAM,2BAA2B,CAAC;AAyBlF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,qBAEX,SAAQ,kBAAiD;IACxC,WAAW,CAAS;IACpB,WAAW,CAAS;IACpB,aAAa,CAAwB;IAEtD;;;;OAIG;IACH,YAAY,UAAkB,EAAE,UAAkB,EAAE,YAAmC;QACrF,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACpC,CAAC;IAED,aAAa;QACX,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YAC7B,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW;YAC3C,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW;YAC3C,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,UAAU;YACzC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS;SACxC,CAAC;QACF,IAAI,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;YACpC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;QACtD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAES,aAAa;QACrB,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC;IACvC,CAAC;IAES,aAAa;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAES,aAAa;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEkB,YAAY;QAC7B,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,YAAY,CAAC;IACtD,CAAC;IAEkB,eAAe;QAChC,OAAO,IAAI,CAAC,aAAa,CAAC,YAAY,IAAI,MAAM,CAAC;IACnD,CAAC;CACF"}
1
+ {"version":3,"file":"configurable-connector.js","sourceRoot":"","sources":["../../../src/connectors/base/configurable-connector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAI3E;;;;;GAKG;AACH,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAyDtC;;GAEG;AACH,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,KAAK,YAAY,KAAK,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACrC,WAAW,CAAS;IACpB,aAAa,CAAwB;IAEtD;;;OAGG;IACH,YAAY,UAAkB,EAAE,YAAmC;QACjE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACpC,CAAC;IAED,aAAa;QACX,MAAM,IAAI,GAAkB;YAC1B,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YAC7B,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW;YAC3C,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,WAAW;YAC3C,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE;YACpC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS;SACxC,CAAC;QACF,IAAI,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;YACpC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;QACtD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;QACrD,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YACrD,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC;YACd,CAAC;YACD,sEAAsE;YACtE,4CAA4C;QAC9C,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACzD,OAAO,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED;;;;;;OAMG;IACK,eAAe,CAAC,YAAoB;QAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC;YACH,eAAe,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAE5C,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;gBAC5C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;YACxE,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEhD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAC9B,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;YAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO;oBACL,SAAS,EAAE,KAAK;oBAChB,KAAK,EAAE,wCAAwC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE;oBAClF,OAAO,EAAE;wBACP,UAAU;wBACV,QAAQ,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE;qBACxC;iBACF,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE;oBACP,UAAU;oBACV,QAAQ,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE;iBACxC;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpE,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,0BAA0B,YAAY,EAAE;aAChD,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,IAAsB;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAE3C,MAAM,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAEvC,IAAI,MAAuB,CAAC;QAC5B,IAAI,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3C,MAAM,KAAK,GAA4B;YACrC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YACpB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC;QACF,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACvB,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACjC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QAElC,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE5C,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAElC,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACjC,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC5C,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;gBAC5C,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAqB;gBAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,EAAE,KAAK,CAAC,GAAG;aACf,CAAC;YACF,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC5B,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;YACvB,CAAC;YACD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YACjC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,uBAAuB;IAEf,iBAAiB;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC;QAC5C,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACvD,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,YAAY,CAAC;IACtD,CAAC;IAEO,eAAe;QACrB,OAAO,IAAI,CAAC,aAAa,CAAC,YAAY,IAAI,MAAM,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,OAAO,MAAM,KAAK,MAAM;YACtB,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAkB,UAAU,CAAC;YACnD,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAkB,UAAU,CAAC,CAAC;IACxD,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,MAAuB;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,WAAW,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,OAAO,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAqB,CAAC;IAC1D,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,mBAAmB,CAAC,KAA8B;QAC9D,MAAM,QAAQ,GAAG,qBAAqB,CAAC;YACrC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAC,CAAC;QACH,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,uEAAuE;YACvE,yCAAyC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAEO,eAAe,CAAC,KAA8B;QACpD,MAAM,QAAQ,GAAG,qBAAqB,CAAC;YACrC,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAC,CAAC;QACH,OAAO,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,CAAS;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -2,26 +2,26 @@
2
2
  * Base connector interface for MCP clients
3
3
  * @packageDocumentation
4
4
  */
5
- import type { BaseMCPServerConfig, MCPClientInfo, ConnectionStatus } from '../../types/base.types.js';
5
+ import type { MCPClientInfo, ConnectionStatus } from '../../types/client.types.js';
6
+ import type { ServerLaunchSpec } from '../../types/launch.types.js';
6
7
  /**
7
- * Базовый интерфейс для всех MCP коннекторов
8
- * Generic по типу конфигурации сервера
8
+ * Базовый интерфейс для всех MCP коннекторов.
9
9
  *
10
- * @template TConfig - Тип конфигурации MCP сервера (расширяет BaseMCPServerConfig)
10
+ * Framework-агностичен к доменной модели: коннектор оперирует «универсальной»
11
+ * спецификацией запуска {@link ServerLaunchSpec} (`{ command, args, env }`).
12
+ * Маппинг доменных полей в эту спецификацию выполняет вызывающая сторона.
11
13
  *
12
14
  * @example
13
15
  * ```typescript
14
- * interface MyServerConfig extends BaseMCPServerConfig {
15
- * apiKey: string;
16
- * apiBase: string;
17
- * }
18
- *
19
- * class MyConnector implements MCPConnector<MyServerConfig> {
20
- * // implementation
16
+ * class MyConnector implements MCPConnector {
17
+ * async connect(spec: ServerLaunchSpec): Promise<void> {
18
+ * // запись spec в конфиг клиента
19
+ * }
20
+ * // ... остальные методы
21
21
  * }
22
22
  * ```
23
23
  */
24
- export interface MCPConnector<TConfig extends BaseMCPServerConfig = BaseMCPServerConfig> {
24
+ export interface MCPConnector {
25
25
  /**
26
26
  * Получить информацию о MCP клиенте
27
27
  * @returns Метаданные клиента (имя, описание, платформы и т.д.)
@@ -39,24 +39,33 @@ export interface MCPConnector<TConfig extends BaseMCPServerConfig = BaseMCPServe
39
39
  getStatus(): Promise<ConnectionStatus>;
40
40
  /**
41
41
  * Подключить MCP сервер к клиенту
42
- * Записывает конфигурацию в файл клиента
42
+ * Записывает спецификацию запуска в конфигурацию клиента.
43
43
  *
44
- * @param config - Конфигурация MCP сервера
45
- * @throws Если клиент не установлен или конфигурация невалидна
44
+ * @param spec - Спецификация запуска MCP сервера
45
+ * @throws Если клиент не установлен или спецификация невалидна
46
46
  */
47
- connect(config: TConfig): Promise<void>;
47
+ connect(spec: ServerLaunchSpec): Promise<void>;
48
48
  /**
49
49
  * Отключить MCP сервер от клиента
50
- * Удаляет конфигурацию из файла клиента
50
+ * Удаляет конфигурацию из файла клиента.
51
51
  *
52
52
  * @throws Если клиент не установлен или сервер не подключен
53
53
  */
54
54
  disconnect(): Promise<void>;
55
55
  /**
56
- * Валидировать конфигурацию перед подключением
57
- * @param config - Конфигурация для проверки
56
+ * Валидировать спецификацию запуска перед подключением
57
+ * @param spec - Спецификация для проверки
58
58
  * @returns Массив ошибок валидации (пустой если валидация успешна)
59
59
  */
60
- validateConfig(config: TConfig): Promise<string[]>;
60
+ validateLaunchSpec(spec: ServerLaunchSpec): Promise<string[]>;
61
+ /**
62
+ * Получить текущую записанную в конфиге клиента спецификацию запуска.
63
+ * Используется командой `doctor` для самодиагностики (например, проверка
64
+ * существования `command` на диске).
65
+ *
66
+ * @returns Spec, если сервер подключен; `null` если не подключен или конфиг
67
+ * недоступен/повреждён.
68
+ */
69
+ getLaunchSpec(): Promise<ServerLaunchSpec | null>;
61
70
  }
62
71
  //# sourceMappingURL=connector.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connector.interface.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/connector.interface.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,YAAY,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IACrF;;;OAGG;IACH,aAAa,IAAI,aAAa,CAAC;IAE/B;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;OAGG;IACH,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEvC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACpD"}
1
+ {"version":3,"file":"connector.interface.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/connector.interface.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,aAAa,IAAI,aAAa,CAAC;IAE/B;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;OAGG;IACH,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEvC;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE9D;;;;;;;OAOG;IACH,aAAa,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CACnD"}
@@ -4,6 +4,5 @@
4
4
  */
5
5
  export * from './connector.interface.js';
6
6
  export * from './base-connector.js';
7
- export * from './file-based-connector.js';
8
7
  export * from './configurable-connector.js';
9
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connectors/base/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
@@ -4,6 +4,5 @@
4
4
  */
5
5
  export * from './connector.interface.js';
6
6
  export * from './base-connector.js';
7
- export * from './file-based-connector.js';
8
7
  export * from './configurable-connector.js';
9
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/connectors/base/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/connectors/base/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}