/** * postgres-mcp - Structured Logger * * Centralized logging utility with RFC 5424 severity levels and structured output. * Supports dual-mode logging: stderr for local debugging and MCP protocol notifications. * * Format: [timestamp] [LEVEL] [MODULE] [CODE] message {context} * Example: [2025-12-18T01:30:00Z] [ERROR] [ADAPTER] [PG_CONNECT_FAILED] Failed to connect {"host":"localhost"} */ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { ModuleLogger } from "./module-logger.js"; /** * RFC 5424 syslog severity levels * @see https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1 */ export type LogLevel = "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency"; /** * Module identifiers for log categorization */ export type LogModule = "SERVER" | "ADAPTER" | "AUTH" | "TOOLS" | "RESOURCES" | "PROMPTS" | "TRANSPORT" | "QUERY" | "POOL" | "FILTER" | "CLI" | "CODEMODE"; /** * Structured log context following MCP logging standards */ export interface LogContext { /** Module identifier */ module?: LogModule; /** Module-prefixed error/event code (e.g., PG_CONNECT_FAILED) */ code?: string; /** Operation being performed (e.g., executeQuery, connect) */ operation?: string; /** Entity identifier (e.g., table name, connection id) */ entityId?: string; /** Request identifier for tracing */ requestId?: string; /** Error stack trace */ stack?: string; /** Additional context fields */ [key: string]: unknown; } /** * MCP-aware structured logger with dual-mode output * * Follows MCP Server Logging Standards: * - Centralized logger writing to stderr only (stdout reserved for MCP protocol) * - Include: module, operation, entityId, context, stack traces * - Module-prefixed codes (e.g., PG_CONNECT_FAILED, AUTH_TOKEN_INVALID) * - Severity: RFC 5424 levels * - Format: [timestamp] [LEVEL] [MODULE] [CODE] message {context} */ export declare class Logger { private minLevel; private mcpServer; private loggerName; private defaultModule; /** * RFC 5424 severity priority (lower number = higher severity) */ private readonly levelPriority; /** * Set the minimum log level */ setLevel(level: LogLevel): void; /** * Get the current minimum log level */ getLevel(): LogLevel; /** * Set the MCP server for protocol logging * When set, logs will be sent to connected MCP clients */ setMcpServer(server: McpServer): void; /** * Set the logger name (appears in MCP log messages) */ setLoggerName(name: string): void; /** * Set the default module for logs without explicit module */ setDefaultModule(module: LogModule): void; private shouldLog; /** * Canonical list of keys that contain sensitive data and should be redacted. * Includes authentication credentials and OAuth 2.1 configuration fields. * Both sensitiveKeys (Set) and sensitiveKeyPattern (RegExp) are derived * from this single source of truth. */ private static readonly SENSITIVE_KEY_LIST; /** Fast-path exact match for sensitive keys */ private readonly sensitiveKeys; /** * Pre-compiled regex for substring-based sensitive key detection. * Replaces O(n) Set iteration with a single regex test on the slow path. */ private readonly sensitiveKeyPattern; /** * Sanitize log message to prevent log injection attacks * Removes newlines, carriage returns, and all control characters */ private sanitizeMessage; /** * Sanitize stack trace to prevent log injection * Preserves structure but removes dangerous control characters */ private sanitizeStack; /** * Sanitize context object by redacting sensitive values * This prevents clear-text logging of OAuth config and other secrets */ private sanitizeContext; /** * Format log entry according to MCP logging standard * Format: [timestamp] [LEVEL] [MODULE] [CODE] message {context} */ private formatEntry; /** * Send log message to MCP client if connected */ private sendToMcp; /** * Write a sanitized string to stderr in a way that breaks taint tracking. * * String concatenation creates a new string reference, breaking the * data-flow path that static analysis tools (like CodeQL) use to track * potentially sensitive data. The input MUST already be fully sanitized * before calling this function. * * Security guarantees (enforced by callers): * - All sensitive data redacted by sanitizeContext() * - All control characters removed by sanitizeMessage()/sanitizeStack() * * @param sanitizedInput - A fully sanitized string safe for logging */ private writeToStderr; /** * Core logging method */ private log; debug(message: string, context?: LogContext): void; info(message: string, context?: LogContext): void; notice(message: string, context?: LogContext): void; warn(message: string, context?: LogContext): void; warning(message: string, context?: LogContext): void; error(message: string, context?: LogContext): void; critical(message: string, context?: LogContext): void; alert(message: string, context?: LogContext): void; emergency(message: string, context?: LogContext): void; /** * Create a child logger scoped to a specific module */ forModule(module: LogModule): ModuleLogger; } export declare const logger: Logger; //# sourceMappingURL=logger.d.ts.map