rhombus-node-mcp 0.1.23 → 0.1.26

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.
Files changed (41) hide show
  1. package/dist/api/access-control-tool-api.js +1 -1
  2. package/dist/api/alarm-monitoring-tool-api.js +1 -1
  3. package/dist/api/camera-tool-api.js +1 -1
  4. package/dist/api/camera-uptime-tool-api.js +1 -1
  5. package/dist/api/clips-tool-api.js +1 -1
  6. package/dist/api/create-camera-policy-tool-api.js +1 -1
  7. package/dist/api/create-tool-api.js +1 -1
  8. package/dist/api/door-schedule-exception-tool-api.js +199 -0
  9. package/dist/api/door-tool-api.js +1 -1
  10. package/dist/api/entity-lookup-tool-api.js +1 -1
  11. package/dist/api/events-tool-api.js +1 -1
  12. package/dist/api/faces-tool-api.js +1 -1
  13. package/dist/api/get-entity-tool-api.js +12 -11
  14. package/dist/api/get-org-information-tool-api.js +1 -1
  15. package/dist/api/guest-management-tool-api.js +1 -1
  16. package/dist/api/location-tool-api.js +1 -1
  17. package/dist/api/lpr-tool-api.js +1 -1
  18. package/dist/api/policy-alerts-tool-api.js +1 -1
  19. package/dist/api/reboot-cameras-tool-api.js +1 -1
  20. package/dist/api/report-tool-api.js +1 -1
  21. package/dist/api/rules-tool-api.js +1 -1
  22. package/dist/api/search-tool-api.js +1 -1
  23. package/dist/api/update-tool-api.js +1 -1
  24. package/dist/api/user-access-trail-tool-api.js +1 -1
  25. package/dist/api/user-audit-tool-api.js +1 -1
  26. package/dist/api/user-tool-api.js +1 -1
  27. package/dist/createServer.js +1 -0
  28. package/dist/filtering-utils.js +15 -7
  29. package/dist/network/locations.js +60 -0
  30. package/dist/{network.js → network/network.js} +8 -3
  31. package/dist/network/postApiMap.js +7 -0
  32. package/dist/tools/analytics-tool.js +1 -1
  33. package/dist/tools/create-camera-policy-tool.js +1 -1
  34. package/dist/tools/door-schedule-exception-tool.js +113 -0
  35. package/dist/types/access-control-tool-types.js +1 -1
  36. package/dist/types/door-schedule-exception-tool-types.js +160 -0
  37. package/dist/types/report-tool-types.js +7 -7
  38. package/dist/types/user-tool-types.js +1 -1
  39. package/dist/types/zod-schemas.js +670 -665
  40. package/dist/utils/timestampInput.js +5 -8
  41. package/package.json +4 -4
