Skip to main content
Glama

cisco-mcp

A read-only MCP server for Cisco IOS / IOS-XE and Nexus (NX-OS) switches, plus ASA firewalls (including Firepower appliances running the ASA image). It lets an LLM run show commands over SSH — and nothing else.

ASA vs FTD: the asa platform covers the ASA software image — classic 5500-X boxes and Firepower 1000/2100/4100 hardware running ASA. Firepower Threat Defense (FTD) is a different CLI and is not supported (yet).

ASA account setup: an SSH login on ASA lands in user EXEC (>) unless the account auto-enables. Either configure aaa authorization exec LOCAL auto-enable on the ASA (accounts land at their configured privilege level), or set CISCO_RO_ENABLE_SECRET / CISCO_PRIV15_ENABLE_SECRET so the server can enable. Give the read-only account a low privilege level (e.g. 5) with the show commands it needs, and reserve privilege 15 for the CISCO_PRIV15_* account.

The two-account model

To run show running-config on IOS you need privilege 15, but you don't want a priv-15 account doing everything. So the server uses two accounts:

Account

Used for

Read-only (CISCO_RO_*)

Every tool call

Privilege-15 (CISCO_PRIV15_*)

Only show running-config on IOS/IOS-XE/ASA

The priv-15 account is scoped as tightly as possible: it fires only when the command is show running-config (or its abbreviations show run / sh run / show running) on an IOS/IOS-XE/ASA device. Everything else — including show startup-config, show tech-support, and show archive — stays on the read-only account.

Platform-aware: privilege levels are an IOS-family concept that ASA shares (show running-config needs priv 15 on ASA too). Nexus instead uses RBAC — its read-only network-operator role can already read the running config — so on NX-OS devices the server always uses the read-only account and never escalates.

Related MCP server: mcp-netmiko-server

Safety

Every command passes through a fail-closed allowlist (allowlist.py) before it runs:

  • must be a show command (abbreviations like sh run included);

  • config mode, write/erase/reload/copy/clear/debug, command chaining (;, newlines), and pipe-to-write (| redirect, | tee, | append) are rejected.

The LLM never decides what's safe — the server enforces it mechanically, which also contains prompt-injection arriving through arguments or command output.

Setup

# 1. install (uv recommended)
uv sync           # or: pip install -e .

# 2. credentials
cp .env.example .env            # fill in the two accounts

# 3. inventory
cp devices.example.yaml devices.yaml   # list your switches + platform

# 4. run tests
uv run pytest

Register with an MCP client

stdio transport, e.g. in a client config:

{
  "mcpServers": {
    "cisco": {
      "command": "uv",
      "args": ["run", "cisco-mcp"],
      "cwd": "/path/to/cisco-mcp"
    }
  }
}

Tools

35 tools total. Every one runs through the same allowlist + account-selection gate; only get_running_config (or run_show_command with show running-config) on an IOS/IOS-XE/ASA device escalates to the priv-15 account. Tools dispatch the right command variant per platform; a tool that doesn't apply to a platform (e.g. VLANs on ASA, failover on a switch) returns a clear "not supported" error without touching the device.

Meta

  • list_devices — inventory with platform + notes

  • run_show_command(device, command) — any allowlisted show, with the same gate

System / identity

  • get_version — show version

  • get_running_config — show running-config (priv-15 on IOS/IOS-XE/ASA, read-only on NX-OS)

  • get_inventory_hw — show inventory (chassis / modules / serial numbers)

  • get_modules — show module (hardware/service modules; ASA/Firepower, NX-OS, modular Catalyst)

  • get_clock — show clock

  • get_logs — show logging

Health / capacity

  • get_cpu — show processes cpu history (IOS/IOS-XE) / show system resources (NX-OS) / show cpu usage (ASA)

  • get_memory — show memory statistics (IOS/IOS-XE) / show system resources (NX-OS) / show memory (ASA)

  • get_environment — show environment

  • get_poe_status — show power inline (switches only)

L2 / switching

  • get_interfaces — show interfaces / show interface (NX-OS, ASA)

  • get_interface_status — show ip interface brief / show interface ip brief (ASA)

  • get_vlans — show vlan brief (not ASA)

  • get_trunks — show interfaces trunk (not ASA)

  • get_spanning_tree — show spanning-tree (not ASA)

  • get_etherchannels — show etherchannel summary (IOS/IOS-XE) / show port-channel summary (NX-OS, ASA)

  • get_mac_address_table — show mac address-table / show mac-address-table (ASA, transparent mode)

L3 / routing

  • get_arp_table — show ip arp / show arp (ASA)

  • get_ipv6_neighbors — show ipv6 neighbors (IOS) / show ipv6 neighbor (NX-OS, ASA) — IPv6 equivalent of ARP

  • get_routing_table — show ip route / show route (ASA)

  • get_ipv6_route — show ipv6 route

  • get_ipv6_interfaces — show ipv6 interface brief

  • get_ospf_neighbors — show ip ospf neighbor / show ospf neighbor (ASA)

  • get_bgp_summary — show ip bgp summary / show bgp summary (ASA)

  • get_eigrp_neighbors — show ip eigrp neighbors / show eigrp neighbors (ASA)

Neighbor discovery

  • get_cdp_neighbors — show cdp neighbors detail (not ASA)

  • get_lldp_neighbors — show lldp neighbors detail (not ASA)

