netmiko-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., "@netmiko-mcp-servershow ip interface brief on switch_ssh"
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 | 日本語
netmiko-mcp-server
An MCP server for operating network devices through chat. It uses netmiko for SSH / Telnet connectivity and supports enable passwords.
Warning: This tool sends commands directly to network devices. Configuration-change tools are disabled by default, and even show-style commands are all denied unless a commands file is supplied. Always verify behavior in a lab environment before connecting to production devices.
Features
SSH / Telnet support
enablepassword (secret) supportSSH public-key authentication (
use_keys,key_file) supportMCP stdio / SSE modes
Commands are denied by default; only commands explicitly allowed by the allow/deny lists in
commands.tomlcan runThe configuration-change tool (
set_config_commands_and_commit_or_save) is disabled by default; enable it explicitly with--enable-configSSE mode requires Bearer token authentication (can be explicitly disabled with
--no-http-auth, not recommended)Every command attempt and connection result is recorded to a JSON audit log (fail-closed: the operation itself fails if the log write fails)
Large output is automatically saved to a file and can be read back with paging (keeps the LLM's context from being overwhelmed)
Parallel command execution across multiple devices grouped via
[groups]Structured (JSON) output via ntc-templates with
use_textfsm=TrueInventory
password/secretvalues can be stored encrypted (Fernet symmetric encryption)import_inventory.pylets you build or append to the inventory interactively (no LLM tokens needed, with per-field validation)
Related MCP server: Network MCP Lab
Usage
1. Define devices (TOML)
Edit network_devices.toml to define [default] and individual devices.
[default]
username = "netops"
password = "password"
secret = "enablepassword"
[router_telnet]
hostname = "192.0.2.10"
device_type = "cisco_ios_telnet"
[switch_ssh]
hostname = "192.0.2.11"
device_type = "cisco_ios"
use_keys = true
key_file = "/home/user/.ssh/id_rsa"
[c1200coreSW]
hostname = "192.0.2.12"
device_type = "cisco_ios"
pre_commands = ["terminal datadump"]
ansi_escape_codes = trueBuild the inventory interactively (import_inventory.py)
Instead of editing the TOML by hand, you can build or append to the inventory with an interactive script.
uv run python import_inventory.py # default: network_devices.toml
uv run python import_inventory.py -f my_devices.tomlPrompts for each field (device name, hostname/IP with IPv4/IPv6/FQDN support, device_type from netmiko's platform list, etc.) with validation and re-prompting on invalid input. A wrong
device_typeshows partial-match suggestions. Enterqat the device-name prompt to finish and move to the save/confirm step.If the target file already exists, choose append / overwrite / abort. Append mode preserves existing comments, key order, and already-encrypted (
enc:) values untouched. Overwrite mode creates a<filename>.bakbackup first.Entering group names (comma-separated) per device automatically updates the
[groups]table.If
NETMIKO_MCP_SERVER_INVENTORY_KEYis set,password/secretare encrypted automatically before saving (see Encrypting credentials). If it isn't set, you can choose to save in plaintext or abort.The file is written atomically with owner-only permissions (0600), and the saved file is round-trip verified through the inventory loader after writing.
Out of scope: editing/deleting existing devices, creating the
[default]section, and prompting forpre_commands/ansi_escape_codes/ timeout fields (edit these by hand). Note that in append mode, if an existing[groups]table is at the end of the file, new device tables are appended after it — this is still valid TOML and loads correctly.
2. Command allowlist (TOML)
Create commands.toml to explicitly list the commands the LLM is allowed to run. If this file is not provided, every command is denied.
allowed_commands = [
"show version",
"show ip interface brief",
"show ip interface*", # trailing glob: matches "show ip interface" plus anything after it
"show ip route *", # space + glob: "show ip route" alone is not allowed; an argument is required
]
denied_commands = [
"show running-config", # deny always wins, even if it also matches allowed_commands
]Allowlist for configuration-change commands (when using --enable-config)
Adding config_allowed_commands/config_denied_commands to the same commands.toml applies allow/deny checks to each line passed to set_config_commands_and_commit_or_save (denied entirely if unset). If even one command in the batch is denied, nothing is sent to the device.
config_allowed_commands = [
"interface *",
"description *",
"ip address *",
"no shutdown",
]
config_denied_commands = [
"no ip address*",
]In addition, shutdown (bringing an interface down) and clear* are always denied regardless of the above configuration (a hardcoded baseline protection — see BASELINE_CONFIG_DENIED_COMMANDS in security.py). Listing them in config_allowed_commands cannot override this. no shutdown (bringing an interface back up) is not on the dangerous side of the operation, so it is not included in the baseline deny list.
3. Device groups (optional)
Add a [groups] table to network_devices.toml to run commands in parallel across a set of devices with send_command_to_group.
[groups]
core_switches = ["switch_ssh", "c1200coreSW"]Use all instead of a group name to target every device in the inventory.
4. Encrypting credentials (optional)
If plaintext passwords in the TOML file are a concern, password/secret can be encrypted.
# 1. Generate a key and set it as an environment variable (the server needs the same key at startup)
export NETMIKO_MCP_SERVER_INVENTORY_KEY=$(uv run --with cryptography main.py --generate-key)
# 2. Encrypt the password and paste the result into the TOML file
uv run --with cryptography main.py --encrypt-value "mypassword"
# => enc:gAAAAA...[router1]
hostname = "192.0.2.10"
device_type = "cisco_ios"
password = "enc:gAAAAA..."If NETMIKO_MCP_SERVER_INVENTORY_KEY is not set while an encrypted value is being loaded, the server fails at startup. Keep the key out of the TOML file and manage it only through the environment variable.
5. Starting the server
stdio (local)
uv run --with "mcp[cli]" --with netmiko --with uvicorn main.py /path/to/devices.toml \
--commands-file /path/to/commands.tomlAdd --enable-config if you also want to use the configuration-change tool (disabled by default).
SSE (for remote connections)
SSE mode requires Bearer token authentication. First set the token as an environment variable.
export NETMIKO_MCP_SERVER_BEARER_TOKEN="$(openssl rand -hex 32)"uv run --with "mcp[cli]" --with netmiko --with uvicorn main.py /path/to/devices.toml \
--commands-file /path/to/commands.toml \
--sse --bind 10.70.72.1 --port 10000Example SSE URL: http://<server-ip>:10000/sse (the client must send an Authorization: Bearer <token> header)
Starting --sse without NETMIKO_MCP_SERVER_BEARER_TOKEN set stops the server with a startup error. Only pass --no-http-auth explicitly if you want to run without authentication (not recommended).
Restricting access to a specific subnet (e.g. 10.70.72.0/24)
In SSE mode, --allowed-subnet lets you specify allowed subnets (comma-separated). The default is 0.0.0.0/0. Combining this with Bearer token authentication provides defense in depth.
uv run --with "mcp[cli]" --with netmiko --with uvicorn main.py /path/to/devices.toml \
--commands-file /path/to/commands.toml \
--sse --bind 10.70.72.1 --allowed-subnet 10.70.72.0/24,127.0.0.1/32 --port 10000Audit log
By default, entries are recorded in JSON Lines format at ~/.netmiko_mcp_server_audit.log. Use --audit-log-file /path/to/audit.log to change the path.
Handling large output
By default, output exceeding 1000 lines is automatically saved under ~/.netmiko_mcp_server_outputs/<device>/ and can be read back with paging via the list_device_outputs/read_device_output tools. The threshold is configurable with --output-save-threshold, and the save location with --output-dir.
Parallelism for group execution
send_command_to_group defaults to 10 concurrent connections. Change this with --max-workers.
Running with Docker
Use the published image (recommended)
GitHub Actions automatically builds and publishes an image to the GitHub Container Registry (GHCR) on every push to main or on v*.*.* tag pushes (the publish job in .github/workflows/ci.yaml). The image is only published once lint, type-check, and tests all pass.
docker pull ghcr.io/nagayon-935/netmiko_mcp_server:latestAvailable tags:
Tag | Meaning |
| latest commit on the |
| build for a specific commit (for traceability) |
| semver tags, generated only when a |
Supported architectures: linux/amd64, linux/arm64 (also works with Docker/Podman on a Raspberry Pi or Apple Silicon).
Note for first-time publishing: GHCR packages can default to Private even when the repository is public. If
docker pullfails with a 403, go to the repository's GitHub page → Packages → the package's Package settings, and change Visibility to Public. Also check that Actions haspackages: writepermission under Settings → Actions → General → Workflow permissions ("Read and write permissions" must be enabled).
Building it yourself
docker build -t netmiko-mcp-server .Then mount the device config file and the command allowlist and start the container (replace netmiko-mcp-server with ghcr.io/nagayon-935/netmiko_mcp_server:latest if you're using the published image).
docker run -d -p 10000:10000 \
-v $(pwd)/network_devices.toml:/app/config.toml \
-v $(pwd)/commands.toml:/app/commands.toml \
-e NETMIKO_MCP_SERVER_BEARER_TOKEN="$(openssl rand -hex 32)" \
--name netmiko-mcp netmiko-mcp-server \
--sse --port 10000 --commands-file /app/commands.tomlMCP tools
Tool | Description |
| Returns the list of all devices in the inventory (no credentials included) |
| Sends a command to a single device, with |
| Runs a command in parallel across a device name, group name, or |
| Lists saved output files |
| Reads a saved output file with paging |
| Sends configuration-change commands (requires |
Using it from the Gemini CLI (example)
Register the server in the Gemini CLI's MCP configuration.
{
"mcpServers": {
"netmiko server": {
"url": "http://<server-ip>:10000/sse"
}
}
}If Bearer token authentication is enabled (the default), the client also needs to be configured to send an Authorization: Bearer <token> header. How to set headers varies by AI client, so check your client's MCP server configuration documentation. This is not needed if authentication was disabled with --no-http-auth (not recommended).
Notes
Set
device_typeto a name supported bynetmiko.If
secretis set,enable()is attempted automatically.Without
--commands-file,send_command_and_get_outputis always denied (deny-by-default).set_config_commands_and_commit_or_saveis always denied unless--enable-configis passed.send_command_and_get_output/send_command_to_group(show-style commands) are governed byallowed_commands/denied_commands;set_config_commands_and_commit_or_save(configuration changes) is governed byconfig_allowed_commands/config_denied_commands. Everything is denied if--commands-file(orconfig_allowed_commands) is not set.shutdownandclear*are always denied regardless of configuration (baseline protection; see "Command allowlist" above for details). For other configuration commands, only trusted operators should use them, and only within the scope ofconfig_allowed_commands.
Migrating from older versions
The --secured and --disable-config flags from earlier versions have been removed.
--secured(prefix-based blocklist) → replaced by the allow/deny list in--commands-file--disable-config(enabled by default, opt-out) → replaced by--enable-config(disabled by default, opt-in)
License
MIT License. See LICENSE for details.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceSecure network administration MCP server that enables AI assistants to safely execute networking commands like SSH, ping, and DNS lookups inside a Docker container sandbox.16MIT
- Flicense-qualityDmaintenanceMCP server for executing show commands and managing Cisco IOS-XE network devices via async SSH using Scrapli.5
- FlicenseAqualityFmaintenanceAn MCP server that integrates Nornir with NAPALM and Netmiko, enabling LLMs to orchestrate multi-vendor network infrastructure through natural language.52
- Alicense-qualityCmaintenanceMCP server for network operations that lets AI assistants interact with Cisco/Juniper network devices through safe, well-defined tools like compliance audits and configuration backups.MIT
Related MCP Connectors
An MCP server for deep research or task groups
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
A basic MCP server to operate on the Postman API.
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/netmiko-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server