Skip to main content
Glama
index.js14.2 kB
#!/usr/bin/env node /** * MCP Server for Draw.io Diagram Generation * Generates Draw.io compatible diagrams from natural language prompts */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { DrawioGenerator } from './drawio-generator.js'; import * as fs from 'fs'; import * as path from 'path'; class DrawioMCPServer { constructor() { this.server = new Server( { name: 'mcp-drawio-diagram-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.generator = new DrawioGenerator(); this.outputDir = process.env.DRAWIO_OUTPUT_DIR || process.cwd(); this.ensureOutputDirectory(); this.setupHandlers(); } ensureOutputDirectory() { try { if (!fs.existsSync(this.outputDir)) { fs.mkdirSync(this.outputDir, { recursive: true }); console.error(`Created output directory: ${this.outputDir}`); } } catch (error) { console.error(`Warning: Could not create output directory: ${error.message}`); } } saveToFile(filename, content) { try { // Ensure filename has .drawio extension if (!filename.endsWith('.drawio')) { filename += '.drawio'; } const fullPath = path.join(this.outputDir, filename); fs.writeFileSync(fullPath, content, 'utf-8'); return fullPath; } catch (error) { throw new Error(`Failed to save file: ${error.message}`); } } setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'create_flowchart', description: 'Create a flowchart diagram with sequential steps. Supports process boxes, decision diamonds, terminators, and connectors.', inputSchema: { type: 'object', properties: { filename: { type: 'string', description: 'Name for the output .drawio file (extension will be added automatically)', }, steps: { type: 'array', description: 'Array of flowchart steps', items: { type: 'object', properties: { label: { type: 'string', description: 'Text label for the step', }, type: { type: 'string', enum: ['process', 'decision', 'terminator', 'data', 'document', 'delay'], description: 'Shape type for the step', }, connectorLabel: { type: 'string', description: 'Optional label for the connector to this step', }, }, required: ['label'], }, }, }, required: ['filename', 'steps'], }, }, { name: 'create_sequence_diagram', description: 'Create a UML sequence diagram showing interactions between participants/actors.', inputSchema: { type: 'object', properties: { filename: { type: 'string', description: 'Name for the output .drawio file (extension will be added automatically)', }, participants: { type: 'array', description: 'Array of participant names', items: { type: 'string' }, }, interactions: { type: 'array', description: 'Array of interactions between participants', items: { type: 'object', properties: { from: { type: 'string', description: 'Source participant name', }, to: { type: 'string', description: 'Target participant name', }, message: { type: 'string', description: 'Message/interaction label', }, dashed: { type: 'boolean', description: 'Use dashed line for return messages', }, }, required: ['from', 'to', 'message'], }, }, }, required: ['filename', 'participants', 'interactions'], }, }, { name: 'create_network_diagram', description: 'Create a network or architecture diagram with custom positioned nodes and connections.', inputSchema: { type: 'object', properties: { filename: { type: 'string', description: 'Name for the output .drawio file (extension will be added automatically)', }, nodes: { type: 'array', description: 'Array of network nodes', items: { type: 'object', properties: { id: { type: 'string', description: 'Unique identifier for the node', }, label: { type: 'string', description: 'Display label for the node', }, type: { type: 'string', enum: ['rectangle', 'cylinder', 'database', 'cloud', 'hexagon', 'ellipse'], description: 'Shape type for the node', }, x: { type: 'number', description: 'X coordinate position', }, y: { type: 'number', description: 'Y coordinate position', }, }, required: ['id', 'label', 'x', 'y'], }, }, connections: { type: 'array', description: 'Array of connections between nodes', items: { type: 'object', properties: { from: { type: 'string', description: 'Source node ID', }, to: { type: 'string', description: 'Target node ID', }, label: { type: 'string', description: 'Connection label', }, }, required: ['from', 'to'], }, }, }, required: ['filename', 'nodes', 'connections'], }, }, { name: 'create_custom_diagram', description: 'Create a custom diagram with full control over shapes and connectors. Use this for any diagram type not covered by other tools.', inputSchema: { type: 'object', properties: { filename: { type: 'string', description: 'Name for the output .drawio file (extension will be added automatically)', }, shapes: { type: 'array', description: 'Array of shapes to create', items: { type: 'object', properties: { id: { type: 'string', description: 'Unique identifier for referencing in connections', }, label: { type: 'string', description: 'Text label for the shape', }, type: { type: 'string', enum: [ 'rectangle', 'roundedRectangle', 'ellipse', 'diamond', 'parallelogram', 'cylinder', 'hexagon', 'cloud', 'document', 'process', 'decision', 'data', 'terminator', 'database', 'actor', 'note', ], description: 'Shape type', }, x: { type: 'number', description: 'X coordinate', }, y: { type: 'number', description: 'Y coordinate', }, width: { type: 'number', description: 'Shape width (default: 120)', }, height: { type: 'number', description: 'Shape height (default: 60)', }, }, required: ['id', 'label', 'type', 'x', 'y'], }, }, connectors: { type: 'array', description: 'Array of connectors between shapes', items: { type: 'object', properties: { from: { type: 'string', description: 'Source shape ID', }, to: { type: 'string', description: 'Target shape ID', }, label: { type: 'string', description: 'Connector label', }, }, required: ['from', 'to'], }, }, }, required: ['filename', 'shapes'], }, }, ], })); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; switch (name) { case 'create_flowchart': return this.handleCreateFlowchart(args); case 'create_sequence_diagram': return this.handleCreateSequenceDiagram(args); case 'create_network_diagram': return this.handleCreateNetworkDiagram(args); case 'create_custom_diagram': return this.handleCreateCustomDiagram(args); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Error: ${error.message}`, }, ], isError: true, }; } }); } handleCreateFlowchart(args) { const xml = this.generator.createFlowchart(args.steps); const filePath = this.saveToFile(args.filename, xml); return { content: [ { type: 'text', text: `Flowchart diagram created successfully and saved to: ${filePath}\n\nYou can open this file directly in Draw.io.`, }, ], }; } handleCreateSequenceDiagram(args) { const xml = this.generator.createSequenceDiagram(args.participants, args.interactions); const filePath = this.saveToFile(args.filename, xml); return { content: [ { type: 'text', text: `Sequence diagram created successfully and saved to: ${filePath}\n\nYou can open this file directly in Draw.io.`, }, ], }; } handleCreateNetworkDiagram(args) { const xml = this.generator.createNetworkDiagram(args.nodes, args.connections); const filePath = this.saveToFile(args.filename, xml); return { content: [ { type: 'text', text: `Network diagram created successfully and saved to: ${filePath}\n\nYou can open this file directly in Draw.io.`, }, ], }; } handleCreateCustomDiagram(args) { const elements = []; const shapeIds = {}; // Create shapes if (args.shapes) { for (const shape of args.shapes) { const element = this.generator.createShape( shape.label, shape.type, shape.x, shape.y, shape.width, shape.height ); elements.push(element); shapeIds[shape.id] = element.id; } } // Create connectors if (args.connectors) { for (const conn of args.connectors) { const sourceId = shapeIds[conn.from]; const targetId = shapeIds[conn.to]; if (sourceId && targetId) { const connector = this.generator.createConnector(sourceId, targetId, conn.label || ''); elements.push(connector); } } } const xml = this.generator.generateDiagram(elements); const filePath = this.saveToFile(args.filename, xml); return { content: [ { type: 'text', text: `Custom diagram created successfully and saved to: ${filePath}\n\nYou can open this file directly in Draw.io.`, }, ], }; } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Draw.io MCP Server running on stdio'); } } // Start the server const server = new DrawioMCPServer(); server.run().catch(console.error);

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thechandanbhagat/diagram-master'

If you have feedback or need assistance with the MCP directory API, please join our Discord server