关于 UniFi Gateway
UniFi Gateway 是面向自托管 UniFi 环境的 MCP 服务,适合管理网络、Protect 和 Access 的运维人员。它以默认安全机制为核心,提供变更预览、审计记录和失败回滚,并可通过一个实例管理多个站点。
主要功能
- 01网络、Protect 与 Access 管理
- 02破坏性操作支持 dry-run
- 03复合操作失败时回滚
- 04JSONL 审计日志与重放 CLI
- 05多控制器与只读模式
适用场景
- 01预览网络配置变更再执行
- 02为部分失败的配置流程回滚
- 03审查并重放控制器操作记录
MCP 相关
该服务向 MCP 客户端开放 UniFi Network 工具,并可选启用 Protect 和 Access。支持 stdio 与 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e STUB_MODE -e UNIFI_HOST -e UNIFI_API_KEY -e UNIFI_SITE -e UNIFI_VERIFY_SSL -e MCP_UNIFI_CONTROLLERS_FILE -e MCP_UNIFI_MODULES_ENABLED -e UNIFI_ACCESS_HOST -e UNIFI_ACCESS_API_KEY -e UNIFI_ACCESS_PORT -e MCP_UNIFI_AUDIT_SINK -e MCP_UNIFI_AUDIT_PATH ghcr.io/pete-builds/mcp-unifi:0.27.0STUB_MODEWhen true, the server returns realistic mock data and requires no UniFi hardware. Defaults to true so the image is functional out of the box.UNIFI_HOSTIP address or hostname of the UniFi OS gateway (UCG-Fiber, UDM Pro, etc). Required when STUB_MODE=false and MCP_UNIFI_CONTROLLERS_FILE is unset.UNIFI_API_KEY密钥Local API key generated under Settings -> Control Plane -> Integrations on the gateway. Required when STUB_MODE=false and MCP_UNIFI_CONTROLLERS_FILE is unset.UNIFI_SITEUniFi controller site name. Defaults to 'default'.UNIFI_VERIFY_SSLWhether to verify the gateway's TLS certificate. Defaults to false because most home gateways use a self-signed cert.MCP_UNIFI_CONTROLLERS_FILEPath to a YAML file describing multiple named controllers for multi-site management. When set, the legacy UNIFI_HOST / UNIFI_API_KEY env vars are ignored. Each entry needs name, host, api_key, and optionally port, site, verify_ssl.MCP_UNIFI_MODULES_ENABLEDComma-separated list of modules to load. Known values: 'network', 'protect', 'access'. Defaults to 'network'. Set to 'network,protect,access' to enable Protect and Access tools alongside Network. Access currently ships read-only; door unlocks and credential issuance require session-token auth and are deferred.UNIFI_ACCESS_HOSTUniFi Access hub IP or hostname. Required when the access module is enabled and STUB_MODE=false. Often the same host as UNIFI_HOST.UNIFI_ACCESS_API_KEY密钥UniFi Access API key. Separate from the Network API key; generated on the Access controller's developer settings. Required when the access module is enabled and STUB_MODE=false.UNIFI_ACCESS_PORTHTTPS port for the Access hub. Defaults to 12445 (the direct Access app port).MCP_UNIFI_AUDIT_SINKAudit log sink. One of 'file' (default), 'stdout', or 'syslog'. Every tool call is recorded to a JSONL stream with secrets scrubbed.MCP_UNIFI_AUDIT_PATHPath for the audit log file when MCP_UNIFI_AUDIT_SINK=file. Defaults to audit.jsonl in the process CWD.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/pete-builds/mcp-unifi:0.27.0Streamable HTTP工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-unifi
以安全为先的自托管 UniFi MCP 服务。支持试运行预览、JSONL 审计日志和复合回滚。涵盖 Network、Protect 和 Access。
这是一个围绕以下假设构建的 MCP 服务:由大模型驱动的基础设施调用需要防护措施。每个具有破坏性的工具都接受 dry_run=True,并返回预测的变更集,而不执行写入。复合工具(create_iot_network、create_guest_network、provision_homelab_service、provision_camera)会记录操作前的状态,并在部分失败时回滚已应用的步骤。每次调用——无论是试运行还是真正执行——都会写入 JSONL 审计日志,并清除其中的机密信息;随附的 mcp-unifi-replay CLI 可将日志重新应用到新的控制器。
除安全基础设施外,还提供用于设备、AP 无线电调优、VLAN、WLAN、防火墙、交换机端口、端口转发、DHCP 保留、AP 组、可观测性、威胁管理 / IDS-IPS、蜜罐和 Teleport VPN 的 Network 工具,以及可选启用的 Protect(摄像头、运动事件、智能检测、录制配置)和 Access(门、凭证、访客、门禁卡事件、集线器 / 读卡器)。每个工具都接受 controller 参数,因此一个服务实例即可管理多个 UniFi 站点。支持 stdio(Claude Desktop、uvx、.dxt)和 Streamable HTTP(Docker、Helm)。完整且始终保持最新的工具列表见自动生成的工具清单。适用于运行 UniFi Network 9.x 或更高版本的任何 UniFi OS 网关(UDM、UDM Pro、UDM SE、UCG-Fiber、UCG-Ultra、UDR、UDW、UniFi OS Server),并使用通过 Settings → Control Plane → Integrations 获取的本地 API 密钥进行身份验证。已在运行 UniFi OS 5.1.33、搭载 UniFi Network 10.6.101 的 UCG-Fiber 上验证(2026-09-13)。防火墙读取同时涵盖旧版规则集(list_firewall_rules)和基于区域的防火墙(list_firewall_policies、list_firewall_zones),且 audit_open_ports 会同时检查两者,因此已迁移到区域的站点不会被误报为没有防火墙。旧版防火墙写入操作(create_firewall_rule 及相关工具)通过 /rest/firewallrule 执行;区域策略写入操作(create_firewall_policy、update_firewall_policy、delete_firewall_policy)仅通过官方 Integration API 执行;在基于区域的站点上,配置复合工具会创建区域策略,而非旧版规则(ADR 0009)。网络和 WLAN 写入操作会在请求可完全映射到官方 Integration API 时通过该 API 执行,否则回退到私有 API;UNIFI_WRITE_API=private 会让所有写入操作都使用私有 API(ADR 0008)。无需 Site Manager 或云账户。
安装
支持四种方式。请选择与你运行 Claude 的方式相匹配的一种。
Docker
长期运行的容器,通过端口 3714 提供 Streamable HTTP。最适合家庭实验室和多客户端配置。
HTTP 传输在没有 bearer token 时不会启动,因此请提供一个:
export MCP_UNIFI_TOKEN=$(openssl rand -hex 32)
docker run --rm -p 3714:3714 \
-e STUB_MODE=true \
-e MCP_UNIFI_AUTH_TOKENS="$MCP_UNIFI_TOKEN" \
ghcr.io/pete-builds/mcp-unifi:latest
客户端随后发送 Authorization: Bearer $MCP_UNIFI_TOKEN。仅在回环地址上进行临时本地测试时,可使用 -e MCP_UNIFI_AUTH_REQUIRED=false 完全跳过身份验证;切勿在其他设备可访问的网络接口上使用,因为每个连接的客户端都将获得与管理员等效的控制器访问权限。
Claude Desktop (.dxt) — 一键安装
从最新版本下载 mcp-unifi-<version>.dxt 并双击。通过 Claude Desktop 内置的界面进行配置。安装包内含 Python 运行时,无需单独安装。使用 stdio 传输。
Helm
helm repo add mcp-unifi https://pete-builds.github.io/mcp-unifi/
helm install unifi mcp-unifi/mcp-unifi \
--set unifi.host=192.168.1.1 \
--set unifi.apiKey=<your-local-api-key> \
--set auth.tokens=$(openssl rand -hex 32)
该 chart 的 auth.required: true,而 auth.tokens: "",因此必须先设置 token(或使用 --set auth.required=false;这仅适用于可信的单租户集群),Pod 才会启动。
uvx / pipx
直接从 GitHub 仓库快速运行一次性任务。使用 stdio 传输。
uvx --from git+https://github.com/pete-builds/mcp-unifi mcp-unifi
在 URL 末尾追加 @v0.5.0-rc.2(或任何标签)即可固定到指定版本。
各安装方式的完整指南请参阅文档网站。
设计
- 只读模式。
MCP_UNIFI_READONLY=true会从结构上阻止服务进行任何更改:修改类工具会从tools/list中隐藏,并在tools/call时遭到拒绝,因此调用被隐藏工具时只会收到常规错误信封,而不会执行写入操作。工具的分类在注册时逐个声明(@audited("list_networks", mutates=False)),绝不根据工具名称推断——十二个修改类工具(包括confirm_destructive_action)的名称都没有create_/update_/delete_/set_前缀。如果工具未声明分类,注册就会失败,因此新工具无法默认变为可调用状态。这是在只读 UniFi API 密钥之上的纵深防御,而非其替代方案。 - 安全机制。 每个具有破坏性的工具都接受
dry_run=True,并会返回预测的变更集,而不执行写入。组合工具(create_iot_network、create_guest_network、provision_homelab_service、provision_camera)会捕获变更前状态,并在部分失败时回滚已应用的步骤。每次工具调用都会写入 JSONL 审计日志,并清除其中的机密信息;随附的mcp-unifi-replayCLI 可将日志重新应用到全新的控制器。 - 单一镜像,多控制器。 一个容器即可同时运行 Network、Protect 和 Access。同一进程通过
controller参数和 YAML 控制器文件(MCP_UNIFI_CONTROLLERS_FILE)并行管理多个 UniFi 站点。无需为每个控制器单独运行一个进程。 - 优先使用 API 密钥进行身份验证。 使用 Settings → Control Plane → Integrations 中的本地 API 密钥,访问
/proxy/network/api端点。不存储用户名和密码,无需云账户,也不依赖 Site Manager。 - 多渠道分发。 提供 Docker、适用于 Claude Desktop 的 .dxt 一键安装包、Helm chart 和 uvx。已列入官方 MCP Registry。容器镜像使用 cosign(无密钥 OIDC)签名,每个版本都附带 CycloneDX SBOM。
- Network + Protect + Access。 Network 默认启用;Protect 和 Access 通过
MCP_UNIFI_MODULES_ENABLED=network,protect,access选择启用。Access 默认只读(门禁解锁和凭证签发需要会话令牌身份验证,因此暂不提供)。UniFi Drive 不在范围内。
快速开始
最快的冷启动方式:使用 Docker + Claude Code 并启用 stub 模式,无需硬件。
-
启动容器。默认启用身份验证,因此请先生成令牌:
export MCP_UNIFI_TOKEN=$(openssl rand -hex 32) docker run -d --rm -p 3714:3714 \ -e STUB_MODE=true \ -e MCP_UNIFI_AUTH_TOKENS="$MCP_UNIFI_TOKEN" \ --name mcp-unifi ghcr.io/pete-builds/mcp-unifi:latest -
将其注册到 Claude Code,并传入令牌:
claude mcp add --transport http --scope user unifi http://localhost:3714/mcp \ --header "Authorization: Bearer $MCP_UNIFI_TOKEN" -
验证连接:
claude mcp list -
在 Claude Code 会话中,提问:“列出我的 UniFi 设备”。你将收到两个 stub 设备。
-
准备好连接到实际网关时,关闭 stub 模式:
docker run -d --rm -p 3714:3714 \ -e STUB_MODE=false \ -e UNIFI_HOST=192.168.1.1 \ -e UNIFI_API_KEY=<your-local-api-key> \ -e MCP_UNIFI_AUTH_TOKENS="$MCP_UNIFI_TOKEN" \ --name mcp-unifi ghcr.io/pete-builds/mcp-unifi:latest
在网关的 Settings → Control Plane → Integrations → Create API Key 下生成 API 密钥。
配置
所有配置均从环境变量读取(存在 .env 时也会读取)。最常用的六个变量:
| 变量 | 默认值 | 说明 |
|---|---|---|
STUB_MODE | true | 设为 false 时,必须配置真实模式下的控制器。 |
UNIFI_HOST | (空) | 网关 IP 或主机名。真实模式下必填。 |
UNIFI_API_KEY | (空) | 本地 API 密钥。真实模式下必填。 |
MCP_UNIFI_READONLY | false | 设为 true 时,隐藏并拒绝会修改数据的工具。请参阅安全指南。 |
MCP_UNIFI_MODULES_ENABLED | network | 设置为 network,protect,access 以启用全部三个模块。 |
MCP_UNIFI_CONTROLLERS_FILE | (未设置) | 包含命名控制器的 YAML 文件,用于多站点配置。 |
MCP_UNIFI_OTEL_ENABLED | false | 可选的 OpenTelemetry 跟踪,每次工具调用对应一个 span。默认关闭,且 SDK 不是依赖项。请参阅运维。 |
UNIFI_API_KEY_FILE | (未设置) | 从文件(Docker 或 Kubernetes 密钥挂载)读取 API 密钥,而不是从 UNIFI_API_KEY 读取。如果两者都设置,则优先使用此项,并默认启用 TLS 验证。 |
UNIFI_ACCESS_API_KEY_FILE | (未设置) | UNIFI_ACCESS_API_KEY 的文件形式。 |
UNIFI_OS_PASSWORD_FILE | (未设置) | UNIFI_OS_PASSWORD 的文件形式。 |
MCP_UNIFI_AUTH_TOKEN_FILE | (未设置) | 包含一个 bearer 令牌(或完整的 MCP_UNIFI_AUTH_TOKENS 语法)的文件。会与 MCP_UNIFI_AUTH_TOKENS 定义的内容合并。 |
MCP_UNIFI_CLIENT_ID | (未设置) | MCP_UNIFI_AUTH_TOKEN_FILE 中裸令牌对应的客户端名称。 |
UNIFI_PINNED_CERT | (未设置) | mcp-unifi-pin-cert 提取的控制台自身证书(PEM)路径。设置后,服务仅接受此控制器提供的该证书。见下文。 |
完整的环境变量参考和多站点 YAML 架构请参阅配置文档。
基于文件的密钥
每个密钥都有对应的 _FILE 变量,可用于 Docker 和 Kubernetes 密钥挂载。本版本不会弃用环境变量形式,它仍可正常使用;文件形式为可选配置,并包含更严格的默认设置,因此使用 api_key_file 配置的控制器会验证网关的 TLS 证书,除非你设置 verify_ssl: false。在控制器 YAML 中:
- name: lan
host: 192.168.1.1
api_key: <inline key> # verify_ssl stays false: self-signed console on a LAN
- name: datacenter
host: unifi.example.com
api_key_file: /run/secrets/unifi_api_key # verify_ssl defaults to true here
密钥文件缺失、为空或不可读时,服务会在启动时失败,并提示控制器名称和字段,但绝不会泄露文件内容。每次启动时,对于仍使用环境变量形式或关闭了 TLS 验证的控制器,服务都会各记录一行日志。这项警告是分阶段推进计划(可选启用,然后警告,最后在某个主要版本中切换)的第一步,相关计划记录在 ADR 0007 中;目前不会拒绝任何配置。docker-compose.yml 展示了密钥挂载方式。
证书固定
UniFi 控制台提供的自签名证书,其名称列表中不包含你连接时使用的地址,因此普通的 TLS 验证永远无法通过,verify_ssl 默认关闭。固定证书无需 CA 即可弥补这一缺口:记录一次控制台的证书,此后服务只接受该证书,不接受其他任何证书。
mcp-unifi-pin-cert 192.168.1.1 --out /etc/mcp-unifi/pins/home.pem
# prints the SHA-256 fingerprint; compare it against the console before trusting it
ssh [email protected] 'openssl x509 -in /data/unifi-core/config/unifi-core.crt -noout -fingerprint -sha256'
# the same fingerprint read on the console itself, over a channel the pin does not depend on
然后在 YAML 中为控制器设置 pinned_cert: /etc/mcp-unifi/pins/home.pem,或在单控制器环境变量形式中设置 UNIFI_PINNED_CERT。固定证书的控制器会对每个连接都依据该证书进行验证,如果控制台提供了其他任何证书,则直接失败;没有回退机制。如果固件更新重新生成了控制台证书,请求会失败并给出提示信息,其中会列出重新固定的命令,你在核对新指纹后使用 --force 重新运行该命令。服务绝不会自行获取并信任证书:引导过程始终是这条显式命令。传入 --expect-fingerprint,使其拒绝与控制台上读取到的指纹不匹配的证书。在容器中,以只读方式挂载该固定证书(compose 文件中显示了挂载位置)。
它是如何构建的
工具集周边的工程脚手架(当前数量见工具清单),以防你想知道是什么在支撑它:
测试纪律。 约 880 个测试,涵盖单元测试、集成测试和基于属性的测试(Hypothesis)——当前数量见 pytest --collect-only。HTTP 使用 respx 进行 mock,因此测试不会打到真实的控制器。CI 中覆盖率以 80% 分支覆盖率为门槛;当前下限为 90%。
代码质量门禁。 Ruff(pycodestyle、pyflakes、isort、flake8-bugbear、pyupgrade、simplify、flake8-bandit 安全规则集、comprehensions)加上 mypy strict(禁止隐式 Any、标记不可达代码、标记未使用的 ignore)。Pre-commit 钩子运行 lint、format、types,并重新生成工具清单并做漂移检查,因此坏代码永远到不了 CI。
CI 流水线(5 个门禁任务)。 每个 PR 依次运行 lockfile 漂移检查 → lint + 类型检查 → 测试 + 覆盖率 → 多架构 Docker 构建 → Trivy 文件系统和镜像扫描(HIGH/CRITICAL 会导致构建失败)。每一项都作为下一项的门禁。
发布流水线。 推送 git tag vX.Y.Z 会触发多架构(linux/amd64 + linux/arm64)Docker 构建、通过 sigstore OIDC 进行 cosign 无密钥签名、SLSA 构建来源证明、通过 Syft 生成并附加到 GitHub release 的 CycloneDX SBOM、用于 Claude Desktop 一键安装的 .dxt 包、以 vX.Y.Z / X.Y / latest 标签推送到 GHCR,以及自动更新 main 分支上示例 docker-compose.yml。
依赖卫生。 通过 pip install --require-hashes 进行哈希固定。自定义 CI 步骤验证 requirements.in 中每个固定的依赖都与 requirements.lock 匹配,因此没人能在不更新另一个的情况下只升级一个。Dependabot 自动合并安全的补丁。基础镜像以 digest 固定,而非以 tag 固定。
容器加固。 以非 root UID 1000 运行,无 shell,无主目录。通过 Docker / Helm 强制只读根文件系统。/tmp 是 16MiB 的 tmpfs。设置了 no-new-privileges。丢弃所有 Linux capabilities。专用的 /health 端点避免 streamable-HTTP 传输在每次 Docker 健康检查时记录 406 噪音。
安全态势。 HTTP 传输上使用 Bearer token 认证,默认安全(没有 token 就拒绝启动)。审计日志记录每次调用中经过认证的 client_id,并对 api_key、passphrase、password、secret、token 子串匹配进行密钥擦除。API key 包装在 pydantic SecretStr 中。SECURITY.md 提供私密披露路径。
分发渠道。 GHCR(已签名的多架构)、Smithery(已注册)、MCP Registry(已列出)、Helm chart(Secret/Deployment/Service/Ingress/NetworkPolicy 模板)、.dxt 包、uvx / pipx。
文档纪律。 Astro Starlight 站点自动部署到 GitHub Pages。各工具的参考页面由 scripts/generate_tool_manifest.py 通过 FastMCP 内省生成,pre-commit 钩子会重新生成并做漂移检查,因此代码和文档不会出现分歧。CHANGELOG 遵循 Keep a Changelog 格式。
版本纪律。 pyproject.toml、git tag、CHANGELOG 条目、Docker 镜像标签、docker-compose 示例以及 Helm chart 的 appVersion 始终保持一致,因为发布工作流强制要求如此。永远不会出现文档和代码对这个版本是什么意见不一的情况。
开发
克隆、安装开发依赖,并接好 pre-commit 钩子:
git clone https://github.com/pete-builds/mcp-unifi.git
cd mcp-unifi
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" pre-commit
pre-commit install
Pre-commit 钩子会运行 ruff(lint + format)、mypy strict 和工具
清单生成器。只要 src/mcp_unifi/modules/ 下的任何文件发生变化,清单钩子就会重新生成
docs/site/src/content/docs/tools/,如果磁盘上的
清单与已注册的工具集出现漂移,就会使提交失败。使用
pytest 运行测试。
手动重新生成清单:
python scripts/generate_tool_manifest.py # write
python scripts/generate_tool_manifest.py --check # CI-style drift check
文档
许可证
MIT。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。