From connectwise-automate
Manages ConnectWise Automate computers/endpoints: lists, searches, monitors status (online/offline), inventory, patches, antivirus, and remote operations.
npx claudepluginhub wyre-technology/msp-claude-plugins --plugin connectwise-automateThis skill uses the workspace's default tool permissions.
Computers are the core managed entities in ConnectWise Automate. Each computer represents an endpoint with the Automate agent installed - workstations, servers, or network devices. This skill covers computer identification, status monitoring, inventory, patch management, and antivirus status.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Compresses source documents into lossless, LLM-optimized distillates preserving all facts and relationships. Use for 'distill documents' or 'create distillate' requests.
Computers are the core managed entities in ConnectWise Automate. Each computer represents an endpoint with the Automate agent installed - workstations, servers, or network devices. This skill covers computer identification, status monitoring, inventory, patch management, and antivirus status.
Every computer has multiple identifiers:
| Identifier | Type | Description | Example |
|---|---|---|---|
ComputerID | integer | Primary key, auto-incrementing | 12345 |
Name | string | Computer hostname | ACME-DC01 |
ComputerGUID | string | Globally unique identifier | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
LastContact | datetime | Last agent check-in time | 2024-02-15T10:30:00Z |
MAC | string | Primary MAC address | 00:1A:2B:3C:4D:5E |
| Status | Description | Business Impact |
|---|---|---|
Online | Agent actively checking in | Normal operation |
Offline | No agent communication | May require attention |
Degraded | Agent checking in with issues | Performance concerns |
Unknown | Status undetermined | Check connectivity |
| OS Type | Examples |
|---|---|
Windows Server | 2016, 2019, 2022 |
Windows Workstation | Windows 10, Windows 11 |
macOS | Monterey, Ventura, Sonoma |
Linux | Ubuntu, CentOS, RHEL |
interface Computer {
// Identifiers
ComputerID: number; // Primary key
Name: string; // Hostname
ComputerGUID: string; // GUID
// Client/Location Association
ClientID: number; // Parent client ID
LocationID: number; // Location within client
Client: {
Name: string; // Client name
};
Location: {
Name: string; // Location name
};
// Status
Status: string; // Online, Offline, Degraded
LastContact: string; // ISO datetime of last check-in
Uptime: number; // Uptime in seconds
// Network
IPAddress: string; // Internal IP
ExternalIP: string; // External/public IP
DefaultGateway: string; // Gateway IP
MAC: string; // Primary MAC address
// Operating System
OS: string; // "Windows 10 Pro"
OSType: string; // "Windows", "macOS", "Linux"
OSVersion: string; // "10.0.19045"
SerialNumber: string; // OS serial/product key
// Hardware
Manufacturer: string; // "Dell Inc."
Model: string; // "OptiPlex 7090"
TotalMemory: number; // RAM in MB
ProcessorName: string; // CPU model
ProcessorCount: number; // Number of CPUs
// Agent
AgentVersion: string; // "2023.1.0.123"
RemoteAgentVersion: string; // Remote agent version
// Timestamps
DateAdded: string; // When computer was added
LastInventory: string; // Last inventory scan
LastPatched: string; // Last patch operation
// Extra Data Fields (EDFs)
ExtraData: {
[key: string]: string; // Custom fields
};
}
interface ComputerInventory {
// Disk Information
Drives: DriveInfo[];
// Software
Software: SoftwareItem[];
// Hardware
Memory: MemoryModule[];
NetworkAdapters: NetworkAdapter[];
Printers: Printer[];
// Services
Services: Service[];
// Monitors/Displays
Monitors: Monitor[];
}
interface DriveInfo {
Letter: string; // "C:"
Type: string; // "Fixed", "Network", "Removable"
FileSystem: string; // "NTFS"
TotalSize: number; // Size in MB
FreeSpace: number; // Free space in MB
PercentFree: number; // Percentage free
}
interface SoftwareItem {
Name: string; // Application name
Publisher: string; // Software publisher
Version: string; // Installed version
InstallDate: string; // When installed
}
GET /cwa/api/v1/Computers?pageSize=250
Authorization: Bearer {token}
Response:
[
{
"ComputerID": 12345,
"Name": "ACME-DC01",
"ClientID": 100,
"LocationID": 1,
"Status": "Online",
"IPAddress": "192.168.1.10",
"OS": "Windows Server 2022 Standard",
"LastContact": "2024-02-15T10:30:00Z",
"Client": {
"Name": "Acme Corporation"
},
"Location": {
"Name": "Main Office"
}
}
]
GET /cwa/api/v1/Computers/{computerID}
Authorization: Bearer {token}
Response:
{
"ComputerID": 12345,
"Name": "ACME-DC01",
"ComputerGUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"ClientID": 100,
"LocationID": 1,
"Status": "Online",
"IPAddress": "192.168.1.10",
"ExternalIP": "203.0.113.50",
"MAC": "00:1A:2B:3C:4D:5E",
"OS": "Windows Server 2022 Standard",
"OSVersion": "10.0.20348",
"Manufacturer": "Dell Inc.",
"Model": "PowerEdge R640",
"SerialNumber": "ABC1234567",
"TotalMemory": 32768,
"ProcessorName": "Intel Xeon Gold 6230",
"AgentVersion": "2023.1.0.123",
"LastContact": "2024-02-15T10:30:00Z",
"Uptime": 864000,
"DateAdded": "2023-01-15T08:00:00Z"
}
GET /cwa/api/v1/Computers?condition=ClientID = 100&pageSize=250
Authorization: Bearer {token}
GET /cwa/api/v1/Computers?condition=Status = 'Online'&pageSize=250
Authorization: Bearer {token}
GET /cwa/api/v1/Computers?condition=OS contains 'Windows Server'&pageSize=250
Authorization: Bearer {token}
GET /cwa/api/v1/Computers/{computerID}/Drives
Authorization: Bearer {token}
Response:
[
{
"DriveID": 1,
"Letter": "C:",
"Type": "Fixed",
"FileSystem": "NTFS",
"TotalSize": 500000,
"FreeSpace": 150000,
"PercentFree": 30
}
]
GET /cwa/api/v1/Computers/{computerID}/Software
Authorization: Bearer {token}
GET /cwa/api/v1/Computers/{computerID}/Patches
Authorization: Bearer {token}
Response:
{
"Installed": 145,
"Missing": 3,
"Pending": 2,
"Failed": 0,
"Patches": [
{
"KBID": "KB5034441",
"Title": "2024-01 Security Update",
"Status": "Missing",
"Severity": "Critical",
"ReleaseDate": "2024-01-09T00:00:00Z"
}
]
}
GET /cwa/api/v1/Computers/{computerID}/Antivirus
Authorization: Bearer {token}
Response:
{
"Product": "Windows Defender",
"Version": "4.18.2401.7",
"DefinitionVersion": "1.405.123.0",
"DefinitionDate": "2024-02-15T00:00:00Z",
"RealTimeProtection": true,
"LastScan": "2024-02-15T03:00:00Z",
"ScanType": "Quick",
"ThreatsFound": 0
}
async function findComputerByHostname(client, hostname) {
const computers = await client.request(
`/Computers?condition=Name contains '${hostname}'&pageSize=100`
);
if (computers.length === 0) {
return { found: false, suggestions: [] };
}
if (computers.length === 1) {
return { found: true, computer: computers[0] };
}
return {
found: false,
ambiguous: true,
suggestions: computers.map(c => ({
name: c.Name,
id: c.ComputerID,
client: c.Client?.Name,
status: c.Status
}))
};
}
async function findComputerByIP(client, ipAddress) {
const computers = await client.request(
`/Computers?condition=IPAddress = '${ipAddress}' or ExternalIP = '${ipAddress}'`
);
return computers[0] || null;
}
async function getOfflineComputers(client, options = {}) {
const { clientId, offlineMinutes = 30 } = options;
let condition = "Status = 'Offline'";
if (clientId) {
condition += ` and ClientID = ${clientId}`;
}
const computers = await client.request(
`/Computers?condition=${encodeURIComponent(condition)}&pageSize=500`
);
const now = new Date();
return computers.map(computer => ({
name: computer.Name,
id: computer.ComputerID,
client: computer.Client?.Name,
location: computer.Location?.Name,
lastContact: computer.LastContact,
offlineMinutes: Math.floor(
(now - new Date(computer.LastContact)) / 60000
)
}));
}
async function getLowDiskSpaceComputers(client, threshold = 10) {
// Get all computers
const computers = await client.request('/Computers?pageSize=500');
const lowDiskComputers = [];
for (const computer of computers) {
const drives = await client.request(
`/Computers/${computer.ComputerID}/Drives`
);
const lowDrives = drives.filter(d =>
d.Type === 'Fixed' && d.PercentFree < threshold
);
if (lowDrives.length > 0) {
lowDiskComputers.push({
computer: computer.Name,
client: computer.Client?.Name,
drives: lowDrives.map(d => ({
letter: d.Letter,
percentFree: d.PercentFree,
freeGB: Math.round(d.FreeSpace / 1024)
}))
});
}
// Respect rate limits
await sleep(100);
}
return lowDiskComputers;
}
async function getPatchComplianceReport(client, clientId) {
let condition = '';
if (clientId) {
condition = `?condition=ClientID = ${clientId}`;
}
const computers = await client.request(`/Computers${condition}&pageSize=500`);
const report = {
total: computers.length,
compliant: 0,
nonCompliant: 0,
computers: []
};
for (const computer of computers) {
const patches = await client.request(
`/Computers/${computer.ComputerID}/Patches`
);
const isCompliant = patches.Missing === 0 && patches.Failed === 0;
if (isCompliant) {
report.compliant++;
} else {
report.nonCompliant++;
report.computers.push({
name: computer.Name,
missing: patches.Missing,
failed: patches.Failed
});
}
await sleep(100);
}
return report;
}
| Error | Status | Cause | Resolution |
|---|---|---|---|
| Computer not found | 404 | Invalid ComputerID | Verify computer exists |
| Invalid filter | 400 | Malformed condition | Check OData syntax |
| Permission denied | 403 | Insufficient rights | Check user permissions |
| Rate limited | 429 | Too many requests | Wait and retry |
{
"error": {
"code": "NotFound",
"message": "Computer with ID 99999 not found"
}
}
function validateComputerQuery(params) {
const errors = [];
if (params.condition) {
// Validate OData operators
const validOperators = ['=', '!=', '<', '>', '<=', '>=', 'contains', 'startswith'];
const hasValidOperator = validOperators.some(op =>
params.condition.includes(op)
);
if (!hasValidOperator) {
errors.push('Invalid condition operator');
}
}
if (params.pageSize && (params.pageSize < 1 || params.pageSize > 1000)) {
errors.push('pageSize must be between 1 and 1000');
}
return {
valid: errors.length === 0,
errors
};
}
function assessComputerHealth(computer, patches, antivirus, drives) {
const issues = [];
// Check online status
if (computer.Status !== 'Online') {
issues.push({
severity: 'critical',
message: `Computer is ${computer.Status}`
});
}
// Check agent age
const lastContact = new Date(computer.LastContact);
const minutesSinceContact = (Date.now() - lastContact) / 60000;
if (minutesSinceContact > 60) {
issues.push({
severity: 'warning',
message: `No contact in ${Math.round(minutesSinceContact)} minutes`
});
}
// Check patch status
if (patches.Missing > 0) {
const severity = patches.Missing > 10 ? 'critical' : 'warning';
issues.push({
severity,
message: `${patches.Missing} missing patch(es)`
});
}
// Check antivirus
if (!antivirus.RealTimeProtection) {
issues.push({
severity: 'critical',
message: 'Real-time protection disabled'
});
}
const defAge = (Date.now() - new Date(antivirus.DefinitionDate)) / 86400000;
if (defAge > 7) {
issues.push({
severity: 'warning',
message: `AV definitions ${Math.round(defAge)} days old`
});
}
// Check disk space
for (const drive of drives) {
if (drive.Type === 'Fixed' && drive.PercentFree < 10) {
issues.push({
severity: drive.PercentFree < 5 ? 'critical' : 'warning',
message: `Drive ${drive.Letter} only ${drive.PercentFree}% free`
});
}
}
return {
healthy: issues.filter(i => i.severity === 'critical').length === 0,
issues
};
}