Files
skill-unifi/SKILL.md

9.2 KiB

name: unifi description: Diagnostica y consulta la red UniFi del beneficio Rio Frio (UDM Pro en 192.168.87.5) en lenguaje natural. Úsala cuando el usuario pregunte sobre dispositivos conectados, APs, switches, clientes WiFi, estado de la red local, si tal báscula/impresora/ESP32 está online, ancho de banda, MACs, IPs del LAN 192.168.87.0/24, o cualquier diagnóstico del UDM Pro. Ejemplos: "qué hay conectado al WiFi", "está online la impresora del patio", "qué AP tiene más clientes", "muéstrame los dispositivos del laboratorio", "qué IP tiene la báscula tolva_bodega", "cuántos APs tengo y están todos arriba", "quién está chupándose el internet", "qué pasó con la conexión hace un rato". allowed-tools: Bash, Read, Grep

UniFi UDM Pro — skill de diagnóstico local

Qué es esto

Skill 100% local que consulta el UDM Pro del beneficio Rio Frio (192.168.87.5) usando la Integration API oficial de UniFi Network (≥ v9.3.43, X-API-KEY stateless).

No hay servidor intermedio, no hay MCP server, no hay nada en el Swarm. Solo curl desde tu PC contra el UDM Pro vía la LAN o a través del DNS interno.

  • Base URL: https://192.168.87.5/proxy/network/integration/v1
  • Auth: header X-API-KEY: $UNIFI_API_KEY
  • El API key vive en: ~/.claude/skills/unifi/.env (local, no versionado)
  • Scope: read-only (Integration API write está en preview, no lo tocamos)

Cómo invocarla correctamente

Antes de cualquier query:

  1. Verifica que ~/.claude/skills/unifi/.env exista. Si no, avísale al usuario y dale el comando para crearlo (ver "Setup inicial" más abajo).
  2. Verifica conectividad básica con un GET /sites. Si falla con 401/403 → API key inválida o caducada. Si falla con conexión rechazada/timeout → no estás en la LAN del beneficio (recordá que 192.168.87.5 no es ruteable desde fuera).

Dos APIs, dos scripts

Script API Auth Cuándo usar
query.sh Integration API v1 X-API-KEY (stateless) devices, clients (sin bytes/signal), networks, vouchers, statistics/latest
query-classic.sh Classic API session cookie + CSRF (login flow, cache 25 min) health, eventos, alarmas, bytes por cliente, SSID/signal, configs (WLANs, firewall, port forwards)

query.sh (Integration API)

~/.claude/skills/unifi/scripts/query.sh /sites
~/.claude/skills/unifi/scripts/query.sh "/sites/{site}/devices"
~/.claude/skills/unifi/scripts/query.sh "/sites/{site}/clients"

El placeholder {site} se expande automáticamente al UUID del site ($UNIFI_SITE en .env). La Integration API exige UUID, NO el nombre default. Siempre comillas dobles alrededor del path para que la shell no interprete las llaves.

query-classic.sh (Classic API — para todo lo que la Integration no expone)

~/.claude/skills/unifi/scripts/query-classic.sh /stat/health      # WAN/WLAN/LAN/UDM stats
~/.claude/skills/unifi/scripts/query-classic.sh /stat/sta         # clientes CON bytes/signal/SSID
~/.claude/skills/unifi/scripts/query-classic.sh /stat/event       # eventos (login, roaming, etc)
~/.claude/skills/unifi/scripts/query-classic.sh /stat/alarm       # alarmas
~/.claude/skills/unifi/scripts/query-classic.sh /list/wlanconf    # WLANs / SSIDs
~/.claude/skills/unifi/scripts/query-classic.sh /rest/firewallrule

El path corto (/stat/...) se prefija a /proxy/network/api/s/$UNIFI_SITE_NAME automáticamente. La sesión se cachea 25 min en .cache/cookies.txt + .cache/csrf (chmod 600).

Read-only por diseño — modelo de seguridad

Tres capas, en orden de fuerza:

  1. Server-side (la que importa): la cuenta claudecode0 tiene rol "Site View Only" en Network. El UDM responde 403 a cualquier POST/PUT/DELETE sin importar qué cliente intente, vía API key o via Classic. Esto es lo que te garantiza no romper nada.
  2. Guard en los scripts: query.sh y query-classic.sh rechazan flags -X POST/PUT/DELETE/PATCH y -d/--data con exit 3 antes de salir a la red. Defensa en profundidad — falla rápido con error claro.
  3. Doc: esta sección. Si Claude (yo o cualquier futura sesión) lee esto y aún así intenta escribir, el server lo bloqueará igual.

⚠️ La API Key del .env la generó el Owner del UDM (no claudecode0, porque View Only no puede crear keys). Técnicamente esa key tiene scope completo — el guard del script y la convención son lo único que evitan que alguien la use para escribir vía Integration API. Si querés blindaje total ahí también, pedile al Owner que regenere una key suya y revoque la actual.

Si no tenés jq

