UNPKG

aironin-browse-mcp

Version:

aiRonin Browse MCP server with headed Chrome support

163 lines 5.53 kB
import * as net from "node:net"; import axios from "axios"; import * as dns from "node:dns"; /** * Check if a port is open on a given host */ export async function isPortOpen(host, port, timeout = 1000) { return new Promise((resolve) => { const socket = new net.Socket(); let status = false; // Set timeout socket.setTimeout(timeout); // Handle successful connection socket.on("connect", () => { status = true; socket.destroy(); }); // Handle any errors socket.on("error", () => { socket.destroy(); }); // Handle timeout socket.on("timeout", () => { socket.destroy(); }); // Handle close socket.on("close", () => { resolve(status); }); // Attempt to connect socket.connect(port, host); }); } /** * Try to connect to Chrome at a specific IP address */ export async function tryChromeHostUrl(chromeHostUrl) { try { console.error(`Trying to connect to Chrome at: ${chromeHostUrl}/json/version`); await axios.get(`${chromeHostUrl}/json/version`, { timeout: 1000 }); return true; } catch (error) { return false; } } /** * Get Docker host IP */ export async function getDockerHostIP() { try { // Try to resolve host.docker.internal (works on Docker Desktop) return new Promise((resolve) => { dns.lookup("host.docker.internal", (err, address) => { if (err) { resolve(null); } else { resolve(address); } }); }); } catch (error) { console.error("Could not determine Docker host IP:", error); return null; } } /** * Scan a network range for Chrome debugging port */ export async function scanNetworkForChrome(baseIP, port) { if (!baseIP || !baseIP.match(/^\d+\.\d+\.\d+\./)) { return null; } // Extract the network prefix (e.g., "192.168.65.") const networkPrefix = baseIP.split(".").slice(0, 3).join(".") + "."; // Common Docker host IPs to try first const priorityIPs = [ networkPrefix + "1", // Common gateway networkPrefix + "2", // Common host networkPrefix + "254", // Common host in some Docker setups ]; console.error(`Scanning priority IPs in network ${networkPrefix}*`); // Check priority IPs first for (const ip of priorityIPs) { const isOpen = await isPortOpen(ip, port); if (isOpen) { console.error(`Found Chrome debugging port open on ${ip}`); return ip; } } return null; } // Function to discover Chrome instances on the network const discoverChromeHosts = async (port) => { // Get all network interfaces const ipAddresses = []; // Try to get Docker host IP const hostIP = await getDockerHostIP(); if (hostIP) { console.error("Found Docker host IP:", hostIP); ipAddresses.push(hostIP); } // Remove duplicates const uniqueIPs = [...new Set(ipAddresses)]; console.error("IP Addresses to try:", uniqueIPs); // Try connecting to each IP address for (const ip of uniqueIPs) { const hostEndpoint = `http://${ip}:${port}`; const hostIsValid = await tryChromeHostUrl(hostEndpoint); if (hostIsValid) { // Store the successful IP for future use console.error(`✅ Found Chrome at ${hostEndpoint}`); // Return the host URL and endpoint return hostEndpoint; } } return null; }; /** * Test connection to a remote browser debugging websocket. * First tries specific hosts, then attempts auto-discovery if needed. * @param browserHostUrl Optional specific host URL to check first * @param port Browser debugging port (default: 9222) * @returns WebSocket debugger URL if connection is successful, null otherwise */ export async function discoverChromeHostUrl(port = 9222) { // First try specific hosts const hostsToTry = [`http://localhost:${port}`, `http://127.0.0.1:${port}`]; // Try each host directly first for (const hostUrl of hostsToTry) { console.error(`Trying to connect to: ${hostUrl}`); try { const hostIsValid = await tryChromeHostUrl(hostUrl); if (hostIsValid) return hostUrl; } catch (error) { console.error(`Failed to connect to ${hostUrl}: ${error instanceof Error ? error.message : error}`); } } // If direct connections failed, attempt auto-discovery console.error("Direct connections failed. Attempting auto-discovery..."); const discoveredHostUrl = await discoverChromeHosts(port); if (discoveredHostUrl) { console.error(`Trying to connect to discovered host: ${discoveredHostUrl}`); try { const hostIsValid = await tryChromeHostUrl(discoveredHostUrl); if (hostIsValid) return discoveredHostUrl; console.error(`Failed to connect to discovered host ${discoveredHostUrl}`); } catch (error) { console.error(`Error connecting to discovered host: ${error instanceof Error ? error.message : error}`); } } else { console.error("No browser instances discovered on network"); } return null; } //# sourceMappingURL=browserDiscovery.js.map