SDN Guardian MCP
Provides tools for defending Cisco software-defined networks by reading telemetry and interface state, simulating policy impact, safely pushing ACL/flow rules, and confirming or rolling back changes on Cisco IOS-XE devices via RESTCONF and NETCONF.
Click on "Deploy 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., "@SDN Guardian MCPCheck traffic anomalies and safely block the top SYN flood source."
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.
SDN Guardian MCP
Closed-loop SDN defense with safe policy execution for Cisco Foundation-Sec-8B
An LLM agent finds the attack and proposes the block. The server checks the rule first, and rolls it back on its own if nobody confirms it.
Overview · How it works · Quick start · Cisco sandbox · Safety model · Future work
Overview
SDN Guardian is an MCP server that lets Cisco's open-weight
security model, fdtn-ai/Foundation-Sec-8B-Instruct,
defend a software-defined network without being able to break it. The agent runs an OODA
loop through seven tools; every safety rule is enforced by the server, not by the prompt.
Stage | Tool | Returns |
🔍 Observe |
| Per-source summary; flags SYN floods and high-rate sources |
🧭 Orient |
| Live switchport state vs. the Source of Truth (VLAN, enabled, description) |
⚖️ Decide |
| PASS/FAIL dry run, the conflicts, a concrete fix and a |
⚡ Act |
| Provisional install behind a dead-man's switch (auto-rollback) |
✅ Act |
| Runs the health check; commits if healthy, otherwise rolls back |
📋 Inspect |
| Commit and flow-table state |
Every tool answers in a few lines of Markdown, never raw JSON or YANG, so an 8B model can reason over the results in a small context window.
Technology stack: Python 3.10+, a standalone MCP server over stdio (works with any MCP client), Hugging Face transformers for the model, RESTCONF + NETCONF for Cisco IOS-XE. Status: beta (v0.1.0). Mock mode and the L4 model tier are validated end to end; live IOS-XE is tested against a simulated device only (see Future work).
Highlights
Validated on a real GPU. Foundation-Sec-8B (bf16, NVIDIA L4) ran the full defense in Colab: 6 tool calls, 0 parse retries, a full-source block committed, and a truthful summary (validation log).
Device-native rollback. On Cisco IOS-XE, writes use NETCONF
confirmed-commit, so the router itself reverts if the guardian dies before confirming.Fixes, not just failures. A rejected rule comes back with the fix, e.g.
Minimum safe priority: 101, which the model follows.112 tests cover the simulator, the rollback timer, the stdio MCP server end to end, the IOS-XE adapter against a simulated device, and the ReAct loop with a fake LLM.
Related MCP server: cisco-mcp
Problem Statement
LLM agents are good at reading telemetry and proposing a block rule. They are bad at the parts that take a network down:
Risk | What goes wrong |
Rule precedence | A new DENY below an existing broad ALLOW never matches (shadowing). A broad DENY above the management subnet locks out the controller. |
Stale state | A rule that was safe when checked may be unsafe after the table changed. |
No undo | A bad push has to be noticed and reverted by a human. |
Drift | The Source of Truth says VLAN 20, the device says VLAN 99, so VLAN-scoped policy silently misses. |
Hallucinated outcomes | The model reports actions it never took ("drift reconciled"). |
Prompting the model to "be careful" does not solve these. SDN Guardian moves the checks into the server, so they hold no matter what the model outputs.
How It Works
flowchart LR
subgraph Agent["🤖 Agent (Colab / any MCP client)"]
LLM["Foundation-Sec-8B<br/>ReAct loop"]
RP["Replay agent<br/>(fallback)"]
end
subgraph Server["🛡️ sdn-guardian-mcp (stdio)"]
T["7 tools + sdn://flows<br/>compact Markdown"]
O["Observe<br/>telemetry_summarizer"]
OR["Orient<br/>drift_detector"]
D["Decide<br/>conflict_simulator"]
A["Act<br/>rollback_manager"]
S[("SQLite state<br/>SoT · sims · commits")]
end
subgraph Net["🌐 Network"]
M["Mock SDN adapter"]
C["Cisco IOS-XE<br/>RESTCONF + NETCONF"]
end
LLM -- "{tool, args} JSON" --> T
RP --> T
T --> O & OR & D & A
D -- "PASS sim + sha256" --> A
A -- "snapshot · confirmed commit · rollback" --> M & C
O & OR --> M & C
D & A <--> S
classDef cisco fill:#049FD9,stroke:#0D274D,color:#fff
classDef dark fill:#0D274D,stroke:#049FD9,color:#fff
class T,D,A cisco
class O,OR,S,LLM,RP,M,C darkObserve. Telemetry samples are aggregated per source IP. A SYN flood is flagged at ≥100 SYN/s with a SYN:SYN-ACK ratio ≥3 (critical at ≥1000/s).
Orient. Live interface state is diffed against the SoT, with an impact line (e.g. "prefer IP-based rules").
Decide. The candidate
FlowRule(priority, src_cidr, dst_cidr, protocol, dst_port_range, action)is checked against every rule in the table (higher priority wins, as in OpenFlow). Detected relations:SHADOWED,OVERRIDES,GENERALIZATION,CORRELATION,REDUNDANTandMGMT_LOCKOUT.SHADOWEDandMGMT_LOCKOUTfail, and the report includes the fix. The simulation is stored with a sha256 of the normalized rule and the flow-table version.Act.
push_safe_sdn_policytakes only asimulation_id. The server reloads the rule from the stored PASS simulation, rejects it if the table changed since, snapshots the table, installs the rule and starts a timer.confirm_commitruns the health check itself (the controller and management subnet must stay reachable). If the check fails, or nobody confirms before the deadline, the snapshot is restored.
The demo scenario. Attacker 10.10.20.45 floods the controller 10.10.10.10 from
switchport Gi0/2. Rule #10 (ALLOW 10.10.20.0/24, priority 100) is a trap: a DENY at or below
priority 100 is shadowed by it. The agent has to read the fix, re-simulate at priority ≥101,
push and confirm. A bonus run pushes a rule, never confirms it, and shows the table restored.
Installation
Local
Requires Python ≥3.10.
git clone https://github.com/faithere1/sdn-guardian-mcp.git
cd sdn-guardian-mcp
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]" # add ,live for IOS-XE, ,llm for the local model
cp .env.example .env # defaults to mock mode
.venv/bin/ruff check . && .venv/bin/pytestExtra | Adds |
| ncclient for NETCONF |
| transformers, accelerate, bitsandbytes |
| pytest, pytest-asyncio, ruff |
Exact versions are pinned in requirements.txt.
macOS can mark the editable-install.pth file as hidden, and Python then skips it
(No module named 'sdn_guardian'). Set PYTHONPATH=src when running modules directly.
Pytest already does this.
Colab
Click Open in Colab, pick a GPU runtime, optionally add HF_TOKEN in Colab Secrets
(with notebook access), and run all cells. The notebook clones this repo, installs .[llm,live]
and picks the model tier from the GPU:
GPU | Tier | Status |
L4 / A100 (≥20 GB, compute capability ≥8.0) | bf16 (vLLM on A100 if installed) | ✅ Validated on L4 |
T4 (≥6 GB) | 4-bit NF4 | |
None / load failure | Replay agent | ✅ Validated |
Rerunning after a code change? Delete/content/sdn-guardian-mcp first (or reset the
runtime). The install cell skips the clone when that folder exists.
Cisco Sandbox Configuration
Mock mode needs no device. Live mode drives a Cisco IOS-XE device (Catalyst 8000V, CSR1000v, Catalyst 9000): RESTCONF for reads, NETCONF candidate datastore + confirmed commit for writes.
1. Get a device. A reservable Cisco DevNet sandbox (IOS-XE / Cat8kv) or your own lab device. The shared always-on sandbox is often read-only for NETCONF candidate writes, so use it for reads only.
2. Enable the APIs (privilege 15 user required):
ip http secure-server
restconf
netconf-yang
netconf-yang feature candidate-datastore3. Create the guardian-owned ACL and bind it to the interfaces it guards. The guardian
treats this ACL as its flow table (seq = 10000 - priority) and never touches other ACLs:
ip access-list extended SDN-GUARDIAN
9900 permit ip any any
interface GigabitEthernet2
ip access-group SDN-GUARDIAN in4. Configure .env (or the notebook's §5 form):
SDN_GUARDIAN_MODE=live
SDN_GUARDIAN_DB=./sdn_guardian_live.db
IOSXE_HOST=<device or sandbox host>
IOSXE_USERNAME=<user>
IOSXE_PASSWORD=<password>
IOSXE_RESTCONF_PORT=443
IOSXE_NETCONF_PORT=830
IOSXE_VERIFY_TLS=false # sandboxes use self-signed certs
IOSXE_ACL_NAME=SDN-GUARDIANLive mode has no telemetry source (that needs NetFlow) and no seeded Source of Truth, so seed the SoT for the interfaces you check and start the trace at drift/simulate (notebook §5 shows how). ACEs the rule model cannot represent (source ports, GRE, non-contiguous wildcards) raise an error instead of being silently widened.
Usage Examples
Replay demo (no GPU, no device)
PYTHONPATH=src .venv/bin/python -m sdn_guardian.agent.replay_agent --scenario canonical### 3. simulate_flow_impact(src_cidr='10.10.20.45/32', action='deny', priority=40)
**Simulation `sim-55ee0d44ba50`: FAIL** (flow table v1)
Rule: #21 prio 40 DENY any 10.10.20.45/32 -> 0.0.0.0/0
- SHADOWED (block): fully covered by higher-precedence #10 prio 100 ALLOW any 10.10.20.0/24 -> 0.0.0.0/0; the new rule never matches.
Fix: Minimum safe priority: 101
### 4. simulate_flow_impact(src_cidr='10.10.20.45/32', action='deny', priority=150)
**Simulation `sim-7fb514023c87`: PASS** (flow table v1)
...
### 6. confirm_commit(commit_id='commit-76095e9d3cc7')
**Commit `commit-76095e9d3cc7`: COMMITTED**
Rule: #21 prio 150 DENY any 10.10.20.45/32 -> 0.0.0.0/0
Detail: health check passed--scenario bonus pushes a rule with a 10 s deadline, never confirms it, and shows the commit
turn ROLLED_BACK with the table restored. --scenario both runs both.
Any MCP client (Claude Desktop, Claude Code, Cursor, …)
Run the server over stdio with sdn-guardian-mcp (add --reset to re-seed the mock demo).
examples/mcp_client_config.json is a ready-made
mcpServers entry; replace /ABSOLUTE/PATH/TO/sdn-guardian-mcp with your clone's path. For
Claude Code:
claude mcp add sdn-guardian -e PYTHONPATH="$PWD/src" -- "$PWD/.venv/bin/sdn-guardian-mcp"Then ask: "Check for traffic anomalies and block the attacker safely."
From Python
import asyncio
from sdn_guardian.agent.llm_backend import load_backend
from sdn_guardian.agent.react_loop import run_over_stdio
backend, tier = load_backend() # (None, choice) -> canonical replay when no usable GPU
result = asyncio.run(run_over_stdio(backend=backend, load=False))
print(result.stop_reason, result.summary, result.summary_warnings)Safety model & limitations
Enforced by the server, not the prompt:
🔒 Only a PASS simulation can be pushed, and only if its rule hash and flow-table version still match. The rule comes from the stored simulation, never from push arguments.
🛡️ The management subnet (
SDN_GUARDIAN_PROTECTED_SUBNETS) and controller IP cannot be blocked (MGMT_LOCKOUTfails the simulation).⏱️ One pending commit at a time. Each push snapshots the table first;
timeout_sis capped at 300 s.♻️
confirm_commitruns the health check itself and rolls back on failure or after the deadline. Pending commits are stored in SQLite; on startuprecover()rolls back the ones that expired while the server was down. In live mode the device's own confirmed-commit timer is a second line of defense.🧾 The agent's final summary is checked against the trace: claims such as "drift fixed", or a block without a COMMITTED confirm, are flagged in
summary_warnings.
Limitations:
Health is reachability of the controller and management subnet; it does not measure service impact on other hosts.
The rule model covers IPv4 L3/L4 matches (CIDR, protocol, destination port range). No IPv6, source ports or VLAN-scoped rules.
Live mode: no telemetry, one rule per priority (priority ≤ 9999), and ACL binding is left to the operator. It is tested against a simulated device (mocked RESTCONF/NETCONF), not yet against real hardware.
The LLM tier is validated on Colab L4 (bf16) only. The summary check is a keyword heuristic for known failure modes, not a general fact checker.
The mock adapter is a demo emulator, not a network simulator.
Future work
T4 / 4-bit validation. Run the notebook on a Colab T4 and record the 4-bit NF4 tier (load time, parse retries, rule choice) next to the L4 runs in
docs/COLAB_VALIDATION.md. Also try vLLM on an A100.Real IOS-XE hardware. Run notebook §5 against a reservable DevNet Cat8kv sandbox and record the confirmed-commit and rollback behavior.
Live telemetry. Feed NetFlow/IPFIX into
get_traffic_anomaliesin live mode.Drift remediation. A guarded tool to reconcile switchport config, behind the same simulate → push → confirm flow.
Richer rule model. IPv6, source ports and VLAN-scoped rules.
DevNet resources
Related sandbox: Cisco DevNet Sandbox, an IOS-XE / Catalyst 8000V lab (reservable for NETCONF writes). Setup steps are in Cisco Sandbox Configuration.
Learning lab: Introduction to Device Level Interfaces (NETCONF, RESTCONF, YANG)
Model: Foundation-Sec-8B-Instruct by Cisco Foundation AI.
Getting help
Open a GitHub issue with the mode (mock or live), where you ran it (local or Colab, GPU) and the tool output. Report security problems privately as described in SECURITY.md.
Getting involved
Contributions are welcome, especially the Future work items: a Colab T4 run, a real IOS-XE sandbox run, NetFlow telemetry and drift remediation. See CONTRIBUTING.md and the Code of Conduct.
Credits and references
Foundation-Sec-8B, Cisco Foundation AI's open-weight security LLM.
Model Context Protocol and its Python SDK.
Rule-anomaly classes (shadowing, correlation, generalization, redundancy) follow E. Al-Shaer and H. Hamed, Discovery of Policy Anomalies in Distributed Firewalls, IEEE INFOCOM 2004.
RFC 6241 (NETCONF) confirmed commit and RFC 8040 (RESTCONF).
Google Colab for the GPU runs.
Project layout
src/sdn_guardian/
├── mcp_server.py # 7 tools + sdn://flows (stdio)
├── engine/ # telemetry_summarizer · drift_detector · conflict_simulator · rollback_manager
├── adapters/ # mock_sdn_adapter · cisco_iosxe_adapter (RESTCONF + NETCONF)
└── agent/ # llm_backend (GPU tiers) · react_loop · replay_agent
notebooks/ # Colab notebook (live model + replay + rollback + live IOS-XE)
docs/COLAB_VALIDATION.md # every Colab run, problem and fix
docs/demo-video/ # HyperFrames source of the demo GIFLicense
Apache-2.0; copyright and third-party notices are in NOTICE. Cisco, IOS-XE and DevNet are trademarks of Cisco Systems, Inc. This is an independent project, not affiliated with or endorsed by Cisco.
This server cannot be deployed
Maintenance
Related MCP Connectors
Real-time MCP & A2A prompt-injection, jailbreak, and tool-schema poisoning firewall for AI agents.
Deterministic runtime safety for AI agents: scan PII, gate tool actions, verify LLM output.
AgentGuard — 20-tool AI safety MCP: policy preflight, risk scoring, audit logging, rate limits.
The WAF for agents. Pattern-based + heuristic firewall scans prompts, RAG documents, tool argume...
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to create, onboard, and diagnose Cisco SD-WAN branch edges using MCP tools that interact with a FastAPI automation backend, with guardrails for safe operations.1MIT
- FlicenseAqualityCmaintenanceEnables LLMs to run read-only show commands on Cisco IOS/IOS-XE and Nexus switches over SSH, with a two-account model for privilege separation and a fail-closed allowlist for safety.25-
- AlicenseNot gradedqualityCmaintenanceEnables LLM agents to triage network incidents by fetching device telemetry, inspecting syslogs, and executing traffic reroutes through MCP tools.MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to safely troubleshoot networks through read-only tools for device inventory, interface status, VLAN paths, BGP neighbors, route lookups, and interface error detection. Integrates with Microsoft Copilot Studio and Teams for natural-language-driven network diagnostics.-