nornir-napalm-mcp

FastMCP server exposing Nornir + NAPALM network device state to AI assistants

Documentation

Nornir-NAPALM MCP Server

Python 3.12+ Nornir 3.4+ NAPALM 5.0+ License: MIT Code style: ruff

Nornir-NAPALM FastMCP Server

A FastMCP server that exposes live network device state to AI assistants via NAPALM getters. Nornir handles inventory loading and concurrent device connections over SSH, eAPI, and NETCONF.

All operations are read-only — no configuration push is exposed.


Features

ToolDescription
nornir_list_inventoryList all devices with hostname, platform, and group membership
nornir_get_factsSystem facts: vendor, model, OS version, serial number
nornir_run_getterRun any NAPALM getter by name (arp_table, bgp_neighbors, vlans, etc.)
nornir_get_configRetrieve running and/or startup configuration from a device
nornir_run_cliExecute read-only CLI commands via NAPALM's CLI method
nornir_list_gettersIntrospect available NAPALM getters for each platform in the inventory
nornir_reload_inventoryRe-read YAML inventory from disk
  • Lazy initialization — server starts even with a broken inventory, exposing the tool catalogue for inspection.
  • Singleton caching — Nornir instance is initialized once and reused across requests. Failed-device quarantine (failed_hosts) is reset before every call so dropped devices are available again on the next request.
  • Flexible filtering — filter by device name, group, or platform on any tool.
  • HTTP and STDIO transport — run locally for Claude Desktop or expose over HTTP.

Prerequisites

RequirementVersionNotes
Python3.12+Required for type hint syntax and pathlib improvements
uvlatestRecommended package manager (install)
NAPALM-supported devicesVendor-specificSSH, eAPI, or NETCONF access to target devices

Setup

Nornir configuration

The server requires a Nornir configuration file, provided via the NORNIR_CONFIG environment variable.

Configuration Setup

  • Copy the included example config to the project root (or any path you prefer):
cp config.example.yaml config.yaml
  • Edit config.yaml to point at your inventory files. A minimal config looks like:
---
inventory:
  plugin: SimpleInventory
  options:
    host_file: "inventory/hosts.yaml"
    group_file: "inventory/groups.yaml"
    defaults_file: "inventory/defaults.yaml"

runner:
  plugin: threaded
  options:
    num_workers: 10

logging:
  enabled: false

Note: The inventory files referenced must exist relative to this config file.


MCP client configuration

Register this server with any MCP client (Claude Desktop, VS Code, etc.) by adding the following to your project's .mcp.json:

uvx from GitHub (recommended)

{
  "mcpServers": {
    "nornir": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/sydasif/nornir-napalm-mcp",
        "nornir-napalm-mcp"
      ],
      "env": {
        "NORNIR_CONFIG": "/absolute/path/to/config.yaml"
      }
    }
  }
}

Environment variables

VariableDefaultDescription
NORNIR_CONFIG— (required)Path to the Nornir bootstrap config

NAPALM getters

Use nornir_run_getter with any of these:

GetterDescription
arp_tableARP table
bgp_configBGP running configuration
bgp_neighborsBGP neighbors summary
bgp_neighbors_detailBGP neighbors detailed
configRunning/startup/candidate configuration
factsSystem facts (vendor, model, OS, serial, uptime)
interfacesInterface status and details
interfaces_ipIP addresses on interfaces
lldp_neighborsLLDP neighbors summary
lldp_neighbors_detailLLDP neighbors detailed
mac_address_tableMAC address table
ntp_serversNTP server configuration
snmp_informationSNMP configuration
vlansVLAN information

Usage

List inventory

uv run nornir-napalm-mcp --help

Run as MCP server (STDIO)

NORNIR_CONFIG=/path/to/config.yaml uv run nornir-napalm-mcp

Run as HTTP server

NORNIR_CONFIG=/path/to/config.yaml uv run nornir-napalm-mcp --transport http --host 0.0.0.0 --port 8000

Run as Python module

NORNIR_CONFIG=/path/to/config.yaml uv run python -m nornir_napalm_mcp

Project Structure

nornir-napalm-mcp/
├── nornir_napalm_mcp/
│   ├── __init__.py       # Package version
│   ├── __main__.py       # python -m support
│   ├── main.py           # CLI entry point (argparse, transport selection)
│   ├── models.py         # Pydantic data models (InventoryDevice, GetterInfo, HostResult)
│   ├── runner.py         # Nornir init, config loading, singleton caching, NornirLike protocol
│   ├── tasks.py          # Task helpers: device filtering, execution, result normalization
│   ├── introspection.py  # NAPALM getter discovery per platform
│   ├── server.py         # FastMCP server instance and the 7 tool definitions
│   └── py.typed          # PEP 561 marker for downstream type checking
├── tests/
│   ├── conftest.py       # Fake Nornir stubs and pytest fixtures
│   ├── test_helpers.py   # Unit tests for all MCP tools and CLI entry point
│   └── test_runner.py    # Unit tests for config loading and path expansion
├── config.example.yaml   # Example Nornir configuration
├── pyproject.toml        # Build config, dependencies, and tool settings
├── uv.lock               # Locked dependencies
└── README.md

Contributing

Development workflow

# Install dependencies
uv sync

# Run tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=nornir_napalm_mcp --cov-branch

# Lint
uv run ruff check .

# Auto-fix lint issues
uv run ruff check --fix .

# Format
uv run ruff format .

# Type check (strict mode)
uv run mypy .

Code standards

  • Python 3.12+ — use modern syntax (f-strings, match, str.removeprefix)
  • Type hints — required on all function signatures (mypy --strict)
  • Docstrings — Google-style with Args:, Returns:, Raises:
  • Tests — AAA pattern, one assertion per logical check, use pytest fixtures
  • Lintingruff with E, F, I, UP rules

Commit conventions

Use Conventional Commits:

feat(server): add nornir_ping tool
fix(runner): handle missing NORNIR_CONFIG gracefully
refactor: extract _run_nornir_task helper
test: add runner config expansion tests

Companion Lab

Test against real devices using the netlab-demo test lab with Cisco devices via Containerlab.


License

MIT