mirror of
https://github.com/penpot/penpot-mcp.git
synced 2026-04-25 03:08:19 +00:00
Enable file logging (writing to mcp-server/logs at info level by default)
This commit is contained in:
parent
f01774ab6b
commit
60acaec396
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@ dist
|
||||
*.orig
|
||||
temp
|
||||
*.tsbuildinfo
|
||||
|
||||
# Log files
|
||||
logs/
|
||||
*.log
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { PenpotMcpServer } from "./PenpotMcpServer";
|
||||
import { createLogger } from "./logger";
|
||||
import { createLogger, logFilePath } from "./logger";
|
||||
|
||||
/**
|
||||
* Entry point for Penpot MCP Server
|
||||
@ -10,18 +10,20 @@ import { createLogger } from "./logger";
|
||||
* gracefully and ensuring proper process termination.
|
||||
*
|
||||
* Usage:
|
||||
* - Default port: node dist/index.js (runs on 4401)
|
||||
* - Custom port: node dist/index.js --port <port>
|
||||
* - Help: node dist/index.js --help
|
||||
* - Default configuration: runs on port 4401, logs to mcp-server/logs at info level
|
||||
*/
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const logger = createLogger("main");
|
||||
try {
|
||||
// Parse command line arguments for port configuration
|
||||
const args = process.argv.slice(2);
|
||||
let port = 4401; // Default port
|
||||
|
||||
// log the file path early so it appears before any potential errors
|
||||
logger.info(`Logging to file: ${logFilePath}`);
|
||||
|
||||
try {
|
||||
const args = process.argv.slice(2);
|
||||
let port = 4401; // default port
|
||||
|
||||
// parse command line arguments
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === "--port" || args[i] === "-p") {
|
||||
if (i + 1 < args.length) {
|
||||
@ -32,10 +34,20 @@ async function main(): Promise<void> {
|
||||
logger.info("Invalid port number. Using default port 4401.");
|
||||
}
|
||||
}
|
||||
} else if (args[i] === "--log-level" || args[i] === "-l") {
|
||||
if (i + 1 < args.length) {
|
||||
process.env.LOG_LEVEL = args[i + 1];
|
||||
}
|
||||
} else if (args[i] === "--log-dir") {
|
||||
if (i + 1 < args.length) {
|
||||
process.env.LOG_DIR = args[i + 1];
|
||||
}
|
||||
} else if (args[i] === "--help" || args[i] === "-h") {
|
||||
logger.info("Usage: node dist/index.js [options]");
|
||||
logger.info("Options:");
|
||||
logger.info(" --port, -p <number> Port number for the HTTP/SSE server (default: 4401)");
|
||||
logger.info(" --log-level, -l <level> Log level: trace, debug, info, warn, error (default: info)");
|
||||
logger.info(" --log-dir <path> Directory for log files (default: mcp-server/logs)");
|
||||
logger.info(" --help, -h Show this help message");
|
||||
process.exit(0);
|
||||
}
|
||||
@ -44,7 +56,7 @@ async function main(): Promise<void> {
|
||||
const server = new PenpotMcpServer(port);
|
||||
await server.start();
|
||||
|
||||
// Keep the process alive
|
||||
// keep the process alive
|
||||
process.on("SIGINT", async () => {
|
||||
logger.info("Received SIGINT, shutting down gracefully...");
|
||||
await server.stop();
|
||||
|
||||
@ -1,27 +1,71 @@
|
||||
import pino from "pino";
|
||||
import { join, resolve } from "path";
|
||||
|
||||
/**
|
||||
* Logger instance configured for console output with metadata.
|
||||
* Configuration for log file location and level.
|
||||
*/
|
||||
const LOG_DIR = process.env.LOG_DIR || "logs";
|
||||
const LOG_LEVEL = process.env.LOG_LEVEL || "info";
|
||||
|
||||
/**
|
||||
* Generates a timestamped log file name.
|
||||
*
|
||||
* Configured to output to console only with level, full timestamp, origin, and message.
|
||||
* @returns Log file name
|
||||
*/
|
||||
function generateLogFileName(): string {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(now.getDate()).padStart(2, "0");
|
||||
const hours = String(now.getHours()).padStart(2, "0");
|
||||
const minutes = String(now.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(now.getSeconds()).padStart(2, "0");
|
||||
return `penpot-mcp-${year}${month}${day}-${hours}${minutes}${seconds}.log`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute path to the log file being written.
|
||||
*/
|
||||
export const logFilePath = resolve(join(LOG_DIR, generateLogFileName()));
|
||||
|
||||
/**
|
||||
* Logger instance configured for both console and file output with metadata.
|
||||
*
|
||||
* Both console and file output use pretty formatting for human readability.
|
||||
* Console output includes colors, while file output is plain text.
|
||||
*/
|
||||
export const logger = pino({
|
||||
level: "info",
|
||||
level: LOG_LEVEL,
|
||||
timestamp: pino.stdTimeFunctions.isoTime,
|
||||
formatters: {
|
||||
level: (label) => {
|
||||
return { level: label };
|
||||
},
|
||||
},
|
||||
transport: {
|
||||
target: "pino-pretty",
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l",
|
||||
ignore: "pid,hostname",
|
||||
messageFormat: "{msg}",
|
||||
levelFirst: true,
|
||||
},
|
||||
targets: [
|
||||
{
|
||||
// console transport with pretty formatting
|
||||
target: "pino-pretty",
|
||||
level: LOG_LEVEL,
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l",
|
||||
ignore: "pid,hostname",
|
||||
messageFormat: "{msg}",
|
||||
levelFirst: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// file transport with pretty formatting (same as console)
|
||||
target: "pino-pretty",
|
||||
level: LOG_LEVEL,
|
||||
options: {
|
||||
destination: logFilePath,
|
||||
colorize: false,
|
||||
translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l",
|
||||
ignore: "pid,hostname",
|
||||
messageFormat: "{msg}",
|
||||
levelFirst: true,
|
||||
mkdir: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user