unas-mcp

unas-mcp

MCP server for managing a Ubiquiti UNAS Pro NAS, providing health monitoring, storage and disk inventory, NFS export visibility, read-only file inspection, and gated lifecycle operations via SSH and the UniFi Drive API.

Category
Visit Server

README

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.

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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured