Skip to main content
Glama
logger.ts2.79 kB
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js'; import { config, type LogLevel } from '../config/env.js'; /** * Structured log data */ interface LogData { message: string; [key: string]: unknown; } /** * Logger that outputs to stderr and optionally sends MCP log notifications. * * Note: stdout is reserved for MCP protocol messages, so all logs go to stderr. */ class Logger { private server?: McpServer; private readonly levelPriority: Record<LogLevel, number> = { debug: 0, info: 1, warning: 2, error: 3, }; /** * Set the MCP server instance to enable sending log notifications to the client. */ setServer(server: McpServer): void { this.server = server; } private shouldLog(level: LogLevel): boolean { return this.levelPriority[level] >= this.levelPriority[config.LOG_LEVEL]; } private formatLog(level: LogLevel, logger: string, data: LogData): string { const timestamp = new Date().toISOString(); const { message, ...rest } = data; const extra = Object.keys(rest).length > 0 ? ` ${JSON.stringify(rest)}` : ''; return `[${timestamp}] [${level.toUpperCase()}] [${logger}] ${message}${extra}`; } private log(level: LogLevel, loggerName: string, data: LogData): void { if (!this.shouldLog(level)) return; // Always log to stderr (stdout is for MCP protocol) const formatted = this.formatLog(level, loggerName, data); console.error(formatted); // Also send to MCP client if connected this.sendMcpLog(level, loggerName, data); } private sendMcpLog(level: LogLevel, loggerName: string, data: LogData): void { if (!this.server) return; const mcpLevel = this.toMcpLevel(level); // Fire and forget - don't await to avoid blocking this.server.server .sendLoggingMessage({ level: mcpLevel, logger: loggerName, data, }) .catch(() => { // Ignore errors from logging - we don't want logging to crash the server }); } private toMcpLevel(level: LogLevel): LoggingLevel { switch (level) { case 'debug': return 'debug'; case 'info': return 'info'; case 'warning': return 'warning'; case 'error': return 'error'; } } debug(logger: string, data: LogData): void { this.log('debug', logger, data); } info(logger: string, data: LogData): void { this.log('info', logger, data); } warning(logger: string, data: LogData): void { this.log('warning', logger, data); } error(logger: string, data: LogData): void { this.log('error', logger, data); } } /** Global logger instance */ export const logger = new Logger();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/iceener/files-stdio-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server