nornir-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nornir-mcp-serverrun show version on core routers in tokyo"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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) supportParallel execution of
showcommands (SSH/Telnet)REST API request execution (via
httpx)Direct serial connection support to hosts (
netmikoserial 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 sync2. 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.yamlhosts.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.yamlEdit 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: Falseconfig.yaml (NetBox integration example):
---
inventory:
plugin: NBInventory
options:
nb_url: "https://netbox.local"
nb_token: "YOUR_NETBOX_API_TOKEN"
logging:
enabled: False3. Start the MCP server
Run it locally with:
uv run mcp run server.pyRunning 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:latestExample:
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:latestMCP 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(ifTrue, 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_dataConfigure the target host's inventory data (
host.data) withbase_url(e.g.https://192.168.1.1),http_headers, andtls_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_criteriaThe target host's inventory data must include
serial_settings(port, baudrate, etc.). Netmiko's serial drivers require adevice_typeending in_serial, so either setserial_settings.device_typeexplicitly, or leave it unset and it will be derived by appending_serialtohost.platform(e.g.cisco_ios).Login uses the top-level
username/passwordfields fromhosts.yaml/groups.yaml/defaults.yaml. It does not readconnection_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_criteriaOnly
{{ 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/ -vLicense
MIT License
Maintenance
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
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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