| name | pyats-network |
| description | Network device automation via pyATS - run show commands, ping, apply config, learn config/logging, list devices, run Linux commands, execute dynamic tests on Cisco IOS-XE/NX-OS devices. Use when running CLI commands on routers or switches, checking interface status, applying configuration changes, or collecting device data via pyATS. |
| license | Apache-2.0 |
| user-invocable | true |
| metadata | {"openclaw":{"requires":{"bins":["python3"],"env":["PYATS_TESTBED_PATH"]}}} |
pyATS Network Device Tool
Server & Testbed
- Server script:
$PYATS_MCP_SCRIPT
- Testbed:
$PYATS_TESTBED_PATH
- Environment variable:
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH
Available Devices
- R1 (devnetsandboxiosxec8k.cisco.com) — Cisco IOS-XE, C8000v/CSR1kv
How to Call Tools
Use the $MCP_CALL protocol handler to invoke MCP tools:
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" TOOL_NAME 'ARGS_JSON'
All 8 Available Tools
1. pyats_list_devices
List all devices in the testbed with their properties: name, alias, type, OS, platform, connection types, credentials summary.
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_list_devices '{}'
Use when: Starting any session — always list devices first to confirm connectivity and inventory.
2. pyats_run_show_command
Execute any show command with automatic Genie structured parsing. Returns parsed JSON when a Genie parser exists, raw text otherwise.
device_name (string): Target device from testbed
command (string): Show command — must start with "show"
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_run_show_command '{"device_name":"R1","command":"show ip interface brief"}'
Validation rules:
- Must start with "show"
- No pipes (
|), redirects (>), or shell characters
- Cannot include: copy, delete, erase, reload, write, configure keywords
- Do NOT use for
show running-config or show logging — use the dedicated tools
Commands with Genie parsers (structured JSON output) on IOS-XE:
Routing:
show ip route / show ip route vrf <name>
show ip protocols
show ip bgp / show ip bgp summary / show ip bgp neighbors
show ip ospf / show ip ospf neighbor / show ip ospf interface / show ip ospf database
show ip eigrp neighbors / show ip eigrp topology
show isis neighbors / show isis database
show ip static route
Interfaces:
show ip interface brief / show ipv6 interface brief
show interfaces / show interfaces <name>
show interfaces status
show interfaces counters
show ip interface
L2/Switching:
show vlan / show vlan brief
show spanning-tree / show spanning-tree detail
show mac address-table
show etherchannel summary
Neighbors:
show cdp neighbors / show cdp neighbors detail
show lldp neighbors / show lldp neighbors detail
FHRP:
show standby / show standby brief
show vrrp / show vrrp brief
System:
show version
show inventory
show processes cpu / show processes cpu sorted
show processes memory / show processes memory sorted
show platform
show ntp associations / show ntp status
show snmp
show clock
show bootflash
show license
Security:
show access-lists / show ip access-lists
show crypto isakmp sa / show crypto ipsec sa
show dot1x
show port-security
show authentication sessions
QoS:
show policy-map / show policy-map interface
VRF / MPLS:
show vrf / show vrf detail
show mpls forwarding-table
show mpls ldp neighbor
Other:
show arp
show ip nat translations
show ip dhcp binding
show track
show route-map
show ip prefix-list
show bfd neighbors
show flow monitor
3. pyats_configure_device
Apply configuration changes to a device. Automatically enters config mode and exits.
device_name (string): Target device
config_commands (list of strings OR multiline string): Configuration lines
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_configure_device '{"device_name":"R1","config_commands":["interface Loopback99","ip address 99.99.99.99 255.255.255.255","description NetClaw-Test","no shutdown"]}'
Rules:
- Do NOT include
configure terminal, conf t, or end — the tool handles mode transitions
- DO include
exit commands when you need to return to a higher config context
- Preserves indentation for submode commands (route-maps, ACLs, etc.)
- Blocked commands:
write erase, erase, reload, delete, format
4. pyats_show_running_config
Retrieve the full running configuration from a device.
device_name (string): Target device
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_show_running_config '{"device_name":"R1"}'
Use when: Capturing configuration baselines, auditing config, pre/post change verification.
5. pyats_show_logging
Fetch system logs (last 250 entries) from a device.
device_name (string): Target device
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_show_logging '{"device_name":"R1"}'
Use when: Checking for errors, tracebacks, interface flaps, protocol events after changes.
6. pyats_ping_from_network_device
Execute ping from the network device itself (not from the MCP client).
device_name (string): Source device
command (string): Ping command (e.g., ping 8.8.8.8, ping 10.0.0.1 repeat 100 source Loopback0)
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_ping_from_network_device '{"device_name":"R1","command":"ping 8.8.8.8"}'
Returns: Structured JSON with success rate %, RTT stats, packet loss when Genie parsing succeeds.
7. pyats_run_linux_command
Execute shell commands on Linux-based devices in the testbed.
device_name (string): Linux-capable device
command (string): Shell command
Use when: The testbed includes Linux hosts (containers, VMs) for system administration tasks.
8. pyats_run_dynamic_test
Execute a complete pyATS AEtest validation script inline. The script runs in a sandboxed environment.
test_script_content (string): Complete Python AEtest script
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "${PYATS_PYTHON:-python3} -u $PYATS_MCP_SCRIPT" pyats_run_dynamic_test '{"test_script_content":"import logging\nfrom pyats import aetest\n\nlogger = logging.getLogger(__name__)\n\nTEST_DATA = {\"expected_interfaces\": [\"GigabitEthernet1\", \"Loopback0\"]}\n\nclass InterfaceTest(aetest.Testcase):\n @aetest.test\n def verify_interfaces(self):\n for intf in TEST_DATA[\"expected_interfaces\"]:\n logger.info(f\"Checking interface: {intf}\")\n assert intf.startswith(\"Gi\") or intf.startswith(\"Loop\"), f\"Unexpected interface type: {intf}\"\n\nif __name__ == \"__main__\":\n aetest.main()"}'
Rules:
- Must define
TEST_DATA as a Python dict literal (not loaded from file/network)
- Cannot connect to devices (embed all data inline)
- 300-second timeout
- Banned imports: os, sys, subprocess, shutil, socket, pathlib, pickle, yaml, requests, urllib, http, ssl
- Banned functions:
__import__(), eval(), exec(), compile(), open(), json.loads()
Use when: Complex pass/fail validation, multi-step assertions, compliance checks on data already collected via show commands.
Alternative: Direct Python pyATS
For operations beyond the 8 MCP tools, use pyATS directly:
from pyats.topology import loader
tb = loader.load('$PYATS_TESTBED_PATH')
device = tb.devices['R1']
device.connect(learn_hostname=True, log_stdout=False)
output = device.parse('show ip interface brief')
print(output)
device.disconnect()
Genie Learn (multi-command feature snapshots)
from genie.testbed import load
testbed = load('$PYATS_TESTBED_PATH')
dev = testbed.devices['R1']
dev.connect(learn_hostname=True, log_stdout=False)
ospf = dev.learn('ospf')
bgp = dev.learn('bgp')
intf = dev.learn('interface')
routing = dev.learn('routing')
platform = dev.learn('platform')
print(ospf.info)
dev.disconnect()
All 34 learnable features: acl, arp, bgp, config, device, dot1x, eigrp, fdb, hsrp, igmp, interface, isis, lag, lisp, lldp, mcast, mld, msdp, nd, ntp, ospf, pim, platform, prefix_list, rip, route_policy, routing, static_routing, stp, terminal, utils, vlan, vrf, vxlan.
Genie Diff (state comparison)
from genie.utils.diff import Diff
before = dev.learn('ospf')
after = dev.learn('ospf')
diff = Diff(before.info, after.info)
diff.findDiff()
print(diff)