rhombus-node-mcp
Version:
MCP server for Rhombus API
69 lines (68 loc) • 3.54 kB
JavaScript
import { z } from "zod";
import { createUuidSchema } from "../types.js";
import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
export const TOOL_ARGS = {
area: z.string().nullable().describe("Optional: restrict to events entering this area (full-text)."),
locationUuids: z.array(createUuidSchema()).nullable().describe("Optional: restrict to these location UUIDs."),
deviceUuids: z.array(createUuidSchema()).nullable().describe("Optional: restrict to these camera UUIDs."),
startTime: z
.string()
.datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
.nullable()
.describe("Start of the window to scan for lost/inactive-badge use (inclusive). " + ISOTimestampFormatDescription),
endTime: z
.string()
.datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
.nullable()
.describe("End of the window (inclusive). " + ISOTimestampFormatDescription),
faceWindowSeconds: z
.number()
.nullable()
.describe("± seconds around each badge event to look for the face at the door (default 30)."),
limit: z.number().nullable().describe("Max badge events to scan in the window (default 50)."),
timeZone: z
.string()
.nullable()
.describe("IANA timezone for formatting times, e.g. America/New_York. Defaults to UTC."),
};
const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
const ClipHintSchema = z.object({ deviceUuid: z.string(), startTimeMs: z.number(), endTimeMs: z.number() });
const StillHintSchema = z.object({ deviceUuid: z.string(), timestampMs: z.number() });
const FaceAtDoorSchema = z.object({
faceName: z.string().optional().describe('Recognized name, or absent/UNIDENTIFIED if no enrolled match.'),
personUuid: z.string().optional(),
thumbnailS3Key: z.string().optional().describe("Face crop thumbnail key for display."),
faceEventUuid: z.string().optional(),
eventTimestamp: z.string().optional(),
});
const SightingSchema = z.object({
deviceUuid: z.string().optional().describe("Camera where the same face was seen."),
datetime: z.string().optional(),
timestampMs: z.number().optional(),
similarity: z.number().optional(),
personUuid: z.string().optional(),
});
export const LostBadgeIncidentSchema = z.object({
cardholderOfRecord: z.string().optional().describe("The cardholder the badge is registered to (may not be who used it)."),
badgeStatus: z.string().optional(),
datetime: z.string().optional(),
timestampMs: z.number().optional(),
deviceUuid: z.string().optional().describe("Door camera. Pass to camera-tool (image) / clips-tool (createClip)."),
area: z.string().optional(),
clipHint: ClipHintSchema.optional(),
stillHint: StillHintSchema.optional(),
facesAtDoor: z.array(FaceAtDoorSchema).optional().describe("Face(s) captured at the door at the time of use."),
sightings: z
.array(SightingSchema)
.optional()
.describe("Same face seen across cameras, ordered in time — the track after the door."),
lastKnownSighting: z
.object({ deviceUuid: z.string().optional(), datetime: z.string().optional() })
.optional()
.describe("Most recent sighting — the person's last-known location."),
});
export const OUTPUT_SCHEMA = z.object({
incidents: z.array(LostBadgeIncidentSchema).optional(),
count: z.number().optional(),
error: z.string().optional(),
});