UniFi MCP Server

UniFi MCP Server

MCP server providing Claude Code with full UniFi network management capabilities -- devices, clients, ports, bandwidth auditing, firewall policies, and traffic rules -- all through natural language.

Category
访问服务器

README

UniFi MCP Server

MCP server providing Claude Code with full UniFi network management capabilities -- devices, clients, ports, bandwidth auditing, firewall policies, and traffic rules -- all through natural language.

License: MIT GitHub release MCP Tools TypeScript Node.js UniFi


Overview

The UniFi MCP Server connects Claude Code to one or more UniFi network controllers via the UDM REST API. It exposes 19 tools that let you query, audit, and configure your network infrastructure conversationally.

Key capabilities:

  • Self-healing authentication -- automatic re-auth on expiry or 401, with proactive refresh and mutex protection against concurrent auth storms
  • Automated TOTP -- generates MFA codes from a stored seed, no manual authenticator app interaction
  • 19 management tools covering devices, clients, ports, port profiles, networks, bandwidth auditing, traffic routes, and firewall policies
  • Encrypted session persistence using AES-256-GCM
  • Resilient API client with 429 throttle handling, 5xx exponential backoff, and 401 transparent re-auth
  • Dual-controller support -- cloud-hosted controllers (two-step MFA) and UDM Pro Max (single-step MFA)

Architecture

graph LR
    CC[Claude Code] <-->|stdio| MCP[MCP Server<br/>StdioServerTransport]
    MCP --> Tools[19 Tools<br/>Zod-validated inputs]
    Tools --> UC[UniFi Client<br/>Axios + retry interceptors]
    UC --> SM[Session Manager<br/>Self-healing auth]
    SM --> SC[Session Cache<br/>AES-256-GCM]
    SM --> TOTP[TOTP Generator<br/>RFC 6238]
    UC -->|HTTPS| API[UniFi Controller<br/>REST API]

    style CC fill:#4A90D9,color:#fff
    style MCP fill:#6C5CE7,color:#fff
    style Tools fill:#00B894,color:#fff
    style UC fill:#FDCB6E,color:#000
    style SM fill:#E17055,color:#fff
    style API fill:#2D3436,color:#fff

Features

Self-Healing Authentication

The server never requires manual re-authentication during operation. The session manager implements a multi-layered strategy:

Layer Trigger Behavior
Proactive refresh Session < 15 min remaining Fire-and-forget re-auth in the background; current request uses existing session
Expired session Session TTL = 0 Blocking re-auth before the request proceeds
401 retry Controller returns HTTP 401 Interceptor triggers re-auth, then transparently retries the original request
Mutex protection Concurrent requests during auth All callers await the same in-flight auth promise (no auth storms)
Failure circuit breaker 3 consecutive auth failures Auth disabled until server restart (prevents credential lockout)

Two-Step MFA with Automated TOTP

Cloud-hosted UniFi controllers require two-step MFA:

sequenceDiagram
    participant S as MCP Server
    participant C as UniFi Controller
    participant T as TOTP Generator

    S->>C: POST /api/auth/login {username, password}
    C-->>S: 200 MFA_AUTH_REQUIRED + UBIC_2FA cookie
    S->>T: Generate TOTP from base32 seed
    T-->>S: 6-digit code
    S->>C: POST /api/auth/login {username, password, token}<br/>Cookie: UBIC_2FA=...
    C-->>S: 200 + Set-Cookie: TOKEN=jwt...
    S->>S: Parse JWT for CSRF token + expiry
    S->>S: Encrypt and persist session to disk

For UDM Pro Max controllers, authentication completes in a single step (username + password + TOTP in one request).

Resilient API Client

Every API call passes through axios interceptors that handle transient failures:

  • 429 Too Many Requests -- waits for Retry-After header (or 5s default), then retries
  • 5xx Server Error -- exponential backoff (1s, 2s, 4s) up to 3 retries
  • 401 Unauthorized -- triggers self-healing re-auth, refreshes headers, retries the request once

