mid-server
SKILL.md
MID Server for ServiceNow
MID Server enables ServiceNow to communicate with resources inside your network.
MID Server Architecture
ServiceNow Instance
↓ ECC Queue
MID Server
├── Probes (Outbound)
│ └── Commands sent TO MID
├── Sensors (Inbound)
│ └── Results sent FROM MID
└── Script Execution
Key Tables
| Table | Purpose |
|---|---|
ecc_agent |
MID Server records |
ecc_queue |
Input/Output queue |
discovery_probes |
Probe definitions |
discovery_sensors |
Sensor definitions |
sys_script_execution |
Script execution requests |
ECC Queue Communication (ES5)
Send Command to MID Server
// Send command via ECC queue (ES5 ONLY!)
function sendMIDCommand(midServerName, command, parameters) {
var mid = getMIDServer(midServerName)
if (!mid) {
gs.error("MID Server not found: " + midServerName)
return null
}
var ecc = new GlideRecord("ecc_queue")
ecc.initialize()
// ECC Queue settings
ecc.setValue("agent", mid.getUniqueValue())
ecc.setValue("topic", "Command")
ecc.setValue("name", command)
ecc.setValue("source", "CustomScript")
// Parameters as payload
ecc.setValue("payload", buildPayload(parameters))
// Direction: output = to MID, input = from MID
ecc.setValue("queue", "output")
// State
ecc.setValue("state", "ready")
return ecc.insert()
}
function getMIDServer(name) {
var mid = new GlideRecord("ecc_agent")
mid.addQuery("name", name)
mid.addQuery("status", "Up")
mid.query()
if (mid.next()) {
return mid
}
return null
}
function buildPayload(params) {
var xml = '<?xml version="1.0" encoding="UTF-8"?>'
xml += "<parameters>"
for (var key in params) {
if (params.hasOwnProperty(key)) {
xml += '<parameter name="' + key + '">'
xml += "<value>" + escapeXML(params[key]) + "</value>"
xml += "</parameter>"
}
}
xml += "</parameters>"
return xml
}
function escapeXML(str) {
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
}
Monitor ECC Response
// Wait for ECC queue response (ES5 ONLY!)
function waitForECCResponse(eccSysId, timeoutSeconds) {
var startTime = new Date().getTime()
var timeout = timeoutSeconds * 1000
while (true) {
// Check for response
var response = new GlideRecord("ecc_queue")
response.addQuery("response_to", eccSysId)
response.addQuery("queue", "input")
response.query()
if (response.next()) {
return {
success: response.getValue("state") === "processed",
payload: response.getValue("payload"),
error: response.getValue("error_string"),
}
}
// Check timeout
if (new Date().getTime() - startTime > timeout) {
return {
success: false,
error: "Timeout waiting for MID response",
}
}
// Wait before retry
gs.sleep(1000)
}
}
MID Server Scripts (ES5)
Execute Script on MID
// Execute JavaScript on MID Server (ES5 ONLY!)
function executeMIDScript(midServerName, script) {
var mid = getMIDServer(midServerName)
if (!mid) {
return { success: false, error: "MID Server not found" }
}
var ecc = new GlideRecord("ecc_queue")
ecc.initialize()
ecc.setValue("agent", mid.getUniqueValue())
ecc.setValue("topic", "JSProbe")
ecc.setValue("name", "Custom Script Execution")
// Script payload
var payload = '<?xml version="1.0" encoding="UTF-8"?>'
payload += "<parameters>"
payload += '<parameter name="script"><value><![CDATA[' + script + "]]></value></parameter>"
payload += "</parameters>"
ecc.setValue("payload", payload)
ecc.setValue("queue", "output")
ecc.setValue("state", "ready")
var eccSysId = ecc.insert()
return {
success: true,
ecc_sys_id: eccSysId,
}
}
// Example: Check disk space on remote server
var diskCheckScript = [
"var output = {};",
"try {",
' var cmd = "df -h /";',
" var result = Packages.com.service_now.mid.probe.tpcon.OperatingSystemCommand.execute(cmd);",
" output.disk_info = result.getOutput();",
" output.success = true;",
"} catch (e) {",
" output.success = false;",
" output.error = e.message;",
"}",
"output;",
].join("\n")
Custom Probes (ES5)
Create Probe
// Create custom probe (ES5 ONLY!)
var probe = new GlideRecord("discovery_probes")
probe.initialize()
probe.setValue("name", "Custom Application Status")
probe.setValue("short_description", "Check custom application status")
probe.setValue("active", true)
// Probe type
probe.setValue("mid_type", "probe")
// Trigger type
probe.setValue("triggered_by", "on_demand")
// Probe script (runs on MID Server - ES5/Rhino!)
probe.setValue(
"script",
"var output = {};\n" +
"\n" +
"// Get parameters\n" +
'var host = probe.getParameter("host");\n' +
'var port = probe.getParameter("port");\n' +
"\n" +
"try {\n" +
" // Execute health check\n" +
' var url = "http://" + host + ":" + port + "/health";\n' +
" var conn = new java.net.URL(url).openConnection();\n" +
' conn.setRequestMethod("GET");\n' +
" conn.setConnectTimeout(5000);\n" +
" conn.setReadTimeout(5000);\n" +
" \n" +
" var responseCode = conn.getResponseCode();\n" +
' output.status = (responseCode === 200) ? "healthy" : "unhealthy";\n' +
" output.response_code = responseCode;\n" +
" output.success = true;\n" +
"} catch (e) {\n" +
' output.status = "unreachable";\n' +
" output.error = e.message;\n" +
" output.success = false;\n" +
"}\n" +
"\n" +
"output;",
)
probe.insert()
Create Sensor
// Create sensor to process probe results (ES5 ONLY!)
var sensor = new GlideRecord("discovery_sensors")
sensor.initialize()
sensor.setValue("name", "Process Application Status")
sensor.setValue("short_description", "Process custom application status results")
sensor.setValue("active", true)
// Link to probe
sensor.setValue("triggered_by", probeSysId)
// Sensor script (runs on ServiceNow instance - ES5!)
sensor.setValue(
"script",
"(function process(result, source) {\n" +
" var output = JSON.parse(result.output);\n" +
" \n" +
" // Find or create application CI\n" +
' var appCI = new GlideRecord("cmdb_ci_appl");\n' +
' appCI.addQuery("name", source.getParameter("app_name"));\n' +
" appCI.query();\n" +
" \n" +
" if (!appCI.next()) {\n" +
" appCI.initialize();\n" +
' appCI.name = source.getParameter("app_name");\n' +
" appCI.insert();\n" +
" }\n" +
" \n" +
" // Update status\n" +
" appCI.u_health_status = output.status;\n" +
" appCI.u_last_health_check = new GlideDateTime();\n" +
" appCI.update();\n" +
" \n" +
" // Create event if unhealthy\n" +
' if (output.status !== "healthy") {\n' +
" createHealthAlert(appCI, output);\n" +
" }\n" +
"})(result, source);",
)
sensor.insert()
Orchestration (ES5)
Remote PowerShell
// Execute PowerShell on Windows server (ES5 ONLY!)
function executeRemotePowerShell(midServerName, targetHost, script, credential) {
var payload = [
'<?xml version="1.0" encoding="UTF-8"?>',
"<parameters>",
' <parameter name="host"><value>' + targetHost + "</value></parameter>",
' <parameter name="credential_id"><value>' + credential + "</value></parameter>",
' <parameter name="script"><value><![CDATA[' + script + "]]></value></parameter>",
"</parameters>",
].join("\n")
var mid = getMIDServer(midServerName)
if (!mid) {
return { success: false, error: "MID Server not found" }
}
var ecc = new GlideRecord("ecc_queue")
ecc.initialize()
ecc.setValue("agent", mid.getUniqueValue())
ecc.setValue("topic", "PowerShell")
ecc.setValue("name", "Remote PowerShell Execution")
ecc.setValue("payload", payload)
ecc.setValue("queue", "output")
ecc.setValue("state", "ready")
return {
success: true,
ecc_sys_id: ecc.insert(),
}
}
Remote SSH
// Execute SSH command (ES5 ONLY!)
function executeRemoteSSH(midServerName, targetHost, command, credential) {
var payload = [
'<?xml version="1.0" encoding="UTF-8"?>',
"<parameters>",
' <parameter name="host"><value>' + targetHost + "</value></parameter>",
' <parameter name="credential_id"><value>' + credential + "</value></parameter>",
' <parameter name="command"><value>' + escapeXML(command) + "</value></parameter>",
"</parameters>",
].join("\n")
var mid = getMIDServer(midServerName)
if (!mid) {
return { success: false, error: "MID Server not found" }
}
var ecc = new GlideRecord("ecc_queue")
ecc.initialize()
ecc.setValue("agent", mid.getUniqueValue())
ecc.setValue("topic", "SSHCommand")
ecc.setValue("name", "Remote SSH Execution")
ecc.setValue("payload", payload)
ecc.setValue("queue", "output")
ecc.setValue("state", "ready")
return {
success: true,
ecc_sys_id: ecc.insert(),
}
}
MID Server Monitoring (ES5)
Check MID Status
// Get MID Server status (ES5 ONLY!)
function getMIDServerStatus() {
var servers = []
var mid = new GlideRecord("ecc_agent")
mid.addQuery("status", "!=", "Decommissioned")
mid.query()
while (mid.next()) {
servers.push({
name: mid.getValue("name"),
status: mid.getValue("status"),
ip: mid.getValue("ip_address"),
version: mid.getValue("version"),
validated: mid.getValue("validated"),
last_refreshed: mid.getValue("last_refreshed"),
host_name: mid.getValue("host_name"),
})
}
return servers
}
MCP Tool Integration
Available Tools
| Tool | Purpose |
|---|---|
snow_query_table |
Query MID and ECC tables |
snow_find_artifact |
Find probes/sensors |
snow_execute_script_with_output |
Test MID scripts |
Example Workflow
// 1. Check MID Server status
await snow_query_table({
table: "ecc_agent",
query: "status=Up",
fields: "name,ip_address,version,last_refreshed",
})
// 2. Query ECC queue
await snow_query_table({
table: "ecc_queue",
query: "queue=output^state=ready",
fields: "agent,topic,name,state,sys_created_on",
})
// 3. Find probes
await snow_query_table({
table: "discovery_probes",
query: "active=true",
fields: "name,short_description,mid_type",
})
Best Practices
- Credentials - Never hardcode in scripts
- Error Handling - Handle network failures
- Timeouts - Set appropriate timeouts
- Logging - Log for troubleshooting
- Security - Limit MID access
- Monitoring - Track MID health
- Load Balancing - Multiple MIDs for HA
- ES5 Only - No modern JavaScript syntax
Weekly Installs
49
Repository
groeimetai/snow-flowGitHub Stars
51
First Seen
Jan 22, 2026
Security Audits
Installed on
claude-code45
github-copilot44
gemini-cli44
opencode44
codex44
cursor43