Skip to main content
Glama

Network AI Assistant

Python 3.12+ FastMCP UV Async

Asynchronous MCP (Model Context Protocol) server for unified multi-platform network infrastructure management.

Expose network devices, WiFi controllers, monitoring systems, and data centers through a unified API accessible by Claude Desktop, Warp AI, and any MCP-compatible client.


Key Features

100% Asynchronous Architecture

  • Async/await engine: All I/O operations leverage asyncio, asyncssh, and httpx for optimal performance

  • Parallel execution: Native support for multi-device operations with timeout protection

  • Persistent sessions: Reusable HTTP connections with keepalive to minimize latency

  • Smart JWT caching: Thread-safe authentication token management with automatic renewal

10 Specialized Connectors

Connector

Type

MCP Tools

Description

Generic SSH

SSH

2

Universal CLI access to any SSH device (Cisco, Juniper, Arista, Linux, etc.)

MikroTik REST

REST API

9

Complete management via REST API (interfaces, BGP, routing, system health)

MikroTik SSH

SSH

2

Specific commands unavailable in REST (route check, custom commands)

Palo Alto SSH

SSH PTY

2

PAN-OS firewalls with PTY interactive sessions (VPN, routing, system)

Palo Alto Panorama

REST API

16

Panorama centralized management (devices, device-groups, security rules, compliance, audit)

Aruba WiFi

REST API

9

WiFi controller (APs, clients, rogues, RF, WLANs, statistics)

Graylog

REST API

3

Centralized log search with time filters and streaming

LibreNMS

REST API

10

Network monitoring (inventory, health, ports, sensors, events)

Cisco APIC (ACI)

REST API

28

ACI data center (fabric, tenants, EPGs, VRFs, contracts, topology, analytics)

Cisco NDFC

REST API

14

Nexus Dashboard Fabric Controller (fabrics, switches, networks, VRFs, events)

Total: 97 MCP tools (95 connectors + 2 skills tools)


Related MCP server: ai-mcp-terminal

Installation

Prerequisites

  • Python 3.12 or higher

  • UV package manager

  • dotenvx for encrypted credentials (brew install dotenvx/brew/dotenvx)

  • Network access to target devices/APIs

  • MCP client (Claude Desktop, Warp AI, etc.)

Install with UV

# Clone the repository
git clone https://github.com/angoran/git-netai.git
cd git-netai

# Sync dependencies (UV automatically creates virtual environment)
uv sync

# Verify installation
uv run python -c "from server import mcp; print(f'{mcp.name} operational')"

Configuration

Environment Variables

Create a .env file at project root with the following variables:

# Generic SSH
SSH_USERNAME="admin"
SSH_PASSWORD="your_password"

# MikroTik REST API
MIKROTIK_USERNAME="api_user"
MIKROTIK_PASSWORD="api_password"
MIKROTIK_PORT="443"

# MikroTik SSH (if different from REST)
MIKROTIK_SSH_USERNAME="ssh_user"
MIKROTIK_SSH_PASSWORD="ssh_password"
MIKROTIK_SSH_PORT="22"

# Palo Alto Firewalls
PALOALTO_SSH_USERNAME="admin"
PALOALTO_SSH_PASSWORD="firewall_password"

# Aruba WiFi Controller
ARUBA_IP="10.x.x.x"
ARUBA_USERNAME="admin"
ARUBA_PASSWORD="aruba_password"

# Graylog
GRAYLOG_API_URL="https://graylog.example.com"
GRAYLOG_USERNAME="graylog_user"
GRAYLOG_PASSWORD="graylog_password"

# LibreNMS
LIBRENMS_URL="https://librenms.example.com"
LIBRENMS_API_TOKEN="your_api_token_here"

# Cisco APIC (ACI)
APIC_HOST="https://apic.example.com"
APIC_USERNAME="apic_user"
APIC_PASSWORD="apic_password"
APIC_VERIFY_SSL="false"
APIC_TIMEOUT="30"
APIC_TOKEN_CACHE_DURATION="3540"

# Cisco NDFC
NDFC_HOST="https://ndfc.example.com"
NDFC_USER="ndfc_user"
NDFC_PASSWORD="ndfc_password"
NDFC_DOMAIN="DefaultAuth"
NDFC_VERIFY_SSL="false"
NDFC_TIMEOUT="30"

# Palo Alto Panorama
PANORAMA_URL="https://panorama.example.com/api"
PANORAMA_USERNAME="panorama_user"
PANORAMA_PASSWORD="panorama_password"
PANORAMA_TIMEOUT="30"

Security Note: Credentials are stored encrypted using dotenvx. The .env file contains AES-256-GCM encrypted values. The private key is stored in .env.keys (excluded from version control). Never commit .env.keys to the repository.

Encrypting Credentials

After filling in your .env file, encrypt it with dotenvx:

# Encrypt all values in .env (generates .env.keys with the private key)
dotenvx encrypt

# Verify decryption works correctly
dotenvx run -- uv run python -c "from server import mcp; print(f'{mcp.name} operational')"

Keep .env.keys secure and distribute it to other users via a secure channel (password manager, secrets vault). The encrypted .env can be safely shared or committed to version control.


MCP Client Configuration

Claude Desktop

Configuration file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "netai-o": {
      "command": "dotenvx",
      "args": [
        "run",
        "--env-file", "/absolute/path/to/netai/.env",
        "--",
        "uv",
        "--directory", "/absolute/path/to/netai",
        "run",
        "python",
        "server.py"
      ],
      "env": {
        "DOTENV_PRIVATE_KEY": "<your-private-key-from-.env.keys>"
      }
    }
  }
}

Warp AI

Configuration file: ~/.warp/mcp_config.json

{
  "mcpServers": {
    "netai-o": {
      "command": "dotenvx",
      "args": ["run", "--", "uv", "run", "python", "server.py"],
      "env": {
        "DOTENV_PRIVATE_KEY": "<your-private-key-from-.env.keys>"
      },
      "working_directory": "/absolute/path/to/netai"
    }
  }
}

Usage

Starting the Server

# Launch MCP server in stdio mode (with encrypted .env decryption)
dotenvx run -- uv run python server.py

The server exposes all MCP tools via stdio protocol. MCP clients (Claude Desktop, Warp) launch the server automatically based on their configuration files.