Tools Reference

Device Tools (3)

Tool Description Key Parameters
unifi-device-list List all devices (switches, APs, gateways) with name, model, IP, state, firmware type: filter by usw, uap, ugw, udm, or all
unifi-device-detail Full detail for a single device by MAC address, including port count and uptime mac: device MAC address
unifi-device-ports All ports on a switch with status, speed, PoE, connected MACs, and assigned port profile mac: switch MAC address

Client Tools (3)

Tool Description Key Parameters
unifi-client-list List active clients connected to the network filter: all, wired, or wireless; limit: max results (1-500)
unifi-client-detail Detailed info for a specific client by MAC mac: client MAC address
unifi-client-history All known clients including offline (historical database) limit: max results (1-500)

Port Profile Tools (6 -- 2 read, 4 write)

Tool Description Key Parameters
unifi-port-profiles List all port profiles (bandwidth/VLAN configs) --
unifi-port-profile-detail Full raw detail for a port profile by ID profileId
unifi-port-profile-create Create a new port profile with bandwidth limits name, forward, nativeNetworkId, egressRateKbps, ingressRateKbps, confirm
unifi-port-profile-update Update an existing profile (fetch-then-merge) profileId, + any field to change, confirm
unifi-port-profile-delete Delete a port profile (fails if ports still assigned) profileId, confirm
unifi-port-set-profile Assign a port profile to a specific switch port deviceMac, portIdx, profileId, portName, confirm

All write tools require confirm: true to execute. Set confirm: false for a dry-run preview of what would change.

Network Tools (2)

Tool Description Key Parameters
unifi-network-list List all configured networks (VLANs, corporate, guest) --
unifi-network-detail Full configuration for a specific network networkId

Audit Tools (1)

Tool Description Key Parameters
unifi-bandwidth-audit Per-room bandwidth audit across all switches. Shows port name, bandwidth limits, active status, connected device count. Designed for cross-referencing with billing systems. switchMac (optional), includeUnnamed

Route & Firewall Tools (2)

Tool Description Key Parameters
unifi-traffic-routes List traffic routes/rules with bandwidth shaping data (raw response) --
unifi-firewall-policies List firewall policies from v2 API including traffic rules (raw response) --

Utility Tools (2)

Tool Description Key Parameters
unifi-auth-status Check authentication status, session expiry, and controller connectivity --
unifi-api Generic API escape hatch -- make any UniFi API call not covered by other tools method, path, useAbsolutePath, params, body

Setup

Prerequisites

  • Node.js >= 20.0.0
  • Access to a UniFi controller (cloud-hosted or UDM Pro / UDM Pro Max)
  • TOTP seed from your authenticator app setup (for automated MFA)
  • WireGuard VPN (if targeting a UDM Pro / UDM Pro Max on a private LAN)

VPN Setup (WireGuard)

If your UniFi controller is a UDM Pro / UDM Pro Max on a private network, you need a WireGuard VPN tunnel to reach it. Cloud-hosted controllers are publicly accessible and do not require VPN.

Required routed subnets:

Your WireGuard AllowedIPs must include every subnet the MCP server and your tools need to reach:

Subnet Purpose
UDM management subnet Controller API access (required)
Switch management subnet SSH access for device operations (if switches are on a separate subnet)
Tenant/client subnets Client data and VLAN networks (if querying client tools)

Example WireGuard peer config:

[Peer]
PublicKey = <udm-public-key>
AllowedIPs = <udm-subnet>/24, <switch-subnet>/24, <tenant-supernet>/8
Endpoint = <udm-wan-ip>:51820

Verifying connectivity:

# Check the tunnel routes all required subnets
wg show <tunnel-name> allowed-ips

# Verify controller reachable
ping <your-udm-ip>

# Verify switches reachable (if on a separate management subnet)
ping <switch-ip>

Troubleshooting: devices unreachable but controller responds

