@owine/unifi-network-mcp 2.1.0 → 2.2.1
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/README.md +14 -4
- package/dist/tools/acl.js +21 -7
- package/dist/tools/devices.js +3 -2
- package/dist/tools/dns-policies.js +48 -12
- package/dist/tools/firewall.js +16 -2
- package/dist/tools/index.js +2 -0
- package/dist/tools/networks.js +14 -2
- package/dist/tools/switching.d.ts +3 -0
- package/dist/tools/switching.js +156 -0
- package/dist/tools/traffic-matching.js +4 -3
- package/dist/tools/wifi.js +221 -3
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UniFi Network MCP Server
|
|
2
2
|
|
|
3
|
-
An MCP (Model Context Protocol) server that exposes the UniFi Network Integration API as tools for Claude Code and other MCP clients. Provides
|
|
3
|
+
An MCP (Model Context Protocol) server that exposes the UniFi Network Integration API as tools for Claude Code and other MCP clients. Provides 74 tools for managing sites, devices, clients, networks, WiFi, firewalls, ACLs, switching, DNS policies, hotspot vouchers, VPNs, and more.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -76,7 +76,7 @@ This server provides layered safety controls for responsible operation:
|
|
|
76
76
|
- **Confirmation parameter** — The most dangerous tools (e.g., `unifi_remove_device`, `unifi_bulk_delete_vouchers`) require an explicit `confirm: true` parameter that must be present for the call to succeed
|
|
77
77
|
- **Dry-run support** — All write tools accept an optional `dryRun: true` parameter that returns a preview of the HTTP request (method, path, body) without making any changes
|
|
78
78
|
|
|
79
|
-
## Tools (
|
|
79
|
+
## Tools (74 total)
|
|
80
80
|
|
|
81
81
|
### System (1)
|
|
82
82
|
| Tool | Description |
|
|
@@ -136,7 +136,7 @@ This server provides layered safety controls for responsible operation:
|
|
|
136
136
|
| `unifi_delete_voucher` | **DESTRUCTIVE:** Delete a hotspot voucher |
|
|
137
137
|
| `unifi_bulk_delete_vouchers` | **DESTRUCTIVE:** Bulk delete vouchers matching a filter |
|
|
138
138
|
|
|
139
|
-
### Firewall Zones & Policies (
|
|
139
|
+
### Firewall Zones & Policies (13)
|
|
140
140
|
| Tool | Description |
|
|
141
141
|
|---|---|
|
|
142
142
|
| `unifi_list_firewall_zones` | List all firewall zones at a site |
|
|
@@ -156,7 +156,7 @@ This server provides layered safety controls for responsible operation:
|
|
|
156
156
|
### ACL Rules (7)
|
|
157
157
|
| Tool | Description |
|
|
158
158
|
|---|---|
|
|
159
|
-
| `unifi_list_acl_rules` | List all ACL
|
|
159
|
+
| `unifi_list_acl_rules` | List all ACL rules at a site |
|
|
160
160
|
| `unifi_get_acl_rule` | Get a specific ACL rule by ID |
|
|
161
161
|
| `unifi_get_acl_rule_ordering` | Get user-defined ACL rule ordering |
|
|
162
162
|
| `unifi_create_acl_rule` | Create a new ACL rule |
|
|
@@ -164,6 +164,16 @@ This server provides layered safety controls for responsible operation:
|
|
|
164
164
|
| `unifi_delete_acl_rule` | **DESTRUCTIVE:** Delete an ACL rule |
|
|
165
165
|
| `unifi_reorder_acl_rules` | Reorder user-defined ACL rules |
|
|
166
166
|
|
|
167
|
+
### Switching (6)
|
|
168
|
+
| Tool | Description |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `unifi_list_switch_stacks` | List all Switch Stacks at a site |
|
|
171
|
+
| `unifi_get_switch_stack` | Get details of a specific Switch Stack |
|
|
172
|
+
| `unifi_list_mc_lag_domains` | List all MC-LAG (Multi-Chassis LAG) Domains at a site |
|
|
173
|
+
| `unifi_get_mc_lag_domain` | Get details of a specific MC-LAG Domain |
|
|
174
|
+
| `unifi_list_lags` | List all LAGs (Link Aggregation Groups) at a site |
|
|
175
|
+
| `unifi_get_lag` | Get details of a specific LAG |
|
|
176
|
+
|
|
167
177
|
### DNS Policies (5)
|
|
168
178
|
| Tool | Description |
|
|
169
179
|
|---|---|
|
package/dist/tools/acl.js
CHANGED
|
@@ -7,7 +7,7 @@ const query_js_1 = require("../utils/query.js");
|
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
8
|
function registerAclTools(server, client, readOnly = false) {
|
|
9
9
|
server.registerTool("unifi_list_acl_rules", {
|
|
10
|
-
description: "List all ACL
|
|
10
|
+
description: "List all ACL rules at a site",
|
|
11
11
|
inputSchema: {
|
|
12
12
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
13
|
offset: zod_1.z
|
|
@@ -73,7 +73,7 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
73
73
|
if (readOnly)
|
|
74
74
|
return;
|
|
75
75
|
server.registerTool("unifi_create_acl_rule", {
|
|
76
|
-
description: "Create a new ACL
|
|
76
|
+
description: "Create a new ACL rule",
|
|
77
77
|
inputSchema: {
|
|
78
78
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
79
79
|
type: zod_1.z.enum(["IPV4", "MAC"]).describe("Rule type"),
|
|
@@ -115,20 +115,34 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
115
115
|
inputSchema: {
|
|
116
116
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
117
117
|
aclRuleId: zod_1.z.string().describe("ACL rule ID"),
|
|
118
|
-
|
|
118
|
+
type: zod_1.z.string().describe("ACL rule type"),
|
|
119
|
+
name: zod_1.z.string().describe("ACL rule name"),
|
|
120
|
+
enabled: zod_1.z.boolean().describe("Whether the rule is enabled"),
|
|
121
|
+
action: zod_1.z.string().describe("Rule action (ALLOW, DENY, etc.)"),
|
|
122
|
+
description: zod_1.z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe("Rule description"),
|
|
126
|
+
protocolFilter: zod_1.z
|
|
119
127
|
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
120
|
-
.
|
|
128
|
+
.optional()
|
|
129
|
+
.describe("Protocol filter configuration"),
|
|
121
130
|
dryRun: zod_1.z
|
|
122
131
|
.boolean()
|
|
123
132
|
.optional()
|
|
124
133
|
.describe("Preview this action without executing it"),
|
|
125
134
|
},
|
|
126
135
|
annotations: safety_js_1.WRITE,
|
|
127
|
-
}, async ({ siteId, aclRuleId,
|
|
136
|
+
}, async ({ siteId, aclRuleId, type, name, enabled, action, description, protocolFilter, dryRun }) => {
|
|
128
137
|
try {
|
|
138
|
+
const body = { type, name, enabled, action };
|
|
139
|
+
if (description !== undefined)
|
|
140
|
+
body.description = description;
|
|
141
|
+
if (protocolFilter !== undefined)
|
|
142
|
+
body.protocolFilter = protocolFilter;
|
|
129
143
|
if (dryRun)
|
|
130
|
-
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/acl-rules/${aclRuleId}`,
|
|
131
|
-
const data = await client.put(`/sites/${siteId}/acl-rules/${aclRuleId}`,
|
|
144
|
+
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/acl-rules/${aclRuleId}`, body);
|
|
145
|
+
const data = await client.put(`/sites/${siteId}/acl-rules/${aclRuleId}`, body);
|
|
132
146
|
return (0, responses_js_1.formatSuccess)(data);
|
|
133
147
|
}
|
|
134
148
|
catch (err) {
|
package/dist/tools/devices.js
CHANGED
|
@@ -104,13 +104,14 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
104
104
|
inputSchema: {
|
|
105
105
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
106
106
|
macAddress: zod_1.z.string().describe("MAC address of the device"),
|
|
107
|
+
ignoreDeviceLimit: zod_1.z.boolean().optional().describe("Ignore device limit when adopting (default: false)"),
|
|
107
108
|
dryRun: zod_1.z.boolean().optional().describe("Preview this action without executing it"),
|
|
108
109
|
},
|
|
109
110
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
110
|
-
}, async ({ siteId, macAddress, dryRun }) => {
|
|
111
|
+
}, async ({ siteId, macAddress, ignoreDeviceLimit, dryRun }) => {
|
|
111
112
|
const body = {
|
|
112
113
|
macAddress,
|
|
113
|
-
ignoreDeviceLimit: false,
|
|
114
|
+
ignoreDeviceLimit: ignoreDeviceLimit ?? false,
|
|
114
115
|
};
|
|
115
116
|
if (dryRun)
|
|
116
117
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/devices`, body);
|
|
@@ -61,20 +61,38 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
61
61
|
description: "Create a new DNS policy",
|
|
62
62
|
inputSchema: {
|
|
63
63
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
64
|
-
|
|
65
|
-
.
|
|
66
|
-
|
|
64
|
+
type: zod_1.z
|
|
65
|
+
.enum([
|
|
66
|
+
"A_RECORD",
|
|
67
|
+
"AAAA_RECORD",
|
|
68
|
+
"CNAME_RECORD",
|
|
69
|
+
"MX_RECORD",
|
|
70
|
+
"TXT_RECORD",
|
|
71
|
+
"SRV_RECORD",
|
|
72
|
+
"FORWARD_DOMAIN",
|
|
73
|
+
])
|
|
74
|
+
.describe("DNS record type"),
|
|
75
|
+
enabled: zod_1.z.boolean().describe("Whether the DNS policy is enabled"),
|
|
76
|
+
domain: zod_1.z.string().min(1).max(127).describe("Domain name"),
|
|
77
|
+
ipv4Address: zod_1.z.string().describe("IPv4 address for the record"),
|
|
78
|
+
ttlSeconds: zod_1.z
|
|
79
|
+
.number()
|
|
80
|
+
.int()
|
|
81
|
+
.min(0)
|
|
82
|
+
.max(86400)
|
|
83
|
+
.describe("Time to live in seconds"),
|
|
67
84
|
dryRun: zod_1.z
|
|
68
85
|
.boolean()
|
|
69
86
|
.optional()
|
|
70
87
|
.describe("Preview this action without executing it"),
|
|
71
88
|
},
|
|
72
89
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
73
|
-
}, async ({ siteId,
|
|
90
|
+
}, async ({ siteId, type, enabled, domain, ipv4Address, ttlSeconds, dryRun }) => {
|
|
74
91
|
try {
|
|
92
|
+
const body = { type, enabled, domain, ipv4Address, ttlSeconds };
|
|
75
93
|
if (dryRun)
|
|
76
|
-
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/dns/policies`,
|
|
77
|
-
const data = await client.post(`/sites/${siteId}/dns/policies`,
|
|
94
|
+
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/dns/policies`, body);
|
|
95
|
+
const data = await client.post(`/sites/${siteId}/dns/policies`, body);
|
|
78
96
|
return (0, responses_js_1.formatSuccess)(data);
|
|
79
97
|
}
|
|
80
98
|
catch (err) {
|
|
@@ -86,20 +104,38 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
86
104
|
inputSchema: {
|
|
87
105
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
88
106
|
dnsPolicyId: zod_1.z.string().describe("DNS policy ID"),
|
|
89
|
-
|
|
90
|
-
.
|
|
91
|
-
|
|
107
|
+
type: zod_1.z
|
|
108
|
+
.enum([
|
|
109
|
+
"A_RECORD",
|
|
110
|
+
"AAAA_RECORD",
|
|
111
|
+
"CNAME_RECORD",
|
|
112
|
+
"MX_RECORD",
|
|
113
|
+
"TXT_RECORD",
|
|
114
|
+
"SRV_RECORD",
|
|
115
|
+
"FORWARD_DOMAIN",
|
|
116
|
+
])
|
|
117
|
+
.describe("DNS record type"),
|
|
118
|
+
enabled: zod_1.z.boolean().describe("Whether the DNS policy is enabled"),
|
|
119
|
+
domain: zod_1.z.string().min(1).max(127).describe("Domain name"),
|
|
120
|
+
ipv4Address: zod_1.z.string().describe("IPv4 address for the record"),
|
|
121
|
+
ttlSeconds: zod_1.z
|
|
122
|
+
.number()
|
|
123
|
+
.int()
|
|
124
|
+
.min(0)
|
|
125
|
+
.max(86400)
|
|
126
|
+
.describe("Time to live in seconds"),
|
|
92
127
|
dryRun: zod_1.z
|
|
93
128
|
.boolean()
|
|
94
129
|
.optional()
|
|
95
130
|
.describe("Preview this action without executing it"),
|
|
96
131
|
},
|
|
97
132
|
annotations: safety_js_1.WRITE,
|
|
98
|
-
}, async ({ siteId, dnsPolicyId,
|
|
133
|
+
}, async ({ siteId, dnsPolicyId, type, enabled, domain, ipv4Address, ttlSeconds, dryRun }) => {
|
|
99
134
|
try {
|
|
135
|
+
const body = { type, enabled, domain, ipv4Address, ttlSeconds };
|
|
100
136
|
if (dryRun)
|
|
101
|
-
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/dns/policies/${dnsPolicyId}`,
|
|
102
|
-
const data = await client.put(`/sites/${siteId}/dns/policies/${dnsPolicyId}`,
|
|
137
|
+
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/dns/policies/${dnsPolicyId}`, body);
|
|
138
|
+
const data = await client.put(`/sites/${siteId}/dns/policies/${dnsPolicyId}`, body);
|
|
103
139
|
return (0, responses_js_1.formatSuccess)(data);
|
|
104
140
|
}
|
|
105
141
|
catch (err) {
|
package/dist/tools/firewall.js
CHANGED
|
@@ -108,15 +108,29 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
108
108
|
description: "Get user-defined firewall policy ordering for a zone pair",
|
|
109
109
|
inputSchema: {
|
|
110
110
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
111
|
-
sourceFirewallZoneId: zod_1.z
|
|
111
|
+
sourceFirewallZoneId: zod_1.z
|
|
112
|
+
.string()
|
|
113
|
+
.optional()
|
|
114
|
+
.describe("Source firewall zone ID"),
|
|
112
115
|
destinationFirewallZoneId: zod_1.z
|
|
113
116
|
.string()
|
|
117
|
+
.optional()
|
|
114
118
|
.describe("Destination firewall zone ID"),
|
|
115
119
|
},
|
|
116
120
|
annotations: safety_js_1.READ_ONLY,
|
|
117
121
|
}, async ({ siteId, sourceFirewallZoneId, destinationFirewallZoneId }) => {
|
|
118
122
|
try {
|
|
119
|
-
|
|
123
|
+
let query = "";
|
|
124
|
+
const params = new URLSearchParams();
|
|
125
|
+
if (sourceFirewallZoneId !== undefined) {
|
|
126
|
+
params.set("sourceFirewallZoneId", sourceFirewallZoneId);
|
|
127
|
+
}
|
|
128
|
+
if (destinationFirewallZoneId !== undefined) {
|
|
129
|
+
params.set("destinationFirewallZoneId", destinationFirewallZoneId);
|
|
130
|
+
}
|
|
131
|
+
const qs = params.toString();
|
|
132
|
+
if (qs)
|
|
133
|
+
query = `?${qs}`;
|
|
120
134
|
const data = await client.get(`/sites/${siteId}/firewall/policies/ordering${query}`);
|
|
121
135
|
return (0, responses_js_1.formatSuccess)(data);
|
|
122
136
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const firewall_js_1 = require("./firewall.js");
|
|
|
12
12
|
const acl_js_1 = require("./acl.js");
|
|
13
13
|
const dns_policies_js_1 = require("./dns-policies.js");
|
|
14
14
|
const traffic_matching_js_1 = require("./traffic-matching.js");
|
|
15
|
+
const switching_js_1 = require("./switching.js");
|
|
15
16
|
const supporting_js_1 = require("./supporting.js");
|
|
16
17
|
function registerAllTools(server, client, readOnly = false) {
|
|
17
18
|
(0, system_js_1.registerSystemTools)(server, client);
|
|
@@ -25,5 +26,6 @@ function registerAllTools(server, client, readOnly = false) {
|
|
|
25
26
|
(0, acl_js_1.registerAclTools)(server, client, readOnly);
|
|
26
27
|
(0, dns_policies_js_1.registerDnsPolicyTools)(server, client, readOnly);
|
|
27
28
|
(0, traffic_matching_js_1.registerTrafficMatchingTools)(server, client, readOnly);
|
|
29
|
+
(0, switching_js_1.registerSwitchingTools)(server, client);
|
|
28
30
|
(0, supporting_js_1.registerSupportingTools)(server, client);
|
|
29
31
|
}
|
package/dist/tools/networks.js
CHANGED
|
@@ -88,15 +88,21 @@ function registerNetworkTools(server, client, readOnly = false) {
|
|
|
88
88
|
.min(1)
|
|
89
89
|
.max(4009)
|
|
90
90
|
.describe("VLAN ID (1 for default, 2+ for additional)"),
|
|
91
|
+
dhcpGuarding: zod_1.z
|
|
92
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
93
|
+
.optional()
|
|
94
|
+
.describe("DHCP Guarding settings (trustedDhcpServerIpAddresses)"),
|
|
91
95
|
dryRun: zod_1.z
|
|
92
96
|
.boolean()
|
|
93
97
|
.optional()
|
|
94
98
|
.describe("Preview this action without executing it"),
|
|
95
99
|
},
|
|
96
100
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
97
|
-
}, async ({ siteId, name, management, enabled, vlanId, dryRun }) => {
|
|
101
|
+
}, async ({ siteId, name, management, enabled, vlanId, dhcpGuarding, dryRun }) => {
|
|
98
102
|
try {
|
|
99
103
|
const body = { name, management, enabled, vlanId };
|
|
104
|
+
if (dhcpGuarding !== undefined)
|
|
105
|
+
body.dhcpGuarding = dhcpGuarding;
|
|
100
106
|
if (dryRun)
|
|
101
107
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/networks`, body);
|
|
102
108
|
const data = await client.post(`/sites/${siteId}/networks`, body);
|
|
@@ -122,15 +128,21 @@ function registerNetworkTools(server, client, readOnly = false) {
|
|
|
122
128
|
.min(1)
|
|
123
129
|
.max(4009)
|
|
124
130
|
.describe("VLAN ID (1-4009)"),
|
|
131
|
+
dhcpGuarding: zod_1.z
|
|
132
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
133
|
+
.optional()
|
|
134
|
+
.describe("DHCP Guarding settings (trustedDhcpServerIpAddresses)"),
|
|
125
135
|
dryRun: zod_1.z
|
|
126
136
|
.boolean()
|
|
127
137
|
.optional()
|
|
128
138
|
.describe("Preview this action without executing it"),
|
|
129
139
|
},
|
|
130
140
|
annotations: safety_js_1.WRITE,
|
|
131
|
-
}, async ({ siteId, networkId, name, management, enabled, vlanId, dryRun }) => {
|
|
141
|
+
}, async ({ siteId, networkId, name, management, enabled, vlanId, dhcpGuarding, dryRun }) => {
|
|
132
142
|
try {
|
|
133
143
|
const body = { name, management, enabled, vlanId };
|
|
144
|
+
if (dhcpGuarding !== undefined)
|
|
145
|
+
body.dhcpGuarding = dhcpGuarding;
|
|
134
146
|
if (dryRun)
|
|
135
147
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/networks/${networkId}`, body);
|
|
136
148
|
const data = await client.put(`/sites/${siteId}/networks/${networkId}`, body);
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerSwitchingTools = registerSwitchingTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const responses_js_1 = require("../utils/responses.js");
|
|
6
|
+
const query_js_1 = require("../utils/query.js");
|
|
7
|
+
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
function registerSwitchingTools(server, client) {
|
|
9
|
+
server.registerTool("unifi_list_switch_stacks", {
|
|
10
|
+
description: "List all Switch Stacks at a site",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
|
+
offset: zod_1.z
|
|
14
|
+
.number()
|
|
15
|
+
.int()
|
|
16
|
+
.nonnegative()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Number of records to skip (default: 0)"),
|
|
19
|
+
limit: zod_1.z
|
|
20
|
+
.number()
|
|
21
|
+
.int()
|
|
22
|
+
.min(1)
|
|
23
|
+
.max(200)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Number of records to return (default: 25, max: 200)"),
|
|
26
|
+
filter: zod_1.z
|
|
27
|
+
.string()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Filter expression"),
|
|
30
|
+
},
|
|
31
|
+
annotations: safety_js_1.READ_ONLY,
|
|
32
|
+
}, async ({ siteId, offset, limit, filter }) => {
|
|
33
|
+
try {
|
|
34
|
+
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
35
|
+
const data = await client.get(`/sites/${siteId}/switching/switch-stacks${query}`);
|
|
36
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return (0, responses_js_1.formatError)(err);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
server.registerTool("unifi_get_switch_stack", {
|
|
43
|
+
description: "Get details of a specific Switch Stack",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
46
|
+
switchStackId: zod_1.z.string().describe("Switch Stack ID"),
|
|
47
|
+
},
|
|
48
|
+
annotations: safety_js_1.READ_ONLY,
|
|
49
|
+
}, async ({ siteId, switchStackId }) => {
|
|
50
|
+
try {
|
|
51
|
+
const data = await client.get(`/sites/${siteId}/switching/switch-stacks/${switchStackId}`);
|
|
52
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
return (0, responses_js_1.formatError)(err);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
server.registerTool("unifi_list_mc_lag_domains", {
|
|
59
|
+
description: "List all MC-LAG (Multi-Chassis LAG) Domains at a site",
|
|
60
|
+
inputSchema: {
|
|
61
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
62
|
+
offset: zod_1.z
|
|
63
|
+
.number()
|
|
64
|
+
.int()
|
|
65
|
+
.nonnegative()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Number of records to skip (default: 0)"),
|
|
68
|
+
limit: zod_1.z
|
|
69
|
+
.number()
|
|
70
|
+
.int()
|
|
71
|
+
.min(1)
|
|
72
|
+
.max(200)
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("Number of records to return (default: 25, max: 200)"),
|
|
75
|
+
filter: zod_1.z
|
|
76
|
+
.string()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("Filter expression"),
|
|
79
|
+
},
|
|
80
|
+
annotations: safety_js_1.READ_ONLY,
|
|
81
|
+
}, async ({ siteId, offset, limit, filter }) => {
|
|
82
|
+
try {
|
|
83
|
+
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
84
|
+
const data = await client.get(`/sites/${siteId}/switching/mc-lag-domains${query}`);
|
|
85
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
return (0, responses_js_1.formatError)(err);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
server.registerTool("unifi_get_mc_lag_domain", {
|
|
92
|
+
description: "Get details of a specific MC-LAG (Multi-Chassis LAG) Domain",
|
|
93
|
+
inputSchema: {
|
|
94
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
95
|
+
mcLagDomainId: zod_1.z.string().describe("MC-LAG Domain ID"),
|
|
96
|
+
},
|
|
97
|
+
annotations: safety_js_1.READ_ONLY,
|
|
98
|
+
}, async ({ siteId, mcLagDomainId }) => {
|
|
99
|
+
try {
|
|
100
|
+
const data = await client.get(`/sites/${siteId}/switching/mc-lag-domains/${mcLagDomainId}`);
|
|
101
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return (0, responses_js_1.formatError)(err);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
server.registerTool("unifi_list_lags", {
|
|
108
|
+
description: "List all LAGs (Link Aggregation Groups) at a site",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
111
|
+
offset: zod_1.z
|
|
112
|
+
.number()
|
|
113
|
+
.int()
|
|
114
|
+
.nonnegative()
|
|
115
|
+
.optional()
|
|
116
|
+
.describe("Number of records to skip (default: 0)"),
|
|
117
|
+
limit: zod_1.z
|
|
118
|
+
.number()
|
|
119
|
+
.int()
|
|
120
|
+
.min(1)
|
|
121
|
+
.max(200)
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Number of records to return (default: 25, max: 200)"),
|
|
124
|
+
filter: zod_1.z
|
|
125
|
+
.string()
|
|
126
|
+
.optional()
|
|
127
|
+
.describe("Filter expression"),
|
|
128
|
+
},
|
|
129
|
+
annotations: safety_js_1.READ_ONLY,
|
|
130
|
+
}, async ({ siteId, offset, limit, filter }) => {
|
|
131
|
+
try {
|
|
132
|
+
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
133
|
+
const data = await client.get(`/sites/${siteId}/switching/lags${query}`);
|
|
134
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
return (0, responses_js_1.formatError)(err);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
server.registerTool("unifi_get_lag", {
|
|
141
|
+
description: "Get details of a specific LAG (Link Aggregation Group)",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
siteId: zod_1.z.string().describe("Site ID"),
|
|
144
|
+
lagId: zod_1.z.string().describe("LAG ID"),
|
|
145
|
+
},
|
|
146
|
+
annotations: safety_js_1.READ_ONLY,
|
|
147
|
+
}, async ({ siteId, lagId }) => {
|
|
148
|
+
try {
|
|
149
|
+
const data = await client.get(`/sites/${siteId}/switching/lags/${lagId}`);
|
|
150
|
+
return (0, responses_js_1.formatSuccess)(data);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
return (0, responses_js_1.formatError)(err);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
@@ -64,9 +64,10 @@ function registerTrafficMatchingTools(server, client, readOnly = false) {
|
|
|
64
64
|
type: zod_1.z
|
|
65
65
|
.enum(["PORTS", "IPV4_ADDRESSES", "IPV6_ADDRESSES"])
|
|
66
66
|
.describe("List type"),
|
|
67
|
-
name: zod_1.z.string().describe("List name"),
|
|
67
|
+
name: zod_1.z.string().min(1).describe("List name"),
|
|
68
68
|
items: zod_1.z
|
|
69
69
|
.array(zod_1.z.unknown())
|
|
70
|
+
.min(1)
|
|
70
71
|
.describe("List items (ports or IP addresses)"),
|
|
71
72
|
dryRun: zod_1.z
|
|
72
73
|
.boolean()
|
|
@@ -94,8 +95,8 @@ function registerTrafficMatchingTools(server, client, readOnly = false) {
|
|
|
94
95
|
type: zod_1.z
|
|
95
96
|
.enum(["PORTS", "IPV4_ADDRESSES", "IPV6_ADDRESSES"])
|
|
96
97
|
.describe("List type"),
|
|
97
|
-
name: zod_1.z.string().describe("List name"),
|
|
98
|
-
items: zod_1.z.array(zod_1.z.unknown()).describe("List items"),
|
|
98
|
+
name: zod_1.z.string().min(1).describe("List name"),
|
|
99
|
+
items: zod_1.z.array(zod_1.z.unknown()).min(1).describe("List items"),
|
|
99
100
|
dryRun: zod_1.z
|
|
100
101
|
.boolean()
|
|
101
102
|
.optional()
|
package/dist/tools/wifi.js
CHANGED
|
@@ -63,24 +63,118 @@ function registerWifiTools(server, client, readOnly = false) {
|
|
|
63
63
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
64
64
|
name: zod_1.z.string().describe("SSID name"),
|
|
65
65
|
enabled: zod_1.z.boolean().describe("Enable the WiFi network"),
|
|
66
|
-
type: zod_1.z.enum(["STANDARD"]).describe("WiFi type"),
|
|
66
|
+
type: zod_1.z.enum(["STANDARD", "IOT_OPTIMIZED"]).describe("WiFi type"),
|
|
67
67
|
broadcastingFrequenciesGHz: zod_1.z
|
|
68
68
|
.array(zod_1.z.string())
|
|
69
69
|
.describe("Frequencies: 2.4, 5, 6"),
|
|
70
|
+
securityConfiguration: zod_1.z
|
|
71
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
72
|
+
.describe("Security configuration object"),
|
|
73
|
+
multicastToUnicastConversionEnabled: zod_1.z
|
|
74
|
+
.boolean()
|
|
75
|
+
.describe("Enable multicast to unicast conversion"),
|
|
76
|
+
clientIsolationEnabled: zod_1.z
|
|
77
|
+
.boolean()
|
|
78
|
+
.describe("Enable client isolation"),
|
|
79
|
+
hideName: zod_1.z.boolean().describe("Hide SSID name"),
|
|
80
|
+
uapsdEnabled: zod_1.z
|
|
81
|
+
.boolean()
|
|
82
|
+
.describe("Enable Unscheduled Automatic Power Save Delivery"),
|
|
83
|
+
arpProxyEnabled: zod_1.z.boolean().describe("Enable ARP proxy"),
|
|
84
|
+
bssTransitionEnabled: zod_1.z
|
|
85
|
+
.boolean()
|
|
86
|
+
.describe("Enable BSS transition"),
|
|
87
|
+
advertiseDeviceName: zod_1.z
|
|
88
|
+
.boolean()
|
|
89
|
+
.describe("Advertise device name in beacon frames"),
|
|
90
|
+
network: zod_1.z
|
|
91
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
92
|
+
.optional()
|
|
93
|
+
.describe("Network reference"),
|
|
94
|
+
broadcastingDeviceFilter: zod_1.z
|
|
95
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("Custom scope of broadcasting devices"),
|
|
98
|
+
mdnsProxyConfiguration: zod_1.z
|
|
99
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
100
|
+
.optional()
|
|
101
|
+
.describe("mDNS proxy configuration"),
|
|
102
|
+
multicastFilteringPolicy: zod_1.z
|
|
103
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
104
|
+
.optional()
|
|
105
|
+
.describe("Multicast filtering policy"),
|
|
106
|
+
basicDataRateKbpsByFrequencyGHz: zod_1.z
|
|
107
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("Basic data rate in kbps by frequency"),
|
|
110
|
+
clientFilteringPolicy: zod_1.z
|
|
111
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("Client MAC address filtering policy"),
|
|
114
|
+
blackoutScheduleConfiguration: zod_1.z
|
|
115
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
116
|
+
.optional()
|
|
117
|
+
.describe("Blackout schedule configuration"),
|
|
118
|
+
hotspotConfiguration: zod_1.z
|
|
119
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
120
|
+
.optional()
|
|
121
|
+
.describe("Hotspot configuration"),
|
|
122
|
+
mloEnabled: zod_1.z
|
|
123
|
+
.boolean()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe("Enable MLO (Multi-Link Operation)"),
|
|
126
|
+
bandSteeringEnabled: zod_1.z
|
|
127
|
+
.boolean()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe("Enable band steering"),
|
|
130
|
+
dtimPeriodByFrequencyGHzOverride: zod_1.z
|
|
131
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
132
|
+
.optional()
|
|
133
|
+
.describe("DTIM period override by frequency"),
|
|
70
134
|
dryRun: zod_1.z
|
|
71
135
|
.boolean()
|
|
72
136
|
.optional()
|
|
73
137
|
.describe("Preview this action without executing it"),
|
|
74
138
|
},
|
|
75
139
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
76
|
-
}, async ({ siteId, name, enabled, type, broadcastingFrequenciesGHz, dryRun, }) => {
|
|
140
|
+
}, async ({ siteId, name, enabled, type, broadcastingFrequenciesGHz, securityConfiguration, multicastToUnicastConversionEnabled, clientIsolationEnabled, hideName, uapsdEnabled, arpProxyEnabled, bssTransitionEnabled, advertiseDeviceName, network, broadcastingDeviceFilter, mdnsProxyConfiguration, multicastFilteringPolicy, basicDataRateKbpsByFrequencyGHz, clientFilteringPolicy, blackoutScheduleConfiguration, hotspotConfiguration, mloEnabled, bandSteeringEnabled, dtimPeriodByFrequencyGHzOverride, dryRun, }) => {
|
|
77
141
|
try {
|
|
78
142
|
const body = {
|
|
79
143
|
name,
|
|
80
144
|
enabled,
|
|
81
145
|
type,
|
|
82
146
|
broadcastingFrequenciesGHz: broadcastingFrequenciesGHz.map(Number),
|
|
147
|
+
securityConfiguration,
|
|
148
|
+
multicastToUnicastConversionEnabled,
|
|
149
|
+
clientIsolationEnabled,
|
|
150
|
+
hideName,
|
|
151
|
+
uapsdEnabled,
|
|
152
|
+
arpProxyEnabled,
|
|
153
|
+
bssTransitionEnabled,
|
|
154
|
+
advertiseDeviceName,
|
|
83
155
|
};
|
|
156
|
+
if (network !== undefined)
|
|
157
|
+
body.network = network;
|
|
158
|
+
if (broadcastingDeviceFilter !== undefined)
|
|
159
|
+
body.broadcastingDeviceFilter = broadcastingDeviceFilter;
|
|
160
|
+
if (mdnsProxyConfiguration !== undefined)
|
|
161
|
+
body.mdnsProxyConfiguration = mdnsProxyConfiguration;
|
|
162
|
+
if (multicastFilteringPolicy !== undefined)
|
|
163
|
+
body.multicastFilteringPolicy = multicastFilteringPolicy;
|
|
164
|
+
if (basicDataRateKbpsByFrequencyGHz !== undefined)
|
|
165
|
+
body.basicDataRateKbpsByFrequencyGHz = basicDataRateKbpsByFrequencyGHz;
|
|
166
|
+
if (clientFilteringPolicy !== undefined)
|
|
167
|
+
body.clientFilteringPolicy = clientFilteringPolicy;
|
|
168
|
+
if (blackoutScheduleConfiguration !== undefined)
|
|
169
|
+
body.blackoutScheduleConfiguration = blackoutScheduleConfiguration;
|
|
170
|
+
if (hotspotConfiguration !== undefined)
|
|
171
|
+
body.hotspotConfiguration = hotspotConfiguration;
|
|
172
|
+
if (mloEnabled !== undefined)
|
|
173
|
+
body.mloEnabled = mloEnabled;
|
|
174
|
+
if (bandSteeringEnabled !== undefined)
|
|
175
|
+
body.bandSteeringEnabled = bandSteeringEnabled;
|
|
176
|
+
if (dtimPeriodByFrequencyGHzOverride !== undefined)
|
|
177
|
+
body.dtimPeriodByFrequencyGHzOverride = dtimPeriodByFrequencyGHzOverride;
|
|
84
178
|
if (dryRun)
|
|
85
179
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/wifi/broadcasts`, body);
|
|
86
180
|
const data = await client.post(`/sites/${siteId}/wifi/broadcasts`, body);
|
|
@@ -97,19 +191,143 @@ function registerWifiTools(server, client, readOnly = false) {
|
|
|
97
191
|
wifiBroadcastId: zod_1.z.string().describe("WiFi Broadcast ID"),
|
|
98
192
|
name: zod_1.z.string().optional().describe("SSID name"),
|
|
99
193
|
enabled: zod_1.z.boolean().optional().describe("Enable the WiFi network"),
|
|
194
|
+
type: zod_1.z
|
|
195
|
+
.enum(["STANDARD", "IOT_OPTIMIZED"])
|
|
196
|
+
.optional()
|
|
197
|
+
.describe("WiFi type"),
|
|
198
|
+
broadcastingFrequenciesGHz: zod_1.z
|
|
199
|
+
.array(zod_1.z.string())
|
|
200
|
+
.optional()
|
|
201
|
+
.describe("Frequencies: 2.4, 5, 6"),
|
|
202
|
+
securityConfiguration: zod_1.z
|
|
203
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
204
|
+
.optional()
|
|
205
|
+
.describe("Security configuration object"),
|
|
206
|
+
multicastToUnicastConversionEnabled: zod_1.z
|
|
207
|
+
.boolean()
|
|
208
|
+
.optional()
|
|
209
|
+
.describe("Enable multicast to unicast conversion"),
|
|
210
|
+
clientIsolationEnabled: zod_1.z
|
|
211
|
+
.boolean()
|
|
212
|
+
.optional()
|
|
213
|
+
.describe("Enable client isolation"),
|
|
214
|
+
hideName: zod_1.z.boolean().optional().describe("Hide SSID name"),
|
|
215
|
+
uapsdEnabled: zod_1.z
|
|
216
|
+
.boolean()
|
|
217
|
+
.optional()
|
|
218
|
+
.describe("Enable Unscheduled Automatic Power Save Delivery"),
|
|
219
|
+
arpProxyEnabled: zod_1.z
|
|
220
|
+
.boolean()
|
|
221
|
+
.optional()
|
|
222
|
+
.describe("Enable ARP proxy"),
|
|
223
|
+
bssTransitionEnabled: zod_1.z
|
|
224
|
+
.boolean()
|
|
225
|
+
.optional()
|
|
226
|
+
.describe("Enable BSS transition"),
|
|
227
|
+
advertiseDeviceName: zod_1.z
|
|
228
|
+
.boolean()
|
|
229
|
+
.optional()
|
|
230
|
+
.describe("Advertise device name in beacon frames"),
|
|
231
|
+
network: zod_1.z
|
|
232
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
233
|
+
.optional()
|
|
234
|
+
.describe("Network reference"),
|
|
235
|
+
broadcastingDeviceFilter: zod_1.z
|
|
236
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
237
|
+
.optional()
|
|
238
|
+
.describe("Custom scope of broadcasting devices"),
|
|
239
|
+
mdnsProxyConfiguration: zod_1.z
|
|
240
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
241
|
+
.optional()
|
|
242
|
+
.describe("mDNS proxy configuration"),
|
|
243
|
+
multicastFilteringPolicy: zod_1.z
|
|
244
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
245
|
+
.optional()
|
|
246
|
+
.describe("Multicast filtering policy"),
|
|
247
|
+
basicDataRateKbpsByFrequencyGHz: zod_1.z
|
|
248
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
249
|
+
.optional()
|
|
250
|
+
.describe("Basic data rate in kbps by frequency"),
|
|
251
|
+
clientFilteringPolicy: zod_1.z
|
|
252
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
253
|
+
.optional()
|
|
254
|
+
.describe("Client MAC address filtering policy"),
|
|
255
|
+
blackoutScheduleConfiguration: zod_1.z
|
|
256
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
257
|
+
.optional()
|
|
258
|
+
.describe("Blackout schedule configuration"),
|
|
259
|
+
hotspotConfiguration: zod_1.z
|
|
260
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
261
|
+
.optional()
|
|
262
|
+
.describe("Hotspot configuration"),
|
|
263
|
+
mloEnabled: zod_1.z
|
|
264
|
+
.boolean()
|
|
265
|
+
.optional()
|
|
266
|
+
.describe("Enable MLO (Multi-Link Operation)"),
|
|
267
|
+
bandSteeringEnabled: zod_1.z
|
|
268
|
+
.boolean()
|
|
269
|
+
.optional()
|
|
270
|
+
.describe("Enable band steering"),
|
|
271
|
+
dtimPeriodByFrequencyGHzOverride: zod_1.z
|
|
272
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
273
|
+
.optional()
|
|
274
|
+
.describe("DTIM period override by frequency"),
|
|
100
275
|
dryRun: zod_1.z
|
|
101
276
|
.boolean()
|
|
102
277
|
.optional()
|
|
103
278
|
.describe("Preview this action without executing it"),
|
|
104
279
|
},
|
|
105
280
|
annotations: safety_js_1.WRITE,
|
|
106
|
-
}, async ({ siteId, wifiBroadcastId, name, enabled, dryRun }) => {
|
|
281
|
+
}, async ({ siteId, wifiBroadcastId, name, enabled, type, broadcastingFrequenciesGHz, securityConfiguration, multicastToUnicastConversionEnabled, clientIsolationEnabled, hideName, uapsdEnabled, arpProxyEnabled, bssTransitionEnabled, advertiseDeviceName, network, broadcastingDeviceFilter, mdnsProxyConfiguration, multicastFilteringPolicy, basicDataRateKbpsByFrequencyGHz, clientFilteringPolicy, blackoutScheduleConfiguration, hotspotConfiguration, mloEnabled, bandSteeringEnabled, dtimPeriodByFrequencyGHzOverride, dryRun, }) => {
|
|
107
282
|
try {
|
|
108
283
|
const body = {};
|
|
109
284
|
if (name !== undefined)
|
|
110
285
|
body.name = name;
|
|
111
286
|
if (enabled !== undefined)
|
|
112
287
|
body.enabled = enabled;
|
|
288
|
+
if (type !== undefined)
|
|
289
|
+
body.type = type;
|
|
290
|
+
if (broadcastingFrequenciesGHz !== undefined)
|
|
291
|
+
body.broadcastingFrequenciesGHz = broadcastingFrequenciesGHz.map(Number);
|
|
292
|
+
if (securityConfiguration !== undefined)
|
|
293
|
+
body.securityConfiguration = securityConfiguration;
|
|
294
|
+
if (multicastToUnicastConversionEnabled !== undefined)
|
|
295
|
+
body.multicastToUnicastConversionEnabled =
|
|
296
|
+
multicastToUnicastConversionEnabled;
|
|
297
|
+
if (clientIsolationEnabled !== undefined)
|
|
298
|
+
body.clientIsolationEnabled = clientIsolationEnabled;
|
|
299
|
+
if (hideName !== undefined)
|
|
300
|
+
body.hideName = hideName;
|
|
301
|
+
if (uapsdEnabled !== undefined)
|
|
302
|
+
body.uapsdEnabled = uapsdEnabled;
|
|
303
|
+
if (arpProxyEnabled !== undefined)
|
|
304
|
+
body.arpProxyEnabled = arpProxyEnabled;
|
|
305
|
+
if (bssTransitionEnabled !== undefined)
|
|
306
|
+
body.bssTransitionEnabled = bssTransitionEnabled;
|
|
307
|
+
if (advertiseDeviceName !== undefined)
|
|
308
|
+
body.advertiseDeviceName = advertiseDeviceName;
|
|
309
|
+
if (network !== undefined)
|
|
310
|
+
body.network = network;
|
|
311
|
+
if (broadcastingDeviceFilter !== undefined)
|
|
312
|
+
body.broadcastingDeviceFilter = broadcastingDeviceFilter;
|
|
313
|
+
if (mdnsProxyConfiguration !== undefined)
|
|
314
|
+
body.mdnsProxyConfiguration = mdnsProxyConfiguration;
|
|
315
|
+
if (multicastFilteringPolicy !== undefined)
|
|
316
|
+
body.multicastFilteringPolicy = multicastFilteringPolicy;
|
|
317
|
+
if (basicDataRateKbpsByFrequencyGHz !== undefined)
|
|
318
|
+
body.basicDataRateKbpsByFrequencyGHz = basicDataRateKbpsByFrequencyGHz;
|
|
319
|
+
if (clientFilteringPolicy !== undefined)
|
|
320
|
+
body.clientFilteringPolicy = clientFilteringPolicy;
|
|
321
|
+
if (blackoutScheduleConfiguration !== undefined)
|
|
322
|
+
body.blackoutScheduleConfiguration = blackoutScheduleConfiguration;
|
|
323
|
+
if (hotspotConfiguration !== undefined)
|
|
324
|
+
body.hotspotConfiguration = hotspotConfiguration;
|
|
325
|
+
if (mloEnabled !== undefined)
|
|
326
|
+
body.mloEnabled = mloEnabled;
|
|
327
|
+
if (bandSteeringEnabled !== undefined)
|
|
328
|
+
body.bandSteeringEnabled = bandSteeringEnabled;
|
|
329
|
+
if (dtimPeriodByFrequencyGHzOverride !== undefined)
|
|
330
|
+
body.dtimPeriodByFrequencyGHzOverride = dtimPeriodByFrequencyGHzOverride;
|
|
113
331
|
if (dryRun)
|
|
114
332
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/wifi/broadcasts/${wifiBroadcastId}`, body);
|
|
115
333
|
const data = await client.put(`/sites/${siteId}/wifi/broadcasts/${wifiBroadcastId}`, body);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owine/unifi-network-mcp",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "MCP server for the UniFi Network API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@eslint/js": "10.0.1",
|
|
44
44
|
"@types/node": "24.12.0",
|
|
45
|
-
"@vitest/coverage-v8": "4.
|
|
46
|
-
"eslint": "10.0
|
|
45
|
+
"@vitest/coverage-v8": "4.1.2",
|
|
46
|
+
"eslint": "10.1.0",
|
|
47
47
|
"typescript": "5.9.3",
|
|
48
|
-
"typescript-eslint": "8.
|
|
49
|
-
"vitest": "4.
|
|
48
|
+
"typescript-eslint": "8.57.2",
|
|
49
|
+
"vitest": "4.1.2"
|
|
50
50
|
}
|
|
51
51
|
}
|