Skip to main content
Glama

unas-mcp

MCP server for managing a Ubiquiti UNAS Pro 8 NAS (6×26 TB RAID-6, ~104 TB usable) — health monitoring, storage/disk inventory, NFS export visibility, read-only file inspection, and gated lifecycle operations. 20 tools, deployed as a container on VM 102 (http://10.0.40.25:8490/mcp).

What it is

The UNAS Pro 8 exposes two independent surfaces, and this server is a thin, safety-gated layer over both:

  • SSH (root@<host>, key-only, src/unas_mcp/ssh.py) — /proc/mdstat, smartctl, df, rpcinfo, exportfs, uptime/last, uname, and a handful of read-only filesystem commands (ls, du). This is the same transport docs/reference/unas-pro-8-capabilities.md (in the homelab repo) documents as voiding Ubiquiti's warranty — used here only where the UI and the Drive API cannot answer the question.

  • UniFi Drive API (src/unas_mcp/api.py, unofficial/undocumented — findings in docs/drive-api-findings.md) — physical bay mapping (slotId), vendor healthScore/riskReasons, and per-RAID-group currentProtection vs expectedProtection. SSH's /proc/mdstat and smartctl are enough for pass/fail health, but they don't carry which physical bay to pull at the rack or the vendor's own risk scoring — that's the entire reason the Drive API transport exists in this server.

Every parser in this project is "tolerant but honest": a field genuinely absent from a live reply is surfaced as None (or raises, for the small set of fields health decisions are gated on), and is never silently defaulted to a value that reads as healthy (0, "ok", False, or a label count standing in for a verdict actually read). See api.py, parsers/smart.py, and tools/storage.py's module docstrings for the specific traps this pattern was built to close.

Related MCP server: unifi-mcp

Tool inventory (20 tools, 5 groups)

Group

Tool

Tier

What it does

Health (SSH)

unas_health_summary

read

Rolled-up healthy | unhealthy | unknown verdict across array, SMART, capacity, and NFS — unknown on any transport/parse failure or incomplete reply, never silently healthy

unas_array_status

read

Parsed /proc/mdstat — per-array [n/m] state, healthy flag, rebuild/resync/reshape progress

unas_smart_status

read

One SMART record per drive bay (sda-sdf): verdict + the three failure-predicting counters

unas_smart_details

read

Full SMART health + identity record for one drive bay

unas_capacity

read

Media volume capacity in bytes (total/used/avail) + used_pct, from df -B1

unas_nfs_state

read

Whether nfsd/mountd are registered with the local RPC portmapper

unas_uptime_boot

read

uptime + last 5 last -x boot/shutdown records

unas_system_info

read

uname -a + /etc/os-release

Lifecycle (SSH)

unas_smart_test_start

direct

Start a SMART self-test (short/long) on a drive bay

unas_smart_test_status

direct

Read a drive bay's SMART self-test log

unas_firmware_status

read

Firmware/OS release identity

unas_service_status

read

Running systemd services

unas_reboot

confirm

Reboot the appliance — ~9.5 min of NFS downtime for every client; requires confirm="yes"

Storage (Drive API)

unas_pool_status

read

Every pool's status/type/capacity/usage + per-RAID-group protection state

unas_disk_inventory

read

Every physical disk + cache slot: slotId, model, serial, temp, healthScore, riskReasons, error counters

unas_fan_status

read

Raw fan-control status

NFS (SSH)

unas_nfs_exports

read

Live exportfs -v table — export paths, client allow-lists, squash options

unas_fix_permissions

confirm

Recursive chown 977:988 under a share's .data root (the UNAS's hardcoded NFS all_squash uid/gid)

Files (SSH)

unas_list_dir

read

ls -lah on a path under a share

unas_disk_usage_by_dir

read

du -h --max-depth=N on a path under a share (bounded depth, 180s timeout)

Tiers: read = no gate. direct = additive/trivially reversible, no gate. confirm = requires confirm="yes" (safety.requires_confirmation) — anything else raises PermissionError and issues no remote command.

Deliberate exclusions

Two categories of tool are absent by design, not merely unimplemented — their absence is the actual protection, not a confirmation prompt sitting in front of them:

  • No write file operations. Not move, delete, copy, upload, or mkdir. The same bytes are already reachable through nine NFS client mounts with ordinary tools (mv, rm, cp, rsync, ...) — a second write path to the same ~75 TB of data only doubles the ways to corrupt it. See tools/files.py's module docstring. (unas_fix_permissions is the one narrow exception: a chown, not a data-touching write, and the only survivor of an investigated-and-cut NFS-allow-list write path — see tools/nfs.py's module docstring for why that one was rejected.)

  • No pool or disk lifecycle tools at all — no create/destroy/format/ reshape/expand for pools, RAID groups, or disks. safety.py calls this the absent tier: "a confirmation prompt is a speed bump; absence is a wall." is_forbidden_tool_name() in safety.py is defence in depth on top of that absence (it blocks an obviously-named destructive tool from being registered by accident), but the real guarantee is the exact-match allowlist test (tests/test_health_tools.py:: test_registers_exactly_the_twenty_expected_tool_names) — any new tool, named anything, fails it until a human deliberately updates the expected set.

Environment contract

Variable

Purpose

UNAS_HOST

Hostname/IP of the UNAS Pro 8

UNAS_SSH_KEY

Path to the SSH private key used to reach the UNAS

UNAS_API_KEY

UniFi Drive API key (X-API-Key header) for the storage tools — see docs/drive-api-findings.md

MCP_PORT

Port the MCP server listens on (default 8490)

Development

python3.12 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest -v

Docker

docker build -t unas-mcp .

The image includes an openssh-client for the SSH transport.

Deployed

Live on VM 102 (10.0.40.25:8490), registered for Claude Code:

claude mcp add unas --transport http http://10.0.40.25:8490/mcp --scope user

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A safety-first MCP server for managing UniFi networks, exposing 17 tools for telemetry, diagnostics, and guarded mutations with dry-run previews and confirm requirements.
    14
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for UniFi Network Controller enabling AI assistants to manage UniFi infrastructure via natural language. It supports firewall rules, IPv6, and uses lazy/eager tool modes to minimize context usage.
    5
    Mozilla Public 2.0