pyats-network
pyATS Network Device Tool
You have access to a pyATS MCP server that can interact with network devices defined in the testbed.
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 "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 "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 testbedcommand(string): Show command — must start with "show"
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "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-configorshow 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 protocolsshow ip bgp/show ip bgp summary/show ip bgp neighborsshow ip ospf/show ip ospf neighbor/show ip ospf interface/show ip ospf databaseshow ip eigrp neighbors/show ip eigrp topologyshow isis neighbors/show isis databaseshow ip static route
Interfaces:
show ip interface brief/show ipv6 interface briefshow interfaces/show interfaces <name>show interfaces statusshow interfaces countersshow ip interface
L2/Switching:
show vlan/show vlan briefshow spanning-tree/show spanning-tree detailshow mac address-tableshow etherchannel summary
Neighbors:
show cdp neighbors/show cdp neighbors detailshow lldp neighbors/show lldp neighbors detail
FHRP:
show standby/show standby briefshow vrrp/show vrrp brief
System:
show versionshow inventoryshow processes cpu/show processes cpu sortedshow processes memory/show processes memory sortedshow platformshow ntp associations/show ntp statusshow snmpshow clockshow bootflashshow license
Security:
show access-lists/show ip access-listsshow crypto isakmp sa/show crypto ipsec sashow dot1xshow port-securityshow authentication sessions
QoS:
show policy-map/show policy-map interface
VRF / MPLS:
show vrf/show vrf detailshow mpls forwarding-tableshow mpls ldp neighbor
Other:
show arpshow ip nat translationsshow ip dhcp bindingshow trackshow route-mapshow ip prefix-listshow bfd neighborsshow flow monitor
3. pyats_configure_device
Apply configuration changes to a device. Automatically enters config mode and exits.
device_name(string): Target deviceconfig_commands(list of strings OR multiline string): Configuration lines
PYATS_TESTBED_PATH=$PYATS_TESTBED_PATH python3 $MCP_CALL "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, orend— the tool handles mode transitions - DO include
exitcommands 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 "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 "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 devicecommand(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 "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 devicecommand(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 "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_DATAas 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)
# Learn returns an OS-agnostic normalized data model
ospf = dev.learn('ospf') # Neighbors, interfaces, database, areas, LSAs
bgp = dev.learn('bgp') # Neighbors, address-families, routes, state
intf = dev.learn('interface') # All interfaces: status, IP, counters, MTU, speed
routing = dev.learn('routing') # Full routing table from all protocols
platform = dev.learn('platform') # Hardware, modules, images, slots
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
# Capture before state
before = dev.learn('ospf')
# ... make changes ...
# Capture after state
after = dev.learn('ospf')
diff = Diff(before.info, after.info)
diff.findDiff()
print(diff) # Shows + additions and - deletions