ntfy-mcp-server
Version:
An MCP (Model Context Protocol) server designed to interact with the ntfy push notification service. It enables LLMs and AI agents to send notifications to your devices with extensive customization options.
93 lines (92 loc) • 3.54 kB
JavaScript
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import winston from "winston";
// Handle ESM module dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Resolve logs directory relative to project root (2 levels up from utils/)
const projectRoot = path.resolve(__dirname, '..', '..');
const logsDir = path.join(projectRoot, 'logs');
class Logger {
constructor() {
const logLevel = process.env.LOG_LEVEL || "info";
// Ensure logs directory exists
if (!fs.existsSync(logsDir)) {
fs.mkdirSync(logsDir, { recursive: true });
}
// Common format for all transports
const commonFormat = winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.printf(({ timestamp, level, message, context, stack }) => {
const contextStr = context ? `\n Context: ${JSON.stringify(context, null, 2)}` : "";
const stackStr = stack ? `\n Stack: ${stack}` : "";
return `[${timestamp}] ${level}: ${message}${contextStr}${stackStr}`;
}));
this.logger = winston.createLogger({
level: logLevel,
format: winston.format.json(),
transports: [
// Combined log file for all levels
new winston.transports.File({
filename: path.join(logsDir, 'combined.log'),
format: commonFormat
}),
// Separate log files for each level
new winston.transports.File({
filename: path.join(logsDir, 'error.log'),
level: 'error',
format: commonFormat
}),
new winston.transports.File({
filename: path.join(logsDir, 'warn.log'),
level: 'warn',
format: commonFormat
}),
new winston.transports.File({
filename: path.join(logsDir, 'info.log'),
level: 'info',
format: commonFormat
}),
new winston.transports.File({
filename: path.join(logsDir, 'debug.log'),
level: 'debug',
format: commonFormat
})
]
});
}
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
debug(message, context) {
this.logger.debug(message, { context });
}
info(message, context) {
this.logger.info(message, { context });
}
warn(message, context) {
this.logger.warn(message, { context });
}
error(message, context) {
this.logger.error(message, { context });
}
createChildLogger(metadata) {
return {
debug: (message, context) => {
this.debug(`[${metadata.module}] ${message}`, context);
},
info: (message, context) => {
this.info(`[${metadata.module}] ${message}`, context);
},
warn: (message, context) => {
this.warn(`[${metadata.module}] ${message}`, context);
},
error: (message, context) => {
this.error(`[${metadata.module}] ${message}`, context);
}
};
}
}
export const logger = Logger.getInstance();