The WireGuard Windows app stores tunnel configs internally. Editing the .conf file on disk does not update the running tunnel. If your config file has the correct AllowedIPs but wg show is missing a subnet:

  1. Open the WireGuard app
  2. Remove the tunnel
  3. Import tunnel from file (re-import the updated .conf)
  4. Activate the tunnel

Verify with wg show <tunnel-name> allowed-ips.

Installation

# Clone the repository
git clone <repo-url>
cd mcp-servers/unifi-mcp-server

# Install dependencies
npm install

# Configure environment
cp .env.example .env
# Edit .env with your controller details (see Configuration section)

# Build
npm run build

# Authenticate (first time)
npm run auth           # Interactive mode
npm run auth -- --auto # Non-interactive (requires UNIFI_USERNAME, UNIFI_PASSWORD, UNIFI_TOTP_SEED)

# Start the server
npm run start

Claude Code Configuration

Add the server to your Claude Code MCP settings (~/.claude/settings.json or project-level .mcp.json):

{
  "mcpServers": {
    "unifi": {
      "command": "node",
      "args": ["/path/to/unifi-mcp-server/dist/index.js"],
      "env": {
        "UNIFI_HOST": "your-controller-ip",
        "UNIFI_SITE": "default"
      }
    }
  }
}

The server communicates over stdin/stdout using the MCP StdioServerTransport.


Configuration

All configuration is loaded from .env at the project root via Zod-validated schemas.

Core Settings

Variable Required Default Description
UNIFI_HOST Yes -- Hostname or IP of the UniFi controller
UNIFI_PORT No 443 HTTPS port
UNIFI_SITE No default UniFi site ID (visible in the controller URL)
UNIFI_VERIFY_SSL No false Set true only if the controller has a valid TLS certificate

Authentication

Variable Required Default Description
UNIFI_USERNAME For self-healing -- UniFi SSO or local admin username
UNIFI_PASSWORD For self-healing -- UniFi SSO or local admin password
UNIFI_TOTP_SEED For self-healing -- Base32-encoded TOTP secret from authenticator setup

Session Storage

Variable Required Default Description
TOKEN_CACHE_PATH No ./data/unifi-session.encrypted.json Path to the encrypted session cache file
TOKEN_ENCRYPTION_KEY No -- 64-character hex key for AES-256-GCM encryption. Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))". Falls back to base64 encoding if unset.

Logging

Variable Required Default Description
LOG_LEVEL No info Log verbosity: debug, info, warn, error

Webhook Push (scripts/webhook-push.ts only)

Variable Required Default Description
WEBHOOK_URL For webhook -- Make.com or other webhook URL for monthly bandwidth audit
VPN_TUNNEL_NAME No -- WireGuard tunnel name for automatic VPN connect/disconnect
VPN_GATEWAY No -- IP to ping for VPN health check (e.g., your gateway behind the tunnel)
MAX_RETRIES No 3 Number of retry attempts for webhook push
RETRY_DELAY_MS No 60000 Initial delay between retries in ms (linear backoff: 1x, 2x, 3x)

Authentication

How It Works

UniFi controllers use cookie-based authentication with JWT tokens. The server supports two authentication flows depending on the controller type:

Cloud-hosted controller (two-step MFA):

  1. POST username + password to /api/auth/login -- returns UBIC_2FA cookie
  2. Generate TOTP code from the stored base32 seed (RFC 6238, HMAC-SHA1, 30-second period, 6 digits)
  3. POST username + password + TOTP code with the UBIC_2FA cookie -- returns TOKEN in Set-Cookie
  4. Parse the JWT payload for the csrfToken and exp (expiry) claims
  5. Encrypt and persist the session to disk

UDM Pro / UDM Pro Max (single-step):

  1. POST username + password + TOTP code in a single request -- returns TOKEN in Set-Cookie
  2. Parse and persist as above

Initial Authentication

Run the auth script to establish the first session:

# Interactive -- prompts for username and password
npm run auth

