UNPKG

drawio-mcp-server

Version:

Provides Draw.io services to MCP Clients

117 lines (116 loc) 4.06 kB
import { z } from "zod"; // Log levels (lower is more severe) const LogLevelMap = { emergency: 0, alert: 1, critical: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7, }; export const validLogLevels = Object.keys(LogLevelMap); // Define the request schema for setLevels const SetLevelsRequestSchema = z.object({ method: z.literal("logging/setLevels"), params: z.object({ levels: z.record(z.string(), z.enum(validLogLevels).nullable()), }), }); // Define the request schema for setLevel const SetLevelRequestSchema = z.object({ method: z.literal("logging/setLevel"), params: z.object({ level: z.enum(validLogLevels), }), }); // Per-logger log levels (default is root `"."`) let logLevels = { ".": LogLevelMap.info, // Start with info level }; // Helper: Effective log level for a logger const getEffectiveLogLevel = (loggerName) => { return loggerName in logLevels ? logLevels[loggerName] : (logLevels["."] ?? LogLevelMap.info); }; // Helper: Should we log at this level? const shouldLog = (level, loggerName) => { const numericLevel = LogLevelMap[level]; const effectiveLevel = getEffectiveLogLevel(loggerName); return numericLevel <= effectiveLevel; }; // Helper: Actually send a log if allowed const log = (server) => (level, loggerName, data) => { if (!(level in LogLevelMap)) { console.error(`Internal Error: Invalid log level used: ${level}`); return; } if (shouldLog(level, loggerName)) { server.server.sendLoggingMessage({ level, logger: loggerName, data, }); } }; export function create_logger(server) { const log3 = log(server); // 2. Register handler for logging/setLevels (only override requested loggers) server.server.setRequestHandler(SetLevelsRequestSchema, async (request) => { const newLevels = request.params.levels; // Only update logLevels for specified keys; unset any set to null for (const loggerName in newLevels) { if (Object.prototype.hasOwnProperty.call(newLevels, loggerName)) { const levelName = newLevels[loggerName]; if (levelName === null) { if (loggerName !== ".") { delete logLevels[loggerName]; // Remove override log3("debug", "logging", { message: `Reset log level for logger: ${loggerName}`, }); } } else if (levelName && validLogLevels.includes(levelName)) { logLevels[loggerName] = LogLevelMap[levelName]; log3("debug", "logging", { message: `Set log level for logger '${loggerName}' to '${levelName}'`, }); } else { log3("warning", "logging", { message: `Invalid log level '${levelName}' received for logger '${loggerName}'`, }); } } } return {}; }); // Register handler for logging/setLevel (sets root logger level) server.server.setRequestHandler(SetLevelRequestSchema, async (request) => { const log3 = log(server); const levelName = request.params.level; if (validLogLevels.includes(levelName)) { logLevels["."] = LogLevelMap[levelName]; log3("debug", "logging", { message: `Set root log level to '${levelName}'`, }); } else { log3("warning", "logging", { message: `Invalid log level '${levelName}' received`, }); } return {}; }); return { log: (level, message, ...data) => { log3(level, ".", { message, data }); }, debug: (message, ...data) => { log3("debug", ".", { message, data }); }, }; }