mcp-ynab
Version:
Model Context Protocol server for YNAB integration
89 lines (71 loc) • 2.16 kB
JavaScript
import { writeFile, appendFile, existsSync, mkdirSync } from 'fs';
import { promisify } from 'util';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const writeFileAsync = promisify(writeFile);
const appendFileAsync = promisify(appendFile);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
class Logger {
constructor() {
this.logsDir = resolve(__dirname, '../../logs');
this.logFile = resolve(this.logsDir, 'mcp-debug.log');
// Don't check enabled in constructor - check at runtime
}
get enabled() {
// Check environment variables at runtime, not construction time
return process.env.NODE_ENV === 'development' || process.env.MCP_DEBUG === 'true';
}
ensureLogsDirectory() {
if (this.enabled && !existsSync(this.logsDir)) {
try {
mkdirSync(this.logsDir, { recursive: true });
} catch (error) {
// Silently fail to avoid breaking MCP protocol
}
}
}
async log(level, message, data = null) {
if (!this.enabled) return;
// Ensure logs directory exists
this.ensureLogsDirectory();
const timestamp = new Date().toISOString();
const logEntry = {
timestamp,
level,
message,
data,
pid: process.pid
};
const logLine = JSON.stringify(logEntry) + '\n';
try {
await appendFileAsync(this.logFile, logLine);
} catch (error) {
// Silently fail - don't break MCP protocol
}
}
async info(message, data) {
await this.log('INFO', message, data);
}
async error(message, data) {
await this.log('ERROR', message, data);
}
async debug(message, data) {
await this.log('DEBUG', message, data);
}
async warn(message, data) {
await this.log('WARN', message, data);
}
async startup(message, data) {
await this.log('STARTUP', message, data);
}
async tool(toolName, params, result) {
await this.log('TOOL', `Tool executed: ${toolName}`, {
tool: toolName,
params,
success: !result?.error,
resultSize: JSON.stringify(result).length
});
}
}
export default new Logger();