# Unifi Network Mcp

> Extended UniFi Network MCP server with 125 tools (44 new v1/v2/system endpoints). Forked from sirkirby/unifi-network-mcp.

- **Type:** MCP server
- **Install:** `agentstack add mcp-rodaddy-unifi-network-mcp`
- **Verified:** Pending review
- **Seller:** [rodaddy](https://agentstack.voostack.com/s/rodaddy)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [rodaddy](https://github.com/rodaddy)
- **Source:** https://github.com/rodaddy/unifi-network-mcp

## Install

```sh
agentstack add mcp-rodaddy-unifi-network-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 📡 UniFi Network MCP Server

[![License][license-shield]](LICENSE)
![Project Maintenance][maintenance-shield]
[![GitHub Activity][commits-shield]][commits]

[![GitHub Release][release-shield]][releases]
[![issues][issues-shield]][issues-link]
[![test-badge]][test-workflow]
[![validate-badge]][validate-workflow]
[![validate-docker-badge]][validate-docker-workflow]

[](https://www.buymeacoffee.com/sirkirby)

A self-hosted [Model Context Protocol](https://github.com/modelcontextprotocol) (MCP) server that turns your UniFi Network Controller into a rich set of interactive tools. Every capability is exposed via standard MCP **tools** prefixed with `unifi_`, so any LLM or agent that speaks MCP (e.g. Claude Desktop, `mcp-cli`, LangChain, etc.) can query, analyze **and** – when explicitly authorized – modify your network. These tools must have local access to your UniFi Network Controller, by either running locally or in the cloud connected via a secure reverse proxy. Please consider the [security implications](#security-considerations) of running these tools in the cloud as they contain sensitive information and access to your network.

---

## Table of Contents

* [Features](#features)
* [Quick Start](#quick-start)
  * [Docker](#docker)
  * [Python / UV](#python--uv)
  * [Install from PyPI](#install-from-pypi)
* [Using with Local LLMs and Agents](#using-with-local-llms-and-agents)
* [Using with Claude Desktop](#using-with-claude-desktop)
* [Code Execution Mode](#code-execution-mode)
  * [Overview](#overview)
  * [Context Optimization](#context-optimization)
  * [Tool Index](#tool-index)
  * [Tool Execution](#tool-execution)
* [Runtime Configuration](#runtime-configuration)
* [Diagnostics (Advanced Logging)](#diagnostics-advanced-logging)
* [Developer Console (Local Tool Tester)](#developer-console-local-tool-tester)
* [Security Considerations](#security-considerations)
* [📚 Tool Catalog](#-tool-catalog)
* [📖 Documentation](#-documentation)
* [Testing](#testing)
* [Local Development](#local-development)
* [Contributing: Releasing / Publishing](#contributing-releasing--publishing)

---

## Features

* Full catalog of UniFi controller operations – firewall, traffic-routes, port-forwards, QoS, VPN, WLANs, stats, devices, clients **and more**.
* All mutating tools require `confirm=true` so nothing can change your network by accident.
* **Workflow automation friendly** – set `UNIFI_AUTO_CONFIRM=true` to skip confirmation prompts (ideal for n8n, Make, Zapier).
* Works over **stdio** (FastMCP). Optional SSE HTTP endpoint can be enabled via config.
* **Code execution mode** with tool index, async operations, and TypeScript examples.
* One-liner launch via the console-script **`unifi-network-mcp`**.
* Idiomatic Python ≥ 3.13, packaged with **pyproject.toml** and ready for PyPI.

---

## Quick Start

### Docker

```bash
# 1. Retrieve the latest image (published from CI)
docker pull ghcr.io/sirkirby/unifi-network-mcp:latest

# 2. Run – supply UniFi credentials via env-vars or a mounted .env file
# Ensure all UNIFI_* variables are set as needed (see Runtime Configuration table)
docker run -i --rm \
  -e UNIFI_HOST=192.168.1.1 \
  -e UNIFI_USERNAME=admin \
  -e UNIFI_PASSWORD=secret \
  -e UNIFI_PORT=443 \
  -e UNIFI_SITE=default \
  -e UNIFI_VERIFY_SSL=false \
  ghcr.io/sirkirby/unifi-network-mcp:latest
  # Optional: Set controller type (auto-detected if omitted)
  # -e UNIFI_CONTROLLER_TYPE=auto \
```

### Python / UV

```bash
# Install UV (modern pip/venv manager) if you don't already have it
curl -fsSL https://astral.sh/uv/install.sh | bash

# 1. Clone & create a virtual-env
git clone https://github.com/sirkirby/unifi-network-mcp.git
cd unifi-network-mcp
uv venv
source .venv/bin/activate

# 2. Install in editable mode (develop-install)
uv pip install --no-deps -e .

# 3. Provide credentials (either export vars or create .env)
# The server will auto-detect your controller type (UniFi OS vs standard)
# Use UNIFI_CONTROLLER_TYPE to manually override if needed
cp .env.example .env  # then edit values

# 4. Launch
unifi-network-mcp
```

### Install from PyPI

*(when published)*

```bash
uv pip install unifi-network-mcp  # or: pip install unifi-network-mcp
```

The `unifi-network-mcp` entry-point will be added to your `$PATH`.

---

## Using with Local LLMs and Agents

No internet access is required, everything runs locally. It's recommend you have an M-Series Mac or Windows/Linux with a very modern GPU (Nvidia RTX 4000 series or better)

### Recommended

Install [LM Studio](https://lmstudio.ai) and edit the mcp.json file `chat prompt --> tool icon --> edit mcp.json` to add the unifi-network-mcp server tools, allowing you to prompt using a locally run LLM of your choice. Configure just as you would for Claude desktop. I recommend loading a tool capable model like OpenAI's [gp-oss](https://lmstudio.ai/models/openai/gpt-oss-20b), and prompt it to use the UniFi tools.

```text
Example prompt: using the unifi tools, list my most active clients on the network and include the type of traffic and total bandwidth used.
```

### Alternative

Use [Ollama](https://ollama.com/) with [ollmcp](https://github.com/jonigl/mcp-client-for-ollama), allowing you to use a locally run LLM capable of tool calling via your favorite [terminal](https://app.warp.dev/referral/EJK58L).

---

## Code Execution Mode

The UniFi Network MCP server supports **code-execution mode**, enabling agents to write code that interacts with tools programmatically. This approach reduces token usage by up to 98% compared to traditional tool calls, as agents can filter and transform data in code before presenting results.

### Overview

Code execution mode consists of three key components:

1. **Tool Index** - Machine-readable catalog of all available tools with JSON schemas
2. **Async Operations** - Background job execution for long-running operations
3. **Reference Implementations** - Example clients showing code-execution patterns

This implementation follows the patterns described in [Anthropic's Code Execution with MCP article](https://www.anthropic.com/engineering/code-execution-with-mcp).

### 🚀 Context Optimization (New in v0.2.0)

The server now supports **lazy tool registration** to dramatically reduce LLM context usage.

**🎯 DEFAULT: Lazy Mode (lazy)** ⭐⭐⭐ **Active in v0.2.0!**
- Registers only 3 meta-tools initially
- ~200 tokens consumed (96% reduction!)
- Tools loaded automatically on first use
- **Seamless UX** - no manual discovery needed
- **Best of both worlds!**
- **Active by default** - no configuration needed

**Eager Mode (eager):**
- Registers all 67 tools immediately
- ~5,000 tokens consumed for tool schemas
- All tools visible in context from start
- **Best for:** Dev console, automation scripts
- **How to enable:** Set `UNIFI_TOOL_REGISTRATION_MODE=eager`

**Meta-Only Mode (meta_only):**
- Registers only 3 meta-tools initially
- ~200 tokens consumed (96% reduction!)
- Requires `unifi_tool_index` call for discovery
- **Best for:** Maximum control
- **How to enable:** Set `UNIFI_TOOL_REGISTRATION_MODE=meta_only`

**Upgrading from v0.1.x?**

If you're upgrading and want to restore the previous behavior (all tools registered immediately), add this to your config:

```json
{
  "mcpServers": {
    "unifi": {
      "command": "uv",
      "args": ["--directory", "/path/to/unifi-network-mcp", "run", "python", "-m", "src.main"],
      "env": {
        "UNIFI_HOST": "192.168.1.1",
        "UNIFI_USERNAME": "admin",
        "UNIFI_PASSWORD": "password",
        "UNIFI_TOOL_REGISTRATION_MODE": "eager"
      }
    }
  }
}
```

**Default behavior (lazy mode - recommended):**

```json
{
  "mcpServers": {
    "unifi": {
      "command": "uv",
      "args": ["--directory", "/path/to/unifi-network-mcp", "run", "python", "-m", "src.main"],
      "env": {
        "UNIFI_HOST": "192.168.1.1",
        "UNIFI_USERNAME": "admin",
        "UNIFI_PASSWORD": "password"
        // UNIFI_TOOL_REGISTRATION_MODE defaults to "lazy" - no need to set!
      }
    }
  }
}
```

**Result:** Claude starts with minimal context, tools load transparently when called - 96% token savings with zero UX compromise!

### Tool Index

The server exposes a special `unifi_tool_index` tool that returns a complete list of all registered tools with their schemas:

```json
{
  "name": "unifi_tool_index",
  "arguments": {}
}
```

**Response:**
```json
{
  "tools": [
    {
      "name": "unifi_list_clients",
      "schema": {
        "name": "unifi_list_clients",
        "description": "List all network clients",
        "input_schema": {
          "type": "object",
          "properties": {
            "filter": {"type": "string"},
            "limit": {"type": "integer"}
          }
        }
      }
    },
    ...
  ]
}
```

**Use Cases:**
- Programmatic tool discovery
- Wrapper/SDK generation
- Dynamic client configuration
- IDE autocomplete support

### Tool Execution

The server provides two execution modes for discovered tools:

**Single Tool Execution (synchronous):**
```json
{
  "name": "unifi_execute",
  "arguments": {
    "tool": "unifi_list_clients",
    "arguments": {}
  }
}
```

**Batch Execution (parallel, async):**

For bulk operations or long-running tasks, use batch mode:

```json
{
  "name": "unifi_batch",
  "arguments": {
    "operations": [
      {"tool": "unifi_get_client_details", "arguments": {"mac": "aa:bb:cc:dd:ee:ff"}},
      {"tool": "unifi_get_client_details", "arguments": {"mac": "11:22:33:44:55:66"}}
    ]
  }
}
```

**Response:**
```json
{
  "jobs": [
    {"index": 0, "tool": "unifi_get_client_details", "jobId": "af33b233cbdc860c"},
    {"index": 1, "tool": "unifi_get_client_details", "jobId": "bf44c344dcde971d"}
  ],
  "message": "Started 2 operation(s). Use unifi_batch_status to check progress."
}
```

**Check batch status:**
```json
{
  "name": "unifi_batch_status",
  "arguments": {
    "jobIds": ["af33b233cbdc860c", "bf44c344dcde971d"]
  }
}
```

**Response:**
```json
{
  "jobs": [
    {"jobId": "af33b233cbdc860c", "status": "done", "result": {...}},
    {"jobId": "bf44c344dcde971d", "status": "done", "result": {...}}
  ]
}
```

**Notes:**
- Use `unifi_execute` for single operations (returns result directly)
- Use `unifi_batch` + `unifi_batch_status` for parallel/bulk operations
- Jobs are stored in-memory only (no persistence)
- Job IDs are unique per server session

### Using with Claude Desktop

Claude Desktop has built-in code execution that automatically uses the tool index:

```
You: "Show me the top 10 wireless clients by traffic, excluding guest networks"
```

Claude will:
1. Query `unifi_tool_index` to discover tools
2. Call `unifi_list_clients` to fetch data
3. Write and execute code to filter/sort in its sandbox
4. Show you only the final top 10 results

**Token savings:** Instead of processing 500+ clients in context, Claude processes them in code and shows only the summary.

See [`examples/CLAUDE_DESKTOP.md`](examples/CLAUDE_DESKTOP.md) for detailed usage guide.

### Python Client Examples

Practical examples showing programmatic usage:

```python
from mcp import ClientSession, stdio_client

# Discover tools
tools = await session.call_tool("unifi_tool_index", {})

# Execute a single tool (returns result directly)
result = await session.call_tool("unifi_execute", {
    "tool": "unifi_list_clients",
    "arguments": {}
})

# Batch execution for parallel operations
batch = await session.call_tool("unifi_batch", {
    "operations": [
        {"tool": "unifi_get_client_details", "arguments": {"mac": "..."}},
        {"tool": "unifi_get_device_details", "arguments": {"mac": "..."}}
    ]
})

# Check batch status
status = await session.call_tool("unifi_batch_status", {
    "jobIds": [j["jobId"] for j in batch["jobs"]]
})
```

**Three complete examples:**
- `query_tool_index.py` - Discover available tools
- `use_async_jobs.py` - Batch operations and status checking
- `programmatic_client.py` - Build custom Python clients

See [`examples/python/README.md`](examples/python/README.md) for complete examples.

### MCP Identity

The server advertises its capabilities via an MCP identity file at [`.well-known/mcp-server.json`](.well-known/mcp-server.json):

```json
{
  "name": "unifi-network-mcp",
  "version": "0.2.0",
  "transports": ["stdio", "http+sse"],
  "capabilities": {
    "tools": true,
    "tool_index": true,
    "batch_operations": true
  },
  "features": {
    "tool_index": {
      "tool": "unifi_tool_index"
    },
    "execution": {
      "tool": "unifi_execute"
    },
    "batch_operations": {
      "start_tool": "unifi_batch",
      "status_tool": "unifi_batch_status"
    }
  }
}
```

This enables:
- Programmatic capability discovery
- Future MCP registry integration
- Client auto-configuration

---

## Using with Claude Desktop

Add (or update) the `unifi-network-mcp` block under `mcpServers` in your `claude_desktop_config.json`.

### Option 1 – Claude invokes the local package

```jsonc
"unifi-network-mcp": {
  "command": "/path/to/your/.local/bin/uvx",
  "args": ["--quiet", "unifi-network-mcp"], // Or "unifi-network-mcp=="
  "env": {
    "UNIFI_HOST": "192.168.1.1",
    "UNIFI_USERNAME": "admin",
    "UNIFI_PASSWORD": "secret",
    "UNIFI_PORT": "443",
    "UNIFI_SITE": "default",
    "UNIFI_VERIFY_SSL": "false"
    // Optional: "UNIFI_CONTROLLER_TYPE": "auto"
  }
}
```

* `uvx` handles installing/running the package in its own environment.
* The `--quiet` flag is recommended if `uvx` outputs non-JSON messages.
* If you want to pin to a specific version, use `"unifi-network-mcp=="` as the package name.
* If your script name in `pyproject.toml` differs from the package name, use `["--quiet", "", ""]`.

### Option 2 – Claude starts a Docker container

```jsonc
"unifi-network-mcp": {
  "command": "docker",
  "args": [
    "run", "--rm", "-i",
    "-e", "UNIFI_HOST=192.168.1.1",
    "-e", "UNIFI_USERNAME=admin",
    "-e", "UNIFI_PASSWORD=secret",
    "-e", "UNIFI_PORT=443",
    "-e", "UNIFI_SITE=default",
    "-e", "UNIFI_VERIFY_SSL=false",
    // Optional: "-e", "UNIFI_CONTROLLER_TYPE=auto",
    "ghcr.io/sirkirby/unifi-network-mcp:latest"
  ]
}
```

### Option 3 – Claude attaches to an existing Docker container (recommended for compose)

1) Using the container name as specified in `docker-compose.yml` from the repository root:

```yaml
docker-compose up --build
```

2) Then configure Claude Desktop:

```jsonc
"unifi-network-mcp": {
  "command": "docker",
  "args": ["exec", "-i", "unifi-network-mcp", "unifi-network-mcp"]
}
```

Notes:

* Use `-T` only with `docker compose exec` (it disables TTY for clean JSON). Do not use `-T` with `docker exec`.
* Ensure the compose service is running (`docker compose up -d`) before attaching.

After editing the config **restart Claude Desktop**, then test with:

```text
@unifi-network-mcp list tools
```

### Optional HTTP SSE endpoint (off by default)

For environments where HTTP is acceptable (e.g., local development), you can enable the HTTP SSE server and expose it explicitly:

```bash
docker run -i --rm \
  -p 3000:3000 \
  -e UNIFI_MCP_HTTP_ENABLED=true \
  ...
  ghcr.io/sirkirby/unifi-network-mcp:latest
```

Security note: Leave this disabled in production or sensitive environments. The stdio transport remains the default and recommended mode.

---

## Runtime Configuration

The server merges settings from **environment variables**, an optional `.env` file, and `src/config/config.yaml` (listed in order of precedence).

### Essential variables

| Variable | Description |
|----------|-------------|
| `CONFIG_PATH` | Full path to a custom config YAML file. If not set, checks CWD for `config/config.yaml`, then falls back to the bundled default (`src/config/config.yaml`). |
| `UNIFI_HOST` | IP / hostname of the controller |
| `UNIFI_USERNAME` | Local UniFi admin |
| `UNIFI_PASSWORD` | Admin password |
| `UNIFI_PORT` | HTTPS port (default `443`) |
| `UNIFI_SITE` | Site name (default `default`) |
| `UNIF

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [rodaddy](https://github.com/rodaddy)
- **Source:** [rodaddy/unifi-network-mcp](https://github.com/rodaddy/unifi-network-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-rodaddy-unifi-network-mcp
- Seller: https://agentstack.voostack.com/s/rodaddy
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
