diff --git a/server.mjs b/server.mjs index b5835a7..31186d9 100644 --- a/server.mjs +++ b/server.mjs @@ -50,6 +50,25 @@ if (!MCP_TOKEN) { const PORT = Number(process.env.PORT || 8935); const OUTPUT_DIR = process.env.IMAGE_MCP_OUTPUT_DIR || '/app/generated-images'; +// ---------- In-memory circular log buffer (for /logs debug endpoint) ---------- +const LOG_MAX = 500; +const logBuffer = []; +function writeLog(msg) { + logBuffer.push(msg); + if (logBuffer.length > LOG_MAX) logBuffer.shift(); + process.stderr.write(msg); +} +function readLogBuffer(n) { + return logBuffer.slice(-n).join(''); +} +// Override stderr.write to also capture to our buffer +const origStdErrWrite = process.stderr.write.bind(process.stderr); +process.stderr.write = (chunk, ...args) => { + logBuffer.push(String(chunk)); + if (logBuffer.length > LOG_MAX) logBuffer.shift(); + return origStdErrWrite(chunk, ...args); +}; + // ---------- Models that support transparent background ---------- // Recraft (v3 confirmed via OpenRouter /api/v1/images endpoint, accepts background param) // GPT-Image (1/2/5-image) via /chat/completions with image_config.background=transparent @@ -602,8 +621,8 @@ await mcpServer.connect(mcpTransport); const httpServer = http.createServer(async (req, res) => { const url = new URL(req.url, `http://${req.headers.host || 'localhost'}`); - // Auth gate — skip /health and /images/ - if (!url.pathname.startsWith('/health') && !url.pathname.startsWith('/images/')) { + // Auth gate — skip /health, /images/ and /logs + if (!url.pathname.startsWith('/health') && !url.pathname.startsWith('/images/') && !url.pathname.startsWith('/logs')) { const auth = req.headers.authorization || ''; const expected = `Bearer ${MCP_TOKEN}`; if (auth !== expected) { @@ -616,7 +635,7 @@ const httpServer = http.createServer(async (req, res) => { } } - // Lightweight /health for Coolify / Traefik probes +// Lightweight /health for Coolify / Traefik probes if (url.pathname === '/health') { res.statusCode = 200; res.setHeader('content-type', 'application/json'); @@ -624,6 +643,16 @@ const httpServer = http.createServer(async (req, res) => { return; } + // Recent logs viewer (no auth, for debugging Figma connections) + if (url.pathname === '/logs') { + const maxLines = parseInt(url.searchParams.get('n') || '50', 10); + const logLines = readLogBuffer(maxLines); + res.statusCode = 200; + res.setHeader('content-type', 'text/plain; charset=utf-8'); + res.end(logLines); + return; + } + process.stderr.write(`[HTTP] ${req.method} ${url.pathname} -> incoming\n`); try {