schemeog-mcp 2.0.0 → 2.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 +189 -52
- package/index.js +801 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# SchemeOG MCP Server v2.
|
|
1
|
+
# SchemeOG MCP Server v2.1
|
|
2
2
|
|
|
3
3
|
MCP сервер для [SchemeOG Cloud](https://scheme.smartlaunchhub.com) — создавай диаграммы и схемы с помощью AI.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 14 команд для полного контроля
|
|
6
|
+
|
|
7
|
+
### Схемы (5 команд)
|
|
6
8
|
|
|
7
9
|
| Команда | Описание |
|
|
8
10
|
|---------|----------|
|
|
@@ -12,12 +14,31 @@ MCP сервер для [SchemeOG Cloud](https://scheme.smartlaunchhub.com) —
|
|
|
12
14
|
| `replace_schema` | Заменить содержимое схемы |
|
|
13
15
|
| `delete_schema` | Удалить схему |
|
|
14
16
|
|
|
17
|
+
### Проекты (5 команд)
|
|
18
|
+
|
|
19
|
+
| Команда | Описание |
|
|
20
|
+
|---------|----------|
|
|
21
|
+
| `list_projects` | Список проектов (папок) |
|
|
22
|
+
| `create_project` | Создать проект |
|
|
23
|
+
| `update_project` | Обновить проект |
|
|
24
|
+
| `delete_project` | Удалить проект |
|
|
25
|
+
| `move_schema_to_project` | Переместить схему в проект |
|
|
26
|
+
|
|
27
|
+
### Теги (4 команды)
|
|
28
|
+
|
|
29
|
+
| Команда | Описание |
|
|
30
|
+
|---------|----------|
|
|
31
|
+
| `list_tags` | Список тегов схемы |
|
|
32
|
+
| `add_tag` | Добавить тег в схему |
|
|
33
|
+
| `remove_tag` | Удалить тег из схемы |
|
|
34
|
+
| `tag_element` | Присвоить/убрать тег с элемента |
|
|
35
|
+
|
|
15
36
|
## Установка
|
|
16
37
|
|
|
17
38
|
### Через npx (рекомендуется)
|
|
18
39
|
|
|
19
40
|
```bash
|
|
20
|
-
npx schemeog-
|
|
41
|
+
npx schemeog-mcp
|
|
21
42
|
```
|
|
22
43
|
|
|
23
44
|
## Настройка
|
|
@@ -26,8 +47,8 @@ npx schemeog-cloud-mcp
|
|
|
26
47
|
|
|
27
48
|
1. Открой https://scheme.smartlaunchhub.com
|
|
28
49
|
2. Войди по email
|
|
29
|
-
3.
|
|
30
|
-
4. Скопируй
|
|
50
|
+
3. Перейди в Профиль
|
|
51
|
+
4. Скопируй токен из секции "Claude Code Integration"
|
|
31
52
|
|
|
32
53
|
### 2. Добавь в Claude Code / Cline
|
|
33
54
|
|
|
@@ -38,91 +59,207 @@ npx schemeog-cloud-mcp
|
|
|
38
59
|
"mcpServers": {
|
|
39
60
|
"schemeog": {
|
|
40
61
|
"command": "npx",
|
|
41
|
-
"args": ["-y", "schemeog-
|
|
62
|
+
"args": ["-y", "schemeog-mcp"],
|
|
42
63
|
"env": {
|
|
43
|
-
"SCHEMEOG_TOKEN": "
|
|
64
|
+
"SCHEMEOG_TOKEN": "schog_xxxxx..."
|
|
44
65
|
}
|
|
45
66
|
}
|
|
46
67
|
}
|
|
47
68
|
}
|
|
48
69
|
```
|
|
49
70
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
### Создать схему
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
Создай схему "User Registration Flow" с блоками:
|
|
56
|
-
- Форма регистрации
|
|
57
|
-
- Валидация
|
|
58
|
-
- Сохранение в БД
|
|
59
|
-
- Отправка email
|
|
60
|
-
- Успех
|
|
61
|
-
```
|
|
71
|
+
## Формат данных схемы
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
### Полный пример схемы
|
|
64
74
|
|
|
65
75
|
```json
|
|
66
76
|
{
|
|
67
77
|
"name": "User Registration Flow",
|
|
78
|
+
"description": "Процесс регистрации пользователя",
|
|
68
79
|
"elements": [
|
|
69
|
-
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
{
|
|
81
|
+
"id": "start",
|
|
82
|
+
"type": "card",
|
|
83
|
+
"title": "Форма регистрации",
|
|
84
|
+
"color": "light_green",
|
|
85
|
+
"borderColor": "green",
|
|
86
|
+
"tags": ["пользователь"],
|
|
87
|
+
"description": "Пользователь заполняет форму с email и паролем"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "validate",
|
|
91
|
+
"type": "condition",
|
|
92
|
+
"title": "Валидация данных",
|
|
93
|
+
"color": "light_yellow",
|
|
94
|
+
"borderColor": "yellow",
|
|
95
|
+
"tags": ["система", "проверка"],
|
|
96
|
+
"description": "Проверка корректности email и сложности пароля"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "save",
|
|
100
|
+
"type": "card",
|
|
101
|
+
"title": "Сохранение в БД",
|
|
102
|
+
"color": "light_blue",
|
|
103
|
+
"borderColor": "blue",
|
|
104
|
+
"tags": ["система"],
|
|
105
|
+
"description": "Создание записи пользователя в базе данных"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "error",
|
|
109
|
+
"type": "card",
|
|
110
|
+
"title": "Ошибка валидации",
|
|
111
|
+
"color": "light_red",
|
|
112
|
+
"borderColor": "red",
|
|
113
|
+
"tags": ["система", "ошибка"],
|
|
114
|
+
"description": "Показать пользователю ошибки валидации"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "success",
|
|
118
|
+
"type": "card",
|
|
119
|
+
"title": "Успешная регистрация",
|
|
120
|
+
"color": "light_green",
|
|
121
|
+
"borderColor": "green",
|
|
122
|
+
"tags": ["пользователь"],
|
|
123
|
+
"description": "Пользователь успешно зарегистрирован"
|
|
124
|
+
}
|
|
74
125
|
],
|
|
75
126
|
"connections": [
|
|
76
|
-
{"from": "
|
|
77
|
-
{"from": "
|
|
78
|
-
{"from": "
|
|
79
|
-
{"from": "
|
|
127
|
+
{"from": "start", "to": "validate", "label": "отправка формы"},
|
|
128
|
+
{"from": "validate", "to": "save", "label": "данные корректны"},
|
|
129
|
+
{"from": "validate", "to": "error", "label": "ошибка"},
|
|
130
|
+
{"from": "save", "to": "success"},
|
|
131
|
+
{"from": "error", "to": "start", "label": "исправить"}
|
|
132
|
+
],
|
|
133
|
+
"tagsDictionary": [
|
|
134
|
+
{"id": "tag-user", "name": "пользователь", "color": "#4CAF50"},
|
|
135
|
+
{"id": "tag-system", "name": "система", "color": "#2196F3"},
|
|
136
|
+
{"id": "tag-check", "name": "проверка", "color": "#FF9800"},
|
|
137
|
+
{"id": "tag-error", "name": "ошибка", "color": "#F44336"}
|
|
80
138
|
]
|
|
81
139
|
}
|
|
82
140
|
```
|
|
83
141
|
|
|
84
|
-
###
|
|
142
|
+
### Элемент (card или condition)
|
|
85
143
|
|
|
86
|
-
```
|
|
87
|
-
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"id": "unique_id",
|
|
147
|
+
"type": "card",
|
|
148
|
+
"title": "Название карточки",
|
|
149
|
+
"color": "light_blue",
|
|
150
|
+
"borderColor": "blue",
|
|
151
|
+
"tags": ["тег1", "тег2"],
|
|
152
|
+
"description": "Подробное описание действия или процесса"
|
|
153
|
+
}
|
|
88
154
|
```
|
|
89
155
|
|
|
90
|
-
|
|
156
|
+
**Типы элементов:**
|
|
157
|
+
- `card` — обычная карточка процесса/действия
|
|
158
|
+
- `condition` — точка принятия решения (ромб)
|
|
91
159
|
|
|
92
|
-
|
|
160
|
+
**Доступные цвета фона (`color`):**
|
|
161
|
+
| Цвет | Назначение |
|
|
162
|
+
|------|------------|
|
|
163
|
+
| `white` | Базовый белый |
|
|
164
|
+
| `light_blue` | Основные процессы |
|
|
165
|
+
| `light_green` | Старт и успех |
|
|
166
|
+
| `light_yellow` | Проверки и условия |
|
|
167
|
+
| `light_orange` | Предупреждения |
|
|
168
|
+
| `light_red` | Ошибки и критичное |
|
|
169
|
+
| `light_purple` | Решения |
|
|
170
|
+
| `light_gray` | Завершение |
|
|
171
|
+
| `light_pink` | Дополнительные процессы |
|
|
172
|
+
| `light_teal` | Специальные операции |
|
|
93
173
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```
|
|
174
|
+
**Цвета обводки (`borderColor`):**
|
|
175
|
+
`default`, `blue`, `green`, `orange`, `purple`, `red`, `teal`, `yellow`, `gray`, `black`
|
|
97
176
|
|
|
98
|
-
|
|
177
|
+
**Важно:** НЕ указывай `width`, `height`, `x`, `y` — они рассчитываются автоматически!
|
|
99
178
|
|
|
100
|
-
###
|
|
179
|
+
### Связь (connection)
|
|
101
180
|
|
|
102
181
|
```json
|
|
103
182
|
{
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"text": "Текст", // содержимое
|
|
109
|
-
"width": 200, // ширина (опционально)
|
|
110
|
-
"height": 100, // высота (опционально)
|
|
111
|
-
"color": "#E3F2FD" // цвет фона (опционально)
|
|
183
|
+
"from": "source_id",
|
|
184
|
+
"to": "target_id",
|
|
185
|
+
"label": "подпись (опционально)",
|
|
186
|
+
"style": "solid"
|
|
112
187
|
}
|
|
113
188
|
```
|
|
114
189
|
|
|
115
|
-
|
|
190
|
+
**Стили линий (`style`):** `solid`, `dashed`, `dotted`
|
|
191
|
+
|
|
192
|
+
### Справочник тегов (tagsDictionary)
|
|
116
193
|
|
|
117
194
|
```json
|
|
118
195
|
{
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
196
|
+
"tagsDictionary": [
|
|
197
|
+
{"id": "tag-1", "name": "система", "color": "#2196F3"},
|
|
198
|
+
{"id": "tag-2", "name": "пользователь", "color": "#4CAF50"},
|
|
199
|
+
{"id": "tag-3", "name": "проверка", "color": "#FF9800"}
|
|
200
|
+
]
|
|
123
201
|
}
|
|
124
202
|
```
|
|
125
203
|
|
|
204
|
+
**Теги = роли/акторы.** Указывают КТО выполняет действие:
|
|
205
|
+
- `система`, `пользователь`, `администратор`
|
|
206
|
+
- `клиент`, `менеджер`, `бот`
|
|
207
|
+
- `муж`, `жена`, `ребёнок` (для личных схем)
|
|
208
|
+
|
|
209
|
+
## Примеры использования
|
|
210
|
+
|
|
211
|
+
### Создать схему
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
Создай схему "Авторизация пользователя" с этапами:
|
|
215
|
+
1. Ввод логина/пароля (пользователь)
|
|
216
|
+
2. Проверка в базе (система)
|
|
217
|
+
3. Успех или ошибка
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Обновить схему
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Добавь в схему блок "Двухфакторная аутентификация" между проверкой и успехом
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Работа с проектами
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Создай проект "Backend API" с иконкой 🚀 и синим цветом
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
Перемести схему в проект Backend API
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Работа с тегами
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
Добавь тег "Critical" красного цвета в схему
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
Пометь элемент "Валидация" тегом Critical
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Методология создания схем
|
|
247
|
+
|
|
248
|
+
Схема = полное дерево **ДЕЙСТВИЙ** и **ПОСЛЕДСТВИЙ**:
|
|
249
|
+
|
|
250
|
+
1. Каждое решение → показать ВСЕ возможные варианты
|
|
251
|
+
2. Каждый вариант → показать ВСЕ последствия
|
|
252
|
+
3. Использовать `condition` для точек принятия решений
|
|
253
|
+
4. НЕ абстрактные размышления — КОНКРЕТНЫЕ пути развития
|
|
254
|
+
5. Теги указывают КТО выполняет действие
|
|
255
|
+
|
|
256
|
+
**Пример:**
|
|
257
|
+
```
|
|
258
|
+
"Отправка формы" → condition "Валидация" →
|
|
259
|
+
├── "Данные корректны" → "Сохранение" → "Успех"
|
|
260
|
+
└── "Ошибка" → "Показать ошибки" → "Исправить форму"
|
|
261
|
+
```
|
|
262
|
+
|
|
126
263
|
## Ссылки
|
|
127
264
|
|
|
128
265
|
- [SchemeOG Cloud](https://scheme.smartlaunchhub.com)
|
package/index.js
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* SchemeOG
|
|
4
|
+
* SchemeOG MCP Server v2.1
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* 5 команд — максимум мощи, минимум сложности.
|
|
6
|
+
* MCP сервер для работы со схемами, проектами и тегами в SchemeOG Cloud.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
8
|
+
* Команды для схем:
|
|
10
9
|
* - list_schemas: Список всех схем
|
|
11
10
|
* - get_schema: Получить схему с данными
|
|
12
11
|
* - create_schema: Создать схему (с элементами и связями)
|
|
13
12
|
* - replace_schema: Полностью заменить содержимое схемы
|
|
14
13
|
* - delete_schema: Удалить схему
|
|
14
|
+
*
|
|
15
|
+
* Команды для проектов:
|
|
16
|
+
* - list_projects: Список проектов (папок)
|
|
17
|
+
* - create_project: Создать проект
|
|
18
|
+
* - update_project: Обновить проект
|
|
19
|
+
* - delete_project: Удалить проект
|
|
20
|
+
* - move_schema_to_project: Переместить схему в проект
|
|
21
|
+
*
|
|
22
|
+
* Команды для тегов:
|
|
23
|
+
* - list_tags: Список тегов схемы
|
|
24
|
+
* - add_tag: Добавить тег в схему
|
|
25
|
+
* - remove_tag: Удалить тег из схемы
|
|
26
|
+
* - tag_element: Присвоить/убрать тег с элемента
|
|
15
27
|
*/
|
|
16
28
|
|
|
17
29
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -24,16 +36,98 @@ import {
|
|
|
24
36
|
// Конфигурация
|
|
25
37
|
const API_BASE_URL = process.env.SCHEMEOG_API_URL || "https://scheme.smartlaunchhub.com";
|
|
26
38
|
const AUTH_TOKEN = process.env.SCHEMEOG_TOKEN || "";
|
|
39
|
+
const DOCS_URL = "https://scheme.smartlaunchhub.com/docs";
|
|
40
|
+
const PROFILE_URL = "https://scheme.smartlaunchhub.com/profile";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Коды ошибок MCP
|
|
44
|
+
*/
|
|
45
|
+
const ErrorCodes = {
|
|
46
|
+
AUTH_MISSING: "AUTH_MISSING",
|
|
47
|
+
AUTH_INVALID: "AUTH_INVALID",
|
|
48
|
+
AUTH_EXPIRED: "AUTH_EXPIRED",
|
|
49
|
+
NOT_FOUND: "NOT_FOUND",
|
|
50
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
51
|
+
RATE_LIMIT: "RATE_LIMIT",
|
|
52
|
+
SERVER_ERROR: "SERVER_ERROR",
|
|
53
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Создать форматированную ошибку
|
|
58
|
+
*/
|
|
59
|
+
function createError(code, message, details = {}) {
|
|
60
|
+
const errorMessages = {
|
|
61
|
+
[ErrorCodes.AUTH_MISSING]: {
|
|
62
|
+
title: "🔑 Токен не указан",
|
|
63
|
+
hint: `Укажите SCHEMEOG_TOKEN в настройках MCP.\n\nПолучить токен: ${PROFILE_URL}\nДокументация: ${DOCS_URL}`,
|
|
64
|
+
},
|
|
65
|
+
[ErrorCodes.AUTH_INVALID]: {
|
|
66
|
+
title: "🔒 Неверный токен",
|
|
67
|
+
hint: `Токен невалидный или отозван.\n\nСоздайте новый токен: ${PROFILE_URL}`,
|
|
68
|
+
},
|
|
69
|
+
[ErrorCodes.AUTH_EXPIRED]: {
|
|
70
|
+
title: "⏰ Токен истёк",
|
|
71
|
+
hint: `Срок действия токена истёк.\n\nСоздайте новый токен: ${PROFILE_URL}`,
|
|
72
|
+
},
|
|
73
|
+
[ErrorCodes.NOT_FOUND]: {
|
|
74
|
+
title: "🔍 Не найдено",
|
|
75
|
+
hint: `Проверьте правильность ID.\n\nСписок схем: list_schemas\nСписок проектов: list_projects`,
|
|
76
|
+
},
|
|
77
|
+
[ErrorCodes.VALIDATION_ERROR]: {
|
|
78
|
+
title: "⚠️ Ошибка валидации",
|
|
79
|
+
hint: `Проверьте формат данных.\n\nДокументация: ${DOCS_URL}`,
|
|
80
|
+
},
|
|
81
|
+
[ErrorCodes.RATE_LIMIT]: {
|
|
82
|
+
title: "🚫 Превышен лимит запросов",
|
|
83
|
+
hint: "Подождите немного и повторите запрос.",
|
|
84
|
+
},
|
|
85
|
+
[ErrorCodes.SERVER_ERROR]: {
|
|
86
|
+
title: "💥 Ошибка сервера",
|
|
87
|
+
hint: `Попробуйте позже или обратитесь в поддержку.\n\nСтатус: ${API_BASE_URL}/status`,
|
|
88
|
+
},
|
|
89
|
+
[ErrorCodes.NETWORK_ERROR]: {
|
|
90
|
+
title: "🌐 Ошибка сети",
|
|
91
|
+
hint: "Проверьте подключение к интернету.",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const errorInfo = errorMessages[code] || { title: "Ошибка", hint: "" };
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
code,
|
|
99
|
+
message: `${errorInfo.title}\n\n${message}${errorInfo.hint ? `\n\n${errorInfo.hint}` : ""}`,
|
|
100
|
+
details,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
27
103
|
|
|
28
104
|
/**
|
|
29
105
|
* Выполнить запрос к API SchemeOG
|
|
30
106
|
*/
|
|
31
107
|
async function apiRequest(endpoint, options = {}) {
|
|
108
|
+
// Проверка токена перед запросом
|
|
109
|
+
if (!AUTH_TOKEN) {
|
|
110
|
+
const error = createError(
|
|
111
|
+
ErrorCodes.AUTH_MISSING,
|
|
112
|
+
"Переменная окружения SCHEMEOG_TOKEN не установлена."
|
|
113
|
+
);
|
|
114
|
+
throw new Error(error.message);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Базовая валидация формата токена
|
|
118
|
+
if (!AUTH_TOKEN.startsWith("sk-") || AUTH_TOKEN.length < 20) {
|
|
119
|
+
const error = createError(
|
|
120
|
+
ErrorCodes.AUTH_INVALID,
|
|
121
|
+
`Неверный формат токена. Токен должен начинаться с "sk-" и содержать минимум 20 символов.\n\nПолучен: ${AUTH_TOKEN.substring(0, 10)}...`
|
|
122
|
+
);
|
|
123
|
+
throw new Error(error.message);
|
|
124
|
+
}
|
|
125
|
+
|
|
32
126
|
const url = `${API_BASE_URL}/api${endpoint}`;
|
|
33
127
|
|
|
34
128
|
const headers = {
|
|
35
129
|
"Content-Type": "application/json",
|
|
36
|
-
|
|
130
|
+
"Authorization": `Bearer ${AUTH_TOKEN}`,
|
|
37
131
|
...options.headers,
|
|
38
132
|
};
|
|
39
133
|
|
|
@@ -43,15 +137,67 @@ async function apiRequest(endpoint, options = {}) {
|
|
|
43
137
|
headers,
|
|
44
138
|
});
|
|
45
139
|
|
|
46
|
-
|
|
140
|
+
// Попробуем распарсить JSON
|
|
141
|
+
let data;
|
|
142
|
+
try {
|
|
143
|
+
data = await response.json();
|
|
144
|
+
} catch {
|
|
145
|
+
data = { error: "Invalid JSON response" };
|
|
146
|
+
}
|
|
47
147
|
|
|
48
148
|
if (!response.ok) {
|
|
49
|
-
|
|
149
|
+
// Определяем тип ошибки по статусу
|
|
150
|
+
let errorCode;
|
|
151
|
+
let errorMessage = data.message || data.error || `HTTP ${response.status}`;
|
|
152
|
+
|
|
153
|
+
switch (response.status) {
|
|
154
|
+
case 401:
|
|
155
|
+
errorCode = ErrorCodes.AUTH_INVALID;
|
|
156
|
+
errorMessage = "Токен отклонён сервером. Возможно, он отозван или недействителен.";
|
|
157
|
+
break;
|
|
158
|
+
case 403:
|
|
159
|
+
errorCode = ErrorCodes.AUTH_EXPIRED;
|
|
160
|
+
errorMessage = "Доступ запрещён. Проверьте права токена.";
|
|
161
|
+
break;
|
|
162
|
+
case 404:
|
|
163
|
+
errorCode = ErrorCodes.NOT_FOUND;
|
|
164
|
+
errorMessage = data.message || "Ресурс не найден. Проверьте ID схемы или проекта.";
|
|
165
|
+
break;
|
|
166
|
+
case 422:
|
|
167
|
+
errorCode = ErrorCodes.VALIDATION_ERROR;
|
|
168
|
+
errorMessage = data.message || "Неверный формат данных.";
|
|
169
|
+
if (data.errors) {
|
|
170
|
+
errorMessage += "\n\nДетали:\n" + JSON.stringify(data.errors, null, 2);
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
case 429:
|
|
174
|
+
errorCode = ErrorCodes.RATE_LIMIT;
|
|
175
|
+
errorMessage = "Слишком много запросов.";
|
|
176
|
+
break;
|
|
177
|
+
default:
|
|
178
|
+
errorCode = response.status >= 500 ? ErrorCodes.SERVER_ERROR : ErrorCodes.VALIDATION_ERROR;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const error = createError(errorCode, errorMessage);
|
|
182
|
+
throw new Error(error.message);
|
|
50
183
|
}
|
|
51
184
|
|
|
52
185
|
return data;
|
|
53
186
|
} catch (error) {
|
|
54
|
-
|
|
187
|
+
// Если это уже наша форматированная ошибка — пробрасываем
|
|
188
|
+
if (error.message.includes("🔑") || error.message.includes("🔒") ||
|
|
189
|
+
error.message.includes("🔍") || error.message.includes("⚠️") ||
|
|
190
|
+
error.message.includes("🚫") || error.message.includes("💥") ||
|
|
191
|
+
error.message.includes("🌐") || error.message.includes("⏰")) {
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Ошибка сети
|
|
196
|
+
const networkError = createError(
|
|
197
|
+
ErrorCodes.NETWORK_ERROR,
|
|
198
|
+
`Не удалось подключиться к ${API_BASE_URL}\n\nДетали: ${error.message}`
|
|
199
|
+
);
|
|
200
|
+
throw new Error(networkError.message);
|
|
55
201
|
}
|
|
56
202
|
}
|
|
57
203
|
|
|
@@ -89,14 +235,15 @@ function prepareConnections(connections) {
|
|
|
89
235
|
}
|
|
90
236
|
|
|
91
237
|
/**
|
|
92
|
-
*
|
|
238
|
+
* Инструменты MCP
|
|
93
239
|
*/
|
|
94
240
|
const TOOLS = [
|
|
241
|
+
// ========== СХЕМЫ ==========
|
|
95
242
|
{
|
|
96
243
|
name: "list_schemas",
|
|
97
244
|
description: `Получить список всех схем пользователя.
|
|
98
245
|
|
|
99
|
-
Возвращает: ID, название, описание, дату обновления каждой схемы.
|
|
246
|
+
Возвращает: ID, название, описание, проект, дату обновления каждой схемы.
|
|
100
247
|
|
|
101
248
|
Используй эту команду чтобы узнать какие схемы есть у пользователя.`,
|
|
102
249
|
inputSchema: {
|
|
@@ -132,45 +279,63 @@ const TOOLS = [
|
|
|
132
279
|
name: "create_schema",
|
|
133
280
|
description: `Создать новую схему с элементами и связями.
|
|
134
281
|
|
|
135
|
-
ВАЖНО: Генерируй сразу полную схему с elements и
|
|
282
|
+
ВАЖНО: Генерируй сразу полную схему с elements, connections и tagsDictionary!
|
|
136
283
|
|
|
137
284
|
Параметры:
|
|
138
285
|
- name: название схемы (обязательно)
|
|
139
286
|
- description: описание
|
|
287
|
+
- project_id: ID проекта (опционально)
|
|
140
288
|
- elements: массив элементов
|
|
141
289
|
- connections: массив связей
|
|
290
|
+
- tagsDictionary: справочник тегов (опционально)
|
|
142
291
|
|
|
143
292
|
Формат элемента:
|
|
144
293
|
{
|
|
145
|
-
"id": "
|
|
146
|
-
"type": "
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"color": "#E3F2FD" // цвет фона (опционально)
|
|
294
|
+
"id": "unique_id", // уникальный ID
|
|
295
|
+
"type": "card", // card (карточка) или condition (ромб решения)
|
|
296
|
+
"title": "Название", // заголовок карточки
|
|
297
|
+
"color": "light_blue", // цвет фона: white, light_blue, light_green, light_yellow, light_orange, light_red, light_purple, light_gray, light_pink, light_teal
|
|
298
|
+
"borderColor": "blue", // цвет обводки: default, blue, green, orange, purple, red, teal, yellow, gray, black
|
|
299
|
+
"tags": ["тег1"], // массив названий тегов (опционально)
|
|
300
|
+
"description": "Описание процесса" // подробное описание (опционально)
|
|
153
301
|
}
|
|
154
302
|
|
|
303
|
+
НЕ указывай x, y, width, height - рассчитываются автоматически!
|
|
304
|
+
|
|
155
305
|
Формат связи:
|
|
156
306
|
{
|
|
157
|
-
"from": "
|
|
158
|
-
"to": "
|
|
307
|
+
"from": "source_id", // ID элемента-источника
|
|
308
|
+
"to": "target_id", // ID элемента-назначения
|
|
159
309
|
"label": "подпись", // текст на связи (опционально)
|
|
160
310
|
"style": "solid" // solid, dashed, dotted (опционально)
|
|
161
311
|
}
|
|
162
312
|
|
|
163
|
-
|
|
313
|
+
Формат тега (tagsDictionary):
|
|
164
314
|
{
|
|
165
|
-
"
|
|
315
|
+
"id": "tag-1", // уникальный ID тега
|
|
316
|
+
"name": "система", // название тега (роль/актор)
|
|
317
|
+
"color": "#2196F3" // цвет в HEX
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
Пример: создать схему регистрации:
|
|
321
|
+
{
|
|
322
|
+
"name": "User Registration",
|
|
166
323
|
"elements": [
|
|
167
|
-
{"id": "
|
|
168
|
-
{"id": "
|
|
169
|
-
{"id": "
|
|
324
|
+
{"id": "start", "type": "card", "title": "Форма регистрации", "color": "light_green", "tags": ["пользователь"]},
|
|
325
|
+
{"id": "validate", "type": "condition", "title": "Валидация", "color": "light_yellow", "tags": ["система"]},
|
|
326
|
+
{"id": "save", "type": "card", "title": "Сохранение в БД", "color": "light_blue", "tags": ["система"]},
|
|
327
|
+
{"id": "error", "type": "card", "title": "Ошибка", "color": "light_red", "tags": ["система"]},
|
|
328
|
+
{"id": "success", "type": "card", "title": "Успех", "color": "light_green", "tags": ["пользователь"]}
|
|
170
329
|
],
|
|
171
330
|
"connections": [
|
|
172
|
-
{"from": "
|
|
173
|
-
{"from": "
|
|
331
|
+
{"from": "start", "to": "validate"},
|
|
332
|
+
{"from": "validate", "to": "save", "label": "OK"},
|
|
333
|
+
{"from": "validate", "to": "error", "label": "ошибка"},
|
|
334
|
+
{"from": "save", "to": "success"}
|
|
335
|
+
],
|
|
336
|
+
"tagsDictionary": [
|
|
337
|
+
{"id": "tag-user", "name": "пользователь", "color": "#4CAF50"},
|
|
338
|
+
{"id": "tag-system", "name": "система", "color": "#2196F3"}
|
|
174
339
|
]
|
|
175
340
|
}`,
|
|
176
341
|
inputSchema: {
|
|
@@ -184,6 +349,10 @@ const TOOLS = [
|
|
|
184
349
|
type: "string",
|
|
185
350
|
description: "Описание схемы",
|
|
186
351
|
},
|
|
352
|
+
project_id: {
|
|
353
|
+
type: "string",
|
|
354
|
+
description: "ID проекта для размещения схемы (опционально)",
|
|
355
|
+
},
|
|
187
356
|
elements: {
|
|
188
357
|
type: "array",
|
|
189
358
|
description: "Массив элементов схемы",
|
|
@@ -191,13 +360,12 @@ const TOOLS = [
|
|
|
191
360
|
type: "object",
|
|
192
361
|
properties: {
|
|
193
362
|
id: { type: "string" },
|
|
194
|
-
type: { type: "string", enum: ["
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
color: { type: "string" },
|
|
363
|
+
type: { type: "string", enum: ["card", "condition"] },
|
|
364
|
+
title: { type: "string" },
|
|
365
|
+
color: { type: "string", enum: ["white", "light_blue", "light_green", "light_yellow", "light_orange", "light_red", "light_purple", "light_gray", "light_pink", "light_teal"] },
|
|
366
|
+
borderColor: { type: "string", enum: ["default", "blue", "green", "orange", "purple", "red", "teal", "yellow", "gray", "black"] },
|
|
367
|
+
tags: { type: "array", items: { type: "string" } },
|
|
368
|
+
description: { type: "string" },
|
|
201
369
|
},
|
|
202
370
|
},
|
|
203
371
|
},
|
|
@@ -215,6 +383,18 @@ const TOOLS = [
|
|
|
215
383
|
required: ["from", "to"],
|
|
216
384
|
},
|
|
217
385
|
},
|
|
386
|
+
tagsDictionary: {
|
|
387
|
+
type: "array",
|
|
388
|
+
description: "Справочник тегов схемы",
|
|
389
|
+
items: {
|
|
390
|
+
type: "object",
|
|
391
|
+
properties: {
|
|
392
|
+
id: { type: "string" },
|
|
393
|
+
name: { type: "string" },
|
|
394
|
+
color: { type: "string" },
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
},
|
|
218
398
|
},
|
|
219
399
|
required: ["name"],
|
|
220
400
|
},
|
|
@@ -285,14 +465,319 @@ const TOOLS = [
|
|
|
285
465
|
required: ["schema_id"],
|
|
286
466
|
},
|
|
287
467
|
},
|
|
468
|
+
|
|
469
|
+
// ========== ПРОЕКТЫ ==========
|
|
470
|
+
{
|
|
471
|
+
name: "list_projects",
|
|
472
|
+
description: `Получить список всех проектов пользователя.
|
|
473
|
+
|
|
474
|
+
Проекты - это папки для группировки схем.
|
|
475
|
+
Возвращает: ID, название, описание, цвет, иконку и количество схем в каждом проекте.`,
|
|
476
|
+
inputSchema: {
|
|
477
|
+
type: "object",
|
|
478
|
+
properties: {},
|
|
479
|
+
required: [],
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: "create_project",
|
|
484
|
+
description: `Создать новый проект (папку для схем).
|
|
485
|
+
|
|
486
|
+
Параметры:
|
|
487
|
+
- name: название проекта (обязательно)
|
|
488
|
+
- description: описание проекта
|
|
489
|
+
- color: цвет в формате HEX (например #FF5733)
|
|
490
|
+
- icon: emoji иконка (например 📁, 🚀, 💡)`,
|
|
491
|
+
inputSchema: {
|
|
492
|
+
type: "object",
|
|
493
|
+
properties: {
|
|
494
|
+
name: {
|
|
495
|
+
type: "string",
|
|
496
|
+
description: "Название проекта",
|
|
497
|
+
},
|
|
498
|
+
description: {
|
|
499
|
+
type: "string",
|
|
500
|
+
description: "Описание проекта",
|
|
501
|
+
},
|
|
502
|
+
color: {
|
|
503
|
+
type: "string",
|
|
504
|
+
description: "Цвет проекта в формате HEX",
|
|
505
|
+
},
|
|
506
|
+
icon: {
|
|
507
|
+
type: "string",
|
|
508
|
+
description: "Emoji иконка проекта",
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
required: ["name"],
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: "delete_project",
|
|
516
|
+
description: `Удалить проект.
|
|
517
|
+
|
|
518
|
+
ВАЖНО: Схемы внутри проекта НЕ удаляются - они перемещаются в раздел "Общие".`,
|
|
519
|
+
inputSchema: {
|
|
520
|
+
type: "object",
|
|
521
|
+
properties: {
|
|
522
|
+
project_id: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "ID проекта для удаления",
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
required: ["project_id"],
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "move_schema_to_project",
|
|
532
|
+
description: `Переместить схему в проект или убрать из проекта.
|
|
533
|
+
|
|
534
|
+
Параметры:
|
|
535
|
+
- schema_id: ID схемы (обязательно)
|
|
536
|
+
- project_id: ID проекта. Если не указан или null - схема перемещается в "Общие" (без проекта)`,
|
|
537
|
+
inputSchema: {
|
|
538
|
+
type: "object",
|
|
539
|
+
properties: {
|
|
540
|
+
schema_id: {
|
|
541
|
+
type: "string",
|
|
542
|
+
description: "ID схемы",
|
|
543
|
+
},
|
|
544
|
+
project_id: {
|
|
545
|
+
type: "string",
|
|
546
|
+
description: "ID проекта (или null для перемещения в Общие)",
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
required: ["schema_id"],
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
name: "update_project",
|
|
554
|
+
description: `Обновить проект - изменить название, описание, цвет или иконку.
|
|
555
|
+
|
|
556
|
+
Параметры:
|
|
557
|
+
- project_id: ID проекта (обязательно)
|
|
558
|
+
- name: новое название
|
|
559
|
+
- description: новое описание
|
|
560
|
+
- color: новый цвет в формате HEX
|
|
561
|
+
- icon: новая emoji иконка`,
|
|
562
|
+
inputSchema: {
|
|
563
|
+
type: "object",
|
|
564
|
+
properties: {
|
|
565
|
+
project_id: {
|
|
566
|
+
type: "string",
|
|
567
|
+
description: "ID проекта",
|
|
568
|
+
},
|
|
569
|
+
name: {
|
|
570
|
+
type: "string",
|
|
571
|
+
description: "Новое название проекта",
|
|
572
|
+
},
|
|
573
|
+
description: {
|
|
574
|
+
type: "string",
|
|
575
|
+
description: "Новое описание проекта",
|
|
576
|
+
},
|
|
577
|
+
color: {
|
|
578
|
+
type: "string",
|
|
579
|
+
description: "Новый цвет проекта в формате HEX",
|
|
580
|
+
},
|
|
581
|
+
icon: {
|
|
582
|
+
type: "string",
|
|
583
|
+
description: "Новая emoji иконка проекта",
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
required: ["project_id"],
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
// ========== ТЕГИ ==========
|
|
591
|
+
{
|
|
592
|
+
name: "add_tag",
|
|
593
|
+
description: `Добавить новый тег в схему.
|
|
594
|
+
|
|
595
|
+
Теги используются для категоризации элементов схемы.
|
|
596
|
+
|
|
597
|
+
Параметры:
|
|
598
|
+
- schema_id: ID схемы (обязательно)
|
|
599
|
+
- name: название тега (обязательно)
|
|
600
|
+
- color: цвет тега в формате HEX (например #4CAF50)`,
|
|
601
|
+
inputSchema: {
|
|
602
|
+
type: "object",
|
|
603
|
+
properties: {
|
|
604
|
+
schema_id: {
|
|
605
|
+
type: "string",
|
|
606
|
+
description: "ID схемы",
|
|
607
|
+
},
|
|
608
|
+
name: {
|
|
609
|
+
type: "string",
|
|
610
|
+
description: "Название тега",
|
|
611
|
+
},
|
|
612
|
+
color: {
|
|
613
|
+
type: "string",
|
|
614
|
+
description: "Цвет тега в формате HEX",
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
required: ["schema_id", "name"],
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
name: "remove_tag",
|
|
622
|
+
description: `Удалить тег из схемы.
|
|
623
|
+
|
|
624
|
+
Тег будет удалён из tagsDictionary и убран со всех элементов.
|
|
625
|
+
|
|
626
|
+
Параметры:
|
|
627
|
+
- schema_id: ID схемы (обязательно)
|
|
628
|
+
- tag_id: ID тега для удаления (обязательно)`,
|
|
629
|
+
inputSchema: {
|
|
630
|
+
type: "object",
|
|
631
|
+
properties: {
|
|
632
|
+
schema_id: {
|
|
633
|
+
type: "string",
|
|
634
|
+
description: "ID схемы",
|
|
635
|
+
},
|
|
636
|
+
tag_id: {
|
|
637
|
+
type: "string",
|
|
638
|
+
description: "ID тега для удаления",
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
required: ["schema_id", "tag_id"],
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
name: "tag_element",
|
|
646
|
+
description: `Присвоить или убрать тег с элемента.
|
|
647
|
+
|
|
648
|
+
Параметры:
|
|
649
|
+
- schema_id: ID схемы (обязательно)
|
|
650
|
+
- element_id: ID элемента (обязательно)
|
|
651
|
+
- tag_id: ID тега (обязательно)
|
|
652
|
+
- action: "add" или "remove" (по умолчанию "add")`,
|
|
653
|
+
inputSchema: {
|
|
654
|
+
type: "object",
|
|
655
|
+
properties: {
|
|
656
|
+
schema_id: {
|
|
657
|
+
type: "string",
|
|
658
|
+
description: "ID схемы",
|
|
659
|
+
},
|
|
660
|
+
element_id: {
|
|
661
|
+
type: "string",
|
|
662
|
+
description: "ID элемента",
|
|
663
|
+
},
|
|
664
|
+
tag_id: {
|
|
665
|
+
type: "string",
|
|
666
|
+
description: "ID тега",
|
|
667
|
+
},
|
|
668
|
+
action: {
|
|
669
|
+
type: "string",
|
|
670
|
+
enum: ["add", "remove"],
|
|
671
|
+
description: "Действие: add (добавить) или remove (убрать)",
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
required: ["schema_id", "element_id", "tag_id"],
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
name: "list_tags",
|
|
679
|
+
description: `Получить список всех тегов схемы.
|
|
680
|
+
|
|
681
|
+
Параметры:
|
|
682
|
+
- schema_id: ID схемы (обязательно)`,
|
|
683
|
+
inputSchema: {
|
|
684
|
+
type: "object",
|
|
685
|
+
properties: {
|
|
686
|
+
schema_id: {
|
|
687
|
+
type: "string",
|
|
688
|
+
description: "ID схемы",
|
|
689
|
+
},
|
|
690
|
+
},
|
|
691
|
+
required: ["schema_id"],
|
|
692
|
+
},
|
|
693
|
+
},
|
|
288
694
|
];
|
|
289
695
|
|
|
696
|
+
/**
|
|
697
|
+
* Валидация UUID формата
|
|
698
|
+
*/
|
|
699
|
+
function isValidUUID(str) {
|
|
700
|
+
if (!str || typeof str !== "string") return false;
|
|
701
|
+
// Принимаем разные форматы ID: UUID и cuid
|
|
702
|
+
return /^[a-zA-Z0-9_-]{10,}$/.test(str);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Валидация параметров команды
|
|
707
|
+
*/
|
|
708
|
+
function validateArgs(name, args) {
|
|
709
|
+
const errors = [];
|
|
710
|
+
|
|
711
|
+
// Валидация schema_id
|
|
712
|
+
if (["get_schema", "replace_schema", "delete_schema", "add_tag", "remove_tag", "tag_element", "list_tags"].includes(name)) {
|
|
713
|
+
if (!args.schema_id) {
|
|
714
|
+
errors.push("schema_id — обязательный параметр");
|
|
715
|
+
} else if (!isValidUUID(args.schema_id)) {
|
|
716
|
+
errors.push(`schema_id "${args.schema_id}" — неверный формат. Используйте ID из list_schemas`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Валидация project_id
|
|
721
|
+
if (["delete_project", "update_project"].includes(name)) {
|
|
722
|
+
if (!args.project_id) {
|
|
723
|
+
errors.push("project_id — обязательный параметр");
|
|
724
|
+
} else if (!isValidUUID(args.project_id)) {
|
|
725
|
+
errors.push(`project_id "${args.project_id}" — неверный формат. Используйте ID из list_projects`);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Валидация name для создания
|
|
730
|
+
if (["create_schema", "create_project"].includes(name)) {
|
|
731
|
+
if (!args.name || typeof args.name !== "string" || args.name.trim().length === 0) {
|
|
732
|
+
errors.push("name — обязательный параметр (название)");
|
|
733
|
+
} else if (args.name.length > 100) {
|
|
734
|
+
errors.push("name — слишком длинное название (макс. 100 символов)");
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Валидация тегов
|
|
739
|
+
if (name === "add_tag") {
|
|
740
|
+
if (!args.name || typeof args.name !== "string") {
|
|
741
|
+
errors.push("name — обязательный параметр (название тега)");
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (name === "remove_tag" || name === "tag_element") {
|
|
746
|
+
if (!args.tag_id) {
|
|
747
|
+
errors.push("tag_id — обязательный параметр");
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
if (name === "tag_element") {
|
|
752
|
+
if (!args.element_id) {
|
|
753
|
+
errors.push("element_id — обязательный параметр");
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Валидация цвета
|
|
758
|
+
if (args.color && !/^#[0-9A-Fa-f]{6}$/.test(args.color)) {
|
|
759
|
+
errors.push(`color "${args.color}" — неверный формат. Используйте HEX: #RRGGBB (например #4CAF50)`);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
return errors;
|
|
763
|
+
}
|
|
764
|
+
|
|
290
765
|
/**
|
|
291
766
|
* Обработчики инструментов
|
|
292
767
|
*/
|
|
293
768
|
async function handleTool(name, args) {
|
|
769
|
+
// Валидация параметров
|
|
770
|
+
const validationErrors = validateArgs(name, args);
|
|
771
|
+
if (validationErrors.length > 0) {
|
|
772
|
+
const error = createError(
|
|
773
|
+
ErrorCodes.VALIDATION_ERROR,
|
|
774
|
+
`Ошибки в параметрах:\n\n• ${validationErrors.join("\n• ")}`
|
|
775
|
+
);
|
|
776
|
+
throw new Error(error.message);
|
|
777
|
+
}
|
|
778
|
+
|
|
294
779
|
switch (name) {
|
|
295
|
-
// ==========
|
|
780
|
+
// ========== СХЕМЫ ==========
|
|
296
781
|
case "list_schemas": {
|
|
297
782
|
const result = await apiRequest("/schemas");
|
|
298
783
|
|
|
@@ -309,6 +794,8 @@ async function handleTool(name, args) {
|
|
|
309
794
|
id: s.id,
|
|
310
795
|
name: s.name,
|
|
311
796
|
description: s.description || "",
|
|
797
|
+
projectId: s.projectId || null,
|
|
798
|
+
projectName: s.project?.name || "Общие",
|
|
312
799
|
updatedAt: s.updatedAt,
|
|
313
800
|
elementsCount: s.data?.elements?.length || 0,
|
|
314
801
|
connectionsCount: s.data?.connections?.length || 0,
|
|
@@ -322,7 +809,6 @@ async function handleTool(name, args) {
|
|
|
322
809
|
};
|
|
323
810
|
}
|
|
324
811
|
|
|
325
|
-
// ========== GET SCHEMA ==========
|
|
326
812
|
case "get_schema": {
|
|
327
813
|
const { schema_id } = args;
|
|
328
814
|
const result = await apiRequest(`/schemas/${schema_id}`);
|
|
@@ -336,6 +822,7 @@ async function handleTool(name, args) {
|
|
|
336
822
|
|
|
337
823
|
ID: ${schema.id}
|
|
338
824
|
Описание: ${schema.description || "(нет)"}
|
|
825
|
+
Проект: ${schema.project?.name || "Общие"}
|
|
339
826
|
Элементов: ${schema.data?.elements?.length || 0}
|
|
340
827
|
Связей: ${schema.data?.connections?.length || 0}
|
|
341
828
|
URL: ${API_BASE_URL}/canvas?id=${schema.id}
|
|
@@ -349,9 +836,8 @@ ${JSON.stringify(schema.data?.connections || [], null, 2)}`,
|
|
|
349
836
|
};
|
|
350
837
|
}
|
|
351
838
|
|
|
352
|
-
// ========== CREATE SCHEMA ==========
|
|
353
839
|
case "create_schema": {
|
|
354
|
-
const { name, description, elements, connections } = args;
|
|
840
|
+
const { name, description, project_id, elements, connections } = args;
|
|
355
841
|
|
|
356
842
|
const data = {
|
|
357
843
|
elements: prepareElements(elements),
|
|
@@ -361,15 +847,18 @@ ${JSON.stringify(schema.data?.connections || [], null, 2)}`,
|
|
|
361
847
|
|
|
362
848
|
const result = await apiRequest("/schemas", {
|
|
363
849
|
method: "POST",
|
|
364
|
-
body: JSON.stringify({ name, description, data }),
|
|
850
|
+
body: JSON.stringify({ name, description, data, projectId: project_id }),
|
|
365
851
|
});
|
|
366
852
|
|
|
853
|
+
const projectInfo = project_id ? `Проект: ${project_id}` : 'Проект: Общие';
|
|
854
|
+
|
|
367
855
|
return {
|
|
368
856
|
content: [{
|
|
369
857
|
type: "text",
|
|
370
858
|
text: `Схема "${result.schema.name}" создана!
|
|
371
859
|
|
|
372
860
|
ID: ${result.schema.id}
|
|
861
|
+
${projectInfo}
|
|
373
862
|
Элементов: ${data.elements.length}
|
|
374
863
|
Связей: ${data.connections.length}
|
|
375
864
|
|
|
@@ -380,7 +869,6 @@ URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
|
|
|
380
869
|
};
|
|
381
870
|
}
|
|
382
871
|
|
|
383
|
-
// ========== REPLACE SCHEMA ==========
|
|
384
872
|
case "replace_schema": {
|
|
385
873
|
const { schema_id, name, description, elements, connections } = args;
|
|
386
874
|
|
|
@@ -423,7 +911,6 @@ URL: ${API_BASE_URL}/canvas?id=${schema_id}`,
|
|
|
423
911
|
};
|
|
424
912
|
}
|
|
425
913
|
|
|
426
|
-
// ========== DELETE SCHEMA ==========
|
|
427
914
|
case "delete_schema": {
|
|
428
915
|
const { schema_id } = args;
|
|
429
916
|
|
|
@@ -439,6 +926,253 @@ URL: ${API_BASE_URL}/canvas?id=${schema_id}`,
|
|
|
439
926
|
};
|
|
440
927
|
}
|
|
441
928
|
|
|
929
|
+
// ========== ПРОЕКТЫ ==========
|
|
930
|
+
case "list_projects": {
|
|
931
|
+
const result = await apiRequest("/projects");
|
|
932
|
+
|
|
933
|
+
if (!result.projects || result.projects.length === 0) {
|
|
934
|
+
return {
|
|
935
|
+
content: [{
|
|
936
|
+
type: "text",
|
|
937
|
+
text: `Проектов пока нет. Все схемы находятся в разделе "Общие" (${result.unassignedCount || 0} схем).\n\nСоздай проект с помощью create_project.`,
|
|
938
|
+
}],
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const projectsList = result.projects.map(p => ({
|
|
943
|
+
id: p.id,
|
|
944
|
+
name: p.name,
|
|
945
|
+
description: p.description || "",
|
|
946
|
+
color: p.color,
|
|
947
|
+
icon: p.icon,
|
|
948
|
+
schemasCount: p.schemasCount || 0,
|
|
949
|
+
}));
|
|
950
|
+
|
|
951
|
+
return {
|
|
952
|
+
content: [{
|
|
953
|
+
type: "text",
|
|
954
|
+
text: `Найдено ${result.projects.length} проектов:\n\n${JSON.stringify(projectsList, null, 2)}\n\nСхем без проекта ("Общие"): ${result.unassignedCount || 0}`,
|
|
955
|
+
}],
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
case "create_project": {
|
|
960
|
+
const { name, description, color, icon } = args;
|
|
961
|
+
|
|
962
|
+
const result = await apiRequest("/projects", {
|
|
963
|
+
method: "POST",
|
|
964
|
+
body: JSON.stringify({ name, description, color, icon }),
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
return {
|
|
968
|
+
content: [{
|
|
969
|
+
type: "text",
|
|
970
|
+
text: `Проект "${result.project.name}" создан!\n\nID: ${result.project.id}`,
|
|
971
|
+
}],
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
case "delete_project": {
|
|
976
|
+
const { project_id } = args;
|
|
977
|
+
|
|
978
|
+
const result = await apiRequest(`/projects/${project_id}`, {
|
|
979
|
+
method: "DELETE",
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
return {
|
|
983
|
+
content: [{
|
|
984
|
+
type: "text",
|
|
985
|
+
text: result.message || "Проект удалён. Схемы перемещены в 'Общие'.",
|
|
986
|
+
}],
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
case "move_schema_to_project": {
|
|
991
|
+
const { schema_id, project_id } = args;
|
|
992
|
+
|
|
993
|
+
if (project_id) {
|
|
994
|
+
// Переместить в проект
|
|
995
|
+
const result = await apiRequest(`/projects/${project_id}/schemas/${schema_id}`, {
|
|
996
|
+
method: "PUT",
|
|
997
|
+
});
|
|
998
|
+
return {
|
|
999
|
+
content: [{
|
|
1000
|
+
type: "text",
|
|
1001
|
+
text: result.message || "Схема перемещена в проект.",
|
|
1002
|
+
}],
|
|
1003
|
+
};
|
|
1004
|
+
} else {
|
|
1005
|
+
// Убрать из проекта (в "Общие")
|
|
1006
|
+
const result = await apiRequest(`/projects/null/schemas/${schema_id}`, {
|
|
1007
|
+
method: "DELETE",
|
|
1008
|
+
});
|
|
1009
|
+
return {
|
|
1010
|
+
content: [{
|
|
1011
|
+
type: "text",
|
|
1012
|
+
text: result.message || "Схема перемещена в 'Общие'.",
|
|
1013
|
+
}],
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
case "update_project": {
|
|
1019
|
+
const { project_id, name, description, color, icon } = args;
|
|
1020
|
+
|
|
1021
|
+
const updateBody = {};
|
|
1022
|
+
if (name !== undefined) updateBody.name = name;
|
|
1023
|
+
if (description !== undefined) updateBody.description = description;
|
|
1024
|
+
if (color !== undefined) updateBody.color = color;
|
|
1025
|
+
if (icon !== undefined) updateBody.icon = icon;
|
|
1026
|
+
|
|
1027
|
+
const result = await apiRequest(`/projects/${project_id}`, {
|
|
1028
|
+
method: "PUT",
|
|
1029
|
+
body: JSON.stringify(updateBody),
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
return {
|
|
1033
|
+
content: [{
|
|
1034
|
+
type: "text",
|
|
1035
|
+
text: `Проект "${result.project.name}" обновлён!\n\nID: ${result.project.id}`,
|
|
1036
|
+
}],
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// ========== ТЕГИ ==========
|
|
1041
|
+
case "add_tag": {
|
|
1042
|
+
const { schema_id, name, color } = args;
|
|
1043
|
+
|
|
1044
|
+
// Получаем текущую схему
|
|
1045
|
+
const currentResult = await apiRequest(`/schemas/${schema_id}`);
|
|
1046
|
+
const currentData = currentResult.schema.data || { elements: [], connections: [], tagsDictionary: [] };
|
|
1047
|
+
|
|
1048
|
+
// Создаём новый тег
|
|
1049
|
+
const newTag = {
|
|
1050
|
+
id: generateId(),
|
|
1051
|
+
name: name,
|
|
1052
|
+
color: color || "#9E9E9E",
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
// Добавляем тег в tagsDictionary
|
|
1056
|
+
const tagsDictionary = currentData.tagsDictionary || [];
|
|
1057
|
+
tagsDictionary.push(newTag);
|
|
1058
|
+
|
|
1059
|
+
// Обновляем схему
|
|
1060
|
+
await apiRequest(`/schemas/${schema_id}`, {
|
|
1061
|
+
method: "PUT",
|
|
1062
|
+
body: JSON.stringify({
|
|
1063
|
+
data: { ...currentData, tagsDictionary },
|
|
1064
|
+
}),
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
return {
|
|
1068
|
+
content: [{
|
|
1069
|
+
type: "text",
|
|
1070
|
+
text: `Тег "${name}" добавлен!\n\nID: ${newTag.id}\nЦвет: ${newTag.color}`,
|
|
1071
|
+
}],
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
case "remove_tag": {
|
|
1076
|
+
const { schema_id, tag_id } = args;
|
|
1077
|
+
|
|
1078
|
+
// Получаем текущую схему
|
|
1079
|
+
const currentResult = await apiRequest(`/schemas/${schema_id}`);
|
|
1080
|
+
const currentData = currentResult.schema.data || { elements: [], connections: [], tagsDictionary: [] };
|
|
1081
|
+
|
|
1082
|
+
// Удаляем тег из tagsDictionary
|
|
1083
|
+
const tagsDictionary = (currentData.tagsDictionary || []).filter(t => t.id !== tag_id);
|
|
1084
|
+
|
|
1085
|
+
// Удаляем тег со всех элементов
|
|
1086
|
+
const elements = (currentData.elements || []).map(el => {
|
|
1087
|
+
if (el.tags && Array.isArray(el.tags)) {
|
|
1088
|
+
el.tags = el.tags.filter(t => t !== tag_id);
|
|
1089
|
+
}
|
|
1090
|
+
return el;
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
// Обновляем схему
|
|
1094
|
+
await apiRequest(`/schemas/${schema_id}`, {
|
|
1095
|
+
method: "PUT",
|
|
1096
|
+
body: JSON.stringify({
|
|
1097
|
+
data: { ...currentData, tagsDictionary, elements },
|
|
1098
|
+
}),
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
return {
|
|
1102
|
+
content: [{
|
|
1103
|
+
type: "text",
|
|
1104
|
+
text: `Тег удалён из схемы и со всех элементов.`,
|
|
1105
|
+
}],
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
case "tag_element": {
|
|
1110
|
+
const { schema_id, element_id, tag_id, action = "add" } = args;
|
|
1111
|
+
|
|
1112
|
+
// Получаем текущую схему
|
|
1113
|
+
const currentResult = await apiRequest(`/schemas/${schema_id}`);
|
|
1114
|
+
const currentData = currentResult.schema.data || { elements: [], connections: [], tagsDictionary: [] };
|
|
1115
|
+
|
|
1116
|
+
// Находим элемент и обновляем его теги
|
|
1117
|
+
const elements = (currentData.elements || []).map(el => {
|
|
1118
|
+
if (el.id === element_id) {
|
|
1119
|
+
const tags = el.tags || [];
|
|
1120
|
+
if (action === "add") {
|
|
1121
|
+
if (!tags.includes(tag_id)) {
|
|
1122
|
+
tags.push(tag_id);
|
|
1123
|
+
}
|
|
1124
|
+
} else if (action === "remove") {
|
|
1125
|
+
const index = tags.indexOf(tag_id);
|
|
1126
|
+
if (index > -1) {
|
|
1127
|
+
tags.splice(index, 1);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
el.tags = tags;
|
|
1131
|
+
}
|
|
1132
|
+
return el;
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
// Обновляем схему
|
|
1136
|
+
await apiRequest(`/schemas/${schema_id}`, {
|
|
1137
|
+
method: "PUT",
|
|
1138
|
+
body: JSON.stringify({
|
|
1139
|
+
data: { ...currentData, elements },
|
|
1140
|
+
}),
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
const actionText = action === "add" ? "добавлен к" : "убран с";
|
|
1144
|
+
return {
|
|
1145
|
+
content: [{
|
|
1146
|
+
type: "text",
|
|
1147
|
+
text: `Тег ${actionText} элемента ${element_id}.`,
|
|
1148
|
+
}],
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
case "list_tags": {
|
|
1153
|
+
const { schema_id } = args;
|
|
1154
|
+
|
|
1155
|
+
// Получаем схему
|
|
1156
|
+
const result = await apiRequest(`/schemas/${schema_id}`);
|
|
1157
|
+
const tagsDictionary = result.schema.data?.tagsDictionary || [];
|
|
1158
|
+
|
|
1159
|
+
if (tagsDictionary.length === 0) {
|
|
1160
|
+
return {
|
|
1161
|
+
content: [{
|
|
1162
|
+
type: "text",
|
|
1163
|
+
text: "В схеме нет тегов.\n\nДобавь тег с помощью add_tag.",
|
|
1164
|
+
}],
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
return {
|
|
1169
|
+
content: [{
|
|
1170
|
+
type: "text",
|
|
1171
|
+
text: `Теги схемы (${tagsDictionary.length}):\n\n${JSON.stringify(tagsDictionary, null, 2)}`,
|
|
1172
|
+
}],
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
|
|
442
1176
|
default:
|
|
443
1177
|
throw new Error(`Неизвестная команда: ${name}`);
|
|
444
1178
|
}
|
|
@@ -449,13 +1183,35 @@ URL: ${API_BASE_URL}/canvas?id=${schema_id}`,
|
|
|
449
1183
|
*/
|
|
450
1184
|
async function main() {
|
|
451
1185
|
if (!AUTH_TOKEN) {
|
|
452
|
-
console.error(
|
|
1186
|
+
console.error(`
|
|
1187
|
+
⚠️ SCHEMEOG_TOKEN не установлен!
|
|
1188
|
+
|
|
1189
|
+
Для работы MCP сервера необходим API токен.
|
|
1190
|
+
|
|
1191
|
+
1. Получите токен: ${PROFILE_URL}
|
|
1192
|
+
2. Добавьте в настройки MCP:
|
|
1193
|
+
|
|
1194
|
+
"env": {
|
|
1195
|
+
"SCHEMEOG_TOKEN": "sk-ваш-токен"
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
Документация: ${DOCS_URL}
|
|
1199
|
+
`);
|
|
1200
|
+
} else if (!AUTH_TOKEN.startsWith("sk-")) {
|
|
1201
|
+
console.error(`
|
|
1202
|
+
⚠️ Неверный формат токена!
|
|
1203
|
+
|
|
1204
|
+
Токен должен начинаться с "sk-".
|
|
1205
|
+
Получен: ${AUTH_TOKEN.substring(0, 10)}...
|
|
1206
|
+
|
|
1207
|
+
Создайте новый токен: ${PROFILE_URL}
|
|
1208
|
+
`);
|
|
453
1209
|
}
|
|
454
1210
|
|
|
455
1211
|
const server = new Server(
|
|
456
1212
|
{
|
|
457
1213
|
name: "schemeog-mcp",
|
|
458
|
-
version: "2.
|
|
1214
|
+
version: "2.1.0",
|
|
459
1215
|
},
|
|
460
1216
|
{
|
|
461
1217
|
capabilities: {
|
|
@@ -485,7 +1241,7 @@ async function main() {
|
|
|
485
1241
|
const transport = new StdioServerTransport();
|
|
486
1242
|
await server.connect(transport);
|
|
487
1243
|
|
|
488
|
-
console.error("SchemeOG MCP Server v2.
|
|
1244
|
+
console.error("SchemeOG MCP Server v2.1 запущен");
|
|
489
1245
|
}
|
|
490
1246
|
|
|
491
1247
|
main().catch(console.error);
|