@@ -0,0 +1,113 @@
1
+ import { createDoorScheduleException, deleteDoorScheduleException, findDoorScheduleExceptions, findDoorScheduleExceptionsForDoor, findDoorScheduleExceptionsForLocation, getDoorScheduleException, updateDoorScheduleException, } from "../api/door-schedule-exception-tool-api.js";
2
+ import { DoorScheduleExceptionRequestType, OUTPUT_SCHEMA, TOOL_ARGS, } from "../types/door-schedule-exception-tool-types.js";
3
+ import { createToolStructuredContent, createToolTextContent, extractFromToolExtra, } from "../util.js";
4
+ const TOOL_NAME = "door-schedule-exception-tool";
5
+ const TOOL_DESCRIPTION = `
6
+ This tool manages Rhombus door schedule exceptions.
7
+ A door lock/unlock exception is a one-time rule used to change an access controlled door's locked/unlocked state.
8
+ If a lock/unlock exception is enabled, it will overwrite the existing lock/unlock schedule.
9
+ A schedule exception allows you to create a custom schedule that is only active for the specified dates/times.
10
+ Once the date/time a schedule exception is set for passes, the original schedule will resume.
11
+
12
+ It has the following modes of operation, determined by the "requestType" parameter:
13
+ - ${DoorScheduleExceptionRequestType.CREATE_EXCEPTION}: Create a door schedule exception. Requires exception (DoorScheduleExceptionType object). If locationUuid is missing but doorUuids are provided, the tool will resolve the location automatically.
14
+ - ${DoorScheduleExceptionRequestType.DELETE_EXCEPTION}: Delete a door schedule exception. Requires exceptionUuid.
15
+ - ${DoorScheduleExceptionRequestType.FIND_EXCEPTIONS}: Find door schedule exceptions across the organization, optionally filtered by date range.
16
+ - ${DoorScheduleExceptionRequestType.FIND_EXCEPTIONS_FOR_LOCATION}: Find door schedule exceptions for a location. Requires locationUuid. Supports optional date range filters.
17
+ - ${DoorScheduleExceptionRequestType.FIND_EXCEPTIONS_FOR_DOOR}: Find door schedule exceptions for a door. Requires doorUuid. Supports optional date range filters.
18
+ - ${DoorScheduleExceptionRequestType.GET_EXCEPTION}: Get a single door schedule exception by UUID. Requires exceptionUuid.
19
+ - ${DoorScheduleExceptionRequestType.UPDATE_EXCEPTION}: Update a door schedule exception. Requires exception (DoorScheduleExceptionType object). If intervals are omitted but defaultState and date range are provided, the tool will generate a full-day interval.
20
+
21
+ Use get-entity-tool to look up location and door UUIDs when needed.
22
+ `;
23
+ function buildDateRangeFilter(args) {
24
+ return {
25
+ localStartDateRangeStart: args.localStartDateRangeStart ?? undefined,
26
+ localStartDateRangeEnd: args.localStartDateRangeEnd ?? undefined,
27
+ localEndDateRangeStart: args.localEndDateRangeStart ?? undefined,
28
+ localEndDateRangeEnd: args.localEndDateRangeEnd ?? undefined,
29
+ };
30
+ }
31
+ const TOOL_HANDLER = async (args, _extra) => {
32
+ const { requestModifiers, sessionId } = extractFromToolExtra(_extra);
33
+ try {
34
+ switch (args.requestType) {
35
+ case DoorScheduleExceptionRequestType.CREATE_EXCEPTION: {
36
+ if (!args.exception) {
37
+ return createToolTextContent(JSON.stringify({
38
+ error: "exception is required for create-exception.",
39
+ }));
40
+ }
41
+ const created = await createDoorScheduleException(args.exception, requestModifiers, sessionId);
42
+ return createToolStructuredContent(created);
43
+ }
44
+ case DoorScheduleExceptionRequestType.DELETE_EXCEPTION: {
45
+ if (!args.exceptionUuid) {
46
+ return createToolTextContent(JSON.stringify({
47
+ error: "exceptionUuid is required for delete-exception.",
48
+ }));
49
+ }
50
+ const deleted = await deleteDoorScheduleException(args.exceptionUuid, requestModifiers, sessionId);
51
+ return createToolStructuredContent(deleted);
52
+ }
53
+ case DoorScheduleExceptionRequestType.FIND_EXCEPTIONS: {
54
+ const results = await findDoorScheduleExceptions(buildDateRangeFilter(args), requestModifiers, sessionId);
55
+ return createToolStructuredContent(results);
56
+ }
57
+ case DoorScheduleExceptionRequestType.FIND_EXCEPTIONS_FOR_LOCATION: {
58
+ if (!args.locationUuid) {
59
+ return createToolTextContent(JSON.stringify({
60
+ error: "locationUuid is required for find-exceptions-for-location.",
61
+ }));
62
+ }
63
+ const results = await findDoorScheduleExceptionsForLocation(args.locationUuid, buildDateRangeFilter(args), requestModifiers, sessionId);
64
+ return createToolStructuredContent(results);
65
+ }
66
+ case DoorScheduleExceptionRequestType.FIND_EXCEPTIONS_FOR_DOOR: {
67
+ if (!args.doorUuid) {
68
+ return createToolTextContent(JSON.stringify({
69
+ error: "doorUuid is required for find-exceptions-for-door.",
70
+ }));
71
+ }
72
+ const results = await findDoorScheduleExceptionsForDoor(args.doorUuid, buildDateRangeFilter(args), requestModifiers, sessionId);
73
+ return createToolStructuredContent(results);
74
+ }
75
+ case DoorScheduleExceptionRequestType.GET_EXCEPTION: {
76
+ if (!args.exceptionUuid) {
77
+ return createToolTextContent(JSON.stringify({
78
+ error: "exceptionUuid is required for get-exception.",
79
+ }));
80
+ }
81
+ const exception = await getDoorScheduleException(args.exceptionUuid, requestModifiers, sessionId);
82
+ return createToolStructuredContent(exception);
83
+ }
84
+ case DoorScheduleExceptionRequestType.UPDATE_EXCEPTION: {
85
+ if (!args.exception) {
86
+ return createToolTextContent(JSON.stringify({
87
+ error: "exception is required for update-exception.",
88
+ }));
89
+ }
90
+ const updated = await updateDoorScheduleException(args.exception, requestModifiers, sessionId);
91
+ return createToolStructuredContent(updated);
92
+ }
93
+ }
94
+ }
95
+ catch (error) {
96
+ if (error instanceof Error) {
97
+ return createToolStructuredContent({
98
+ error: error.message,
99
+ });
100
+ }
101
+ return createToolStructuredContent({
102
+ error: "Unknown error",
103
+ });
104
+ }
105
+ return createToolStructuredContent({ error: "Invalid request type" });
106
+ };
107
+ export function createTool(server) {
108
+ server.registerTool(TOOL_NAME, {
109
+ description: TOOL_DESCRIPTION,
110
+ inputSchema: TOOL_ARGS,
111
+ outputSchema: OUTPUT_SCHEMA.shape,
112
+ }, TOOL_HANDLER);
113
+ }
@@ -13,7 +13,7 @@ export var AccessControlRequestType;
13
13
  AccessControlRequestType["GET_REMOTE_UNLOCK_USERS"] = "get-remote-unlock-users";