Example Commands

The following examples demonstrate natural language commands that can be used with Claude Desktop or Warp AI:

Generic SSH Operations

Execute "show version" on device 192.168.1.1
Run "show ip route" on devices 192.168.1.1 and 192.168.1.2 in parallel

MikroTik Management

Show BGP sessions on MikroTik router 10.0.0.1
Check route to 8.8.8.8 on MikroTik 10.0.0.1 via SSH
Display interface statistics for 10.0.0.1

Palo Alto Firewall Operations

Show VPN status on Palo Alto firewall 10.240.203.241
Execute "show system info" on firewalls 10.240.203.241 and 10.240.203.242 in parallel
Display routing table on firewall 10.240.203.241

Aruba WiFi Controller

List all access points on Aruba controller
Show connected WiFi clients
Detect rogue access points
Display RF channel utilization
Show WLAN configuration

Graylog Log Management

Search for "authentication failure" in logs from the last 2 hours
List available Graylog streams
Show system overview and statistics

LibreNMS Network Monitoring

Show all monitored MikroTik devices
Display health metrics for device router-core-01
List all ports on switch-distro-01
Show temperature sensors for all devices
Retrieve event logs for the last 24 hours

Cisco APIC (ACI Data Center)

Show overall ACI fabric health
List all APIC tenants
Search for endpoint with IP address 10.1.1.50
Analyze connectivity between EPG web and EPG database
Show top talkers in Production tenant
Display fabric topology
List all contracts in tenant Production

Cisco NDFC

List all NDFC fabrics
Show switches in fabric DC1
Get critical events from the last 24 hours
Show interface details for switch with serial FDO23460MQC
Display VRFs in fabric DC1
Show network deployment status

Palo Alto Panorama

Show Panorama system information
List all managed firewalls
Show device groups and their members
Analyze security rules quality for device-group Production
Find rules without security profile in device-group DMZ
Check version compliance across all firewalls
Show configuration audit logs
Find duplicate address objects
Show pending configuration changes

Skills (Guided Workflows)

The recommended way to invoke a skill is to explicitly instruct the agent to load and follow it:

Load and execute the skill "infrastructure-health-check".
Follow every step of the procedure in order and produce a structured report.
Use skills_list to find the most appropriate skill, then load it with skills_load
and execute it step by step.
Task: BGP sessions on router 10.0.0.1 are flapping since this morning.
# Discovery and filtering
List all available skills
List skills for platform ACI
List skills tagged with "change-management"

# Monitoring and NOC
Run an infrastructure health check across all platforms
Perform a WiFi health monitoring report on the Aruba controller
Do a deep dive on device router-wan-01

# Troubleshooting
Diagnose BGP on MikroTik router 10.0.0.1
Track endpoint with IP 10.1.2.50 in the ACI fabric
Run a full ACI fabric health diagnostic
Check connectivity between device A and device B

# Compliance and Audit
Run a Panorama security audit on device-group Production
Check software version compliance and certificate expiry across all firewalls
Audit the ACI configuration for tenant Prod

# Change Management
Perform a pre-check before the maintenance window for change CHG0012345
Validate the post-change state and compare with the pre-check baseline
Detect any unauthorized configuration changes in the last 48 hours

# Inventory and Capacity
Generate a consolidated multi-vendor inventory
Map the physical network topology using LLDP discovery
Produce a capacity planning report for the infrastructure

# Incident Response
Correlate events and logs to identify the root cause of the incident
reported at 14:30 UTC — application servers cannot reach the database

Skills are step-by-step operational procedures in Markdown. The LLM calls skills_list() to discover available procedures filtered by platform or tag, then skills_load() to retrieve the full procedure and follow it by calling the referenced MCP tools in sequence. Each skill includes a Decision Matrix, Output Standards for enterprise-grade reporting, and a Notes section with operational best practices.


Technical Architecture

Project Structure

git-netai/
├── server.py                    # MCP entry point (FastMCP stdio transport)
├── skills_engine.py             # Skills index + loader (in-memory, YAML frontmatter)
├── connectors/                  # Asynchronous connector modules
│   ├── ssh_c.py                # Generic SSH connector (asyncssh)
│   ├── mikrotik_c.py           # MikroTik REST API connector (httpx)
│   ├── mikrotik_ssh_c.py       # MikroTik SSH connector (asyncssh)
│   ├── paloalto_c.py           # Palo Alto SSH PTY connector (asyncssh)
│   ├── panorama_c.py           # Palo Alto Panorama REST API connector (httpx + XML→JSON)
│   ├── aruba_c.py              # Aruba WiFi REST API connector (httpx)
│   ├── graylog_c.py            # Graylog REST API connector (httpx)
│   ├── librenms_c.py           # LibreNMS REST API connector (httpx)
│   ├── apic_c.py               # Cisco APIC REST API connector (httpx + JWT cache)
│   └── ndfc_c.py               # Cisco NDFC REST API connector (httpx + JWT cache)
├── skills/                      # Diagnostic skills (Markdown procedures with YAML frontmatter)
│   ├── TEMPLATE.md                          # Template and frontmatter reference for new skills
│   ├── bgp-diagnostic-mikrotik.md           # BGP session diagnostic on MikroTik
│   ├── connectivity-check.md                # End-to-end connectivity check
│   ├── multicast-diagnostic-aci.md          # ACI multicast diagnostic
│   ├── infrastructure-health-check.md       # Multi-platform health overview (NOC/shift handover)
│   ├── wifi-health-monitoring.md            # Aruba WiFi fleet health and RF audit
│   ├── device-deep-dive.md                  # Deep investigation of a single device (LibreNMS)
│   ├── aci-endpoint-tracking.md             # Locate and diagnose an endpoint in ACI
│   ├── aci-fabric-health-diagnostic.md      # ACI fabric degradation investigation
│   ├── aci-configuration-audit.md           # ACI logical config consistency audit
│   ├── aci-traffic-analysis.md              # ACI top talkers and interface utilization
│   ├── panorama-security-audit.md           # Firewall security rules quality audit
│   ├── compliance-versions-certificates.md  # Software versions and certificate expiry check
│   ├── change-pre-check.md                  # Baseline capture before a planned change
│   ├── change-post-check.md                 # Regression validation after a change
│   ├── configuration-drift-detection.md     # Unauthorized change detection (multi-source)
│   ├── multi-vendor-inventory.md            # Consolidated inventory across all platforms
│   ├── network-topology-mapping.md          # LLDP-based physical topology discovery
│   ├── ndfc-deployment-validation.md        # NDFC network/VRF deployment validation
│   ├── incident-root-cause-correlation.md   # Multi-source incident correlation and timeline
│   └── capacity-planning-report.md          # Infrastructure capacity assessment
├── pyproject.toml              # UV project configuration and dependencies
├── uv.lock                     # UV dependency lockfile
├── .env                        # Environment variables (not version controlled)
├── .gitignore                  # Git ignore rules
└── README.md                   # Project documentation

