Skip to main content
Glama

@pulumi/mcp-server

Official
by pulumi
sessionManager.ts4.63 kB
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { randomUUID } from 'node:crypto'; import { logger } from '../../logging/logging.js'; import { createServer, Server } from '../server.js'; import { SESSION_CONFIG } from './config.js'; /** * Represents an active MCP session with its associated transport and server. * Each session is tied to a specific origin for security. */ export interface MCPSession { /** Unique session identifier */ id: string; /** HTTP transport for this session */ transport: StreamableHTTPServerTransport; /** MCP server instance for this session */ server: Server; /** Last activity timestamp for cleanup purposes */ lastActivity: number; /** Origin that created this session (for security validation) */ origin?: string; } /** * Manages MCP sessions for HTTP transport. * Handles session creation, cleanup, and lifecycle management. */ export class SessionManager { private sessions = new Map<string, MCPSession>(); private cleanupTimer: NodeJS.Timeout | null = null; private config: typeof SESSION_CONFIG; constructor(config: typeof SESSION_CONFIG) { this.config = config; this.startCleanup(); } /** * Creates a new MCP session with associated transport and server. * Enforces session limits and associates the session with an origin. */ async createSession(origin?: string): Promise<MCPSession> { // Enforce maximum session limit if (this.sessions.size >= this.config.maxSessions) { logger.warn( `Maximum sessions (${this.config.maxSessions}) reached, cleaning up expired sessions` ); this.cleanup(); } // Generate unique session ID const id = randomUUID(); // Create MCP transport and server instances const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => id }); const server = createServer(); await server.connect(transport); // Auto-cleanup when transport closes transport.onclose = () => { this.sessions.delete(id); }; // Create and store the new session const session: MCPSession = { id, transport, server, lastActivity: Date.now(), origin }; this.sessions.set(session.id, session); return session; } /** * Gets a session and updates its activity time if validation passes. * Returns the session if validation passes, undefined otherwise. */ getAndUpdateSession(sessionId: string, requestOrigin?: string): MCPSession | undefined { const session = this.sessions.get(sessionId); if (!session) { return undefined; } // Security check: ensure request origin matches session origin if (session.origin !== requestOrigin) { return undefined; } // Update last activity time session.lastActivity = Date.now(); return session; } /** * Deletes a specific session by ID. * Performs cleanup and removes from session map. */ deleteSession(id: string): void { const session = this.sessions.get(id); if (session) { this.cleanupSession(session); this.sessions.delete(id); } } /** * Cleans up expired sessions based on their last activity. * Called periodically by the cleanup timer. */ cleanup(): void { const now = Date.now(); const expiredSessions = Array.from(this.sessions.entries()).filter( ([, session]) => now - session.lastActivity > this.config.sessionTimeout ); expiredSessions.forEach(([id, session]) => { this.cleanupSession(session); this.sessions.delete(id); }); } /** * Shuts down the session manager and cleans up all resources. * Stops the cleanup timer and closes all active sessions. */ destroy(): void { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = null; } // Cleanup all sessions Array.from(this.sessions.values()).forEach((session) => this.cleanupSession(session)); this.sessions.clear(); } /** * Cleans up a single session by closing its server. * Handles errors gracefully during cleanup. */ private cleanupSession(session: MCPSession): void { try { session.server.close(); } catch (error) { logger.warn(`Error cleaning up session ${session.id}:`, error); } } /** * Starts the periodic cleanup timer. * Runs session cleanup at configured intervals. */ private startCleanup(): void { this.cleanupTimer = setInterval(() => { this.cleanup(); }, this.config.cleanupInterval); } }

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/pulumi/mcp-server'

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