Skip to main content
Glama
ooples

MCP Console Automation Server

PSRemotingProtocol.ts29.7 kB
import { spawn, ChildProcess } from 'child_process'; import { BaseProtocol } from '../core/BaseProtocol.js'; import { ConsoleSession, SessionOptions, ConsoleType, ConsoleOutput, } from '../types/index.js'; import { ProtocolCapabilities, SessionState, ErrorContext, ProtocolHealthStatus, ErrorRecoveryResult, ResourceUsage, } from '../core/IProtocol.js'; // PowerShell Remoting Protocol connection options interface PSRemotingConnectionOptions extends SessionOptions { computerName: string; port?: number; useSSL?: boolean; applicationName?: string; configurationName?: string; sessionOption?: Record<string, any>; authentication?: | 'Default' | 'Basic' | 'Negotiate' | 'NegotiateWithImplicitCredential' | 'Credssp' | 'Digest' | 'Kerberos'; certificateThumbprint?: string; credential?: { username: string; password?: string; domain?: string; useSecureString?: boolean; }; sessionType?: 'Interactive' | 'RemoteSession' | 'InvokeBatch' | 'RunAsJob'; connectionUri?: string; allowRedirection?: boolean; sessionName?: string; idleTimeout?: number; maxIdleTimeout?: number; outputBufferingMode?: 'None' | 'Block' | 'Drop'; inputFormat?: 'Text' | 'XML'; outputFormat?: 'Text' | 'XML'; culture?: string; uiCulture?: string; sessionTimeout?: number; operationTimeout?: number; cancelTimeout?: number; enableNetworkAccess?: boolean; includePortInSPN?: boolean; skipCACheck?: boolean; skipCNCheck?: boolean; skipRevocationCheck?: boolean; noEncryption?: boolean; useUtf16?: boolean; maxConcurrentCommandsPerSession?: number; maxSessions?: number; maxSessionsPerShell?: number; maxMemoryPerShellMB?: number; maxProcessesPerShell?: number; maxShells?: number; maxShellsPerUser?: number; shellTimeoutMs?: number; executionPolicy?: | 'Restricted' | 'AllSigned' | 'RemoteSigned' | 'Unrestricted' | 'Bypass' | 'Undefined'; psVersion?: string; enableClr?: boolean; clrVersion?: string; apartmentState?: 'STA' | 'MTA' | 'Unknown'; threadOptions?: 'Default' | 'UseNewThread' | 'ReuseThread'; workingDirectory?: string; initialScript?: string; modulesToImport?: string[]; snapinsToAdd?: string[]; functionsToDefine?: Record<string, string>; variablesToDefine?: Record<string, any>; aliasesToDefine?: Record<string, string>; drivesToMap?: Record<string, string>; enableHistory?: boolean; historySize?: number; saveHistoryPath?: string; enableVerboseRecord?: boolean; enableErrorRecord?: boolean; enableProgressRecord?: boolean; enableDebugRecord?: boolean; enableInformationRecord?: boolean; enableWarningRecord?: boolean; jobName?: string; asJob?: boolean; throttleLimit?: number; hVArgs?: string[]; vmName?: string; vmId?: string; containerName?: string; containerId?: string; enableVMIntegration?: boolean; enableContainerIntegration?: boolean; runAsAdministrator?: boolean; windowStyle?: 'Normal' | 'Hidden' | 'Minimized' | 'Maximized'; verb?: 'runas' | 'open'; argumentList?: string[]; filePath?: string; scriptBlock?: string; loadProfile?: boolean; noProfile?: boolean; nonInteractive?: boolean; mta?: boolean; sta?: boolean; inputObject?: any; enableCustomPSHost?: boolean; customPSHostSettings?: Record<string, any>; remoteDebug?: boolean; stepInto?: boolean; breakAll?: boolean; enablePSReadLine?: boolean; psReadLineOptions?: Record<string, any>; enableLogging?: boolean; logLevel?: 'Critical' | 'Error' | 'Warning' | 'Informational' | 'Verbose'; logPath?: string; enableScriptBlockLogging?: boolean; enableModuleLogging?: boolean; enableTranscription?: boolean; transcriptionDirectory?: string; enablePowerShellDetection?: boolean; environment?: Record<string, string>; customPowerShellPath?: string; customFlags?: string[]; } /** * PowerShell Remoting Protocol Implementation * * Provides PowerShell Remoting capabilities for Windows and cross-platform systems * Supports comprehensive PowerShell Remoting functionality including Enter-PSSession, * New-PSSession, Invoke-Command, PowerShell jobs, WS-Management, SSH remoting, * and enterprise PowerShell administration features */ export class PSRemotingProtocol extends BaseProtocol { public readonly type: ConsoleType = 'psremoting'; public readonly capabilities: ProtocolCapabilities; private psremotingProcesses = new Map<string, ChildProcess>(); // Compatibility property for old ProtocolFactory interface public get healthStatus(): ProtocolHealthStatus { return { isHealthy: this.isInitialized, lastChecked: new Date(), errors: [], warnings: [], metrics: { activeSessions: this.sessions.size, totalSessions: this.sessions.size, averageLatency: 0, successRate: 100, uptime: 0, }, dependencies: {}, }; } constructor() { super('psremoting'); this.capabilities = { supportsStreaming: true, supportsFileTransfer: true, supportsX11Forwarding: false, supportsPortForwarding: false, supportsAuthentication: true, supportsEncryption: true, supportsCompression: true, supportsMultiplexing: true, supportsKeepAlive: true, supportsReconnection: true, supportsBinaryData: true, supportsCustomEnvironment: true, supportsWorkingDirectory: true, supportsSignals: true, supportsResizing: false, supportsPTY: false, maxConcurrentSessions: 32, // PowerShell Remoting can handle many concurrent sessions defaultTimeout: 300000, // PowerShell operations can take longer supportedEncodings: ['utf-8', 'utf-16le', 'ascii'], supportedAuthMethods: [ 'basic', 'negotiate', 'kerberos', 'credssp', 'digest', ], platformSupport: { windows: true, // Primary PowerShell Remoting platform linux: true, // PowerShell Core with SSH remoting macos: true, // PowerShell Core with SSH remoting freebsd: true, }, }; } async initialize(): Promise<void> { if (this.isInitialized) return; try { // Check if PowerShell is available await this.checkPowerShellAvailability(); this.isInitialized = true; this.logger.info( 'PowerShell Remoting protocol initialized with enterprise features' ); } catch (error: any) { this.logger.error( 'Failed to initialize PowerShell Remoting protocol', error ); throw error; } } async createSession(options: SessionOptions): Promise<ConsoleSession> { const sessionId = `psremoting-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`; return await this.createSessionWithTypeDetection(sessionId, options); } async dispose(): Promise<void> { await this.cleanup(); } async executeCommand( sessionId: string, command: string, args?: string[] ): Promise<void> { const fullCommand = args && args.length > 0 ? `${command} ${args.join(' ')}` : command; await this.sendInput(sessionId, fullCommand + '\r\n'); } async sendInput(sessionId: string, input: string): Promise<void> { const psremotingProcess = this.psremotingProcesses.get(sessionId); const session = this.sessions.get(sessionId); if (!psremotingProcess || !psremotingProcess.stdin || !session) { throw new Error(`No active PowerShell Remoting session: ${sessionId}`); } psremotingProcess.stdin.write(input); session.lastActivity = new Date(); this.emit('input-sent', { sessionId, input, timestamp: new Date(), }); this.logger.debug( `Sent input to PowerShell Remoting session ${sessionId}: ${input.substring(0, 100)}` ); } async closeSession(sessionId: string): Promise<void> { try { const psremotingProcess = this.psremotingProcesses.get(sessionId); if (psremotingProcess) { // Try graceful shutdown first psremotingProcess.kill('SIGTERM'); // Force kill after timeout setTimeout(() => { if (psremotingProcess && !psremotingProcess.killed) { psremotingProcess.kill('SIGKILL'); } }, 15000); this.psremotingProcesses.delete(sessionId); } // Clean up base protocol session this.sessions.delete(sessionId); this.logger.info(`PowerShell Remoting session ${sessionId} closed`); this.emit('session-closed', sessionId); } catch (error) { this.logger.error( `Error closing PowerShell Remoting session ${sessionId}:`, error ); throw error; } } async doCreateSession( sessionId: string, options: SessionOptions, sessionState: SessionState ): Promise<ConsoleSession> { if (!this.isInitialized) { await this.initialize(); } const psremotingOptions = options as PSRemotingConnectionOptions; // Validate required PowerShell Remoting parameters if (!psremotingOptions.computerName) { throw new Error( 'Computer name is required for PowerShell Remoting protocol' ); } // Build PowerShell Remoting command const psremotingCommand = this.buildPSRemotingCommand(psremotingOptions); // Spawn PowerShell Remoting process const psremotingProcess = spawn( psremotingCommand[0], psremotingCommand.slice(1), { stdio: ['pipe', 'pipe', 'pipe'], cwd: options.cwd || process.cwd(), env: { ...process.env, ...this.buildEnvironment(psremotingOptions), ...options.env, }, } ); // Set up output handling psremotingProcess.stdout?.on('data', (data) => { const output: ConsoleOutput = { sessionId, type: 'stdout', data: data.toString(), timestamp: new Date(), }; this.addToOutputBuffer(sessionId, output); }); psremotingProcess.stderr?.on('data', (data) => { const output: ConsoleOutput = { sessionId, type: 'stderr', data: data.toString(), timestamp: new Date(), }; this.addToOutputBuffer(sessionId, output); }); psremotingProcess.on('error', (error) => { this.logger.error( `PowerShell Remoting process error for session ${sessionId}:`, error ); this.emit('session-error', { sessionId, error }); }); psremotingProcess.on('close', (code) => { this.logger.info( `PowerShell Remoting process closed for session ${sessionId} with code ${code}` ); this.markSessionComplete(sessionId, code || 0); }); // Store the process this.psremotingProcesses.set(sessionId, psremotingProcess); // Create session object const session: ConsoleSession = { id: sessionId, command: psremotingCommand[0], args: psremotingCommand.slice(1), cwd: options.cwd || process.cwd(), env: { ...process.env, ...this.buildEnvironment(psremotingOptions), ...options.env, }, createdAt: new Date(), lastActivity: new Date(), status: 'running', type: this.type, streaming: options.streaming, executionState: 'idle', activeCommands: new Map(), pid: psremotingProcess.pid, }; this.sessions.set(sessionId, session); this.logger.info( `PowerShell Remoting session ${sessionId} created for computer ${psremotingOptions.computerName}` ); this.emit('session-created', { sessionId, type: 'psremoting', session }); return session; } // Override getOutput to satisfy old ProtocolFactory interface (returns string) async getOutput(sessionId: string, since?: Date): Promise<any> { const outputs = await super.getOutput(sessionId, since); return outputs.map((output) => output.data).join(''); } // Missing IProtocol methods for compatibility getAllSessions(): ConsoleSession[] { return Array.from(this.sessions.values()); } getActiveSessions(): ConsoleSession[] { return Array.from(this.sessions.values()).filter( (session) => session.status === 'running' ); } getSessionCount(): number { return this.sessions.size; } async getSessionState(sessionId: string): Promise<SessionState> { const session = this.sessions.get(sessionId); if (!session) { throw new Error(`Session ${sessionId} not found`); } return { sessionId, status: session.status, isOneShot: false, // PowerShell Remoting sessions are typically persistent isPersistent: true, createdAt: session.createdAt, lastActivity: session.lastActivity, pid: session.pid, metadata: {}, }; } async handleError( error: Error, context: ErrorContext ): Promise<ErrorRecoveryResult> { this.logger.error( `Error in PowerShell Remoting session ${context.sessionId}: ${error.message}` ); return { recovered: false, strategy: 'none', attempts: 0, duration: 0, error: error.message, }; } async recoverSession(sessionId: string): Promise<boolean> { const psremotingProcess = this.psremotingProcesses.get(sessionId); return (psremotingProcess && !psremotingProcess.killed) || false; } getResourceUsage(): ResourceUsage { const memUsage = process.memoryUsage(); const cpuUsage = process.cpuUsage(); return { memory: { used: memUsage.heapUsed, available: memUsage.heapTotal, peak: memUsage.heapTotal, }, cpu: { usage: cpuUsage.user + cpuUsage.system, load: [0, 0, 0], }, network: { bytesIn: 0, bytesOut: 0, connectionsActive: this.psremotingProcesses.size, }, storage: { bytesRead: 0, bytesWritten: 0, }, sessions: { active: this.sessions.size, total: this.sessions.size, peak: this.sessions.size, }, }; } async getHealthStatus(): Promise<ProtocolHealthStatus> { const baseStatus = await super.getHealthStatus(); try { await this.checkPowerShellAvailability(); return { ...baseStatus, dependencies: { powershell: { available: true }, }, }; } catch (error) { return { ...baseStatus, isHealthy: false, errors: [...baseStatus.errors, `PowerShell not available: ${error}`], dependencies: { powershell: { available: false }, }, }; } } private async checkPowerShellAvailability(): Promise<void> { return new Promise((resolve, reject) => { // Try PowerShell Core first, then Windows PowerShell const testProcess = spawn('pwsh', ['-Command', 'Get-Host'], { stdio: 'pipe', }); testProcess.on('close', (code) => { if (code === 0) { resolve(); } else { // Try Windows PowerShell const fallbackProcess = spawn( 'powershell', ['-Command', 'Get-Host'], { stdio: 'pipe' } ); fallbackProcess.on('close', (fallbackCode) => { if (fallbackCode === 0) { resolve(); } else { reject( new Error( 'PowerShell not found. Please install PowerShell Core or Windows PowerShell.' ) ); } }); fallbackProcess.on('error', () => { reject( new Error( 'PowerShell not found. Please install PowerShell Core or Windows PowerShell.' ) ); }); } }); testProcess.on('error', () => { // Try Windows PowerShell const fallbackProcess = spawn('powershell', ['-Command', 'Get-Host'], { stdio: 'pipe', }); fallbackProcess.on('close', (fallbackCode) => { if (fallbackCode === 0) { resolve(); } else { reject( new Error( 'PowerShell not found. Please install PowerShell Core or Windows PowerShell.' ) ); } }); fallbackProcess.on('error', () => { reject( new Error( 'PowerShell not found. Please install PowerShell Core or Windows PowerShell.' ) ); }); }); }); } private buildPSRemotingCommand( options: PSRemotingConnectionOptions ): string[] { const command = []; // PowerShell executable if (options.customPowerShellPath) { command.push(options.customPowerShellPath); } else { // Try PowerShell Core first, fallback to Windows PowerShell command.push(process.platform === 'win32' ? 'pwsh' : 'pwsh'); } // PowerShell execution policy if (options.executionPolicy) { command.push('-ExecutionPolicy', options.executionPolicy); } else { command.push('-ExecutionPolicy', 'Bypass'); } // Profile loading if (options.noProfile) { command.push('-NoProfile'); } if (options.loadProfile) { command.push('-LoadProfile'); } // Interactive mode if (options.nonInteractive) { command.push('-NonInteractive'); } // Apartment state if (options.mta) { command.push('-MTA'); } if (options.sta) { command.push('-STA'); } // PowerShell version if (options.psVersion) { command.push('-Version', options.psVersion); } // Working directory if (options.workingDirectory) { command.push('-WorkingDirectory', options.workingDirectory); } // Window style if (options.windowStyle) { command.push('-WindowStyle', options.windowStyle); } // Build PowerShell remoting command based on session type let psCommand = ''; if (options.sessionType === 'Interactive' || !options.sessionType) { // Enter-PSSession for interactive remoting psCommand = this.buildEnterPSSessionCommand(options); } else if (options.sessionType === 'RemoteSession') { // New-PSSession for persistent sessions psCommand = this.buildNewPSSessionCommand(options); } else if (options.sessionType === 'InvokeBatch') { // Invoke-Command for batch execution psCommand = this.buildInvokeCommand(options); } else if (options.sessionType === 'RunAsJob') { // Start-Job with Invoke-Command for background jobs psCommand = this.buildJobCommand(options); } command.push('-Command', psCommand); return command; } private buildEnterPSSessionCommand( options: PSRemotingConnectionOptions ): string { let cmd = 'Enter-PSSession'; // Computer name cmd += ` -ComputerName '${options.computerName}'`; // Connection settings if (options.port) { cmd += ` -Port ${options.port}`; } if (options.useSSL) { cmd += ' -UseSSL'; } if (options.applicationName) { cmd += ` -ApplicationName '${options.applicationName}'`; } if (options.configurationName) { cmd += ` -ConfigurationName '${options.configurationName}'`; } if (options.connectionUri) { cmd += ` -ConnectionUri '${options.connectionUri}'`; } // Authentication if (options.authentication) { cmd += ` -Authentication ${options.authentication}`; } if (options.certificateThumbprint) { cmd += ` -CertificateThumbprint '${options.certificateThumbprint}'`; } if (options.credential) { if (options.credential.useSecureString) { cmd += ` -Credential (Get-Credential -UserName '${options.credential.username}' -Message 'Enter credentials')`; } else { cmd += ` -Credential (New-Object System.Management.Automation.PSCredential('${options.credential.username}', (ConvertTo-SecureString '${options.credential.password}' -AsPlainText -Force)))`; } } // Session options if (options.sessionName) { cmd += ` -Name '${options.sessionName}'`; } if (options.enableNetworkAccess) { cmd += ' -EnableNetworkAccess'; } // SSL options if (options.skipCACheck) { cmd += ' -SessionOption (New-PSSessionOption -SkipCACheck)'; } if (options.skipCNCheck) { cmd += ' -SessionOption (New-PSSessionOption -SkipCNCheck)'; } if (options.skipRevocationCheck) { cmd += ' -SessionOption (New-PSSessionOption -SkipRevocationCheck)'; } if (options.noEncryption) { cmd += ' -SessionOption (New-PSSessionOption -NoEncryption)'; } return cmd; } private buildNewPSSessionCommand( options: PSRemotingConnectionOptions ): string { let cmd = '$session = New-PSSession'; // Computer name cmd += ` -ComputerName '${options.computerName}'`; // Add all the same parameters as Enter-PSSession if (options.port) { cmd += ` -Port ${options.port}`; } if (options.useSSL) { cmd += ' -UseSSL'; } if (options.applicationName) { cmd += ` -ApplicationName '${options.applicationName}'`; } if (options.configurationName) { cmd += ` -ConfigurationName '${options.configurationName}'`; } if (options.authentication) { cmd += ` -Authentication ${options.authentication}`; } if (options.credential) { if (options.credential.useSecureString) { cmd += ` -Credential (Get-Credential -UserName '${options.credential.username}' -Message 'Enter credentials')`; } else { cmd += ` -Credential (New-Object System.Management.Automation.PSCredential('${options.credential.username}', (ConvertTo-SecureString '${options.credential.password}' -AsPlainText -Force)))`; } } if (options.sessionName) { cmd += ` -Name '${options.sessionName}'`; } if (options.throttleLimit) { cmd += ` -ThrottleLimit ${options.throttleLimit}`; } // Add session to variable and then enter it cmd += '; Enter-PSSession -Session $session'; return cmd; } private buildInvokeCommand(options: PSRemotingConnectionOptions): string { let cmd = 'Invoke-Command'; // Computer name cmd += ` -ComputerName '${options.computerName}'`; // Script block or file if (options.scriptBlock) { cmd += ` -ScriptBlock { ${options.scriptBlock} }`; } else if (options.filePath) { cmd += ` -FilePath '${options.filePath}'`; } else if (options.command) { cmd += ` -ScriptBlock { ${options.command} }`; } // Authentication and connection parameters if (options.credential) { if (options.credential.useSecureString) { cmd += ` -Credential (Get-Credential -UserName '${options.credential.username}' -Message 'Enter credentials')`; } else { cmd += ` -Credential (New-Object System.Management.Automation.PSCredential('${options.credential.username}', (ConvertTo-SecureString '${options.credential.password}' -AsPlainText -Force)))`; } } if (options.authentication) { cmd += ` -Authentication ${options.authentication}`; } if (options.port) { cmd += ` -Port ${options.port}`; } if (options.useSSL) { cmd += ' -UseSSL'; } if (options.configurationName) { cmd += ` -ConfigurationName '${options.configurationName}'`; } if (options.inputObject) { cmd += ` -InputObject $inputObject`; } if (options.argumentList && options.argumentList.length > 0) { cmd += ` -ArgumentList ${options.argumentList.map((arg) => `'${arg}'`).join(', ')}`; } if (options.enableNetworkAccess) { cmd += ' -EnableNetworkAccess'; } if (options.asJob) { cmd += ' -AsJob'; if (options.jobName) { cmd += ` -JobName '${options.jobName}'`; } } if (options.throttleLimit) { cmd += ` -ThrottleLimit ${options.throttleLimit}`; } return cmd; } private buildJobCommand(options: PSRemotingConnectionOptions): string { let cmd = 'Start-Job -ScriptBlock {'; // Add Invoke-Command inside the job cmd += ` Invoke-Command -ComputerName '${options.computerName}'`; if (options.scriptBlock) { cmd += ` -ScriptBlock { ${options.scriptBlock} }`; } else if (options.filePath) { cmd += ` -FilePath '${options.filePath}'`; } else if (options.command) { cmd += ` -ScriptBlock { ${options.command} }`; } if (options.credential) { if (options.credential.useSecureString) { cmd += ` -Credential (Get-Credential -UserName '${options.credential.username}' -Message 'Enter credentials')`; } else { cmd += ` -Credential (New-Object System.Management.Automation.PSCredential('${options.credential.username}', (ConvertTo-SecureString '${options.credential.password}' -AsPlainText -Force)))`; } } cmd += ' }'; if (options.jobName) { cmd += ` -Name '${options.jobName}'`; } return cmd; } private buildEnvironment( options: PSRemotingConnectionOptions ): Record<string, string> { const env: Record<string, string> = {}; // PowerShell environment variables if (options.psVersion) { env.POWERSHELL_VERSION = options.psVersion; } if (options.executionPolicy) { env.POWERSHELL_EXECUTION_POLICY = options.executionPolicy; } // Remoting settings if (options.sessionTimeout) { env.PSREMOTING_SESSION_TIMEOUT = options.sessionTimeout.toString(); } if (options.operationTimeout) { env.PSREMOTING_OPERATION_TIMEOUT = options.operationTimeout.toString(); } if (options.maxSessions) { env.PSREMOTING_MAX_SESSIONS = options.maxSessions.toString(); } if (options.maxMemoryPerShellMB) { env.PSREMOTING_MAX_MEMORY_PER_SHELL = options.maxMemoryPerShellMB.toString(); } // Culture settings if (options.culture) { env.LC_ALL = options.culture; } if (options.uiCulture) { env.POWERSHELL_UI_CULTURE = options.uiCulture; } // Logging settings if (options.enableLogging) { env.PSREMOTING_ENABLE_LOGGING = '1'; if (options.logLevel) { env.PSREMOTING_LOG_LEVEL = options.logLevel; } if (options.logPath) { env.PSREMOTING_LOG_PATH = options.logPath; } } if (options.enableScriptBlockLogging) { env.PSREMOTING_SCRIPT_BLOCK_LOGGING = '1'; } if (options.enableTranscription) { env.PSREMOTING_TRANSCRIPTION = '1'; if (options.transcriptionDirectory) { env.PSREMOTING_TRANSCRIPTION_DIR = options.transcriptionDirectory; } } // History settings if (options.enableHistory) { env.PSREMOTING_ENABLE_HISTORY = '1'; if (options.historySize) { env.PSREMOTING_HISTORY_SIZE = options.historySize.toString(); } if (options.saveHistoryPath) { env.PSREMOTING_HISTORY_PATH = options.saveHistoryPath; } } // Module and snapin settings if (options.modulesToImport && options.modulesToImport.length > 0) { env.PSREMOTING_MODULES = options.modulesToImport.join(';'); } if (options.snapinsToAdd && options.snapinsToAdd.length > 0) { env.PSREMOTING_SNAPINS = options.snapinsToAdd.join(';'); } // CLR settings if (options.enableClr) { env.PSREMOTING_CLR_ENABLED = '1'; if (options.clrVersion) { env.PSREMOTING_CLR_VERSION = options.clrVersion; } } // Debug and development settings if (options.remoteDebug) { env.PSREMOTING_REMOTE_DEBUG = '1'; } if (options.enablePSReadLine) { env.PSREMOTING_PSREADLINE = '1'; } if (options.enableVerboseRecord) { env.PSREMOTING_VERBOSE_RECORD = '1'; } if (options.enableErrorRecord) { env.PSREMOTING_ERROR_RECORD = '1'; } if (options.enableProgressRecord) { env.PSREMOTING_PROGRESS_RECORD = '1'; } if (options.enableDebugRecord) { env.PSREMOTING_DEBUG_RECORD = '1'; } if (options.enableInformationRecord) { env.PSREMOTING_INFORMATION_RECORD = '1'; } if (options.enableWarningRecord) { env.PSREMOTING_WARNING_RECORD = '1'; } // Hyper-V and Container integration if (options.enableVMIntegration && options.vmName) { env.PSREMOTING_VM_NAME = options.vmName; } if (options.enableVMIntegration && options.vmId) { env.PSREMOTING_VM_ID = options.vmId; } if (options.enableContainerIntegration && options.containerName) { env.PSREMOTING_CONTAINER_NAME = options.containerName; } if (options.enableContainerIntegration && options.containerId) { env.PSREMOTING_CONTAINER_ID = options.containerId; } // Custom environment variables if (options.environment) { Object.assign(env, options.environment); } return env; } async cleanup(): Promise<void> { this.logger.info('Cleaning up PowerShell Remoting protocol'); // Close all PowerShell Remoting processes for (const [sessionId, process] of Array.from(this.psremotingProcesses)) { try { process.kill(); } catch (error) { this.logger.error( `Error killing PowerShell Remoting process for session ${sessionId}:`, error ); } } // Clear all data this.psremotingProcesses.clear(); // Call parent cleanup await super.cleanup(); } } export default PSRemotingProtocol;

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/ooples/mcp-console-automation'

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