@owine/unifi-network-mcp 2.5.0 → 2.7.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/dist/tools/acl.js +14 -8
- package/dist/tools/clients.js +9 -6
- package/dist/tools/devices.js +20 -12
- package/dist/tools/dns-policies.js +11 -6
- package/dist/tools/firewall.js +27 -16
- package/dist/tools/hotspot.js +10 -6
- package/dist/tools/networks.js +15 -9
- package/dist/tools/sites.js +4 -2
- package/dist/tools/supporting.js +25 -16
- package/dist/tools/switching.js +19 -12
- package/dist/tools/system.js +4 -2
- package/dist/tools/traffic-matching.js +11 -6
- package/dist/tools/wifi.js +11 -6
- package/dist/utils/output-schemas.d.ts +611 -0
- package/dist/utils/output-schemas.js +507 -0
- package/dist/utils/responses.d.ts +4 -1
- package/dist/utils/responses.js +10 -5
- package/package.json +5 -4
package/dist/tools/acl.js
CHANGED
|
@@ -5,9 +5,10 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
8
9
|
function registerAclTools(server, client, readOnly = false) {
|
|
9
10
|
server.registerTool("unifi_list_acl_rules", {
|
|
10
|
-
description: "List
|
|
11
|
+
description: "List ACL rules (switch/AP-level access control lists, distinct from zone-based firewall policies) at a site. Returns: id, type (IPV4/MAC), name, enabled, action (ALLOW/BLOCK), description, protocolFilter, source/destination matchers. ACLs apply earlier in the path than firewall policies.",
|
|
11
12
|
inputSchema: {
|
|
12
13
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
14
|
offset: zod_1.z
|
|
@@ -28,43 +29,46 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
28
29
|
.optional()
|
|
29
30
|
.describe("Filter expression"),
|
|
30
31
|
},
|
|
32
|
+
outputSchema: output_schemas_js_1.listAclRulesOutputSchema,
|
|
31
33
|
annotations: safety_js_1.READ_ONLY,
|
|
32
34
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
33
35
|
try {
|
|
34
36
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
35
37
|
const data = await client.get(`/sites/${siteId}/acl-rules${query}`);
|
|
36
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
38
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
37
39
|
}
|
|
38
40
|
catch (err) {
|
|
39
41
|
return (0, responses_js_1.formatError)(err);
|
|
40
42
|
}
|
|
41
43
|
});
|
|
42
44
|
server.registerTool("unifi_get_acl_rule", {
|
|
43
|
-
description: "Get a specific ACL rule by ID",
|
|
45
|
+
description: "Get a specific ACL rule by ID (full match criteria and action).",
|
|
44
46
|
inputSchema: {
|
|
45
47
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
46
48
|
aclRuleId: zod_1.z.string().describe("ACL rule ID"),
|
|
47
49
|
},
|
|
50
|
+
outputSchema: output_schemas_js_1.aclRuleOutputSchema,
|
|
48
51
|
annotations: safety_js_1.READ_ONLY,
|
|
49
52
|
}, async ({ siteId, aclRuleId }) => {
|
|
50
53
|
try {
|
|
51
54
|
const data = await client.get(`/sites/${siteId}/acl-rules/${aclRuleId}`);
|
|
52
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
55
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
53
56
|
}
|
|
54
57
|
catch (err) {
|
|
55
58
|
return (0, responses_js_1.formatError)(err);
|
|
56
59
|
}
|
|
57
60
|
});
|
|
58
61
|
server.registerTool("unifi_get_acl_rule_ordering", {
|
|
59
|
-
description: "Get user-defined ACL
|
|
62
|
+
description: "Get the evaluation order of user-defined ACL rules. Returns: orderedAclRuleIds[]. Rules higher in the list win.",
|
|
60
63
|
inputSchema: {
|
|
61
64
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
62
65
|
},
|
|
66
|
+
outputSchema: output_schemas_js_1.aclRuleOrderingOutputSchema,
|
|
63
67
|
annotations: safety_js_1.READ_ONLY,
|
|
64
68
|
}, async ({ siteId }) => {
|
|
65
69
|
try {
|
|
66
70
|
const data = await client.get(`/sites/${siteId}/acl-rules/ordering`);
|
|
67
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
71
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
68
72
|
}
|
|
69
73
|
catch (err) {
|
|
70
74
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -93,6 +97,7 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
93
97
|
.optional()
|
|
94
98
|
.describe("Preview this action without executing it"),
|
|
95
99
|
},
|
|
100
|
+
outputSchema: output_schemas_js_1.aclRuleOutputSchema,
|
|
96
101
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
97
102
|
}, async ({ siteId, type, name, enabled, action, description, protocolFilter, dryRun }) => {
|
|
98
103
|
try {
|
|
@@ -104,7 +109,7 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
104
109
|
if (dryRun)
|
|
105
110
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/acl-rules`, body);
|
|
106
111
|
const data = await client.post(`/sites/${siteId}/acl-rules`, body);
|
|
107
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
112
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
108
113
|
}
|
|
109
114
|
catch (err) {
|
|
110
115
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -132,6 +137,7 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
132
137
|
.optional()
|
|
133
138
|
.describe("Preview this action without executing it"),
|
|
134
139
|
},
|
|
140
|
+
outputSchema: output_schemas_js_1.aclRuleOutputSchema,
|
|
135
141
|
annotations: safety_js_1.WRITE,
|
|
136
142
|
}, async ({ siteId, aclRuleId, type, name, enabled, action, description, protocolFilter, dryRun }) => {
|
|
137
143
|
try {
|
|
@@ -143,7 +149,7 @@ function registerAclTools(server, client, readOnly = false) {
|
|
|
143
149
|
if (dryRun)
|
|
144
150
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/acl-rules/${aclRuleId}`, body);
|
|
145
151
|
const data = await client.put(`/sites/${siteId}/acl-rules/${aclRuleId}`, body);
|
|
146
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
152
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
147
153
|
}
|
|
148
154
|
catch (err) {
|
|
149
155
|
return (0, responses_js_1.formatError)(err);
|
package/dist/tools/clients.js
CHANGED
|
@@ -5,9 +5,10 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
8
9
|
function registerClientTools(server, client, readOnly = false) {
|
|
9
10
|
server.registerTool("unifi_list_clients", {
|
|
10
|
-
description: "List
|
|
11
|
+
description: "List currently connected clients at a site. Returns per client: id, name, type (WIRED/WIRELESS/VPN/TELEPORT), macAddress, ipAddress, connectedAt, uplinkDeviceId (the switch/AP they're attached to), access.type. NOTE: verified against 10.4.55 — the Integration API client schema is minimal and identical across types; it does NOT expose signal strength, channel, or per-port binding. Use for: who's online right now. Disconnected/historical clients are NOT in the Integration API.",
|
|
11
12
|
inputSchema: {
|
|
12
13
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
14
|
offset: zod_1.z
|
|
@@ -25,28 +26,30 @@ function registerClientTools(server, client, readOnly = false) {
|
|
|
25
26
|
.describe("Number of records to return (default: 25, max: 200)"),
|
|
26
27
|
filter: zod_1.z.string().optional().describe("Filter expression"),
|
|
27
28
|
},
|
|
29
|
+
outputSchema: output_schemas_js_1.listClientsOutputSchema,
|
|
28
30
|
annotations: safety_js_1.READ_ONLY,
|
|
29
31
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
30
32
|
try {
|
|
31
33
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
32
34
|
const data = await client.get(`/sites/${siteId}/clients${query}`);
|
|
33
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
35
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
34
36
|
}
|
|
35
37
|
catch (err) {
|
|
36
38
|
return (0, responses_js_1.formatError)(err);
|
|
37
39
|
}
|
|
38
40
|
});
|
|
39
41
|
server.registerTool("unifi_get_client", {
|
|
40
|
-
description: "Get a specific client by ID",
|
|
42
|
+
description: "Get a specific connected client by ID. Returns same shape as unifi_list_clients entries.",
|
|
41
43
|
inputSchema: {
|
|
42
44
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
43
45
|
clientId: zod_1.z.string().describe("Client ID"),
|
|
44
46
|
},
|
|
47
|
+
outputSchema: output_schemas_js_1.getClientOutputSchema,
|
|
45
48
|
annotations: safety_js_1.READ_ONLY,
|
|
46
49
|
}, async ({ siteId, clientId }) => {
|
|
47
50
|
try {
|
|
48
51
|
const data = await client.get(`/sites/${siteId}/clients/${clientId}`);
|
|
49
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
52
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
50
53
|
}
|
|
51
54
|
catch (err) {
|
|
52
55
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -55,7 +58,7 @@ function registerClientTools(server, client, readOnly = false) {
|
|
|
55
58
|
if (readOnly)
|
|
56
59
|
return;
|
|
57
60
|
server.registerTool("unifi_authorize_guest", {
|
|
58
|
-
description: "Authorize a guest client
|
|
61
|
+
description: "Authorize a guest client through a captive-portal hotspot. Optional limits override hotspot defaults. Idempotency: not safe to retry — re-authorizing extends the session.",
|
|
59
62
|
inputSchema: {
|
|
60
63
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
61
64
|
clientId: zod_1.z.string().describe("Client ID"),
|
|
@@ -113,7 +116,7 @@ function registerClientTools(server, client, readOnly = false) {
|
|
|
113
116
|
}
|
|
114
117
|
});
|
|
115
118
|
server.registerTool("unifi_unauthorize_guest", {
|
|
116
|
-
description: "
|
|
119
|
+
description: "Revoke guest authorization; the client returns to the captive portal on next request. Idempotent.",
|
|
117
120
|
inputSchema: {
|
|
118
121
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
119
122
|
clientId: zod_1.z.string().describe("Client ID"),
|
package/dist/tools/devices.js
CHANGED
|
@@ -5,9 +5,12 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
9
|
+
// Adopt echoes the adopted device — reuse the device detail schema.
|
|
10
|
+
const adoptDeviceOutputSchema = output_schemas_js_1.getDeviceOutputSchema;
|
|
8
11
|
function registerDeviceTools(server, client, readOnly = false) {
|
|
9
12
|
server.registerTool("unifi_list_devices", {
|
|
10
|
-
description: "List all adopted devices at a site",
|
|
13
|
+
description: "List all adopted devices (gateways, switches, APs) at a site. Returns: id, name, model, macAddress, ipAddress, state (ONLINE/OFFLINE/etc), supported, firmwareVersion, firmwareUpdatable, features[] (capability tags, e.g. ['switching'] or ['accessPoint']), interfaces[] (e.g. ['ports'] or ['radios']). NOTE: features/interfaces are string arrays here; unifi_get_device expands them into objects. Use for: device inventory; pair with unifi_get_device for full config (port table, radios) and unifi_get_device_statistics for live metrics.",
|
|
11
14
|
inputSchema: {
|
|
12
15
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
16
|
offset: zod_1.z
|
|
@@ -25,51 +28,54 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
25
28
|
.describe("Number of records to return (default: 25, max: 200)"),
|
|
26
29
|
filter: zod_1.z.string().optional().describe("Filter expression"),
|
|
27
30
|
},
|
|
31
|
+
outputSchema: output_schemas_js_1.listDevicesOutputSchema,
|
|
28
32
|
annotations: safety_js_1.READ_ONLY,
|
|
29
33
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
30
34
|
try {
|
|
31
35
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
32
36
|
const data = await client.get(`/sites/${siteId}/devices${query}`);
|
|
33
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
37
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
34
38
|
}
|
|
35
39
|
catch (err) {
|
|
36
40
|
return (0, responses_js_1.formatError)(err);
|
|
37
41
|
}
|
|
38
42
|
});
|
|
39
43
|
server.registerTool("unifi_get_device", {
|
|
40
|
-
description: "Get a
|
|
44
|
+
description: "Get full configuration for a device. Returns (in addition to list fields): supported, firmwareUpdatable, provisionedAt, configurationId, uplink.deviceId, features (object keyed by capability: switching {lags[]} / accessPoint {}), interfaces.ports[] for switches ({idx, state, connector, maxSpeedMbps, speedMbps, poe:{standard, type, enabled, state}}), interfaces.radios[] for APs ({wlanStandard, frequencyGHz, channelWidthMHz, channel}). NOTE: in the LIST endpoint, features/interfaces are capability-tag string arrays instead. Use for: switch port layout/PoE state, AP radio config, uplink topology. For live throughput/CPU/memory, use unifi_get_device_statistics.",
|
|
41
45
|
inputSchema: {
|
|
42
46
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
43
47
|
deviceId: zod_1.z.string().describe("Device ID"),
|
|
44
48
|
},
|
|
49
|
+
outputSchema: output_schemas_js_1.getDeviceOutputSchema,
|
|
45
50
|
annotations: safety_js_1.READ_ONLY,
|
|
46
51
|
}, async ({ siteId, deviceId }) => {
|
|
47
52
|
try {
|
|
48
53
|
const data = await client.get(`/sites/${siteId}/devices/${deviceId}`);
|
|
49
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
54
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
50
55
|
}
|
|
51
56
|
catch (err) {
|
|
52
57
|
return (0, responses_js_1.formatError)(err);
|
|
53
58
|
}
|
|
54
59
|
});
|
|
55
60
|
server.registerTool("unifi_get_device_statistics", {
|
|
56
|
-
description: "Get latest statistics for a device",
|
|
61
|
+
description: "Get latest live statistics for a device. Returns: uptimeSec, lastHeartbeatAt, nextHeartbeatAt, loadAverage1/5/15Min, cpuUtilizationPct, memoryUtilizationPct, uplink (txRateBps, rxRateBps), interfaces.radios[] for APs ({frequencyGHz, txRetriesPct}). NOTE: verified against 10.4.55 — the Integration API does NOT expose per-switch-port byte/error/PoE-power counters here; port-level live stats are unavailable. Use for: device health and AP radio metrics. For config (channel, power, port assignment), use unifi_get_device.",
|
|
57
62
|
inputSchema: {
|
|
58
63
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
59
64
|
deviceId: zod_1.z.string().describe("Device ID"),
|
|
60
65
|
},
|
|
66
|
+
outputSchema: output_schemas_js_1.getDeviceStatisticsOutputSchema,
|
|
61
67
|
annotations: safety_js_1.READ_ONLY,
|
|
62
68
|
}, async ({ siteId, deviceId }) => {
|
|
63
69
|
try {
|
|
64
70
|
const data = await client.get(`/sites/${siteId}/devices/${deviceId}/statistics/latest`);
|
|
65
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
71
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
66
72
|
}
|
|
67
73
|
catch (err) {
|
|
68
74
|
return (0, responses_js_1.formatError)(err);
|
|
69
75
|
}
|
|
70
76
|
});
|
|
71
77
|
server.registerTool("unifi_list_pending_devices", {
|
|
72
|
-
description: "List devices pending adoption (global, not site-
|
|
78
|
+
description: "List devices pending adoption across all sites (global endpoint, not site-scoped). Returns: basic device info per pending device (macAddress, model, ipAddress, firmwareVersion, etc. — exact per-row schema is not rendered in the 10.4.55 docs). Use for: discovering new devices on the network before calling unifi_adopt_device.",
|
|
73
79
|
inputSchema: {
|
|
74
80
|
offset: zod_1.z
|
|
75
81
|
.number()
|
|
@@ -86,12 +92,13 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
86
92
|
.describe("Number of records to return (default: 25, max: 200)"),
|
|
87
93
|
filter: zod_1.z.string().optional().describe("Filter expression"),
|
|
88
94
|
},
|
|
95
|
+
outputSchema: output_schemas_js_1.listPendingDevicesOutputSchema,
|
|
89
96
|
annotations: safety_js_1.READ_ONLY,
|
|
90
97
|
}, async ({ offset, limit, filter }) => {
|
|
91
98
|
try {
|
|
92
99
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
93
100
|
const data = await client.get(`/pending-devices${query}`);
|
|
94
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
101
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
95
102
|
}
|
|
96
103
|
catch (err) {
|
|
97
104
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -100,13 +107,14 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
100
107
|
if (readOnly)
|
|
101
108
|
return;
|
|
102
109
|
server.registerTool("unifi_adopt_device", {
|
|
103
|
-
description: "Adopt a pending device",
|
|
110
|
+
description: "Adopt a pending device into a site by MAC address. The device must already appear in unifi_list_pending_devices. Idempotency: not safe to retry — re-adopting may error or duplicate.",
|
|
104
111
|
inputSchema: {
|
|
105
112
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
106
113
|
macAddress: zod_1.z.string().describe("MAC address of the device"),
|
|
107
114
|
ignoreDeviceLimit: zod_1.z.boolean().optional().describe("Ignore device limit when adopting (default: false)"),
|
|
108
115
|
dryRun: zod_1.z.boolean().optional().describe("Preview this action without executing it"),
|
|
109
116
|
},
|
|
117
|
+
outputSchema: adoptDeviceOutputSchema,
|
|
110
118
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
111
119
|
}, async ({ siteId, macAddress, ignoreDeviceLimit, dryRun }) => {
|
|
112
120
|
const body = {
|
|
@@ -117,7 +125,7 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
117
125
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/devices`, body);
|
|
118
126
|
try {
|
|
119
127
|
const data = await client.post(`/sites/${siteId}/devices`, body);
|
|
120
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
128
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
121
129
|
}
|
|
122
130
|
catch (err) {
|
|
123
131
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -147,7 +155,7 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
147
155
|
}
|
|
148
156
|
});
|
|
149
157
|
server.registerTool("unifi_restart_device", {
|
|
150
|
-
description: "Restart a device",
|
|
158
|
+
description: "Restart (reboot) a device. The device will be unreachable for ~1–3 minutes. Idempotent: repeated calls trigger fresh reboots.",
|
|
151
159
|
inputSchema: {
|
|
152
160
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
153
161
|
deviceId: zod_1.z.string().describe("Device ID"),
|
|
@@ -167,7 +175,7 @@ function registerDeviceTools(server, client, readOnly = false) {
|
|
|
167
175
|
}
|
|
168
176
|
});
|
|
169
177
|
server.registerTool("unifi_power_cycle_port", {
|
|
170
|
-
description: "Power
|
|
178
|
+
description: "Power-cycle PoE on a specific switch port (briefly drops then restores power). portIdx is the port number (1-based) as shown in unifi_get_device interfaces.ports[].idx. Use for: rebooting a PoE-powered camera/AP without touching the device.",
|
|
171
179
|
inputSchema: {
|
|
172
180
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
173
181
|
deviceId: zod_1.z.string().describe("Device ID"),
|
|
@@ -5,9 +5,10 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
8
9
|
function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
9
10
|
server.registerTool("unifi_list_dns_policies", {
|
|
10
|
-
description: "List
|
|
11
|
+
description: "List DNS policies (local DNS records and forward rules served by the gateway) at a site. Returns: id, type (A_RECORD, AAAA_RECORD, CNAME_RECORD, MX_RECORD, TXT_RECORD, SRV_RECORD, FORWARD_DOMAIN), enabled, domain, ipv4Address, ttlSeconds.",
|
|
11
12
|
inputSchema: {
|
|
12
13
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
14
|
offset: zod_1.z
|
|
@@ -28,28 +29,30 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
28
29
|
.optional()
|
|
29
30
|
.describe("Filter expression"),
|
|
30
31
|
},
|
|
32
|
+
outputSchema: output_schemas_js_1.listDnsPoliciesOutputSchema,
|
|
31
33
|
annotations: safety_js_1.READ_ONLY,
|
|
32
34
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
33
35
|
try {
|
|
34
36
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
35
37
|
const data = await client.get(`/sites/${siteId}/dns/policies${query}`);
|
|
36
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
38
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
37
39
|
}
|
|
38
40
|
catch (err) {
|
|
39
41
|
return (0, responses_js_1.formatError)(err);
|
|
40
42
|
}
|
|
41
43
|
});
|
|
42
44
|
server.registerTool("unifi_get_dns_policy", {
|
|
43
|
-
description: "Get a specific DNS policy by ID",
|
|
45
|
+
description: "Get a specific DNS policy by ID (same fields as the list entry).",
|
|
44
46
|
inputSchema: {
|
|
45
47
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
46
48
|
dnsPolicyId: zod_1.z.string().describe("DNS policy ID"),
|
|
47
49
|
},
|
|
50
|
+
outputSchema: output_schemas_js_1.dnsPolicyOutputSchema,
|
|
48
51
|
annotations: safety_js_1.READ_ONLY,
|
|
49
52
|
}, async ({ siteId, dnsPolicyId }) => {
|
|
50
53
|
try {
|
|
51
54
|
const data = await client.get(`/sites/${siteId}/dns/policies/${dnsPolicyId}`);
|
|
52
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
55
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
53
56
|
}
|
|
54
57
|
catch (err) {
|
|
55
58
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -86,6 +89,7 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
86
89
|
.optional()
|
|
87
90
|
.describe("Preview this action without executing it"),
|
|
88
91
|
},
|
|
92
|
+
outputSchema: output_schemas_js_1.dnsPolicyOutputSchema,
|
|
89
93
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
90
94
|
}, async ({ siteId, type, enabled, domain, ipv4Address, ttlSeconds, dryRun }) => {
|
|
91
95
|
try {
|
|
@@ -93,7 +97,7 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
93
97
|
if (dryRun)
|
|
94
98
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/dns/policies`, body);
|
|
95
99
|
const data = await client.post(`/sites/${siteId}/dns/policies`, body);
|
|
96
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
100
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
97
101
|
}
|
|
98
102
|
catch (err) {
|
|
99
103
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -129,6 +133,7 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
129
133
|
.optional()
|
|
130
134
|
.describe("Preview this action without executing it"),
|
|
131
135
|
},
|
|
136
|
+
outputSchema: output_schemas_js_1.dnsPolicyOutputSchema,
|
|
132
137
|
annotations: safety_js_1.WRITE,
|
|
133
138
|
}, async ({ siteId, dnsPolicyId, type, enabled, domain, ipv4Address, ttlSeconds, dryRun }) => {
|
|
134
139
|
try {
|
|
@@ -136,7 +141,7 @@ function registerDnsPolicyTools(server, client, readOnly = false) {
|
|
|
136
141
|
if (dryRun)
|
|
137
142
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/dns/policies/${dnsPolicyId}`, body);
|
|
138
143
|
const data = await client.put(`/sites/${siteId}/dns/policies/${dnsPolicyId}`, body);
|
|
139
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
144
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
140
145
|
}
|
|
141
146
|
catch (err) {
|
|
142
147
|
return (0, responses_js_1.formatError)(err);
|
package/dist/tools/firewall.js
CHANGED
|
@@ -5,9 +5,10 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
8
9
|
function registerFirewallTools(server, client, readOnly = false) {
|
|
9
10
|
server.registerTool("unifi_list_firewall_zones", {
|
|
10
|
-
description: "List
|
|
11
|
+
description: "List firewall zones (groupings of networks for zone-based firewalling) at a site. Returns: id, name, networkIds[], metadata.origin (indicates system-defined vs user-defined). Use for: zone inventory; pair with unifi_list_firewall_policies to see rules between zones.",
|
|
11
12
|
inputSchema: {
|
|
12
13
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
14
|
offset: zod_1.z
|
|
@@ -28,35 +29,37 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
28
29
|
.optional()
|
|
29
30
|
.describe("Filter expression"),
|
|
30
31
|
},
|
|
32
|
+
outputSchema: output_schemas_js_1.listFirewallZonesOutputSchema,
|
|
31
33
|
annotations: safety_js_1.READ_ONLY,
|
|
32
34
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
33
35
|
try {
|
|
34
36
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
35
37
|
const data = await client.get(`/sites/${siteId}/firewall/zones${query}`);
|
|
36
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
38
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
37
39
|
}
|
|
38
40
|
catch (err) {
|
|
39
41
|
return (0, responses_js_1.formatError)(err);
|
|
40
42
|
}
|
|
41
43
|
});
|
|
42
44
|
server.registerTool("unifi_get_firewall_zone", {
|
|
43
|
-
description: "Get a
|
|
45
|
+
description: "Get a firewall zone by ID (same fields as the list entry).",
|
|
44
46
|
inputSchema: {
|
|
45
47
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
46
48
|
firewallZoneId: zod_1.z.string().describe("Firewall zone ID"),
|
|
47
49
|
},
|
|
50
|
+
outputSchema: output_schemas_js_1.firewallZoneOutputSchema,
|
|
48
51
|
annotations: safety_js_1.READ_ONLY,
|
|
49
52
|
}, async ({ siteId, firewallZoneId }) => {
|
|
50
53
|
try {
|
|
51
54
|
const data = await client.get(`/sites/${siteId}/firewall/zones/${firewallZoneId}`);
|
|
52
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
55
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
53
56
|
}
|
|
54
57
|
catch (err) {
|
|
55
58
|
return (0, responses_js_1.formatError)(err);
|
|
56
59
|
}
|
|
57
60
|
});
|
|
58
61
|
server.registerTool("unifi_list_firewall_policies", {
|
|
59
|
-
description: "List
|
|
62
|
+
description: "List firewall policies (zone-based rules) at a site. Returns: id, name, enabled, action (object with type field), source/destination (zone reference + trafficFilter), ipProtocolScope, connectionStateFilter, ipsecFilter, schedule, loggingEnabled, index, description, metadata.origin. Protocols/ports are encoded inside source/destination.trafficFilter, not as top-level fields. Evaluation order within a zone pair comes from unifi_get_firewall_policy_ordering.",
|
|
60
63
|
inputSchema: {
|
|
61
64
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
62
65
|
offset: zod_1.z
|
|
@@ -77,35 +80,37 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
77
80
|
.optional()
|
|
78
81
|
.describe("Filter expression"),
|
|
79
82
|
},
|
|
83
|
+
outputSchema: output_schemas_js_1.listFirewallPoliciesOutputSchema,
|
|
80
84
|
annotations: safety_js_1.READ_ONLY,
|
|
81
85
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
82
86
|
try {
|
|
83
87
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
84
88
|
const data = await client.get(`/sites/${siteId}/firewall/policies${query}`);
|
|
85
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
89
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
86
90
|
}
|
|
87
91
|
catch (err) {
|
|
88
92
|
return (0, responses_js_1.formatError)(err);
|
|
89
93
|
}
|
|
90
94
|
});
|
|
91
95
|
server.registerTool("unifi_get_firewall_policy", {
|
|
92
|
-
description: "Get a
|
|
96
|
+
description: "Get a firewall policy by ID with full match criteria and action.",
|
|
93
97
|
inputSchema: {
|
|
94
98
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
95
99
|
firewallPolicyId: zod_1.z.string().describe("Firewall policy ID"),
|
|
96
100
|
},
|
|
101
|
+
outputSchema: output_schemas_js_1.firewallPolicyOutputSchema,
|
|
97
102
|
annotations: safety_js_1.READ_ONLY,
|
|
98
103
|
}, async ({ siteId, firewallPolicyId }) => {
|
|
99
104
|
try {
|
|
100
105
|
const data = await client.get(`/sites/${siteId}/firewall/policies/${firewallPolicyId}`);
|
|
101
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
106
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
102
107
|
}
|
|
103
108
|
catch (err) {
|
|
104
109
|
return (0, responses_js_1.formatError)(err);
|
|
105
110
|
}
|
|
106
111
|
});
|
|
107
112
|
server.registerTool("unifi_get_firewall_policy_ordering", {
|
|
108
|
-
description: "Get user-defined firewall
|
|
113
|
+
description: "Get the evaluation order of user-defined firewall policies for a specific (source zone, destination zone) pair. Returns: beforeSystemDefined[] and afterSystemDefined[] arrays of policy IDs. System-defined rules sit between these two arrays.",
|
|
109
114
|
inputSchema: {
|
|
110
115
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
111
116
|
sourceFirewallZoneId: zod_1.z
|
|
@@ -115,12 +120,13 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
115
120
|
.string()
|
|
116
121
|
.describe("Destination firewall zone ID"),
|
|
117
122
|
},
|
|
123
|
+
outputSchema: output_schemas_js_1.firewallPolicyOrderingOutputSchema,
|
|
118
124
|
annotations: safety_js_1.READ_ONLY,
|
|
119
125
|
}, async ({ siteId, sourceFirewallZoneId, destinationFirewallZoneId }) => {
|
|
120
126
|
try {
|
|
121
127
|
const query = `?sourceFirewallZoneId=${encodeURIComponent(sourceFirewallZoneId)}&destinationFirewallZoneId=${encodeURIComponent(destinationFirewallZoneId)}`;
|
|
122
128
|
const data = await client.get(`/sites/${siteId}/firewall/policies/ordering${query}`);
|
|
123
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
129
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
124
130
|
}
|
|
125
131
|
catch (err) {
|
|
126
132
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -141,6 +147,7 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
141
147
|
.optional()
|
|
142
148
|
.describe("Preview this action without executing it"),
|
|
143
149
|
},
|
|
150
|
+
outputSchema: output_schemas_js_1.firewallZoneOutputSchema,
|
|
144
151
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
145
152
|
}, async ({ siteId, name, networkIds, dryRun }) => {
|
|
146
153
|
try {
|
|
@@ -148,7 +155,7 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
148
155
|
if (dryRun)
|
|
149
156
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/firewall/zones`, body);
|
|
150
157
|
const data = await client.post(`/sites/${siteId}/firewall/zones`, body);
|
|
151
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
158
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
152
159
|
}
|
|
153
160
|
catch (err) {
|
|
154
161
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -168,6 +175,7 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
168
175
|
.optional()
|
|
169
176
|
.describe("Preview this action without executing it"),
|
|
170
177
|
},
|
|
178
|
+
outputSchema: output_schemas_js_1.firewallZoneOutputSchema,
|
|
171
179
|
annotations: safety_js_1.WRITE,
|
|
172
180
|
}, async ({ siteId, firewallZoneId, name, networkIds, dryRun }) => {
|
|
173
181
|
try {
|
|
@@ -175,7 +183,7 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
175
183
|
if (dryRun)
|
|
176
184
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/firewall/zones/${firewallZoneId}`, body);
|
|
177
185
|
const data = await client.put(`/sites/${siteId}/firewall/zones/${firewallZoneId}`, body);
|
|
178
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
186
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
179
187
|
}
|
|
180
188
|
catch (err) {
|
|
181
189
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -222,13 +230,14 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
222
230
|
.optional()
|
|
223
231
|
.describe("Preview this action without executing it"),
|
|
224
232
|
},
|
|
233
|
+
outputSchema: output_schemas_js_1.firewallPolicyOutputSchema,
|
|
225
234
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
226
235
|
}, async ({ siteId, policy, dryRun }) => {
|
|
227
236
|
try {
|
|
228
237
|
if (dryRun)
|
|
229
238
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/firewall/policies`, policy);
|
|
230
239
|
const data = await client.post(`/sites/${siteId}/firewall/policies`, policy);
|
|
231
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
240
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
232
241
|
}
|
|
233
242
|
catch (err) {
|
|
234
243
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -247,20 +256,21 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
247
256
|
.optional()
|
|
248
257
|
.describe("Preview this action without executing it"),
|
|
249
258
|
},
|
|
259
|
+
outputSchema: output_schemas_js_1.firewallPolicyOutputSchema,
|
|
250
260
|
annotations: safety_js_1.WRITE,
|
|
251
261
|
}, async ({ siteId, firewallPolicyId, policy, dryRun }) => {
|
|
252
262
|
try {
|
|
253
263
|
if (dryRun)
|
|
254
264
|
return (0, safety_js_1.formatDryRun)("PUT", `/sites/${siteId}/firewall/policies/${firewallPolicyId}`, policy);
|
|
255
265
|
const data = await client.put(`/sites/${siteId}/firewall/policies/${firewallPolicyId}`, policy);
|
|
256
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
266
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
257
267
|
}
|
|
258
268
|
catch (err) {
|
|
259
269
|
return (0, responses_js_1.formatError)(err);
|
|
260
270
|
}
|
|
261
271
|
});
|
|
262
272
|
server.registerTool("unifi_patch_firewall_policy", {
|
|
263
|
-
description: "Partially update a firewall policy
|
|
273
|
+
description: "Partially update a firewall policy without resending all fields. Common use: toggle loggingEnabled or enabled. Idempotent for fields supplied.",
|
|
264
274
|
inputSchema: {
|
|
265
275
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
266
276
|
firewallPolicyId: zod_1.z.string().describe("Firewall policy ID"),
|
|
@@ -272,13 +282,14 @@ function registerFirewallTools(server, client, readOnly = false) {
|
|
|
272
282
|
.optional()
|
|
273
283
|
.describe("Preview this action without executing it"),
|
|
274
284
|
},
|
|
285
|
+
outputSchema: output_schemas_js_1.firewallPolicyOutputSchema,
|
|
275
286
|
annotations: safety_js_1.WRITE,
|
|
276
287
|
}, async ({ siteId, firewallPolicyId, policy, dryRun }) => {
|
|
277
288
|
try {
|
|
278
289
|
if (dryRun)
|
|
279
290
|
return (0, safety_js_1.formatDryRun)("PATCH", `/sites/${siteId}/firewall/policies/${firewallPolicyId}`, policy);
|
|
280
291
|
const data = await client.patch(`/sites/${siteId}/firewall/policies/${firewallPolicyId}`, policy);
|
|
281
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
292
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
282
293
|
}
|
|
283
294
|
catch (err) {
|
|
284
295
|
return (0, responses_js_1.formatError)(err);
|
package/dist/tools/hotspot.js
CHANGED
|
@@ -5,9 +5,10 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const responses_js_1 = require("../utils/responses.js");
|
|
6
6
|
const query_js_1 = require("../utils/query.js");
|
|
7
7
|
const safety_js_1 = require("../utils/safety.js");
|
|
8
|
+
const output_schemas_js_1 = require("../utils/output-schemas.js");
|
|
8
9
|
function registerHotspotTools(server, client, readOnly = false) {
|
|
9
10
|
server.registerTool("unifi_list_vouchers", {
|
|
10
|
-
description: "List
|
|
11
|
+
description: "List hotspot/guest-portal vouchers at a site. Returns: id, code, name, createdAt, activatedAt (when first guest used it), expiresAt, timeLimitMinutes, dataUsageLimitMBytes, rxRateLimitKbps, txRateLimitKbps, authorizedGuestLimit, authorizedGuestCount, expired. Use filter like 'expired.eq(true)' to bulk-find stale vouchers.",
|
|
11
12
|
inputSchema: {
|
|
12
13
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
13
14
|
offset: zod_1.z
|
|
@@ -30,28 +31,30 @@ function registerHotspotTools(server, client, readOnly = false) {
|
|
|
30
31
|
.optional()
|
|
31
32
|
.describe("Filter expression (e.g., 'expired.eq(true)')"),
|
|
32
33
|
},
|
|
34
|
+
outputSchema: output_schemas_js_1.listVouchersOutputSchema,
|
|
33
35
|
annotations: safety_js_1.READ_ONLY,
|
|
34
36
|
}, async ({ siteId, offset, limit, filter }) => {
|
|
35
37
|
try {
|
|
36
38
|
const query = (0, query_js_1.buildQuery)({ offset, limit, filter });
|
|
37
39
|
const data = await client.get(`/sites/${siteId}/hotspot/vouchers${query}`);
|
|
38
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
40
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
39
41
|
}
|
|
40
42
|
catch (err) {
|
|
41
43
|
return (0, responses_js_1.formatError)(err);
|
|
42
44
|
}
|
|
43
45
|
});
|
|
44
46
|
server.registerTool("unifi_get_voucher", {
|
|
45
|
-
description: "Get a specific hotspot voucher by ID",
|
|
47
|
+
description: "Get a specific hotspot voucher by ID (same fields as the list entry).",
|
|
46
48
|
inputSchema: {
|
|
47
49
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
48
50
|
voucherId: zod_1.z.string().describe("Voucher ID"),
|
|
49
51
|
},
|
|
52
|
+
outputSchema: output_schemas_js_1.voucherOutputSchema,
|
|
50
53
|
annotations: safety_js_1.READ_ONLY,
|
|
51
54
|
}, async ({ siteId, voucherId }) => {
|
|
52
55
|
try {
|
|
53
56
|
const data = await client.get(`/sites/${siteId}/hotspot/vouchers/${voucherId}`);
|
|
54
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
57
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
55
58
|
}
|
|
56
59
|
catch (err) {
|
|
57
60
|
return (0, responses_js_1.formatError)(err);
|
|
@@ -60,7 +63,7 @@ function registerHotspotTools(server, client, readOnly = false) {
|
|
|
60
63
|
if (readOnly)
|
|
61
64
|
return;
|
|
62
65
|
server.registerTool("unifi_create_voucher", {
|
|
63
|
-
description: "Create hotspot vouchers",
|
|
66
|
+
description: "Create one or more hotspot vouchers (use count for batch creation, up to 1000 at once). Returns: array of created vouchers with their generated codes. Idempotency: not safe to retry — each call mints fresh codes.",
|
|
64
67
|
inputSchema: {
|
|
65
68
|
siteId: zod_1.z.string().describe("Site ID"),
|
|
66
69
|
name: zod_1.z
|
|
@@ -112,6 +115,7 @@ function registerHotspotTools(server, client, readOnly = false) {
|
|
|
112
115
|
.optional()
|
|
113
116
|
.describe("Preview this action without executing it"),
|
|
114
117
|
},
|
|
118
|
+
outputSchema: output_schemas_js_1.createVouchersOutputSchema,
|
|
115
119
|
annotations: safety_js_1.WRITE_NOT_IDEMPOTENT,
|
|
116
120
|
}, async ({ siteId, name, timeLimitMinutes, count, authorizedGuestLimit, dataUsageLimitMBytes, rxRateLimitKbps, txRateLimitKbps, dryRun, }) => {
|
|
117
121
|
try {
|
|
@@ -132,7 +136,7 @@ function registerHotspotTools(server, client, readOnly = false) {
|
|
|
132
136
|
if (dryRun)
|
|
133
137
|
return (0, safety_js_1.formatDryRun)("POST", `/sites/${siteId}/hotspot/vouchers`, body);
|
|
134
138
|
const data = await client.post(`/sites/${siteId}/hotspot/vouchers`, body);
|
|
135
|
-
return (0, responses_js_1.formatSuccess)(data);
|
|
139
|
+
return (0, responses_js_1.formatSuccess)(data, { structured: true });
|
|
136
140
|
}
|
|
137
141
|
catch (err) {
|
|
138
142
|
return (0, responses_js_1.formatError)(err);
|