/**
* ============================================================================
* 日志模块 - 用于 MCP 服务器调试
* ============================================================================
*
* 由于 MCP 服务器的 stdout 被协议占用,只能使用 stderr 输出日志。
* 但 stderr 在 Cursor 中不可见,所以我们同时将日志写入文件。
*
* 使用方法:
* import { log, logError } from './logger.js';
* log('普通日志');
* logError('错误日志');
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// 获取当前文件所在目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 日志文件路径
const LOG_FILE = path.join(__dirname, 'mcp-server.log');
// 是否启用文件日志(可以通过环境变量控制)
const ENABLE_FILE_LOG = process.env.MCP_DEBUG !== '0';
/**
* 获取当前时间戳字符串
*/
function getTimestamp() {
return new Date().toISOString();
}
/**
* 写入日志到文件
*/
function writeToFile(level, message) {
if (!ENABLE_FILE_LOG) return;
const logLine = `[${getTimestamp()}] [${level}] ${message}\n`;
try {
fs.appendFileSync(LOG_FILE, logLine);
} catch (err) {
// 文件写入失败时静默处理,避免影响主程序
}
}
/**
* 普通日志
* @param {...any} args - 日志内容
*/
export function log(...args) {
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
).join(' ');
// 输出到 stderr(MCP Inspector 可以看到)
console.error(`[INFO] ${message}`);
// 同时写入文件
writeToFile('INFO', message);
}
/**
* 错误日志
* @param {...any} args - 日志内容
*/
export function logError(...args) {
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
).join(' ');
console.error(`[ERROR] ${message}`);
writeToFile('ERROR', message);
}
/**
* 调试日志(仅在 MCP_DEBUG=1 时输出)
* @param {...any} args - 日志内容
*/
export function logDebug(...args) {
if (process.env.MCP_DEBUG !== '1') return;
const message = args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
).join(' ');
console.error(`[DEBUG] ${message}`);
writeToFile('DEBUG', message);
}
/**
* 清空日志文件
*/
export function clearLog() {
try {
fs.writeFileSync(LOG_FILE, '');
console.error('[INFO] 日志文件已清空');
} catch (err) {
console.error('[ERROR] 清空日志文件失败:', err.message);
}
}
// 启动时记录一条日志
log('日志模块已加载,日志文件:', LOG_FILE);