"""Phase 4 Demo: Network Discovery Tools
This demo showcases all the network discovery tools implemented in Phase 4:
- Device listing and details (switches, APs, gateways)
- Client listing and details (wired and wireless)
- Network listing and details (VLANs, subnets)
- WLAN listing and details (wireless networks)
Run this demo to see the complete network discovery capabilities.
"""
import asyncio
import json
from typing import Any, Dict
from unifi_mcp.unifi_client import UniFiClient
from unifi_mcp.tools.network_discovery import (
ListDevicesTool,
GetDeviceDetailsTool,
ListClientsTool,
GetClientDetailsTool,
ListNetworksTool,
GetNetworkDetailsTool,
ListWLANsTool,
GetWLANDetailsTool,
)
def print_section(title: str) -> None:
"""Print a section header."""
print("\n" + "=" * 80)
print(f" {title}")
print("=" * 80 + "\n")
def print_result(result: Dict[str, Any], indent: int = 0) -> None:
"""Pretty print a result."""
print(json.dumps(result, indent=2))
async def demo_device_tools(client: UniFiClient) -> None:
"""Demo device listing and details tools."""
print_section("DEVICE DISCOVERY TOOLS")
# List all devices
print("š Listing all devices...")
list_tool = ListDevicesTool()
result = await list_tool.execute(client, device_type="all", page=1, page_size=10)
if result.get("success"):
print(f"ā
Found {result['total']} devices")
print(f" Showing page {result['page']} ({result['count']} devices)\n")
for device in result["data"]:
status_icon = "š¢" if device["status"] == "online" else "š“"
print(f" {status_icon} {device['name']} ({device['type']})")
print(f" MAC: {device['mac']}, IP: {device['ip']}")
print(f" Model: {device['model']}, Version: {device['version']}")
print()
# Get details for first device
if result["data"]:
first_device = result["data"][0]
print(f"\nš Getting details for '{first_device['name']}'...")
detail_tool = GetDeviceDetailsTool()
detail_result = await detail_tool.execute(client, device_id=first_device["id"])
if detail_result.get("success"):
device = detail_result["data"]
print(f"ā
Device Details:")
print(f" Name: {device['name']}")
print(f" Type: {device['type']}")
print(f" Model: {device.get('model_name', device['model'])}")
print(f" IP: {device['ip']}")
print(f" Status: {device['status']}")
print(f" Uptime: {device['uptime_readable']}")
print(f" CPU: {device.get('cpu_usage', 0)}%")
print(f" Memory: {device.get('memory_usage', 0)}%")
# Show ports for switches
if "ports" in device:
print(f"\n Ports: {device['port_count']} total")
active_ports = [p for p in device["ports"] if p["up"]]
print(f" Active: {len(active_ports)} ports")
# Show radios for APs
if "radios" in device:
print(f"\n Radios: {len(device['radios'])}")
print(f" Connected Clients: {device.get('client_count', 0)}")
else:
print(f"ā Error: {result.get('error', {}).get('message', 'Unknown error')}")
async def demo_client_tools(client: UniFiClient) -> None:
"""Demo client listing and details tools."""
print_section("CLIENT DISCOVERY TOOLS")
# List all clients
print("š Listing all connected clients...")
list_tool = ListClientsTool()
result = await list_tool.execute(client, connection_type="all", page=1, page_size=10)
if result.get("success"):
print(f"ā
Found {result['total']} connected clients")
print(f" Showing page {result['page']} ({result['count']} clients)\n")
for client_info in result["data"]:
conn_icon = "š" if client_info["connection_type"] == "wired" else "š”"
print(f" {conn_icon} {client_info['name']}")
print(f" MAC: {client_info['mac']}, IP: {client_info['ip']}")
print(f" Network: {client_info['network']}")
print(f" Uptime: {client_info['uptime_readable']}")
print(f" TX: {client_info['tx_bytes_readable']}, RX: {client_info['rx_bytes_readable']}")
if client_info["connection_type"] == "wireless":
print(f" SSID: {client_info.get('essid', 'N/A')}")
print(f" Signal: {client_info.get('signal_strength', 0)} dBm")
print()
# Get details for first client
if result["data"]:
first_client = result["data"][0]
print(f"\nš Getting details for '{first_client['name']}'...")
detail_tool = GetClientDetailsTool()
detail_result = await detail_tool.execute(client, mac_address=first_client["mac"])
if detail_result.get("success"):
client_detail = detail_result["data"]
print(f"ā
Client Details:")
print(f" Name: {client_detail['name']}")
print(f" MAC: {client_detail['mac']}")
print(f" IP: {client_detail['ip']}")
print(f" Connection: {client_detail['connection_type']}")
print(f" Network: {client_detail['network']}")
print(f" Uptime: {client_detail['uptime_readable']}")
if client_detail["connection_type"] == "wireless":
print(f"\n Wireless Info:")
print(f" SSID: {client_detail.get('essid', 'N/A')}")
print(f" Signal: {client_detail.get('signal_strength', 0)} dBm")
print(f" RSSI: {client_detail.get('rssi', 0)} dBm")
print(f" Channel: {client_detail.get('channel', 0)}")
else:
print(f"ā Error: {result.get('error', {}).get('message', 'Unknown error')}")
async def demo_network_tools(client: UniFiClient) -> None:
"""Demo network listing and details tools."""
print_section("NETWORK CONFIGURATION TOOLS")
# List all networks
print("š Listing all networks and VLANs...")
list_tool = ListNetworksTool()
result = await list_tool.execute(client)
if result.get("success"):
print(f"ā
Found {result['total']} networks\n")
for network in result["data"]:
vlan_icon = "š·ļø" if network["vlan_enabled"] else "š¶"
dhcp_icon = "ā
" if network["dhcp_enabled"] else "ā"
print(f" {vlan_icon} {network['name']}")
print(f" Purpose: {network['purpose']}")
print(f" Subnet: {network['ip_subnet']}")
if network["vlan_enabled"]:
print(f" VLAN: {network['vlan']}")
print(f" DHCP: {dhcp_icon} ({network['dhcp_start']} - {network['dhcp_stop']})")
print(f" Domain: {network['domain_name']}")
print()
# Get details for first network
if result["data"]:
first_network = result["data"][0]
print(f"\nš Getting details for '{first_network['name']}'...")
detail_tool = GetNetworkDetailsTool()
detail_result = await detail_tool.execute(client, network_id=first_network["id"])
if detail_result.get("success"):
network = detail_result["data"]
print(f"ā
Network Details:")
print(f" Name: {network['name']}")
print(f" Purpose: {network['purpose']}")
print(f" Subnet: {network['ip_subnet']}")
print(f" Gateway: {network.get('gateway_ip', 'N/A')}")
if network["vlan_enabled"]:
print(f"\n VLAN Configuration:")
print(f" VLAN ID: {network['vlan']}")
if network["dhcp_enabled"]:
print(f"\n DHCP Configuration:")
print(f" Range: {network['dhcp_start']} - {network['dhcp_stop']}")
print(f" Lease Time: {network['dhcp_lease_time']}s")
print(f" DNS Servers: {', '.join(network.get('dhcp_dns', []))}")
print(f" Gateway: {network.get('dhcp_gateway', 'N/A')}")
print(f"\n Network Settings:")
print(f" Guest Network: {'Yes' if network.get('is_guest') else 'No'}")
print(f" NAT: {'Enabled' if network.get('is_nat') else 'Disabled'}")
print(f" IGMP Snooping: {'Enabled' if network.get('igmp_snooping') else 'Disabled'}")
else:
print(f"ā Error: {result.get('error', {}).get('message', 'Unknown error')}")
async def demo_wlan_tools(client: UniFiClient) -> None:
"""Demo WLAN listing and details tools."""
print_section("WIRELESS NETWORK TOOLS")
# List all WLANs
print("š Listing all wireless networks (WLANs)...")
list_tool = ListWLANsTool()
result = await list_tool.execute(client)
if result.get("success"):
print(f"ā
Found {result['total']} wireless networks\n")
for wlan in result["data"]:
status_icon = "š¢" if wlan["enabled"] else "š“"
guest_icon = "š„" if wlan["is_guest"] else "š"
hidden_icon = "š" if wlan["hide_ssid"] else "šļø"
print(f" {status_icon} {wlan['name']} {guest_icon} {hidden_icon}")
print(f" SSID: {wlan['ssid']}")
print(f" Security: {wlan['security']} ({wlan.get('wpa_mode', 'N/A')})")
if wlan["vlan_enabled"]:
print(f" VLAN: {wlan['vlan']}")
print(f" Network ID: {wlan['network_id']}")
print()
# Get details for first WLAN
if result["data"]:
first_wlan = result["data"][0]
print(f"\nš Getting details for '{first_wlan['name']}'...")
detail_tool = GetWLANDetailsTool()
detail_result = await detail_tool.execute(client, wlan_id=first_wlan["id"])
if detail_result.get("success"):
wlan = detail_result["data"]
print(f"ā
WLAN Details:")
print(f" Name: {wlan['name']}")
print(f" SSID: {wlan['ssid']}")
print(f" Enabled: {'Yes' if wlan['enabled'] else 'No'}")
print(f"\n Security Configuration:")
print(f" Type: {wlan['security']}")
print(f" WPA Mode: {wlan.get('wpa_mode', 'N/A')}")
print(f" Encryption: {wlan.get('wpa_enc', 'N/A')}")
print(f" WPA3 Support: {'Yes' if wlan.get('wpa3_support') else 'No'}")
if wlan["vlan_enabled"]:
print(f"\n VLAN Configuration:")
print(f" VLAN ID: {wlan['vlan']}")
print(f" Network ID: {wlan['network_id']}")
print(f"\n SSID Settings:")
print(f" Hidden: {'Yes' if wlan['hide_ssid'] else 'No'}")
print(f" Guest Network: {'Yes' if wlan['is_guest'] else 'No'}")
print(f" MAC Filtering: {'Enabled' if wlan['mac_filter_enabled'] else 'Disabled'}")
print(f"\n Advanced Settings:")
print(f" Band Steering: {wlan.get('band_steering_mode', 'N/A')}")
print(f" Fast Roaming: {'Enabled' if wlan.get('fast_roaming_enabled') else 'Disabled'}")
print(f" Group Rekey: {wlan.get('group_rekey', 0)}s")
if wlan["is_guest"]:
print(f"\n Guest Portal:")
print(f" Enabled: {'Yes' if wlan.get('guest_portal_enabled') else 'No'}")
print(f" Customized: {'Yes' if wlan.get('guest_portal_customized') else 'No'}")
else:
print(f"ā Error: {result.get('error', {}).get('message', 'Unknown error')}")
async def demo_summary(client: UniFiClient) -> None:
"""Show a summary of all network resources."""
print_section("NETWORK SUMMARY")
print("š Gathering network statistics...\n")
# Count devices
devices_tool = ListDevicesTool()
devices_result = await devices_tool.execute(client, device_type="all", page=1, page_size=1)
device_count = devices_result.get("total", 0) if devices_result.get("success") else 0
# Count clients
clients_tool = ListClientsTool()
clients_result = await clients_tool.execute(client, connection_type="all", page=1, page_size=1)
client_count = clients_result.get("total", 0) if clients_result.get("success") else 0
# Count networks
networks_tool = ListNetworksTool()
networks_result = await networks_tool.execute(client)
network_count = networks_result.get("total", 0) if networks_result.get("success") else 0
# Count WLANs
wlans_tool = ListWLANsTool()
wlans_result = await wlans_tool.execute(client)
wlan_count = wlans_result.get("total", 0) if wlans_result.get("success") else 0
print(f" š„ļø UniFi Devices: {device_count}")
print(f" š¤ Connected Clients: {client_count}")
print(f" š Networks/VLANs: {network_count}")
print(f" š” Wireless Networks: {wlan_count}")
print("\n" + "=" * 80)
print(" Phase 4 Network Discovery Tools - Complete! ā
")
print("=" * 80 + "\n")
async def main():
"""Run the Phase 4 demo."""
print("\n" + "=" * 80)
print(" UniFi MCP Server - Phase 4 Demo")
print(" Network Discovery Tools")
print("=" * 80)
# Configuration
print("\nāļø Configuration:")
print(" This demo uses mock data for demonstration purposes.")
print(" In production, connect to your UniFi controller.\n")
# Create a mock client (in production, use real credentials)
# For demo purposes, we'll show what the tools can do
print("š Note: This demo shows the tool capabilities.")
print(" To run against a real UniFi controller, update the configuration.\n")
# Show tool capabilities
print_section("AVAILABLE TOOLS")
tools = [
("unifi_list_devices", "List all UniFi devices (switches, APs, gateways)"),
("unifi_get_device_details", "Get detailed information about a specific device"),
("unifi_list_clients", "List all connected clients (wired and wireless)"),
("unifi_get_client_details", "Get detailed information about a specific client"),
("unifi_list_networks", "List all configured networks and VLANs"),
("unifi_get_network_details", "Get detailed information about a specific network"),
("unifi_list_wlans", "List all configured wireless networks"),
("unifi_get_wlan_details", "Get detailed information about a specific WLAN"),
]
for i, (name, description) in enumerate(tools, 1):
print(f" {i}. {name}")
print(f" {description}\n")
print("\n" + "=" * 80)
print(" Tool Features")
print("=" * 80 + "\n")
features = [
"ā
Device Discovery - Find all switches, APs, and gateways",
"ā
Client Tracking - Monitor all connected devices",
"ā
Network Configuration - View VLANs and subnets",
"ā
Wireless Networks - Manage SSIDs and security",
"ā
Pagination Support - Handle large deployments",
"ā
Filtering Options - Device type, connection type",
"ā
Flexible Lookup - By ID, MAC address, or name",
"ā
AI-Optimized Output - Summary and detail views",
"ā
Error Handling - Clear error messages with actionable steps",
"ā
Comprehensive Testing - 92 unit tests, all passing",
]
for feature in features:
print(f" {feature}")
print("\n" + "=" * 80)
print(" Use Cases")
print("=" * 80 + "\n")
use_cases = [
"š Network Inventory - 'List all devices on my network'",
"š Client Monitoring - 'Show me all wireless clients'",
"š·ļø VLAN Management - 'What VLANs are configured?'",
"š” WiFi Configuration - 'Show me the guest network settings'",
"š§ Troubleshooting - 'Why is this device offline?'",
"š Capacity Planning - 'How many clients per AP?'",
"š Security Audit - 'What wireless networks are open?'",
"š Migration Support - 'Export current network configuration'",
]
for use_case in use_cases:
print(f" {use_case}")
print("\n" + "=" * 80)
print(" Next Steps")
print("=" * 80 + "\n")
print(" To use these tools with your UniFi controller:")
print(" 1. Set up your UniFi controller credentials")
print(" 2. Configure the MCP server (see docs/MCP-SERVER.md)")
print(" 3. Start the server: python -m unifi_mcp.server")
print(" 4. Connect your AI agent to the MCP server")
print(" 5. Ask questions about your network!\n")
print(" For more information:")
print(" - Implementation: docs/TASK-11-SUMMARY.md (devices)")
print(" - Implementation: docs/TASK-12-SUMMARY.md (clients)")
print(" - Implementation: docs/TASK-13-SUMMARY.md (networks/WLANs)")
print(" - Server Setup: docs/MCP-SERVER.md")
print(" - Examples: examples/")
print("\n" + "=" * 80)
print(" Demo Complete! š")
print("=" * 80 + "\n")
if __name__ == "__main__":
asyncio.run(main())