Los ejemplos de endpoints.md usan jq por brevedad. Si no está instalado (ej. git bash en Windows sin extras), tenés dos opciones:

  1. Instalar jq (recomendado, una vez):
    winget install jqlang.jq
    # o:  choco install jq
    
  2. Usar Python como filtro (ya viene con la PC):
    ~/.claude/skills/unifi/scripts/query.sh "/sites/{site}/devices" \
      | python -c "import json,sys; d=json.load(sys.stdin); [print(x['name'], x['state']) for x in d['data']]"
    

Flujos típicos de diagnóstico

"¿qué está conectado a la red?"

~/.claude/skills/unifi/scripts/query.sh /sites/{site}/clients | jq '.data | length'
~/.claude/skills/unifi/scripts/query.sh /sites/{site}/clients | jq '.data[] | {name, mac, ip, type, uplinkDeviceId, lastSeen}'

Filtra por type (WIRED vs WIRELESS) y por uplinkDeviceId para saber a qué AP/switch está pegado cada uno.

"¿están todos los APs online?"

~/.claude/skills/unifi/scripts/query.sh /sites/{site}/devices | jq '.data[] | {name, model, state, ip, mac, uptime}'

state: ONLINE | OFFLINE | PROVISIONING | UPGRADING | .... Reporta cualquier device con state ≠ ONLINE.

"¿la báscula sacos_bodega (o impresora patio, etc.) está conectada?"

  1. Busca el equipo en topology.md (mapeo nombre → MAC).
  2. Si no está mapeado todavía: lista clientes y proponé al usuario el match más probable basándote en el nombre o en la IP fija conocida (las impresoras del manifest tienen IP fija: printerCentral cubre 192.168.87.142, .147, .150, .220, .221).
  3. Una vez tengas el MAC: query.sh /sites/{site}/clients | jq '.data[] | select(.mac == "AA:BB:...")'
  4. Si lo encontrás, agregá el mapeo a topology.md para futuras queries.

"¿qué AP cubre tal facility?"

Combiná topology.md (zonas físicas → AP esperado) + el listado real de devices filtrado por nombre/ubicación que tengan configurado en el UDM.

"¿qué carga tiene cada AP / cuál está saturado?"

La Integration API NO devuelve bytes ni count de clientes en /clients ni en /devices. Lo que SÍ tenés es statistics/latest por device, con CPU%, RAM%, uplink tx/rxBps y % de retransmisiones por radio (indicador de saturación inalámbrica):

~/.claude/skills/unifi/scripts/query.sh "/sites/{site}/devices/<deviceId>/statistics/latest"

Para ranking de clientes por bytes consumidos NO hay endpoint — necesita Classic API.

No está en la Integration API. Por device sí podés ver uplink.txRateBps/rxRateBps en statistics/latest, pero el health agregado del WAN (latencia, drops, ISP status) solo está en Classic API. Si el usuario insiste, avisale que toca extender la skill con query-classic.sh (login flow). No lo improvises sin avisar.

Setup inicial (lo hace el usuario UNA vez)

  1. Generar API Key en el UDM Pro UI:
    • Abrí https://192.168.87.5 en el navegador (o el dominio interno si lo tenés mapeado).
    • Loggéate con admin local (NO cuenta cloud).
    • UniFi Network → Settings → Control PlaneIntegrations.
    • "Create API Key", copiá el valor (solo se muestra una vez).
  2. Crear el .env:
    cp ~/.claude/skills/unifi/.env.example ~/.claude/skills/unifi/.env
    # Editar y pegar el API key:
    #   UNIFI_API_KEY=<el valor que copiaste>
    
  3. Probar:
    ~/.claude/skills/unifi/scripts/query.sh /sites
    
    Esperado: JSON con un array data que contenga al menos default.

Notas sobre red

  • El UDM Pro está SOLO accesible desde la LAN (192.168.87.0/24). Si vas a usar esta skill desde fuera del beneficio, necesitás VPN/Tailscale o un túnel.
  • El cert TLS del UDM Pro es self-signed → el helper usa curl -k. Es aceptable para tráfico en la LAN, pero no copies ese patrón a apps en producción.
  • DNS interno (*.interno) lo sirve este mismo UDM. Si la skill empieza a fallar en resolución, probá apuntar a la IP cruda 192.168.87.5.

Qué NO hace esta skill

  • No escribe (no bloquea/desbloquea clientes, no provisiona VLANs, no reinicia APs). Read-only por diseño.
  • No habla con UniFi Protect, Access ni Talk. Solo Network.
  • No mantiene cache local. Cada query golpea el UDM Pro.
  • No expone MCP — es Bash + curl. Si más adelante querés exponerla a Claude Desktop o a la agentUI, ahí sí justifica un sidecar Bun en el Swarm.

Referencias

  • endpoints.md — cheat sheet de los 15 endpoints Integration API v1 + algunos Classic útiles
  • topology.md — mapa de MACs/IPs → equipo del beneficio (jala del manifest, se llena con uso)
  • Doc oficial: https://developer.ui.com/ (Integration API)