check_printer_connectivity
check_printer_connectivity
Tests TCP connectivity to a network printer on standard ports: 9100 (raw/JetDirect), 631 (IPP), 80 (HTTP admin). Use to determine if a printer issue is network-level vs driver/software level.
Metadata
Name
check_printer_connectivity
Updated
2 months ago
Source
Risk
Low
Requires consent
false
Affected scope
user
Code
/**
* mcp/skills/checkPrinterConnectivity.ts — check_printer_connectivity skill
*
* Tests TCP connectivity to a network printer on standard ports:
* 9100 (raw/JetDirect), 631 (IPP), 80 (HTTP admin).
* Use to determine if a printer issue is network-level vs driver/software level.
*
* Platform strategy
* -----------------
* darwin & win32 Pure Node.js net.createConnection() — platform independent.
* For each port, attempts connection with timeout and records
* success/latency.
*
* Smoke test
* npx tsx -r dotenv/config mcp/skills/checkPrinterConnectivity.ts
*/
import * as os from "os";
import * as net from "net";
import { z } from "zod";
// -- Meta ---------------------------------------------------------------------
export const meta = {
name: "check_printer_connectivity",
description:
"Tests TCP connectivity to a network printer on standard ports: " +
"9100 (raw/JetDirect), 631 (IPP), 80 (HTTP admin). " +
"Use to determine if a printer issue is network-level vs driver/software level.",
riskLevel: "low",
destructive: false,
requiresConsent: false,
supportsDryRun: false,
affectedScope: ["user"],
auditRequired: false,
schema: {
host: z
.string()
.describe("Printer IP address or hostname"),
ports: z
.array(z.number())
.optional()
.describe("Ports to test. Default: [9100, 631, 80]"),
timeoutMs: z
.number()
.optional()
.describe("Timeout per port in ms. Default: 3000"),
},
} as const;
// -- Types --------------------------------------------------------------------
interface PrinterPortResult {
port: number;
service: string;
reachable: boolean;
latencyMs: number | null;
}
// -- Helpers ------------------------------------------------------------------
function portService(port: number): string {
switch (port) {
case 9100: return "raw/JetDirect";
case 631: return "IPP";
case 80: return "HTTP admin";
default: return "unknown";
}
}
function testPort(host: string, port: number, timeoutMs: number): Promise<PrinterPortResult> {
return new Promise((resolve) => {
const service = portService(port);
const startedAt = Date.now();
let resolved = false;
const finish = (result: PrinterPortResult) => {
if (!resolved) {
resolved = true;
socket.destroy();
resolve(result);
}
};
const socket = net.createConnection({ host, port });
socket.setTimeout(timeoutMs);
socket.on("connect", () => {
const latencyMs = Date.now() - startedAt;
finish({ port, service, reachable: true, latencyMs });
});
socket.on("timeout", () => {
finish({ port, service, reachable: false, latencyMs: null });
});
socket.on("error", () => {
finish({ port, service, reachable: false, latencyMs: null });
});
});
}
// -- Exported run function ----------------------------------------------------
export async function run({
host,
ports = [9100, 631, 80],
timeoutMs = 3000,
}: {
host: string;
ports?: number[];
timeoutMs?: number;
}) {
const results = await Promise.all(ports.map((p) => testPort(host, p, timeoutMs)));
const isReachable = results.some((r) => r.reachable);
// Build recommendation based on which ports are open
const ipp631 = results.find((r) => r.port === 631 && r.reachable);
let recommendation = "";
if (ipp631) {
recommendation = `IPP is available. Recommended printer URI: ipp://${host}/ipp/print`;
} else if (results.find((r) => r.port === 9100 && r.reachable)) {
recommendation = `Raw/JetDirect is available. Recommended printer URI: socket://${host}:9100`;
} else if (!isReachable) {
recommendation = "Printer is not reachable on any tested port. Check network connection, IP address, and that the printer is powered on.";
} else {
recommendation = "Some ports are open. Check printer documentation for the correct URI.";
}
return {
host,
ports: results,
isReachable,
recommendation,
platform: os.platform(),
};
}
// -- Smoke test ---------------------------------------------------------------
if (false) {
run({ host: "192.168.1.100" })
.then(r => console.log(JSON.stringify(r, null, 2)))
.catch((err: Error) => { console.error(err.message); process.exit(1); });
}