Firewall (ASA only, except access lists)

  • get_failover_status — show failover (HA state and health)

  • get_connection_count — show conn count

  • get_xlate_count — show xlate count (NAT translation count)

  • get_nat — show nat (NAT policies with hit counts)

  • get_vpn_sessions — show vpn-sessiondb (active VPN session summary)

  • get_access_lists — show access-lists / show access-list (ASA) — all platforms

Layout

src/cisco_mcp/
  server.py       MCP tools (FastMCP, stdio)
  allowlist.py    safety gate + priv-15 policy   <- security core
  connection.py   account selection + Netmiko SSH
  credentials.py  two account profiles from env
  inventory.py    devices.yaml loader
  platforms.py    IOS vs NX-OS vs ASA behavior
tests/            allowlist + account-selection + dispatch tests (no network)

Available Tools

25 tools
get_arp_tableB

Show the ARP table ('show ip arp').

Inputs: device (required). Returns: result

get_bgp_summaryA

Show BGP peer summary ('show ip bgp summary').

Inputs: device (required). Returns: result

get_cdp_neighborsA

Show directly connected Cisco neighbors ('show cdp neighbors detail').

Inputs: device (required). Returns: result

get_clockB

Show the device's current time ('show clock').

Inputs: device (required). Returns: result

get_cpuA

Show CPU utilization.

IOS/IOS-XE: 'show processes cpu history'. NX-OS: 'show system resources'.

Inputs: device (required). Returns: result

get_eigrp_neighborsB

Show EIGRP neighbors ('show ip eigrp neighbors').

Inputs: device (required). Returns: result

get_environmentA

Show environmental info -- power, fans, temperature ('show environment').

Inputs: device (required). Returns: result

get_etherchannelsC

Show link-aggregation state.

IOS/IOS-XE: 'show etherchannel summary'. NX-OS: 'show port-channel summary'.

Inputs: device (required). Returns: result

get_interfacesB

Show interface details ('show interfaces').

Inputs: device (required). Returns: result

get_interface_statusB

Show a brief interface status table ('show ip interface brief').

Inputs: device (required). Returns: result

get_inventory_hwA

Show chassis/module/serial inventory ('show inventory').

Inputs: device (required). Returns: result

get_lldp_neighborsA

Show LLDP neighbors, including non-Cisco devices ('show lldp neighbors detail').

Inputs: device (required). Returns: result

get_logsA

Show the device's log buffer ('show logging'). Can be large on busy devices.

Inputs: device (required). Returns: result

get_mac_address_tableA

Show the MAC address table ('show mac address-table').

Inputs: device (required). Returns: result

get_memoryA

Show memory utilization.

IOS/IOS-XE: 'show memory statistics'. NX-OS: 'show system resources'.

Inputs: device (required). Returns: result

get_ospf_neighborsA

Show OSPF neighbors ('show ip ospf neighbor').

Inputs: device (required). Returns: result

get_poe_statusA

Show PoE inline power status ('show power inline'). Only meaningful on PoE switches.

Inputs: device (required). Returns: result

get_routing_tableA

Show the IPv4 routing table ('show ip route').

Inputs: device (required). Returns: result

get_running_configA

Show the running configuration ('show running-config').

On IOS/IOS-XE this uses the privilege-15 account; on NX-OS the read-only (network-operator) account can already read it.

Inputs: device (required). Returns: result

get_spanning_treeA

Show spanning-tree state per VLAN ('show spanning-tree').

Inputs: device (required). Returns: result

get_trunksA

Show trunk interfaces and allowed VLANs ('show interfaces trunk').

Inputs: device (required). Returns: result

get_versionB

Show hardware/software version info ('show version').

Inputs: device (required). Returns: result

get_vlansA

Show configured VLANs ('show vlan brief').

Inputs: device (required). Returns: result

list_devicesA

List the switches available in the inventory, with platform and notes.

Inputs: no named parameters. Returns: result

run_show_commandA

Run an arbitrary read-only 'show' command on a device.

Only 'show' commands are permitted; the server rejects anything else. On IOS/IOS-XE, 'show running-config' is the only command that escalates to the privilege-15 account -- everything else, and every command on NX-OS, uses the read-only account.

Inputs: device (required), command (required). Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 25 tools

    Disambiguation5/5

    Each tool targets a distinct resource or protocol: EIGRP, OSPF, BGP, CDP, and LLDP neighbors are clearly separated, and other tools cover unique aspects like CPU, memory, VLANs, or MAC tables. Even run_show_command is unambiguous because it is the generic fallback, while the specific getters are purpose-built for their particular show command.

    Naming Consistency4/5

    The vast majority follow a consistent get_<resource> pattern (e.g., get_cpu, get_vlans). Two exceptions exist: list_devices uses a different verb, and run_show_command is a non-get generic action. These are minor deviations that do not obscure the overall structure, but they prevent a perfect score.

    Tool Count3/5

    With 25 tools, this set sits in the 16-25 range that feels heavy for a tool surface. While each tool is justified for network monitoring, the count is above the typical well-scoped range of 3-15 tools, making it borderline excessive.

    Completeness5/5

    The tool set comprehensively covers the read-only monitoring domain for Cisco devices, including neighbors, inventory, performance metrics, Layer 2/3 state, and configuration. The inclusion of run_show_command ensures there are no dead ends—any missing show command can be executed through this generic escape hatch.

    Related MCP Connectors

    Related MCP Servers