schemeog-mcp 2.9.3 → 2.10.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 (2) hide show
  1. package/index.js +175 -23
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -756,7 +756,8 @@ Claude обрезает большие параметры, но file_path чит
756
756
  name: "delete_schema",
757
757
  description: `Удалить схему по ID.
758
758
 
759
- ВНИМАНИЕ: Это действие необратимо! Схема будет удалена навсегда.`,
759
+ Схема перемещается в корзину (soft delete). Можно восстановить через restore_schema.
760
+ Для полного удаления используй permanent_delete_schema.`,
760
761
  inputSchema: {
761
762
  type: "object",
762
763
  properties: {
@@ -768,6 +769,52 @@ Claude обрезает большие параметры, но file_path чит
768
769
  required: ["schema_id"],
769
770
  },
770
771
  },
772
+ {
773
+ name: "list_deleted_schemas",
774
+ description: `Получить список удалённых схем (корзина).
775
+
776
+ Возвращает схемы, которые были удалены но ещё не удалены навсегда.
777
+ Можно восстановить через restore_schema или удалить навсегда через permanent_delete_schema.`,
778
+ inputSchema: {
779
+ type: "object",
780
+ properties: {},
781
+ required: [],
782
+ },
783
+ },
784
+ {
785
+ name: "restore_schema",
786
+ description: `Восстановить схему из корзины.
787
+
788
+ Параметры:
789
+ - schema_id: ID схемы из корзины (можно получить через list_deleted_schemas)`,
790
+ inputSchema: {
791
+ type: "object",
792
+ properties: {
793
+ schema_id: {
794
+ type: "string",
795
+ description: "ID схемы для восстановления",
796
+ },
797
+ },
798
+ required: ["schema_id"],
799
+ },
800
+ },
801
+ {
802
+ name: "permanent_delete_schema",
803
+ description: `Удалить схему НАВСЕГДА.
804
+
805
+ ВНИМАНИЕ: Это действие необратимо! Схема будет удалена из базы данных навсегда.
806
+ Работает только со схемами в корзине (сначала нужен обычный delete_schema).`,
807
+ inputSchema: {
808
+ type: "object",
809
+ properties: {
810
+ schema_id: {
811
+ type: "string",
812
+ description: "ID схемы для полного удаления",
813
+ },
814
+ },
815
+ required: ["schema_id"],
816
+ },
817
+ },
771
818
 
772
819
  // ========== ПРОЕКТЫ ==========
773
820
  {
@@ -1438,9 +1485,12 @@ URL: ${API_BASE_URL}/canvas?schema=${result.schema.id}
1438
1485
  const updateBody = {};
1439
1486
  let warnings = [];
1440
1487
  let finalElements = elements;
1488
+ let finalConnections = null; // Связи из файла (cloud формат)
1489
+ let finalTagsDictionary = null; // Теги из файла
1441
1490
  let fileSize = null;
1442
1491
  let fileNameFromJson = null;
1443
1492
  let fileDescFromJson = null;
1493
+ let preservePositionsFromFile = false; // Флаг: сохранять координаты из файла
1444
1494
 
1445
1495
  // Если указан file_path — читаем элементы из файла (обходит лимит Claude)
1446
1496
  if (file_path) {
@@ -1457,22 +1507,26 @@ URL: ${API_BASE_URL}/canvas?schema=${result.schema.id}
1457
1507
  schemaData = parsedContent.schema;
1458
1508
  fileNameFromJson = schemaData.name;
1459
1509
  fileDescFromJson = schemaData.description;
1510
+ preservePositionsFromFile = true; // Экспорт содержит точные координаты
1460
1511
  }
1461
- // Формат 2: Вложенный формат { name, data: { elements: [...] } }
1512
+ // Формат 2: Вложенный формат { name, data: { elements: [...], connections: [...] } }
1462
1513
  else if (parsedContent.data && parsedContent.data.elements) {
1463
1514
  schemaData = parsedContent.data;
1464
1515
  fileNameFromJson = parsedContent.name;
1465
1516
  fileDescFromJson = parsedContent.description;
1517
+ preservePositionsFromFile = true; // Полный формат с координатами
1466
1518
  }
1467
1519
  // Формат 3: Простой { name, elements, connections }
1468
1520
  else if (parsedContent.elements || parsedContent.name) {
1469
1521
  schemaData = parsedContent;
1470
1522
  fileNameFromJson = parsedContent.name;
1471
1523
  fileDescFromJson = parsedContent.description;
1524
+ preservePositionsFromFile = true;
1472
1525
  }
1473
1526
  // Формат 4: Только массив элементов
1474
1527
  else if (Array.isArray(parsedContent)) {
1475
1528
  schemaData = { elements: parsedContent };
1529
+ preservePositionsFromFile = false; // Простой массив — без координат
1476
1530
  }
1477
1531
  else {
1478
1532
  return {
@@ -1485,6 +1539,10 @@ URL: ${API_BASE_URL}/canvas?schema=${result.schema.id}
1485
1539
  }
1486
1540
 
1487
1541
  finalElements = schemaData.elements || [];
1542
+ // КРИТИЧНО: Берём connections из файла если есть (cloud формат)
1543
+ finalConnections = schemaData.connections || null;
1544
+ // Берём tagsDictionary из файла если есть
1545
+ finalTagsDictionary = schemaData.tagsDictionary || null;
1488
1546
  } catch (readError) {
1489
1547
  return {
1490
1548
  content: [{
@@ -1526,27 +1584,57 @@ URL: ${API_BASE_URL}/canvas?schema=${result.schema.id}
1526
1584
  };
1527
1585
  }
1528
1586
 
1529
- // ВАЖНО: Сохраняем координаты существующих элементов!
1530
- // MCP не передаёт x/y, поэтому берём их из текущих данных.
1531
- const existingPositions = {};
1532
- (currentData.elements || []).forEach(el => {
1533
- if (el.id && (typeof el.x === 'number' || typeof el.y === 'number')) {
1534
- existingPositions[el.id] = { x: el.x, y: el.y };
1535
- }
1536
- });
1537
-
1538
- // Применяем сохранённые координаты к элементам
1539
- normalized.elements.forEach(el => {
1540
- if (existingPositions[el.id]) {
1541
- el.x = existingPositions[el.id].x;
1542
- el.y = existingPositions[el.id].y;
1543
- }
1544
- // Новые элементы (без координат) будут расположены через auto-layout на клиенте
1545
- });
1587
+ // Сохраняем координаты:
1588
+ // - Если file_path с preservePositionsFromFile берём x/y из файла
1589
+ // - Иначе — из текущих данных схемы на сервере
1590
+ if (preservePositionsFromFile) {
1591
+ // Координаты из ФАЙЛА восстанавливаем из исходных элементов
1592
+ const filePositions = {};
1593
+ finalElements.forEach(el => {
1594
+ if (el.id && (typeof el.x === 'number' || typeof el.y === 'number')) {
1595
+ filePositions[el.id] = { x: el.x, y: el.y };
1596
+ }
1597
+ });
1598
+ normalized.elements.forEach(el => {
1599
+ if (filePositions[el.id]) {
1600
+ el.x = filePositions[el.id].x;
1601
+ el.y = filePositions[el.id].y;
1602
+ }
1603
+ });
1604
+ } else {
1605
+ // Координаты из СЕРВЕРА (для MCP-созданных элементов без координат)
1606
+ const existingPositions = {};
1607
+ (currentData.elements || []).forEach(el => {
1608
+ if (el.id && (typeof el.x === 'number' || typeof el.y === 'number')) {
1609
+ existingPositions[el.id] = { x: el.x, y: el.y };
1610
+ }
1611
+ });
1612
+ normalized.elements.forEach(el => {
1613
+ if (existingPositions[el.id]) {
1614
+ el.x = existingPositions[el.id].x;
1615
+ el.y = existingPositions[el.id].y;
1616
+ }
1617
+ });
1618
+ }
1546
1619
 
1547
1620
  newData.elements = normalized.elements;
1548
- // Связи извлекаются из элементов (inline формат)
1549
- newData.connections = normalized.extractedConnections;
1621
+
1622
+ // КРИТИЧНО: Выбор источника связей
1623
+ // 1. Если есть finalConnections (из файла в cloud формате) — используем их
1624
+ // 2. Иначе — связи из inline формата внутри элементов
1625
+ if (finalConnections && Array.isArray(finalConnections) && finalConnections.length > 0) {
1626
+ // Cloud формат: connections как отдельный массив
1627
+ newData.connections = prepareConnections(finalConnections);
1628
+ } else {
1629
+ // Inline формат: connections внутри элементов
1630
+ newData.connections = normalized.extractedConnections;
1631
+ }
1632
+
1633
+ // Обновляем tagsDictionary если есть в файле
1634
+ if (finalTagsDictionary && Array.isArray(finalTagsDictionary)) {
1635
+ newData.tagsDictionary = finalTagsDictionary;
1636
+ }
1637
+
1550
1638
  warnings = normalized.warnings;
1551
1639
  }
1552
1640
  updateBody.data = newData;
@@ -1590,14 +1678,78 @@ URL: ${API_BASE_URL}/canvas?schema=${schema_id}${warningsText}`,
1590
1678
  case "delete_schema": {
1591
1679
  const { schema_id } = args;
1592
1680
 
1593
- await apiRequest(`/schemas/${schema_id}`, {
1681
+ const result = await apiRequest(`/schemas/${schema_id}`, {
1682
+ method: "DELETE",
1683
+ });
1684
+
1685
+ return {
1686
+ content: [{
1687
+ type: "text",
1688
+ text: `🗑️ Схема перемещена в корзину.
1689
+
1690
+ Восстановить можно через restore_schema или в профиле на сайте.
1691
+ Для полного удаления используй permanent_delete_schema.`,
1692
+ }],
1693
+ };
1694
+ }
1695
+
1696
+ case "list_deleted_schemas": {
1697
+ const result = await apiRequest("/schemas/deleted/list");
1698
+
1699
+ if (!result.schemas || result.schemas.length === 0) {
1700
+ return {
1701
+ content: [{
1702
+ type: "text",
1703
+ text: `Корзина пуста. Удалённых схем нет.`,
1704
+ }],
1705
+ };
1706
+ }
1707
+
1708
+ const schemasList = result.schemas.map(s => ({
1709
+ id: s.id,
1710
+ name: s.name,
1711
+ description: s.description || "",
1712
+ deletedAt: s.deletedAt,
1713
+ }));
1714
+
1715
+ return {
1716
+ content: [{
1717
+ type: "text",
1718
+ text: `🗑️ В корзине ${result.count} схем:\n\n${JSON.stringify(schemasList, null, 2)}`,
1719
+ }],
1720
+ };
1721
+ }
1722
+
1723
+ case "restore_schema": {
1724
+ const { schema_id } = args;
1725
+
1726
+ const result = await apiRequest(`/schemas/${schema_id}/restore`, {
1727
+ method: "POST",
1728
+ });
1729
+
1730
+ return {
1731
+ content: [{
1732
+ type: "text",
1733
+ text: `✅ ${result.message}
1734
+
1735
+ URL: ${API_BASE_URL}/canvas?schema=${schema_id}`,
1736
+ }],
1737
+ };
1738
+ }
1739
+
1740
+ case "permanent_delete_schema": {
1741
+ const { schema_id } = args;
1742
+
1743
+ const result = await apiRequest(`/schemas/${schema_id}/permanent`, {
1594
1744
  method: "DELETE",
1595
1745
  });
1596
1746
 
1597
1747
  return {
1598
1748
  content: [{
1599
1749
  type: "text",
1600
- text: `Схема удалена.`,
1750
+ text: `🔥 ${result.message}
1751
+
1752
+ Это действие необратимо.`,
1601
1753
  }],
1602
1754
  };
1603
1755
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schemeog-mcp",
3
- "version": "2.9.3",
3
+ "version": "2.10.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",