# Non-interactive -- reads credentials from environment
npm run auth -- --auto

The --auto flag is used for scheduled tasks and CI environments. It requires UNIFI_USERNAME, UNIFI_PASSWORD, and UNIFI_TOTP_SEED to be set in .env.

Self-Healing Auth

When UNIFI_USERNAME, UNIFI_PASSWORD, and UNIFI_TOTP_SEED are all present in the environment, the server re-authenticates automatically without any manual intervention:

  • Proactive refresh: When the session has fewer than 15 minutes remaining, a background refresh is triggered (fire-and-forget; the current request continues with the existing session)
  • Expired re-auth: When the session has fully expired, re-auth blocks until complete before the request proceeds
  • 401 retry: If the controller returns 401, the axios interceptor triggers re-auth, refreshes the Cookie and X-CSRF-Token headers, and retries the original request
  • Mutex: A promise-based mutex ensures concurrent requests share a single auth attempt
  • Circuit breaker: After 3 consecutive authentication failures, auth is disabled until the server is restarted (prevents credential lockout loops)

Scripts

webhook-push.ts

Automated monthly bandwidth audit push to a Make.com webhook. Designed to run as a scheduled task on the 1st of each month.

npx tsx scripts/webhook-push.ts

What it does:

  1. Connects WireGuard VPN (if VPN_TUNNEL_NAME is set)
  2. Authenticates to the UniFi controller with automated TOTP
  3. Pulls all switch device data and builds a per-room bandwidth payload
  4. POSTs the payload to the configured WEBHOOK_URL
  5. Disconnects VPN
  6. Retries up to MAX_RETRIES times with linear backoff on failure

initial-auth.ts

Interactive or automated initial login to establish a session cache.

npm run auth           # Interactive
npm run auth -- --auto # Non-interactive

auto-reauth.ts

Non-interactive re-authentication for use in scheduled tasks and CI. Generates TOTP automatically, saves the session to the encrypted cache.

npx tsx scripts/auto-reauth.ts            # re-auth + save session
npx tsx scripts/auto-reauth.ts --quiet    # suppress progress logs
npx tsx scripts/auto-reauth.ts --json     # output token JSON to stdout for script chaining

Development

Commands

Command Description
npm run build Compile TypeScript to dist/
npm run dev Watch mode (tsc --watch)
npm run start Run the compiled server (node dist/index.js)
npm run auth Run the initial auth script (npx tsx scripts/initial-auth.ts)

Project Structure

unifi-mcp-server/
├── src/
│   ├── index.ts                 # Server bootstrap (McpServer + StdioServerTransport)
│   ├── config/
│   │   └── index.ts             # Zod-validated env config from .env
│   ├── auth/
│   │   ├── sessionManager.ts    # Self-healing auth with proactive refresh + mutex
│   │   ├── sessionCache.ts      # AES-256-GCM encrypted session persistence
│   │   └── totp.ts              # RFC 6238 TOTP generator (zero external dependencies)
│   ├── unifi/
│   │   ├── unifiClient.ts       # Axios client with 401/429/5xx retry interceptors
│   │   └── types.ts             # TypeScript interfaces for UniFi API entities
│   ├── tools/
│   │   ├── index.ts             # registerTools() — wires all tool modules
│   │   ├── devices.ts           # 3 tools: device-list, device-detail, device-ports
│   │   ├── clients.ts           # 3 tools: client-list, client-detail, client-history
│   │   ├── ports.ts             # 6 tools: profiles CRUD + port-set-profile
│   │   ├── networks.ts          # 2 tools: network-list, network-detail
│   │   ├── audit.ts             # 1 tool: bandwidth-audit
│   │   ├── routes.ts            # 2 tools: traffic-routes, firewall-policies
│   │   └── utility.ts           # 2 tools: auth-status, generic api escape hatch
│   └── utils/
│       ├── errors.ts            # Error hierarchy: UniFiError → Auth / Api / Config
│       ├── logger.ts            # stderr logger with sensitive key redaction
│       └── formatters.ts        # Entity formatters for clean LLM output
├── scripts/
│   ├── initial-auth.ts          # Interactive/auto auth script
│   ├── auto-reauth.ts           # Non-interactive re-auth for scheduled tasks
│   └── webhook-push.ts          # Monthly bandwidth audit → webhook
├── data/                        # Session cache (gitignored)
├── dist/                        # Compiled output (gitignored)
├── .env                         # Environment variables (gitignored)
├── .env.example                 # Template with all variables documented
├── .gitignore
├── package.json
└── tsconfig.json

