schemeog-mcp 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +106 -151
  2. package/index.js +255 -28
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,58 +1,58 @@
1
- # SchemeOG MCP Server v2.1
1
+ # SchemeOG MCP Server v2.2
2
2
 
3
- MCP сервер для [SchemeOG Cloud](https://scheme.smartlaunchhub.com) — создавай диаграммы и схемы с помощью AI.
3
+ MCP server for [SchemeOG Cloud](https://scheme.smartlaunchhub.com) — create diagrams and flowcharts with AI.
4
4
 
5
- ## 14 команд для полного контроля
5
+ ## 14 Commands
6
6
 
7
- ### Схемы (5 команд)
7
+ ### Schemas (5 commands)
8
8
 
9
- | Команда | Описание |
10
- |---------|----------|
11
- | `list_schemas` | Список всех схем |
12
- | `get_schema` | Получить схему с данными |
13
- | `create_schema` | Создать новую схему |
14
- | `replace_schema` | Заменить содержимое схемы |
15
- | `delete_schema` | Удалить схему |
9
+ | Command | Description |
10
+ |---------|-------------|
11
+ | `list_schemas` | List all schemas |
12
+ | `get_schema` | Get schema with data |
13
+ | `create_schema` | Create new schema |
14
+ | `replace_schema` | Replace schema content |
15
+ | `delete_schema` | Delete schema |
16
16
 
17
- ### Проекты (5 команд)
17
+ ### Projects (5 commands)
18
18
 
19
- | Команда | Описание |
20
- |---------|----------|
21
- | `list_projects` | Список проектов (папок) |
22
- | `create_project` | Создать проект |
23
- | `update_project` | Обновить проект |
24
- | `delete_project` | Удалить проект |
25
- | `move_schema_to_project` | Переместить схему в проект |
19
+ | Command | Description |
20
+ |---------|-------------|
21
+ | `list_projects` | List projects (folders) |
22
+ | `create_project` | Create project |
23
+ | `update_project` | Update project |
24
+ | `delete_project` | Delete project |
25
+ | `move_schema_to_project` | Move schema to project |
26
26
 
27
- ### Теги (4 команды)
27
+ ### Tags (4 commands)
28
28
 
29
- | Команда | Описание |
30
- |---------|----------|
31
- | `list_tags` | Список тегов схемы |
32
- | `add_tag` | Добавить тег в схему |
33
- | `remove_tag` | Удалить тег из схемы |
34
- | `tag_element` | Присвоить/убрать тег с элемента |
29
+ | Command | Description |
30
+ |---------|-------------|
31
+ | `list_tags` | List schema tags |
32
+ | `add_tag` | Add tag to schema |
33
+ | `remove_tag` | Remove tag from schema |
34
+ | `tag_element` | Assign/remove tag from element |
35
35
 
36
- ## Установка
36
+ ## Installation
37
37
 
38
- ### Через npx (рекомендуется)
38
+ ### Via npx (recommended)
39
39
 
40
40
  ```bash
41
41
  npx schemeog-mcp
42
42
  ```
43
43
 
44
- ## Настройка
44
+ ## Setup
45
45
 
46
- ### 1. Получи токен
46
+ ### 1. Get your token
47
47
 
48
- 1. Открой https://scheme.smartlaunchhub.com
49
- 2. Войди по email
50
- 3. Перейди в Профиль
51
- 4. Скопируй токен из секции "Claude Code Integration"
48
+ 1. Open https://scheme.smartlaunchhub.com
49
+ 2. Sign in with email
50
+ 3. Go to Profile
51
+ 4. Copy token from "Claude Code Integration" section
52
52
 
53
- ### 2. Добавь в Claude Code / Cline
53
+ ### 2. Add to Claude Code / Cline
54
54
 
55
- В `~/.claude.json` (или настройки Cline):
55
+ In `~/.claude.json` (or Cline settings):
56
56
 
57
57
  ```json
58
58
  {
@@ -68,199 +68,154 @@ npx schemeog-mcp
68
68
  }
69
69
  ```
70
70
 
71
- ## Формат данных схемы
71
+ ## Schema Data Format
72
72
 
73
- ### Полный пример схемы
73
+ ### Full schema example
74
74
 
75
75
  ```json
76
76
  {
77
77
  "name": "User Registration Flow",
78
- "description": "Процесс регистрации пользователя",
78
+ "description": "User registration process",
79
79
  "elements": [
80
80
  {
81
81
  "id": "start",
82
82
  "type": "card",
83
- "title": "Форма регистрации",
83
+ "title": "Registration Form",
84
84
  "color": "light_green",
85
- "borderColor": "green",
86
- "tags": ["пользователь"],
87
- "description": "Пользователь заполняет форму с email и паролем"
85
+ "tags": ["user"],
86
+ "description": "User fills in email and password"
88
87
  },
89
88
  {
90
89
  "id": "validate",
91
90
  "type": "condition",
92
- "title": "Валидация данных",
91
+ "title": "Validate Data",
93
92
  "color": "light_yellow",
94
- "borderColor": "yellow",
95
- "tags": ["система", "проверка"],
96
- "description": "Проверка корректности email и сложности пароля"
93
+ "tags": ["system", "check"],
94
+ "description": "Check email format and password strength"
97
95
  },
98
96
  {
99
97
  "id": "save",
100
98
  "type": "card",
101
- "title": "Сохранение в БД",
99
+ "title": "Save to Database",
102
100
  "color": "light_blue",
103
- "borderColor": "blue",
104
- "tags": ["система"],
105
- "description": "Создание записи пользователя в базе данных"
101
+ "tags": ["system"],
102
+ "description": "Create user record in database"
106
103
  },
107
104
  {
108
105
  "id": "error",
109
106
  "type": "card",
110
- "title": "Ошибка валидации",
107
+ "title": "Validation Error",
111
108
  "color": "light_red",
112
- "borderColor": "red",
113
- "tags": ["система", "ошибка"],
114
- "description": "Показать пользователю ошибки валидации"
109
+ "tags": ["system", "error"],
110
+ "description": "Show validation errors to user"
115
111
  },
116
112
  {
117
113
  "id": "success",
118
114
  "type": "card",
119
- "title": "Успешная регистрация",
115
+ "title": "Registration Complete",
120
116
  "color": "light_green",
121
- "borderColor": "green",
122
- "tags": ["пользователь"],
123
- "description": "Пользователь успешно зарегистрирован"
117
+ "tags": ["user"],
118
+ "description": "User successfully registered"
124
119
  }
125
120
  ],
126
121
  "connections": [
127
- {"from": "start", "to": "validate", "label": "отправка формы"},
128
- {"from": "validate", "to": "save", "label": "данные корректны"},
129
- {"from": "validate", "to": "error", "label": "ошибка"},
122
+ {"from": "start", "to": "validate", "label": "submit"},
123
+ {"from": "validate", "to": "save", "label": "valid"},
124
+ {"from": "validate", "to": "error", "label": "invalid"},
130
125
  {"from": "save", "to": "success"},
131
- {"from": "error", "to": "start", "label": "исправить"}
126
+ {"from": "error", "to": "start", "label": "retry"}
132
127
  ],
133
128
  "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"}
129
+ {"id": "tag-user", "name": "user", "color": "#4CAF50"},
130
+ {"id": "tag-system", "name": "system", "color": "#2196F3"},
131
+ {"id": "tag-check", "name": "check", "color": "#FF9800"},
132
+ {"id": "tag-error", "name": "error", "color": "#F44336"}
138
133
  ]
139
134
  }
140
135
  ```
141
136
 
142
- ### Элемент (card или condition)
137
+ ### Element (card or condition)
143
138
 
144
139
  ```json
145
140
  {
146
141
  "id": "unique_id",
147
142
  "type": "card",
148
- "title": "Название карточки",
143
+ "title": "Card Title",
149
144
  "color": "light_blue",
150
- "borderColor": "blue",
151
- "tags": ["тег1", "тег2"],
152
- "description": "Подробное описание действия или процесса"
145
+ "tags": ["tag1", "tag2"],
146
+ "description": "Detailed description of the action or process"
153
147
  }
154
148
  ```
155
149
 
156
- **Типы элементов:**
157
- - `card` — обычная карточка процесса/действия
158
- - `condition` — точка принятия решения (ромб)
150
+ **Element types:**
151
+ - `card` — regular process/action card
152
+ - `condition` — decision point (diamond shape)
159
153
 
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` | Специальные операции |
154
+ **Available colors (`color`):**
155
+ | Color | Purpose |
156
+ |-------|---------|
157
+ | `white` | Default white |
158
+ | `light_blue` | Main processes |
159
+ | `light_green` | Start and success |
160
+ | `light_yellow` | Checks and conditions |
161
+ | `light_orange` | Warnings |
162
+ | `light_red` | Errors and critical |
163
+ | `light_purple` | Decisions |
164
+ | `light_gray` | Completion |
165
+ | `light_pink` | Additional processes |
166
+ | `light_teal` | Special operations |
173
167
 
174
- **Цвета обводки (`borderColor`):**
175
- `default`, `blue`, `green`, `orange`, `purple`, `red`, `teal`, `yellow`, `gray`, `black`
168
+ **Border colors (`borderColor`):** `default`, `blue`, `green`, `orange`, `purple`, `red`, `teal`, `yellow`, `gray`, `black`
176
169
 
177
- **Важно:** НЕ указывай `width`, `height`, `x`, `y` — они рассчитываются автоматически!
170
+ **Important:** Do NOT specify `width`, `height`, `x`, `y` — they are calculated automatically!
178
171
 
179
- ### Связь (connection)
172
+ ### Connection
180
173
 
181
174
  ```json
182
175
  {
183
176
  "from": "source_id",
184
177
  "to": "target_id",
185
- "label": "подпись (опционально)",
178
+ "label": "optional label",
186
179
  "style": "solid"
187
180
  }
188
181
  ```
189
182
 
190
- **Стили линий (`style`):** `solid`, `dashed`, `dotted`
183
+ **Line styles (`style`):** `solid`, `dashed`, `dotted`
191
184
 
192
- ### Справочник тегов (tagsDictionary)
185
+ ### Tags Dictionary (tagsDictionary)
193
186
 
194
187
  ```json
195
188
  {
196
189
  "tagsDictionary": [
197
- {"id": "tag-1", "name": "система", "color": "#2196F3"},
198
- {"id": "tag-2", "name": "пользователь", "color": "#4CAF50"},
199
- {"id": "tag-3", "name": "проверка", "color": "#FF9800"}
190
+ {"id": "tag-1", "name": "system", "color": "#2196F3"},
191
+ {"id": "tag-2", "name": "user", "color": "#4CAF50"},
192
+ {"id": "tag-3", "name": "check", "color": "#FF9800"}
200
193
  ]
201
194
  }
202
195
  ```
203
196
 
204
- **Теги = роли/акторы.** Указывают КТО выполняет действие:
205
- - `система`, `пользователь`, `администратор`
206
- - `клиент`, `менеджер`, `бот`
207
- - `муж`, `жена`, `ребёнок` (для личных схем)
197
+ **Tags = roles/actors.** Indicate WHO performs the action:
198
+ - `system`, `user`, `admin`
199
+ - `client`, `manager`, `bot`
208
200
 
209
- ## Примеры использования
201
+ ## Schema Methodology
210
202
 
211
- ### Создать схему
203
+ Schema = complete tree of **ACTIONS** and **CONSEQUENCES**:
212
204
 
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. Теги указывают КТО выполняет действие
205
+ 1. Each decision → show ALL possible options
206
+ 2. Each option show ALL consequences
207
+ 3. Use `condition` for decision points
208
+ 4. NOT abstract thoughts — CONCRETE paths
209
+ 5. Tags indicate WHO performs the action
255
210
 
256
- **Пример:**
211
+ **Example:**
257
212
  ```
258
- "Отправка формы" → condition "Валидация" →
259
- ├── "Данные корректны" → "Сохранение" → "Успех"
260
- └── "Ошибка" → "Показать ошибки" → "Исправить форму"
213
+ "Submit Form" → condition "Validate" →
214
+ ├── "Data Valid" → "Save" → "Success"
215
+ └── "Error" → "Show Errors" → "Fix Form"
261
216
  ```
262
217
 
263
- ## Ссылки
218
+ ## Links
264
219
 
265
220
  - [SchemeOG Cloud](https://scheme.smartlaunchhub.com)
266
221
  - [GitLab](https://gitlab.com/serter2069/schemeog-cloud)
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * SchemeOG MCP Server v2.1
4
+ * SchemeOG MCP Server v2.2
5
5
  *
6
6
  * MCP сервер для работы со схемами, проектами и тегами в SchemeOG Cloud.
7
7
  *
@@ -114,11 +114,11 @@ async function apiRequest(endpoint, options = {}) {
114
114
  throw new Error(error.message);
115
115
  }
116
116
 
117
- // Базовая валидация формата токена
118
- if (!AUTH_TOKEN.startsWith("sk-") || AUTH_TOKEN.length < 20) {
117
+ // Базовая валидация формата токена (schog_ - новый формат)
118
+ if (!AUTH_TOKEN.startsWith("schog_") || AUTH_TOKEN.length < 20) {
119
119
  const error = createError(
120
120
  ErrorCodes.AUTH_INVALID,
121
- `Неверный формат токена. Токен должен начинаться с "sk-" и содержать минимум 20 символов.\n\nПолучен: ${AUTH_TOKEN.substring(0, 10)}...`
121
+ `Неверный формат токена. Токен должен начинаться с "schog_" и содержать минимум 20 символов.\n\nПолучен: ${AUTH_TOKEN.substring(0, 10)}...`
122
122
  );
123
123
  throw new Error(error.message);
124
124
  }
@@ -209,18 +209,208 @@ function generateId() {
209
209
  }
210
210
 
211
211
  /**
212
- * Подготовить элементы добавить ID если нет
212
+ * Допустимые именованные цвета для элементов
213
+ */
214
+ const VALID_COLORS = ["white", "light_blue", "light_green", "light_yellow", "light_orange", "light_red", "light_purple", "light_gray", "light_pink", "light_teal"];
215
+
216
+ /**
217
+ * Маппинг HEX цветов к именованным (ближайшее соответствие)
218
+ */
219
+ const HEX_TO_NAMED_COLOR = {
220
+ // Белые/серые
221
+ "#FFFFFF": "white", "#FFF": "white", "#FAFAFA": "white", "#F5F5F5": "light_gray",
222
+ "#E0E0E0": "light_gray", "#BDBDBD": "light_gray", "#9E9E9E": "light_gray",
223
+ "#CFD8DC": "light_gray", "#ECEFF1": "light_gray",
224
+
225
+ // Синие
226
+ "#E3F2FD": "light_blue", "#BBDEFB": "light_blue", "#90CAF9": "light_blue",
227
+ "#64B5F6": "light_blue", "#42A5F5": "light_blue", "#2196F3": "light_blue",
228
+ "#1E88E5": "light_blue", "#1976D2": "light_blue",
229
+
230
+ // Зелёные
231
+ "#E8F5E9": "light_green", "#C8E6C9": "light_green", "#A5D6A7": "light_green",
232
+ "#81C784": "light_green", "#66BB6A": "light_green", "#4CAF50": "light_green",
233
+ "#43A047": "light_green", "#388E3C": "light_green", "#DCEDC8": "light_green",
234
+
235
+ // Жёлтые
236
+ "#FFFDE7": "light_yellow", "#FFF9C4": "light_yellow", "#FFF59D": "light_yellow",
237
+ "#FFF176": "light_yellow", "#FFEE58": "light_yellow", "#FFEB3B": "light_yellow",
238
+ "#FDD835": "light_yellow", "#FBC02D": "light_yellow",
239
+
240
+ // Оранжевые
241
+ "#FFF3E0": "light_orange", "#FFE0B2": "light_orange", "#FFCC80": "light_orange",
242
+ "#FFB74D": "light_orange", "#FFA726": "light_orange", "#FF9800": "light_orange",
243
+ "#FB8C00": "light_orange", "#F57C00": "light_orange",
244
+ "#FFE5B4": "light_orange", "#FFCCBC": "light_orange", // персиковые
245
+
246
+ // Красные
247
+ "#FFEBEE": "light_red", "#FFCDD2": "light_red", "#EF9A9A": "light_red",
248
+ "#E57373": "light_red", "#EF5350": "light_red", "#F44336": "light_red",
249
+ "#E53935": "light_red", "#D32F2F": "light_red",
250
+ "#FCE4EC": "light_pink", "#F8BBD0": "light_pink", // розовые → light_pink
251
+
252
+ // Фиолетовые
253
+ "#F3E5F5": "light_purple", "#E1BEE7": "light_purple", "#CE93D8": "light_purple",
254
+ "#BA68C8": "light_purple", "#AB47BC": "light_purple", "#9C27B0": "light_purple",
255
+ "#8E24AA": "light_purple", "#7B1FA2": "light_purple",
256
+ "#D1C4E9": "light_purple", "#EDE7F6": "light_purple",
257
+
258
+ // Розовые
259
+ "#FCE4EC": "light_pink", "#F8BBD0": "light_pink", "#F48FB1": "light_pink",
260
+ "#F06292": "light_pink", "#EC407A": "light_pink", "#E91E63": "light_pink",
261
+
262
+ // Бирюзовые/Teal
263
+ "#E0F7FA": "light_teal", "#B2DFDB": "light_teal", "#80CBC4": "light_teal",
264
+ "#4DB6AC": "light_teal", "#26A69A": "light_teal", "#009688": "light_teal",
265
+ "#E0F2F1": "light_teal",
266
+ };
267
+
268
+ /**
269
+ * Конвертировать HEX цвет в ближайший именованный
270
+ */
271
+ function hexToNamedColor(hex) {
272
+ if (!hex) return "white";
273
+
274
+ // Если уже именованный — проверяем и возвращаем
275
+ if (VALID_COLORS.includes(hex)) return hex;
276
+
277
+ // Нормализуем HEX
278
+ const normalizedHex = hex.toUpperCase().trim();
279
+
280
+ // Ищем точное соответствие
281
+ if (HEX_TO_NAMED_COLOR[normalizedHex]) {
282
+ return HEX_TO_NAMED_COLOR[normalizedHex];
283
+ }
284
+
285
+ // Если не нашли — пытаемся определить по оттенку
286
+ // Простой алгоритм: анализируем RGB компоненты
287
+ const match = normalizedHex.match(/^#?([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i);
288
+ if (match) {
289
+ const r = parseInt(match[1], 16);
290
+ const g = parseInt(match[2], 16);
291
+ const b = parseInt(match[3], 16);
292
+
293
+ // Определяем доминирующий цвет
294
+ const max = Math.max(r, g, b);
295
+ const min = Math.min(r, g, b);
296
+ const brightness = (r + g + b) / 3;
297
+
298
+ // Белый/серый
299
+ if (max - min < 30) {
300
+ return brightness > 200 ? "white" : "light_gray";
301
+ }
302
+
303
+ // Красный доминирует
304
+ if (r === max && r > g + 20 && r > b + 20) {
305
+ return g > 150 ? "light_orange" : (b > 100 ? "light_pink" : "light_red");
306
+ }
307
+
308
+ // Зелёный доминирует
309
+ if (g === max && g > r + 20 && g > b + 20) {
310
+ return b > 150 ? "light_teal" : "light_green";
311
+ }
312
+
313
+ // Синий доминирует
314
+ if (b === max && b > r + 20 && b > g + 20) {
315
+ return r > 150 ? "light_purple" : "light_blue";
316
+ }
317
+
318
+ // Жёлтый (R и G высокие, B низкий)
319
+ if (r > 200 && g > 200 && b < 150) {
320
+ return "light_yellow";
321
+ }
322
+
323
+ // Оранжевый (R высокий, G средний, B низкий)
324
+ if (r > 200 && g > 100 && g < 200 && b < 150) {
325
+ return "light_orange";
326
+ }
327
+ }
328
+
329
+ // Fallback
330
+ return "light_blue";
331
+ }
332
+
333
+ /**
334
+ * Нормализовать элементы — исправить типы, цвета, удалить лишние поля
335
+ * Возвращает { elements, warnings }
336
+ */
337
+ function normalizeElements(elements) {
338
+ if (!elements || !Array.isArray(elements)) return { elements: [], warnings: [] };
339
+
340
+ const warnings = [];
341
+
342
+ const normalized = elements.map((el, index) => {
343
+ const fixed = {
344
+ id: el.id || generateId(),
345
+ };
346
+
347
+ // Тип: block/note → card
348
+ if (el.type === "block" || el.type === "note" || el.type === "group") {
349
+ fixed.type = "card";
350
+ warnings.push(`Элемент ${index + 1}: type "${el.type}" → "card"`);
351
+ } else if (el.type === "condition" || el.type === "diamond") {
352
+ fixed.type = "condition";
353
+ } else {
354
+ fixed.type = el.type || "card";
355
+ }
356
+
357
+ // Title: text → title
358
+ if (el.text && !el.title) {
359
+ fixed.title = el.text;
360
+ warnings.push(`Элемент ${index + 1}: "text" → "title"`);
361
+ } else {
362
+ fixed.title = el.title || "";
363
+ }
364
+
365
+ // Цвет: HEX → именованный
366
+ if (el.color) {
367
+ if (el.color.startsWith("#")) {
368
+ const namedColor = hexToNamedColor(el.color);
369
+ fixed.color = namedColor;
370
+ warnings.push(`Элемент ${index + 1}: color "${el.color}" → "${namedColor}"`);
371
+ } else if (VALID_COLORS.includes(el.color)) {
372
+ fixed.color = el.color;
373
+ } else {
374
+ fixed.color = "white";
375
+ warnings.push(`Элемент ${index + 1}: неизвестный color "${el.color}" → "white"`);
376
+ }
377
+ } else {
378
+ fixed.color = "white";
379
+ }
380
+
381
+ // borderColor — оставляем если валидный
382
+ const validBorderColors = ["default", "blue", "green", "orange", "purple", "red", "teal", "yellow", "gray", "black"];
383
+ if (el.borderColor && validBorderColors.includes(el.borderColor)) {
384
+ fixed.borderColor = el.borderColor;
385
+ }
386
+
387
+ // Description
388
+ if (el.description) {
389
+ fixed.description = el.description;
390
+ }
391
+
392
+ // Tags
393
+ if (el.tags && Array.isArray(el.tags)) {
394
+ fixed.tags = el.tags;
395
+ }
396
+
397
+ // НЕ копируем: x, y, width, height — они автоматические
398
+ if (el.x !== undefined || el.y !== undefined || el.width !== undefined || el.height !== undefined) {
399
+ warnings.push(`Элемент ${index + 1}: x/y/width/height удалены (рассчитываются автоматически)`);
400
+ }
401
+
402
+ return fixed;
403
+ });
404
+
405
+ return { elements: normalized, warnings };
406
+ }
407
+
408
+ /**
409
+ * Подготовить элементы — нормализовать и добавить ID
410
+ * Возвращает { elements, warnings }
213
411
  */
214
412
  function prepareElements(elements) {
215
- if (!elements) return [];
216
- return elements.map(el => ({
217
- id: el.id || generateId(),
218
- type: el.type || "block",
219
- x: el.x || 0,
220
- y: el.y || 0,
221
- text: el.text || "",
222
- ...el
223
- }));
413
+ return normalizeElements(elements);
224
414
  }
225
415
 
226
416
  /**
@@ -259,11 +449,22 @@ const TOOLS = [
259
449
  Возвращает:
260
450
  - name: название схемы
261
451
  - description: описание
262
- - elements: массив элементов (блоки, заметки, группы)
452
+ - elements: массив элементов (card или condition)
263
453
  - connections: массив связей между элементами
454
+ - tagsDictionary: справочник тегов
455
+
456
+ Формат элемента:
457
+ {
458
+ "id": "unique_id",
459
+ "type": "card", // card или condition
460
+ "title": "Название", // заголовок
461
+ "color": "light_blue", // ТОЛЬКО: white, light_blue, light_green, light_yellow, light_orange, light_red, light_purple, light_gray, light_pink, light_teal
462
+ "description": "Текст", // описание
463
+ "tags": ["тег1"] // массив тегов
464
+ }
264
465
 
265
- Каждый элемент содержит: id, type, x, y, text, width, height, color
266
- Каждая связь содержит: id, from, to, label, style`,
466
+ ВАЖНО: НЕ используй x, y, width, height — они рассчитываются автоматически!
467
+ ВАЖНО: Цвета ТОЛЬКО именованные (light_blue), НЕ HEX (#FFFFFF)!`,
267
468
  inputSchema: {
268
469
  type: "object",
269
470
  properties: {
@@ -837,12 +1038,15 @@ ${JSON.stringify(schema.data?.connections || [], null, 2)}`,
837
1038
  }
838
1039
 
839
1040
  case "create_schema": {
840
- const { name, description, project_id, elements, connections } = args;
1041
+ const { name, description, project_id, elements, connections, tagsDictionary } = args;
1042
+
1043
+ // Нормализуем элементы и получаем предупреждения
1044
+ const { elements: normalizedElements, warnings } = prepareElements(elements);
841
1045
 
842
1046
  const data = {
843
- elements: prepareElements(elements),
1047
+ elements: normalizedElements,
844
1048
  connections: prepareConnections(connections),
845
- tagsDictionary: [],
1049
+ tagsDictionary: tagsDictionary || [],
846
1050
  };
847
1051
 
848
1052
  const result = await apiRequest("/schemas", {
@@ -852,6 +1056,16 @@ ${JSON.stringify(schema.data?.connections || [], null, 2)}`,
852
1056
 
853
1057
  const projectInfo = project_id ? `Проект: ${project_id}` : 'Проект: Общие';
854
1058
 
1059
+ // Формируем сообщение о предупреждениях
1060
+ let warningsText = "";
1061
+ if (warnings.length > 0) {
1062
+ warningsText = `\n\n⚠️ Автоисправления (${warnings.length}):\n• ${warnings.slice(0, 10).join("\n• ")}`;
1063
+ if (warnings.length > 10) {
1064
+ warningsText += `\n• ...и ещё ${warnings.length - 10}`;
1065
+ }
1066
+ warningsText += `\n\n💡 Подсказка: используй type "card"/"condition", цвета light_blue/light_green/etc, НЕ указывай x/y/width/height`;
1067
+ }
1068
+
855
1069
  return {
856
1070
  content: [{
857
1071
  type: "text",
@@ -864,7 +1078,7 @@ ${projectInfo}
864
1078
 
865
1079
  URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
866
1080
 
867
- Открой ссылку в браузере чтобы увидеть схему.`,
1081
+ Открой ссылку в браузере чтобы увидеть схему.${warningsText}`,
868
1082
  }],
869
1083
  };
870
1084
  }
@@ -879,6 +1093,7 @@ URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
879
1093
 
880
1094
  // Формируем обновление
881
1095
  const updateBody = {};
1096
+ let warnings = [];
882
1097
 
883
1098
  if (name) updateBody.name = name;
884
1099
  if (description !== undefined) updateBody.description = description;
@@ -886,7 +1101,9 @@ URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
886
1101
  // Обновляем данные только если переданы
887
1102
  const newData = { ...currentData };
888
1103
  if (elements !== undefined) {
889
- newData.elements = prepareElements(elements);
1104
+ const normalized = prepareElements(elements);
1105
+ newData.elements = normalized.elements;
1106
+ warnings = normalized.warnings;
890
1107
  }
891
1108
  if (connections !== undefined) {
892
1109
  newData.connections = prepareConnections(connections);
@@ -898,6 +1115,16 @@ URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
898
1115
  body: JSON.stringify(updateBody),
899
1116
  });
900
1117
 
1118
+ // Формируем сообщение о предупреждениях
1119
+ let warningsText = "";
1120
+ if (warnings.length > 0) {
1121
+ warningsText = `\n\n⚠️ Автоисправления (${warnings.length}):\n• ${warnings.slice(0, 10).join("\n• ")}`;
1122
+ if (warnings.length > 10) {
1123
+ warningsText += `\n• ...и ещё ${warnings.length - 10}`;
1124
+ }
1125
+ warningsText += `\n\n💡 Подсказка: используй type "card"/"condition", цвета light_blue/light_green/etc, НЕ указывай x/y/width/height`;
1126
+ }
1127
+
901
1128
  return {
902
1129
  content: [{
903
1130
  type: "text",
@@ -906,7 +1133,7 @@ URL: ${API_BASE_URL}/canvas?id=${result.schema.id}
906
1133
  Элементов: ${result.schema.data?.elements?.length || 0}
907
1134
  Связей: ${result.schema.data?.connections?.length || 0}
908
1135
 
909
- URL: ${API_BASE_URL}/canvas?id=${schema_id}`,
1136
+ URL: ${API_BASE_URL}/canvas?id=${schema_id}${warningsText}`,
910
1137
  }],
911
1138
  };
912
1139
  }
@@ -1192,16 +1419,16 @@ async function main() {
1192
1419
  2. Добавьте в настройки MCP:
1193
1420
 
1194
1421
  "env": {
1195
- "SCHEMEOG_TOKEN": "sk-ваш-токен"
1422
+ "SCHEMEOG_TOKEN": "schog_ваш-токен"
1196
1423
  }
1197
1424
 
1198
1425
  Документация: ${DOCS_URL}
1199
1426
  `);
1200
- } else if (!AUTH_TOKEN.startsWith("sk-")) {
1427
+ } else if (!AUTH_TOKEN.startsWith("schog_")) {
1201
1428
  console.error(`
1202
1429
  ⚠️ Неверный формат токена!
1203
1430
 
1204
- Токен должен начинаться с "sk-".
1431
+ Токен должен начинаться с "schog_".
1205
1432
  Получен: ${AUTH_TOKEN.substring(0, 10)}...
1206
1433
 
1207
1434
  Создайте новый токен: ${PROFILE_URL}
@@ -1211,7 +1438,7 @@ async function main() {
1211
1438
  const server = new Server(
1212
1439
  {
1213
1440
  name: "schemeog-mcp",
1214
- version: "2.1.0",
1441
+ version: "2.3.0",
1215
1442
  },
1216
1443
  {
1217
1444
  capabilities: {
@@ -1241,7 +1468,7 @@ async function main() {
1241
1468
  const transport = new StdioServerTransport();
1242
1469
  await server.connect(transport);
1243
1470
 
1244
- console.error("SchemeOG MCP Server v2.1 запущен");
1471
+ console.error("SchemeOG MCP Server v2.3 запущен");
1245
1472
  }
1246
1473
 
1247
1474
  main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schemeog-mcp",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "MCP Server for SchemeOG Cloud - Create and manage visual diagrams and flowcharts with AI assistance",
5
5
  "type": "module",
6
6
  "main": "index.js",