Skip to main content
Glama

English | 日本語

nornir-mcp-server

nornir-mcp-server is an MCP (Model Context Protocol) server that exposes Nornir, a network automation framework, to AI agents.

Rather than the traditional "iterate over every device in a list" approach, it lets an AI agent leverage Nornir's metadata-based filtering (nornir.filter) to autonomously select targets — e.g. "only the core routers in Tokyo" — and run tasks against them in parallel.

Current Status

  • Phase 1, 2, 3 complete (full feature set)

    • SimpleInventory (YAML) and NetBox (nornir_netbox) support

    • Parallel execution of show commands (SSH/Telnet)

    • REST API request execution (via httpx)

    • Direct serial connection support to hosts (netmiko serial mode)

    • Dynamic config generation with Jinja2

    • Deploying configuration to real devices (Config Deploy)

Related MCP server: mcp-netmiko-server

Key Features

  • Flexible inventory: Uses Nornir's plugin ecosystem as-is — the standard SimpleInventory (hosts.yaml / groups.yaml) rather than a custom format. Dynamic inventory from NetBox is also supported.

  • Autonomous filtering: The AI narrows down target devices at runtime by supplying metadata such as {"role": "core", "site": "tokyo"}.

  • Configuration management and deployment: Give (or have the AI write) a template, and it instantly generates per-host configuration and can push it straight to the real devices.

  • Multi-protocol support: SSH/Telnet, REST APIs, and physical serial console connections are all reachable from a single MCP server.

  • Fast parallel execution: Nornir's ThreadedRunner dispatches tasks to multiple devices safely and quickly (serial ports are the exception — see below).

Installation and Setup

This project is managed with the uv package manager.

1. Install dependencies

cd nornir-mcp-server
uv sync

2. Configure the inventory

YAML files are used by default; edit config.yaml to switch to NetBox, etc.

By default the config file is loaded from config.yaml next to server.py, but you can point it anywhere with the NORNIR_MCP_CONFIG environment variable (independent of the process's working directory).

export NORNIR_MCP_CONFIG=/path/to/config.yaml

hosts.yaml / groups.yaml contain device credentials and are gitignored. Copy them from the templates:

cp hosts.yaml.example hosts.yaml
cp groups.yaml.example groups.yaml

Edit groups.yaml and replace CHANGE_ME with real login credentials. This file is never committed.

config.yaml (SimpleInventory example):

---
inventory:
  plugin: SimpleInventory
  options:
    host_file: "hosts.yaml"
    group_file: "groups.yaml"
logging:
  enabled: False

config.yaml (NetBox integration example):

---
inventory:
  plugin: NBInventory
  options:
    nb_url: "https://netbox.local"
    nb_token: "YOUR_NETBOX_API_TOKEN"
logging:
  enabled: False

3. Start the MCP server

Run it locally with:

uv run mcp run server.py

Running via Docker (GHCR)

GitHub Actions automatically builds and publishes a container image to the GitHub Container Registry (GHCR) on every commit to main. If you have Docker, you can use the server right away without cloning the repository.

docker pull ghcr.io/nagayon-935/nornir-mcp-server:latest

Example: Mount your config files (config.yaml and the inventory files) into /app in the container. (MCP communicates over stdio, so you'll need -i or similar — follow your MCP client's setup instructions.)

docker run -i --rm \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -v $(pwd)/hosts.yaml:/app/hosts.yaml \
  -v $(pwd)/groups.yaml:/app/groups.yaml \
  ghcr.io/nagayon-935/nornir-mcp-server:latest

MCP Tools Provided

The following tools are currently exposed to AI agents.

get_inventory

Returns the hosts and their metadata from the current inventory, optionally filtered.

  • Args: filter_criteria (e.g. {"site": "tokyo"})

run_netmiko_command

Runs a show-style command in parallel across the filtered target devices.

  • Args: command (the CLI command to run), filter_criteria (target filter), use_textfsm (if True, parses output into structured JSON using ntc-templates)

run_http_request

Sends an HTTP request to the REST API endpoint of each filtered target device.

  • Args: method (GET/POST/etc.), path (API path), filter_criteria, json_data

  • Configure the target host's inventory data (host.data) with base_url (e.g. https://192.168.1.1), http_headers, and tls_verify (True/False) as needed.

run_serial_command

Runs a command over a direct serial connection (console cable, etc.). Physical ports can only be held by one process at a time, so even with multiple target hosts, they are always processed one at a time (never in parallel).

  • Args: command (the CLI command to run), filter_criteria

  • The target host's inventory data must include serial_settings (port, baudrate, etc.). Netmiko's serial drivers require a device_type ending in _serial, so either set serial_settings.device_type explicitly, or leave it unset and it will be derived by appending _serial to host.platform (e.g. cisco_ios).

  • Login uses the top-level username / password fields from hosts.yaml / groups.yaml / defaults.yaml. It does not read connection_options.netmiko.extras (which is used for SSH connections), so if you also use serial connections, set credentials at the top level too.

generate_config

Renders a Jinja2 template (in a sandboxed environment) to generate configuration. Does not deploy it — useful for dry runs and auditing.

  • Args: template_string (a Jinja2 template), filter_criteria

  • Only {{ host.name }}, {{ host.hostname }}, {{ host.platform }}, {{ host.groups }}, and {{ host.data['key'] }} are available inside the template. Other host attributes (such as credentials) are intentionally not exposed.

run_netmiko_config

⚠️ This is a destructive operation that changes device configuration. Deploys the given configuration commands (or a generated config) to the target devices in parallel.

  • Args: commands (list of configuration commands to deploy), filter_criteria

Testing

Unit tests live in tests/.

uv sync
uv run pytest tests/ -v

License

MIT License

Install Server
F
license - not found
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nagayon-935/nornir-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server