Skills System

Skills are step-by-step diagnostic and operational procedures stored as Markdown files in skills/*.md. Each file carries a YAML frontmatter header (title, platform, tags, required tools) parsed into an in-memory index at server startup. Two dedicated MCP tools expose the system.

How it works:

  1. The LLM calls skills_list() to discover available skills — returns metadata only (name, title, platform, tags, description, required tools), never content

  2. Optional filters: skills_list(platform="mikrotik") or skills_list(tag="bgp")

  3. The LLM calls skills_load("bgp-diagnostic-mikrotik") to retrieve the full procedure — partial and case-insensitive name matching supported; both skill_name and name parameters are accepted

  4. The Markdown content describes each step: which MCP tool to call, expected results, and decision logic

  5. The LLM follows the procedure autonomously, calling the referenced tools in sequence

  6. Each skill enforces Output Standards: structured sections, professional tone, enterprise-ready reports suitable for incident tickets, audit documents, or management briefings

Creating a new skill:

  1. Copy skills/TEMPLATE.md to skills/{subject}-{platform}.md

  2. Fill in the YAML frontmatter (title, platform, tags, tools, description)

  3. Write the procedure steps referencing existing MCP tools

  4. Call skills_list(reload=True) to refresh the index — no server restart needed

Frontmatter schema (required in every skill file):

---
title: BGP Diagnostic on MikroTik
platform: mikrotik  # mikrotik | aruba | aci | graylog | librenms | paloalto | panorama | generic
tags: [bgp, routing, peering, sessions]
tools: [get_mikrotik_bgp_sessions, get_mikrotik_bgp_connections]
description: One-sentence description of what this skill diagnoses.
---

Available skills (20):

Skill

Platform

Category

Description

bgp-diagnostic-mikrotik

mikrotik

Troubleshooting

BGP session diagnostic (sessions, config, routes, logs)

connectivity-check

generic

Troubleshooting

End-to-end connectivity verification across devices

multicast-diagnostic-aci

aci

Troubleshooting

ACI fabric multicast diagnostic (GIPo, bridge domains, IGMP)

infrastructure-health-check

generic

Monitoring

Multi-platform health overview for NOC/shift handover

wifi-health-monitoring

aruba

Monitoring

WiFi fleet health: APs, clients, RF channels, rogue APs

device-deep-dive

librenms

Monitoring

Full investigation of a single device (sensors, interfaces, logs)

aci-endpoint-tracking

aci

Troubleshooting

Locate an endpoint in ACI fabric and diagnose connectivity

aci-fabric-health-diagnostic

aci

Troubleshooting

ACI fabric degradation: faults, nodes, topology, resources

panorama-security-audit

panorama

Compliance

Firewall security rules quality: profiles, unused rules, overrides

compliance-versions-certificates

panorama

Compliance

Software version matrix and certificate expiry across fleet

aci-configuration-audit

aci

Compliance

ACI logical config consistency: tenants, VRFs, EPGs, contracts

change-pre-check

generic

Change Management

Baseline capture before a planned maintenance change

change-post-check

generic

Change Management

Regression validation by comparison with pre-check baseline

configuration-drift-detection

generic

Change Management

Unauthorized change detection across Panorama, ACI, and logs

multi-vendor-inventory

generic

Inventory

Consolidated inventory across all platforms (CMDB-ready)

network-topology-mapping

generic

Inventory

LLDP-based physical topology discovery and documentation

aci-traffic-analysis

aci

Capacity

ACI top talkers, interface utilization, and TCAM capacity

ndfc-deployment-validation

generic

Automation

NDFC network/VRF deployment status and configuration preview

incident-root-cause-correlation

generic

Incident Response

Multi-source timeline correlation to identify root cause

capacity-planning-report

generic

Capacity

Infrastructure capacity assessment across all domains

Asynchronous Design Patterns

1. Persistent HTTP Sessions

REST API connectors (Aruba, Graylog, LibreNMS) use persistent HTTP connections to minimize connection overhead:

async with httpx.AsyncClient(timeout=30) as client:
    response = await client.get(url, headers=headers)
    # HTTP session is automatically reused for subsequent requests

2. Thread-Safe JWT Token Caching

APIC and NDFC connectors implement thread-safe JWT token caching with automatic renewal:

_token_cache = {"token": None, "expires_at": 0, "lock": asyncio.Lock()}

async def _get_token():
    async with _token_cache["lock"]:
        if time.time() < _token_cache["expires_at"]:
            return _token_cache["token"]
        # Automatic token renewal when expired
        return await _authenticate()

Key features:

  • Async lock prevents concurrent authentication requests

  • Configurable token expiration with safety margin

  • Automatic renewal on 401 responses

  • Zero-downtime token refresh

3. Parallel Execution with Timeout Protection

SSH connectors support parallel command execution across multiple devices:

async def send_custom_command_parallel(targets: List[Dict], timeout: int = 120):
    tasks = [execute_single(target) for target in targets]
    results = await asyncio.wait_for(
        asyncio.gather(*tasks, return_exceptions=True),
        timeout=timeout
    )
    return results

Benefits:

  • Concurrent execution across multiple devices

  • Global timeout prevents indefinite hangs

  • Exception handling per device

  • Results aggregated in single response

4. PTY Interactive Sessions

Palo Alto PAN-OS requires PTY (pseudo-terminal) interactive sessions due to non-standard SSH implementation:

async with asyncssh.connect(ip, ...) as conn:
    async with conn.create_process(term_type='vt100') as process:
        await process.stdin.write(command + '\n')
        output = await process.stdout.read()

Why PTY is required:

  • PAN-OS CLI expects interactive terminal

  • Standard SSH exec channels are rejected

  • Terminal emulation (vt100) required for proper output formatting

5. Encrypted Credential Injection (dotenvx)

Credentials are never stored in plain text. dotenvx intercepts the process launch, decrypts the .env file (AES-256-GCM), and injects the variables into the process environment before Python starts. The application code reads os.getenv() as usual — no change required in the connectors.

dotenvx run -- uv run python server.py
    │
    ├─ reads .env (AES-256-GCM ciphertext)
    ├─ reads DOTENV_PRIVATE_KEY (from .env.keys or env field in MCP config)
    ├─ decrypts → injects into os.environ
    └─ spawns Python process
         └─ connectors read os.getenv("APIC_PASSWORD") → plaintext value

Key properties:

  • The encrypted .env can be committed to version control — ciphertext only

  • The private key (.env.keys) is the only secret to protect and distribute

  • dotenvx is external to UV — installed once per machine via Homebrew or install script

  • If DOTENV_PRIVATE_KEY is missing or invalid, dotenvx logs a warning but does not block startup — connectors will fail at first network call with a None credential error

Key Dependencies

Library

Version

Purpose

fastmcp

2.13+

MCP server framework with stdio transport

asyncssh

2.21+

Asynchronous SSH client (RFC-compliant + PTY support)

httpx

0.28+

Async HTTP client with connection pooling

mcp[cli]

1.23+

MCP protocol implementation and CLI tools

dotenvx (external)

1.54+

Encrypted .env management — installed via Homebrew, not UV


Testing

Quick Verification

# Verify MCP server loads correctly (with encrypted .env)
dotenvx run -- uv run python -c "from server import mcp; print(f'{mcp.name} operational')"

# Test SSH connector
uv run python -c "
import asyncio
from connectors.ssh_c import send_custom_command
result = asyncio.run(send_custom_command('192.168.1.1', 'show version'))
print(result)
"

# Test REST API connector (LibreNMS)
uv run python -c "
import asyncio
from connectors.librenms_c import list_devices
result = asyncio.run(list_devices())
print(result)
"

Response Format

All connector functions return a standardized dictionary structure:

{
    "success": bool,           # True if operation completed successfully
    "output": dict|str|list,   # Response data (structure varies by connector)
    "error": str               # Error message if success is False
}

Success response example:

{
    "success": True,
    "output": {"hostname": "router-01", "version": "7.14.1"},
    "error": None
}

Error response example:

{
    "success": False,
    "output": None,
    "error": "Connection timeout after 30 seconds"
}

Security Considerations

Development vs Production

Aspect

Development Environment

Production Environment

Credentials

Local .env file

Secrets manager (HashiCorp Vault, AWS Secrets Manager, 1Password CLI)

SSL Verification

VERIFY_SSL=false (lab devices with self-signed certificates)

VERIFY_SSL=true with valid certificate chain

SSH Known Hosts

Disabled (known_hosts=None) for rapid prototyping

Strict validation with maintained known_hosts file

Account Permissions

Admin accounts for full access

Service accounts with minimal required privileges (least privilege principle)

Logging

Debug logging enabled for troubleshooting

Session logs disabled to prevent credential exposure

Network Access

Direct device access

Restricted access via bastion host/jump server with firewall rules

Production Credential Management

Example using 1Password CLI for secure credential injection:

# Launch server — dotenvx decrypts .env at startup using the private key
dotenvx run -- uv run python server.py

# Alternative: inject private key from a secrets manager (1Password, Vault, etc.)
export DOTENV_PRIVATE_KEY=$(op read "op://Production/netai/dotenv-private-key")
dotenvx run -- uv run python server.py

Audit and Compliance

For production deployments:

  • Enable audit logging for all MCP tool invocations

  • Implement role-based access control (RBAC) at MCP client level

  • Rotate service account credentials regularly (90-day maximum)

  • Monitor for suspicious command patterns or unauthorized access attempts

  • Maintain audit trail of all configuration changes


Troubleshooting

Common Issues and Solutions

Issue

Diagnosis

Solution

SSH authentication failure

Incorrect credentials or account locked

Verify SSH_USERNAME and SSH_PASSWORD in .env. Test manually: ssh user@host. Check account status on target device.

Connection timeout

Network unreachable or firewall blocking

Verify connectivity: ping <host>, telnet <host> <port>. Check firewall rules and routing. Increase timeout values in .env.

SSL/TLS certificate error

Self-signed certificate or untrusted CA

Development: Set VERIFY_SSL=false. Production: Install proper CA certificates or use certifi bundle.

JWT token expired (APIC/NDFC)

Token lifetime exceeded

Token renewal is automatic. If persistent, verify credentials and check APIC/NDFC authentication logs.

MCP server fails to start

Missing dependencies or Python version mismatch

Check uv --version and python --version (must be 3.12+). Re-run uv sync to reinstall dependencies.

Palo Alto session timeout

PAN-OS aggressive session timeout

Increase timeout parameter in tool calls. Consider implementing keepalive packets.

LibreNMS API 401 error

Invalid or expired API token

Regenerate API token in LibreNMS web interface under user settings. Update LIBRENMS_API_TOKEN in .env.

APIC/NDFC 403 forbidden

Insufficient account permissions

Verify account has required role assignments (admin or fabric-admin for full access).

Enabling Debug Logging

Add the following to server.py for detailed logging output:

import logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

For production environments, configure logging to external syslog or SIEM:

import logging
from logging.handlers import SysLogHandler

handler = SysLogHandler(address=('syslog.example.com', 514))
logging.basicConfig(handlers=[handler], level=logging.INFO)

Roadmap

Current Implementation

  • 100% asynchronous architecture (asyncio/asyncssh/httpx)

  • 10 connectors (SSH, MikroTik REST+SSH, Aruba, Palo Alto SSH, Panorama, Graylog, LibreNMS, APIC, NDFC)

  • 97 exposed MCP tools (95 connectors + 2 skills tools)

  • Smart JWT cache with automatic renewal

  • Persistent HTTP sessions with keepalive

  • Parallel execution with timeout protection

  • PTY support for Palo Alto PAN-OS

  • Modern UV management (pyproject.toml + uv.lock)

  • Encrypted credential management with dotenvx (AES-256-GCM)

  • Panorama API integration with XML→JSON conversion

  • Skills system with in-memory index, YAML frontmatter, platform/tag filtering, and fuzzy name matching

  • 20 professional skills across 7 operational categories (monitoring, troubleshooting, compliance, change management, inventory, capacity, incident response)

  • Enterprise Output Standards enforced in every skill (structured reports, professional tone, enterprise-ready)

Planned Enhancements

Additional Platform Support & more endpoints:

  • Add more LibreNMS endpoints (alerts, device groups, inventory)

  • Add more APIC endpoints (troubleshooting, change management)

  • Expand Aruba capabilities (RF analytics, heat maps)

  • Expand Panorama capabilities (policy push, commit operations)

Skills:

  • OSPF diagnostic skill (MikroTik / generic)

  • VPN tunnel diagnostic skill (Palo Alto)

  • WiFi client troubleshooting skill (Aruba)

  • Post-incident post-mortem report skill


License

This project is licensed under the MIT License. See the LICENSE file for complete terms and conditions.


Acknowledgments

  • FastMCP - High-performance MCP server framework

  • asyncssh - Production-grade asynchronous SSH implementation

  • httpx - Modern async HTTP client with HTTP/2 support

  • UV - Next-generation Python package manager built in Rust

  • Anthropic - Model Context Protocol specification and reference implementations


Support

For issues, questions, or contributions:


Professional network automation for enterprise environments

Available Tools

97 tools
apic_analyze_connectivityA
Perform comprehensive connectivity and health analysis of the APIC infrastructure.

Returns complete analysis including:
- APIC controller connectivity and version
- Fabric health (nodes online, critical faults)
- Capacity metrics and high-utilization nodes
- Multicast configuration summary

This is a composite function that provides an overall health check of the entire fabric.

Inputs: no named parameters.

apic_analyze_pathA
Analyze network paths between two EPGs.

Args:
    src_epg: Source EPG DN or name
    dst_epg: Destination EPG DN or name

Returns:
- Contracts found between EPGs
- Consumer/provider relationships
- Connectivity status

Useful for troubleshooting connectivity issues and validating security policies.

Inputs: src_epg (required), dst_epg (required).

apic_get_audit_logsA
Retrieve audit logs of configuration changes.

Args:
    hours: Number of hours back to retrieve logs (default: 24h)

Returns audit logs with user activity breakdown and configuration changes.
Limited to 50 most recent changes.

Inputs: hours.

apic_get_bridge_domain_multicast_by_tenantA
Retrieve multicast information for bridge domains of a specific tenant.

Args:
    tenant: Tenant name to filter bridge domains

Returns multicast configuration for the tenant's bridge domains including GIPo addresses.

Inputs: tenant (required).

apic_get_bridge_domains_multicastA
Retrieve multicast information for all bridge domains.

Returns comprehensive multicast configuration including:
- GIPo multicast addresses (bcastP) for BUM traffic
- IGMP snooping configuration
- Multicast flooding settings
- IPv6 multicast support
- Discovered IGMP groups
- Static multicast groups

Inputs: no named parameters.

apic_get_capacity_metricsA
Retrieve fabric capacity metrics.

Returns capacity information for each node including:
- Current usage
- Maximum capacity
- Utilization percentage
- Context information

Useful for capacity planning and resource monitoring.

Inputs: no named parameters.

apic_get_contractsA
Retrieve security contracts from APIC.

Args:
    tenant: Optional tenant name filter. If not specified, returns contracts from all tenants.

Returns contracts with tenant, name, description, scope, priority, and DSCP settings.

Inputs: tenant.

apic_get_cpu_utilizationA

Retrieve CPU utilization for all fabric nodes.

Returns CPU usage statistics per node including average, max, and min utilization. Shows user, kernel, idle, and wait times for each node.

Inputs: no named parameters.

apic_get_epg_endpointsA
Retrieve endpoints from a specific EPG.

Args:
    tenant: Tenant name
    application: Application profile name
    epg: Endpoint Group name

Returns all endpoints in the EPG with MAC, IP, encapsulation, and location details.

Inputs: tenant (required), application (required), epg (required).

apic_get_epgsA
Retrieve Endpoint Groups (EPGs) from APIC.

Args:
    tenant: Optional tenant name filter. If not specified, returns EPGs from all tenants.

Returns EPGs with tenant, application, name, description, and policy details.

Inputs: tenant.

apic_get_eventsA
Retrieve recent events from APIC event log.

Args:
    time_range: Time range in hours (default: 24h)

Returns recent events with severity breakdown, sorted by creation time.
Limited to 100 most recent events.

Inputs: time_range.

apic_get_fabric_healthA

Get ACI fabric overall health status.

Returns health summary including critical faults count, controller status, and details of the 5 most recent critical faults.

Inputs: no named parameters.

apic_get_fabric_topologyA

Retrieve ACI fabric topology with nodes and links.

Returns complete fabric topology including all nodes (controllers, leafs, spines) and fabric links between them. Useful for understanding physical connectivity.

Inputs: no named parameters.

apic_get_faultsA

Retrieve active faults from the Cisco APIC system.

Returns list of active faults with severity breakdown (critical, major, minor, warning, info). Faults are sorted by severity and creation time (most recent first). Limited to 50 most recent/critical faults.

Inputs: no named parameters.

apic_get_gipo_pool_configA

Retrieve GIPo (Group IP Outer) multicast pool configuration.

Returns GIPo pool configuration for bridge domains and VRFs. GIPo addresses are used for BUM (Broadcast, Unknown unicast, Multicast) traffic in the fabric.

Inputs: no named parameters.

apic_get_health_scoresA
Retrieve health scores of APIC objects.

Returns health scores of monitored objects with severity classification.
Objects are classified as healthy (>=90), minor (75-89), major (50-74), or critical (<50).

Inputs: no named parameters.

apic_get_interface_statisticsB
Retrieve interface statistics for specific node and/or interface.

Args:
    node_id: Optional node ID filter
    interface: Optional specific interface name

Returns interface statistics including operational state, speed, and usage.
Useful for monitoring interface health and performance.

Inputs: node_id, interface.

apic_get_lldp_neighborsA
Retrieve LLDP neighbors discovered on fabric nodes.

Args:
    node_id: Optional node ID filter. If not specified, returns neighbors from all nodes (limited to 50).

Returns LLDP neighbor information including remote system name, port description,
chassis ID, and management IP. Useful for understanding physical topology.

Inputs: node_id.

apic_get_nodes_inventoryA

Retrieve ACI fabric nodes inventory.

Returns complete inventory of fabric nodes including controllers, leafs, and spines. Includes node ID, name, serial number, model, role, version, IP address, and fabric status.

Inputs: no named parameters.

apic_get_physical_interfacesA
Retrieve physical interfaces from a specific node or all nodes.

Args:
    node_id: Optional node ID filter. If not specified, returns interfaces from all nodes (limited to 100).

Returns list of physical interfaces with admin state, operational state, speed, usage, and MTU.

Inputs: node_id.

apic_get_resource_utilizationA
Analyze CPU and memory resource utilization across the fabric.

Returns:
- CPU utilization per node
- Memory utilization per node
- Average CPU and memory usage
- Nodes with high utilization (>80% CPU, >85% memory)

Essential for performance monitoring and capacity planning.

Inputs: no named parameters.

apic_get_tenantsA

List all tenants configured on the Cisco APIC.

Returns list of tenants with name, DN, description, and status. Tenants are sorted alphabetically by name.

Inputs: no named parameters.

apic_get_top_talkersA
Identify top network conversations (top talkers).

Returns the top 20 traffic generators including:
- Tenant and EPG information
- Bytes and packets transferred
- Utilization percentage
- Traffic ranking

Useful for identifying bandwidth consumers and traffic patterns.

Inputs: no named parameters.

apic_get_traffic_analysisB
Analyze network traffic for a tenant or EPG.

Args:
    tenant: Optional tenant name to filter traffic
    epg: Optional EPG name to filter traffic (requires tenant)

Returns traffic statistics including:
- Bytes average, max, and min
- Traffic data over 5-minute intervals
- Total bytes transferred

Useful for traffic monitoring and troubleshooting.

Inputs: tenant, epg.

apic_get_vrfsA
Retrieve VRFs (Virtual Routing and Forwarding instances) from APIC.

Args:
    tenant: Optional tenant name filter. If not specified, returns VRFs from all tenants.

Returns VRFs with tenant, name, description, and policy control settings.

Inputs: tenant.

apic_search_by_ipA
Search APIC objects by IP address.

Args:
    ip_address: IP address to search

Returns matching endpoints and subnets that contain or use this IP address.
Comprehensive search across the fabric.

Inputs: ip_address (required).

apic_test_connectionB

Test connection to Cisco APIC controller.

Inputs: no named parameters.

apic_track_endpointA
Track a specific endpoint by MAC or IP address.

Args:
    mac_or_ip: MAC address (format: XX:XX:XX:XX:XX:XX or XX-XX-XX-XX-XX-XX) or IP address

Returns endpoint location including tenant, application, EPG, encapsulation, and other details.
Useful for troubleshooting connectivity issues.

Inputs: mac_or_ip (required).

aruba_custom_commandA

Execute custom show command on Aruba controller (e.g., 'show ap database').

Inputs: command (required).

aruba_get_ap_databaseC

Get complete list of Access Points from Aruba controller.

Inputs: limit.

aruba_get_ap_statsB

Get AP performance metrics and ARM state.

Inputs: no named parameters.

aruba_get_channelsB

Get active channel information for RF optimization.

Inputs: no named parameters.

aruba_get_clientsC

Get list of connected WiFi clients.

Inputs: limit.

aruba_get_controller_infoA

Get Aruba controller system information and version.

Inputs: no named parameters.

aruba_get_licensesB

Get license compliance information.

Inputs: no named parameters.

aruba_get_rogue_apsC

Get list of unauthorized/rogue access points (Security).

Inputs: limit.

aruba_get_wlansC

Get WLAN/SSID profile configuration.

Inputs: no named parameters.

get_mikrotik_bgp_connectionsC

Retrieves the BGP connection configuration.

Inputs: identifier (required).

get_mikrotik_bgp_sessionsC

Retrieves the state of BGP sessions.

Inputs: identifier (required).

get_mikrotik_healthB

Retrieves system health (temperature, voltage).

Inputs: identifier (required).

get_mikrotik_identityC

Retrieves the name of router.

Inputs: identifier (required).

get_mikrotik_interfacesC

Retrieves the interfaces of a MikroTik router.

Inputs: identifier (required).

get_mikrotik_ipaddressesC

Retrieves the configured IP addresses.

Inputs: identifier (required).

get_mikrotik_logsC

Retrieves system logs (default: last 100 logs).

Inputs: identifier (required), limit.

get_mikrotik_route_prefixC

Query routing for a specific prefix on a MikroTik.

Inputs: identifier (required), dst_address (required).

get_mikrotik_routerboardC

Retrieves the hardware information from the routerboard.

Inputs: identifier (required).

graylog_get_streamsB

Retrieve list of available Graylog log streams.

Inputs: no named parameters.

graylog_search_logsB

Search Graylog logs with query filter (ex: 'bgp', 'firewall'). Default: 1h, 20 results.

Inputs: query (required), hours, limit.

graylog_system_infoB

Retrieve Graylog system information.

Inputs: no named parameters.

librenms_get_device_eventlogC

Get event logs for a specific device.

Inputs: hostname (required), limit, sort_order.

librenms_get_device_healthC

Get device health information including all sensor types.

Inputs: hostname (required).

librenms_get_device_infoC

Get detailed device information by hostname.

Inputs: hostname (required).

librenms_get_device_portsC

Get all ports/interfaces information for a device.

Inputs: hostname (required).

librenms_get_devices_by_osA

Get all devices running a specific OS (e.g., 'routeros', 'ios', 'linux').

Inputs: os_name (required).

librenms_get_device_sensorsC

Get device sensors with optional filter (temperature, voltage, state, etc.).

Inputs: hostname (required), sensor_type.

librenms_get_device_statsC

Get comprehensive device statistics (uptime, ports, availability).

Inputs: hostname (required).

librenms_get_eventlogC

Get general event logs from LibreNMS.

Inputs: limit, sort_order.

librenms_get_locationsA

Get all locations configured in LibreNMS.

Inputs: no named parameters.

librenms_list_devicesA

List all devices or filter by criteria (type, os, location, hostname).

Inputs: filter_type, filter_value.

mikrotik_ssh_customC

Execute custom MikroTik command via SSH (for LLM flexibility).

Inputs: identifier (required), command (required).

mikrotik_ssh_route_checkC

Check route to destination via SSH (NOT available in REST API).

Inputs: identifier (required), destination_ip (required).

ndfc_get_all_switchesB
Get list of all switches across all fabrics.

Returns:
    Dict with list of switches including serial numbers, fabric, IP addresses, etc.

Inputs: no named parameters.

ndfc_get_deployment_historyB
Get configuration deployment history for a specific fabric.

Args:
    fabric_name: Name of the fabric

Returns:
    Dict with deployment history records including timestamps and status

Inputs: fabric_name (required).

ndfc_get_event_recordsA
Get event records from Nexus Dashboard event monitoring.
This endpoint provides critical events, alarms, and system notifications.

Args:
    limit: Maximum number of events to return (default: 50, max recommended: 1000)
    severity: Optional filter by severity (critical, error, warning, info)

Returns:
    Dict with event records including metadata and items with severity, description, timestamps, etc.
    Results are automatically limited client-side if API returns more than requested.

Inputs: limit, severity.

ndfc_get_fabricsC
Get list of fabric configurations.

Returns:
    Dict with fabrics information including fabric names, types, and status

Inputs: no named parameters.

ndfc_get_fabric_summaryA
Get summary of all fabric associations (MSD fabric-member relationships).

Returns:
    Dict with fabric summary and associations

Inputs: no named parameters.

ndfc_get_interface_detailsA
Get detailed interface information for a specific switch by serial number.

Args:
    serial_number: Serial number of the switch (e.g., "FDO23460MQC")

Returns:
    Dict with list of all interfaces and their details (status, VLAN, compliance, etc.)

Inputs: serial_number (required).

ndfc_get_network_previewB
Get configuration preview for a specific network deployment.

Args:
    fabric_name: Name of the fabric
    network_name: Name of the network

Returns:
    Dict with configuration preview for each switch showing what will be deployed

Inputs: fabric_name (required), network_name (required).

ndfc_get_networksB
Get list of networks in a specific fabric.

Args:
    fabric_name: Name of the fabric

Returns:
    Dict with networks information including network names, VLANs, and configuration

Inputs: fabric_name (required).

ndfc_get_network_statusA
Get deployment status for a specific network in a fabric.

Args:
    fabric_name: Name of the fabric
    network_name: Name of the network

Returns:
    Dict with network status details including deployment state and errors

Inputs: fabric_name (required), network_name (required).

ndfc_get_sitesB
Get list of NDFC sites/fabrics.

Returns:
    Dict with sites information

Inputs: no named parameters.

ndfc_get_switchesA
Get list of switches in a specific fabric.

Args:
    fabric_name: Name of the fabric

Returns:
    Dict with switches information including serial numbers, IP addresses, and status

Inputs: fabric_name (required).

ndfc_get_vrfsA
Get list of VRFs (Virtual Routing and Forwarding instances) in a specific fabric.

Args:
    fabric_name: Name of the fabric

Returns:
    Dict with VRFs information including VRF names and configuration

Inputs: fabric_name (required).

ndfc_loginA
Authenticate to NDFC and obtain JWT token.
Token is valid for 3600 seconds (1 hour).

Returns:
    Dict with success status and authentication information

Inputs: no named parameters.

ndfc_logoutA
Logout from NDFC and clear JWT token.

Returns:
    Dict with success status

Inputs: no named parameters.

paloalto_send_commandA
Execute SSH command specifically on Palo Alto firewalls.

🔥 USE THIS for ALL Palo Alto firewall commands (show vpn, show system, show routing, etc.).
This tool uses PTY interactive sessions required by Palo Alto PAN-OS.

Examples:
- "show vpn gateway"
- "show system info"
- "show routing route"

Inputs: ip_address (required), command (required).

paloalto_send_command_parallelA
Execute SSH commands on multiple Palo Alto firewalls in parallel.

🔥 USE THIS for batch operations on multiple Palo Alto firewalls.

Args:
    targets: List of {"ip": "10.240.203.241", "command": "show vpn gateway"}
    timeout: Global timeout in seconds (default: 120s)

Inputs: targets (required), timeout.

panorama_audit_logsB
Get configuration audit logs (who changed what, when).

Args:
    limit: Maximum number of logs to return (default: 100, max: 1000)

Returns:
    Dict with total_logs count and logs list containing:
    - time, admin, command, result, path

Inputs: limit.

panorama_config_diffA
Get pending configuration changes (candidate vs running config).

Returns:
    Dict with has_pending_changes boolean, diff_summary, and diff_content

Inputs: no named parameters.

panorama_custom_commandB
Execute custom operational command on Panorama.

Args:
    cmd: XML command (e.g., "<show><system><info></info></system></show>")

Returns:
    Dict with command execution results in JSON format

Inputs: cmd (required).

panorama_device_groupsA
Get list of Device-Groups and their member firewalls.

Returns:
    Dict with total_device_groups count and device_groups list
    containing name, member devices, and device count

Inputs: no named parameters.

panorama_duplicate_addressesB
Find duplicate address objects (same IP, different names).

Args:
    limit: Maximum number of addresses to analyze (default: 100)

Returns:
    Dict with total_addresses, duplicates_found count, and
    duplicates list with IP and conflicting names

Inputs: limit.

panorama_expiring_certificatesA
Check for certificates expiring within threshold days.

Args:
    days_threshold: Days before expiration to alert (default: 30)

Returns:
    Dict with total_certificates, expiring_certificates list,
    expired_certificates list, and counts

Inputs: days_threshold.

panorama_generate_keyB
Generate and return a Panorama API key.

Returns:
    Dict with api_key for manual API operations

Inputs: no named parameters.

panorama_local_overridesA
Find local overrides not managed by Panorama.

Args:
    limit: Maximum number of devices to check (default: 100)

Returns:
    Dict with devices_with_overrides list

Inputs: limit.

panorama_managed_devicesA
Get inventory of all firewalls managed by Panorama.

Returns:
    Dict with total_devices count and devices list containing:
    - device name, serial, version, HA state, connection status
    - IP address, model, uptime, installed plugins

Inputs: no named parameters.

panorama_never_matched_rulesA
Find security rules that never matched traffic.

Args:
    device_group: Name of the device-group to analyze
    days: Analysis period in days (default: 30)
    limit: Maximum number of rules to analyze (default: 100)

Returns:
    Dict with never_matched_rules list and analysis details

Inputs: device_group (required), days, limit.

panorama_rules_without_profileA
Find security rules without Security Profile Group attached.

Args:
    device_group: Name of the device-group to analyze
    limit: Maximum number of rules to analyze (default: 100)

Returns:
    Dict with total_rules_analyzed, rules_without_profile list, and count

Inputs: device_group (required), limit.

panorama_security_rules_analysisA
Analyze security rules quality for a Device-Group.

Args:
    device_group: Name of the device-group to analyze

Returns:
    Dict with rules list and quality_issues analysis:
    - rules_without_description count
    - rules_with_generic_names count
    - too_permissive_rules count (any/any/any)
    - details with specific rule names

Inputs: device_group (required).

panorama_system_infoA
Get Panorama system information.

Returns:
    Dict with hostname, version, uptime, serial, model, and security versions
    (threat, AV, wildfire, URL filtering)

Inputs: no named parameters.

panorama_unused_objectsB
Find unused address objects in Panorama configuration.

Args:
    object_type: Type of object to analyze (default: "address")

Returns:
    Dict with total_objects, unused_count, and unused_objects list

Inputs: object_type.

panorama_unused_zonesA
Find unused zones in security rules.

Args:
    limit: Maximum number of zones to analyze (default: 100)

Returns:
    Dict with total_zones and zones list

Inputs: limit.

panorama_version_complianceA
Check PAN-OS, Threat, AV, Wildfire version compliance across devices.

Returns:
    Dict with panorama versions and devices_versions showing
    version and model for each managed firewall

Inputs: no named parameters.

send_custom_commandA
Execute SSH command on generic network devices (Cisco, Juniper, Arista, Linux, etc.).

⚠️ NOT for Palo Alto firewalls - use paloalto_send_command instead.
Works with standard SSH devices that don't require PTY interactive sessions.

Inputs: identifier (required), command (required).

send_custom_command_parallelA
Execute SSH commands on multiple generic network devices in parallel.

⚠️ NOT for Palo Alto firewalls - use paloalto_send_command_parallel instead.

Args:
    targets: List of {"ip": "192.168.1.1", "command": "show version"}
    timeout: Global timeout in seconds (default: 30s)

Example:
    [
        {"ip": "192.168.1.1", "command": "show version"},
        {"ip": "192.168.1.2", "command": "show ip route"}
    ]

Inputs: targets (required), timeout.

skills_listA
List available diagnostic skills/workflows.

Skills are step-by-step procedures that guide Claude through structured
troubleshooting using the MCP tools. Call this first to discover what's
available, then use skills_load() to load a specific skill.

Args:
    platform: Filter by platform (mikrotik, aruba, aci, graylog, librenms,
              paloalto, panorama, generic). If None, returns all skills.
    tag: Filter by topic tag (bgp, routing, multicast, connectivity, wifi…).
         If None, no tag filter is applied.
    reload: Set True to refresh the index after adding new skill files (default: False).

Returns:
    List of skills with name, title, platform, tags, description and required tools.
    Never returns skill content — use skills_load() for that.

Inputs: platform, tag, reload.

skills_loadA
Load a diagnostic skill and return its full procedure.

The skill contains step-by-step instructions: which MCP tools to call, in what
order, what results to expect, and how to interpret anomalies. Read and follow
the skill before executing the corresponding workflow.

Matching priority: exact → case-insensitive exact → prefix → substring.
If the name is ambiguous, returns a list of candidates instead of content.

Args:
    skill_name: Skill name (e.g., "bgp-diagnostic-mikrotik", "connectivity-check").
                Partial and case-insensitive matches are supported.
                Use skills_list() first if unsure of the exact name.
    name: Alias for skill_name — either parameter is accepted.

Returns:
    Full Markdown content of the skill plus metadata (platform, tags, token estimate).

Inputs: skill_name, name.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3/5.0

    Scored across 97 tools

    Disambiguation3/5

    While tools target distinct platforms, there are multiple 'send custom command' style tools (send_custom_command, paloalto_send_command, mikrotik_ssh_custom, etc.) that could cause confusion. Additionally, several log retrieval tools exist across different systems (apic_get_events, graylog_search_logs, librenms_get_eventlog) with overlapping purposes.

    Naming Consistency4/5

    Most tools follow a consistent platform_verb_noun pattern (apic_get_tenants, mikrotik_get_interfaces). However, 'skills_list' and 'skills_load' lack a platform prefix, and 'apic_analyze_connectivity' uses 'analyze' instead of 'get', introducing minor inconsistency.

    Tool Count2/5

    With 97 tools covering multiple platforms (ACI, Aruba, MikroTik, Graylog, LibreNMS, NDFC, Palo Alto, Panorama, and generic SSH), the server feels like a kitchen sink rather than a focused assistant. This excessive count can overwhelm agents and degrade selection accuracy.

    Completeness3/5

    The toolset is strong for monitoring and diagnostics on many platforms, but lacks write/modify operations for most devices (e.g., no create/update for MikroTik, Aruba, or generic devices). Skills and analysis tools compensate partially, but the surface is not fully capable of end-to-end network management.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      C
      quality
      D
      maintenance
      Comprehensive MCP server for integrating with Zabbix monitoring systems, providing 90+ API tools across 19 categories for monitoring, alerting, and infrastructure management.
      100
      15
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Multi-threaded terminal management MCP server for AI assistants, enabling async command execution, batch operations, and real-time web monitoring with up to 100 concurrent terminals.
      33 PyPI
      2
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      A comprehensive MCP server for network device management via SSH/Telnet. Supports multiple vendors such as Cisco IOS and BDCOM, enabling AI assistants to execute commands and manage routers, switches, and firewalls.
      4
      MIT