{
  "markdown": "# go-unifi-mcp\n\nA Model Context Protocol (MCP) server for UniFi Network Controller, written in\nGo.\n\n## Overview\n\n`go-unifi-mcp` provides an MCP interface to UniFi Network Controller, enabling\nAI assistants and other MCP clients to interact with your UniFi infrastructure.\n\n### Why this exists\n\nI couldn’t find an MCP server that supported both v1 and v2 firewall rules and\nIPv6, so I built one. This wraps the go-unifi library (which I trust from my\nTerraform provider experience) and leans on its generated API surface. The\nserver is generated from the controller’s own API definitions, which makes it\nmuch easier to keep tool coverage up to date as UniFi evolves.\n\n### UniFi controller versioning\n\nThis project generates tools against the same UniFi Controller version pinned by\ngo-unifi. When go-unifi updates its supported controller version, we regenerate\nour field definitions and tool metadata to match. We support the same controller\nrange; see their\n[controller support range](https://github.com/filipowm/go-unifi/tree/main?tab=readme-ov-file#supported-unifi-controller-versions).\n\n## Installation\n\n### Binary (GitHub Releases)\n\nDownload pre-built binaries from the\n[Releases page](https://github.com/claytono/go-unifi-mcp/releases). Binaries are\navailable for macOS and Linux (amd64/arm64).\n\n```bash\n# macOS (Apple Silicon)\ncurl -L https://github.com/claytono/go-unifi-mcp/releases/latest/download/go-unifi-mcp_darwin_arm64.tar.gz | tar xz\nsudo mv go-unifi-mcp /usr/local/bin/\n\n# macOS (Intel)\ncurl -L https://github.com/claytono/go-unifi-mcp/releases/latest/download/go-unifi-mcp_darwin_amd64.tar.gz | tar xz\nsudo mv go-unifi-mcp /usr/local/bin/\n\n# Linux (amd64)\ncurl -L https://github.com/claytono/go-unifi-mcp/releases/latest/download/go-unifi-mcp_linux_amd64.tar.gz | tar xz\nsudo mv go-unifi-mcp /usr/local/bin/\n\n# Linux (arm64)\ncurl -L https://github.com/claytono/go-unifi-mcp/releases/latest/download/go-unifi-mcp_linux_arm64.tar.gz | tar xz\nsudo mv go-unifi-mcp /usr/local/bin/\n```\n\n### Homebrew\n\nAvailable from the\n[claytono/homebrew-tap](https://github.com/claytono/homebrew-tap) tap:\n\n```bash\nbrew install claytono/tap/go-unifi-mcp\n```\n\n### Nix\n\n```bash\n# Run without installing\nnix run github:claytono/go-unifi-mcp\n\n# Install to your profile\nnix profile install github:claytono/go-unifi-mcp\n```\n\n### Docker\n\nMulti-architecture images (amd64/arm64) are published to GitHub Container\nRegistry.\n\n```bash\n# Latest (pinned to most recent release, rebuilt on base image updates)\ndocker pull ghcr.io/claytono/go-unifi-mcp:latest\n\n# Edge (built from main on every merge, unstable)\ndocker pull ghcr.io/claytono/go-unifi-mcp:edge\n```\n\n### Go Install\n\n```bash\ngo install github.com/claytono/go-unifi-mcp/cmd/go-unifi-mcp@latest\n```\n\n## Configuration\n\n### UniFi Credentials\n\nThe server requires access to a UniFi Network Controller. Two authentication\nmethods are supported:\n\n1. **API Key** (preferred): Create an API key in your UniFi controller under\n   Settings > Control Plane > Integrations. Set `UNIFI_HOST` and\n   `UNIFI_API_KEY`.\n\n2. **Username/Password**: Use a local admin account. Set `UNIFI_HOST`,\n   `UNIFI_USERNAME`, and `UNIFI_PASSWORD`.\n\n### Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n**Using the binary:**\n\n```json\n{\n  \"mcpServers\": {\n    \"unifi\": {\n      \"command\": \"/usr/local/bin/go-unifi-mcp\",\n      \"env\": {\n        \"UNIFI_HOST\": \"https://your-controller:443\",\n        \"UNIFI_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\n**Using Docker:**\n\n```json\n{\n  \"mcpServers\": {\n    \"unifi\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\",\n        \"-i\",\n        \"--rm\",\n        \"-e\",\n        \"UNIFI_HOST\",\n        \"-e\",\n        \"UNIFI_API_KEY\",\n        \"ghcr.io/claytono/go-unifi-mcp:latest\"\n      ],\n      \"env\": {\n        \"UNIFI_HOST\": \"https://your-controller:443\",\n        \"UNIFI_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code\n\n```bash\nclaude mcp add unifi -- go-unifi-mcp\n```\n\nThen set the required environment variables in your shell before running\n`claude`.\n\n### Environment Variables\n\n| Variable           | Required | Default   | Description                     |\n| ------------------ | -------- | --------- | ------------------------------- |\n| `UNIFI_HOST`       | Yes      | —         | UniFi controller URL            |\n| `UNIFI_API_KEY`    | \\*       | —         | API key (preferred auth method) |\n| `UNIFI_USERNAME`   | \\*       | —         | Username for password auth      |\n| `UNIFI_PASSWORD`   | \\*       | —         | Password for password auth      |\n| `UNIFI_SITE`       | No       | `default` | UniFi site name                 |\n| `UNIFI_VERIFY_SSL` | No       | `true`    | Whether to verify SSL certs     |\n| `UNIFI_LOG_LEVEL`  | No       | `error`   | go-unifi client log level       |\n| `UNIFI_TOOL_MODE`  | No       | `lazy`    | Tool registration mode          |\n\n\\* Either `UNIFI_API_KEY` or both `UNIFI_USERNAME` and `UNIFI_PASSWORD` must be\nset.\n\n### Log Levels\n\nThe `UNIFI_LOG_LEVEL` variable controls logging from the underlying go-unifi\nclient library. The default is `error` because the client otherwise emits INFO\nmessages to stderr, which can interfere with tools like mcp-cli that parse JSON\non stdout/stderr.\n\n| Level      | Description                          |\n| ---------- | ------------------------------------ |\n| `disabled` | No logging                           |\n| `trace`    | Most verbose, including wire details |\n| `debug`    | Debug messages                       |\n| `info`     | Informational messages               |\n| `warn`     | Warnings only                        |\n| `error`    | Errors only (default)                |\n\n### Tool Modes\n\nThe server supports two tool registration modes, following the pattern\nestablished by\n[unifi-network-mcp](https://github.com/sirkirby/unifi-network-mcp):\n\n| Mode    | Tools | Context Size | Description                                     |\n| ------- | ----- | ------------ | ----------------------------------------------- |\n| `lazy`  | 3     | ~200 tokens  | Meta-tools only (default, recommended for LLMs) |\n| `eager` | 252   | ~55K tokens  | All tools registered directly                   |\n\n**Lazy mode** (default) registers only 3 meta-tools that provide access to 252\nUniFi operations (generated from the controller API):\n\n- `tool_index` - Search/filter the tool catalog by category or resource\n- `execute` - Execute any tool by name with arguments\n- `batch` - Execute multiple tools in parallel\n\nThis dramatically reduces context window usage while preserving full\nfunctionality. The LLM first queries the index to find relevant tools, then\nexecutes them via the dispatcher.\n\n**Eager mode** registers all 252 tools directly, which may be useful for non-LLM\nclients or debugging but consumes significant context.\n\n**Update semantics:** Updates use a read-modify-write flow against the\ncontroller API. We fetch the current resource, merge your fields, and submit the\nfull object. This avoids clearing unspecified fields, but it is not atomic and\nconcurrent updates can race (last write wins) because the UniFi API does not\nexpose etags or revision IDs. In practice this is unlikely to be an issue, but\nit's something to be aware of.\n\n### ID Resolution\n\nResponses from the UniFi API contain opaque ID references (e.g. `network_id`,\n`usergroup_id`, `networkconf_id`). By default, the server resolves these to\nhuman-readable names by looking up the referenced resource and injecting a\nsibling `_name` field:\n\n```json\n{\n  \"src_networkconf_id\": \"609fbf24e3ae433962e000de\",\n  \"src_networkconf_name\": \"IOT\"\n}\n```\n\nResolution uses a per-request cache, so listing 100 firewall rules that\nreference networks only makes one additional `ListNetwork` API call. Typical\noverhead is 10-40ms depending on how many distinct resource types are\nreferenced.\n\nTo disable resolution for a specific call, pass `\"resolve\": false` in the tool\narguments.\n\n### Query Parameters\n\nAll list operations support optional post-processing parameters for filtering\nand projecting results.\n\n**filter** — Match items by field values. Supports three operators:\n\n```jsonc\n// Exact match\n{\"filter\": {\"type\": \"usw\"}}\n\n// Substring match (case-insensitive)\n{\"filter\": {\"name\": {\"contains\": \"office\"}}}\n\n// Regular expression (RE2 syntax: https://github.com/google/re2/wiki/Syntax)\n{\"filter\": {\"name\": {\"regex\": \"^ap-.*\"}}}\n\n// Multiple conditions (ANDed together)\n{\"filter\": {\"type\": \"uap\", \"name\": {\"contains\": \"echo\"}}}\n```\n\n**search** — Case-insensitive full-text search across all string field values:\n\n```json\n{ \"search\": \"living room\" }\n```\n\n**fields** — Project the response to include only specific keys:\n\n```json\n{ \"fields\": [\"name\", \"ip\", \"mac\"] }\n```\n\nParameters can be combined. Execution order is filter → search → fields, so you\ncan filter on fields that are excluded from the output:\n\n```json\n{\n  \"filter\": { \"type\": \"uap\" },\n  \"search\": \"echo\",\n  \"fields\": [\"name\", \"ip\"]\n}\n```\n\n## Development\n\n### Prerequisites\n\n- [Nix](https://nixos.org/download.html) with flakes enabled\n- [direnv](https://direnv.net/) (optional but recommended)\n\n### Developing\n\n```bash\n# Clone the repository\ngit clone https://github.com/claytono/go-unifi-mcp.git\ncd go-unifi-mcp\n\n# Enter the development environment\nnix develop\n# Or with direnv:\ndirenv allow\n\n# Install pre-commit hooks\npre-commit install\n\n# Run linters\ntask lint\n\n# Run tests\ntask test\n\n# Run tests with coverage\ntask coverage\n```\n\n### Available Tasks\n\n```bash\ntask lint        # Run linters via pre-commit\ntask test        # Run tests\ntask coverage    # Run tests with coverage checks\ntask build       # Build the binary\ntask generate    # Run go generate\n```\n\n### Testing with mcp-cli\n\nThe development environment includes\n[mcp-cli](https://github.com/philschmid/mcp-cli) for interactive testing of the\nMCP server.\n\n1. Create `.envrc.local` with your UniFi credentials (not tracked in git):\n\n   ```bash\n   export UNIFI_HOST=\"https://your-controller:443\"\n   export UNIFI_API_KEY=\"your-api-key\"\n   # Or use username/password:\n   # export UNIFI_USERNAME=\"admin\"\n   # export UNIFI_PASSWORD=\"password\"\n   ```\n\n2. Build the binary:\n\n   ```bash\n   task build\n   ```\n\n3. Test with mcp-cli:\n\n   The `.mcp_servers.json` config provides two server entries:\n   - `go-unifi-mcp` - eager mode (252 tools)\n   - `go-unifi-mcp-lazy` - lazy mode (3 meta-tools)\n\n   **Eager mode** (direct tool access):\n\n   ```bash\n   # List tools (shows all 252)\n   mcp-cli info go-unifi-mcp\n\n   # Call a tool directly\n   mcp-cli call go-unifi-mcp list_device '{}'\n   mcp-cli call go-unifi-mcp list_network '{\"site\": \"default\"}'\n   ```\n\n   **Lazy mode** (meta-tools):\n\n   ```bash\n   # List tools (shows only 3 meta-tools)\n   mcp-cli info go-unifi-mcp-lazy\n\n   # Query the tool index\n   mcp-cli call go-unifi-mcp-lazy tool_index '{}'\n   mcp-cli call go-unifi-mcp-lazy tool_index '{\"category\": \"list\"}'\n   mcp-cli call go-unifi-mcp-lazy tool_index '{\"resource\": \"network\"}'\n\n   # Execute a tool via the dispatcher\n   mcp-cli call go-unifi-mcp-lazy execute '{\"tool\": \"list_device\", \"arguments\": {}}'\n\n   # Batch execute multiple tools\n   mcp-cli call go-unifi-mcp-lazy batch '{\"calls\": [{\"tool\": \"list_network\", \"arguments\": {}}, {\"tool\": \"list_device\", \"arguments\": {}}]}'\n   ```\n\n## Credits\n\nThis project builds upon:\n\n- [go-unifi](https://github.com/paultyng/go-unifi) - Go client library for UniFi\n  Network Controller\n- [unifi-network-mcp](https://github.com/sirkirby/unifi-network-mcp) - Python\n  MCP server for UniFi that inspired this project\n- [mcp-go](https://github.com/mark3labs/mcp-go) - Go SDK for Model Context\n  Protocol\n\n## License\n\nMPL-2.0\n",
  "bytes": 11616,
  "sha": "78495d9cfbb3aafc0f994d2beb7d3c4304935479ca8988074b1729ff58273807",
  "repo_slug": "claytono/go-unifi-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_claytono_go_unifi_mcp_cce8a79f/readme"
}