@hiabhee/archdraw-mcp-server 1.0.2

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 (109) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +745 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/lib/__tests__/constants.test.d.ts +2 -0
  6. package/dist/lib/__tests__/constants.test.d.ts.map +1 -0
  7. package/dist/lib/__tests__/constants.test.js +47 -0
  8. package/dist/lib/__tests__/constants.test.js.map +1 -0
  9. package/dist/lib/__tests__/diagram-state.test.d.ts +2 -0
  10. package/dist/lib/__tests__/diagram-state.test.d.ts.map +1 -0
  11. package/dist/lib/__tests__/diagram-state.test.js +82 -0
  12. package/dist/lib/__tests__/diagram-state.test.js.map +1 -0
  13. package/dist/lib/__tests__/elk-runner.test.d.ts +2 -0
  14. package/dist/lib/__tests__/elk-runner.test.d.ts.map +1 -0
  15. package/dist/lib/__tests__/elk-runner.test.js +87 -0
  16. package/dist/lib/__tests__/elk-runner.test.js.map +1 -0
  17. package/dist/lib/checkpoints.d.ts +48 -0
  18. package/dist/lib/checkpoints.d.ts.map +1 -0
  19. package/dist/lib/checkpoints.js +67 -0
  20. package/dist/lib/checkpoints.js.map +1 -0
  21. package/dist/lib/constants.d.ts +29 -0
  22. package/dist/lib/constants.d.ts.map +1 -0
  23. package/dist/lib/constants.js +62 -0
  24. package/dist/lib/constants.js.map +1 -0
  25. package/dist/lib/diagram-state.d.ts +24 -0
  26. package/dist/lib/diagram-state.d.ts.map +1 -0
  27. package/dist/lib/diagram-state.js +59 -0
  28. package/dist/lib/diagram-state.js.map +1 -0
  29. package/dist/lib/elk-runner.d.ts +29 -0
  30. package/dist/lib/elk-runner.d.ts.map +1 -0
  31. package/dist/lib/elk-runner.js +532 -0
  32. package/dist/lib/elk-runner.js.map +1 -0
  33. package/dist/lib/http.d.ts +3 -0
  34. package/dist/lib/http.d.ts.map +1 -0
  35. package/dist/lib/http.js +13 -0
  36. package/dist/lib/http.js.map +1 -0
  37. package/dist/lib/node-catalog.d.ts +10 -0
  38. package/dist/lib/node-catalog.d.ts.map +1 -0
  39. package/dist/lib/node-catalog.js +122 -0
  40. package/dist/lib/node-catalog.js.map +1 -0
  41. package/dist/lib/parse-prompt.d.ts +26 -0
  42. package/dist/lib/parse-prompt.d.ts.map +1 -0
  43. package/dist/lib/parse-prompt.js +289 -0
  44. package/dist/lib/parse-prompt.js.map +1 -0
  45. package/dist/lib/prompt-builder.d.ts +14 -0
  46. package/dist/lib/prompt-builder.d.ts.map +1 -0
  47. package/dist/lib/prompt-builder.js +133 -0
  48. package/dist/lib/prompt-builder.js.map +1 -0
  49. package/dist/lib/schema.d.ts +1240 -0
  50. package/dist/lib/schema.d.ts.map +1 -0
  51. package/dist/lib/schema.js +261 -0
  52. package/dist/lib/schema.js.map +1 -0
  53. package/dist/server.d.ts +36 -0
  54. package/dist/server.d.ts.map +1 -0
  55. package/dist/server.js +287 -0
  56. package/dist/server.js.map +1 -0
  57. package/dist/tools/__tests__/export-diagram.test.d.ts +2 -0
  58. package/dist/tools/__tests__/export-diagram.test.d.ts.map +1 -0
  59. package/dist/tools/__tests__/export-diagram.test.js +40 -0
  60. package/dist/tools/__tests__/export-diagram.test.js.map +1 -0
  61. package/dist/tools/__tests__/update-diagram.test.d.ts +2 -0
  62. package/dist/tools/__tests__/update-diagram.test.d.ts.map +1 -0
  63. package/dist/tools/__tests__/update-diagram.test.js +98 -0
  64. package/dist/tools/__tests__/update-diagram.test.js.map +1 -0
  65. package/dist/tools/apply-template.d.ts +29 -0
  66. package/dist/tools/apply-template.d.ts.map +1 -0
  67. package/dist/tools/apply-template.js +392 -0
  68. package/dist/tools/apply-template.js.map +1 -0
  69. package/dist/tools/export-diagram.d.ts +36 -0
  70. package/dist/tools/export-diagram.d.ts.map +1 -0
  71. package/dist/tools/export-diagram.js +65 -0
  72. package/dist/tools/export-diagram.js.map +1 -0
  73. package/dist/tools/fix-layout.d.ts +23 -0
  74. package/dist/tools/fix-layout.d.ts.map +1 -0
  75. package/dist/tools/fix-layout.js +39 -0
  76. package/dist/tools/fix-layout.js.map +1 -0
  77. package/dist/tools/generate-diagram.d.ts +32 -0
  78. package/dist/tools/generate-diagram.d.ts.map +1 -0
  79. package/dist/tools/generate-diagram.js +325 -0
  80. package/dist/tools/generate-diagram.js.map +1 -0
  81. package/dist/tools/list-nodes.d.ts +18 -0
  82. package/dist/tools/list-nodes.d.ts.map +1 -0
  83. package/dist/tools/list-nodes.js +48 -0
  84. package/dist/tools/list-nodes.js.map +1 -0
  85. package/dist/tools/load-checkpoint.d.ts +18 -0
  86. package/dist/tools/load-checkpoint.d.ts.map +1 -0
  87. package/dist/tools/load-checkpoint.js +24 -0
  88. package/dist/tools/load-checkpoint.js.map +1 -0
  89. package/dist/tools/read-me.d.ts +2 -0
  90. package/dist/tools/read-me.d.ts.map +1 -0
  91. package/dist/tools/read-me.js +14 -0
  92. package/dist/tools/read-me.js.map +1 -0
  93. package/dist/tools/save-checkpoint.d.ts +11 -0
  94. package/dist/tools/save-checkpoint.d.ts.map +1 -0
  95. package/dist/tools/save-checkpoint.js +17 -0
  96. package/dist/tools/save-checkpoint.js.map +1 -0
  97. package/dist/tools/update-diagram.d.ts +20 -0
  98. package/dist/tools/update-diagram.d.ts.map +1 -0
  99. package/dist/tools/update-diagram.js +217 -0
  100. package/dist/tools/update-diagram.js.map +1 -0
  101. package/dist/tools/validate-diagram.d.ts +16 -0
  102. package/dist/tools/validate-diagram.d.ts.map +1 -0
  103. package/dist/tools/validate-diagram.js +204 -0
  104. package/dist/tools/validate-diagram.js.map +1 -0
  105. package/dist/types/index.d.ts +218 -0
  106. package/dist/types/index.d.ts.map +1 -0
  107. package/dist/types/index.js +2 -0
  108. package/dist/types/index.js.map +1 -0
  109. package/package.json +50 -0
