Skip to main content
Glama
nathan-bw

UniFi MCP Server

by nathan-bw
README.md
# UniFi MCP Server

A [Model Context Protocol](https://modelcontextprotocol.io/) server for managing UniFi networks through Claude Desktop or other MCP clients.

## Features

- **18 MCP Tools** - Comprehensive network management capabilities
- **OAuth 2.1 + PKCE** - Secure authentication with Cloudflare Access
- **API Key Authentication** - Uses official UniFi API with X-API-KEY
- **MCP 2025-11-25 Compliant** - Full specification compliance
- **Remote Ready** - Designed for access via Cloudflare Tunnel

## Quick Start

### 1. Generate UniFi API Key

In your UniFi Controller/UDM:
- Go to **Settings → Control Plane → Integrations**
- Click **Generate API Key**
- Copy the key

### 2. Configure Environment

```bash
cp .env.example .env
```

Edit `.env`:
```bash
# Server
BASE_URL=https://your-domain.com

# Cloudflare Access for SaaS (OAuth identity provider)
CF_ACCESS_TEAM=your-team-name
CF_CLIENT_ID=your-client-id
CF_CLIENT_SECRET=your-client-secret

# UniFi Controller
UNIFI_HOST=192.168.1.1
UNIFI_API_KEY=your-api-key-from-step-1
```

### 3. Start with Docker

```bash
docker compose up -d
```

### 4. Configure Cloudflare

1. Create a **Cloudflare Tunnel** pointing to your server
2. Create an **Access for SaaS** application in Zero Trust:
   - Protocol: OIDC
   - Redirect URL: `https://your-domain.com/callback`
3. Connect with Claude Desktop using your tunnel URL

## Available Tools

### Client Management
| Tool | Description |
|------|-------------|
| `list_clients` | List all connected devices |
| `get_client` | Get details for a specific client by MAC |
| `search_devices` | Search by name, IP, or MAC |
| `block_client` | Block a device from the network |
| `unblock_client` | Unblock a device |
| `reconnect_client` | Force a client to reconnect |
| `list_blocked_clients` | List blocked devices |

### Device Management
| Tool | Description |
|------|-------------|
| `list_devices` | List all UniFi devices (APs, switches, gateways) |
| `list_access_points` | List access points with status |
| `restart_device` | Restart an AP or switch |

### Network Configuration
| Tool | Description |
|------|-------------|
| `list_networks` | List VLANs and subnets |
| `list_wlans` | List wireless SSIDs |
| `list_port_forwards` | List port forwarding rules |

### Monitoring
| Tool | Description |
|------|-------------|
| `get_network_health` | Network health statistics |
| `list_events` | Recent network events |
| `list_alarms` | Active and recent alarms |

## Architecture

```
Claude Desktop
      ↓
Cloudflare Tunnel (secure tunnel)
      ↓
UniFi MCP Server (OAuth 2.1 + MCP)
      ↓
UniFi Controller/UDM (X-API-KEY)
```

## Authentication Flow

This server implements OAuth 2.1 with Cloudflare Access as the identity provider:

1. MCP client discovers OAuth endpoints via `/.well-known/oauth-authorization-server`
2. Client initiates OAuth flow to `/authorize` with PKCE
3. User authenticates via Cloudflare Access (supports Entra ID, Google, etc.)
4. Upon approval, client exchanges code for tokens at `/token`
5. Client accesses `/mcp` with Bearer token

### OAuth Endpoints

| Endpoint | Description |
|----------|-------------|
| `/.well-known/oauth-authorization-server` | Authorization server metadata |
| `/.well-known/oauth-protected-resource/mcp` | Protected resource metadata (RFC 9728) |
| `/authorize` | Authorization endpoint (auto-registers clients) |
| `/token` | Token endpoint |
| `/register` | Dynamic client registration |
| `/callback` | Cloudflare OAuth callback |

## Configuration

| Variable | Required | Description |
|----------|----------|-------------|
| `PORT` | No | Server port (default: 3000) |
| `BASE_URL` | Yes | Public URL for OAuth redirects |
| `CF_ACCESS_TEAM` | Yes | Cloudflare Access team name |
| `CF_CLIENT_ID` | Yes | From Access for SaaS app |
| `CF_CLIENT_SECRET` | Yes | From Access for SaaS app |
| `UNIFI_HOST` | Yes | UniFi controller IP |
| `UNIFI_PORT` | No | Controller port (default: 443) |
| `UNIFI_API_KEY` | Yes | API key from UniFi |
| `UNIFI_SITE` | No | Site name (default: "default") |

## Security

- **OAuth 2.1 + PKCE** - Secure token exchange
- **Cloudflare Tunnel** - No direct IP exposure
- **Cloudflare Access** - Identity verification at the edge
- **API Key Auth** - No passwords stored, scoped access

### Recommended WAF Rules

Consider blocking non-essential paths:
- Allow: `/.well-known/*`, `/register`, `/authorize`, `/callback`, `/token`, `/mcp`
- Block or protect: `/`, `/health`

## Tech Stack

- Node.js 22 with ES Modules
- [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk)
- Express.js
- Docker with Alpine Linux

## Development

```bash
# Install dependencies
npm install

# Run with hot-reload
npm run dev

# Check syntax
node --check server.js
```

## License

MIT