UniFi Gateway について
UniFi Gateway は、セルフホスト型 UniFi の Network、Protect、Access を管理する運用担当者向けの MCP サーバーです。dry-run による変更確認、監査ログ、複合操作のロールバックを備え、1つのインスタンスで複数サイトを扱えます。
主な機能
- 01Network、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。
LLM 主導のインフラストラクチャ操作にはガードレールが必要であるという前提に基づいて構築された 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 グループ、可観測性、Threat Management/IDS-IPS、Honeypot、Teleport VPN に対応する Network ツールと、オプトインで利用できる Protect(カメラ、モーションイベント、スマート検知、録画設定)および Access(ドア、認証情報、訪問者、バッジイベント、ハブ/リーダー)を備えています。すべてのツールは controller パラメーターを受け付けるため、1 つのサーバーインスタンスで複数の 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)と Zone-Based Firewall(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)。Network および WLAN への書き込みは、リクエストがそのまま公式 Integration API に対応する場合は同 API を経由し、それ以外の場合はプライベート API にフォールバックします。UNIFI_WRITE_API=private を設定すると、すべての書き込みでプライベート API が使用されます(ADR 0008)。Site Manager やクラウドアカウントは必要ありません。
インストール
サポートされている方法は 4 つあります。Claude の実行方法に合ったものを選んでください。
Docker
ポート 3714 で Streamable HTTP を使用する長時間稼働コンテナです。ホームラボや複数クライアントの構成に最適です。
HTTP トランスポートはベアラートークンがないと起動しないため、トークンを指定してください。
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 に組み込まれた UI から行います。バンドルには 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)
このチャートでは auth.required: true と auth.tokens: "" が設定されているため、トークンを設定するまで Pod は起動しません(または --set auth.required=false を指定しますが、これは信頼できる単一テナントのクラスターでのみ適切です)。
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))。変更を伴う12個のツールのうち、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 を使うと、新しいコントローラーに対してログの操作を再実行できます。 - 単一イメージ、複数コントローラー。 1つのコンテナで 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 チャート、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 をスタブモードで使う方法です。ハードウェアは必要ありません。
-
コンテナを起動します。認証はデフォルトで有効なので、最初にトークンを作成します。
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 デバイスを一覧表示して」*と尋ねます。スタブのデバイスが2台返されます。
-
実際のゲートウェイに接続する準備ができたら、スタブモードを無効にします。
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 が存在する場合はそこからも読み込まれます)。最もよく使われる6つの設定は次のとおりです。
| 変数 | デフォルト | 備考 |
|---|---|---|
STUB_MODE | true | false の場合、実モードのコントローラー設定が必要です。 |
UNIFI_HOST | (空) | ゲートウェイの IP アドレスまたはホスト名です。実モードでは必須です。 |
UNIFI_API_KEY | (空) | ローカル API キーです。実モードでは必須です。 |
MCP_UNIFI_READONLY | false | true の場合、変更を伴うツールは非表示になり、実行も拒否されます。セキュリティガイドを参照してください。 |
MCP_UNIFI_MODULES_ENABLED | network | network,protect,access を指定すると、3つのモジュールすべてが有効になります。 |
MCP_UNIFI_CONTROLLERS_FILE | (未設定) | 複数サイト用の、名前付きコントローラーを記述した YAML ファイルです。 |
MCP_UNIFI_OTEL_ENABLED | false | オプションの OpenTelemetry トレースです。ツール呼び出しごとに1つのスパンを記録します。デフォルトでは無効で、SDK も依存関係に含まれません。運用ガイドを参照してください。 |
UNIFI_API_KEY_FILE | (未設定) | UNIFI_API_KEY の代わりに、ファイル(Docker または Kubernetes のシークレットマウント)から API キーを読み込みます。両方が設定されている場合はこちらが優先され、TLS 検証がデフォルトで有効になります。 |
UNIFI_ACCESS_API_KEY_FILE | (未設定) | UNIFI_ACCESS_API_KEY のファイルベースの形式です。 |
UNIFI_OS_PASSWORD_FILE | (未設定) | UNIFI_OS_PASSWORD のファイルベースの形式です。 |
MCP_UNIFI_AUTH_TOKEN_FILE | (未設定) | 1つのベアラートークン(または 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 スキーマについては、設定ドキュメントを参照してください。
ファイルベースのシークレット
すべてのシークレットには、Docker や Kubernetes のシークレットマウント向けに _FILE 形式があります。環境変数形式も引き続き使用でき、このリリースで非推奨にはなりません。ファイル形式はオプトインで、その中には強化されたデフォルト設定が適用されます。そのため、api_key_file で設定したコントローラーは、verify_ssl: false を設定しない限り、ゲートウェイの TLS 証明書を検証します。コントローラー 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 検証を無効にしているコントローラーごとに、サーバーは1行のログを出力します。この警告は、日付付きの移行計画(オプトイン、次に警告、そしてメジャーリリースで切り替え)の第一段階です。この計画は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 ファイルに記載されています)。
これがどのように構築されているか
ツールの仕組みを支えるエンジニアリング基盤について説明します(現在の件数はツールマニフェストを参照)。何が支えているのか知りたい方はご覧ください。
テストの徹底。 単体テスト、統合テスト、プロパティベーステスト(Hypothesis)を合わせて約880件あります。現在の件数はpytest --collect-onlyで確認できます。HTTPはrespxでモックしているため、テストが実際のコントローラーにアクセスすることはありません。CIではブランチカバレッジ80%をゲートとしており、現在の基準は90%です。
コード品質ゲート。 Ruff(pycodestyle、pyflakes、isort、flake8-bugbear、pyupgrade、simplify、flake8-banditセキュリティルールセット、内包表記)とmypy strict(暗黙のAnyを禁止、到達不能コードを検出、未使用のignoreを検出)を使用しています。pre-commitフックは、リント、フォーマット、型チェックに加え、差分チェック付きでツールマニフェストを再生成します。これにより、不適切なコードがCIに到達することはありません。
CIパイプライン(ゲート付きジョブ5件)。 すべてのPRで、ロックファイルの差分チェック → リントと型チェック → テストとカバレッジ → マルチアーキテクチャのDockerビルド → Trivyによるファイルシステムおよびイメージのスキャン(HIGH/CRITICALがある場合はビルド失敗)が実行されます。各工程が次の工程へのゲートになります。
リリースパイプライン。 git tag vX.Y.Zのプッシュをトリガーに、マルチアーキテクチャ(linux/amd64 + linux/arm64)のDockerビルド、sigstore OIDCによるcosignのキーレス署名、SLSAビルド来歴のアテステーション、SyftによるCycloneDX SBOMの生成とGitHubリリースへの添付、Claude Desktopのワンクリックインストール用.dxtバンドルの生成、vX.Y.Z / X.Y / latestタグを付けたGHCRへのプッシュ、main上のサンプルdocker-compose.ymlの自動更新が行われます。
依存関係の管理。 pip install --require-hashesによるハッシュ固定を採用しています。カスタムCIステップで、requirements.in内の固定されたすべての依存関係がrequirements.lockと一致することを検証するため、両方をそろえずに一方だけ更新することはできません。Dependabotが安全なパッチを自動マージします。ベースイメージはタグではなくダイジェストで固定しています。
コンテナーの強化。 非rootのUID 1000で実行し、シェルもホームディレクトリもありません。Docker / Helmでルートファイルシステムを読み取り専用にしています。/tmpは16MiBのtmpfsです。no-new-privilegesを設定し、Linuxのすべてのケイパビリティを削除しています。専用の/healthエンドポイントにより、ストリーミングHTTPトランスポートでDockerのヘルスチェックごとに406のノイズがログに記録されるのを防ぎます。
セキュリティ態勢。 HTTPトランスポートではベアラートークン認証を行い、デフォルトで安全な設定としています(トークンなしでは起動を拒否します)。監査ログには、各呼び出しで認証されたclient_idが記録されます。また、api_key、passphrase、password、secret、tokenの部分文字列に一致する値は、シークレットを伏せて記録します。APIキーはpydanticのSecretStrでラップしています。SECURITY.mdには非公開の脆弱性報告経路を記載しています。
配布先。 GHCR(署名済みマルチアーキテクチャ)、Smithery(登録済み)、MCP Registry(掲載済み)、Helmチャート(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タグ、CHANGELOGのエントリー、Dockerイメージのタグ、docker-composeのサンプル、Helmチャートの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(リントとフォーマット)、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
ドキュメント
- ドキュメントサイト
- Network ツールリファレンス
- Protect ツールリファレンス
- Access ツールリファレンス
- マルチサイトのセットアップ
- Access のセットアップ
- ドライランと監査ログ
- セキュリティモデル
- v0.x からの移行
- 変更履歴
- セキュリティポリシー
ライセンス
MIT。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。