environment-setup — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited environment-setup (Rules) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<p align="center"> <img src="assets/unifi-mcp-server-logo.png" alt="UniFi MCP Server logo" width="200" height="200"> </p>
<h1 align="center">UniFi MCP Server</h1>
<p align="center"> <strong>AI-native control of UniFi networks through the Model Context Protocol</strong> </p>
<p align="center">
</p>
An MCP server that exposes UniFi Network, UniFi Protect and the UniFi cloud APIs (Site Manager, Mobility, InnerSpace, Carrier Fabric) as MCP tools, so AI agents can read and change UniFi infrastructure through one standard interface. It runs against one controller or, in fleet mode, many.
Current release: 0.6.4. See CHANGELOG.md for what changed.
343 tools in local mode, from 60 modules.
fleet_* tools that read across controllers. See MULTI_CONTROLLER.md and docs/FLEET_SCALING_PLAN.md.confirm=True and supports dry_run=True, plus read-only and dry-run server modes, role-based access over risk tiers, and a hash-chained audit log (see below)./metrics, /healthz, SIEM export of audit records, optional Redis caching, webhooks with HMAC verification.Set UNIFI_API_TYPE to choose how the server reaches UniFi.
| Mode | What it reaches | Use it for |
|---|---|---|
local (recommended) | Your UniFi console or gateway on the LAN (UNIFI_LOCAL_HOST) | Everything: device and client control, configuration, firewall, Protect |
cloud-ea | UniFi's Early Access cloud API | Sites and aggregate statistics; no per-device control or configuration |
cloud-v1 | UniFi's stable v1 cloud API | Sites and aggregate statistics; no per-device control or configuration |
The cloud tools (Site Manager, Mobility, InnerSpace, Carrier Fabric) call api.ui.com and are registered in every mode. Set UNIFI_SITE_MANAGER_ENABLED=true to use them. In local mode the server registers 343 tools; in either cloud mode, 71.
Zone-based firewall tools need UniFi Network 9.0 or later. Some documented UniFi endpoints do not exist on every firmware version; see docs/UNIFI_API.md.
pip install unifi-mcp-server # or: uv tool install unifi-mcp-server
# Fleet mode extras (Postgres, Redis):
pip install 'unifi-mcp-server[fleet]'Or use the container image (amd64, arm64 and arm/v7; the -fleet variant for amd64 and arm64):
docker pull ghcr.io/enuno/unifi-mcp-server:latestClaude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows), Cursor (mcp.json, from View: Open MCP Settings) and most other MCP clients take the same mcpServers block:
{
"mcpServers": {
"unifi": {
"command": "uvx",
"args": ["unifi-mcp-server"],
"env": {
"UNIFI_API_KEY": "your-api-key-here",
"UNIFI_API_TYPE": "local",
"UNIFI_LOCAL_HOST": "192.168.2.1"
}
}
}
}If you installed with pip, use "command": "unifi-mcp-server" and drop args. To run the container instead:
{
"mcpServers": {
"unifi": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "UNIFI_API_KEY=your-api-key-here",
"-e", "UNIFI_API_TYPE=local",
"-e", "UNIFI_LOCAL_HOST=192.168.2.1",
"ghcr.io/enuno/unifi-mcp-server:latest"
]
}
}
}Keep -i and do not add -d: the client talks to the server over the container's stdin and stdout.
| Variable | Purpose | Default |
|---|---|---|
UNIFI_API_KEY | UniFi API key (required) | — |
UNIFI_API_TYPE | local, cloud-ea or cloud-v1 | cloud-ea |
UNIFI_LOCAL_HOST / UNIFI_LOCAL_PORT | Console address in local mode | — / 443 |
UNIFI_LOCAL_VERIFY_SSL | Verify the console's TLS certificate. false logs a warning at startup | true |
UNIFI_LOCAL_CA_FILE | CA certificate (PEM) for a self-signed console, instead of turning verification off | — |
UNIFI_DEFAULT_SITE | Site used when a tool call names none | default |
UNIFI_SITE_MANAGER_ENABLED | Enable the cloud tools (Site Manager, Mobility, InnerSpace, Carrier) | false |
UNIFI_PROFILE | Register only one group of tools (profiles) | all |
UNIFI_READ_ONLY / UNIFI_DRY_RUN | Read-only or preview-only server | false |
DEBUG | Registers debug_api_request (raw GET/DELETE, destructive tier, removed by read-only). Leave unset in production | unset |
MCP_SERVER_TRANSPORT | stdio, streamable_http, http or sse | stdio |
MCP_AUTH_TOKEN | Bearer token, required on network transports; viewer:<token> (or operator:, admin:) limits a token's role | — |
REDIS_URL | Optional response cache | — |
WEBHOOK_SECRET | HMAC secret for incoming UniFi webhooks | — |
DATABASE_URL | Turns on fleet mode (Postgres) | — |
.env.example lists every setting with comments, including audit logging, SIEM export, metrics, Supermemory and agnost.ai.
The skills/ directory holds agent skills: Markdown files an AI agent loads on demand, so it knows which UniFi tools exist and how to use them safely without keeping every tool definition in context. Each skill is a folder with a SKILL.md, in the layout Claude Code and other agents install.
Using the server (operator skills)
| Skill | Covers |
|---|---|
unifi-network | Clients, networks and VLANs, WiFi, DHCP, DNS, WAN, vouchers |
unifi-devices | Inventory, adoption, restarts and upgrades, ports, switching, topology |
unifi-security | Firewall rules and groups, zone-based firewall, ACLs, port forwarding, VPN |
unifi-system | Sites, backups, QoS, traffic flows, DPI, RADIUS, guest portal |
unifi-channel-planning | Low-interference WiFi channel plans from neighbor scans |
Changing this codebase (developer skills)
| Skill | Covers |
|---|---|
unifi-mcp-tool-builder | Adding any MCP tool: model, function, registration, tests, docs |
unifi-network-config-tools | Network configuration tools: URL spaces, site IDs, read-modify-write |
unifi-security-tools | Firewall, ZBF, ACL and port forward tools, and their risk tiers |
unifi-protect-tools | The protect_* modules and the Protect client |
unifi-cloud-fleet-tools | Cloud API tools and the fleet stack |
Claude Code loads skills from ~/.claude/skills/<name>/SKILL.md (every session) or <project>/.claude/skills/<name>/SKILL.md (one project). Copy the folders you want:
git clone https://github.com/enuno/unifi-mcp-server.git
cd unifi-mcp-server
mkdir -p ~/.claude/skills
# All operator skills
cp -r skills/unifi-network skills/unifi-devices skills/unifi-security \
skills/unifi-system skills/unifi-channel-planning ~/.claude/skills/
# Or one skill
cp -r skills/unifi-security ~/.claude/skills/
# The one-file overview of the whole server, as a skill named "unifi"
mkdir -p ~/.claude/skills/unifi && cp SKILL.md ~/.claude/skills/unifi/SKILL.mdOther agents that read the same SKILL.md format take the same folders; copy them into that agent's skills directory (Codex, for example, reads .agents/skills/). To update, pull and copy again. Inside this repository the developer skills are already installed for Claude Code (.claude/skills/) and Codex (.agents/skills/).
You don't invoke a skill yourself. The agent reads each skill's description and loads the one that matches your request, then calls the MCP tools it describes, so the MCP server must also be configured in the same client. For example:
unifi-network.unifi-security.unifi-channel-planning.If the agent doesn't pick a skill up, name it ("use the unifi-security skill"). Pair a skill with the matching UNIFI_PROFILE to keep the tool list small too. docs/SKILLS.md has the full guide.
Profiles. UNIFI_PROFILE registers only one group of modules, so the client sees fewer tool definitions:
| Profile | Tools | Covers |
|---|---|---|
network | 48 | Clients, networks, WiFi, DHCP, DNS, WAN, vouchers, channel planning |
devices | 53 | Devices, control, migration, ports, switching, topology, diagnostics |
security | 47 | Firewall, ZBF, ACLs, port forwarding, VPN, content filtering |
system | 182 | Sites, backups, events, DPI, QoS, RADIUS, traffic flows, Protect, cloud |
protect | 75 | The Protect modules |
mobility / innerspace / carrier | 12 / 10 / 15 | One cloud API each |
minimal | 19 | Sites, clients, devices |
Counts include the four fleet tools every profile gets. An unknown profile logs a warning and loads everything.
Safety controls.
confirm=True, and dry_run=True returns the change it would make without making it.UNIFI_READ_ONLY=true leaves mutating tools out of the tool list entirely. UNIFI_DRY_RUN=true forces every mutating call into preview mode.DEBUG=true adds debug_api_request, a raw GET or DELETE to any controller endpoint. It is a destructive-tier tool, a DELETE needs confirm=True, and read-only mode removes it. Leave DEBUG unset in production.read, write, destructive) and each role a set of tiers: viewer reads, operator writes, and admin can also run destructive tools, including deletes, restores, restarts, client blocking and firewall policy changes. See API.md.stdio is the default and needs no port. To serve MCP over the network, use Streamable HTTP:
export MCP_SERVER_TRANSPORT=streamable_http
export MCP_SERVER_PORT=3000
export MCP_AUTH_TOKEN=$(openssl rand -hex 32) # required on every network transport
unifi-mcp-server
# Listening on 127.0.0.1:3000; clients send Authorization: Bearer $MCP_AUTH_TOKENClients and MCP gateways then connect to http://<host>:3000/mcp. The server binds to 127.0.0.1 unless you set MCP_SERVER_HOST; put an authenticating TLS proxy in front before exposing it further. http also works. sse is deprecated: client proxies such as mcp-remote can race its initialize handshake (#96).
Container, with the published port on loopback:
services:
unifi-mcp:
image: ghcr.io/enuno/unifi-mcp-server:latest
environment:
UNIFI_API_KEY: your-api-key
UNIFI_API_TYPE: local
UNIFI_LOCAL_HOST: 192.168.2.1
MCP_SERVER_TRANSPORT: streamable_http
MCP_SERVER_PORT: 3000
MCP_SERVER_HOST: 0.0.0.0 # inside the container only
MCP_AUTH_TOKEN: ${MCP_AUTH_TOKEN}
ports:
- "127.0.0.1:3000:3000"The repository's docker-compose.yml adds Redis and the MCP Toolbox dashboard (MCP_TOOLBOX.md); copy .env.docker.example to .env and run make compose-up. That example starts read-only (UNIFI_READ_ONLY=true) with a viewer stdio caller (UNIFI_STDIO_ROLE=viewer); to allow changes, set UNIFI_READ_ONLY=false and raise UNIFI_STDIO_ROLE to operator, or admin for destructive changes.
Any MCP client library works. With the FastMCP client:
import asyncio
from fastmcp import Client
config = {
"mcpServers": {
"unifi": {
"command": "unifi-mcp-server",
"env": {
"UNIFI_API_KEY": "your-api-key-here",
"UNIFI_API_TYPE": "local",
"UNIFI_LOCAL_HOST": "192.168.2.1",
},
}
}
}
async def main() -> None:
async with Client(config) as client:
sites = await client.call_tool("list_sites", {})
print(sites.data)
clients = await client.call_tool("list_active_clients", {"site_id": "default"})
print(clients.data)
# Mutations need confirm=True; dry_run=True previews the change.
preview = await client.call_tool(
"create_firewall_zone",
{"site_id": "default", "name": "IoT", "confirm": True, "dry_run": True},
)
print(preview.data)
asyncio.run(main())bin/unifi-cli runs a single tool from a shell (unifi-cli list-clients --site default); see docs/SKILLS.md.
| Document | Contents |
|---|---|
| API.md | Every MCP tool and resource, with parameters and examples |
| docs/SKILLS.md | Agent skills, profiles and the CLI wrapper |
| docs/UNIFI_API.md | The UniFi endpoints behind the tools |
| MULTI_CONTROLLER.md | Fleet mode: controllers, tokens and roles |
| METRICS.md, WEBHOOK_SETUP.md, A2A.md | Metrics, webhooks, the A2A agent endpoints |
| NETWORK_PLAYBOOK.md, HARBOR_SETUP.md | Operating runbooks |
| SECURITY.md | Reporting vulnerabilities, audit logging and hardening |
| SPEC.md, DEVELOPMENT_PLAN.md, ROADMAP.md | Architecture target and roadmap |
| CHANGELOG.md, docs/RELEASE_PROCESS.md | Release history and how releases are cut and published |
git clone https://github.com/enuno/unifi-mcp-server.git
cd unifi-mcp-server
make install # uv sync from uv.lock with the dev extra (no activation needed)
make hooks # pre-commit and commit-msg hooks
cp .env.example .env # then set UNIFI_API_KEY and, for local mode, UNIFI_LOCAL_HOST
make test # unit tests
make ci # every blocking CI check: lint, typecheck, security, docs coverage, tests with the 80% gate
make inspect # open the server in the MCP Inspector (needs Node.js)
make help # list every targetWithout make, the same commands run through uv run --locked, for example uv run --locked pytest tests/unit/ -m "not integration". Integration tests (-m integration) need real UniFi hardware.
Layout: src/main.py builds the server, src/tools/ holds the tool modules, src/api/ the UniFi clients, src/models/ the Pydantic models, src/fleet/ the fleet stack, and tests/unit/ the unit tests. AGENTS.md and CLAUDE.md describe the conventions in detail, and commands.md lists the development commands.
Contributions from people and AI coding agents are welcome. See CONTRIBUTING.md and AGENTS.md.
make ci.feat: ..., fix: ...) and open a pull request.Issues with [Bug] in the title opened by a maintainer or collaborator get an automated first analysis; other reports are triaged by hand (details).
Report vulnerabilities as described in SECURITY.md. Never commit credentials.
Apache License 2.0. See LICENSE.
io.github.enuno/unifi-mcp-server at <https://registry.modelcontextprotocol.io>~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.