@io.github.hj1003862396/draw-flow-mcp-server 1.0.1
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 +208 -0
- package/dist/diagram-operations.d.ts +28 -0
- package/dist/diagram-operations.d.ts.map +1 -0
- package/dist/diagram-operations.js +211 -0
- package/dist/diagram-operations.js.map +1 -0
- package/dist/history.d.ts +16 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +48 -0
- package/dist/history.js.map +1 -0
- package/dist/http-server.d.ts +22 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +562 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +531 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +24 -0
- package/dist/logger.js.map +1 -0
- package/dist/xml-validation.d.ts +40 -0
- package/dist/xml-validation.d.ts.map +1 -0
- package/dist/xml-validation.js +790 -0
- package/dist/xml-validation.js.map +1 -0
- package/package.json +55 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server for Next AI Draw.io
|
|
4
|
+
*
|
|
5
|
+
* Enables AI agents (Claude Desktop, Cursor, etc.) to generate and edit
|
|
6
|
+
* draw.io diagrams with real-time browser preview.
|
|
7
|
+
*
|
|
8
|
+
* Uses an embedded HTTP server - no external dependencies required.
|
|
9
|
+
*/
|
|
10
|
+
// Setup DOM polyfill for Node.js (required for XML operations)
|
|
11
|
+
import { DOMParser } from "linkedom";
|
|
12
|
+
globalThis.DOMParser = DOMParser;
|
|
13
|
+
// Create XMLSerializer polyfill using outerHTML
|
|
14
|
+
class XMLSerializerPolyfill {
|
|
15
|
+
serializeToString(node) {
|
|
16
|
+
if (node.outerHTML !== undefined) {
|
|
17
|
+
return node.outerHTML;
|
|
18
|
+
}
|
|
19
|
+
if (node.documentElement) {
|
|
20
|
+
return node.documentElement.outerHTML;
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
;
|
|
26
|
+
globalThis.XMLSerializer = XMLSerializerPolyfill;
|
|
27
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
29
|
+
import open from "open";
|
|
30
|
+
import { z } from "zod";
|
|
31
|
+
import { applyDiagramOperations, } from "./diagram-operations.js";
|
|
32
|
+
import { addHistory } from "./history.js";
|
|
33
|
+
import { getState, requestSync, setState, shutdown, startHttpServer, waitForSync, } from "./http-server.js";
|
|
34
|
+
import { log } from "./logger.js";
|
|
35
|
+
import { validateAndFixXml } from "./xml-validation.js";
|
|
36
|
+
// Server configuration
|
|
37
|
+
const config = {
|
|
38
|
+
port: parseInt(process.env.PORT || "6002", 10),
|
|
39
|
+
};
|
|
40
|
+
// Session state (single session for simplicity)
|
|
41
|
+
let currentSession = null;
|
|
42
|
+
// Create MCP server
|
|
43
|
+
const server = new McpServer({
|
|
44
|
+
name: "next-ai-drawio",
|
|
45
|
+
version: "0.1.2",
|
|
46
|
+
});
|
|
47
|
+
// Register prompt with workflow guidance
|
|
48
|
+
server.prompt("diagram-workflow", "Guidelines for creating and editing draw.io diagrams", () => ({
|
|
49
|
+
messages: [
|
|
50
|
+
{
|
|
51
|
+
role: "user",
|
|
52
|
+
content: {
|
|
53
|
+
type: "text",
|
|
54
|
+
text: `# Draw.io Diagram Workflow Guidelines
|
|
55
|
+
|
|
56
|
+
## Creating a New Diagram
|
|
57
|
+
1. Call start_session to open the browser preview
|
|
58
|
+
2. Use create_new_diagram with complete mxGraphModel XML to create a new diagram
|
|
59
|
+
|
|
60
|
+
## Adding Elements to Existing Diagram
|
|
61
|
+
1. Use edit_diagram with "add" operation
|
|
62
|
+
2. Provide a unique cell_id and complete mxCell XML
|
|
63
|
+
3. No need to call get_diagram first - the server fetches latest state automatically
|
|
64
|
+
|
|
65
|
+
## Modifying or Deleting Existing Elements
|
|
66
|
+
1. FIRST call get_diagram to see current cell IDs and structure
|
|
67
|
+
2. THEN call edit_diagram with "update" or "delete" operations
|
|
68
|
+
3. For update, provide the cell_id and complete new mxCell XML
|
|
69
|
+
|
|
70
|
+
## Important Notes
|
|
71
|
+
- create_new_diagram REPLACES the entire diagram - only use for new diagrams
|
|
72
|
+
- edit_diagram PRESERVES user's manual changes (fetches browser state first)
|
|
73
|
+
- Always use unique cell_ids when adding elements (e.g., "shape-1", "arrow-2")`,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
}));
|
|
78
|
+
// Tool: start_session
|
|
79
|
+
server.registerTool("start_session", {
|
|
80
|
+
description: "Start a new diagram session and open the browser for real-time preview. " +
|
|
81
|
+
"Starts an embedded server and opens a browser window with draw.io. " +
|
|
82
|
+
"The browser will show diagram updates as they happen.",
|
|
83
|
+
inputSchema: {},
|
|
84
|
+
}, async () => {
|
|
85
|
+
try {
|
|
86
|
+
// Start embedded HTTP server
|
|
87
|
+
const port = await startHttpServer(config.port);
|
|
88
|
+
// Create session
|
|
89
|
+
const sessionId = `mcp-${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 8)}`;
|
|
90
|
+
currentSession = {
|
|
91
|
+
id: sessionId,
|
|
92
|
+
xml: "",
|
|
93
|
+
version: 0,
|
|
94
|
+
lastGetDiagramTime: 0,
|
|
95
|
+
};
|
|
96
|
+
// Open browser
|
|
97
|
+
const browserUrl = `http://localhost:${port}?mcp=${sessionId}`;
|
|
98
|
+
await open(browserUrl);
|
|
99
|
+
log.info(`Started session ${sessionId}, browser at ${browserUrl}`);
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: "text",
|
|
104
|
+
text: `Session started successfully!\n\nSession ID: ${sessionId}\nBrowser URL: ${browserUrl}\n\nThe browser will now show real-time diagram updates.`,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
111
|
+
log.error("start_session failed:", message);
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
// Tool: create_new_diagram
|
|
119
|
+
server.registerTool("create_new_diagram", {
|
|
120
|
+
description: `Create a NEW diagram from mxGraphModel XML. Use this when creating a diagram from scratch or replacing the current diagram entirely.
|
|
121
|
+
|
|
122
|
+
CRITICAL: You MUST provide the 'xml' argument in EVERY call. Do NOT call this tool without xml.
|
|
123
|
+
|
|
124
|
+
When to use this tool:
|
|
125
|
+
- Creating a new diagram from scratch
|
|
126
|
+
- Replacing the current diagram with a completely different one
|
|
127
|
+
- Major structural changes that require regenerating the diagram
|
|
128
|
+
|
|
129
|
+
When to use edit_diagram instead:
|
|
130
|
+
- Small modifications to existing diagram
|
|
131
|
+
- Adding/removing individual elements
|
|
132
|
+
- Changing labels, colors, or positions
|
|
133
|
+
|
|
134
|
+
XML FORMAT - Full mxGraphModel structure:
|
|
135
|
+
<mxGraphModel>
|
|
136
|
+
<root>
|
|
137
|
+
<mxCell id="0"/>
|
|
138
|
+
<mxCell id="1" parent="0"/>
|
|
139
|
+
<mxCell id="2" value="Shape" style="rounded=1;" vertex="1" parent="1">
|
|
140
|
+
<mxGeometry x="100" y="100" width="120" height="60" as="geometry"/>
|
|
141
|
+
</mxCell>
|
|
142
|
+
</root>
|
|
143
|
+
</mxGraphModel>
|
|
144
|
+
|
|
145
|
+
LAYOUT CONSTRAINTS:
|
|
146
|
+
- Keep all elements within x=0-800, y=0-600 (single page viewport)
|
|
147
|
+
- Start from margins (x=40, y=40), keep elements grouped closely
|
|
148
|
+
- Use unique IDs starting from "2" (0 and 1 are reserved)
|
|
149
|
+
- Set parent="1" for top-level shapes
|
|
150
|
+
- Space shapes 150-200px apart for clear edge routing
|
|
151
|
+
|
|
152
|
+
EDGE ROUTING RULES:
|
|
153
|
+
- Never let multiple edges share the same path - use different exitY/entryY values
|
|
154
|
+
- For bidirectional connections (A↔B), use OPPOSITE sides
|
|
155
|
+
- Always specify exitX, exitY, entryX, entryY explicitly in edge style
|
|
156
|
+
- Route edges AROUND obstacles using waypoints (add 20-30px clearance)
|
|
157
|
+
- Use natural connection points based on flow (not corners)
|
|
158
|
+
|
|
159
|
+
COMMON STYLES:
|
|
160
|
+
- Shapes: rounded=1; fillColor=#hex; strokeColor=#hex
|
|
161
|
+
- Edges: endArrow=classic; edgeStyle=orthogonalEdgeStyle; curved=1
|
|
162
|
+
- Text: fontSize=14; fontStyle=1 (bold); align=center`,
|
|
163
|
+
inputSchema: {
|
|
164
|
+
xml: z
|
|
165
|
+
.string()
|
|
166
|
+
.describe("REQUIRED: The complete mxGraphModel XML. Must always be provided."),
|
|
167
|
+
},
|
|
168
|
+
}, async ({ xml: inputXml }) => {
|
|
169
|
+
try {
|
|
170
|
+
if (!currentSession) {
|
|
171
|
+
return {
|
|
172
|
+
content: [
|
|
173
|
+
{
|
|
174
|
+
type: "text",
|
|
175
|
+
text: "Error: No active session. Please call start_session first.",
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
isError: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Validate and auto-fix XML
|
|
182
|
+
let xml = inputXml;
|
|
183
|
+
const { valid, error, fixed, fixes } = validateAndFixXml(xml);
|
|
184
|
+
if (fixed) {
|
|
185
|
+
xml = fixed;
|
|
186
|
+
log.info(`XML auto-fixed: ${fixes.join(", ")}`);
|
|
187
|
+
}
|
|
188
|
+
if (!valid && error) {
|
|
189
|
+
log.error(`XML validation failed: ${error}`);
|
|
190
|
+
return {
|
|
191
|
+
content: [
|
|
192
|
+
{
|
|
193
|
+
type: "text",
|
|
194
|
+
text: `Error: XML validation failed - ${error}`,
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
isError: true,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
log.info(`Setting diagram content, ${xml.length} chars`);
|
|
201
|
+
// Sync from browser state first
|
|
202
|
+
const browserState = getState(currentSession.id);
|
|
203
|
+
if (browserState?.xml) {
|
|
204
|
+
currentSession.xml = browserState.xml;
|
|
205
|
+
}
|
|
206
|
+
// Save user's state before AI overwrites (with cached SVG)
|
|
207
|
+
if (currentSession.xml) {
|
|
208
|
+
addHistory(currentSession.id, currentSession.xml, browserState?.svg || "");
|
|
209
|
+
}
|
|
210
|
+
// Update session state
|
|
211
|
+
currentSession.xml = xml;
|
|
212
|
+
currentSession.version++;
|
|
213
|
+
// Push to embedded server state
|
|
214
|
+
setState(currentSession.id, xml);
|
|
215
|
+
// Save AI result (no SVG yet - will be captured by browser)
|
|
216
|
+
addHistory(currentSession.id, xml, "");
|
|
217
|
+
log.info(`Diagram content set successfully`);
|
|
218
|
+
return {
|
|
219
|
+
content: [
|
|
220
|
+
{
|
|
221
|
+
type: "text",
|
|
222
|
+
text: `Diagram content set successfully!\n\nThe diagram is now visible in your browser.\n\nXML length: ${xml.length} characters`,
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
229
|
+
log.error("create_new_diagram failed:", message);
|
|
230
|
+
return {
|
|
231
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
232
|
+
isError: true,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
// Tool: edit_diagram
|
|
237
|
+
server.registerTool("edit_diagram", {
|
|
238
|
+
description: "Edit the current diagram by ID-based operations (update/add/delete cells).\n\n" +
|
|
239
|
+
"⚠️ REQUIRED: You MUST call get_diagram BEFORE this tool!\n" +
|
|
240
|
+
"This fetches the latest state from the browser including any manual user edits.\n" +
|
|
241
|
+
"Skipping get_diagram WILL cause user's changes to be LOST.\n\n" +
|
|
242
|
+
"Workflow:\n" +
|
|
243
|
+
"1. Call get_diagram to see current cell IDs and structure\n" +
|
|
244
|
+
"2. Use the returned XML to construct your edit operations\n" +
|
|
245
|
+
"3. Call edit_diagram with your operations\n\n" +
|
|
246
|
+
"Operations:\n" +
|
|
247
|
+
"- add: Add a new cell. Provide cell_id (new unique id) and new_xml.\n" +
|
|
248
|
+
"- update: Replace an existing cell by its id. Provide cell_id and complete new_xml.\n" +
|
|
249
|
+
"- delete: Remove a cell by its id. Only cell_id is needed.\n\n" +
|
|
250
|
+
"For add/update, new_xml must be a complete mxCell element including mxGeometry.\n\n" +
|
|
251
|
+
"Example - Add a rectangle:\n" +
|
|
252
|
+
'{"operations": [{"operation": "add", "cell_id": "rect-1", "new_xml": "<mxCell id=\\"rect-1\\" value=\\"Hello\\" style=\\"rounded=0;\\" vertex=\\"1\\" parent=\\"1\\"><mxGeometry x=\\"100\\" y=\\"100\\" width=\\"120\\" height=\\"60\\" as=\\"geometry\\"/></mxCell>"}]}\n\n' +
|
|
253
|
+
"Example - Update a cell:\n" +
|
|
254
|
+
'{"operations": [{"operation": "update", "cell_id": "3", "new_xml": "<mxCell id=\\"3\\" value=\\"New Label\\" style=\\"rounded=1;\\" vertex=\\"1\\" parent=\\"1\\"><mxGeometry x=\\"100\\" y=\\"100\\" width=\\"120\\" height=\\"60\\" as=\\"geometry\\"/></mxCell>"}]}\n\n' +
|
|
255
|
+
"Example - Delete a cell:\n" +
|
|
256
|
+
'{"operations": [{"operation": "delete", "cell_id": "rect-1"}]}',
|
|
257
|
+
inputSchema: {
|
|
258
|
+
operations: z
|
|
259
|
+
.array(z.object({
|
|
260
|
+
operation: z
|
|
261
|
+
.enum(["update", "add", "delete"])
|
|
262
|
+
.describe("Operation to perform: add, update, or delete"),
|
|
263
|
+
cell_id: z.string().describe("The id of the mxCell"),
|
|
264
|
+
new_xml: z
|
|
265
|
+
.string()
|
|
266
|
+
.optional()
|
|
267
|
+
.describe("Complete mxCell XML element (required for update/add)"),
|
|
268
|
+
}))
|
|
269
|
+
.describe("Array of operations to apply"),
|
|
270
|
+
},
|
|
271
|
+
}, async ({ operations }) => {
|
|
272
|
+
try {
|
|
273
|
+
if (!currentSession) {
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: "Error: No active session. Please call start_session first.",
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
isError: true,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
// Enforce workflow: require get_diagram to be called first
|
|
285
|
+
const timeSinceGet = Date.now() - currentSession.lastGetDiagramTime;
|
|
286
|
+
if (timeSinceGet > 30000) {
|
|
287
|
+
// 30 seconds
|
|
288
|
+
log.warn("edit_diagram called without recent get_diagram - rejecting to prevent data loss");
|
|
289
|
+
return {
|
|
290
|
+
content: [
|
|
291
|
+
{
|
|
292
|
+
type: "text",
|
|
293
|
+
text: "Error: You must call get_diagram first before edit_diagram.\n\n" +
|
|
294
|
+
"This ensures you have the latest diagram state including any manual edits the user made in the browser. " +
|
|
295
|
+
"Please call get_diagram, then use that XML to construct your edit operations.",
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
isError: true,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// Fetch latest state from browser
|
|
302
|
+
const browserState = getState(currentSession.id);
|
|
303
|
+
if (browserState?.xml) {
|
|
304
|
+
currentSession.xml = browserState.xml;
|
|
305
|
+
log.info("Fetched latest diagram state from browser");
|
|
306
|
+
}
|
|
307
|
+
if (!currentSession.xml) {
|
|
308
|
+
return {
|
|
309
|
+
content: [
|
|
310
|
+
{
|
|
311
|
+
type: "text",
|
|
312
|
+
text: "Error: No diagram to edit. Please create a diagram first with create_new_diagram.",
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
isError: true,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
log.info(`Editing diagram with ${operations.length} operation(s)`);
|
|
319
|
+
// Save before editing (with cached SVG from browser)
|
|
320
|
+
addHistory(currentSession.id, currentSession.xml, browserState?.svg || "");
|
|
321
|
+
// Validate and auto-fix new_xml for each operation
|
|
322
|
+
const validatedOps = operations.map((op) => {
|
|
323
|
+
if (op.new_xml) {
|
|
324
|
+
const { valid, error, fixed, fixes } = validateAndFixXml(op.new_xml);
|
|
325
|
+
if (fixed) {
|
|
326
|
+
log.info(`Operation ${op.operation} ${op.cell_id}: XML auto-fixed: ${fixes.join(", ")}`);
|
|
327
|
+
return { ...op, new_xml: fixed };
|
|
328
|
+
}
|
|
329
|
+
if (!valid && error) {
|
|
330
|
+
log.warn(`Operation ${op.operation} ${op.cell_id}: XML validation failed: ${error}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return op;
|
|
334
|
+
});
|
|
335
|
+
// Apply operations
|
|
336
|
+
const { result, errors } = applyDiagramOperations(currentSession.xml, validatedOps);
|
|
337
|
+
if (errors.length > 0) {
|
|
338
|
+
const errorMessages = errors
|
|
339
|
+
.map((e) => `${e.type} ${e.cellId}: ${e.message}`)
|
|
340
|
+
.join("\n");
|
|
341
|
+
log.warn(`Edit had ${errors.length} error(s): ${errorMessages}`);
|
|
342
|
+
}
|
|
343
|
+
// Update state
|
|
344
|
+
currentSession.xml = result;
|
|
345
|
+
currentSession.version++;
|
|
346
|
+
// Push to embedded server
|
|
347
|
+
setState(currentSession.id, result);
|
|
348
|
+
// Save AI result (no SVG yet - will be captured by browser)
|
|
349
|
+
addHistory(currentSession.id, result, "");
|
|
350
|
+
log.info(`Diagram edited successfully`);
|
|
351
|
+
const successMsg = `Diagram edited successfully!\n\nApplied ${operations.length} operation(s).`;
|
|
352
|
+
const errorMsg = errors.length > 0
|
|
353
|
+
? `\n\nWarnings:\n${errors.map((e) => `- ${e.type} ${e.cellId}: ${e.message}`).join("\n")}`
|
|
354
|
+
: "";
|
|
355
|
+
return {
|
|
356
|
+
content: [
|
|
357
|
+
{
|
|
358
|
+
type: "text",
|
|
359
|
+
text: successMsg + errorMsg,
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
366
|
+
log.error("edit_diagram failed:", message);
|
|
367
|
+
return {
|
|
368
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
369
|
+
isError: true,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
// Tool: get_diagram
|
|
374
|
+
server.registerTool("get_diagram", {
|
|
375
|
+
description: "Get the current diagram XML (fetches latest from browser, including user's manual edits). " +
|
|
376
|
+
"Call this BEFORE edit_diagram if you need to update or delete existing elements, " +
|
|
377
|
+
"so you can see the current cell IDs and structure.",
|
|
378
|
+
}, async () => {
|
|
379
|
+
try {
|
|
380
|
+
if (!currentSession) {
|
|
381
|
+
return {
|
|
382
|
+
content: [
|
|
383
|
+
{
|
|
384
|
+
type: "text",
|
|
385
|
+
text: "Error: No active session. Please call start_session first.",
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
isError: true,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
// Request browser to push fresh state and wait for it
|
|
392
|
+
const syncRequested = requestSync(currentSession.id);
|
|
393
|
+
if (syncRequested) {
|
|
394
|
+
const synced = await waitForSync(currentSession.id);
|
|
395
|
+
if (!synced) {
|
|
396
|
+
log.warn("get_diagram: sync timeout - state may be stale");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// Mark that get_diagram was called (for edit_diagram workflow check)
|
|
400
|
+
currentSession.lastGetDiagramTime = Date.now();
|
|
401
|
+
// Fetch latest state from browser
|
|
402
|
+
const browserState = getState(currentSession.id);
|
|
403
|
+
if (browserState?.xml) {
|
|
404
|
+
currentSession.xml = browserState.xml;
|
|
405
|
+
}
|
|
406
|
+
if (!currentSession.xml) {
|
|
407
|
+
return {
|
|
408
|
+
content: [
|
|
409
|
+
{
|
|
410
|
+
type: "text",
|
|
411
|
+
text: "No diagram exists yet. Use create_new_diagram to create one.",
|
|
412
|
+
},
|
|
413
|
+
],
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
content: [
|
|
418
|
+
{
|
|
419
|
+
type: "text",
|
|
420
|
+
text: `Current diagram XML:\n\n${currentSession.xml}`,
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
427
|
+
log.error("get_diagram failed:", message);
|
|
428
|
+
return {
|
|
429
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
430
|
+
isError: true,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
// Tool: export_diagram
|
|
435
|
+
server.registerTool("export_diagram", {
|
|
436
|
+
description: "Export the current diagram to a .drawio file.",
|
|
437
|
+
inputSchema: {
|
|
438
|
+
path: z
|
|
439
|
+
.string()
|
|
440
|
+
.describe("File path to save the diagram (e.g., ./diagram.drawio)"),
|
|
441
|
+
},
|
|
442
|
+
}, async ({ path }) => {
|
|
443
|
+
try {
|
|
444
|
+
if (!currentSession) {
|
|
445
|
+
return {
|
|
446
|
+
content: [
|
|
447
|
+
{
|
|
448
|
+
type: "text",
|
|
449
|
+
text: "Error: No active session. Please call start_session first.",
|
|
450
|
+
},
|
|
451
|
+
],
|
|
452
|
+
isError: true,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
// Fetch latest state
|
|
456
|
+
const browserState = getState(currentSession.id);
|
|
457
|
+
if (browserState?.xml) {
|
|
458
|
+
currentSession.xml = browserState.xml;
|
|
459
|
+
}
|
|
460
|
+
if (!currentSession.xml) {
|
|
461
|
+
return {
|
|
462
|
+
content: [
|
|
463
|
+
{
|
|
464
|
+
type: "text",
|
|
465
|
+
text: "Error: No diagram to export. Please create a diagram first.",
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
isError: true,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const fs = await import("node:fs/promises");
|
|
472
|
+
const nodePath = await import("node:path");
|
|
473
|
+
let filePath = path;
|
|
474
|
+
if (!filePath.endsWith(".drawio")) {
|
|
475
|
+
filePath = `${filePath}.drawio`;
|
|
476
|
+
}
|
|
477
|
+
const absolutePath = nodePath.resolve(filePath);
|
|
478
|
+
await fs.writeFile(absolutePath, currentSession.xml, "utf-8");
|
|
479
|
+
log.info(`Diagram exported to ${absolutePath}`);
|
|
480
|
+
return {
|
|
481
|
+
content: [
|
|
482
|
+
{
|
|
483
|
+
type: "text",
|
|
484
|
+
text: `Diagram exported successfully!\n\nFile: ${absolutePath}\nSize: ${currentSession.xml.length} characters`,
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
491
|
+
log.error("export_diagram failed:", message);
|
|
492
|
+
return {
|
|
493
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
494
|
+
isError: true,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
// Graceful shutdown handler
|
|
499
|
+
let isShuttingDown = false;
|
|
500
|
+
function gracefulShutdown(reason) {
|
|
501
|
+
if (isShuttingDown)
|
|
502
|
+
return;
|
|
503
|
+
isShuttingDown = true;
|
|
504
|
+
log.info(`Shutting down: ${reason}`);
|
|
505
|
+
shutdown();
|
|
506
|
+
process.exit(0);
|
|
507
|
+
}
|
|
508
|
+
// Handle stdin close (primary method - works on all platforms including Windows)
|
|
509
|
+
process.stdin.on("close", () => gracefulShutdown("stdin closed"));
|
|
510
|
+
process.stdin.on("end", () => gracefulShutdown("stdin ended"));
|
|
511
|
+
// Handle signals (may not work reliably on Windows)
|
|
512
|
+
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
|
|
513
|
+
process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
|
|
514
|
+
// Handle broken pipe (writing to closed stdout)
|
|
515
|
+
process.stdout.on("error", (err) => {
|
|
516
|
+
if (err.code === "EPIPE" || err.code === "ERR_STREAM_DESTROYED") {
|
|
517
|
+
gracefulShutdown("stdout error");
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
// Start the MCP server
|
|
521
|
+
async function main() {
|
|
522
|
+
log.info("Starting MCP server for Next AI Draw.io (embedded mode)...");
|
|
523
|
+
const transport = new StdioServerTransport();
|
|
524
|
+
await server.connect(transport);
|
|
525
|
+
log.info("MCP server running on stdio");
|
|
526
|
+
}
|
|
527
|
+
main().catch((error) => {
|
|
528
|
+
log.error("Fatal error:", error);
|
|
529
|
+
process.exit(1);
|
|
530
|
+
});
|
|
531
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger for MCP server
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: MCP servers communicate via STDIO (stdin/stdout).
|
|
5
|
+
* Using console.log() will corrupt the JSON-RPC protocol messages.
|
|
6
|
+
* ALL logging MUST use console.error() which writes to stderr.
|
|
7
|
+
*/
|
|
8
|
+
export declare const log: {
|
|
9
|
+
info: (msg: string, ...args: unknown[]) => void;
|
|
10
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
11
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
12
|
+
warn: (msg: string, ...args: unknown[]) => void;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,GAAG;gBACA,MAAM,WAAW,OAAO,EAAE;iBAGzB,MAAM,WAAW,OAAO,EAAE;iBAG1B,MAAM,WAAW,OAAO,EAAE;gBAK3B,MAAM,WAAW,OAAO,EAAE;CAGzC,CAAA"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger for MCP server
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: MCP servers communicate via STDIO (stdin/stdout).
|
|
5
|
+
* Using console.log() will corrupt the JSON-RPC protocol messages.
|
|
6
|
+
* ALL logging MUST use console.error() which writes to stderr.
|
|
7
|
+
*/
|
|
8
|
+
export const log = {
|
|
9
|
+
info: (msg, ...args) => {
|
|
10
|
+
console.error(`[MCP-DrawIO] [INFO] ${msg}`, ...args);
|
|
11
|
+
},
|
|
12
|
+
error: (msg, ...args) => {
|
|
13
|
+
console.error(`[MCP-DrawIO] [ERROR] ${msg}`, ...args);
|
|
14
|
+
},
|
|
15
|
+
debug: (msg, ...args) => {
|
|
16
|
+
if (process.env.DEBUG === "true") {
|
|
17
|
+
console.error(`[MCP-DrawIO] [DEBUG] ${msg}`, ...args);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
warn: (msg, ...args) => {
|
|
21
|
+
console.error(`[MCP-DrawIO] [WARN] ${msg}`, ...args);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,GAAG,GAAG;IACf,IAAI,EAAE,CAAC,GAAW,EAAE,GAAG,IAAe,EAAE,EAAE;QACtC,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IACxD,CAAC;IACD,KAAK,EAAE,CAAC,GAAW,EAAE,GAAG,IAAe,EAAE,EAAE;QACvC,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IACzD,CAAC;IACD,KAAK,EAAE,CAAC,GAAW,EAAE,GAAG,IAAe,EAAE,EAAE;QACvC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;QACzD,CAAC;IACL,CAAC;IACD,IAAI,EAAE,CAAC,GAAW,EAAE,GAAG,IAAe,EAAE,EAAE;QACtC,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IACxD,CAAC;CACJ,CAAA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XML Validation and Auto-Fix for draw.io diagrams
|
|
3
|
+
* Copied from lib/utils.ts to avoid cross-package imports
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validates draw.io XML structure for common issues
|
|
7
|
+
* Uses DOM parsing + additional regex checks for high accuracy
|
|
8
|
+
* @param xml - The XML string to validate
|
|
9
|
+
* @returns null if valid, error message string if invalid
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateMxCellStructure(xml: string): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Attempts to auto-fix common XML issues in draw.io diagrams
|
|
14
|
+
* @param xml - The XML string to fix
|
|
15
|
+
* @returns Object with fixed XML and list of fixes applied
|
|
16
|
+
*/
|
|
17
|
+
export declare function autoFixXml(xml: string): {
|
|
18
|
+
fixed: string;
|
|
19
|
+
fixes: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Validates XML and attempts to fix if invalid
|
|
23
|
+
* @param xml - The XML string to validate and potentially fix
|
|
24
|
+
* @returns Object with validation result, fixed XML if applicable, and fixes applied
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateAndFixXml(xml: string): {
|
|
27
|
+
valid: boolean;
|
|
28
|
+
error: string | null;
|
|
29
|
+
fixed: string | null;
|
|
30
|
+
fixes: string[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Check if mxCell XML output is complete (not truncated).
|
|
34
|
+
* Uses a robust approach that handles any LLM provider's wrapper tags
|
|
35
|
+
* by finding the last valid mxCell ending and checking if suffix is just closing tags.
|
|
36
|
+
* @param xml - The XML string to check (can be undefined/null)
|
|
37
|
+
* @returns true if XML appears complete, false if truncated or empty
|
|
38
|
+
*/
|
|
39
|
+
export declare function isMxCellXmlComplete(xml: string | undefined | null): boolean;
|
|
40
|
+
//# sourceMappingURL=xml-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml-validation.d.ts","sourceRoot":"","sources":["../src/xml-validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0OH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkGlE;AAMD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CA6f1E;AAMD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC5C,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;CAClB,CAyBA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAqB3E"}
|