@butlr/butlr-mcp-server 0.1.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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/cache/occupancy-cache.d.ts +72 -0
- package/dist/cache/occupancy-cache.d.ts.map +1 -0
- package/dist/cache/occupancy-cache.js +166 -0
- package/dist/cache/occupancy-cache.js.map +1 -0
- package/dist/cache/topology-cache.d.ts +36 -0
- package/dist/cache/topology-cache.d.ts.map +1 -0
- package/dist/cache/topology-cache.js +74 -0
- package/dist/cache/topology-cache.js.map +1 -0
- package/dist/clients/auth-client.d.ts +22 -0
- package/dist/clients/auth-client.d.ts.map +1 -0
- package/dist/clients/auth-client.js +82 -0
- package/dist/clients/auth-client.js.map +1 -0
- package/dist/clients/graphql-client.d.ts +6 -0
- package/dist/clients/graphql-client.d.ts.map +1 -0
- package/dist/clients/graphql-client.js +106 -0
- package/dist/clients/graphql-client.js.map +1 -0
- package/dist/clients/queries/topology.d.ts +36 -0
- package/dist/clients/queries/topology.d.ts.map +1 -0
- package/dist/clients/queries/topology.js +252 -0
- package/dist/clients/queries/topology.js.map +1 -0
- package/dist/clients/reporting-client.d.ts +191 -0
- package/dist/clients/reporting-client.d.ts.map +1 -0
- package/dist/clients/reporting-client.js +353 -0
- package/dist/clients/reporting-client.js.map +1 -0
- package/dist/clients/stats-client.d.ts +119 -0
- package/dist/clients/stats-client.d.ts.map +1 -0
- package/dist/clients/stats-client.js +238 -0
- package/dist/clients/stats-client.js.map +1 -0
- package/dist/clients/types.d.ts +215 -0
- package/dist/clients/types.d.ts.map +1 -0
- package/dist/clients/types.js +6 -0
- package/dist/clients/types.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors/mcp-errors.d.ts +63 -0
- package/dist/errors/mcp-errors.d.ts.map +1 -0
- package/dist/errors/mcp-errors.js +144 -0
- package/dist/errors/mcp-errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/butlr-available-rooms.d.ts +49 -0
- package/dist/tools/butlr-available-rooms.d.ts.map +1 -0
- package/dist/tools/butlr-available-rooms.js +492 -0
- package/dist/tools/butlr-available-rooms.js.map +1 -0
- package/dist/tools/butlr-fetch-entity-details.d.ts +42 -0
- package/dist/tools/butlr-fetch-entity-details.d.ts.map +1 -0
- package/dist/tools/butlr-fetch-entity-details.js +276 -0
- package/dist/tools/butlr-fetch-entity-details.js.map +1 -0
- package/dist/tools/butlr-get-asset-details.d.ts +51 -0
- package/dist/tools/butlr-get-asset-details.d.ts.map +1 -0
- package/dist/tools/butlr-get-asset-details.js +391 -0
- package/dist/tools/butlr-get-asset-details.js.map +1 -0
- package/dist/tools/butlr-get-current-occupancy.d.ts +21 -0
- package/dist/tools/butlr-get-current-occupancy.d.ts.map +1 -0
- package/dist/tools/butlr-get-current-occupancy.js +126 -0
- package/dist/tools/butlr-get-current-occupancy.js.map +1 -0
- package/dist/tools/butlr-get-occupancy-timeseries.d.ts +31 -0
- package/dist/tools/butlr-get-occupancy-timeseries.d.ts.map +1 -0
- package/dist/tools/butlr-get-occupancy-timeseries.js +145 -0
- package/dist/tools/butlr-get-occupancy-timeseries.js.map +1 -0
- package/dist/tools/butlr-hardware-snapshot.d.ts +55 -0
- package/dist/tools/butlr-hardware-snapshot.d.ts.map +1 -0
- package/dist/tools/butlr-hardware-snapshot.js +556 -0
- package/dist/tools/butlr-hardware-snapshot.js.map +1 -0
- package/dist/tools/butlr-list-topology.d.ts +27 -0
- package/dist/tools/butlr-list-topology.d.ts.map +1 -0
- package/dist/tools/butlr-list-topology.js +241 -0
- package/dist/tools/butlr-list-topology.js.map +1 -0
- package/dist/tools/butlr-search-assets.d.ts +53 -0
- package/dist/tools/butlr-search-assets.d.ts.map +1 -0
- package/dist/tools/butlr-search-assets.js +206 -0
- package/dist/tools/butlr-search-assets.js.map +1 -0
- package/dist/tools/butlr-space-busyness.d.ts +23 -0
- package/dist/tools/butlr-space-busyness.d.ts.map +1 -0
- package/dist/tools/butlr-space-busyness.js +304 -0
- package/dist/tools/butlr-space-busyness.js.map +1 -0
- package/dist/tools/butlr-traffic-flow.d.ts +39 -0
- package/dist/tools/butlr-traffic-flow.d.ts.map +1 -0
- package/dist/tools/butlr-traffic-flow.js +369 -0
- package/dist/tools/butlr-traffic-flow.js.map +1 -0
- package/dist/types/responses.d.ts +253 -0
- package/dist/types/responses.d.ts.map +1 -0
- package/dist/types/responses.js +8 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/utils/asset-flattener.d.ts +50 -0
- package/dist/utils/asset-flattener.d.ts.map +1 -0
- package/dist/utils/asset-flattener.js +131 -0
- package/dist/utils/asset-flattener.js.map +1 -0
- package/dist/utils/asset-helpers.d.ts +8 -0
- package/dist/utils/asset-helpers.d.ts.map +1 -0
- package/dist/utils/asset-helpers.js +24 -0
- package/dist/utils/asset-helpers.js.map +1 -0
- package/dist/utils/field-validator.d.ts +29 -0
- package/dist/utils/field-validator.d.ts.map +1 -0
- package/dist/utils/field-validator.js +197 -0
- package/dist/utils/field-validator.js.map +1 -0
- package/dist/utils/fuzzy-match.d.ts +29 -0
- package/dist/utils/fuzzy-match.d.ts.map +1 -0
- package/dist/utils/fuzzy-match.js +70 -0
- package/dist/utils/fuzzy-match.js.map +1 -0
- package/dist/utils/graphql-helpers.d.ts +29 -0
- package/dist/utils/graphql-helpers.d.ts.map +1 -0
- package/dist/utils/graphql-helpers.js +43 -0
- package/dist/utils/graphql-helpers.js.map +1 -0
- package/dist/utils/natural-language.d.ts +73 -0
- package/dist/utils/natural-language.d.ts.map +1 -0
- package/dist/utils/natural-language.js +172 -0
- package/dist/utils/natural-language.js.map +1 -0
- package/dist/utils/occupancy-helpers.d.ts +63 -0
- package/dist/utils/occupancy-helpers.d.ts.map +1 -0
- package/dist/utils/occupancy-helpers.js +203 -0
- package/dist/utils/occupancy-helpers.js.map +1 -0
- package/dist/utils/path-builder.d.ts +10 -0
- package/dist/utils/path-builder.d.ts.map +1 -0
- package/dist/utils/path-builder.js +34 -0
- package/dist/utils/path-builder.js.map +1 -0
- package/dist/utils/time-range-validator.d.ts +13 -0
- package/dist/utils/time-range-validator.d.ts.map +1 -0
- package/dist/utils/time-range-validator.js +65 -0
- package/dist/utils/time-range-validator.js.map +1 -0
- package/dist/utils/timezone-helpers.d.ts +49 -0
- package/dist/utils/timezone-helpers.d.ts.map +1 -0
- package/dist/utils/timezone-helpers.js +209 -0
- package/dist/utils/timezone-helpers.js.map +1 -0
- package/dist/utils/tree-formatter.d.ts +23 -0
- package/dist/utils/tree-formatter.d.ts.map +1 -0
- package/dist/utils/tree-formatter.js +258 -0
- package/dist/utils/tree-formatter.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
import { apolloClient } from "../clients/graphql-client.js";
|
|
2
|
+
import { gql } from "@apollo/client";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { GET_ALL_SENSORS, GET_ALL_HIVES } from "../clients/queries/topology.js";
|
|
5
|
+
import { buildHardwareSummary, daysBetween, hoursBetween } from "../utils/natural-language.js";
|
|
6
|
+
import { isProductionSensor, isProductionHive, rethrowIfGraphQLError, } from "../utils/graphql-helpers.js";
|
|
7
|
+
/** Shared shape — used by both registerTool and full validation */
|
|
8
|
+
const hardwareSnapshotInputShape = {
|
|
9
|
+
scope_type: z
|
|
10
|
+
.enum(["org", "site", "building", "floor"])
|
|
11
|
+
.default("org")
|
|
12
|
+
.describe("Scope of the health check"),
|
|
13
|
+
scope_id: z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1, "scope_id cannot be empty")
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Required if scope_type is not 'org'"),
|
|
18
|
+
include_battery_details: z
|
|
19
|
+
.boolean()
|
|
20
|
+
.default(false)
|
|
21
|
+
.describe("Include list of sensors needing battery service"),
|
|
22
|
+
battery_status_filter: z
|
|
23
|
+
.enum(["critical", "due_soon", "healthy", "all"])
|
|
24
|
+
.default("all")
|
|
25
|
+
.describe("Filter battery details by status"),
|
|
26
|
+
limit: z
|
|
27
|
+
.number()
|
|
28
|
+
.int("limit must be an integer")
|
|
29
|
+
.min(1, "limit must be at least 1")
|
|
30
|
+
.max(500, "limit cannot exceed 500")
|
|
31
|
+
.default(20)
|
|
32
|
+
.describe("Max devices in battery_details list"),
|
|
33
|
+
offline_devices_limit: z
|
|
34
|
+
.number()
|
|
35
|
+
.int("offline_devices_limit must be an integer")
|
|
36
|
+
.min(1)
|
|
37
|
+
.max(500)
|
|
38
|
+
.default(20)
|
|
39
|
+
.describe("Max offline devices to show"),
|
|
40
|
+
};
|
|
41
|
+
export const HardwareSnapshotArgsSchema = z
|
|
42
|
+
.object(hardwareSnapshotInputShape)
|
|
43
|
+
.strict()
|
|
44
|
+
.refine((data) => {
|
|
45
|
+
if (data.scope_type !== "org" && !data.scope_id) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}, {
|
|
50
|
+
message: "scope_id is required when scope_type is not 'org'",
|
|
51
|
+
path: ["scope_id"],
|
|
52
|
+
});
|
|
53
|
+
const HARDWARE_SNAPSHOT_DESCRIPTION = "Get unified device health check combining online/offline status and battery health across your entire portfolio or specific locations. Provides proactive maintenance insights for facilities teams managing IoT sensor infrastructure.\n\n" +
|
|
54
|
+
"Primary Users:\n" +
|
|
55
|
+
"- IT Manager: Monitor sensor/hive uptime, track device health KPIs, report on system reliability\n" +
|
|
56
|
+
"- Field Technician: Identify devices needing maintenance before site visits, prioritize battery replacements\n" +
|
|
57
|
+
"- Facilities Manager: Verify system health before quarterly reviews, validate sensor coverage\n\n" +
|
|
58
|
+
"Example Queries:\n" +
|
|
59
|
+
'1. "Show me all offline sensors in Building 2 East Tower"\n' +
|
|
60
|
+
'2. "Which sensors need battery replacements in the next 7 days?"\n' +
|
|
61
|
+
'3. "Give me a hardware health snapshot for the SF office"\n' +
|
|
62
|
+
'4. "Are there any sensors that haven\'t reported in 24 hours?"\n' +
|
|
63
|
+
'5. "What\'s the battery status for Floor 3?"\n' +
|
|
64
|
+
'6. "How many hives are offline organization-wide?"\n' +
|
|
65
|
+
'7. "Show me sensors with overdue battery changes (critical status)"\n' +
|
|
66
|
+
'8. "I\'m planning a site visit to Chicago - what devices need attention?"\n\n' +
|
|
67
|
+
"When to Use:\n" +
|
|
68
|
+
"- Quick overview of device health for planning maintenance\n" +
|
|
69
|
+
"- Preparing for site visits (know which devices need service)\n" +
|
|
70
|
+
"- Proactive battery alerts before sensor failures impact data quality\n" +
|
|
71
|
+
"- Reporting uptime metrics or system reliability to leadership\n" +
|
|
72
|
+
"- Troubleshooting missing data issues (check if sensors are online)\n\n" +
|
|
73
|
+
"When NOT to Use:\n" +
|
|
74
|
+
"- Need detailed config for specific sensor → use butlr_get_asset_details with include_devices: true\n" +
|
|
75
|
+
"- Searching for sensor by name/MAC → use butlr_search_assets first with asset_types: ['sensor']\n" +
|
|
76
|
+
"- Historical device uptime trends → this tool shows current snapshot only\n\n" +
|
|
77
|
+
"CRE Context: Battery-powered sensors typically last 1-2 years depending on mode. Proactive battery management prevents data gaps that could impact space utilization reporting and right-sizing decisions.\n\n" +
|
|
78
|
+
"See Also: butlr_search_assets, butlr_get_asset_details, butlr_list_topology";
|
|
79
|
+
/**
|
|
80
|
+
* GraphQL query for topology (without devices - they're queried separately)
|
|
81
|
+
*/
|
|
82
|
+
const GET_TOPOLOGY_FOR_HEALTH = gql `
|
|
83
|
+
query GetTopologyForHealth {
|
|
84
|
+
sites {
|
|
85
|
+
data {
|
|
86
|
+
id
|
|
87
|
+
name
|
|
88
|
+
buildings {
|
|
89
|
+
id
|
|
90
|
+
name
|
|
91
|
+
site_id
|
|
92
|
+
floors {
|
|
93
|
+
id
|
|
94
|
+
name
|
|
95
|
+
building_id
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
/**
|
|
103
|
+
* Calculate battery status for a sensor
|
|
104
|
+
* Exported for unit testing
|
|
105
|
+
*/
|
|
106
|
+
export function getBatteryStatus(sensor, currentDate = new Date()) {
|
|
107
|
+
// Wired sensors don't use batteries
|
|
108
|
+
if (sensor.power_type === "Wired") {
|
|
109
|
+
return "no_battery";
|
|
110
|
+
}
|
|
111
|
+
// No battery_change_by_date means we don't have battery tracking
|
|
112
|
+
if (!sensor.battery_change_by_date) {
|
|
113
|
+
return "unknown";
|
|
114
|
+
}
|
|
115
|
+
const changeByDate = new Date(sensor.battery_change_by_date);
|
|
116
|
+
const daysRemaining = daysBetween(currentDate, changeByDate);
|
|
117
|
+
if (daysRemaining < 0) {
|
|
118
|
+
return "critical"; // Overdue!
|
|
119
|
+
}
|
|
120
|
+
else if (daysRemaining <= 30) {
|
|
121
|
+
return "due_soon"; // Within 30 days
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return "healthy";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Build hierarchy context for a sensor/hive
|
|
129
|
+
*/
|
|
130
|
+
function buildDevicePath(device, floors, buildings, sites) {
|
|
131
|
+
const deviceFloorId = device.floor_id || device.floorID;
|
|
132
|
+
const floor = floors.find((f) => f.id === deviceFloorId);
|
|
133
|
+
if (!floor)
|
|
134
|
+
return device.name;
|
|
135
|
+
const building = buildings.find((b) => b.id === floor.building_id);
|
|
136
|
+
if (!building)
|
|
137
|
+
return `${floor.name} > ${device.name}`;
|
|
138
|
+
const site = sites.find((s) => s.id === building.site_id);
|
|
139
|
+
if (!site)
|
|
140
|
+
return `${building.name} > ${floor.name} > ${device.name}`;
|
|
141
|
+
return `${site.name} > ${building.name} > ${floor.name} > ${device.name}`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Filter production devices from raw API responses, excluding test/mirror/placeholder devices.
|
|
145
|
+
* Returns production devices and counts of excluded test devices.
|
|
146
|
+
*/
|
|
147
|
+
function filterProductionDevices(rawSensors, rawHives) {
|
|
148
|
+
const sensors = rawSensors.filter(isProductionSensor);
|
|
149
|
+
const hives = rawHives.filter(isProductionHive);
|
|
150
|
+
const mirrorSensors = rawSensors.filter((s) => s.mac_address?.startsWith("mi-rr-or") || s.mac_address?.startsWith("fa-ke")).length;
|
|
151
|
+
const emptySensors = rawSensors.filter((s) => !s.mac_address || s.mac_address.trim() === "").length;
|
|
152
|
+
const fakeHives = rawHives.filter((h) => h.serialNumber?.toLowerCase().startsWith("fake")).length;
|
|
153
|
+
const emptyHives = rawHives.filter((h) => !h.serialNumber || h.serialNumber.trim() === "").length;
|
|
154
|
+
return {
|
|
155
|
+
sensors,
|
|
156
|
+
hives,
|
|
157
|
+
testCounts: {
|
|
158
|
+
sensors: {
|
|
159
|
+
mirror: mirrorSensors,
|
|
160
|
+
placeholder: emptySensors,
|
|
161
|
+
total_test: mirrorSensors + emptySensors,
|
|
162
|
+
},
|
|
163
|
+
hives: { fake: fakeHives, placeholder: emptyHives, total_test: fakeHives + emptyHives },
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Group devices by floor ID and merge into floor objects
|
|
169
|
+
*/
|
|
170
|
+
function assignDevicesToFloors(sensors, hives, floors) {
|
|
171
|
+
const sensorsByFloor = {};
|
|
172
|
+
const hivesByFloor = {};
|
|
173
|
+
for (const sensor of sensors) {
|
|
174
|
+
const floorId = sensor.floor_id || sensor.floorID;
|
|
175
|
+
if (floorId) {
|
|
176
|
+
if (!sensorsByFloor[floorId])
|
|
177
|
+
sensorsByFloor[floorId] = [];
|
|
178
|
+
sensorsByFloor[floorId].push(sensor);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
for (const hive of hives) {
|
|
182
|
+
const floorId = hive.floor_id || hive.floorID;
|
|
183
|
+
if (floorId) {
|
|
184
|
+
if (!hivesByFloor[floorId])
|
|
185
|
+
hivesByFloor[floorId] = [];
|
|
186
|
+
hivesByFloor[floorId].push(hive);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
for (const floor of floors) {
|
|
190
|
+
floor.sensors = sensorsByFloor[floor.id] || [];
|
|
191
|
+
floor.hives = hivesByFloor[floor.id] || [];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Execute hardware snapshot tool
|
|
196
|
+
*/
|
|
197
|
+
export async function executeHardwareSnapshot(args) {
|
|
198
|
+
const scopeType = args.scope_type;
|
|
199
|
+
if (process.env.DEBUG) {
|
|
200
|
+
console.error(`[hardware-snapshot] Querying device health for scope: ${scopeType}${args.scope_id ? `:${args.scope_id}` : ""}`);
|
|
201
|
+
}
|
|
202
|
+
let floors = [];
|
|
203
|
+
let buildings = [];
|
|
204
|
+
let sites = [];
|
|
205
|
+
let scopeName = "";
|
|
206
|
+
let testDeviceCounts = null;
|
|
207
|
+
try {
|
|
208
|
+
// Fetch all devices org-wide (API doesn't support scope-filtered device queries)
|
|
209
|
+
const [sensorsResult, hivesResult] = await Promise.all([
|
|
210
|
+
apolloClient.query({
|
|
211
|
+
query: GET_ALL_SENSORS,
|
|
212
|
+
fetchPolicy: "network-only",
|
|
213
|
+
}),
|
|
214
|
+
apolloClient.query({
|
|
215
|
+
query: GET_ALL_HIVES,
|
|
216
|
+
fetchPolicy: "network-only",
|
|
217
|
+
}),
|
|
218
|
+
]);
|
|
219
|
+
const allSensorsRaw = sensorsResult.data?.sensors?.data || [];
|
|
220
|
+
const allHivesRaw = hivesResult.data?.hives?.data || [];
|
|
221
|
+
if (scopeType === "org") {
|
|
222
|
+
const topoResult = await apolloClient.query({
|
|
223
|
+
query: GET_TOPOLOGY_FOR_HEALTH,
|
|
224
|
+
fetchPolicy: "network-only",
|
|
225
|
+
});
|
|
226
|
+
if (!topoResult.data?.sites?.data) {
|
|
227
|
+
throw new Error("Invalid response structure from API");
|
|
228
|
+
}
|
|
229
|
+
sites = topoResult.data.sites.data;
|
|
230
|
+
buildings = sites.flatMap((s) => s.buildings || []);
|
|
231
|
+
floors = buildings.flatMap((b) => b.floors || []);
|
|
232
|
+
scopeName = "Organization";
|
|
233
|
+
}
|
|
234
|
+
else if (scopeType === "site") {
|
|
235
|
+
const siteResult = await apolloClient.query({
|
|
236
|
+
query: gql `
|
|
237
|
+
query GetSite($id: ID!) {
|
|
238
|
+
site(id: $id) {
|
|
239
|
+
id
|
|
240
|
+
name
|
|
241
|
+
buildings {
|
|
242
|
+
id
|
|
243
|
+
name
|
|
244
|
+
site_id
|
|
245
|
+
floors {
|
|
246
|
+
id
|
|
247
|
+
name
|
|
248
|
+
building_id
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`,
|
|
254
|
+
variables: { id: args.scope_id },
|
|
255
|
+
fetchPolicy: "network-only",
|
|
256
|
+
});
|
|
257
|
+
if (!siteResult.data?.site) {
|
|
258
|
+
throw new Error(`Site ${args.scope_id} not found`);
|
|
259
|
+
}
|
|
260
|
+
sites = [siteResult.data.site];
|
|
261
|
+
buildings = sites[0].buildings || [];
|
|
262
|
+
floors = buildings.flatMap((b) => b.floors || []);
|
|
263
|
+
scopeName = sites[0].name;
|
|
264
|
+
}
|
|
265
|
+
else if (scopeType === "building") {
|
|
266
|
+
const buildingResult = await apolloClient.query({
|
|
267
|
+
query: gql `
|
|
268
|
+
query GetBuilding($id: ID!) {
|
|
269
|
+
building(id: $id) {
|
|
270
|
+
id
|
|
271
|
+
name
|
|
272
|
+
site_id
|
|
273
|
+
floors {
|
|
274
|
+
id
|
|
275
|
+
name
|
|
276
|
+
building_id
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
`,
|
|
281
|
+
variables: { id: args.scope_id },
|
|
282
|
+
fetchPolicy: "network-only",
|
|
283
|
+
});
|
|
284
|
+
if (!buildingResult.data?.building) {
|
|
285
|
+
throw new Error(`Building ${args.scope_id} not found`);
|
|
286
|
+
}
|
|
287
|
+
buildings = [buildingResult.data.building];
|
|
288
|
+
floors = buildings[0].floors || [];
|
|
289
|
+
scopeName = buildings[0].name;
|
|
290
|
+
}
|
|
291
|
+
else if (scopeType === "floor") {
|
|
292
|
+
const floorResult = await apolloClient.query({
|
|
293
|
+
query: gql `
|
|
294
|
+
query GetFloor($id: ID!) {
|
|
295
|
+
floor(id: $id) {
|
|
296
|
+
id
|
|
297
|
+
name
|
|
298
|
+
building_id
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
`,
|
|
302
|
+
variables: { id: args.scope_id },
|
|
303
|
+
fetchPolicy: "network-only",
|
|
304
|
+
});
|
|
305
|
+
if (!floorResult.data?.floor) {
|
|
306
|
+
throw new Error(`Floor ${args.scope_id} not found`);
|
|
307
|
+
}
|
|
308
|
+
floors = [floorResult.data.floor];
|
|
309
|
+
scopeName = floors[0].name;
|
|
310
|
+
}
|
|
311
|
+
// Filter production devices and assign to scoped floors
|
|
312
|
+
const { sensors: prodSensors, hives: prodHives, testCounts, } = filterProductionDevices(allSensorsRaw, allHivesRaw);
|
|
313
|
+
assignDevicesToFloors(prodSensors, prodHives, floors);
|
|
314
|
+
// Only include test device counts for org scope (where they're meaningful)
|
|
315
|
+
if (scopeType === "org") {
|
|
316
|
+
testDeviceCounts = testCounts;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
rethrowIfGraphQLError(error);
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
// Collect scoped sensors and hives (only devices on floors within this scope)
|
|
324
|
+
const allSensors = floors.flatMap((f) => f.sensors || []);
|
|
325
|
+
const allHives = floors.flatMap((f) => f.hives || []);
|
|
326
|
+
if (process.env.DEBUG) {
|
|
327
|
+
console.error(`[hardware-snapshot] Found ${allSensors.length} sensors, ${allHives.length} hives`);
|
|
328
|
+
}
|
|
329
|
+
// Calculate sensor statistics
|
|
330
|
+
const sensorsOnline = allSensors.filter((s) => s.is_online).length;
|
|
331
|
+
const sensorsOffline = allSensors.length - sensorsOnline;
|
|
332
|
+
const sensorsPercentOnline = allSensors.length > 0 ? parseFloat(((sensorsOnline / allSensors.length) * 100).toFixed(1)) : 0;
|
|
333
|
+
// Calculate hive statistics
|
|
334
|
+
const hivesOnline = allHives.filter((h) => h.isOnline).length;
|
|
335
|
+
const hivesOffline = allHives.length - hivesOnline;
|
|
336
|
+
const hivesPercentOnline = allHives.length > 0 ? parseFloat(((hivesOnline / allHives.length) * 100).toFixed(1)) : 0;
|
|
337
|
+
// Calculate battery health
|
|
338
|
+
const batteryStatusCounts = {
|
|
339
|
+
critical: 0,
|
|
340
|
+
due_soon: 0,
|
|
341
|
+
healthy: 0,
|
|
342
|
+
unknown: 0,
|
|
343
|
+
no_battery: 0,
|
|
344
|
+
};
|
|
345
|
+
const batteryDetails = [];
|
|
346
|
+
for (const sensor of allSensors) {
|
|
347
|
+
const status = getBatteryStatus(sensor);
|
|
348
|
+
batteryStatusCounts[status]++;
|
|
349
|
+
// If user requested battery details and this sensor matches filter
|
|
350
|
+
if (args.include_battery_details) {
|
|
351
|
+
const statusFilter = args.battery_status_filter || "all";
|
|
352
|
+
if (statusFilter === "all" || statusFilter === status) {
|
|
353
|
+
const now = new Date();
|
|
354
|
+
const changeByDate = sensor.battery_change_by_date
|
|
355
|
+
? new Date(sensor.battery_change_by_date)
|
|
356
|
+
: null;
|
|
357
|
+
const daysRemaining = changeByDate ? daysBetween(now, changeByDate) : 0;
|
|
358
|
+
batteryDetails.push({
|
|
359
|
+
sensor_id: sensor.id,
|
|
360
|
+
sensor_name: sensor.name,
|
|
361
|
+
mac_address: sensor.mac_address, // Human-readable identifier
|
|
362
|
+
path: buildDevicePath(sensor, floors, buildings, sites),
|
|
363
|
+
status,
|
|
364
|
+
battery_change_by_date: sensor.battery_change_by_date || "N/A",
|
|
365
|
+
days_remaining: daysRemaining,
|
|
366
|
+
last_battery_change_date: sensor.last_battery_change_date,
|
|
367
|
+
next_battery_change_date: sensor.next_battery_change_date,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Sort battery details by urgency (most urgent first)
|
|
373
|
+
batteryDetails.sort((a, b) => a.days_remaining - b.days_remaining);
|
|
374
|
+
// Limit battery details
|
|
375
|
+
const limit = args.limit || 20;
|
|
376
|
+
const limitedBatteryDetails = batteryDetails.slice(0, limit);
|
|
377
|
+
// Build summary
|
|
378
|
+
const summary = buildHardwareSummary({
|
|
379
|
+
sensorsOnline,
|
|
380
|
+
sensorsTotal: allSensors.length,
|
|
381
|
+
hivesOnline,
|
|
382
|
+
hivesTotal: allHives.length,
|
|
383
|
+
batteriesCritical: batteryStatusCounts.critical,
|
|
384
|
+
batteriesDueSoon: batteryStatusCounts.due_soon,
|
|
385
|
+
});
|
|
386
|
+
// Build floor breakdown if multiple floors
|
|
387
|
+
const breakdownByFloor = [];
|
|
388
|
+
if (floors.length > 1) {
|
|
389
|
+
for (const floor of floors) {
|
|
390
|
+
const floorSensors = allSensors.filter((s) => (s.floor_id || s.floorID) === floor.id);
|
|
391
|
+
const floorSensorsOnline = floorSensors.filter((s) => s.is_online).length;
|
|
392
|
+
const floorBatteriesCritical = floorSensors.filter((s) => getBatteryStatus(s) === "critical").length;
|
|
393
|
+
const floorBatteriesDueSoon = floorSensors.filter((s) => getBatteryStatus(s) === "due_soon").length;
|
|
394
|
+
breakdownByFloor.push({
|
|
395
|
+
floor_id: floor.id,
|
|
396
|
+
floor_name: floor.name,
|
|
397
|
+
sensors_online: floorSensorsOnline,
|
|
398
|
+
sensors_total: floorSensors.length,
|
|
399
|
+
percent_online: floorSensors.length > 0
|
|
400
|
+
? parseFloat(((floorSensorsOnline / floorSensors.length) * 100).toFixed(1))
|
|
401
|
+
: 0,
|
|
402
|
+
batteries_critical: floorBatteriesCritical,
|
|
403
|
+
batteries_due_soon: floorBatteriesDueSoon,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// Build offline devices list
|
|
408
|
+
const offlineDevices = [];
|
|
409
|
+
const now = new Date();
|
|
410
|
+
for (const sensor of allSensors) {
|
|
411
|
+
if (!sensor.is_online) {
|
|
412
|
+
// Use isOnline consistently, heartbeat is optional enrichment
|
|
413
|
+
const lastHeartbeat = sensor.last_heartbeat
|
|
414
|
+
? new Date(sensor.last_heartbeat * 1000)
|
|
415
|
+
: undefined;
|
|
416
|
+
const hoursOffline = lastHeartbeat ? hoursBetween(lastHeartbeat, now) : undefined;
|
|
417
|
+
offlineDevices.push({
|
|
418
|
+
type: "sensor",
|
|
419
|
+
id: sensor.id,
|
|
420
|
+
name: sensor.name,
|
|
421
|
+
mac_address: sensor.mac_address,
|
|
422
|
+
path: buildDevicePath(sensor, floors, buildings, sites),
|
|
423
|
+
last_heartbeat: lastHeartbeat?.toISOString(),
|
|
424
|
+
hours_offline: hoursOffline,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
for (const hive of allHives) {
|
|
429
|
+
if (!hive.isOnline) {
|
|
430
|
+
// Use isOnline consistently, heartbeat is optional enrichment
|
|
431
|
+
const lastHeartbeat = hive.lastHeartbeat ? new Date(hive.lastHeartbeat * 1000) : undefined;
|
|
432
|
+
const hoursOffline = lastHeartbeat ? hoursBetween(lastHeartbeat, now) : undefined;
|
|
433
|
+
offlineDevices.push({
|
|
434
|
+
type: "hive",
|
|
435
|
+
id: hive.id,
|
|
436
|
+
name: hive.name,
|
|
437
|
+
serial_number: hive.serialNumber,
|
|
438
|
+
path: buildDevicePath(hive, floors, buildings, sites),
|
|
439
|
+
last_heartbeat: lastHeartbeat?.toISOString(),
|
|
440
|
+
hours_offline: hoursOffline,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
// Sort offline devices by hours offline (SHORTEST first for devices with heartbeat data)
|
|
445
|
+
// Devices without heartbeat go to end
|
|
446
|
+
offlineDevices.sort((a, b) => {
|
|
447
|
+
if (a.hours_offline === undefined && b.hours_offline === undefined)
|
|
448
|
+
return 0;
|
|
449
|
+
if (a.hours_offline === undefined)
|
|
450
|
+
return 1; // No heartbeat goes to end
|
|
451
|
+
if (b.hours_offline === undefined)
|
|
452
|
+
return -1; // No heartbeat goes to end
|
|
453
|
+
return a.hours_offline - b.hours_offline; // Shortest offline first
|
|
454
|
+
});
|
|
455
|
+
// Count offline devices by type
|
|
456
|
+
const offlineSensorCount = offlineDevices.filter((d) => d.type === "sensor").length;
|
|
457
|
+
const offlineHiveCount = offlineDevices.filter((d) => d.type === "hive").length;
|
|
458
|
+
// Build enhanced summary with truncation info
|
|
459
|
+
const offlineDeviceLimit = args.offline_devices_limit || 20;
|
|
460
|
+
let enhancedSummary = summary;
|
|
461
|
+
if (offlineDevices.length > offlineDeviceLimit) {
|
|
462
|
+
enhancedSummary += ` Showing ${offlineDeviceLimit} most recently offline devices (${offlineSensorCount} sensors, ${offlineHiveCount} hives offline).`;
|
|
463
|
+
}
|
|
464
|
+
// Build response
|
|
465
|
+
const response = {
|
|
466
|
+
summary: enhancedSummary,
|
|
467
|
+
sensors: {
|
|
468
|
+
total: allSensors.length,
|
|
469
|
+
online: sensorsOnline,
|
|
470
|
+
offline: sensorsOffline,
|
|
471
|
+
percent_online: sensorsPercentOnline,
|
|
472
|
+
},
|
|
473
|
+
hives: {
|
|
474
|
+
total: allHives.length,
|
|
475
|
+
online: hivesOnline,
|
|
476
|
+
offline: hivesOffline,
|
|
477
|
+
percent_online: hivesPercentOnline,
|
|
478
|
+
},
|
|
479
|
+
battery_health: batteryStatusCounts,
|
|
480
|
+
scope: {
|
|
481
|
+
type: scopeType,
|
|
482
|
+
id: args.scope_id,
|
|
483
|
+
name: scopeName,
|
|
484
|
+
},
|
|
485
|
+
timestamp: new Date().toISOString(),
|
|
486
|
+
};
|
|
487
|
+
// Add test device breakdown if any exist
|
|
488
|
+
if (testDeviceCounts !== null) {
|
|
489
|
+
const totalTestSensors = testDeviceCounts.sensors.total_test;
|
|
490
|
+
const totalTestHives = testDeviceCounts.hives.total_test;
|
|
491
|
+
if (totalTestSensors > 0 || totalTestHives > 0) {
|
|
492
|
+
response.test_devices_excluded = {
|
|
493
|
+
sensors: {
|
|
494
|
+
mirror: testDeviceCounts.sensors.mirror,
|
|
495
|
+
placeholder: testDeviceCounts.sensors.placeholder,
|
|
496
|
+
total: totalTestSensors,
|
|
497
|
+
},
|
|
498
|
+
hives: {
|
|
499
|
+
fake: testDeviceCounts.hives.fake,
|
|
500
|
+
placeholder: testDeviceCounts.hives.placeholder,
|
|
501
|
+
total: totalTestHives,
|
|
502
|
+
},
|
|
503
|
+
note: `Totals exclude ${totalTestSensors} test/placeholder sensors and ${totalTestHives} test hives. These devices still produce occupancy data.`,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Conditionally add optional fields
|
|
508
|
+
if (args.include_battery_details && limitedBatteryDetails.length > 0) {
|
|
509
|
+
response.battery_details = limitedBatteryDetails;
|
|
510
|
+
if (batteryDetails.length > limit) {
|
|
511
|
+
response.battery_details_truncated = true;
|
|
512
|
+
response.battery_details_total = batteryDetails.length;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (breakdownByFloor.length > 0) {
|
|
516
|
+
response.breakdown_by_floor = breakdownByFloor;
|
|
517
|
+
}
|
|
518
|
+
if (offlineDevices.length > 0) {
|
|
519
|
+
const limitedOffline = offlineDevices.slice(0, offlineDeviceLimit);
|
|
520
|
+
response.offline_devices = limitedOffline;
|
|
521
|
+
response.offline_devices_summary = {
|
|
522
|
+
sensors_offline: offlineSensorCount,
|
|
523
|
+
hives_offline: offlineHiveCount,
|
|
524
|
+
total_offline: offlineDevices.length,
|
|
525
|
+
showing: limitedOffline.length,
|
|
526
|
+
};
|
|
527
|
+
if (offlineDevices.length > offlineDeviceLimit) {
|
|
528
|
+
response.offline_devices_truncated = true;
|
|
529
|
+
response.offline_devices_total = offlineDevices.length;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return response;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Register butlr_hardware_snapshot with an McpServer instance
|
|
536
|
+
*/
|
|
537
|
+
export function registerHardwareSnapshot(server) {
|
|
538
|
+
server.registerTool("butlr_hardware_snapshot", {
|
|
539
|
+
title: "Butlr Hardware Health Snapshot",
|
|
540
|
+
description: HARDWARE_SNAPSHOT_DESCRIPTION,
|
|
541
|
+
inputSchema: hardwareSnapshotInputShape,
|
|
542
|
+
annotations: {
|
|
543
|
+
readOnlyHint: true,
|
|
544
|
+
destructiveHint: false,
|
|
545
|
+
idempotentHint: false, // Real-time data changes between calls
|
|
546
|
+
openWorldHint: true,
|
|
547
|
+
},
|
|
548
|
+
}, async (args) => {
|
|
549
|
+
const validated = HardwareSnapshotArgsSchema.parse(args);
|
|
550
|
+
const result = await executeHardwareSnapshot(validated);
|
|
551
|
+
return {
|
|
552
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
553
|
+
};
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
//# sourceMappingURL=butlr-hardware-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butlr-hardware-snapshot.js","sourceRoot":"","sources":["../../src/tools/butlr-hardware-snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { ListTopologyResponse } from "../types/responses.js";
|
|
4
|
+
export declare const ListTopologyArgsSchema: z.ZodObject<{
|
|
5
|
+
asset_ids: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
6
|
+
starting_depth: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
traversal_depth: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
}, "strict", z.ZodTypeAny, {
|
|
9
|
+
starting_depth: number;
|
|
10
|
+
traversal_depth: number;
|
|
11
|
+
asset_ids?: string[] | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
asset_ids?: string[] | undefined;
|
|
14
|
+
starting_depth?: number | undefined;
|
|
15
|
+
traversal_depth?: number | undefined;
|
|
16
|
+
}>;
|
|
17
|
+
type ListTopologyArgs = z.output<typeof ListTopologyArgsSchema>;
|
|
18
|
+
/**
|
|
19
|
+
* Execute butlr_list_topology tool
|
|
20
|
+
*/
|
|
21
|
+
export declare function executeListTopology(args?: ListTopologyArgs): Promise<ListTopologyResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* Register butlr_list_topology with an McpServer instance
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerListTopology(server: McpServer): void;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=butlr-list-topology.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butlr-list-topology.d.ts","sourceRoot":"","sources":["../../src/tools/butlr-list-topology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAkClE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;EAA4C,CAAC;AAEhF,KAAK,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEhE;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE,gBAAyC,GAC9C,OAAO,CAAC,oBAAoB,CAAC,CAiI/B;AAoGD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsB5D"}
|