Skip to main content
Glama
ooples

MCP Console Automation Server

winrm.md44.4 kB
# WinRM (Windows Remote Management) Protocol ## Overview The WinRM Protocol enables AI assistants to remotely manage Windows systems, execute PowerShell commands, and automate Windows infrastructure tasks through Windows Remote Management services via the MCP Console Automation server. ## Features - **Remote PowerShell**: Execute PowerShell commands and scripts remotely - **Service Management**: Start, stop, and configure Windows services - **Registry Operations**: Read and modify Windows registry - **File Operations**: Remote file management and transfers - **Event Log Access**: Query and monitor Windows event logs - **Performance Monitoring**: Collect performance counters and system metrics - **User Management**: Create, modify, and manage user accounts - **GPO Management**: Group Policy operations and compliance - **Certificate Management**: SSL/TLS certificate operations ## Prerequisites - Windows Server 2008 R2+ or Windows 7+ (target machines) - WinRM service enabled and configured - Appropriate firewall exceptions - Valid authentication credentials - PowerShell 3.0+ recommended ### Enable WinRM on Target Machines #### Quick Setup (Administrator PowerShell) ```powershell # Enable WinRM with default settings Enable-PSRemoting -Force # Configure trusted hosts (if needed for workgroup) Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force # Allow unencrypted traffic (not recommended for production) Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value $true # Configure basic authentication (if needed) Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true ``` #### Secure Setup (Domain Environment) ```powershell # Enable WinRM Enable-PSRemoting -Force # Configure HTTPS listener New-SelfSignedCertificate -DnsName "server.domain.com" -CertStoreLocation Cert:\LocalMachine\My $thumbprint = (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match "server.domain.com"}).Thumbprint winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=`"server.domain.com`";CertificateThumbprint=`"$thumbprint`"}" # Configure firewall netsh advfirewall firewall add rule name="WinRM-HTTPS" dir=in action=allow protocol=TCP localport=5986 ``` ## Configuration ### Basic Configuration ```typescript const winrmConfig: WinRMProtocolConfig = { connection: { host: 'windows-server.example.com', port: 5985, // HTTP (5986 for HTTPS) username: 'administrator', password: 'SecurePassword123', transport: 'http', // or 'https' auth: 'ntlm' // or 'basic', 'negotiate', 'kerberos' }, options: { timeout: 30000, operationTimeout: 600000, maxEnvelopeSize: 512000, locale: 'en-US', dataLocale: 'en-US' }, powershell: { executionPolicy: 'RemoteSigned', configurationName: 'Microsoft.PowerShell', shellUri: 'http://schemas.microsoft.com/powershell/Microsoft.PowerShell', maxMemoryPerShellMB: 512 } }; ``` ### Domain Authentication ```typescript const domainWinRMConfig: WinRMProtocolConfig = { connection: { host: 'dc01.contoso.local', port: 5986, // HTTPS domain: 'CONTOSO', username: 'svcaccount', password: process.env.WINRM_PASSWORD, transport: 'https', auth: 'kerberos' }, security: { rejectUnauthorized: true, ca: '/path/to/ca-cert.pem', cert: '/path/to/client-cert.pem', key: '/path/to/client-key.pem', enableSPNEGO: true, enableKerberos: true }, options: { timeout: 60000, operationTimeout: 1800000, // 30 minutes for long operations maxEnvelopeSize: 1024000 } }; ``` ### Multiple Server Configuration ```typescript const multiServerConfig = { servers: { 'web-servers': [ { host: 'web01.contoso.local', role: 'iis' }, { host: 'web02.contoso.local', role: 'iis' }, { host: 'web03.contoso.local', role: 'iis' } ], 'database-servers': [ { host: 'sql01.contoso.local', role: 'sql-primary' }, { host: 'sql02.contoso.local', role: 'sql-secondary' } ], 'domain-controllers': [ { host: 'dc01.contoso.local', role: 'pdc' }, { host: 'dc02.contoso.local', role: 'bdc' } ] }, credentials: { domain: 'CONTOSO', username: 'svc-automation', password: process.env.WINRM_SERVICE_PASSWORD } }; ``` ## Usage Examples ### 1. Basic PowerShell Command Execution ```javascript // Connect to Windows server const winrmSession = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: { host: 'server01.contoso.local', username: 'administrator', password: 'SecurePassword123', transport: 'https', port: 5986 } }); // Execute PowerShell commands const systemInfo = await console_execute_command({ command: 'powershell', args: ['Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory, CsProcessors'], consoleType: 'winrm', sessionId: winrmSession.sessionId }); console.log('System Information:', systemInfo.output); // Check disk space const diskSpace = await console_execute_command({ command: 'powershell', args: ['Get-WmiObject -Class Win32_LogicalDisk | Select-Object DeviceID, Size, FreeSpace, @{Name="PercentFree";Expression={($_.FreeSpace/$_.Size)*100}}'], consoleType: 'winrm', sessionId: winrmSession.sessionId }); console.log('Disk Space:', diskSpace.output); // Get running services const services = await console_execute_command({ command: 'powershell', args: ['Get-Service | Where-Object {$_.Status -eq "Running"} | Select-Object Name, Status, StartType'], consoleType: 'winrm', sessionId: winrmSession.sessionId }); console.log('Running Services:', services.output); ``` ### 2. IIS Web Server Management ```javascript // Manage IIS web servers async function manageIISServers(servers, operation) { const results = []; for (const server of servers) { console.log(`Managing IIS on ${server.host}...`); try { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: { host: server.host, username: 'iis-admin', password: process.env.IIS_ADMIN_PASSWORD, domain: 'CONTOSO' } }); switch (operation) { case 'deploy': await deployWebApplication(session, server); break; case 'backup': await backupIISConfiguration(session, server); break; case 'health-check': const health = await performIISHealthCheck(session, server); results.push({ server: server.host, health }); break; case 'update-config': await updateIISConfiguration(session, server); break; } await console_stop_session({ sessionId: session.sessionId }); } catch (error) { console.error(`Failed to manage ${server.host}:`, error.message); results.push({ server: server.host, error: error.message }); } } return results; } async function deployWebApplication(session, server) { // Stop application pool await console_execute_command({ command: 'powershell', args: ['Import-Module WebAdministration; Stop-WebAppPool -Name "DefaultAppPool"'], consoleType: 'winrm', sessionId: session.sessionId }); // Backup current application const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); await console_execute_command({ command: 'powershell', args: [`Copy-Item -Path "C:\\inetpub\\wwwroot" -Destination "C:\\Backups\\wwwroot-${timestamp}" -Recurse`], consoleType: 'winrm', sessionId: session.sessionId }); // Deploy new application files await console_execute_command({ command: 'powershell', args: [ '$source = "\\\\deploy-server\\releases\\webapp-latest\\*"', '$destination = "C:\\inetpub\\wwwroot"', 'Copy-Item -Path $source -Destination $destination -Recurse -Force' ].join('; '), consoleType: 'winrm', sessionId: session.sessionId }); // Update application configuration await console_execute_command({ command: 'powershell', args: [ 'Import-Module WebAdministration', `Set-WebConfigurationProperty -PSPath "IIS:\\Sites\\Default Web Site" -Filter "appSettings/add[@key='Environment']" -Name "value" -Value "${server.environment}"` ].join('; '), consoleType: 'winrm', sessionId: session.sessionId }); // Start application pool await console_execute_command({ command: 'powershell', args: ['Start-WebAppPool -Name "DefaultAppPool"'], consoleType: 'winrm', sessionId: session.sessionId }); // Verify deployment await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds const healthCheck = await console_execute_command({ command: 'powershell', args: ['Invoke-WebRequest -Uri "http://localhost/health" -UseBasicParsing | Select-Object StatusCode, Content'], consoleType: 'winrm', sessionId: session.sessionId }); if (!healthCheck.output.includes('StatusCode : 200')) { throw new Error('Deployment health check failed'); } console.log(`Deployment successful on ${server.host}`); } async function performIISHealthCheck(session, server) { const checks = { iisService: false, appPools: [], websites: [], diskSpace: null, memory: null, cpuUsage: null }; // Check IIS service const iisStatus = await console_execute_command({ command: 'powershell', args: ['Get-Service -Name W3SVC | Select-Object Status'], consoleType: 'winrm', sessionId: session.sessionId }); checks.iisService = iisStatus.output.includes('Running'); // Check application pools const appPools = await console_execute_command({ command: 'powershell', args: ['Import-Module WebAdministration; Get-IISAppPool | Select-Object Name, State'], consoleType: 'winrm', sessionId: session.sessionId }); // Parse app pool status const appPoolLines = appPools.output.split('\n').slice(3); // Skip headers for (const line of appPoolLines) { if (line.trim()) { const parts = line.trim().split(/\s+/); if (parts.length >= 2) { checks.appPools.push({ name: parts[0], state: parts[1] }); } } } // Check websites const websites = await console_execute_command({ command: 'powershell', args: ['Get-Website | Select-Object Name, State, PhysicalPath'], consoleType: 'winrm', sessionId: session.sessionId }); // Parse website status (similar to app pools) const websiteLines = websites.output.split('\n').slice(3); for (const line of websiteLines) { if (line.trim()) { const parts = line.trim().split(/\s+/); if (parts.length >= 2) { checks.websites.push({ name: parts[0], state: parts[1], path: parts.slice(2).join(' ') }); } } } // Check system resources const resources = await console_execute_command({ command: 'powershell', args: [ '$cpu = Get-WmiObject -Class Win32_Processor | Measure-Object -Property LoadPercentage -Average', '$mem = Get-WmiObject -Class Win32_OperatingSystem', '$disk = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3"', 'Write-Output "CPU: $($cpu.Average)%"', 'Write-Output "Memory: $(($mem.TotalVisibleMemorySize - $mem.FreePhysicalMemory) / $mem.TotalVisibleMemorySize * 100)%"', '$disk | ForEach { Write-Output "Disk $($_.DeviceID): $((1 - $_.FreeSpace / $_.Size) * 100)%" }' ].join('; '), consoleType: 'winrm', sessionId: session.sessionId }); // Parse resource usage const resourceLines = resources.output.split('\n'); for (const line of resourceLines) { if (line.includes('CPU:')) { checks.cpuUsage = parseFloat(line.split(':')[1].replace('%', '').trim()); } else if (line.includes('Memory:')) { checks.memory = parseFloat(line.split(':')[1].replace('%', '').trim()); } else if (line.includes('Disk')) { if (!checks.diskSpace) checks.diskSpace = {}; const parts = line.split(':'); const drive = parts[0].split(' ')[1]; const usage = parseFloat(parts[1].replace('%', '').trim()); checks.diskSpace[drive] = usage; } } return checks; } // Execute IIS management operations const webServers = [ { host: 'web01.contoso.local', environment: 'production' }, { host: 'web02.contoso.local', environment: 'production' }, { host: 'web03.contoso.local', environment: 'production' } ]; const healthResults = await manageIISServers(webServers, 'health-check'); console.log('IIS Health Check Results:', healthResults); ``` ### 3. SQL Server Management ```javascript // SQL Server administration async function manageSQLServer(serverConfig, operation) { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: { host: serverConfig.host, username: serverConfig.username, password: serverConfig.password, domain: serverConfig.domain } }); try { switch (operation.type) { case 'backup': await performDatabaseBackup(session, operation.params); break; case 'restore': await performDatabaseRestore(session, operation.params); break; case 'maintenance': await performDatabaseMaintenance(session, operation.params); break; case 'monitor': return await monitorSQLServer(session); } } finally { await console_stop_session({ sessionId: session.sessionId }); } } async function performDatabaseBackup(session, params) { console.log(`Starting backup of database: ${params.database}`); const backupScript = ` $sqlInstance = "${params.instance || 'localhost'}" $database = "${params.database}" $backupPath = "${params.backupPath || 'C:\\Backups'}" $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $backupFile = "$backupPath\\$database_$timestamp.bak" # Import SQL Server module Import-Module SqlServer -ErrorAction SilentlyContinue if (-not (Get-Module SqlServer)) { Import-Module SQLPS -ErrorAction SilentlyContinue } # Perform backup $backupQuery = @" BACKUP DATABASE [$database] TO DISK = N'$backupFile' WITH FORMAT, INIT, NAME = N'$database-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10 "@ Invoke-Sqlcmd -ServerInstance $sqlInstance -Query $backupQuery -QueryTimeout 7200 if (Test-Path $backupFile) { $size = (Get-Item $backupFile).Length / 1MB Write-Output "Backup completed successfully: $backupFile ($.2f MB)" -f $size } else { throw "Backup file not found: $backupFile" } `; const backupResult = await console_execute_command({ command: 'powershell', args: [backupScript], consoleType: 'winrm', sessionId: session.sessionId, timeout: 7200000 // 2 hours }); if (backupResult.exitCode !== 0) { throw new Error(`Backup failed: ${backupResult.stderr}`); } console.log('Database backup completed:', backupResult.output); } async function monitorSQLServer(session) { const monitoringScript = ` $sqlInstance = "localhost" # Import SQL Server module Import-Module SqlServer -ErrorAction SilentlyContinue # Get SQL Server information $serverInfo = Invoke-Sqlcmd -ServerInstance $sqlInstance -Query @" SELECT @@SERVERNAME as ServerName, @@VERSION as Version, SERVERPROPERTY('Edition') as Edition, SERVERPROPERTY('ProductLevel') as ProductLevel, SERVERPROPERTY('IsClustered') as IsClustered "@ # Get database sizes $databaseSizes = Invoke-Sqlcmd -ServerInstance $sqlInstance -Query @" SELECT name as DatabaseName, size * 8 / 1024 as SizeMB, FILEPROPERTY(name, 'SpaceUsed') * 8 / 1024 as UsedMB FROM sys.master_files WHERE type = 0 ORDER BY size DESC "@ # Get performance counters $perfCounters = @{ 'BatchRequestsSec' = (Get-Counter '\SQLServer:SQL Statistics\Batch Requests/sec' -ErrorAction SilentlyContinue).CounterSamples.CookedValue 'PageLifeExpectancy' = (Get-Counter '\SQLServer:Buffer Manager\Page life expectancy' -ErrorAction SilentlyContinue).CounterSamples.CookedValue 'BufferCacheHitRatio' = (Get-Counter '\SQLServer:Buffer Manager\Buffer cache hit ratio' -ErrorAction SilentlyContinue).CounterSamples.CookedValue } # Get blocked processes $blockedProcesses = Invoke-Sqlcmd -ServerInstance $sqlInstance -Query @" SELECT session_id, blocking_session_id, wait_type, wait_time, last_wait_type, wait_resource FROM sys.dm_exec_requests WHERE blocking_session_id != 0 "@ $monitoring = @{ ServerInfo = $serverInfo DatabaseSizes = $databaseSizes PerformanceCounters = $perfCounters BlockedProcesses = $blockedProcesses Timestamp = Get-Date } $monitoring | ConvertTo-Json -Depth 3 `; const monitoringResult = await console_execute_command({ command: 'powershell', args: [monitoringScript], consoleType: 'winrm', sessionId: session.sessionId }); return JSON.parse(monitoringResult.output); } // Usage const sqlServerConfig = { host: 'sql01.contoso.local', username: 'sql-admin', password: process.env.SQL_ADMIN_PASSWORD, domain: 'CONTOSO' }; // Perform database backup await manageSQLServer(sqlServerConfig, { type: 'backup', params: { database: 'ProductionDB', instance: 'MSSQLSERVER', backupPath: 'C:\\SQLBackups' } }); // Monitor SQL Server const monitoring = await manageSQLServer(sqlServerConfig, { type: 'monitor' }); console.log('SQL Server Monitoring Results:', monitoring); ``` ### 4. Active Directory Management ```javascript // Active Directory user and group management async function manageActiveDirectory(dcConfig, operations) { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: { host: dcConfig.host, username: dcConfig.username, password: dcConfig.password, domain: dcConfig.domain } }); const results = []; try { for (const operation of operations) { console.log(`Performing AD operation: ${operation.type}`); let result; switch (operation.type) { case 'create-user': result = await createADUser(session, operation.params); break; case 'create-group': result = await createADGroup(session, operation.params); break; case 'add-to-group': result = await addUserToGroup(session, operation.params); break; case 'reset-password': result = await resetUserPassword(session, operation.params); break; case 'disable-user': result = await disableADUser(session, operation.params); break; case 'query-users': result = await queryADUsers(session, operation.params); break; } results.push({ operation: operation.type, success: true, result: result }); } } catch (error) { results.push({ operation: operation.type, success: false, error: error.message }); } finally { await console_stop_session({ sessionId: session.sessionId }); } return results; } async function createADUser(session, params) { const createUserScript = ` Import-Module ActiveDirectory $securePassword = ConvertTo-SecureString "${params.password}" -AsPlainText -Force $userParams = @{ Name = "${params.name}" GivenName = "${params.firstName}" Surname = "${params.lastName}" SamAccountName = "${params.username}" UserPrincipalName = "${params.username}@${params.domain}" EmailAddress = "${params.email}" Path = "${params.ou || 'CN=Users,DC=contoso,DC=local'}" AccountPassword = $securePassword Enabled = $true PasswordNeverExpires = $false ChangePasswordAtLogon = ${params.changePasswordAtLogon || 'true'} } New-ADUser @userParams Write-Output "User ${params.username} created successfully" `; const result = await console_execute_command({ command: 'powershell', args: [createUserScript], consoleType: 'winrm', sessionId: session.sessionId }); return result.output; } async function queryADUsers(session, params) { const queryScript = ` Import-Module ActiveDirectory $filter = "${params.filter || '*'}" $properties = @("Name", "SamAccountName", "EmailAddress", "Enabled", "LastLogonDate", "WhenCreated") Get-ADUser -Filter "Name -like '$filter'" -Properties $properties | Select-Object Name, SamAccountName, EmailAddress, Enabled, LastLogonDate, WhenCreated | ConvertTo-Json -Depth 2 `; const result = await console_execute_command({ command: 'powershell', args: [queryScript], consoleType: 'winrm', sessionId: session.sessionId }); return JSON.parse(result.output); } // Bulk user operations async function bulkUserOperations(dcConfig, csvFilePath) { console.log('Processing bulk user operations from CSV...'); const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: dcConfig }); const bulkScript = ` Import-Module ActiveDirectory $csvData = Import-Csv "${csvFilePath}" $results = @() foreach ($user in $csvData) { try { switch ($user.Operation.ToLower()) { 'create' { $securePassword = ConvertTo-SecureString $user.Password -AsPlainText -Force New-ADUser -Name $user.Name -GivenName $user.FirstName -Surname $user.LastName -SamAccountName $user.Username -AccountPassword $securePassword -Enabled:$true $results += [PSCustomObject]@{ Username = $user.Username; Operation = 'Create'; Status = 'Success'; Message = 'User created' } } 'disable' { Disable-ADAccount -Identity $user.Username $results += [PSCustomObject]@{ Username = $user.Username; Operation = 'Disable'; Status = 'Success'; Message = 'User disabled' } } 'enable' { Enable-ADAccount -Identity $user.Username $results += [PSCustomObject]@{ Username = $user.Username; Operation = 'Enable'; Status = 'Success'; Message = 'User enabled' } } } } catch { $results += [PSCustomObject]@{ Username = $user.Username; Operation = $user.Operation; Status = 'Failed'; Message = $_.Exception.Message } } } $results | ConvertTo-Json -Depth 2 `; const result = await console_execute_command({ command: 'powershell', args: [bulkScript], consoleType: 'winrm', sessionId: session.sessionId, timeout: 300000 // 5 minutes }); await console_stop_session({ sessionId: session.sessionId }); return JSON.parse(result.output); } // Usage examples const dcConfig = { host: 'dc01.contoso.local', username: 'domain-admin', password: process.env.DOMAIN_ADMIN_PASSWORD, domain: 'CONTOSO' }; // Create new users const userOperations = [ { type: 'create-user', params: { name: 'John Doe', firstName: 'John', lastName: 'Doe', username: 'jdoe', email: 'john.doe@contoso.com', password: 'TempPassword123!', domain: 'contoso.local', changePasswordAtLogon: true } }, { type: 'query-users', params: { filter: 'John*' } } ]; const adResults = await manageActiveDirectory(dcConfig, userOperations); console.log('Active Directory Results:', adResults); ``` ### 5. System Monitoring and Alerting ```javascript // Comprehensive Windows system monitoring class WindowsSystemMonitor { constructor(servers, alertConfig) { this.servers = servers; this.alertConfig = alertConfig; this.sessions = new Map(); } async startMonitoring() { console.log('Starting Windows system monitoring...'); // Connect to all servers for (const server of this.servers) { try { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: server.connection }); this.sessions.set(server.name, session); console.log(`Connected to ${server.name}`); } catch (error) { console.error(`Failed to connect to ${server.name}:`, error.message); } } // Start monitoring loop this.monitoringInterval = setInterval(() => { this.collectMetrics(); }, this.alertConfig.interval || 60000); // Default 1 minute console.log('Monitoring started'); } async collectMetrics() { for (const [serverName, session] of this.sessions) { try { const metrics = await this.getServerMetrics(session, serverName); await this.processMetrics(serverName, metrics); } catch (error) { console.error(`Failed to collect metrics from ${serverName}:`, error.message); await this.handleConnectionError(serverName); } } } async getServerMetrics(session, serverName) { const metricsScript = ` # CPU Usage $cpuUsage = Get-WmiObject -Class Win32_Processor | Measure-Object -Property LoadPercentage -Average | Select-Object -ExpandProperty Average # Memory Usage $os = Get-WmiObject -Class Win32_OperatingSystem $memoryUsage = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 2) # Disk Usage $diskUsage = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object { [PSCustomObject]@{ Drive = $_.DeviceID Size = [math]::Round($_.Size / 1GB, 2) FreeSpace = [math]::Round($_.FreeSpace / 1GB, 2) PercentUsed = [math]::Round((1 - $_.FreeSpace / $_.Size) * 100, 2) } } # Network Usage (simplified) $networkAdapters = Get-WmiObject -Class Win32_PerfRawData_Tcpip_NetworkInterface | Where-Object {$_.Name -notlike "*Loopback*" -and $_.Name -notlike "*isatap*"} # Service Status $criticalServices = Get-Service | Where-Object { $_.Name -in @("Spooler", "BITS", "Themes", "AudioSrv", "Dnscache", "eventlog", "PlugPlay", "RpcSs", "lanmanserver", "lanmanworkstation") } | Select-Object Name, Status # Event Log Errors (last hour) $errorEvents = Get-WinEvent -FilterHashtable @{LogName='System','Application'; Level=1,2; StartTime=(Get-Date).AddHours(-1)} -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count # Performance Counters $perfCounters = @{ 'ProcessorQueueLength' = (Get-Counter '\System\Processor Queue Length' -ErrorAction SilentlyContinue).CounterSamples.CookedValue 'AvailableBytes' = (Get-Counter '\Memory\Available Bytes' -ErrorAction SilentlyContinue).CounterSamples.CookedValue / 1GB 'PagesPerSec' = (Get-Counter '\Memory\Pages/sec' -ErrorAction SilentlyContinue).CounterSamples.CookedValue } $metrics = [PSCustomObject]@{ Timestamp = Get-Date ServerName = $env:COMPUTERNAME CPU = [PSCustomObject]@{ Usage = $cpuUsage QueueLength = $perfCounters.ProcessorQueueLength } Memory = [PSCustomObject]@{ Usage = $memoryUsage AvailableGB = $perfCounters.AvailableBytes PagesPerSec = $perfCounters.PagesPerSec } Disks = $diskUsage Services = $criticalServices EventErrors = $errorEvents Uptime = (Get-Date) - (gcim Win32_OperatingSystem).LastBootUpTime } $metrics | ConvertTo-Json -Depth 3 `; const result = await console_execute_command({ command: 'powershell', args: [metricsScript], consoleType: 'winrm', sessionId: session.sessionId }); return JSON.parse(result.output); } async processMetrics(serverName, metrics) { // Store metrics console.log(`[${serverName}] CPU: ${metrics.CPU.Usage}%, Memory: ${metrics.Memory.Usage}%`); // Check alert conditions const alerts = []; // CPU Alert if (metrics.CPU.Usage > this.alertConfig.thresholds.cpu) { alerts.push({ type: 'cpu', severity: 'warning', message: `High CPU usage: ${metrics.CPU.Usage}%`, value: metrics.CPU.Usage, threshold: this.alertConfig.thresholds.cpu }); } // Memory Alert if (metrics.Memory.Usage > this.alertConfig.thresholds.memory) { alerts.push({ type: 'memory', severity: 'warning', message: `High memory usage: ${metrics.Memory.Usage}%`, value: metrics.Memory.Usage, threshold: this.alertConfig.thresholds.memory }); } // Disk Space Alert for (const disk of metrics.Disks) { if (disk.PercentUsed > this.alertConfig.thresholds.disk) { alerts.push({ type: 'disk', severity: 'warning', message: `Low disk space on ${disk.Drive}: ${disk.PercentUsed}% used`, value: disk.PercentUsed, threshold: this.alertConfig.thresholds.disk }); } } // Service Alerts const stoppedServices = metrics.Services.filter(s => s.Status !== 'Running'); if (stoppedServices.length > 0) { alerts.push({ type: 'services', severity: 'error', message: `Critical services stopped: ${stoppedServices.map(s => s.Name).join(', ')}`, value: stoppedServices.length, services: stoppedServices }); } // Event Log Errors if (metrics.EventErrors > this.alertConfig.thresholds.eventErrors) { alerts.push({ type: 'events', severity: 'warning', message: `High number of error events: ${metrics.EventErrors} in the last hour`, value: metrics.EventErrors, threshold: this.alertConfig.thresholds.eventErrors }); } // Send alerts if (alerts.length > 0) { await this.sendAlerts(serverName, alerts); } // Store metrics in database or monitoring system await this.storeMetrics(serverName, metrics); } async sendAlerts(serverName, alerts) { console.log(`⚠️ ALERTS for ${serverName}:`); for (const alert of alerts) { console.log(` ${alert.severity.toUpperCase()}: ${alert.message}`); // Send to monitoring system, email, Slack, etc. if (this.alertConfig.webhookUrl) { await this.sendWebhookAlert(serverName, alert); } } } async sendWebhookAlert(serverName, alert) { const webhook = { server: serverName, alert: alert, timestamp: new Date().toISOString() }; try { await require('axios').post(this.alertConfig.webhookUrl, webhook); } catch (error) { console.error('Failed to send webhook alert:', error.message); } } async storeMetrics(serverName, metrics) { // Store in database, time-series database, etc. // This is a placeholder implementation const metricsData = { server: serverName, timestamp: metrics.Timestamp, cpu: metrics.CPU.Usage, memory: metrics.Memory.Usage, disks: metrics.Disks, uptime: metrics.Uptime }; // Example: send to InfluxDB, Prometheus, etc. console.log(`Storing metrics for ${serverName}:`, JSON.stringify(metricsData, null, 2)); } async stopMonitoring() { console.log('Stopping monitoring...'); if (this.monitoringInterval) { clearInterval(this.monitoringInterval); } // Close all WinRM sessions for (const [serverName, session] of this.sessions) { try { await console_stop_session({ sessionId: session.sessionId }); console.log(`Disconnected from ${serverName}`); } catch (error) { console.error(`Failed to disconnect from ${serverName}:`, error.message); } } this.sessions.clear(); console.log('Monitoring stopped'); } async handleConnectionError(serverName) { console.warn(`Connection error for ${serverName}, attempting reconnect...`); const server = this.servers.find(s => s.name === serverName); if (server) { try { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: server.connection }); this.sessions.set(serverName, session); console.log(`Reconnected to ${serverName}`); } catch (error) { console.error(`Failed to reconnect to ${serverName}:`, error.message); } } } } // Usage const servers = [ { name: 'web-server-01', connection: { host: 'web01.contoso.local', username: 'monitor', password: process.env.MONITOR_PASSWORD, domain: 'CONTOSO' } }, { name: 'db-server-01', connection: { host: 'sql01.contoso.local', username: 'monitor', password: process.env.MONITOR_PASSWORD, domain: 'CONTOSO' } } ]; const alertConfig = { interval: 60000, // 1 minute thresholds: { cpu: 80, // 80% memory: 85, // 85% disk: 90, // 90% eventErrors: 10 // 10 errors per hour }, webhookUrl: 'https://hooks.slack.com/services/...' }; const monitor = new WindowsSystemMonitor(servers, alertConfig); await monitor.startMonitoring(); // Stop monitoring after some time (example) setTimeout(async () => { await monitor.stopMonitoring(); }, 3600000); // 1 hour ``` ## Advanced Features ### PowerShell Desired State Configuration (DSC) ```javascript // Deploy and manage DSC configurations async function deployDSCConfiguration(servers, configName, configData) { const dscScript = ` Configuration ${configName} { Node localhost { ${configData} } } ${configName} -OutputPath "C:\\DSC\\${configName}" Start-DscConfiguration -Path "C:\\DSC\\${configName}" -Wait -Verbose -Force Get-DscConfigurationStatus `; for (const server of servers) { console.log(`Deploying DSC configuration to ${server.host}...`); const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: server }); try { const result = await console_execute_command({ command: 'powershell', args: [dscScript], consoleType: 'winrm', sessionId: session.sessionId, timeout: 600000 // 10 minutes }); console.log(`DSC deployment result for ${server.host}:`, result.output); } finally { await console_stop_session({ sessionId: session.sessionId }); } } } // Example DSC configuration const iisConfig = ` WindowsFeature IIS { Ensure = "Present" Name = "IIS-WebServerRole" } WindowsFeature IISManagement { Ensure = "Present" Name = "IIS-ManagementConsole" DependsOn = "[WindowsFeature]IIS" } File WebContent { Ensure = "Present" DestinationPath = "C:\\inetpub\\wwwroot\\index.html" Contents = "<html><body><h1>Hello from DSC!</h1></body></html>" DependsOn = "[WindowsFeature]IIS" } `; const webServers = [ { host: 'web01.contoso.local', username: 'admin', password: 'password' }, { host: 'web02.contoso.local', username: 'admin', password: 'password' } ]; await deployDSCConfiguration(webServers, 'WebServerConfig', iisConfig); ``` ### Certificate Management ```javascript // SSL certificate management async function manageCertificates(servers, operations) { for (const server of servers) { const session = await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: server }); try { for (const operation of operations) { switch (operation.type) { case 'install': await installCertificate(session, operation.params); break; case 'export': await exportCertificate(session, operation.params); break; case 'renew': await renewCertificate(session, operation.params); break; case 'list': const certs = await listCertificates(session, operation.params); console.log(`Certificates on ${server.host}:`, certs); break; } } } finally { await console_stop_session({ sessionId: session.sessionId }); } } } async function installCertificate(session, params) { const installScript = ` $certPath = "${params.certPath}" $password = ConvertTo-SecureString "${params.password}" -AsPlainText -Force $store = "${params.store || 'LocalMachine'}" $storeName = "${params.storeName || 'My'}" Import-PfxCertificate -FilePath $certPath -CertStoreLocation "Cert:\\$store\\$storeName" -Password $password Write-Output "Certificate installed successfully" `; const result = await console_execute_command({ command: 'powershell', args: [installScript], consoleType: 'winrm', sessionId: session.sessionId }); return result.output; } ``` ## Error Handling ### Connection Errors ```javascript protocol.on('connection-error', (error, config) => { console.error(`WinRM connection failed to ${config.host}:${config.port}:`, error.message); switch (error.code) { case 'ECONNREFUSED': console.error('Connection refused - check if WinRM service is running'); break; case 'ENOTFOUND': console.error('Host not found - check hostname and DNS resolution'); break; case 'ETIMEDOUT': console.error('Connection timeout - check network connectivity and firewall'); break; case 'ECONNRESET': console.error('Connection reset - may indicate authentication issues'); break; } }); protocol.on('authentication-error', (error, config) => { console.error(`Authentication failed for ${config.username}@${config.host}`); console.log('Check username, password, and domain configuration'); if (config.auth === 'kerberos') { console.log('For Kerberos auth, ensure proper SPN configuration'); } }); ``` ### PowerShell Execution Errors ```javascript protocol.on('powershell-error', (error, command, session) => { console.error(`PowerShell execution failed: ${error.message}`); console.error(`Command: ${command}`); if (error.message.includes('ExecutionPolicy')) { console.log('Consider setting execution policy: Set-ExecutionPolicy RemoteSigned'); } else if (error.message.includes('Access is denied')) { console.log('User may need elevated privileges'); } }); // Implement retry mechanism async function executeWithRetry(sessionId, command, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await console_execute_command({ command: 'powershell', args: [command], consoleType: 'winrm', sessionId: sessionId }); } catch (error) { console.log(`Attempt ${attempt}/${maxRetries} failed:`, error.message); if (attempt === maxRetries) throw error; // Exponential backoff await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000)); } } } ``` ## Best Practices ### 1. Security ```javascript // Use HTTPS and certificate-based authentication const secureConfig = { transport: 'https', port: 5986, rejectUnauthorized: true, ca: fs.readFileSync('/path/to/ca-cert.pem'), cert: fs.readFileSync('/path/to/client-cert.pem'), key: fs.readFileSync('/path/to/client-key.pem') }; // Use service accounts with limited privileges const serviceAccountConfig = { username: 'svc-automation', password: process.env.SVC_PASSWORD, domain: 'CONTOSO' }; // Implement session timeout const sessionConfig = { timeout: 300000, // 5 minutes operationTimeout: 1800000, // 30 minutes for long operations keepAlive: true, keepAliveInterval: 30000 }; ``` ### 2. Performance ```javascript // Connection pooling class WinRMConnectionPool { constructor(config, maxConnections = 5) { this.config = config; this.maxConnections = maxConnections; this.connections = []; this.busyConnections = new Set(); } async getConnection() { // Reuse existing connection if available const available = this.connections.find(conn => !this.busyConnections.has(conn)); if (available) { this.busyConnections.add(available); return available; } // Create new connection if under limit if (this.busyConnections.size < this.maxConnections) { const newConn = await this.createConnection(); this.connections.push(newConn); this.busyConnections.add(newConn); return newConn; } // Wait for connection to become available return new Promise((resolve) => { const checkInterval = setInterval(() => { const available = this.connections.find(conn => !this.busyConnections.has(conn)); if (available) { clearInterval(checkInterval); this.busyConnections.add(available); resolve(available); } }, 100); }); } releaseConnection(connection) { this.busyConnections.delete(connection); } async createConnection() { return await console_create_session({ command: 'winrm-connect', consoleType: 'winrm', winrmOptions: this.config }); } } // Batch operations for efficiency async function batchPowerShellCommands(sessionId, commands) { const batchScript = commands.join('; '); return await console_execute_command({ command: 'powershell', args: [batchScript], consoleType: 'winrm', sessionId: sessionId }); } ``` ### 3. Monitoring ```javascript // Comprehensive logging const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.File({ filename: 'winrm-operations.log' }), new winston.transports.Console() ] }); protocol.on('command-executed', (command, result, session) => { logger.info('WinRM command executed', { host: session.config.host, command: command, duration: result.duration, exitCode: result.exitCode, timestamp: new Date().toISOString() }); }); // Performance monitoring protocol.on('session-created', (sessionInfo) => { logger.info('WinRM session created', { sessionId: sessionInfo.sessionId, host: sessionInfo.config.host, username: sessionInfo.config.username }); }); ``` ## API Reference ### Events - `connection-established`: Connection successful - `connection-error`: Connection failed - `authentication-error`: Authentication failed - `command-executed`: PowerShell command executed - `session-created`: Session established - `session-ended`: Session terminated - `powershell-error`: PowerShell execution error ### Methods - `createSession(options)`: Create WinRM session - `executeCommand(sessionId, command)`: Execute PowerShell command - `executeBatch(sessionId, commands)`: Execute multiple commands - `uploadFile(sessionId, localPath, remotePath)`: Upload file - `downloadFile(sessionId, remotePath, localPath)`: Download file - `getSystemInfo(sessionId)`: Get system information - `manageService(sessionId, serviceName, action)`: Manage Windows service - `queryEventLog(sessionId, logName, criteria)`: Query event logs - `manageRegistry(sessionId, operation, keyPath, value)`: Registry operations ### Configuration Options See the TypeScript interfaces in the source code for complete configuration options including `WinRMProtocolConfig`, `WinRMConnectionOptions`, and `PowerShellOptions`.

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