14
14
  })(AccessControlRequestType || (AccessControlRequestType = {}));
15
15
  export const TOOL_ARGS = {
16
- requestType: z.nativeEnum(AccessControlRequestType).describe("The type of access control request to make."),
16
+ requestType: z.enum(AccessControlRequestType).describe("The type of access control request to make."),
17
17
  doorUuid: z
18
18
  .string()
19
19
  .nullable()
@@ -0,0 +1,160 @@
1
+ import { z } from "zod";
2
+ import { FILTER_BY_ARG, INCLUDE_FIELDS_ARG } from "../util.js";
3
+ import { AccessControlledDoorStateEnumType } from "./schema.js";
4
+ export var DoorScheduleExceptionRequestType;
5
+ (function (DoorScheduleExceptionRequestType) {
6
+ DoorScheduleExceptionRequestType["CREATE_EXCEPTION"] = "create-exception";
7
+ DoorScheduleExceptionRequestType["DELETE_EXCEPTION"] = "delete-exception";
8
+ DoorScheduleExceptionRequestType["FIND_EXCEPTIONS"] = "find-exceptions";
9
+ DoorScheduleExceptionRequestType["FIND_EXCEPTIONS_FOR_LOCATION"] = "find-exceptions-for-location";
10
+ DoorScheduleExceptionRequestType["FIND_EXCEPTIONS_FOR_DOOR"] = "find-exceptions-for-door";
11
+ DoorScheduleExceptionRequestType["GET_EXCEPTION"] = "get-exception";
12
+ DoorScheduleExceptionRequestType["UPDATE_EXCEPTION"] = "update-exception";
13
+ })(DoorScheduleExceptionRequestType || (DoorScheduleExceptionRequestType = {}));
14
+ export const DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA = z
15
+ .object({
16
+ createdAtMillis: z.number().nullable(),
17
+ defaultState: z.enum(AccessControlledDoorStateEnumType).nullable(),
18
+ description: z.string().nullable(),
19
+ doorUuids: z.array(z.string().nullable()).nullable().optional(),
20
+ intervals: z
21
+ .array(z.object({
22
+ localEndDateTime: z.string().nullable(),
23
+ localStartDateTime: z.string().nullable(),
24
+ state: z.enum(AccessControlledDoorStateEnumType),
25
+ }))
26
+ .nullable(),
27
+ localEndDate: z.string().nullable(),
28
+ localStartDate: z.string().nullable(),
29
+ locationToDoorsMap: z
30
+ .record(z.string(), z.array(z.string().nullable()).nullable())
31
+ .nullable()
32
+ .optional(),
33
+ name: z.string().nullable(),
34
+ updatedAtMillis: z.number().nullable(),
35
+ })
36
+ .superRefine((value, ctx) => {
37
+ if (!value.name) {
38
+ ctx.addIssue({
39
+ code: z.ZodIssueCode.custom,
40
+ message: "exception.name is required.",
41
+ path: ["name"],
42
+ });
43
+ }
44
+ if (!value.localStartDate) {
45
+ ctx.addIssue({
46
+ code: z.ZodIssueCode.custom,
47
+ message: "exception.localStartDate is required.",
48
+ path: ["localStartDate"],
49
+ });
50
+ }
51
+ if (!value.localEndDate) {
52
+ ctx.addIssue({
53
+ code: z.ZodIssueCode.custom,
54
+ message: "exception.localEndDate is required.",
55
+ path: ["localEndDate"],
56
+ });
57
+ }
58
+ if (!value.intervals || value.intervals.length === 0) {
59
+ ctx.addIssue({
60
+ code: z.ZodIssueCode.custom,
61
+ message: "exception.intervals must contain at least one interval.",
62
+ path: ["intervals"],
63
+ });
64
+ }
65
+ const hasDoorUuids = (value.doorUuids?.filter((doorUuid) => !!doorUuid).length ?? 0) > 0;
66
+ const hasLocationToDoorsMap = Object.values(value.locationToDoorsMap ?? {})
67
+ .flatMap((doorUuids) => doorUuids ?? [])
68
+ .some((doorUuid) => !!doorUuid);
69
+ if (!hasDoorUuids && !hasLocationToDoorsMap) {
70
+ ctx.addIssue({
71
+ code: z.ZodIssueCode.custom,
72
+ message: "exception must include at least one door in doorUuids or locationToDoorsMap.",
73
+ path: ["doorUuids"],
74
+ });
75
+ }
76
+ });
77
+ export const TOOL_ARGS = {
78
+ requestType: z
79
+ .nativeEnum(DoorScheduleExceptionRequestType)
80
+ .describe("The type of door schedule exception request to make."),
81
+ exceptionUuid: z
82
+ .string()
83
+ .nullable()
84
+ .describe("Door schedule exception UUID. Required for 'get-exception' and 'delete-exception'."),
85
+ locationUuid: z
86
+ .string()
87
+ .nullable()
88
+ .describe("Location UUID. Required for 'find-exceptions-for-location'."),
89
+ doorUuid: z
90
+ .string()
91
+ .nullable()
92
+ .describe("Door UUID. Required for 'find-exceptions-for-door'."),
93
+ exception: DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA.nullable().describe("DoorScheduleExceptionType object. Required for 'create-exception' and 'update-exception'."),
94
+ localStartDateRangeStart: z.iso
95
+ .datetime({ offset: true })
96
+ .optional()
97
+ .nullable()
98
+ .describe("Optional date range filter (inclusive) for local start date beginning (yyyy-MM-dd)."),
99
+ localStartDateRangeEnd: z.iso
100
+ .datetime({ offset: true })
101
+ .optional()
102
+ .nullable()
103
+ .describe("Optional date range filter (inclusive) for local start date end (yyyy-MM-dd)."),
104
+ localEndDateRangeStart: z.iso
105
+ .datetime({ offset: true })
106
+ .optional()
107
+ .nullable()
108
+ .describe("Optional date range filter (inclusive) for local end date beginning (yyyy-MM-dd)."),
109
+ localEndDateRangeEnd: z.iso
110
+ .datetime({ offset: true })
111
+ .optional()
112
+ .nullable()
113
+ .describe("Optional date range filter (inclusive) for local end date end (yyyy-MM-dd)."),
114
+ includeFields: INCLUDE_FIELDS_ARG,
115
+ filterBy: FILTER_BY_ARG,
116
+ };
117
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
118
+ const EXCEPTION_SCHEMA = z.object({
119
+ uuid: z.string().optional(),
120
+ name: z.string().optional(),
121
+ description: z.string().optional(),
122
+ locationUuid: z.string().optional(),
123
+ localStartDate: z.string().optional(),
124
+ localEndDate: z.string().optional(),
125
+ defaultState: z.string().optional(),
126
+ doorUuids: z.array(z.string()).optional(),
127
+ intervalCount: z.number().optional(),
128
+ createdAtMillis: z.number().optional(),
129
+ updatedAtMillis: z.number().optional(),
130
+ });
131
+ export const OUTPUT_SCHEMA = z.object({
132
+ exception: EXCEPTION_SCHEMA.optional().describe("Single door schedule exception result."),
133
+ exceptions: z
134
+ .array(EXCEPTION_SCHEMA)
135
+ .optional()
136
+ .describe("List of door schedule exceptions."),
137
+ deleted: z
138
+ .object({
139
+ success: z.boolean().optional(),
140
+ exceptionUuid: z.string().optional(),
141
+ })
142
+ .optional()
143
+ .describe("Delete result."),
144
+ expiredACDLicensesDoorUuids: z
145
+ .array(z.string())
146
+ .optional()
147
+ .describe("Door UUIDs with expired access control licenses."),
148
+ unassignedACDLicensesDoorUuids: z
149
+ .array(z.string())
150
+ .optional()
151
+ .describe("Door UUIDs with unassigned access control licenses."),
152
+ warningMsg: z
153
+ .string()
154
+ .optional()
155
+ .describe("Warning returned by backend, if any."),
156
+ error: z
157
+ .string()
158
+ .optional()
159
+ .describe("An error message if the request failed."),
160
+ });
@@ -263,7 +263,7 @@ export const SanitizedTimeSeriesDataPoint = z.object({
263
263
  dateUtcString: z
264
264
  .optional(z.string())
265
265
  .describe("The UTC date of the data point in ISO 8601 format"),
266
- eventCountMap: z.optional(z.record(z.any())),
266
+ eventCountMap: z.optional(z.record(z.string(), z.any())),
267
267
  });
268
268
  const FaceCountEnrichment = z.object({
269
269
  uniqueFaceCount: z.number().describe("Number of unique people identified by face recognition in the same time range"),
@@ -299,12 +299,12 @@ export const OUTPUT_SCHEMA = z.object({
299
299
  error: z.optional(z.boolean()),
300
300
  errorMsg: z.optional(z.string()),
301
301
  timeSeriesDataPoints: z.optional(z.array(z.object({
302
- approximateTimestampMsMap: z.optional(z.record(z.unknown())),
302
+ approximateTimestampMsMap: z.optional(z.record(z.string(), z.unknown())),
303
303
  dateLocal: z.optional(z.string()),
304
304
  dateUtc: z.optional(z.string()),
305
305
  dateLocalString: z.optional(z.string()),
306
306
  dateUtcString: z.optional(z.string()),
307
- eventCountMap: z.optional(z.record(z.unknown())),
307
+ eventCountMap: z.optional(z.record(z.string(), z.unknown())),
308
308
  timestampMs: z.optional(z.number()),
309
309
  }))),
310
310
  faceCountEnrichment: z
@@ -328,7 +328,7 @@ export const OUTPUT_SCHEMA = z.object({
328
328
  name: z.optional(z.string()),
329
329
  serialNumber: z.optional(z.string()),
330
330
  locationUuid: z.optional(z.string()),
331
- facetNameMap: z.optional(z.record(z.string().nullable())),
331
+ facetNameMap: z.optional(z.record(z.string(), z.string().nullable())),
332
332
  deleted: z.optional(z.boolean()),
333
333
  pending: z.optional(z.boolean()),
334
334
  mummified: z.optional(z.boolean()),
@@ -340,7 +340,7 @@ export const OUTPUT_SCHEMA = z.object({
340
340
  .optional(z.object({
341
341
  error: z.optional(z.boolean()),
342
342
  errorMsg: z.optional(z.string()),
343
- camerasToConfigs: z.optional(z.record(z.unknown())),
343
+ camerasToConfigs: z.optional(z.record(z.string(), z.unknown())),
344
344
  }))
345
345
  .nullable()
346
346
  .describe("Cameras at a location that have line crossing enabled with their configurations"),
@@ -438,7 +438,7 @@ export const OUTPUT_SCHEMA = z.object({
438
438
  timeSeriesDataPoints: z.optional(z.array(z.object({
439
439
  dateLocal: z.optional(z.string()),
440
440
  dateUtc: z.optional(z.string()),
441
- eventCountMap: z.optional(z.record(z.union([z.number(), z.boolean(), z.string()]))),
441
+ eventCountMap: z.optional(z.record(z.string(), z.union([z.number(), z.boolean(), z.string()]))),
442
442
  }))),
443
443
  }))
444
444
  .nullable()
@@ -492,7 +492,7 @@ export const OUTPUT_SCHEMA = z.object({
492
492
  timeSeriesDataPoints: z.optional(z.array(z.object({
493
493
  dateLocal: z.optional(z.string()),
494
494
  dateUtc: z.optional(z.string()),
495
- eventCountMap: z.optional(z.record(z.any())),
495
+ eventCountMap: z.optional(z.record(z.string(), z.any())),
496
496
  }))),
497
497
  }))
498
498
  .describe("Custom events report time series"),
@@ -44,7 +44,7 @@ export const OUTPUT_SCHEMA = z.object({
44
44
  permissions: z
45
45
  .object({
46
46
  role: z.string().optional(),
47
- functionalityAccessMap: z.record(z.string()).optional(),
47
+ functionalityAccessMap: z.record(z.string(), z.string()).optional(),
48
48
  })
49
49
  .optional()
50
50
  .describe("Current user permissions"),