UNPKG

drawio-mcp-server

Version:

Provides Draw.io services to MCP Clients

180 lines (179 loc) 5.61 kB
/** * Default configuration values */ const DEFAULT_CONFIG = { extensionPort: 3333, httpPort: 3000, transports: ["stdio"], }; /** * Valid port range */ const PORT_RANGE = { min: 1, max: 65535, }; /** * Parse extension port value from string - pure function */ export const parseExtensionPortValue = (value) => { if (!value) { return new Error("--extension-port flag requires a port number"); } const port = parseInt(value, 10); if (isNaN(port)) { return new Error(`Invalid port number "${value}". Port must be a number`); } if (port < PORT_RANGE.min || port > PORT_RANGE.max) { return new Error(`Invalid port number "${value}". Port must be between ${PORT_RANGE.min} and ${PORT_RANGE.max}`); } return port; }; /** * Parse http port value from string - pure function */ export const parseHttpPortValue = (value) => { if (!value) { return new Error("--http-port flag requires a port number"); } const port = parseInt(value, 10); if (isNaN(port)) { return new Error(`Invalid port number "${value}". Port must be a number`); } if (port < PORT_RANGE.min || port > PORT_RANGE.max) { return new Error(`Invalid port number "${value}". Port must be between ${PORT_RANGE.min} and ${PORT_RANGE.max}`); } return port; }; export const parseTransports = (values) => { if (!values || values.length === 0) { return DEFAULT_CONFIG.transports; } const normalized = values .flatMap((value) => value.split(",")) .map((value) => value.trim().toLowerCase()) .filter((value) => value.length > 0); if (normalized.length === 0) { return new Error("At least one transport must be specified"); } const validTransports = []; for (const value of normalized) { if (value === "stdio" || value === "http") { validTransports.push(value); } else { return new Error(`Invalid transport "${value}". Supported transports: stdio, http`); } } // Remove duplicates while preserving order return Array.from(new Set(validTransports)); }; /** * Find argument value by flag name - pure function */ export const findArgValue = (args, ...flags) => { const index = args.findIndex((arg) => flags.includes(arg)); return index !== -1 ? args[index + 1] : undefined; }; /** * Check if any flag exists in arguments - pure function */ export const hasFlag = (args, ...flags) => { return args.some((arg) => flags.includes(arg)); }; /** * Check if help was requested - pure function */ export const shouldShowHelp = (args) => { return hasFlag(args, "--help", "-h"); }; /** * Parse command line arguments into configuration object * Pure function - no side effects, deterministic output */ export const parseConfig = (args) => { // Walk arguments so repeated flags allow "last wins" semantics let portValue; let httpPortValue; let parsedHttpPort; let transportValues; for (let i = 0; i < args.length; i += 1) { const arg = args[i]; if (arg === "--extension-port" || arg === "-p") { const nextValue = args[i + 1]; if (nextValue === undefined) { return new Error("--extension-port flag requires a port number"); } portValue = nextValue; i += 1; // Skip the value we just consumed } else if (arg === "--http-port") { const nextValue = args[i + 1]; if (nextValue === undefined) { return new Error("--http-port flag requires a port number"); } httpPortValue = nextValue; i += 1; } else if (arg === "--transport") { const nextValue = args[i + 1]; if (nextValue === undefined) { return new Error("--transport flag requires a transport name"); } transportValues = [nextValue]; i += 1; } } if (httpPortValue !== undefined) { const httpPort = parseHttpPortValue(httpPortValue); if (httpPort instanceof Error) { return httpPort; } parsedHttpPort = httpPort; } if (portValue !== undefined) { const extensionPort = parseExtensionPortValue(portValue); if (extensionPort instanceof Error) { return extensionPort; } const transports = parseTransports(transportValues); if (transports instanceof Error) { return transports; } return { ...DEFAULT_CONFIG, extensionPort, httpPort: parsedHttpPort !== undefined ? parsedHttpPort : DEFAULT_CONFIG.httpPort, transports, }; } if (httpPortValue !== undefined) { const transports = parseTransports(transportValues); if (transports instanceof Error) { return transports; } return { ...DEFAULT_CONFIG, httpPort: parsedHttpPort, transports, }; } const transports = parseTransports(transportValues); if (transports instanceof Error) { return transports; } // Return default configuration return { ...DEFAULT_CONFIG, transports, }; }; /** * Build configuration from process.argv * This is the main entry point for configuration * Returns Error for invalid config, or ServerConfig */ export const buildConfig = () => { const args = process.argv.slice(2); return parseConfig(args); };