Skip to main content
Glama

clab-mcp

Two MCP servers that let Claude build, deploy and verify containerlab network topologies on macOS — from a plain-English sentence.

build me a 2-spine 4-leaf EVPN fabric with VNI 10010

Claude turns that into a complete topology: loopbacks, /31 fabric addressing, OSPF areas, BGP EVPN peerings to every route reflector, per-leaf bridge and VXLAN devices, host attachment — then deploys it and walks the verification chain from OSPF adjacency down to a packet capture of the VXLAN header.

Full setup and usage runbook: SETUP.md


How it works

containerlab is a Linux program — netlink, network namespaces, veth pairs. On macOS it runs inside a Linux VM. These servers run on macOS and reach into that VM with orb -m <vm>.

macOS
├── Claude Desktop
│    ├── clab-builder  ── writes topology + config files ──┐
│    └── clab-lab  ── orb -m clab ──┐                      │
└── OrbStack                        │                      │
     └── Linux VM "clab"  <─────────┘                      │
          ├── containerlab + docker                        │
          └── frr containers  <──────── files synced ──────┘

The split is deliberate:

  • clab-builder only writes files. No OrbStack, no containerlab, no network access. It cannot break a running lab.

  • clab-lab is the only thing that runs containerlab.

Related MCP server: netlab-mcp

Requirements

  • macOS (Apple Silicon or Intel)

  • Claude Desktop

  • Python 3.10+

  • OrbStack with a Linux machine (default name clab) running Docker and containerlab

Setting up the VM itself is out of scope — SETUP.md Stage 0 verifies it rather than installing it.

Install

git clone https://github.com/<your-username>/clab-mcp.git ~/clab-mcp
cd ~/clab-mcp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
bash register.sh

register.sh runs preflight checks, backs up your Claude Desktop config with a timestamp, then merges two entries into mcpServers — existing servers and other top-level keys are untouched. Re-running only updates the two entries.

Then quit Claude Desktop with Cmd + Q (closing the window leaves the old processes running) and reopen it.

Verify by asking Claude to run clab_env.

Configuration

Var

Default

Server

Meaning

CLAB_VM

clab

clab-lab

OrbStack machine name

CLAB_VM_DIR

~/labs

clab-lab

topology location inside the VM

CLAB_MAC_DIR

~/containerlab-mac

both

lab directory on macOS

CLAB_SUDO

sudo

clab-lab

set empty if the VM user is root

CLAB_TIMEOUT

900

clab-lab

seconds allowed for deploy/destroy

CLAB_FRR_IMAGE

quay.io/frrouting/frr:10.4.1

clab-builder

router image

CLAB_HOST_IMAGE

ghcr.io/srl-labs/network-multitool

clab-builder

host image

Pass any of them to register.sh and they are written into the config entries:

CLAB_VM=mylab CLAB_MAC_DIR=~/my-labs bash register.sh

Tools

clab-builder — generates topologies

Tool

Purpose

build_fabric

short YAML spec in, complete fabric out — the main one

list_images

image catalog with arm64 / login status

create_lab, add_node, connect, set_node_config

build a topology node by node

render_lab

write the in-memory lab to disk

show_lab

preview generated YAML without writing

validate_lab

correctness checks

list_built_labs, delete_lab

housekeeping

clab-lab — deploys and inspects

Tool

Purpose

clab_env

arch, containerlab version, docker version, lab dir

sync_lab_dir

mirror the macOS lab dir into the VM

list_topologies, list_labs, inspect_lab, read_topology

discovery

deploy, destroy

lifecycle

graph

export Mermaid or draw.io

node_exec, vtysh, node_logs

node access

capture

tcpdump in the node's netns

The fabric spec

Every key except lab has a default:

lab: evpn-vxlan
spines: 2
leaves: 4
underlay: ospf          # ospf (iBGP + route reflector) | ebgp (per-device ASN)
overlay: evpn           # evpn | none
asn: 65000
route_reflectors: [spine1, spine2]
spine_loopbacks: 10.255.0.0/24
leaf_loopbacks: 10.255.1.0/24
p2p: 10.0.0.0/24
fabric_mtu: 9100
vnis:
  - {vni: 10010, vlan: 10}
hosts:
  - {name: pc1, leaf: leaf1, vni: 10010, ip: 192.168.10.11/24}
  - {name: pc2, leaf: leaf2, vni: 10010, ip: 192.168.10.22/24}

Change spines: and leaves: and the addressing, interface numbering, OSPF, BGP peerings and per-leaf VXLAN devices are all recomputed.

What validate_lab catches

The failures that leave a fabric looking healthy while passing no traffic:

  • an interface used by two links, or an endpoint naming a node that does not exist

  • a /31 pair whose two ends are not actually on the same subnet

  • a BGP neighbour address matching no configured loopback or link address

  • a VXLAN device sourced from an IP that is not that leaf's own loopback

  • a VTEP whose BGP is missing advertise-all-vni

  • an access port joined to a bridge that is not a real link

  • the loopback address set after the VXLAN device is created

  • bgpd/ospfd disabled in daemons while the config uses them

  • eBGP without no bgp ebgp-requires-policy — FRR 7.4+ silently drops everything

  • an eBGP EVPN spine missing retain route-target all, or rewriting the VTEP next-hop

Coverage and limits

  • underlay: ospf + overlay: evpn is the validated path — deployed and verified end to end including a packet capture of the VXLAN header.

  • underlay: ebgp generates the standard eBGP-CLOS-with-EVPN pattern and passes every static check, but has not been deployed on a live fabric.

  • L2VNI only. No L3VNI, no tenant VRF, no anycast gateway — hosts sharing a VNI must share a subnet.

  • FRR only. SR Linux nodes can be added with add_node, but build_fabric does not generate SR Linux configs.

  • Images used are arm64-native and login-free: FRRouting and network-multitool.

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers