ames-unifi-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Oliver Ames
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,406 @@
1
+ <p align="center">
2
+ <img src="https://ui.com/favicon-32x32.png" width="48" height="48" alt="UniFi">
3
+ </p>
4
+
5
+ <h1 align="center">UniFi MCP Server</h1>
6
+
7
+ <p align="center">
8
+ <strong>Complete UniFi Network controller management through the Model Context Protocol</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <code>310 tools</code> &nbsp;&bull;&nbsp;
13
+ <code>16 categories</code> &nbsp;&bull;&nbsp;
14
+ <code>3 API layers</code> &nbsp;&bull;&nbsp;
15
+ <code>Network 5.x &ndash; 10.x</code>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="#quick-start">Quick Start</a> &nbsp;&bull;&nbsp;
20
+ <a href="#tool-coverage">Tool Coverage</a> &nbsp;&bull;&nbsp;
21
+ <a href="#architecture">Architecture</a> &nbsp;&bull;&nbsp;
22
+ <a href="#configuration">Configuration</a>
23
+ </p>
24
+
25
+ ---
26
+
27
+ A Go-based MCP server that gives AI assistants deep, safe access to UniFi Network controllers. Built for UniFi OS devices (Dream Machine, Cloud Gateway) and the `unifi.ui.com` cloud interface.
28
+
29
+ ## Why This Exists
30
+
31
+ Managing a UniFi network through natural language means your AI assistant needs to understand every corner of the controller API. This server exposes **310 tools** spanning the complete API surface &mdash; from basic device listing to zone-based firewall policy ordering, from hotspot voucher generation to MC-LAG domain management.
32
+
33
+ Every mutating operation passes through a **confirm gate** that returns a dry-run preview before execution. The assistant sees exactly what will change and asks you before proceeding.
34
+
35
+ ## Quick Start
36
+
37
+ Add to your MCP client configuration:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "unifi": {
43
+ "command": "ames-unifi-mcp",
44
+ "env": {
45
+ "UNIFI_HOST": "https://192.168.1.1",
46
+ "UNIFI_API_KEY": "your-api-key-here",
47
+ "UNIFI_SITE": "default",
48
+ "UNIFI_VERIFY_SSL": "false"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ Generate an API key at **Settings &rarr; Control Plane &rarr; Integrations** (requires Network 9.1.105+). For older firmware, use username/password authentication instead.
56
+
57
+ ## How It Works
58
+
59
+ ### Lazy Mode (Default)
60
+
61
+ Instead of flooding the context window with 310 tool definitions, the server exposes just **3 meta-tools**:
62
+
63
+ | Meta-Tool | Purpose |
64
+ |-----------|---------|
65
+ | `tool_index` | Browse the tool catalog, optionally filtered by category |
66
+ | `tool_execute` | Run any tool by name with input parameters |
67
+ | `tool_batch` | Run multiple tools in parallel for efficiency |
68
+
69
+ The assistant discovers tools on demand, keeping context lean (~200 tokens vs ~30,000 in eager mode).
70
+
71
+ ### Confirm Gate
72
+
73
+ Every write operation requires explicit confirmation. Without `confirm: true`, the tool returns a dry-run preview showing what *would* happen:
74
+
75
+ ```
76
+ You: "Restart the office access point"
77
+ Assistant: Let me preview that first.
78
+ → device_restart {"mac": "aa:bb:cc:dd:ee:ff"}
79
+ ← Preview: This would restart "Office AP" (soft reboot). Confirm?
80
+ You: "Yes"
81
+ Assistant: → device_restart {"mac": "aa:bb:cc:dd:ee:ff", "confirm": true}
82
+ ← Device restarting.
83
+ ```
84
+
85
+ ### Permission Profiles
86
+
87
+ Control what the assistant can do:
88
+
89
+ | Profile | Capabilities |
90
+ |---------|-------------|
91
+ | **read-only** | Query everything, change nothing |
92
+ | **standard** | Reads + safe mutations (WLAN, clients, networks). No PoE cycling, system restarts, or firewall deletes |
93
+ | **admin** | Full access including destructive and system-level operations |
94
+
95
+ Permission-denied tools still appear in `tool_index` (marked `[PERMISSION DENIED]`) so the assistant can explain what's unavailable and why.
96
+
97
+ ### Version Detection
98
+
99
+ On startup, the server queries the controller version and automatically gates tools by firmware requirements:
100
+
101
+ | Feature | Minimum Version |
102
+ |---------|----------------|
103
+ | Legacy API (full) | 5.x+ |
104
+ | Zone-Based Firewall | Network 9.0+ |
105
+ | Integration API | Network 9.0+ |
106
+ | API Key Authentication | Network 9.1.105+ |
107
+ | DNS Policies, ACL Rules | Network 10.0+ |
108
+ | Switch Stacks, LAGs, MC-LAGs | Network 10.0+ |
109
+ | VPN Server/Tunnel CRUD | Network 10.1+ |
110
+
111
+ If a tool isn't in the index, the controller firmware is too old to support it.
112
+
113
+ ---
114
+
115
+ ## Tool Coverage
116
+
117
+ ### 310 tools across 16 categories
118
+
119
+ <table>
120
+ <tr>
121
+ <td width="50%" valign="top">
122
+
123
+ **Devices** &mdash; 29 tools
124
+ ```
125
+ device_list device_restart
126
+ device_get device_adopt
127
+ device_upgrade device_upgrade_all
128
+ device_locate_on/off device_force_provision
129
+ device_spectrum_scan device_rolling_upgrade_*
130
+ device_migrate device_port_action
131
+ device_list_v2 device_stats_latest
132
+ device_unadopt device_pending_list
133
+ ```
134
+
135
+ **Clients** &mdash; 15 tools
136
+ ```
137
+ client_list_active client_block/unblock
138
+ client_get client_reconnect
139
+ client_forget client_sessions
140
+ client_rename client_update
141
+ client_list_v2 client_action
142
+ ```
143
+
144
+ **Networks** &mdash; 10 tools
145
+ ```
146
+ network_list network_create
147
+ network_get network_update
148
+ network_delete network_*_v2 (Integration API)
149
+ ```
150
+
151
+ **Wireless (WLAN + WiFi)** &mdash; 12 tools
152
+ ```
153
+ wlan_list wlan_create/update/delete
154
+ wlan_enable wlan_disable
155
+ wifi_broadcast_list/get/create/update/delete
156
+ ```
157
+
158
+ **Firewall** &mdash; 23 tools
159
+ ```
160
+ firewall_rule_* (legacy CRUD)
161
+ firewall_group_* (address/port groups)
162
+ firewall_zone_* (ZBF zones, 9.0+)
163
+ firewall_policy_* (ZBF policies + ordering)
164
+ ```
165
+
166
+ **ACL Rules** &mdash; 7 tools
167
+ ```
168
+ acl_rule_list/get/create/update/delete
169
+ acl_rule_ordering_get/set
170
+ ```
171
+
172
+ **DNS Policies** &mdash; 5 tools
173
+ ```
174
+ dns_policy_list/get/create/update/delete
175
+ ```
176
+
177
+ **Traffic & QoS** &mdash; 15 tools
178
+ ```
179
+ traffic_rule_* (v2 API rules)
180
+ traffic_route_* (v2 API routes)
181
+ traffic_matching_list_* (10.0+)
182
+ ```
183
+
184
+ </td>
185
+ <td width="50%" valign="top">
186
+
187
+ **VPN** &mdash; 10 tools
188
+ ```
189
+ vpn_server_list/get/create/update/delete
190
+ vpn_tunnel_list/get/create/update/delete
191
+ ```
192
+
193
+ **Switching** &mdash; 15 tools
194
+ ```
195
+ switching_stack_* (switch stacks)
196
+ switching_lag_* (link aggregation)
197
+ switching_mclag_* (MC-LAG domains)
198
+ ```
199
+
200
+ **Stats & DPI** &mdash; 24 tools
201
+ ```
202
+ stats_site_health stats_sysinfo
203
+ stats_dashboard stats_report
204
+ stats_speedtest_* stats_ips_events
205
+ stats_rogueap stats_spectrumscan
206
+ stats_dpi_site stats_dpi_client
207
+ stats_dpi_apps stats_dpi_categories
208
+ ```
209
+
210
+ **Events & Alarms** &mdash; 5 tools
211
+ ```
212
+ event_list alarm_list
213
+ alarm_count alarm_archive
214
+ alarm_archive_all
215
+ ```
216
+
217
+ **Hotspot & Guests** &mdash; 13 tools
218
+ ```
219
+ hotspot_authorize/unauthorize_guest
220
+ hotspot_create_voucher hotspot_extend
221
+ hotspot_voucher_*_v2 (Integration API)
222
+ hotspot_config hotspot_packages
223
+ ```
224
+
225
+ **System & Settings** &mdash; 53 tools
226
+ ```
227
+ system_reboot/poweroff system_settings
228
+ system_backup_* system_firmware_*
229
+ system_port_forward_* system_static_route_*
230
+ system_usergroup_* system_portprofile_*
231
+ system_dhcpoption_* system_radiusprofile_*
232
+ system_tag_* system_led_toggle
233
+ ```
234
+
235
+ **Cloud API** &mdash; 9 tools
236
+ ```
237
+ cloud_host_list/get cloud_site_list
238
+ cloud_device_list cloud_isp_metrics
239
+ cloud_sdwan_*
240
+ ```
241
+
242
+ **Admin & Misc** &mdash; 56 tools
243
+ ```
244
+ admin_site_create/delete/rename
245
+ admin_invite/revoke/grant/update
246
+ poe_power_cycle syslog_query
247
+ apgroup_* misc_rogueknown_*
248
+ misc_scheduletask_* misc_hotspotop_*
249
+ misc_dpigroup_* misc_cnt_resource
250
+ ```
251
+
252
+ </td>
253
+ </tr>
254
+ </table>
255
+
256
+ ### API Layer Coverage
257
+
258
+ The server covers all three UniFi API layers:
259
+
260
+ | API Layer | Path Prefix | Auth | Coverage |
261
+ |-----------|-------------|------|----------|
262
+ | **Legacy API** | `/api/s/{site}/...` | Session cookie | Full &mdash; stat, cmd, rest, set, get, upd, list, cnt, guest, dl |
263
+ | **v2 API** | `/v2/api/site/{site}/...` | Session cookie | Full &mdash; traffic rules, traffic routes, AP groups, system logs |
264
+ | **Integration API** | `/integration/v1/...` | API key or session | Full &mdash; devices, clients, networks, WiFi, firewall, VPN, switching, hotspot, DPI |
265
+ | **Cloud Site Manager** | `api.ui.com/v1/...` | API key | Full &mdash; hosts, sites, devices, ISP metrics, SD-WAN |
266
+
267
+ ---
268
+
269
+ ## Configuration
270
+
271
+ | Variable | Required | Default | Description |
272
+ |----------|----------|---------|-------------|
273
+ | `UNIFI_HOST` | Yes | &mdash; | Controller URL (`https://192.168.1.1`) |
274
+ | `UNIFI_API_KEY` | * | &mdash; | API key (preferred, requires 9.1.105+) |
275
+ | `UNIFI_USERNAME` | * | &mdash; | Username (if no API key) |
276
+ | `UNIFI_PASSWORD` | * | &mdash; | Password (if no API key) |
277
+ | `UNIFI_SITE` | No | `default` | Site name |
278
+ | `UNIFI_VERIFY_SSL` | No | `true` | `false` for self-signed certs |
279
+ | `UNIFI_TOOL_MODE` | No | `lazy` | `lazy` (3 meta-tools) or `eager` (all 310 tools) |
280
+ | `UNIFI_PERMISSION_PROFILE` | No | `standard` | `read-only`, `standard`, or `admin` |
281
+
282
+ <sub>* Either `UNIFI_API_KEY` or both `UNIFI_USERNAME` + `UNIFI_PASSWORD` are required.</sub>
283
+
284
+ ### Authentication Methods
285
+
286
+ **API Key** (recommended) &mdash; Generate at Settings &rarr; Control Plane &rarr; Integrations. Supports both legacy and Integration API endpoints. No session management overhead.
287
+
288
+ **Username/Password** &mdash; Uses session cookies with automatic re-login on expiry. The server includes a single-flight re-login mechanism that prevents thundering-herd issues when batch operations encounter session timeouts simultaneously.
289
+
290
+ ---
291
+
292
+ ## Architecture
293
+
294
+ ```
295
+ cmd/ames-unifi-mcp/main.go Entry point, server wiring
296
+ internal/
297
+ config/ Environment config loading
298
+ client/ HTTP client
299
+ - Session auth with auto re-login (single-flight)
300
+ - API key auth (X-API-Key header)
301
+ - CSRF token management (thread-safe)
302
+ - Retry with backoff (429, 5xx)
303
+ - Legacy envelope parsing (meta.rc/data)
304
+ - Raw response passthrough (Integration/v2 APIs)
305
+ version/ Controller version detection
306
+ permissions/ Permission profiles
307
+ tools/
308
+ tool.go Tool interface
309
+ registry.go Tool registry with version/permission gating
310
+ confirm.go Confirm gate (dry-run preview pattern)
311
+ metatools.go tool_index, tool_execute, tool_batch
312
+ core/ Core tool implementations
313
+ devices.go clients.go networks.go
314
+ wlan.go wifi.go firewall.go
315
+ acl.go dns.go traffic.go
316
+ wan.go switching.go stats.go
317
+ events.go system.go
318
+ extended/ Extended tool implementations
319
+ poe.go hotspot.go cloud.go
320
+ admin.go syslog.go apgroups.go
321
+ misc.go
322
+ ```
323
+
324
+ ### Key Design Decisions
325
+
326
+ **Lazy mode by default.** An LLM calling 310 tools directly wastes context and confuses tool selection. The 3-meta-tool pattern lets the assistant discover tools on demand, typically using < 200 tokens of context for the tool definitions.
327
+
328
+ **Confirm gate on all mutations.** Rather than relying on the MCP client to prevent unintended actions, every mutating tool returns a preview by default. The `confirm: true` parameter is an explicit opt-in. This is baked into the tool schema &mdash; the LLM sees it as a required step, not an optional flag.
329
+
330
+ **Version gating at registration.** Tools for newer API features aren't hidden or errored &mdash; they simply don't register if the controller is too old. The tool index only shows what's actually available.
331
+
332
+ **Permission gating with visibility.** Denied tools appear in the index with a `[PERMISSION DENIED]` suffix. This lets the assistant explain to the user why something isn't available, rather than returning a cryptic "unknown tool" error.
333
+
334
+ ---
335
+
336
+ ## Building
337
+
338
+ ```bash
339
+ go build -o ames-unifi-mcp ./cmd/ames-unifi-mcp/
340
+ ```
341
+
342
+ ### Cross-compilation
343
+
344
+ ```bash
345
+ # Linux ARM64 (e.g., Raspberry Pi, Docker on NAS)
346
+ GOOS=linux GOARCH=arm64 go build -o ames-unifi-mcp ./cmd/ames-unifi-mcp/
347
+
348
+ # Linux AMD64
349
+ GOOS=linux GOARCH=amd64 go build -o ames-unifi-mcp ./cmd/ames-unifi-mcp/
350
+ ```
351
+
352
+ ### Running Tests
353
+
354
+ ```bash
355
+ go test ./...
356
+ ```
357
+
358
+ ---
359
+
360
+ ## Common Operations
361
+
362
+ Here's what natural-language network management looks like:
363
+
364
+ **"How's my network doing?"**
365
+ ```
366
+ → tool_batch: stats_site_health + client_list_active + alarm_count
367
+ ← WAN: healthy, 47 clients connected, 0 active alarms
368
+ ```
369
+
370
+ **"Block that sketchy device"**
371
+ ```
372
+ → client_get {"mac": "aa:bb:cc:dd:ee:ff"}
373
+ ← Device "Unknown-IoT" on VLAN 30, 2.3 GB today
374
+ → client_block {"mac": "aa:bb:cc:dd:ee:ff"}
375
+ ← Preview: Would block Unknown-IoT. Confirm?
376
+ → client_block {"mac": "aa:bb:cc:dd:ee:ff", "confirm": true}
377
+ ← Blocked.
378
+ ```
379
+
380
+ **"Create a guest voucher for 24 hours"**
381
+ ```
382
+ → hotspot_create_voucher {"expire_minutes": 1440, "quota": 1}
383
+ ← Preview: Would create 1 single-use voucher, 24h validity. Confirm?
384
+ → hotspot_create_voucher {"expire_minutes": 1440, "quota": 1, "confirm": true}
385
+ ← Voucher created: 83927-10458
386
+ ```
387
+
388
+ **"Which APs are on old firmware?"**
389
+ ```
390
+ → device_list_basic
391
+ ← 12 devices. Filtering by upgrade_available...
392
+ - Lobby AP (U6-Pro) — current: 6.6.55, available: 7.0.83
393
+ - Garage AP (U6-Lite) — current: 6.6.55, available: 7.0.83
394
+ ```
395
+
396
+ ---
397
+
398
+ ## License
399
+
400
+ MIT
401
+
402
+ ---
403
+
404
+ <p align="center">
405
+ <sub>Built for UniFi OS &nbsp;&bull;&nbsp; Supports Dream Machine, Cloud Gateway, and unifi.ui.com &nbsp;&bull;&nbsp; Not affiliated with Ubiquiti Inc.</sub>
406
+ </p>
Binary file
Binary file
Binary file
Binary file
package/install.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Postinstall script: copies the correct platform binary to bin/ames-unifi-mcp
4
+
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const os = require("os");
8
+
9
+ const BINARY_NAME = "ames-unifi-mcp";
10
+
11
+ const PLATFORM_MAP = {
12
+ "darwin-arm64": `${BINARY_NAME}-darwin-arm64`,
13
+ "darwin-x64": `${BINARY_NAME}-darwin-amd64`,
14
+ "linux-arm64": `${BINARY_NAME}-linux-arm64`,
15
+ "linux-x64": `${BINARY_NAME}-linux-amd64`,
16
+ };
17
+
18
+ function install() {
19
+ const platform = os.platform();
20
+ const arch = os.arch();
21
+ const key = `${platform}-${arch}`;
22
+
23
+ const binaryFile = PLATFORM_MAP[key];
24
+ if (!binaryFile) {
25
+ console.error(
26
+ `Unsupported platform: ${platform}-${arch}. ` +
27
+ `Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ const distDir = path.join(__dirname, "dist");
33
+ const binDir = path.join(__dirname, "bin");
34
+ const src = path.join(distDir, binaryFile);
35
+ const dest = path.join(binDir, BINARY_NAME);
36
+
37
+ if (!fs.existsSync(src)) {
38
+ console.error(`Binary not found: ${src}`);
39
+ console.error("Try rebuilding: make build-all");
40
+ process.exit(1);
41
+ }
42
+
43
+ // Ensure bin/ exists
44
+ if (!fs.existsSync(binDir)) {
45
+ fs.mkdirSync(binDir, { recursive: true });
46
+ }
47
+
48
+ // Copy binary
49
+ fs.copyFileSync(src, dest);
50
+
51
+ // Make executable
52
+ fs.chmodSync(dest, 0o755);
53
+
54
+ console.log(`Installed ${BINARY_NAME} for ${platform}/${arch}`);
55
+ }
56
+
57
+ install();
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "ames-unifi-mcp",
3
+ "version": "1.0.0",
4
+ "description": "UniFi Network MCP server — 310 tools for complete controller management via the Model Context Protocol",
5
+ "keywords": [
6
+ "mcp",
7
+ "unifi",
8
+ "ubiquiti",
9
+ "network",
10
+ "model-context-protocol",
11
+ "dream-machine",
12
+ "cloud-gateway",
13
+ "firewall",
14
+ "wifi",
15
+ "ai",
16
+ "claude",
17
+ "llm"
18
+ ],
19
+ "author": "Oliver Ames",
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/oliverames/ames-unifi-mcp.git"
24
+ },
25
+ "homepage": "https://github.com/oliverames/ames-unifi-mcp#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/oliverames/ames-unifi-mcp/issues"
28
+ },
29
+ "bin": {
30
+ "ames-unifi-mcp": "bin/ames-unifi-mcp"
31
+ },
32
+ "files": [
33
+ "dist/",
34
+ "install.js",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
38
+ "scripts": {
39
+ "postinstall": "node install.js"
40
+ },
41
+ "os": [
42
+ "darwin",
43
+ "linux"
44
+ ],
45
+ "cpu": [
46
+ "x64",
47
+ "arm64"
48
+ ],
49
+ "engines": {
50
+ "node": ">=16"
51
+ }
52
+ }