@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.
- package/README.md +438 -0
- package/dist/commands/connect.command.d.ts +32 -0
- package/dist/commands/connect.command.d.ts.map +1 -0
- package/dist/commands/connect.command.js +120 -0
- package/dist/commands/connect.command.js.map +1 -0
- package/dist/commands/disconnect.command.d.ts +36 -0
- package/dist/commands/disconnect.command.d.ts.map +1 -0
- package/dist/commands/disconnect.command.js +97 -0
- package/dist/commands/disconnect.command.js.map +1 -0
- package/dist/commands/index.d.ts +10 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +13 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/list.command.d.ts +23 -0
- package/dist/commands/list.command.d.ts.map +1 -0
- package/dist/commands/list.command.js +34 -0
- package/dist/commands/list.command.js.map +1 -0
- package/dist/commands/status.command.d.ts +23 -0
- package/dist/commands/status.command.d.ts.map +1 -0
- package/dist/commands/status.command.js +61 -0
- package/dist/commands/status.command.js.map +1 -0
- package/dist/commands/validate.command.d.ts +25 -0
- package/dist/commands/validate.command.d.ts.map +1 -0
- package/dist/commands/validate.command.js +58 -0
- package/dist/commands/validate.command.js.map +1 -0
- package/dist/connectors/base/base-connector.d.ts +89 -0
- package/dist/connectors/base/base-connector.d.ts.map +1 -0
- package/dist/connectors/base/base-connector.js +99 -0
- package/dist/connectors/base/base-connector.js.map +1 -0
- package/dist/connectors/base/configurable-connector.d.ts +68 -0
- package/dist/connectors/base/configurable-connector.d.ts.map +1 -0
- package/dist/connectors/base/configurable-connector.js +73 -0
- package/dist/connectors/base/configurable-connector.js.map +1 -0
- package/dist/connectors/base/connector.interface.d.ts +62 -0
- package/dist/connectors/base/connector.interface.d.ts.map +1 -0
- package/dist/connectors/base/connector.interface.js +6 -0
- package/dist/connectors/base/connector.interface.js.map +1 -0
- package/dist/connectors/base/file-based-connector.d.ts +97 -0
- package/dist/connectors/base/file-based-connector.d.ts.map +1 -0
- package/dist/connectors/base/file-based-connector.js +185 -0
- package/dist/connectors/base/file-based-connector.js.map +1 -0
- package/dist/connectors/base/index.d.ts +9 -0
- package/dist/connectors/base/index.d.ts.map +1 -0
- package/dist/connectors/base/index.js +9 -0
- package/dist/connectors/base/index.js.map +1 -0
- package/dist/connectors/claude-code/claude-code.connector.d.ts +41 -0
- package/dist/connectors/claude-code/claude-code.connector.d.ts.map +1 -0
- package/dist/connectors/claude-code/claude-code.connector.js +96 -0
- package/dist/connectors/claude-code/claude-code.connector.js.map +1 -0
- package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts +38 -0
- package/dist/connectors/claude-desktop/claude-desktop.connector.d.ts.map +1 -0
- package/dist/connectors/claude-desktop/claude-desktop.connector.js +68 -0
- package/dist/connectors/claude-desktop/claude-desktop.connector.js.map +1 -0
- package/dist/connectors/codex/codex.connector.d.ts +51 -0
- package/dist/connectors/codex/codex.connector.d.ts.map +1 -0
- package/dist/connectors/codex/codex.connector.js +76 -0
- package/dist/connectors/codex/codex.connector.js.map +1 -0
- package/dist/connectors/connector-factory.d.ts +42 -0
- package/dist/connectors/connector-factory.d.ts.map +1 -0
- package/dist/connectors/connector-factory.js +81 -0
- package/dist/connectors/connector-factory.js.map +1 -0
- package/dist/connectors/gemini/gemini.connector.d.ts +41 -0
- package/dist/connectors/gemini/gemini.connector.d.ts.map +1 -0
- package/dist/connectors/gemini/gemini.connector.js +61 -0
- package/dist/connectors/gemini/gemini.connector.js.map +1 -0
- package/dist/connectors/index.d.ts +13 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +19 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/qwen/qwen.connector.d.ts +41 -0
- package/dist/connectors/qwen/qwen.connector.d.ts.map +1 -0
- package/dist/connectors/qwen/qwen.connector.js +61 -0
- package/dist/connectors/qwen/qwen.connector.js.map +1 -0
- package/dist/connectors/registry.d.ts +55 -0
- package/dist/connectors/registry.d.ts.map +1 -0
- package/dist/connectors/registry.js +75 -0
- package/dist/connectors/registry.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/base.types.d.ts +116 -0
- package/dist/types/base.types.d.ts.map +1 -0
- package/dist/types/base.types.js +6 -0
- package/dist/types/base.types.js.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/command-executor.d.ts +78 -0
- package/dist/utils/command-executor.d.ts.map +1 -0
- package/dist/utils/command-executor.js +114 -0
- package/dist/utils/command-executor.js.map +1 -0
- package/dist/utils/config-manager.d.ts +76 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +123 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/file-manager.d.ts +146 -0
- package/dist/utils/file-manager.d.ts.map +1 -0
- package/dist/utils/file-manager.js +200 -0
- package/dist/utils/file-manager.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/interactive-prompter.d.ts +109 -0
- package/dist/utils/interactive-prompter.d.ts.map +1 -0
- package/dist/utils/interactive-prompter.js +184 -0
- package/dist/utils/interactive-prompter.js.map +1 -0
- package/dist/utils/logger.d.ts +113 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +130 -0
- package/dist/utils/logger.js.map +1 -0
- 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"}
|