@owine/unifi-protect-mcp 2.14.1 → 2.15.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/README.md +3 -3
- package/dist/client.d.ts +7 -1
- package/dist/client.js +17 -6
- package/dist/schemas/cameras.js +2 -1
- package/dist/schemas/devices.d.ts +0 -10
- package/dist/schemas/devices.js +34 -25
- package/dist/schemas/misc.d.ts +38 -17
- package/dist/schemas/misc.js +20 -13
- package/dist/schemas/pos.d.ts +1 -1
- package/dist/schemas/pos.js +1 -1
- package/dist/tools/alarm-manager.d.ts +3 -0
- package/dist/tools/alarm-manager.js +42 -0
- package/dist/tools/arm-profiles.js +19 -11
- package/dist/tools/cameras.js +62 -16
- package/dist/tools/devices.d.ts +1 -0
- package/dist/tools/devices.js +21 -17
- package/dist/tools/files.js +41 -33
- package/dist/tools/index.js +2 -0
- package/dist/tools/liveviews.js +27 -9
- package/dist/tools/pos.d.ts +4 -2
- package/dist/tools/pos.js +5 -3
- package/dist/tools/subscriptions.js +2 -2
- package/dist/tools/system.js +1 -1
- package/dist/tools/users.js +2 -2
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UniFi Protect MCP Server
|
|
2
2
|
|
|
3
|
-
An MCP (Model Context Protocol) server that exposes UniFi Protect's Integration REST API as tools for Claude Code and other MCP clients. Aligned with UniFi Protect API **7.3.
|
|
3
|
+
An MCP (Model Context Protocol) server that exposes UniFi Protect's Integration REST API as tools for Claude Code and other MCP clients. Aligned with UniFi Protect API **7.3.70** — 74 tools covering cameras, lights, sensors, chimes, viewers, sirens, fobs, relays, speakers, bridges, link stations, alarm hubs, arm profiles, live views, files, users, point-of-sale events, NVR status, and WebSocket subscriptions.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -243,8 +243,8 @@ server logs a warning and talks to that host directly.
|
|
|
243
243
|
| Tool | Description |
|
|
244
244
|
|---|---|
|
|
245
245
|
| `protect_trigger_alarm_webhook` | Trigger an alarm webhook (fires external alarm action) |
|
|
246
|
-
| `protect_list_files` | List files
|
|
247
|
-
| `protect_upload_file` | Upload a file (base64-
|
|
246
|
+
| `protect_list_files` | List device asset files (`animations`) |
|
|
247
|
+
| `protect_upload_file` | Upload a device asset file (base64 in, sent as multipart/form-data) |
|
|
248
248
|
|
|
249
249
|
### Users (4)
|
|
250
250
|
| Tool | Description |
|
package/dist/client.d.ts
CHANGED
|
@@ -14,6 +14,12 @@ export declare class ProtectClient {
|
|
|
14
14
|
data: Buffer;
|
|
15
15
|
mimeType: string;
|
|
16
16
|
}>;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Upload a file as multipart/form-data (the documented encoding for
|
|
19
|
+
* POST /files/{fileType}). fetch sets the Content-Type with its boundary, so
|
|
20
|
+
* none is set here. The part name `file` is not in the published docs but
|
|
21
|
+
* was verified against a live 7.3.70 console.
|
|
22
|
+
*/
|
|
23
|
+
postFile(path: string, data: Buffer, contentType: string, fileName: string): Promise<unknown>;
|
|
18
24
|
connectWebSocket(path: string): WebSocket;
|
|
19
25
|
}
|
package/dist/client.js
CHANGED
|
@@ -81,6 +81,12 @@ class ProtectClient {
|
|
|
81
81
|
if (!response.ok) {
|
|
82
82
|
throw new Error(`HTTP ${response.status}: ${await readErrorBody(response, MAX_JSON_BYTES)}`);
|
|
83
83
|
}
|
|
84
|
+
// 204 No Content (action endpoints: siren/relay/speaker triggers, arm
|
|
85
|
+
// profile enable/disable, PTZ, …) has no body by definition — don't let a
|
|
86
|
+
// stray JSON content-type turn a success into an "empty body" error.
|
|
87
|
+
if (response.status === 204) {
|
|
88
|
+
return "";
|
|
89
|
+
}
|
|
84
90
|
enforceSizeLimit(response, MAX_JSON_BYTES);
|
|
85
91
|
const contentType = response.headers.get("content-type") ?? "";
|
|
86
92
|
const text = await response.text();
|
|
@@ -122,15 +128,20 @@ class ProtectClient {
|
|
|
122
128
|
const arrayBuffer = await response.arrayBuffer();
|
|
123
129
|
return { data: Buffer.from(arrayBuffer), mimeType };
|
|
124
130
|
}
|
|
125
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Upload a file as multipart/form-data (the documented encoding for
|
|
133
|
+
* POST /files/{fileType}). fetch sets the Content-Type with its boundary, so
|
|
134
|
+
* none is set here. The part name `file` is not in the published docs but
|
|
135
|
+
* was verified against a live 7.3.70 console.
|
|
136
|
+
*/
|
|
137
|
+
async postFile(path, data, contentType, fileName) {
|
|
126
138
|
const url = `${this.baseUrl}${path}`;
|
|
139
|
+
const form = new FormData();
|
|
140
|
+
form.append("file", new Blob([new Uint8Array(data)], { type: contentType }), fileName);
|
|
127
141
|
const response = await fetch(url, {
|
|
128
142
|
method: "POST",
|
|
129
|
-
headers: {
|
|
130
|
-
|
|
131
|
-
"Content-Type": contentType,
|
|
132
|
-
},
|
|
133
|
-
body: new Uint8Array(data),
|
|
143
|
+
headers: { "X-API-KEY": this.headers["X-API-KEY"] },
|
|
144
|
+
body: form,
|
|
134
145
|
redirect: "error",
|
|
135
146
|
signal: AbortSignal.timeout(BINARY_TIMEOUT_MS),
|
|
136
147
|
});
|
package/dist/schemas/cameras.js
CHANGED
|
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.talkbackSessionOutputSchema = exports.rtspStreamOutputSchema = exports.rtspStreamSchema = exports.cameraListOutputSchema = exports.cameraOutputSchema = exports.cameraSchema = void 0;
|
|
4
4
|
const common_js_1 = require("./common.js");
|
|
5
5
|
/**
|
|
6
|
-
* Verified against live UniFi Protect Integration API 7.3.47 (2026-09-14)
|
|
6
|
+
* Verified against live UniFi Protect Integration API 7.3.47 (2026-09-14) and
|
|
7
|
+
* re-verified against live 7.3.70 (2026-10-12).
|
|
7
8
|
* The Integration API camera object is far smaller than the internal Protect
|
|
8
9
|
* app's camera model — no isRecording/lastMotion/channels/firmwareVersion/etc.
|
|
9
10
|
* `list` and `get-by-id` return the same field set (confirmed live).
|
|
@@ -94,7 +94,6 @@ export declare const fobSchema: import("zod").ZodObject<{
|
|
|
94
94
|
awayState: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
95
95
|
buttonLabels: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
96
96
|
featureFlags: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
97
|
-
hasKeypad: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
98
97
|
armControlSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
99
98
|
keypadSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
100
99
|
wirelessConnectionState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
@@ -150,7 +149,6 @@ export declare const linkStationSchema: import("zod").ZodObject<{
|
|
|
150
149
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
151
150
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
152
151
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
153
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
154
152
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
155
153
|
}, import("zod/v4/core").$loose>;
|
|
156
154
|
export declare const alarmHubSchema: import("zod").ZodObject<{
|
|
@@ -165,7 +163,6 @@ export declare const alarmHubSchema: import("zod").ZodObject<{
|
|
|
165
163
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
166
164
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
167
165
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
168
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
169
166
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
170
167
|
}, import("zod/v4/core").$loose>;
|
|
171
168
|
export declare const DEVICE_SCHEMAS: {
|
|
@@ -265,7 +262,6 @@ export declare const DEVICE_SCHEMAS: {
|
|
|
265
262
|
awayState: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
266
263
|
buttonLabels: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
267
264
|
featureFlags: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
268
|
-
hasKeypad: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
269
265
|
armControlSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
270
266
|
keypadSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
271
267
|
wirelessConnectionState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
@@ -321,7 +317,6 @@ export declare const DEVICE_SCHEMAS: {
|
|
|
321
317
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
322
318
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
323
319
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
324
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
325
320
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
326
321
|
}, import("zod/v4/core").$loose>;
|
|
327
322
|
readonly alarm_hub: import("zod").ZodObject<{
|
|
@@ -336,7 +331,6 @@ export declare const DEVICE_SCHEMAS: {
|
|
|
336
331
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
337
332
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
338
333
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
339
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
340
334
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
341
335
|
}, import("zod/v4/core").$loose>;
|
|
342
336
|
};
|
|
@@ -431,7 +425,6 @@ export declare function itemOutputShape(key: keyof typeof DEVICE_SCHEMAS): {
|
|
|
431
425
|
awayState: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
432
426
|
buttonLabels: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
433
427
|
featureFlags: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
434
|
-
hasKeypad: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
435
428
|
armControlSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
436
429
|
keypadSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
437
430
|
wirelessConnectionState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
@@ -483,7 +476,6 @@ export declare function itemOutputShape(key: keyof typeof DEVICE_SCHEMAS): {
|
|
|
483
476
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
484
477
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
485
478
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
486
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
487
479
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
488
480
|
};
|
|
489
481
|
export declare function listOutputShape(key: keyof typeof DEVICE_SCHEMAS): {
|
|
@@ -578,7 +570,6 @@ export declare function listOutputShape(key: keyof typeof DEVICE_SCHEMAS): {
|
|
|
578
570
|
awayState: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
579
571
|
buttonLabels: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
580
572
|
featureFlags: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
581
|
-
hasKeypad: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
582
573
|
armControlSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
583
574
|
keypadSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
584
575
|
wirelessConnectionState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
@@ -630,7 +621,6 @@ export declare function listOutputShape(key: keyof typeof DEVICE_SCHEMAS): {
|
|
|
630
621
|
ledSettings: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
631
622
|
lastEvent: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
632
623
|
alarmHub: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
633
|
-
deviceTamperStatus: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
634
624
|
threadState: import("zod").ZodOptional<import("zod").ZodUnknown>;
|
|
635
625
|
}, import("zod/v4/core").$loose>>;
|
|
636
626
|
};
|
package/dist/schemas/devices.js
CHANGED
|
@@ -7,11 +7,11 @@ const common_js_1 = require("./common.js");
|
|
|
7
7
|
/**
|
|
8
8
|
* Device schemas for the config-driven Protect device types.
|
|
9
9
|
*
|
|
10
|
-
* Field sets are derived from the UniFi Protect Integration API 7.3.
|
|
10
|
+
* Field sets are derived from the UniFi Protect Integration API 7.3.70 docs
|
|
11
11
|
* (per-type response samples). Chimes were additionally verified against live
|
|
12
|
-
* console responses (2026-09-14); the rest
|
|
13
|
-
* console, so their TOP-LEVEL fields are
|
|
14
|
-
* every nested object/array is left as `unknownField()` (z.unknown()) — naming
|
|
12
|
+
* console responses (7.3.47 on 2026-09-14, 7.3.70 on 2026-10-12); the rest
|
|
13
|
+
* have no instances on the available console, so their TOP-LEVEL fields are
|
|
14
|
+
* typed from the published docs while every nested object/array is left as `unknownField()` (z.unknown()) — naming
|
|
15
15
|
* the field for the LLM without risking SDK output-validation failures on a
|
|
16
16
|
* shape we have not observed live. `.passthrough()` lets any extra field flow.
|
|
17
17
|
*
|
|
@@ -45,16 +45,16 @@ exports.sensorSchema = (0, common_js_1.passthroughObject)({
|
|
|
45
45
|
featureFlags: (0, common_js_1.unknownField)("Sensor capability flags, added in 7.3.x (object: temperature, humidity, " +
|
|
46
46
|
"light, motion, waterLeak, open, tamper, smoke — each { channelCount })"),
|
|
47
47
|
batteryStatus: (0, common_js_1.unknownField)("Battery status (object: percentage, isLow)"),
|
|
48
|
-
stats: (0, common_js_1.unknownField)("Environmental stats (object: light, humidity, temperature)"),
|
|
49
|
-
lightSettings: (0, common_js_1.unknownField)("Light threshold settings (object)"),
|
|
50
|
-
humiditySettings: (0, common_js_1.unknownField)("Humidity threshold settings (object)"),
|
|
51
|
-
temperatureSettings: (0, common_js_1.unknownField)("Temperature threshold settings (object)"),
|
|
48
|
+
stats: (0, common_js_1.unknownField)("Environmental stats (object: light, humidity, temperature — each { value, status })"),
|
|
49
|
+
lightSettings: (0, common_js_1.unknownField)("Light threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"),
|
|
50
|
+
humiditySettings: (0, common_js_1.unknownField)("Humidity threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"),
|
|
51
|
+
temperatureSettings: (0, common_js_1.unknownField)("Temperature threshold settings (object: isEnabled, margin, lowThreshold, highThreshold)"),
|
|
52
52
|
isOpened: (0, common_js_1.unknownField)("Open/close contact state (boolean)"),
|
|
53
53
|
openStatusChangedAt: (0, common_js_1.unknownField)("Open-status change timestamp in epoch ms (number)"),
|
|
54
54
|
isMotionDetected: (0, common_js_1.unknownField)("Motion currently detected (boolean)"),
|
|
55
55
|
motionDetectedAt: (0, common_js_1.unknownField)("Last motion timestamp in epoch ms (number)"),
|
|
56
|
-
motionSettings: (0, common_js_1.unknownField)("Motion detection settings (object)"),
|
|
57
|
-
glassBreakSettings: (0, common_js_1.unknownField)("Glass-break detection settings (object)"),
|
|
56
|
+
motionSettings: (0, common_js_1.unknownField)("Motion detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"),
|
|
57
|
+
glassBreakSettings: (0, common_js_1.unknownField)("Glass-break detection settings (object: isEnabled, sensitivity, sensitivityWhenArmed)"),
|
|
58
58
|
scheduleMode: (0, common_js_1.nullableString)('Schedule mode: "always" | "when_armed"'),
|
|
59
59
|
armProfileIds: (0, common_js_1.unknownField)("Arm profile IDs this sensor belongs to (array of strings)"),
|
|
60
60
|
hasCustomSensitivityWhenArmed: (0, common_js_1.unknownField)("Custom armed sensitivity enabled (boolean)"),
|
|
@@ -62,12 +62,13 @@ exports.sensorSchema = (0, common_js_1.passthroughObject)({
|
|
|
62
62
|
alarmSettings: (0, common_js_1.unknownField)("Alarm settings (object: isEnabled)"),
|
|
63
63
|
leakDetectedAt: (0, common_js_1.unknownField)("Last leak timestamp in epoch ms (number)"),
|
|
64
64
|
externalLeakDetectedAt: (0, common_js_1.unknownField)("Last external-leak timestamp in epoch ms (number)"),
|
|
65
|
-
leakSettings: (0, common_js_1.unknownField)("Leak detection settings (object)"),
|
|
65
|
+
leakSettings: (0, common_js_1.unknownField)("Leak detection settings, read-only (object: isInternalEnabled, isExternalEnabled)"),
|
|
66
66
|
tamperingDetectedAt: (0, common_js_1.unknownField)("Last tampering timestamp in epoch ms (number)"),
|
|
67
|
-
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object: signalState,
|
|
67
|
+
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object: signalState { signalQuality, signalStrength }, " +
|
|
68
|
+
"batteryStatus { percentage, isLow }, bridge)"),
|
|
68
69
|
});
|
|
69
|
-
// Verified live (7.1.83): chimes return cameraIds[] and
|
|
70
|
-
// items are { cameraId, volume, ringtoneId, repeatTimes }.
|
|
70
|
+
// Verified live (7.1.83, re-verified 7.3.70): chimes return cameraIds[] and
|
|
71
|
+
// ringSettings[] whose items are { cameraId, volume, ringtoneId, repeatTimes }.
|
|
71
72
|
exports.chimeSchema = (0, common_js_1.passthroughObject)({
|
|
72
73
|
...deviceIdentity(),
|
|
73
74
|
cameraIds: (0, common_js_1.unknownField)("Paired camera IDs (array of strings)"),
|
|
@@ -84,25 +85,29 @@ exports.sirenSchema = (0, common_js_1.passthroughObject)({
|
|
|
84
85
|
ledSettings: (0, common_js_1.unknownField)("LED settings (object: isEnabled)"),
|
|
85
86
|
sirenStatus: (0, common_js_1.unknownField)("Current siren status (object: isActive, activatedAt, duration)"),
|
|
86
87
|
connectionType: (0, common_js_1.nullableString)('Connection type, e.g. "lora"'),
|
|
87
|
-
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object
|
|
88
|
+
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object: signalState { signalQuality, signalStrength }, " +
|
|
89
|
+
"batteryStatus { percentage, isLow }, bridge)"),
|
|
88
90
|
});
|
|
89
91
|
exports.fobSchema = (0, common_js_1.passthroughObject)({
|
|
90
92
|
...deviceIdentity(),
|
|
91
93
|
awayState: (0, common_js_1.nullableString)('Away state, e.g. "ONLINE"'),
|
|
92
94
|
buttonLabels: (0, common_js_1.nullableString)('Button label preset, e.g. "securityActions"'),
|
|
93
|
-
featureFlags: (0, common_js_1.unknownField)("Feature flags (object: buttons[])"),
|
|
94
|
-
hasKeypad: (0, common_js_1.unknownField)("Whether this fob has a keypad, added in 7.3.x (boolean)"),
|
|
95
|
+
featureFlags: (0, common_js_1.unknownField)("Feature flags (object: buttons[], hasKeypad — hasKeypad added in 7.3.x)"),
|
|
95
96
|
armControlSettings: (0, common_js_1.unknownField)("Arm-control config, added in 7.3.x (object: enabled, armProfileId, nightProfileId)"),
|
|
96
|
-
keypadSettings: (0, common_js_1.unknownField)("Keypad config, added in 7.3.x (object: beepEnabled, beepVolume
|
|
97
|
-
"backlightEnabled
|
|
98
|
-
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object
|
|
97
|
+
keypadSettings: (0, common_js_1.unknownField)("Keypad config, added in 7.3.x (object: beepEnabled, beepVolume). The " +
|
|
98
|
+
"backlightEnabled/backlightBrightness fields were dropped in 7.3.70."),
|
|
99
|
+
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object: signalState { signalQuality, signalStrength }, " +
|
|
100
|
+
"batteryStatus { percentage, isLow }, bridge)"),
|
|
99
101
|
});
|
|
100
102
|
exports.relaySchema = (0, common_js_1.passthroughObject)({
|
|
101
103
|
...deviceIdentity(),
|
|
102
104
|
ledSettings: (0, common_js_1.unknownField)("LED settings (object: isEnabled)"),
|
|
103
|
-
outputs: (0, common_js_1.unknownField)("Output channels (array of objects
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
outputs: (0, common_js_1.unknownField)("Output channels (array of objects: id, name, type, delay, pulseDuration, " +
|
|
106
|
+
"state, rebootState). `id` is the outputId for protect_activate_relay_output"),
|
|
107
|
+
inputs: (0, common_js_1.unknownField)("Input channels (array of objects: id, name, state, actionTrigger, " +
|
|
108
|
+
"actionType, actionOutputId)"),
|
|
109
|
+
wirelessConnectionState: (0, common_js_1.unknownField)("Wireless link state (object: signalState { signalQuality, signalStrength }, " +
|
|
110
|
+
"batteryStatus { percentage, isLow }, bridge)"),
|
|
106
111
|
});
|
|
107
112
|
exports.speakerSchema = (0, common_js_1.passthroughObject)({
|
|
108
113
|
...deviceIdentity(),
|
|
@@ -125,8 +130,12 @@ const linkStationLikeSchema = () => (0, common_js_1.passthroughObject)({
|
|
|
125
130
|
isAlarmHub: (0, common_js_1.unknownField)("Whether this device is an alarm hub (boolean)"),
|
|
126
131
|
ledSettings: (0, common_js_1.unknownField)("LED settings (object: isEnabled)"),
|
|
127
132
|
lastEvent: (0, common_js_1.unknownField)("Last event timestamp in epoch ms (number)"),
|
|
128
|
-
alarmHub: (0, common_js_1.unknownField)("Alarm hub status (object: armed, battery, connector, cover,
|
|
129
|
-
|
|
133
|
+
alarmHub: (0, common_js_1.unknownField)("Alarm hub status (object: armed, battery, buckboost, connector, cover, " +
|
|
134
|
+
'deviceTamperStatus (e.g. "tampered", added in 7.3.x), ' +
|
|
135
|
+
"currentMeterChannelStatus, currentMeterStatus, inputPower, poeout, " +
|
|
136
|
+
"powerMeter, output and input (maps keyed by channel), " +
|
|
137
|
+
"inputTerminalStatus, outputTerminalStatus, emergencyTerminalStatus, " +
|
|
138
|
+
"auxiliaryPowerTerminalStatus)"),
|
|
130
139
|
threadState: (0, common_js_1.unknownField)("Thread radio state, added in 7.3.x (object: network — status, role, " +
|
|
131
140
|
"networkName, channel, panId, extendedPanId, joinedDeviceCount, " +
|
|
132
141
|
"errorReason, lastUpdatedAt)"),
|
package/dist/schemas/misc.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/**
|
|
3
3
|
* Schemas below are verified against live UniFi Protect Integration API 7.3.47
|
|
4
|
-
* responses (Melrose NVR Pro console, 2026-09-14) where instances exist
|
|
5
|
-
*
|
|
6
|
-
* instances on the console). The Integration API surface is much thinner than
|
|
4
|
+
* responses (Melrose NVR Pro console, 2026-09-14) where instances exist —
|
|
5
|
+
* re-verified live on 7.3.70 (2026-10-12) — and against the 7.3.70 published
|
|
6
|
+
* docs otherwise (arm profiles, files — no instances on the console). The Integration API surface is much thinner than
|
|
7
7
|
* the internal Protect app API — only observed/documented fields are typed;
|
|
8
8
|
* `.passthrough()` still allows anything extra a firmware/hardware mix adds.
|
|
9
9
|
*/
|
|
@@ -17,13 +17,13 @@ export declare const nvrSchema: z.ZodObject<{
|
|
|
17
17
|
modelKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
18
18
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
19
19
|
mac: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
20
|
-
doorbellSettings: z.ZodOptional<z.ZodObject<{
|
|
20
|
+
doorbellSettings: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
21
21
|
defaultMessageText: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
22
22
|
defaultMessageResetTimeoutMs: z.ZodOptional<z.ZodUnknown>;
|
|
23
23
|
customMessages: z.ZodOptional<z.ZodUnknown>;
|
|
24
24
|
customImages: z.ZodOptional<z.ZodUnknown>;
|
|
25
|
-
}, z.core.$loose
|
|
26
|
-
armMode: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
}, z.core.$loose>>>;
|
|
26
|
+
armMode: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
27
27
|
status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
28
28
|
armProfileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
29
29
|
armedAt: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -32,7 +32,7 @@ export declare const nvrSchema: z.ZodObject<{
|
|
|
32
32
|
breachEventCount: z.ZodOptional<z.ZodUnknown>;
|
|
33
33
|
breachTriggerEventId: z.ZodOptional<z.ZodUnknown>;
|
|
34
34
|
breachEventId: z.ZodOptional<z.ZodUnknown>;
|
|
35
|
-
}, z.core.$loose
|
|
35
|
+
}, z.core.$loose>>>;
|
|
36
36
|
}, z.core.$loose>;
|
|
37
37
|
export declare const nvrOutputSchema: {
|
|
38
38
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -41,13 +41,13 @@ export declare const nvrOutputSchema: {
|
|
|
41
41
|
modelKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
42
42
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
43
43
|
mac: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
-
doorbellSettings: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
doorbellSettings: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
45
45
|
defaultMessageText: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
46
46
|
defaultMessageResetTimeoutMs: z.ZodOptional<z.ZodUnknown>;
|
|
47
47
|
customMessages: z.ZodOptional<z.ZodUnknown>;
|
|
48
48
|
customImages: z.ZodOptional<z.ZodUnknown>;
|
|
49
|
-
}, z.core.$loose
|
|
50
|
-
armMode: z.ZodOptional<z.ZodObject<{
|
|
49
|
+
}, z.core.$loose>>>;
|
|
50
|
+
armMode: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
51
51
|
status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
52
|
armProfileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
53
|
armedAt: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -56,7 +56,7 @@ export declare const nvrOutputSchema: {
|
|
|
56
56
|
breachEventCount: z.ZodOptional<z.ZodUnknown>;
|
|
57
57
|
breachTriggerEventId: z.ZodOptional<z.ZodUnknown>;
|
|
58
58
|
breachEventId: z.ZodOptional<z.ZodUnknown>;
|
|
59
|
-
}, z.core.$loose
|
|
59
|
+
}, z.core.$loose>>>;
|
|
60
60
|
};
|
|
61
61
|
export declare const userSchema: z.ZodObject<{
|
|
62
62
|
id: z.ZodOptional<z.ZodString>;
|
|
@@ -124,11 +124,11 @@ export declare const liveviewSchema: z.ZodObject<{
|
|
|
124
124
|
isGlobal: z.ZodOptional<z.ZodUnknown>;
|
|
125
125
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
126
126
|
owner: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
127
|
-
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
127
|
+
slots: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
128
128
|
cameras: z.ZodOptional<z.ZodUnknown>;
|
|
129
129
|
cycleMode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
130
|
cycleInterval: z.ZodOptional<z.ZodUnknown>;
|
|
131
|
-
}, z.core.$loose
|
|
131
|
+
}, z.core.$loose>>>>;
|
|
132
132
|
}, z.core.$loose>;
|
|
133
133
|
export declare const liveviewOutputSchema: {
|
|
134
134
|
id: z.ZodOptional<z.ZodString>;
|
|
@@ -138,11 +138,11 @@ export declare const liveviewOutputSchema: {
|
|
|
138
138
|
isGlobal: z.ZodOptional<z.ZodUnknown>;
|
|
139
139
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
140
140
|
owner: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
141
|
-
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
141
|
+
slots: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
142
142
|
cameras: z.ZodOptional<z.ZodUnknown>;
|
|
143
143
|
cycleMode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
144
144
|
cycleInterval: z.ZodOptional<z.ZodUnknown>;
|
|
145
|
-
}, z.core.$loose
|
|
145
|
+
}, z.core.$loose>>>>;
|
|
146
146
|
};
|
|
147
147
|
export declare const liveviewListOutputSchema: {
|
|
148
148
|
result: z.ZodArray<z.ZodObject<{
|
|
@@ -153,11 +153,11 @@ export declare const liveviewListOutputSchema: {
|
|
|
153
153
|
isGlobal: z.ZodOptional<z.ZodUnknown>;
|
|
154
154
|
layout: z.ZodOptional<z.ZodUnknown>;
|
|
155
155
|
owner: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
156
|
-
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
156
|
+
slots: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
157
157
|
cameras: z.ZodOptional<z.ZodUnknown>;
|
|
158
158
|
cycleMode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
159
159
|
cycleInterval: z.ZodOptional<z.ZodUnknown>;
|
|
160
|
-
}, z.core.$loose
|
|
160
|
+
}, z.core.$loose>>>>;
|
|
161
161
|
}, z.core.$loose>>;
|
|
162
162
|
};
|
|
163
163
|
export declare const armProfileSchema: z.ZodObject<{
|
|
@@ -196,19 +196,40 @@ export declare const armProfileOutputSchema: {
|
|
|
196
196
|
updatedAt: z.ZodOptional<z.ZodUnknown>;
|
|
197
197
|
};
|
|
198
198
|
export declare const fileSchema: z.ZodObject<{
|
|
199
|
+
id: z.ZodOptional<z.ZodString>;
|
|
199
200
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
200
201
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
201
202
|
originalName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
202
203
|
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
204
|
+
size: z.ZodOptional<z.ZodUnknown>;
|
|
205
|
+
createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
206
|
+
updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
207
|
+
metadata: z.ZodOptional<z.ZodUnknown>;
|
|
203
208
|
}, z.core.$loose>;
|
|
204
209
|
export declare const fileListOutputSchema: {
|
|
205
210
|
result: z.ZodArray<z.ZodObject<{
|
|
211
|
+
id: z.ZodOptional<z.ZodString>;
|
|
206
212
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
207
213
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
208
214
|
originalName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
209
215
|
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
216
|
+
size: z.ZodOptional<z.ZodUnknown>;
|
|
217
|
+
createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
218
|
+
updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
219
|
+
metadata: z.ZodOptional<z.ZodUnknown>;
|
|
210
220
|
}, z.core.$loose>>;
|
|
211
221
|
};
|
|
222
|
+
export declare const fileOutputSchema: {
|
|
223
|
+
id: z.ZodOptional<z.ZodString>;
|
|
224
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
225
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
226
|
+
originalName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
227
|
+
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
228
|
+
size: z.ZodOptional<z.ZodUnknown>;
|
|
229
|
+
createdAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
230
|
+
updatedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
231
|
+
metadata: z.ZodOptional<z.ZodUnknown>;
|
|
232
|
+
};
|
|
212
233
|
export declare const subscriptionOutputSchema: {
|
|
213
234
|
messages: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
214
235
|
duration: z.ZodOptional<z.ZodUnknown>;
|
package/dist/schemas/misc.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.subscriptionOutputSchema = exports.fileListOutputSchema = exports.fileSchema = exports.armProfileOutputSchema = exports.armProfileListOutputSchema = exports.armProfileSchema = exports.liveviewListOutputSchema = exports.liveviewOutputSchema = exports.liveviewSchema = exports.ulpUserListOutputSchema = exports.ulpUserOutputSchema = exports.ulpUserSchema = exports.userListOutputSchema = exports.userOutputSchema = exports.userSchema = exports.nvrOutputSchema = exports.nvrSchema = exports.infoOutputSchema = void 0;
|
|
3
|
+
exports.subscriptionOutputSchema = exports.fileOutputSchema = exports.fileListOutputSchema = exports.fileSchema = exports.armProfileOutputSchema = exports.armProfileListOutputSchema = exports.armProfileSchema = exports.liveviewListOutputSchema = exports.liveviewOutputSchema = exports.liveviewSchema = exports.ulpUserListOutputSchema = exports.ulpUserOutputSchema = exports.ulpUserSchema = exports.userListOutputSchema = exports.userOutputSchema = exports.userSchema = exports.nvrOutputSchema = exports.nvrSchema = exports.infoOutputSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const common_js_1 = require("./common.js");
|
|
6
6
|
/**
|
|
7
7
|
* Schemas below are verified against live UniFi Protect Integration API 7.3.47
|
|
8
|
-
* responses (Melrose NVR Pro console, 2026-09-14) where instances exist
|
|
9
|
-
*
|
|
10
|
-
* instances on the console). The Integration API surface is much thinner than
|
|
8
|
+
* responses (Melrose NVR Pro console, 2026-09-14) where instances exist —
|
|
9
|
+
* re-verified live on 7.3.70 (2026-10-12) — and against the 7.3.70 published
|
|
10
|
+
* docs otherwise (arm profiles, files — no instances on the console). The Integration API surface is much thinner than
|
|
11
11
|
* the internal Protect app API — only observed/documented fields are typed;
|
|
12
12
|
* `.passthrough()` still allows anything extra a firmware/hardware mix adds.
|
|
13
13
|
*/
|
|
@@ -30,7 +30,7 @@ const doorbellSettingsSchema = (0, common_js_1.passthroughObject)({
|
|
|
30
30
|
defaultMessageText: (0, common_js_1.nullableString)("Default doorbell LCD message"),
|
|
31
31
|
defaultMessageResetTimeoutMs: (0, common_js_1.unknownField)("Reset timeout in ms (number)"),
|
|
32
32
|
customMessages: (0, common_js_1.unknownField)("Configured custom LCD messages (array of strings)"),
|
|
33
|
-
customImages: (0, common_js_1.unknownField)("Configured custom LCD images (array)"),
|
|
33
|
+
customImages: (0, common_js_1.unknownField)("Configured custom LCD images (array of objects: preview, sprite)"),
|
|
34
34
|
});
|
|
35
35
|
exports.nvrSchema = (0, common_js_1.passthroughObject)({
|
|
36
36
|
id: (0, common_js_1.idField)("NVR ID"),
|
|
@@ -38,8 +38,8 @@ exports.nvrSchema = (0, common_js_1.passthroughObject)({
|
|
|
38
38
|
name: (0, common_js_1.nullableString)("NVR name"),
|
|
39
39
|
...(0, common_js_1.hardwareModelFields)(),
|
|
40
40
|
mac: (0, common_js_1.nullableString)("MAC address, added in 7.3.x"),
|
|
41
|
-
doorbellSettings: doorbellSettingsSchema.optional(),
|
|
42
|
-
armMode: armModeSchema.optional(),
|
|
41
|
+
doorbellSettings: doorbellSettingsSchema.nullable().optional(),
|
|
42
|
+
armMode: armModeSchema.nullable().optional(),
|
|
43
43
|
});
|
|
44
44
|
// Single object — use the shape directly, NOT a list wrapper.
|
|
45
45
|
exports.nvrOutputSchema = { ...exports.nvrSchema.shape };
|
|
@@ -62,7 +62,7 @@ exports.ulpUserSchema = (0, common_js_1.passthroughObject)({
|
|
|
62
62
|
lastName: (0, common_js_1.nullableString)("Last name"),
|
|
63
63
|
fullName: (0, common_js_1.nullableString)("Full name"),
|
|
64
64
|
email: (0, common_js_1.nullableString)("Email address, added in 7.3.x. Empty string for service accounts " +
|
|
65
|
-
"(verified live 7.3.
|
|
65
|
+
"(verified live 7.3.70)"),
|
|
66
66
|
status: (0, common_js_1.nullableString)("Account status, e.g. ACTIVE"),
|
|
67
67
|
});
|
|
68
68
|
exports.ulpUserOutputSchema = { ...exports.ulpUserSchema.shape };
|
|
@@ -81,12 +81,12 @@ exports.liveviewSchema = (0, common_js_1.passthroughObject)({
|
|
|
81
81
|
isGlobal: (0, common_js_1.unknownField)("Whether shared across all users (boolean)"),
|
|
82
82
|
layout: (0, common_js_1.unknownField)("Grid layout / slot count (number)"),
|
|
83
83
|
owner: (0, common_js_1.nullableString)("Owning user ID"),
|
|
84
|
-
slots: zod_1.z.array(liveviewSlotSchema).optional().describe("Camera slots"),
|
|
84
|
+
slots: zod_1.z.array(liveviewSlotSchema).nullable().optional().describe("Camera slots"),
|
|
85
85
|
});
|
|
86
86
|
exports.liveviewOutputSchema = { ...exports.liveviewSchema.shape };
|
|
87
87
|
exports.liveviewListOutputSchema = (0, common_js_1.listResultSchema)(exports.liveviewSchema);
|
|
88
88
|
// --- Arm profiles ---
|
|
89
|
-
// Fields from the 7.
|
|
89
|
+
// Fields from the 7.3.70 docs (no instances on the console to verify live).
|
|
90
90
|
// Arm profiles carry no `modelKey`. Nested arrays stay unknownField.
|
|
91
91
|
exports.armProfileSchema = (0, common_js_1.passthroughObject)({
|
|
92
92
|
id: (0, common_js_1.idField)("Arm profile ID"),
|
|
@@ -102,15 +102,22 @@ exports.armProfileSchema = (0, common_js_1.passthroughObject)({
|
|
|
102
102
|
exports.armProfileListOutputSchema = (0, common_js_1.listResultSchema)(exports.armProfileSchema);
|
|
103
103
|
exports.armProfileOutputSchema = { ...exports.armProfileSchema.shape };
|
|
104
104
|
// --- Files ---
|
|
105
|
-
// Device asset files (only fileType=animations supported).
|
|
106
|
-
//
|
|
105
|
+
// Device asset files (only fileType=animations supported). The 7.3.70 docs show
|
|
106
|
+
// { name, type, originalName, path }; live 7.3.70 records (2026-10-12) also
|
|
107
|
+
// carry id (equal to name), size, createdAt, updatedAt and metadata. No modelKey.
|
|
107
108
|
exports.fileSchema = (0, common_js_1.passthroughObject)({
|
|
109
|
+
id: (0, common_js_1.idField)("File ID (same value as name)"),
|
|
108
110
|
name: (0, common_js_1.nullableString)("Stored file name (server-generated)"),
|
|
109
111
|
type: (0, common_js_1.nullableString)('Asset file type, e.g. "animations"'),
|
|
110
|
-
originalName: (0, common_js_1.nullableString)(
|
|
112
|
+
originalName: (0, common_js_1.nullableString)('Uploaded file name; Protect appends the stored extension, e.g. "welcome.gif.png"'),
|
|
111
113
|
path: (0, common_js_1.nullableString)("Server-side storage path"),
|
|
114
|
+
size: (0, common_js_1.unknownField)("File size in bytes (number)"),
|
|
115
|
+
createdAt: (0, common_js_1.nullableString)("Creation time (ISO 8601)"),
|
|
116
|
+
updatedAt: (0, common_js_1.nullableString)("Last update time (ISO 8601)"),
|
|
117
|
+
metadata: (0, common_js_1.unknownField)("Asset metadata (object, empty in observed records)"),
|
|
112
118
|
});
|
|
113
119
|
exports.fileListOutputSchema = (0, common_js_1.listResultSchema)(exports.fileSchema);
|
|
120
|
+
exports.fileOutputSchema = { ...exports.fileSchema.shape };
|
|
114
121
|
// --- Subscriptions ---
|
|
115
122
|
exports.subscriptionOutputSchema = {
|
|
116
123
|
messages: zod_1.z
|
package/dist/schemas/pos.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Point-of-sale event ingestion, added in UniFi Protect 7.3.x
|
|
3
3
|
* (POST /v1/pos/cameras/{id}/transactions).
|
|
4
4
|
*
|
|
5
|
-
* Shape taken from the 7.3.
|
|
5
|
+
* Shape taken from the 7.3.70 published docs with the response sample expanded
|
|
6
6
|
* — there is no POS-capable register on the available console, so this is
|
|
7
7
|
* doc-verified rather than live-verified. `created` stays `unknownField()`
|
|
8
8
|
* because we have not observed the boolean live; `eventId` publishes the string
|
package/dist/schemas/pos.js
CHANGED
|
@@ -6,7 +6,7 @@ const common_js_1 = require("./common.js");
|
|
|
6
6
|
* Point-of-sale event ingestion, added in UniFi Protect 7.3.x
|
|
7
7
|
* (POST /v1/pos/cameras/{id}/transactions).
|
|
8
8
|
*
|
|
9
|
-
* Shape taken from the 7.3.
|
|
9
|
+
* Shape taken from the 7.3.70 published docs with the response sample expanded
|
|
10
10
|
* — there is no POS-capable register on the available console, so this is
|
|
11
11
|
* doc-verified rather than live-verified. `created` stays `unknownField()`
|
|
12
12
|
* because we have not observed the boolean live; `eventId` publishes the string
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerAlarmManagerTools = registerAlarmManagerTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const responses_js_1 = require("../utils/responses.js");
|
|
6
|
+
const safety_js_1 = require("../utils/safety.js");
|
|
7
|
+
const url_js_1 = require("../utils/url.js");
|
|
8
|
+
function registerAlarmManagerTools(server, client, readOnly) {
|
|
9
|
+
if (readOnly)
|
|
10
|
+
return;
|
|
11
|
+
server.registerTool("protect_trigger_alarm_webhook", {
|
|
12
|
+
description: "Trigger an alarm manager webhook by ID. This fires an external alarm action.",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
id: zod_1.z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.describe("User-defined webhook ID matching an alarm manager configuration"),
|
|
18
|
+
confirm: zod_1.z
|
|
19
|
+
.literal(true)
|
|
20
|
+
.describe("Must be true to confirm triggering the alarm webhook"),
|
|
21
|
+
dryRun: zod_1.z
|
|
22
|
+
.boolean()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("If true, return what would happen without making changes"),
|
|
25
|
+
},
|
|
26
|
+
annotations: safety_js_1.DESTRUCTIVE,
|
|
27
|
+
}, async ({ id, confirm, dryRun }) => {
|
|
28
|
+
const denied = (0, safety_js_1.requireConfirmation)(confirm, "trigger the alarm webhook");
|
|
29
|
+
if (denied)
|
|
30
|
+
return denied;
|
|
31
|
+
try {
|
|
32
|
+
if (dryRun) {
|
|
33
|
+
return (0, safety_js_1.formatDryRun)("POST", (0, url_js_1.safePath) `/alarm-manager/webhook/${id}`);
|
|
34
|
+
}
|
|
35
|
+
await client.post((0, url_js_1.safePath) `/alarm-manager/webhook/${id}`);
|
|
36
|
+
return (0, responses_js_1.formatSuccess)({ triggered: true, webhookId: id });
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return (0, responses_js_1.formatError)(err);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|