Add dev stacks

This commit is contained in:
2025-12-31 20:11:44 -05:00
parent 0bcfed8fb8
commit 13989e2b59
49 changed files with 4948 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
# Network MCP
A "source of truth" for network devices and ports, backed by Elasticsearch, OPNsense, and Nmap.
## Architecture
- **Elasticsearch**: Stores current state (`network-hosts`) and historical events (`network-events-*`).
- **OPNsense Collector**: Fetches DHCP/ARP/DNS data to discover hosts.
- **Nmap Collector**: Scans discovered hosts for open ports and OS info.
## Setup
1. **Environment Config**
Copy `.env.example` to `.env` and fill in your details:
```bash
cp .env.example .env
# Edit .env
```
2. **Bootstrap Elastic**
Run the bootstrap script (requires `requests` installed locally, or you can run it inside a container):
```bash
python3 scripts/bootstrap_indices.py
```
*Note: Ensure you have connectivity to your Elasticsearch instance.*
3. **Start Services**
```bash
docker-compose up -d --build
```
This brings up the collectors and the lightweight frontend (reachable on port `5001`).
## Configuration
- **Static Metadata**: Edit `static/host_metadata.json` to add manual notes, roles, or tags to hosts (keyed by `mac:xx:xx...`).
- **Intervals**: Adjust polling intervals in `.env`.
- **VLAN Discovery (default on)**: Discovery sweeps (`nmap -sn`) run periodically across the OPNsense interfaces listed in `NMAP_DISCOVERY_VLANS`. Adjust the list (or set the flag to `false`) if you only want targeted subnets.
- **Quick vs Full Port Scans**: Each collector loop runs a fast, common-port sweep (`NMAP_QUICK_EXTRA_ARGS`, `NMAP_QUICK_BATCH_SIZE`) while a deeper service scan (`NMAP_PORT_RANGE`, `NMAP_BATCH_SIZE`) is triggered once per `NMAP_FULL_INTERVAL_SECONDS` (default daily). Tune these env vars to balance coverage vs. runtime.
- **Inventory Overlay**: Entries in `./inventory_targets.yml` are mounted into the OPNsense collector and merged by IP—offline/static hosts from that file (names, notes, expected ports) now appear in `network-hosts` with `source: inventory`.
## Data Model
- **`network-hosts`**: Current state of every known host.
- **`network-events-YYYY.MM.DD`**: Immutable log of scans and discovery events.
## Usage
Query `network-hosts` for the latest view of your network:
```json
GET network-hosts/_search
{
"query": {
"match_all": {}
}
}
```
### Quick Frontend
A minimal Flask frontend is bundled in docker-compose (service `frontend`) and is exposed on port `5001` so it can be reached from other machines:
```bash
docker-compose up -d frontend
```
Then visit `http://<host-ip>:5001/` to see the merged view (inventory entries are marked with `source: inventory`). If you prefer to run it without Docker for debugging, follow the steps below:
```bash
cd network-mcp
python3 -m venv .venv && source .venv/bin/activate
pip install -r frontend/requirements.txt
python frontend/app.py
```
### MCP / API Endpoints
The frontend doubles as a Model Context Protocol server. It exposes the manifest at `/.well-known/mcp.json` (or `/api/mcp`) and supports the standard JSON-RPC handshake (`initialize`, `tools/list`, `tools/call`) on the same URL. Agents can either use the RPC tools below or hit the underlying REST endpoints directly.
- MCP Resources are also available (`resources/list`, `resources/read`, `resources/templates/list`) for clients that prefer resource-style access to snapshots and queries.
- `GET /api/hosts` merged host list (supports `limit`, `source`, and repeated `q` params to fuzzy search names, hostnames, IPs, or MACs in a single call).
- `GET /api/hosts/<host_id>` single host document with optional `include_events=true`.
- `GET /api/events` recent scan/discovery events (`limit`, `host_id`, `type`, `since` filters).
- `GET /api/hosts/<host_id>/events` scoped events for a host.
- `GET /api/map` high-level “network map” grouping hosts by detected /24 (IPv4) or /64 (IPv6).
RPC tool names (mirrored in the manifest) are:
- `list_hosts` accepts `{limit, source, terms}` and returns the merged host list.
- `network_map` optional `{limit}` for building /24-/64 summaries.
- `get_host` requires `{host_id}` plus optional `include_events`, `events_limit`.
- `list_events` `{limit, host_id, type, since}`.
- `host_events` requires `{host_id}` plus optional `limit`, `type`, `since`.
Resource URI examples:
- `network://hosts?q=seele&limit=50`
- `network://host/mac:dc:a6:32:67:55:dc?include_events=true&events_limit=50`
- `network://events?type=discovery&limit=100`
All RPC and REST calls share the Elasticsearch credentials from `.env`, so an agent only needs HTTP access to port `5001` to query hosts, notes, and event timelines. Registering the MCP with Codex looks like:
```bash
codex mcp install network-mcp http://<host>:5001/.well-known/mcp.json
```