@@ -0,0 +1,18 @@
1
+ import type { LoadCheckpointInput } from '../lib/schema.js';
2
+ export declare function loadCheckpoint(input: LoadCheckpointInput, workingSession?: string): Promise<{
3
+ success: boolean;
4
+ name?: string;
5
+ restoredAt?: string;
6
+ nodeCount?: number;
7
+ edgeCount?: number;
8
+ message?: string;
9
+ availableCheckpoints?: Array<{
10
+ name: string;
11
+ description?: string;
12
+ savedAt: string;
13
+ nodeCount: number;
14
+ edgeCount: number;
15
+ }>;
16
+ error?: string;
17
+ }>;
18
+ //# sourceMappingURL=load-checkpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-checkpoint.d.ts","sourceRoot":"","sources":["../../src/tools/load-checkpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjG,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5H,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAwBD"}
@@ -0,0 +1,24 @@
1
+ import { loadCheckpoint as loadCheckpointFromStore, getCheckpointState, listCheckpoints } from '../lib/checkpoints.js';
2
+ import { setDiagramState } from '../lib/diagram-state.js';
3
+ export async function loadCheckpoint(input, workingSession) {
4
+ if (input.listAvailable) {
5
+ const checkpoints = listCheckpoints(workingSession);
6
+ return {
7
+ success: true,
8
+ availableCheckpoints: checkpoints,
9
+ message: checkpoints.length === 0
10
+ ? 'No checkpoints saved yet.'
11
+ : `Found ${checkpoints.length} checkpoint(s).`,
12
+ };
13
+ }
14
+ const result = loadCheckpointFromStore(input.name, workingSession);
15
+ if (!result.success) {
16
+ return result;
17
+ }
18
+ const state = getCheckpointState(input.name, workingSession);
19
+ if (state) {
20
+ setDiagramState(state, workingSession);
21
+ }
22
+ return result;
23
+ }
24
+ //# sourceMappingURL=load-checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-checkpoint.js","sourceRoot":"","sources":["../../src/tools/load-checkpoint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,IAAI,uBAAuB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACvH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAA0B,EAAE,cAAuB;IAUtF,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;QACpD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,oBAAoB,EAAE,WAAW;YACjC,OAAO,EAAE,WAAW,CAAC,MAAM,KAAK,CAAC;gBAC/B,CAAC,CAAC,2BAA2B;gBAC7B,CAAC,CAAC,SAAS,WAAW,CAAC,MAAM,iBAAiB;SACjD,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC7D,IAAI,KAAK,EAAE,CAAC;QACV,eAAe,CAAC,KAAY,EAAE,cAAc,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getReadMe(): string;
2
+ //# sourceMappingURL=read-me.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-me.d.ts","sourceRoot":"","sources":["../../src/tools/read-me.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,IAAI,MAAM,CAYlC"}
@@ -0,0 +1,14 @@
1
+ export function getReadMe() {
2
+ return `# ArchDraw MCP guide
3
+
4
+ Use \`generate_diagram\` with Mermaid whenever possible. It runs the same Mermaid → Dagre pipeline as the editor, supports subgraphs, and returns a diagram kept in the current MCP session.
5
+
6
+ Model the system the user describes. Architecture patterns are guidance, not mandatory components: include gateways, queues, authentication, storage, observability, or direct client streams only when the available context supports them.
7
+
8
+ Call \`get_diagram_state\`, \`validate_diagram\`, and \`update_diagram\` to refine the current diagram. Keep and resend \`workingSessionId\` when working on multiple diagrams through one MCP connection.
9
+
10
+ Privacy: set \`publish:true\` only when the user explicitly asks for a browser-accessible link. Published links are visible to people who have the URL. Otherwise, diagram data remains in the MCP session.
11
+
12
+ Use \`apply_template\` for a starting point, \`fix_layout\` to run the editor layout pipeline, and checkpoints to experiment safely.`;
13
+ }
14
+ //# sourceMappingURL=read-me.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-me.js","sourceRoot":"","sources":["../../src/tools/read-me.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACvB,OAAO;;;;;;;;;;qIAU4H,CAAC;AACtI,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { SaveCheckpointInput } from '../lib/schema.js';
2
+ export declare function saveCheckpoint(input: SaveCheckpointInput, workingSession?: string): Promise<{
3
+ success: boolean;
4
+ name: string;
5
+ savedAt: string;
6
+ nodeCount: number;
7
+ edgeCount: number;
8
+ overwritten?: boolean;
9
+ error?: string;
10
+ }>;
11
+ //# sourceMappingURL=save-checkpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-checkpoint.d.ts","sourceRoot":"","sources":["../../src/tools/save-checkpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjG,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAcD"}
@@ -0,0 +1,17 @@
1
+ import { getDiagramState, hasDiagramState } from '../lib/diagram-state.js';
2
+ import { saveCheckpoint as saveCheckpointToStore } from '../lib/checkpoints.js';
3
+ export async function saveCheckpoint(input, workingSession) {
4
+ if (!hasDiagramState(workingSession)) {
5
+ return {
6
+ success: false,
7
+ name: input.name,
8
+ savedAt: '',
9
+ nodeCount: 0,
10
+ edgeCount: 0,
11
+ error: 'No diagram to save. Call generate_diagram or apply_template first.',
12
+ };
13
+ }
14
+ const state = getDiagramState(workingSession);
15
+ return saveCheckpointToStore(input.name, input.description, state, workingSession);
16
+ }
17
+ //# sourceMappingURL=save-checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-checkpoint.js","sourceRoot":"","sources":["../../src/tools/save-checkpoint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAA0B,EAAE,cAAuB;IAStF,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;YACZ,KAAK,EAAE,oEAAoE;SAC5E,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;IAC9C,OAAO,qBAAqB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AACrF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ReactFlowNode, ReactFlowEdge } from '../types/index.js';
2
+ import type { UpdateDiagramInput } from '../lib/schema.js';
3
+ export declare function updateDiagram(input: UpdateDiagramInput, workingSession?: string): Promise<{
4
+ success: boolean;
5
+ nodes: ReactFlowNode[];
6
+ edges: ReactFlowEdge[];
7
+ message: string;
8
+ changes: {
9
+ nodesAdded: number;
10
+ nodesRemoved: number;
11
+ nodesUpdated: number;
12
+ edgesAdded: number;
13
+ edgesRemoved: number;
14
+ nodesRepositioned: number;
15
+ };
16
+ sessionId?: string;
17
+ diagramUrl?: string;
18
+ error?: string;
19
+ }>;
20
+ //# sourceMappingURL=update-diagram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-diagram.d.ts","sourceRoot":"","sources":["../../src/tools/update-diagram.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAuE3D,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA6KD"}
@@ -0,0 +1,217 @@
1
+ import { getDiagramState } from '../lib/diagram-state.js';
2
+ import { validateGraph } from './validate-diagram.js';
3
+ import { fetchWithTimeout } from '../lib/http.js';
4
+ import { TIER_COLORS, COMM_COLORS, TIER_X_POSITIONS_LR, DEFAULT_NODE_WIDTH, DEFAULT_NODE_HEIGHT, DEFAULT_GROUP_WIDTH, DEFAULT_GROUP_HEIGHT, } from '../lib/constants.js';
5
+ const VERTICAL_GAP = 80;
6
+ function tierOf(node) {
7
+ const tier = (node.data?.tier || node.data?.layer || 'compute').toLowerCase();
8
+ return tier;
9
+ }
10
+ /** Find a non-colliding spot for a new node below the existing nodes of its tier. */
11
+ function findPlacement(nodes, tier) {
12
+ const sameTier = nodes.filter(n => tierOf(n) === tier);
13
+ if (sameTier.length === 0) {
14
+ return { x: TIER_X_POSITIONS_LR[tier] ?? 50, y: 80 };
15
+ }
16
+ const maxBottom = Math.max(...sameTier.map(n => n.position.y + (n.height || DEFAULT_NODE_HEIGHT)));
17
+ const x = sameTier[0].position.x;
18
+ return { x, y: maxBottom + VERTICAL_GAP };
19
+ }
20
+ function buildEdge(edge, id) {
21
+ const commType = (edge.communicationType || 'sync');
22
+ const commStyle = COMM_COLORS[commType] || COMM_COLORS.sync;
23
+ const label = edge.label || '';
24
+ const pathType = edge.pathType || 'smooth';
25
+ return {
26
+ id,
27
+ source: edge.source,
28
+ target: edge.target,
29
+ type: 'simpleFloating',
30
+ animated: commStyle.animated,
31
+ label,
32
+ labelShowBg: true,
33
+ labelBgPadding: [8, 4],
34
+ labelBgBorderRadius: 4,
35
+ labelBgStyle: { fill: '#1e1e2e', fillOpacity: 0.9 },
36
+ labelStyle: { fontSize: 10, fontWeight: 600, fill: '#e2e8f0' },
37
+ style: {
38
+ stroke: commStyle.color,
39
+ strokeWidth: 2,
40
+ strokeDasharray: commStyle.dash,
41
+ },
42
+ markerEnd: { type: 'arrowclosed', color: commStyle.color },
43
+ data: {
44
+ communicationType: commType,
45
+ pathType: pathType,
46
+ label,
47
+ },
48
+ };
49
+ }
50
+ export async function updateDiagram(input, workingSession) {
51
+ const state = getDiagramState(workingSession);
52
+ if (state.nodes.length === 0 && state.edges.length === 0) {
53
+ return {
54
+ success: false,
55
+ nodes: [],
56
+ edges: [],
57
+ message: '',
58
+ changes: { nodesAdded: 0, nodesRemoved: 0, nodesUpdated: 0, edgesAdded: 0, edgesRemoved: 0, nodesRepositioned: 0 },
59
+ error: 'No diagram exists. Call generate_diagram first.',
60
+ };
61
+ }
62
+ const changes = { nodesAdded: 0, nodesRemoved: 0, nodesUpdated: 0, edgesAdded: 0, edgesRemoved: 0, nodesRepositioned: 0 };
63
+ let nodes = state.nodes.map(n => ({
64
+ ...n,
65
+ position: { ...n.position },
66
+ data: { ...n.data },
67
+ }));
68
+ let edges = state.edges.map(e => ({ ...e }));
69
+ if (input.removeNodeIds && input.removeNodeIds.length > 0) {
70
+ const removeSet = new Set(input.removeNodeIds);
71
+ nodes = nodes.filter(n => !removeSet.has(n.id));
72
+ edges = edges.filter(e => !removeSet.has(e.source) && !removeSet.has(e.target));
73
+ changes.nodesRemoved = input.removeNodeIds.length;
74
+ changes.edgesRemoved = state.edges.length - edges.length;
75
+ }
76
+ if (input.removeEdgeIds && input.removeEdgeIds.length > 0) {
77
+ const removeSet = new Set(input.removeEdgeIds);
78
+ edges = edges.filter(e => !removeSet.has(e.id));
79
+ changes.edgesRemoved += input.removeEdgeIds.length;
80
+ }
81
+ if (input.addNodes && input.addNodes.length > 0) {
82
+ const existingIds = new Set(nodes.map(node => node.id));
83
+ const addedIds = new Set();
84
+ for (const node of input.addNodes) {
85
+ if (existingIds.has(node.id) || addedIds.has(node.id)) {
86
+ return { success: false, nodes: state.nodes, edges: state.edges, message: '', changes, error: `Node id "${node.id}" already exists.` };
87
+ }
88
+ addedIds.add(node.id);
89
+ }
90
+ const newNodes = input.addNodes.map(node => {
91
+ const tier = (node.tier || 'compute').toLowerCase();
92
+ const isGroup = node.isGroup === true;
93
+ const placement = findPlacement(nodes, tier);
94
+ return {
95
+ id: node.id,
96
+ type: isGroup ? 'groupNode' : 'systemNode',
97
+ position: placement,
98
+ data: {
99
+ label: node.label,
100
+ icon: node.icon || (isGroup ? 'layers' : 'box'),
101
+ layer: tier,
102
+ tier: tier,
103
+ tierColor: node.tierColor || TIER_COLORS[tier] || TIER_COLORS.compute,
104
+ accentColor: node.accentColor,
105
+ subtitle: node.subtitle,
106
+ status: node.status,
107
+ isGroup,
108
+ parentId: node.parentId,
109
+ groupColor: node.groupColor,
110
+ },
111
+ width: isGroup ? (node.width || DEFAULT_GROUP_WIDTH) : (node.width || DEFAULT_NODE_WIDTH),
112
+ height: isGroup ? (node.height || DEFAULT_GROUP_HEIGHT) : (node.height || DEFAULT_NODE_HEIGHT),
113
+ zIndex: isGroup ? 0 : 1,
114
+ ...(node.parentId ? { parentNode: node.parentId } : {}),
115
+ };
116
+ });
117
+ nodes = [...nodes, ...newNodes];
118
+ changes.nodesAdded = input.addNodes.length;
119
+ changes.nodesRepositioned += input.addNodes.length;
120
+ }
121
+ if (input.updateNodes && input.updateNodes.length > 0) {
122
+ for (const update of input.updateNodes) {
123
+ const node = nodes.find(n => n.id === update.id);
124
+ if (node) {
125
+ if (update.label !== undefined)
126
+ node.data.label = update.label;
127
+ if (update.subtitle !== undefined)
128
+ node.data.subtitle = update.subtitle;
129
+ if (update.icon !== undefined)
130
+ node.data.icon = update.icon;
131
+ if (update.accentColor !== undefined)
132
+ node.data.accentColor = update.accentColor;
133
+ if (update.status !== undefined)
134
+ node.data.status = update.status;
135
+ if (update.tier) {
136
+ node.data.layer = update.tier;
137
+ node.data.tier = update.tier;
138
+ node.data.tierColor = update.tierColor || TIER_COLORS[update.tier] || TIER_COLORS.compute;
139
+ }
140
+ else if (update.tierColor) {
141
+ node.data.tierColor = update.tierColor;
142
+ }
143
+ changes.nodesUpdated++;
144
+ }
145
+ }
146
+ }
147
+ if (input.addEdges && input.addEdges.length > 0) {
148
+ let edgeIndex = edges.length;
149
+ const newEdges = input.addEdges.map(edge => buildEdge(edge, `edge-${edgeIndex++}`));
150
+ edges = [...edges, ...newEdges];
151
+ changes.edgesAdded = input.addEdges.length;
152
+ }
153
+ const validation = validateGraph(nodes, edges);
154
+ const errors = validation.issues.filter(issue => issue.severity === 'error');
155
+ if (errors.length > 0) {
156
+ return {
157
+ success: false,
158
+ nodes: state.nodes,
159
+ edges: state.edges,
160
+ message: '',
161
+ changes: { nodesAdded: 0, nodesRemoved: 0, nodesUpdated: 0, edgesAdded: 0, edgesRemoved: 0, nodesRepositioned: 0 },
162
+ error: `Update rejected: ${errors.map(issue => issue.message).join(' ')}`,
163
+ };
164
+ }
165
+ let sessionId;
166
+ let diagramUrl;
167
+ // A published canvas is updated in place using its capability token and
168
+ // optimistic revision. Local-only diagrams never leave this MCP process.
169
+ const API_BASE = process.env.API_BASE_URL;
170
+ if (API_BASE && state.sessionId && state.updateToken) {
171
+ try {
172
+ const saveResponse = await fetchWithTimeout(`${API_BASE}/api/diagram/load`, {
173
+ method: 'POST',
174
+ headers: { 'Content-Type': 'application/json' },
175
+ body: JSON.stringify({
176
+ action: 'mcp-update',
177
+ sessionId: state.sessionId,
178
+ updateToken: state.updateToken,
179
+ expectedRevision: input.expectedRevision ?? state.revision,
180
+ nodes,
181
+ edges,
182
+ }),
183
+ });
184
+ if (saveResponse.ok) {
185
+ const saveData = await saveResponse.json();
186
+ sessionId = saveData.sessionId;
187
+ const urlPath = `/editor?session=${saveData.sessionId}`;
188
+ diagramUrl = `${API_BASE}${urlPath}`;
189
+ state.revision = saveData.revision;
190
+ }
191
+ else {
192
+ return { success: false, nodes: state.nodes, edges: state.edges, message: '', changes, error: 'Published diagram changed elsewhere or could not be updated. Reload it before trying again.' };
193
+ }
194
+ }
195
+ catch {
196
+ return { success: false, nodes: state.nodes, edges: state.edges, message: '', changes, error: 'Could not update the published diagram. Your local diagram was left unchanged.' };
197
+ }
198
+ }
199
+ const changeSummary = [
200
+ changes.nodesAdded > 0 ? `${changes.nodesAdded} node(s) added` : '',
201
+ changes.nodesRemoved > 0 ? `${changes.nodesRemoved} node(s) removed` : '',
202
+ changes.nodesUpdated > 0 ? `${changes.nodesUpdated} node(s) updated` : '',
203
+ changes.edgesAdded > 0 ? `${changes.edgesAdded} edge(s) added` : '',
204
+ changes.edgesRemoved > 0 ? `${changes.edgesRemoved} edge(s) removed` : '',
205
+ ].filter(Boolean).join(', ');
206
+ const urlLine = diagramUrl ? `\n\nView the updated diagram: ${diagramUrl}` : '';
207
+ return {
208
+ success: true,
209
+ nodes,
210
+ edges,
211
+ message: `Diagram updated. ${changeSummary}.${urlLine}`,
212
+ changes,
213
+ sessionId: sessionId || state.sessionId,
214
+ diagramUrl,
215
+ };
216
+ }
217
+ //# sourceMappingURL=update-diagram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-diagram.js","sourceRoot":"","sources":["../../src/tools/update-diagram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ReactFlowNode, ReactFlowEdge } from '../types/index.js';
2
+ interface Issue {
3
+ severity: 'error' | 'warning' | 'suggestion';
4
+ nodeId?: string;
5
+ message: string;
6
+ }
7
+ export declare function validateGraph(nodes: ReactFlowNode[], edges: ReactFlowEdge[]): {
8
+ valid: boolean;
9
+ errorCount: number;
10
+ warningCount: number;
11
+ suggestionCount: number;
12
+ issues: Issue[];
13
+ };
14
+ export declare function validateDiagram(workingSession?: string): Promise<ReturnType<typeof validateGraph>>;
15
+ export {};
16
+ //# sourceMappingURL=validate-diagram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-diagram.d.ts","sourceRoot":"","sources":["../../src/tools/validate-diagram.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAItE,UAAU,KAAK;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG;IAC7E,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAyNA;AAED,wBAAsB,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAGxG"}
@@ -0,0 +1,204 @@
1
+ import { getDiagramState } from '../lib/diagram-state.js';
2
+ import { TIER_RANK } from '../lib/constants.js';
3
+ function getTier(node) {
4
+ return (node.data.tier || node.data.layer || 'compute').toLowerCase();
5
+ }
6
+ export function validateGraph(nodes, edges) {
7
+ const state = { nodes, edges };
8
+ if (state.nodes.length === 0 && state.edges.length === 0) {
9
+ return {
10
+ valid: false,
11
+ errorCount: 1,
12
+ warningCount: 0,
13
+ suggestionCount: 0,
14
+ issues: [{ severity: 'error', message: 'No diagram loaded. Call generate_diagram or apply_template first.' }],
15
+ };
16
+ }
17
+ const issues = [];
18
+ const nodeIds = new Set(state.nodes.map(n => n.id));
19
+ const nodeIdCounts = new Map();
20
+ const nodeEdgeCounts = new Map();
21
+ // Track how many edges TARGET each node (inbound degree)
22
+ const nodeInboundCounts = new Map();
23
+ // Track WHICH nodes each node connects TO (targets)
24
+ const nodeOutboundTargets = new Map();
25
+ for (const node of state.nodes) {
26
+ const count = nodeIdCounts.get(node.id) || 0;
27
+ nodeIdCounts.set(node.id, count + 1);
28
+ nodeEdgeCounts.set(node.id, 0);
29
+ nodeInboundCounts.set(node.id, 0);
30
+ nodeOutboundTargets.set(node.id, []);
31
+ }
32
+ for (const edge of state.edges) {
33
+ const sourceCount = nodeEdgeCounts.get(edge.source) || 0;
34
+ const targetCount = nodeEdgeCounts.get(edge.target) || 0;
35
+ nodeEdgeCounts.set(edge.source, sourceCount + 1);
36
+ nodeEdgeCounts.set(edge.target, targetCount + 1);
37
+ // Track inbound edges per node
38
+ const inbound = nodeInboundCounts.get(edge.target) || 0;
39
+ nodeInboundCounts.set(edge.target, inbound + 1);
40
+ // Track what each node connects to
41
+ const targets = nodeOutboundTargets.get(edge.source) || [];
42
+ targets.push(edge.target);
43
+ nodeOutboundTargets.set(edge.source, targets);
44
+ }
45
+ // ─── Duplicate IDs ────────────────────────────────────────────────────────
46
+ for (const [id, count] of nodeIdCounts) {
47
+ if (count > 1) {
48
+ issues.push({ severity: 'error', nodeId: id, message: `Duplicate node ID: '${id}'` });
49
+ }
50
+ }
51
+ // ─── Dangling edges ───────────────────────────────────────────────────────
52
+ for (const edge of state.edges) {
53
+ if (!nodeIds.has(edge.source)) {
54
+ issues.push({ severity: 'error', nodeId: edge.source, message: `Edge '${edge.id}' references non-existent source node '${edge.source}'` });
55
+ }
56
+ if (!nodeIds.has(edge.target)) {
57
+ issues.push({ severity: 'error', nodeId: edge.target, message: `Edge '${edge.id}' references non-existent target node '${edge.target}'` });
58
+ }
59
+ if (edge.source === edge.target) {
60
+ issues.push({ severity: 'error', nodeId: edge.source, message: `Edge '${edge.id}' cannot connect a node to itself` });
61
+ }
62
+ }
63
+ const edgeIds = new Set();
64
+ for (const edge of state.edges) {
65
+ if (edgeIds.has(edge.id)) {
66
+ issues.push({ severity: 'error', message: `Duplicate edge ID: '${edge.id}'` });
67
+ }
68
+ edgeIds.add(edge.id);
69
+ }
70
+ for (const node of state.nodes) {
71
+ const parentId = node.parentNode || node.data?.parentId;
72
+ if (parentId && !nodeIds.has(parentId)) {
73
+ issues.push({ severity: 'error', nodeId: node.id, message: `Node '${node.id}' references missing parent '${parentId}'` });
74
+ }
75
+ if (parentId && node.data?.isGroup) {
76
+ issues.push({ severity: 'error', nodeId: node.id, message: `Group '${node.id}' cannot also be a child node` });
77
+ }
78
+ }
79
+ // ─── Orphan nodes ─────────────────────────────────────────────────────────
80
+ for (const node of state.nodes) {
81
+ const edgeCount = nodeEdgeCounts.get(node.id) || 0;
82
+ if (edgeCount === 0 && !node.data?.isGroup) {
83
+ issues.push({ severity: 'warning', nodeId: node.id, message: `Orphan node '${node.data.label}' has no connections` });
84
+ }
85
+ }
86
+ // ─── STAR TOPOLOGY DETECTION — critical anti-pattern ─────────────────────
87
+ // If any single non-gateway node has more than 40% of all edges pointing TO it,
88
+ // it is being used as a hub — this is wrong.
89
+ const totalEdges = state.edges.length;
90
+ for (const node of state.nodes) {
91
+ if (node.data?.isGroup)
92
+ continue;
93
+ const tier = getTier(node);
94
+ const inbound = nodeInboundCounts.get(node.id) || 0;
95
+ const label = node.data?.label || node.id;
96
+ // These are architecture heuristics, not correctness constraints. A
97
+ // notification or streaming system may legitimately have return paths.
98
+ if (tier === 'client' && inbound > 2) {
99
+ issues.push({
100
+ severity: 'warning',
101
+ nodeId: node.id,
102
+ message: `STAR TOPOLOGY ERROR: Client node '${label}' is the TARGET of ${inbound} edges. ` +
103
+ `Client tier nodes (Web App, Mobile App) are SOURCES — they initiate requests. ` +
104
+ `Backend/service nodes must NOT connect back to the client. ` +
105
+ `Fix: reverse these edges so they flow FROM the client → API Gateway → Services.`,
106
+ });
107
+ }
108
+ // Gateways, event brokers, and read models can all be intentional hubs.
109
+ if (totalEdges >= 4 && inbound >= Math.ceil(totalEdges * 0.5) && tier !== 'edge') {
110
+ issues.push({
111
+ severity: 'warning',
112
+ nodeId: node.id,
113
+ message: `STAR TOPOLOGY ERROR: Node '${label}' (${tier} tier) is the hub — ${inbound} of ${totalEdges} edges point TO it. ` +
114
+ `Architecture must use a tiered flow, not a star/hub pattern. ` +
115
+ `Edges must flow: client → edge → compute → async/data → external.`,
116
+ });
117
+ }
118
+ }
119
+ // ─── BACKWARD EDGE DETECTION — edges flowing right-to-left across tiers ──
120
+ const nodeById = new Map(state.nodes.map(n => [n.id, n]));
121
+ for (const edge of state.edges) {
122
+ const sourceNode = nodeById.get(edge.source);
123
+ const targetNode = nodeById.get(edge.target);
124
+ if (!sourceNode || !targetNode)
125
+ continue;
126
+ if (sourceNode.data?.isGroup || targetNode.data?.isGroup)
127
+ continue;
128
+ const sourceTier = getTier(sourceNode);
129
+ const targetTier = getTier(targetNode);
130
+ const sourceTierOrder = TIER_RANK[sourceTier] ?? 2;
131
+ const targetTierOrder = TIER_RANK[targetTier] ?? 2;
132
+ // Direction is visual guidance only; it is not a validity condition.
133
+ if (sourceTierOrder > 1 && targetTierOrder === 0) {
134
+ issues.push({
135
+ severity: 'warning',
136
+ nodeId: edge.source,
137
+ message: `BACKWARD EDGE: '${sourceNode.data?.label}' (${sourceTier}) → '${targetNode.data?.label}' (client). ` +
138
+ `Service and data nodes must NEVER connect to the client tier. ` +
139
+ `The client initiates requests; it never receives direct pushes from backend services (use WebSocket gateway or notification service instead).`,
140
+ });
141
+ }
142
+ // Edge tier should not connect back to client
143
+ if (sourceTierOrder >= 1 && targetTierOrder === 0) {
144
+ issues.push({
145
+ severity: 'warning',
146
+ nodeId: edge.source,
147
+ message: `DIRECTION WARNING: Edge from '${sourceNode.data?.label}' (${sourceTier}) points back TO '${targetNode.data?.label}' (client tier). ` +
148
+ `In a request-response architecture, backend→client connections should use response arrows or a separate WebSocket/SSE node, not direct edges.`,
149
+ });
150
+ }
151
+ }
152
+ // ─── Client tier node count ───────────────────────────────────────────────
153
+ const clientNodes = state.nodes.filter(n => getTier(n) === 'client');
154
+ if (clientNodes.length > 3) {
155
+ issues.push({ severity: 'warning', message: `Client tier has ${clientNodes.length} nodes (max recommended: 3)` });
156
+ }
157
+ // ─── Too many nodes ───────────────────────────────────────────────────────
158
+ if (state.nodes.length > 25) {
159
+ issues.push({ severity: 'warning', message: `Diagram has ${state.nodes.length} nodes (may be unreadable, consider simplifying)` });
160
+ }
161
+ // ─── Missing tier assignments ─────────────────────────────────────────────
162
+ for (const node of state.nodes) {
163
+ if (!node.data.layer && !node.data.tier) {
164
+ issues.push({ severity: 'warning', nodeId: node.id, message: `Node '${node.data.label}' has no tier assigned` });
165
+ }
166
+ }
167
+ // ─── No observability ─────────────────────────────────────────────────────
168
+ const observeNodes = state.nodes.filter(n => getTier(n) === 'observe');
169
+ if (observeNodes.length === 0) {
170
+ issues.push({ severity: 'suggestion', message: 'No observability nodes present (consider adding monitoring/logging)' });
171
+ }
172
+ // ─── No async communication ───────────────────────────────────────────────
173
+ const asyncOrEventEdges = state.edges.filter(e => e.data?.communicationType === 'async' || e.data?.communicationType === 'event');
174
+ if (asyncOrEventEdges.length === 0 && state.edges.length > 0) {
175
+ issues.push({ severity: 'suggestion', message: 'No async/event communication used (consider if async patterns would improve architecture)' });
176
+ }
177
+ // ─── Disconnected external nodes ──────────────────────────────────────────
178
+ const externalNodes = state.nodes.filter(n => getTier(n) === 'external');
179
+ for (const extNode of externalNodes) {
180
+ const edgeCount = nodeEdgeCounts.get(extNode.id) || 0;
181
+ if (edgeCount === 0) {
182
+ issues.push({ severity: 'suggestion', nodeId: extNode.id, message: `External tier node '${extNode.data.label}' has no edges` });
183
+ }
184
+ }
185
+ // ─── Too simple ───────────────────────────────────────────────────────────
186
+ if (state.nodes.length < 3) {
187
+ issues.push({ severity: 'suggestion', message: 'Diagram has fewer than 3 nodes (may be too simple to be useful)' });
188
+ }
189
+ const errorCount = issues.filter(i => i.severity === 'error').length;
190
+ const warningCount = issues.filter(i => i.severity === 'warning').length;
191
+ const suggestionCount = issues.filter(i => i.severity === 'suggestion').length;
192
+ return {
193
+ valid: errorCount === 0,
194
+ errorCount,
195
+ warningCount,
196
+ suggestionCount,
197
+ issues,
198
+ };
199
+ }
200
+ export async function validateDiagram(workingSession) {
201
+ const state = getDiagramState(workingSession);
202
+ return validateGraph(state.nodes, state.edges);
203
+ }
204
+ //# sourceMappingURL=validate-diagram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-diagram.js","sourceRoot":"","sources":["../../src/tools/validate-diagram.ts"],"names":[],"mappings":"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"}