import { SessionState } from '../../../shared/models/session.model.js'; import type { Session } from './types.js'; /** * Enhanced MCP Session Manager with comprehensive persistence and lifecycle management. * * This service manages MCP sessions with full state persistence, automatic cleanup, * and graceful shutdown handling. It provides session isolation through unique * server and transport instances per session while maintaining shared resources * for efficiency. * * Key features include: * - Session state persistence to disk with individual session files and index * - Dirty tracking with 5-second batch flushing to minimize I/O operations * - Automatic cleanup of stale sessions based on configurable timeout (default 30 minutes) * - Graceful shutdown handling with SIGTERM/SIGINT signal capture * - Client metadata integration from client tracker service * - Environment variable controlled debugging (SESSION_DEBUG) * * Session storage structure: * ``` * ~/.mcp-hub-lite/ * └── sessions/ * ├── index.json # Session index file * └── {sessionId}.json # Individual session state files * ``` * * @example * ```typescript * const sessionManager = new McpSessionManager(); * const session = await sessionManager.getSession('my-session-id'); * // Use session.server and session.transport for MCP communication * ``` * * @since 1.0.0 */ export declare class McpSessionManager { private sessions; private sessionStates; private dirtySessions; private sessionsPath; private flushTimeout; private isInitialized; private get SESSION_TIMEOUT(); private get CLEANUP_INTERVAL(); constructor(); /** * Registers process shutdown handlers for graceful session cleanup. * * This method sets up event listeners for SIGTERM and SIGINT signals to ensure * that all dirty sessions are flushed to disk before the process terminates. * This prevents data loss during unexpected shutdowns or service restarts. * * The shutdown handler performs a final flush of all dirty sessions and * clears any pending flush timeouts to ensure clean termination. * * @returns {void} * * @example * ```typescript * // Called automatically in constructor * sessionManager.registerShutdownHandler(); * ``` */ private registerShutdownHandler; /** * Marks a session as dirty, indicating it needs to be persisted to disk. * * This method adds the session ID to the dirty sessions set and initiates * a delayed batch flush operation with a 5-second timeout. This optimization * prevents excessive I/O operations by batching multiple session updates * that occur in quick succession. * * When the SESSION_DEBUG environment variable is set, detailed logging * is enabled for debugging session persistence behavior. * * @param {string} sessionId - Unique identifier of the session to mark as dirty * @returns {void} * * @example * ```typescript * sessionManager.markAsDirty('my-session-id'); * // Session will be flushed to disk within 5 seconds * ``` */ private markAsDirty; /** * Loads the complete session store from disk, including all individual session files. * * This method reads the sessions index file and loads each individual session state * file, validating each session state against the SessionStateSchema. Invalid * session states are skipped with warning logs, ensuring robust recovery from * corrupted data. * * The method creates the sessions directory and index file if they don't exist, * providing a clean initialization path for first-time usage. * * @returns {Promise} Complete session store with all valid sessions * @throws {Error} If critical I/O operations fail (non-recoverable errors) * * @example * ```typescript * const store = await sessionManager.loadSessionStore(); * console.log(`Loaded ${Object.keys(store.sessions).length} sessions`); * ``` */ private loadSessionStore; /** * Saves the complete session store to disk, writing individual session files and index. * * This method persists all session states by writing individual JSON files for each * session and updating the sessions index file. The operation is atomic at the * file level, ensuring data integrity even if the process is interrupted. * * @param {SessionStore} store - Complete session store to persist * @returns {Promise} Resolves when all files are successfully written * @throws {Error} If any file write operations fail * * @example * ```typescript * await sessionManager.saveSessionStore(mySessionStore); * console.log('Session store saved successfully'); * ``` */ private saveSessionStore; /** * Restores all sessions from disk during service startup. * * This method is called automatically during initialization to recover session states * from persistent storage. It loads the session store, validates each session state, * and populates the in-memory session state cache. Invalid sessions are skipped * with warning logs to ensure robust startup even with corrupted data. * * The method ensures idempotent execution by checking the initialization flag, * preventing multiple restoration attempts. * * @returns {Promise} Resolves when all valid sessions are restored * * @example * ```typescript * await sessionManager.restoreSessions(); * console.log('Sessions restored from disk'); * ``` */ restoreSessions(): Promise; /** * Flushes all dirty sessions to disk in a single batch operation. * * This method collects all sessions marked as dirty, loads the current session store, * updates it with the dirty sessions, and saves the complete store back to disk. * This batch approach minimizes I/O operations and ensures data consistency. * * The method includes comprehensive error handling to prevent partial writes and * maintains detailed logging for debugging and monitoring purposes. * * @returns {Promise} Resolves when all dirty sessions are successfully flushed * * @example * ```typescript * await sessionManager.flushDirtySessions(); * console.log('All dirty sessions flushed to disk'); * ``` */ private flushDirtySessions; /** * Updates session metadata by retrieving client information from the client tracker service. * * This method fetches current client information including name, version, working directory, * and project context from the client tracker service and returns a partial session state * update object containing only the relevant metadata fields. * * @param {string} sessionId - Unique identifier of the session to update * @returns {Partial} Partial session state with updated client metadata * * @example * ```typescript * const metadata = sessionManager.updateSessionMetadataFromClient('my-session-id'); * console.log('Updated client metadata:', metadata); * ``` */ private updateSessionMetadataFromClient; /** * Creates or updates a session state with current metadata and timestamps. * * This method merges existing session state (if any) with current client metadata * from the client tracker service, updates access timestamps, and ensures proper * session state structure. The updated state is stored in memory and marked as dirty * for persistence. * * @param {string} sessionId - Unique identifier of the session to create or update * @returns {SessionState} Complete updated session state object * * @example * ```typescript * const state = sessionManager.upsertSessionState('my-session-id'); * console.log('Session state updated:', state); * ``` */ private upsertSessionState; /** * Updates session metadata explicitly with provided key-value pairs. * * This method merges the provided metadata object with existing session metadata, * updates the last accessed timestamp, and marks the session as dirty for persistence. * It's useful for storing custom session-specific information that needs to be persisted. * * @param {string} sessionId - Unique identifier of the session to update * @param {Record} metadata - Key-value pairs to merge into session metadata * @returns {Promise} Resolves when metadata is updated and marked for persistence * * @example * ```typescript * await sessionManager.updateSessionMetadata('my-session-id', { * userPreferences: { theme: 'dark' }, * lastProject: 'my-project' * }); * ``` */ updateSessionMetadata(sessionId: string, metadata: Record): Promise; /** * Retrieves an existing session or creates a new one if it doesn't exist. * * This method provides access to active sessions, creating new ones on demand with * proper initialization based on the requireInitialize parameter. It updates session * access timestamps and persists session state changes to ensure data consistency. * * The method includes optimization to prevent excessive timestamp updates for rapid * successive requests by only updating when at least 100ms have passed since the last access. * * @param {string} sessionId - Unique identifier of the session to retrieve or create * @param {boolean} [requireInitialize=true] - Whether to require MCP protocol initialization * @returns {Promise} Active session object with server and transport * * @example * ```typescript * // Get or create session with default initialization * const session = await sessionManager.getSession('my-session-id'); * * // Get or create session without requiring initialization (for restored sessions) * const restoredSession = await sessionManager.getSession('restored-session-id', false); * ``` */ getSession(sessionId: string, requireInitialize?: boolean): Promise; /** * Retrieves all persisted session states for API exposure. * * This method returns an array of all current session states, providing a complete * snapshot of all active sessions and their metadata. It's primarily used by the * web API to expose session information to clients. * * @returns {SessionState[]} Array of all current session states * * @example * ```typescript * const allStates = sessionManager.getAllSessionStates(); * console.log(`Total active sessions: ${allStates.length}`); * ``` */ getAllSessionStates(): SessionState[]; /** * Retrieves a specific session state by session ID for API exposure. * * This method returns the current state of a specific session or undefined if * the session doesn't exist. It's primarily used by the web API to provide * detailed information about individual sessions. * * @param {string} sessionId - Unique identifier of the session to retrieve * @returns {SessionState | undefined} Session state object or undefined if not found * * @example * ```typescript * const state = sessionManager.getSessionState('my-session-id'); * if (state) { * console.log('Session client:', state.clientName); * } * ``` */ getSessionState(sessionId: string): SessionState | undefined; /** * Checks if a session object exists in the active sessions map. * * @param sessionId - Unique identifier of the session to check * @returns {boolean} True if the session object exists, false otherwise */ hasSession(sessionId: string): boolean; /** * Deletes a session and removes it from persistent storage. * * This method gracefully closes the session's MCP server, removes it from memory, * and ensures it's removed from persistent storage by marking it as dirty and * performing an immediate flush. It returns true if the session existed and was deleted. * * @param {string} sessionId - Unique identifier of the session to delete * @returns {Promise} True if session existed and was deleted, false otherwise * * @example * ```typescript * const deleted = await sessionManager.deleteSession('my-session-id'); * if (deleted) { * console.log('Session deleted successfully'); * } * ``` */ deleteSession(sessionId: string): Promise; /** * Creates a new MCP session with proper initialization and transport setup. * * This method sets up a complete MCP session including server, transport, and * communication logging. It handles both fresh sessions and restored sessions, * with special logic for skipping initialization when appropriate. * * Key features: * - Creates StreamableHTTPServerTransport with custom session ID generation * - Sets up comprehensive message logging for debugging * - Handles restored sessions by manually initializing transport state * - Integrates with client tracker service for metadata * - Creates/updates session state and marks as dirty for persistence * * @param {string} sessionId - Unique identifier for the new session * @param {boolean} [requireInitialize=true] - Whether to require MCP protocol initialization * @returns {Promise} Newly created session object * @throws {Error} If session creation or connection fails * * @example * ```typescript * const session = await sessionManager.createSession('new-session-id'); * // Use session.server and session.transport for MCP communication * ``` */ private createSession; /** * Cleans up stale sessions based on the configured session timeout. * * This method is called periodically (every 60 seconds) to identify and close * sessions that haven't been accessed within the configured timeout period * (default 30 minutes). It gracefully closes MCP servers and removes sessions * from memory to prevent resource leaks. * * The method logs detailed information about cleaned sessions and maintains * active session count for monitoring purposes. * * @returns {void} * * @example * ```typescript * // Called automatically every 60 seconds * sessionManager.cleanup(); * ``` */ private cleanup; } export declare const mcpSessionManager: McpSessionManager; //# sourceMappingURL=session-manager.d.ts.map