Skip to main content
Glama

PortMaster MCP

by smspgh
portmaster-cli.ps1•18.7 kB
#!/usr/bin/env powershell <# .SYNOPSIS PortMaster CLI - Direct command-line interface for port and process management .DESCRIPTION This script provides direct CLI access to PortMaster MCP functions without needing Claude Code. You can check ports, find processes, get service info, and perform management operations. .PARAMETER Command The command to execute (check-ports, find-service, process-info, kill-port, etc.) .PARAMETER Target The target for the command (port numbers, service name, PID, etc.) .PARAMETER Force Skip confirmation prompts for destructive operations .EXAMPLE .\portmaster-cli.ps1 check-ports 3000,3001,3002 .\portmaster-cli.ps1 find-service "*SQL*" .\portmaster-cli.ps1 process-info 1234 .\portmaster-cli.ps1 kill-port 8080 -Force #> param( [Parameter(Mandatory=$false)] [ValidateSet("check-ports", "all-ports", "find-service", "service-info", "process-info", "kill-process", "kill-port", "kill-multiple", "stop-service", "start-service", "restart-service", "help")] [string]$Command = "help", [Parameter(Mandatory=$false, ValueFromRemainingArguments=$true)] [string[]]$Target, [Parameter(Mandatory=$false)] [switch]$Force ) # Colors for output $colors = @{ Info = "Cyan" Success = "Green" Warning = "Yellow" Error = "Red" Header = "Magenta" } function Show-Help { Write-Host "" Write-Host "=== PortMaster CLI ===" -ForegroundColor $colors.Header Write-Host "Direct command-line interface for port and process management" -ForegroundColor $colors.Info Write-Host "" Write-Host "DISCOVERY COMMANDS (No admin required):" -ForegroundColor $colors.Header Write-Host " check-ports <ports> - Check what's listening on specific ports" Write-Host " Example: check-ports 3000,3001,3002" Write-Host " all-ports - Show all listening ports on the system" Write-Host " find-service <pattern> - Find services by name (supports wildcards)" Write-Host " Example: find-service '*SQL*'" Write-Host " service-info <name> - Get detailed info about a service" Write-Host " process-info <PID> - Get detailed info about a process" Write-Host "" Write-Host "MANAGEMENT COMMANDS (Require admin/UAC):" -ForegroundColor $colors.Header Write-Host " kill-process <PID> - Kill a process by PID" Write-Host " kill-port <ports> - Kill all processes using specific ports" Write-Host " kill-multiple <PIDs> - Kill multiple processes" Write-Host " stop-service <name> - Stop a Windows service" Write-Host " start-service <name> - Start a Windows service" Write-Host " restart-service <name> - Restart a Windows service" Write-Host "" Write-Host "OPTIONS:" -ForegroundColor $colors.Header Write-Host " -Force - Skip confirmation prompts" Write-Host "" Write-Host "EXAMPLES:" -ForegroundColor $colors.Header Write-Host " .\portmaster-cli.ps1 check-ports 3000-3005" Write-Host " .\portmaster-cli.ps1 find-service 'Docker*'" Write-Host " .\portmaster-cli.ps1 kill-port 8080 -Force" Write-Host " .\portmaster-cli.ps1 all-ports | findstr :80" Write-Host "" } function Check-Ports { param([string]$PortList) if (-not $PortList -or $PortList -eq "") { Write-Host "Error: Port list required" -ForegroundColor $colors.Error Write-Host "Example: check-ports 3000,3001,3002 or check-ports 3000-3005" return } # Parse port ranges and lists $ports = @() $PortList -split ',' | ForEach-Object { $range = $_.Trim() if ($range -match '^(\d+)-(\d+)$') { $start = [int]$matches[1] $end = [int]$matches[2] $ports += $start..$end } else { $ports += [int]$range } } Write-Host "Checking ports: $($ports -join ', ')" -ForegroundColor $colors.Info Write-Host "" $found = $false foreach ($port in $ports) { $connections = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue if ($connections) { $found = $true foreach ($conn in $connections) { $process = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue Write-Host "Port $port - " -NoNewline -ForegroundColor $colors.Warning Write-Host "$($process.ProcessName) " -NoNewline -ForegroundColor $colors.Success Write-Host "(PID: $($conn.OwningProcess)) " -NoNewline Write-Host "[$($conn.LocalAddress)]" -ForegroundColor $colors.Info } } } if (-not $found) { Write-Host "No processes found listening on the specified ports" -ForegroundColor $colors.Warning } } function Get-AllPorts { Write-Host "All listening ports:" -ForegroundColor $colors.Info Write-Host "" $connections = Get-NetTCPConnection -State Listen | Sort-Object LocalPort foreach ($conn in $connections) { $process = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue Write-Host "Port $($conn.LocalPort) - " -NoNewline -ForegroundColor $colors.Warning Write-Host "$($process.ProcessName) " -NoNewline -ForegroundColor $colors.Success Write-Host "(PID: $($conn.OwningProcess)) " -NoNewline Write-Host "[$($conn.LocalAddress)]" -ForegroundColor $colors.Info } } function Find-ServiceByPattern { param([string]$Pattern) if (-not $Pattern) { Write-Host "Error: Service pattern required" -ForegroundColor $colors.Error Write-Host "Example: find-service '*SQL*' or find-service 'Docker'" return } Write-Host "Finding services matching: $Pattern" -ForegroundColor $colors.Info Write-Host "" $services = Get-Service | Where-Object { $_.Name -like $Pattern -or $_.DisplayName -like $Pattern } if ($services) { foreach ($service in $services) { Write-Host "$($service.Name) " -NoNewline -ForegroundColor $colors.Success Write-Host "($($service.DisplayName)) " -NoNewline Write-Host "- $($service.Status)" -ForegroundColor $( if ($service.Status -eq 'Running') { $colors.Success } else { $colors.Warning } ) # Try to find associated processes $processes = Get-Process | Where-Object { $_.ProcessName -like "*$($service.Name)*" } if ($processes) { foreach ($proc in $processes) { Write-Host " └─ Process: $($proc.ProcessName) (PID: $($proc.Id))" -ForegroundColor $colors.Info } } } } else { Write-Host "No services found matching pattern: $Pattern" -ForegroundColor $colors.Warning } } function Get-ProcessChainInfo { param([string]$ProcessId) try { $targetProcess = Get-Process -Id $ProcessId -ErrorAction Stop } catch { Write-Host "Process with PID '$ProcessId' not found" -ForegroundColor $colors.Error return } # Get WMI process info for parent details $wmiProcess = Get-WmiObject -Class Win32_Process -Filter "ProcessId = $ProcessId" -ErrorAction SilentlyContinue Write-Host "" Write-Host "=== Process Information ===" -ForegroundColor $colors.Header Write-Host "Process Name: $($targetProcess.ProcessName)" -ForegroundColor $colors.Success Write-Host "PID: $($targetProcess.Id)" Write-Host "Memory Usage: $([math]::Round($targetProcess.WorkingSet64 / 1MB, 1)) MB" # Format CPU Time properly $cpuTime = if ($targetProcess.TotalProcessorTime) { $targetProcess.TotalProcessorTime.ToString("hh\:mm\:ss\.fff") } else { "Not available" } Write-Host "CPU Time: $cpuTime" # Format Start Time properly $startTime = if ($targetProcess.StartTime) { $targetProcess.StartTime.ToString("yyyy-MM-dd HH:mm:ss") } else { "Not available" } Write-Host "Start Time: $startTime" Write-Host "Priority: $($targetProcess.BasePriority)" Write-Host "Thread Count: $($targetProcess.Threads.Count)" # Get command line and path info if ($wmiProcess) { $cmdLine = if ($wmiProcess.CommandLine) { $wmiProcess.CommandLine } else { "Not available" } $exePath = if ($wmiProcess.ExecutablePath) { $wmiProcess.ExecutablePath } else { "Not available" } Write-Host "Command Line: $cmdLine" -ForegroundColor $colors.Info Write-Host "Executable Path: $exePath" } else { Write-Host "Command Line: Not available (WMI access denied)" -ForegroundColor $colors.Warning Write-Host "Executable Path: Not available (WMI access denied)" -ForegroundColor $colors.Warning } # Get parent process info Write-Host "" Write-Host "=== Process Chain ===" -ForegroundColor $colors.Header if ($wmiProcess -and $wmiProcess.ParentProcessId) { $parentProcess = Get-Process -Id $wmiProcess.ParentProcessId -ErrorAction SilentlyContinue if ($parentProcess) { Write-Host "Parent Process: $($parentProcess.ProcessName) (PID: $($parentProcess.Id))" -ForegroundColor $colors.Warning # Get grandparent if available $parentWmi = Get-WmiObject -Class Win32_Process -Filter "ProcessId = $($parentProcess.Id)" -ErrorAction SilentlyContinue if ($parentWmi -and $parentWmi.ParentProcessId) { $grandparentProcess = Get-Process -Id $parentWmi.ParentProcessId -ErrorAction SilentlyContinue if ($grandparentProcess) { Write-Host " └─ Grandparent: $($grandparentProcess.ProcessName) (PID: $($grandparentProcess.Id))" -ForegroundColor $colors.Info } } } else { Write-Host "Parent Process: (PID: $($wmiProcess.ParentProcessId)) - Process no longer exists" -ForegroundColor $colors.Warning } } else { Write-Host "Parent Process: Not available (may be system process)" -ForegroundColor $colors.Info } # Get child processes $childProcesses = Get-WmiObject -Class Win32_Process -Filter "ParentProcessId = $ProcessId" -ErrorAction SilentlyContinue if ($childProcesses) { Write-Host "" Write-Host "Child Processes:" -ForegroundColor $colors.Warning foreach ($child in $childProcesses) { $childProcess = Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue if ($childProcess) { Write-Host " └─ $($childProcess.ProcessName) (PID: $($child.ProcessId)) - Memory: $([math]::Round($childProcess.WorkingSet64 / 1MB, 1)) MB" -ForegroundColor $colors.Success # Show grandchildren (one level deeper) $grandchildren = Get-WmiObject -Class Win32_Process -Filter "ParentProcessId = $($child.ProcessId)" -ErrorAction SilentlyContinue foreach ($grandchild in $grandchildren) { $grandchildProcess = Get-Process -Id $grandchild.ProcessId -ErrorAction SilentlyContinue if ($grandchildProcess) { Write-Host " └─ $($grandchildProcess.ProcessName) (PID: $($grandchild.ProcessId))" -ForegroundColor $colors.Info } } } } } else { Write-Host "Child Processes: None" -ForegroundColor $colors.Info } # Check if process is listening on any ports Write-Host "" Write-Host "=== Network Information ===" -ForegroundColor $colors.Header $tcpConnections = Get-NetTCPConnection | Where-Object { $_.OwningProcess -eq $ProcessId } if ($tcpConnections) { Write-Host "Listening Ports:" -ForegroundColor $colors.Warning $listeningPorts = $tcpConnections | Where-Object { $_.State -eq "Listen" } | Sort-Object LocalPort -Unique foreach ($conn in $listeningPorts) { Write-Host " └─ Port $($conn.LocalPort) [$($conn.LocalAddress)]" -ForegroundColor $colors.Success } $activePorts = $tcpConnections | Where-Object { $_.State -ne "Listen" } | Sort-Object LocalPort -Unique if ($activePorts) { Write-Host "Active Connections:" -ForegroundColor $colors.Warning foreach ($conn in $activePorts) { Write-Host " └─ $($conn.LocalAddress):$($conn.LocalPort) -> $($conn.RemoteAddress):$($conn.RemotePort) [$($conn.State)]" -ForegroundColor $colors.Info } } } else { Write-Host "Network Connections: None" -ForegroundColor $colors.Info } # Show loaded modules (DLLs) - top 10 by size Write-Host "" Write-Host "=== Loaded Modules (Top 10 by Size) ===" -ForegroundColor $colors.Header try { $modules = $targetProcess.Modules | Sort-Object ModuleMemorySize -Descending | Select-Object -First 10 if ($modules -and $modules.Count -gt 0) { foreach ($module in $modules) { $sizeKB = [math]::Round($module.ModuleMemorySize / 1KB, 1) Write-Host " └─ $($module.ModuleName) - $sizeKB KB" -ForegroundColor $colors.Info } } else { Write-Host " No modules accessible (may be system process or access denied)" -ForegroundColor $colors.Warning } } catch { Write-Host " Modules: Access denied (likely system process or insufficient privileges)" -ForegroundColor $colors.Warning } # Add process uptime calculation Write-Host "" Write-Host "=== Additional Information ===" -ForegroundColor $colors.Header if ($targetProcess.StartTime) { $uptime = (Get-Date) - $targetProcess.StartTime $uptimeString = "{0:dd} days, {0:hh} hours, {0:mm} minutes, {0:ss} seconds" -f $uptime Write-Host "Uptime: $uptimeString" -ForegroundColor $colors.Info } # Show process working set details Write-Host "Working Set: $([math]::Round($targetProcess.WorkingSet64 / 1MB, 1)) MB" Write-Host "Peak Working Set: $([math]::Round($targetProcess.PeakWorkingSet64 / 1MB, 1)) MB" Write-Host "Virtual Memory: $([math]::Round($targetProcess.VirtualMemorySize64 / 1MB, 1)) MB" Write-Host "Peak Virtual Memory: $([math]::Round($targetProcess.PeakVirtualMemorySize64 / 1MB, 1)) MB" Write-Host "" } function Call-AdminHelper { param([string]$Operation, [string]$TargetValue, [bool]$ForceOperation) $scriptPath = Join-Path $PSScriptRoot "admin_helper.ps1" if (-not (Test-Path $scriptPath)) { Write-Host "Error: admin_helper.ps1 not found at $scriptPath" -ForegroundColor $colors.Error return $false } try { $forceArg = if ($ForceOperation) { " -Force" } else { "" } $cmd = "Start-Process powershell -ArgumentList '-ExecutionPolicy Bypass -File `"$scriptPath`" -Operation $Operation -Target `"$TargetValue`"$forceArg' -Verb RunAs -Wait" Write-Host "Requesting admin privileges for operation..." -ForegroundColor $colors.Warning Invoke-Expression $cmd return $true } catch { Write-Host "Error executing admin operation: $_" -ForegroundColor $colors.Error return $false } } # Main execution $TargetString = if ($Target) { $Target -join "," } else { "" } switch ($Command) { "check-ports" { Check-Ports -PortList $TargetString } "all-ports" { Get-AllPorts } "find-service" { Find-ServiceByPattern -Pattern $TargetString } "service-info" { if (-not $TargetString) { Write-Host "Error: Service name required" -ForegroundColor $colors.Error return } $service = Get-Service -Name $TargetString -ErrorAction SilentlyContinue if ($service) { Write-Host "Service: $($service.Name)" -ForegroundColor $colors.Header Write-Host "Display Name: $($service.DisplayName)" Write-Host "Status: $($service.Status)" -ForegroundColor $( if ($service.Status -eq 'Running') { $colors.Success } else { $colors.Warning } ) Write-Host "Start Type: $($service.StartType)" } else { Write-Host "Service '$TargetString' not found" -ForegroundColor $colors.Error } } "process-info" { if (-not $TargetString) { Write-Host "Error: Process ID required" -ForegroundColor $colors.Error return } Get-ProcessChainInfo -ProcessId $TargetString } "kill-process" { if (-not $TargetString) { Write-Host "Error: Process ID required" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "kill-process" -TargetValue $TargetString -ForceOperation $Force } "kill-port" { if (-not $TargetString) { Write-Host "Error: Port number(s) required" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "kill-by-port" -TargetValue $TargetString -ForceOperation $Force } "kill-multiple" { if (-not $TargetString) { Write-Host "Error: Process IDs required (comma-separated)" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "kill-multiple" -TargetValue $TargetString -ForceOperation $Force } "stop-service" { if (-not $TargetString) { Write-Host "Error: Service name required" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "stop-service" -TargetValue $TargetString -ForceOperation $Force } "start-service" { if (-not $TargetString) { Write-Host "Error: Service name required" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "start-service" -TargetValue $TargetString -ForceOperation $Force } "restart-service" { if (-not $TargetString) { Write-Host "Error: Service name required" -ForegroundColor $colors.Error return } Call-AdminHelper -Operation "restart-service" -TargetValue $TargetString -ForceOperation $Force } "help" { Show-Help } default { Write-Host "Unknown command: $Command" -ForegroundColor $colors.Error Show-Help } }

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/smspgh/portmaster_mcp'

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