pyats_list_devicesLABSCO SUMMARY
pyATS with a safety rail, for an agent.
The reason to reach for this over raw pyATS is the guardrail layer: show commands are validated, config changes are screened for reload, erase, delete and format, dynamic scripts run in a restricted sandbox, and Genie Clean can never run a stage that reboots or reimages a device. The learn-diff pair is the workflow that pays off — snapshot a feature, apply a change, snapshot again, and read exactly what moved. It drives a real testbed, so the prerequisite is a working testbed.yaml, not a simulator.
What it is
An MCP server that wraps Cisco pyATS and Genie as structured, guarded tools an agent can call against a live network testbed over Streamable HTTP. pyATS already knows how to parse show output, push config, learn feature state and run declarative tests; this exposes those capabilities to a model, with dangerous paths blocked before they reach a device and every call written to an in-memory audit log.
What you get
- Devices listed and fuzzy-searched from the testbed —
pyats_list_devices,pyats_search_devices - Show commands run and parsed into JSON, one device or many at once, with a process-per-device option for real isolation —
pyats_run_show_command,pyats_run_show_command_multi,pyats_pcall_show_command - Configuration applied with guardrails, applied with a before/after diff, or rolled back to the last snapshot —
pyats_configure_device,pyats_configure_with_diff,pyats_rollback_config - Feature state learned with Genie and two snapshots diffed, to see what a change moved —
pyats_learn_feature,pyats_diff_learned_snapshots - Declarative tests run — Blitz YAML, Robot Framework, or a sandboxed AEtest script —
pyats_run_blitz,pyats_run_robot,pyats_run_dynamic_test - Generic REST/RESTCONF calls and Cisco XPresso requests —
pyats_rest_request,pyats_xpresso_request - The in-memory operation log the agent can review mid-session —
pyats_get_operation_log
Requirements
Python 3.10+, and a pyATS testbed.yaml pointed at real or virtual devices Unicon can reach over SSH/Telnet — the server drives a network, it does not simulate one. Install is a clone plus pip install -r requirements.txt; run python3 pyats_mcp_server.py, which starts a Streamable HTTP server on 0.0.0.0:8080 by default, reachable at http://<YOUR_HOST>:<YOUR_PORT>/mcp. All device details and credentials live in .env and are pulled into the testbed via %ENV{} substitution — nothing is hard-coded. PYATS_TESTBED_PATH points at the testbed; PYATS_MCP_TRANSPORT_MODE chooses stateful or stateless. The pyproject names the package pyats-mcp at 0.1.0. Clients connect over HTTP — Claude Desktop, which is stdio-only, needs an mcp-remote bridge.
Setup effort
Build from source — git clone https://github.com/automateyournetwork/pyATS_MCP
USE CASES
Reading device state as structured data
Run a show command and get parsed JSON back rather than raw text you then have to scrape.
Seeing what a config change actually did
Snapshot the feature before, apply the change with a diff, snapshot after, and diff the two learned states.
Running one command across a fleet
Fan a show command out over many devices at once, or use the process-per-device path when you want real isolation at scale.
Backing out a change that broke something
Roll the device back to its last saved configuration snapshot.
26 tools
Listed in project docs. Your client may show a different list.
pyats_search_devicespyats_run_show_commandpyats_run_show_command_multipyats_pcall_show_commandpyats_show_running_configpyats_show_loggingpyats_ping_from_network_devicepyats_run_linux_commandpyats_configure_devicepyats_configure_devices_multipyats_pcall_configure_devicespyats_configure_with_diffpyats_rollback_configpyats_device_healthpyats_get_neighborspyats_find_interface_by_ippyats_learn_featurepyats_diff_learned_snapshotspyats_clean_devicepyats_run_blitzpyats_run_robotpyats_run_dynamic_testpyats_rest_requestpyats_xpresso_requestpyats_get_operation_logBEFORE YOU INSTALL
What to know first
Tools you get
26 tools named in the project's documentation.
Requires
- Python 3.10+
- A pyATS testbed.yaml pointed at real or virtual devices reachable over SSH/Telnet
INSTALLATION
Connect your client
You clone this one yourself.
Server setup
# 1. Clone and install
git clone https://github.com/automateyournetwork/pyATS_MCP
cd pyATS_MCP
pip install -r requirements.txt
# 2. Configure your environment
cp .env.example .env
# Edit .env — set PYATS_TESTBED_PATH=<YOUR_PYATS_TESTBED_PATH>, then one block per
# device: {DEVICENAME}_IP, _PORT, _OS, _PLATFORM, _USERNAME, _PASSWORD, _ENABLE_PASSWORD
# (testbed.yaml reads them back with %ENV{CORE1_IP} and so on)
# 3. Run — starts a Streamable HTTP server on 0.0.0.0:8080 by default
python3 pyats_mcp_server.pyMCP Clients
Claude Code
{
"mcpServers": {
"pyats": {
"type": "http",
"url": "http://localhost:8080/mcp"
}
}
}VS Code
{
"servers": {
"pyats": {
"type": "http",
"url": "http://localhost:8080/mcp"
}
}
}Codex
codex mcp add pyats --url http://localhost:8080/mcpClaude Desktop — mcp-remote
{
"mcpServers": {
"pyats": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:8080/mcp",
"--transport",
"http-only"
]
}
}
}Python code (LangGraph)
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
async with streamablehttp_client("http://localhost:8080/mcp") as (read, write, _session_id):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
result = await session.call_tool(
"pyats_run_show_command",
arguments={"device_name": "CORE1", "command": "show version"},
)