Skip to main content
Glama
tecnomanu

Network Monitor MCP Server

by tecnomanu
README.md
# 📡 Network Monitor — MCP Server + Real-time Web Dashboard

A single Node.js project that does two things:

1. **An MCP server** exposing network tools (`get_network_status`, `ping_device`, `scan_network`) that any MCP client (Claude Desktop, etc.) can call.
2. **A modern web dashboard** on **port `39824`** with live latency graphs, a device list, and a scan button — dark-mode, clean, and mobile-friendly so you can watch it from your phone.

It is built entirely on Node's `child_process` calling the system `ping` and `arp` commands — **no native modules, no root required** — so it runs the same on macOS, Linux, and Windows.

---

## ✨ Features

- **Real-time latency** to your **gateway (`192.168.18.1`)** and the **internet (`8.8.8.8`)**, sampled every 2 s and streamed to the browser over **WebSockets**.
- **Live latency chart** (Chart.js) with a smooth rolling 40-point window and separate gateway/internet series.
- **Active device list** for the **`192.168.18.0/24`** subnet — each device shows its **IP, ping time, MAC address, and vendor** (offline OUI lookup).
- **One-click network scan** — ping-sweeps all 254 hosts in bounded-concurrency batches, then enriches responders from the ARP cache. Live progress bar included.
- **Beautiful UI** — dark mode, glassy cards, status badges (excellent / good / slow / offline), gateway highlighting, responsive table on desktop and stacked cards on mobile.
- **MCP tools** callable from any MCP-compatible client.
- **Zero native dependencies** — only `express`, `ws`, and the MCP SDK.

---

## 🚀 Quick start

```bash
npm install      # already done if you're reading this after setup
npm start        # starts the web dashboard on port 39824
```

Then open **<http://localhost:39824>** — or from your phone, `http://<your-computer-ip>:39824` (same Wi-Fi).

> The server is typically already running after setup. Check with:
> ```bash
> curl -s http://localhost:39824/api/status
> ```

---

## 🖥️ Running modes

| Command | What it runs |
|---|---|
| `npm start` / `node index.js` | **Web dashboard only** (port 39824). |
| `npm run mcp` / `node mcp-server.js` | **MCP server over stdio** — *and* it also boots the dashboard, so you get tools + UI from one command. |

To run the MCP server **without** the web dashboard (e.g. inside an MCP client that only wants stdio):

```bash
NM_NO_DASHBOARD=1 node mcp-server.js
```

---

## 🔌 Using it as an MCP server

Add this to your MCP client config (e.g. Claude Desktop's `claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "network-monitor": {
      "command": "node",
      "args": ["/absolute/path/to/network-mcp/mcp-server.js"],
      "env": { "NM_NO_DASHBOARD": "1" }
    }
  }
}
```

### Exposed tools

| Tool | Description | Arguments |
|---|---|---|
| `get_network_status` | Latency + reachability to the gateway and internet host, plus online/offline. | *(none)* |
| `ping_device` | Ping one IP/hostname once; returns `alive` + `rtt` (ms). | `host` (required), `timeoutMs` (optional) |
| `scan_network` | Ping-sweep the /24 subnet and return active devices with MAC + vendor. | `subnet` (optional, e.g. `"192.168.18"`) |

---

## 🌐 REST endpoints (bonus)

The dashboard is driven by WebSockets, but these are handy for scripting/debugging:

| Endpoint | Returns |
|---|---|
| `GET /api/status` | Current gateway/internet latency snapshot. |
| `GET /api/scan` | Runs a full subnet scan and returns the device list. |
| `GET /api/config` | Active gateway/internet/subnet configuration. |

---

## ⚙️ Configuration

All settings have sensible defaults and can be overridden with environment variables:

| Variable | Default | Meaning |
|---|---|---|
| `NM_PORT` | `39824` | Web dashboard port. |
| `NM_GATEWAY` | `192.168.18.1` | Gateway host to monitor. |
| `NM_INTERNET` | `8.8.8.8` | Internet host to monitor. |
| `NM_SUBNET` | `192.168.18` | First three octets of the /24 to scan. |
| `NM_SAMPLE_MS` | `2000` | Latency sampling interval (ms). |
| `NM_PING_TIMEOUT` | `1000` | Per-ping timeout (ms). |
| `NM_NO_DASHBOARD` | *(unset)* | Set to `1` to run MCP without the web server. |

Example — monitor a different network:

```bash
NM_GATEWAY=10.0.0.1 NM_INTERNET=1.1.1.1 NM_SUBNET=10.0.0 npm start
```

---

## 📱 Watching from your phone

1. Find your computer's LAN IP (macOS: `ipconfig getifaddr en0`, Linux: `hostname -I`).
2. On your phone (same Wi-Fi), open `http://<that-ip>:39824`.
3. The UI is fully responsive — latency cards, live chart, and a stacked device list.

---

## 🧩 How it works

```
lib/network.js    ← ping / arp via child_process, RTT parsing, subnet sweep, vendor lookup
lib/oui.js        ← compact offline MAC-prefix → vendor table
lib/dashboard.js  ← Express static server + WebSocket live feed + latency sampling loop
public/index.html ← single-page dashboard (Tailwind CDN + Chart.js + WebSocket client)
mcp-server.js     ← MCP stdio server exposing the three tools (also boots the dashboard)
index.js          ← dashboard-only entry point
```

- **Ping** flags are chosen per-platform (`-t` on macOS, `-W` on Linux, `-w` on Windows) and RTT is parsed from `time=… ms` across all of them.
- **Scanning** pings hosts `.1`–`.254` in batches of 32, then reads `arp -a` to attach MAC + vendor to responders (the sweep is what populates the ARP cache).
- **Vendor lookup** is a curated offline OUI table (Apple, Google, TP-Link, Ubiquiti, Espressif/ESP, Raspberry Pi, Samsung, etc.). Unlisted prefixes show `Unknown` — no external calls are ever made.

---

## 🛠️ Troubleshooting

- **No devices found on scan:** confirm your machine really is on `192.168.18.x` (`ipconfig getifaddr en0` / `ip addr`). If not, set `NM_SUBNET` / `NM_GATEWAY` to match.
- **Vendor shows "Unknown":** the OUI table is intentionally compact; the MAC is still shown. It's cosmetic and offline by design.
- **Port already in use:** something else holds `39824` — set `NM_PORT` to another port.
- **Dashboard blank / not updating:** it needs internet for the Tailwind & Chart.js CDNs; check the connection pill in the header (green = live WebSocket).

---

## 📄 License

MIT