giorria (Irish: hare) is a fully reproducible network automation lab that pairs an all-Arista cEOS topology with an AI-powered operations platform built on the Model Context Protocol (MCP).
The lab demonstrates how to build natural-language network operations tooling on top of open-source infrastructure -- offline config analysis, live telemetry, structured audit trails, and AAA accounting -- wired together so that a language model can answer questions like "which BGP sessions are not established?" or "show me the config diff since the last meaningful change" using real network data.
| Component | Technology | Purpose |
|---|---|---|
| Network lab | Containerlab + Arista cEOS 4.35.1F | 6-node spine-leaf fabric, two ASes, inter-fabric peering |
| Offline analysis | Batfish + pybatfish | Config validation, BGP topology, reachability, route tables |
| Fact store | PostgreSQL | Normalised network state populated by the ingest pipeline |
| Config backup | Oxidized | Polls all devices, triggers Batfish pipeline on change |
| Object store | MinIO | Snapshot archives (ZIP) |
| Telemetry | gNMIc + Prometheus | OpenConfig interface counters, system state |
| Logging | Grafana Loki | Structured pipeline audit trail, TACACS+ accounting |
| Dashboards | Grafana | Pre-provisioned datasources (Prometheus + Loki) |
| AAA | TACACS+ | Authentication and command accounting for all 6 devices |
| MCP server | FastMCP (Python) | LLM-accessible tools for all of the above |
Fabric A (AS 65100 / 65101 / 65102) Fabric B (AS 65200 / 65201 / 65202)
arista-spine1 172.100.100.2 arista-spine2 172.100.100.3
Eth1 10.1.1.0/31 Eth1 10.2.0.0/31
Eth2 10.1.2.0/31 Eth2 10.2.0.2/31
Eth3 10.99.0.0/31 --- inter-fabric --------- Eth3 10.99.0.1/31
| |
+---------+ +---------+---------+
| | | |
arista- arista- arista-leaf3 arista-leaf4
leaf1 leaf2 (AS 65201) (AS 65202)
(65101) (65102)
Management network: 172.100.100.0/24 (created by Containerlab as clab-mgmt)
- Docker + Docker Compose
- Containerlab
- Arista cEOS 4.35.1F image (see lab/README.md for how to obtain it)
docker import cEOS-lab-4.35.1F.tar.xz ceos:4.35.1Fpython3 configure.pyThe script asks for a lab password and a TACACS+ shared key (or generates
both for you), then writes all .env files and patches device startup
configs, Oxidized credentials, and gNMIc credentials with the chosen
password.
Important: Run this before deploying the lab — it patches the device startup configs that Containerlab bind-mounts into each container.
cd lab/
sudo containerlab deploy -t topology.yml --reconfigure
cd ..The
--reconfigureflag forces cEOS containers to re-apply their startup configuration from the bind-mounted.cfgfiles. Without it, containers reuse whatever is persisted in flash from a previous deploy and configuration changes are silently ignored.
This creates the clab-mgmt Docker network that all services attach to.
docker compose \
--profile core \
--profile observability \
--profile oxidized \
--profile tacacs \
up -dcd network-mcp/
# Install with uv (recommended)
uv sync
uv run network-mcp
# Or with pip
pip install -e .
network-mcpThe server listens on http://localhost:8080/mcp (Streamable HTTP transport).
Point Claude Desktop or any MCP-compatible client at that URL.
| Service | Port | Notes |
|---|---|---|
| MCP server | 8080 | Streamable HTTP -- http://localhost:8080/mcp |
| pgAdmin | 8006 | PostgreSQL browser |
| MinIO console | 8005 | Object store UI |
| MinIO S3 API | 8004 | |
| Oxidized | 8888 | Web UI + REST API |
| Grafana | 3000 | Dashboards |
| Prometheus | 9090 | Metrics |
| Loki | 3100 | Log aggregation |
| Batfish | 9996 | Config analysis API |
| PostgreSQL | 5432 | Fact store |
| TACACS+ | 49/tcp | AAA |
| Profile | Services |
|---|---|
core |
Batfish, PostgreSQL, pgAdmin, MinIO, ingest pipeline |
observability |
Loki, Prometheus, gNMIc, Grafana |
oxidized |
Oxidized config backup daemon |
tacacs |
TACACS+ server + Promtail log shipper |
Arista device config changes
|
v
Oxidized polls & stores in git
| post_store hook
v
export-to-batfish.sh
writes .cfg to shared volume
| HTTP POST
v
ingest (FastAPI)
+-- archives configs
+-- runs Batfish analysis
+-- writes facts to PostgreSQL
+-- uploads snapshot ZIP to MinIO
| structured events
v
Loki (audit trail)
The MCP server queries PostgreSQL first (no device contact), escalating to live eAPI calls only when real-time state is needed.
| Prefix | Source | Use when |
|---|---|---|
netlab_* |
PostgreSQL fact store | Inventory, interfaces, BGP, routes -- use first |
arista_* |
Live eAPI | Real-time counters, running config, arbitrary show commands |
batfish_* |
Batfish | Reachability, config validation, offline topology analysis |
loki_* |
Loki | Pipeline audit trail, failure analysis, per-node history |
prometheus_* |
Prometheus | gNMI interface counters, system telemetry |
tacacs_* |
Loki (TACACS stream) | AAA audit -- who logged in, what commands ran |
giorria/
+-- compose.yml # All services, profile-gated
+-- configure.py # One-shot setup: generates .env files, patches configs
+-- .env.example # Root environment template
+-- lab/ # Containerlab topology + device configs
+-- ingest/ # FastAPI pipeline orchestrator + Dockerfile
+-- oxidized/ # Oxidized config.example, router.db, hook scripts
+-- collector/ # Prometheus, Loki, gNMIc, Grafana configs
| +-- gnmic.example.yml # gNMIc template (configure.py generates gnmic.yml)
+-- tacacs/ # TACACS+ server (Python RFC 8907 implementation)
+-- network-mcp/ # MCP server (FastMCP, Python, pyproject.toml)
+-- src/network_mcp/
+-- server.py # Tool definitions
+-- config.py # Environment-driven configuration
+-- arista_tools.py # Live eAPI queries
+-- batfish_tools.py # Offline config analysis
+-- postgres_tools.py# Fact store queries
+-- loki_tools.py # Audit trail queries
+-- prometheus_tools.py # gNMI telemetry
+-- tacacs_tools.py # AAA audit queries
| Guide | Description |
|---|---|
| Agent Instructions | Recommended system prompt for MCP clients — tool priority and troubleshooting workflow |
| Grafana Query Reference | Example Loki and Prometheus queries for Grafana Explore |
MIT -- see LICENSE.