Adding a New Tool

  1. Create or edit a file in src/tools/ (group by entity type).

  2. Export a register*Tools(server: McpServer) function:

    import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
    import { z } from 'zod';
    import { unifiClient } from '../unifi/unifiClient.js';
    import { formatErrorForMcp } from '../utils/errors.js';
    
    export function registerMyTools(server: McpServer): void {
      server.tool(
        'unifi-my-tool',
        'Description of what this tool does.',
        {
          param: z.string().describe('What this parameter controls'),
        },
        async ({ param }) => {
          try {
            const data = await unifiClient.get('/rest/endpoint');
            return {
              content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
            };
          } catch (error) {
            return {
              content: [{ type: 'text', text: formatErrorForMcp(error) }],
              isError: true,
            };
          }
        }
      );
    }
    
  3. Wire it into src/tools/index.ts:

    import { registerMyTools } from './mytools.js';
    // ...
    export function registerTools(server: McpServer): void {
      // ... existing registrations
      registerMyTools(server);
    }
    
  4. Build and test: npm run build && npm run start

TypeScript Conventions

  • Target: ES2022 with NodeNext module resolution
  • ESM: "type": "module" in package.json -- all imports must use .js extensions
  • Strict mode: enabled ("strict": true in tsconfig)
  • Output: dist/ with declaration files and source maps

Security

Token Encryption

Session tokens are persisted to disk for survival across server restarts. When TOKEN_ENCRYPTION_KEY is set (64-character hex string = 32 bytes), the session cache is encrypted using AES-256-GCM with:

  • Random 16-byte IV per write
  • GCM authentication tag for tamper detection
  • Format: iv_hex:auth_tag_hex:ciphertext_hex

If the encryption key is not set, sessions fall back to base64 encoding (a warning is logged on every save).

Generate a key:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Credential Handling

  • Credentials (UNIFI_USERNAME, UNIFI_PASSWORD, UNIFI_TOTP_SEED) are read from environment variables only -- never stored in code or committed to version control.
  • The logger automatically redacts any log context key containing token, secret, password, credential, authorization, bearer, apikey, api_key, or cookie.
  • All logs are written to stderr (stdout is reserved for MCP protocol communication).

Self-Signed SSL

UniFi controllers typically use self-signed certificates. By default, UNIFI_VERIFY_SSL=false disables certificate verification via https.Agent({ rejectUnauthorized: false }). Set to true only if your controller has a valid certificate from a trusted CA.


Dependencies

Package Version Purpose
@modelcontextprotocol/sdk ^1.12.0 MCP server framework (McpServer, StdioServerTransport)
axios ^1.7.9 HTTP client with interceptor support for retry logic
dotenv ^16.4.7 Load .env files into process.env
zod ^3.24.1 Runtime schema validation for config and tool inputs

Dev dependencies: typescript ^5.7.2, tsx ^4.19.2, @types/node ^22.10.2


Built by Element Zero

This project is built and maintained by Element Zero -- an AI-driven network automation company specializing in multi-tenant building infrastructure.

We use this MCP server daily to manage commercial building networks with 60+ tenant VLANs, automated bandwidth auditing, and billing integration. It's battle-tested in production.

If you manage UniFi networks for multi-tenant buildings, hotels, or coworking spaces -- we'd love to hear from you. Reach out at phil@ezero.ai.


License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选