@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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/cache/occupancy-cache.d.ts +72 -0
  4. package/dist/cache/occupancy-cache.d.ts.map +1 -0
  5. package/dist/cache/occupancy-cache.js +166 -0
  6. package/dist/cache/occupancy-cache.js.map +1 -0
  7. package/dist/cache/topology-cache.d.ts +36 -0
  8. package/dist/cache/topology-cache.d.ts.map +1 -0
  9. package/dist/cache/topology-cache.js +74 -0
  10. package/dist/cache/topology-cache.js.map +1 -0
  11. package/dist/clients/auth-client.d.ts +22 -0
  12. package/dist/clients/auth-client.d.ts.map +1 -0
  13. package/dist/clients/auth-client.js +82 -0
  14. package/dist/clients/auth-client.js.map +1 -0
  15. package/dist/clients/graphql-client.d.ts +6 -0
  16. package/dist/clients/graphql-client.d.ts.map +1 -0
  17. package/dist/clients/graphql-client.js +106 -0
  18. package/dist/clients/graphql-client.js.map +1 -0
  19. package/dist/clients/queries/topology.d.ts +36 -0
  20. package/dist/clients/queries/topology.d.ts.map +1 -0
  21. package/dist/clients/queries/topology.js +252 -0
  22. package/dist/clients/queries/topology.js.map +1 -0
  23. package/dist/clients/reporting-client.d.ts +191 -0
  24. package/dist/clients/reporting-client.d.ts.map +1 -0
  25. package/dist/clients/reporting-client.js +353 -0
  26. package/dist/clients/reporting-client.js.map +1 -0
  27. package/dist/clients/stats-client.d.ts +119 -0
  28. package/dist/clients/stats-client.d.ts.map +1 -0
  29. package/dist/clients/stats-client.js +238 -0
  30. package/dist/clients/stats-client.js.map +1 -0
  31. package/dist/clients/types.d.ts +215 -0
  32. package/dist/clients/types.d.ts.map +1 -0
  33. package/dist/clients/types.js +6 -0
  34. package/dist/clients/types.js.map +1 -0
  35. package/dist/constants.d.ts +3 -0
  36. package/dist/constants.d.ts.map +1 -0
  37. package/dist/constants.js +3 -0
  38. package/dist/constants.js.map +1 -0
  39. package/dist/errors/mcp-errors.d.ts +63 -0
  40. package/dist/errors/mcp-errors.d.ts.map +1 -0
  41. package/dist/errors/mcp-errors.js +144 -0
  42. package/dist/errors/mcp-errors.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +43 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/tools/butlr-available-rooms.d.ts +49 -0
  48. package/dist/tools/butlr-available-rooms.d.ts.map +1 -0
  49. package/dist/tools/butlr-available-rooms.js +492 -0
  50. package/dist/tools/butlr-available-rooms.js.map +1 -0
  51. package/dist/tools/butlr-fetch-entity-details.d.ts +42 -0
  52. package/dist/tools/butlr-fetch-entity-details.d.ts.map +1 -0
  53. package/dist/tools/butlr-fetch-entity-details.js +276 -0
  54. package/dist/tools/butlr-fetch-entity-details.js.map +1 -0
  55. package/dist/tools/butlr-get-asset-details.d.ts +51 -0
  56. package/dist/tools/butlr-get-asset-details.d.ts.map +1 -0
  57. package/dist/tools/butlr-get-asset-details.js +391 -0
  58. package/dist/tools/butlr-get-asset-details.js.map +1 -0
  59. package/dist/tools/butlr-get-current-occupancy.d.ts +21 -0
  60. package/dist/tools/butlr-get-current-occupancy.d.ts.map +1 -0
  61. package/dist/tools/butlr-get-current-occupancy.js +126 -0
  62. package/dist/tools/butlr-get-current-occupancy.js.map +1 -0
  63. package/dist/tools/butlr-get-occupancy-timeseries.d.ts +31 -0
  64. package/dist/tools/butlr-get-occupancy-timeseries.d.ts.map +1 -0
  65. package/dist/tools/butlr-get-occupancy-timeseries.js +145 -0
  66. package/dist/tools/butlr-get-occupancy-timeseries.js.map +1 -0
  67. package/dist/tools/butlr-hardware-snapshot.d.ts +55 -0
  68. package/dist/tools/butlr-hardware-snapshot.d.ts.map +1 -0
  69. package/dist/tools/butlr-hardware-snapshot.js +556 -0
  70. package/dist/tools/butlr-hardware-snapshot.js.map +1 -0
  71. package/dist/tools/butlr-list-topology.d.ts +27 -0
  72. package/dist/tools/butlr-list-topology.d.ts.map +1 -0
  73. package/dist/tools/butlr-list-topology.js +241 -0
  74. package/dist/tools/butlr-list-topology.js.map +1 -0
  75. package/dist/tools/butlr-search-assets.d.ts +53 -0
  76. package/dist/tools/butlr-search-assets.d.ts.map +1 -0
  77. package/dist/tools/butlr-search-assets.js +206 -0
  78. package/dist/tools/butlr-search-assets.js.map +1 -0
  79. package/dist/tools/butlr-space-busyness.d.ts +23 -0
  80. package/dist/tools/butlr-space-busyness.d.ts.map +1 -0
  81. package/dist/tools/butlr-space-busyness.js +304 -0
  82. package/dist/tools/butlr-space-busyness.js.map +1 -0
  83. package/dist/tools/butlr-traffic-flow.d.ts +39 -0
  84. package/dist/tools/butlr-traffic-flow.d.ts.map +1 -0
  85. package/dist/tools/butlr-traffic-flow.js +369 -0
  86. package/dist/tools/butlr-traffic-flow.js.map +1 -0
  87. package/dist/types/responses.d.ts +253 -0
  88. package/dist/types/responses.d.ts.map +1 -0
  89. package/dist/types/responses.js +8 -0
  90. package/dist/types/responses.js.map +1 -0
  91. package/dist/utils/asset-flattener.d.ts +50 -0
  92. package/dist/utils/asset-flattener.d.ts.map +1 -0
  93. package/dist/utils/asset-flattener.js +131 -0
  94. package/dist/utils/asset-flattener.js.map +1 -0
  95. package/dist/utils/asset-helpers.d.ts +8 -0
  96. package/dist/utils/asset-helpers.d.ts.map +1 -0
  97. package/dist/utils/asset-helpers.js +24 -0
  98. package/dist/utils/asset-helpers.js.map +1 -0
  99. package/dist/utils/field-validator.d.ts +29 -0
  100. package/dist/utils/field-validator.d.ts.map +1 -0
  101. package/dist/utils/field-validator.js +197 -0
  102. package/dist/utils/field-validator.js.map +1 -0
  103. package/dist/utils/fuzzy-match.d.ts +29 -0
  104. package/dist/utils/fuzzy-match.d.ts.map +1 -0
  105. package/dist/utils/fuzzy-match.js +70 -0
  106. package/dist/utils/fuzzy-match.js.map +1 -0
  107. package/dist/utils/graphql-helpers.d.ts +29 -0
  108. package/dist/utils/graphql-helpers.d.ts.map +1 -0
  109. package/dist/utils/graphql-helpers.js +43 -0
  110. package/dist/utils/graphql-helpers.js.map +1 -0
  111. package/dist/utils/natural-language.d.ts +73 -0
  112. package/dist/utils/natural-language.d.ts.map +1 -0
  113. package/dist/utils/natural-language.js +172 -0
  114. package/dist/utils/natural-language.js.map +1 -0
  115. package/dist/utils/occupancy-helpers.d.ts +63 -0
  116. package/dist/utils/occupancy-helpers.d.ts.map +1 -0
  117. package/dist/utils/occupancy-helpers.js +203 -0
  118. package/dist/utils/occupancy-helpers.js.map +1 -0
  119. package/dist/utils/path-builder.d.ts +10 -0
  120. package/dist/utils/path-builder.d.ts.map +1 -0
  121. package/dist/utils/path-builder.js +34 -0
  122. package/dist/utils/path-builder.js.map +1 -0
  123. package/dist/utils/time-range-validator.d.ts +13 -0
  124. package/dist/utils/time-range-validator.d.ts.map +1 -0
  125. package/dist/utils/time-range-validator.js +65 -0
  126. package/dist/utils/time-range-validator.js.map +1 -0
  127. package/dist/utils/timezone-helpers.d.ts +49 -0
  128. package/dist/utils/timezone-helpers.d.ts.map +1 -0
  129. package/dist/utils/timezone-helpers.js +209 -0
  130. package/dist/utils/timezone-helpers.js.map +1 -0
  131. package/dist/utils/tree-formatter.d.ts +23 -0
  132. package/dist/utils/tree-formatter.d.ts.map +1 -0
  133. package/dist/utils/tree-formatter.js +258 -0
  134. package/dist/utils/tree-formatter.js.map +1 -0
  135. package/package.json +93 -0
@@ -0,0 +1,391 @@
1
+ import { apolloClient } from "../clients/graphql-client.js";
2
+ import { gql } from "@apollo/client";
3
+ import { z } from "zod";
4
+ import { translateGraphQLError, formatMCPError, createValidationError, } from "../errors/mcp-errors.js";
5
+ import { detectAssetType } from "../utils/asset-helpers.js";
6
+ const assetIdSchema = z
7
+ .string()
8
+ .min(1, "Asset ID cannot be empty")
9
+ .refine((val) => {
10
+ const validPrefixes = ["site_", "building_", "space_", "floor_", "room_", "zone_"];
11
+ return validPrefixes.some((prefix) => val.startsWith(prefix));
12
+ }, {
13
+ message: "Asset ID must start with valid prefix: site_, building_, floor_, space_, room_, or zone_. For sensor/hive details, use butlr_search_assets or butlr_hardware_snapshot.",
14
+ });
15
+ /** Shared shape — used by both registerTool and full validation */
16
+ const getAssetDetailsInputShape = {
17
+ ids: z
18
+ .array(assetIdSchema)
19
+ .min(1, "ids array must contain at least 1 asset ID")
20
+ .max(50, "ids array cannot exceed 50 assets")
21
+ .describe("Asset IDs to fetch (e.g., ['room_123', 'floor_456'])"),
22
+ include_children: z.boolean().default(true).describe("Include child assets"),
23
+ include_devices: z.boolean().default(false).describe("Include sensors and hives"),
24
+ include_parent_context: z.boolean().default(true).describe("Include parent names for context"),
25
+ };
26
+ export const GetAssetDetailsArgsSchema = z
27
+ .object(getAssetDetailsInputShape)
28
+ .strict()
29
+ .refine((data) => {
30
+ const unique = new Set(data.ids);
31
+ return unique.size === data.ids.length;
32
+ }, {
33
+ message: "ids array contains duplicate asset IDs",
34
+ path: ["ids"],
35
+ });
36
+ const GET_ASSET_DETAILS_DESCRIPTION = "Get comprehensive details for specific assets by ID (sites, buildings, floors, rooms, zones). Automatically detects asset type from ID prefix and returns appropriate fields. Supports batch queries (multiple IDs), optional child/parent context, and device inclusion. Essential for configuration validation, integration development, and detailed asset inspection.\n\n" +
37
+ "Primary Users:\n" +
38
+ "- IT Manager: Verify sensor configurations (mode, model, online status), validate floor/building setups\n" +
39
+ "- Field Technician: Get sensor MAC addresses, hive serial numbers, and physical coordinates before site visits\n" +
40
+ "- Facilities Manager: Verify room capacities, areas, and metadata for space planning\n" +
41
+ "- Developer/Integrator: Fetch asset metadata for building workplace apps, dashboards, or integrations\n\n" +
42
+ "Example Queries:\n" +
43
+ '1. "Show me full details for Conference Room 401" (after finding ID via search)\n' +
44
+ '2. "Get sensor configuration for all sensors on Floor 3" (mode, model, MAC, online status)\n' +
45
+ '3. "Show me all rooms on Floor 6 with their capacities and areas"\n' +
46
+ '4. "Get building details including all floors and their room counts"\n' +
47
+ "5. \"Show me sensor MAC addresses for Room 'Café Barista' for field tech visit\"\n" +
48
+ '6. "Get hive serial numbers and online status for Building 2"\n' +
49
+ '7. "Show me site timezone and all buildings in the Chicago office"\n' +
50
+ '8. "Get room coordinates and rotation for floor plan mapping"\n\n' +
51
+ "When to Use:\n" +
52
+ "- Have asset IDs and need detailed configuration, metadata, or relationships\n" +
53
+ "- Validating sensor/hive assignments for troubleshooting (which hive is this sensor on?)\n" +
54
+ "- Need room capacities, areas, or coordinates for space planning or floor plan integrations\n" +
55
+ "- Preparing for field technician site visit (need device identifiers: MACs, serials)\n" +
56
+ "- Building integrations and need to fetch parent context (room → floor → building → site)\n\n" +
57
+ "When NOT to Use:\n" +
58
+ "- Don't have asset IDs yet → use butlr_search_assets first to find IDs by name\n" +
59
+ "- Need real-time occupancy or sensor data → use occupancy/traffic tools instead\n" +
60
+ "- Want to browse organizational hierarchy → use butlr_list_topology for tree view\n" +
61
+ "- Need to update/configure assets → this is read-only; use Butlr Dashboard for changes\n\n" +
62
+ "Options: include_children (default true), include_devices (default false), include_parent_context (default true)\n\n" +
63
+ "Batch Query: Supports multiple IDs in single call - mixed asset types supported\n\n" +
64
+ "See Also: butlr_search_assets, butlr_list_topology, butlr_fetch_entity_details, butlr_hardware_snapshot";
65
+ /**
66
+ * Build GraphQL query based on asset type and options
67
+ */
68
+ function buildQuery(type, includeChildren, includeDevices, includeParentContext) {
69
+ switch (type) {
70
+ case "site":
71
+ return gql `
72
+ query GetSiteDetails($id: ID!) {
73
+ site(id: $id) {
74
+ id
75
+ name
76
+ timezone
77
+ siteNumber
78
+ customID
79
+ ${includeChildren
80
+ ? `
81
+ buildings {
82
+ id
83
+ name
84
+ building_number
85
+ capacity { max mid }
86
+ ${includeChildren
87
+ ? `
88
+ floors {
89
+ id
90
+ name
91
+ floorNumber
92
+ }
93
+ `
94
+ : ""}
95
+ }
96
+ `
97
+ : ""}
98
+ }
99
+ }
100
+ `;
101
+ case "building":
102
+ return gql `
103
+ query GetBuildingDetails($id: ID!) {
104
+ building(id: $id) {
105
+ id
106
+ name
107
+ building_number
108
+ customID
109
+ capacity { max mid }
110
+ address { lines country }
111
+ ${includeParentContext
112
+ ? `
113
+ site {
114
+ id
115
+ name
116
+ timezone
117
+ }
118
+ `
119
+ : ""}
120
+ ${includeChildren
121
+ ? `
122
+ floors {
123
+ id
124
+ name
125
+ floorNumber
126
+ timezone
127
+ capacity { max mid }
128
+ }
129
+ `
130
+ : ""}
131
+ }
132
+ }
133
+ `;
134
+ case "floor":
135
+ return gql `
136
+ query GetFloorDetails($id: ID!) {
137
+ floor(id: $id) {
138
+ id
139
+ name
140
+ floorNumber
141
+ timezone
142
+ installation_date
143
+ installation_status
144
+ customID
145
+ capacity { max mid }
146
+ area { value unit }
147
+ ${includeParentContext
148
+ ? `
149
+ building {
150
+ id
151
+ name
152
+ building_number
153
+ site {
154
+ id
155
+ name
156
+ timezone
157
+ }
158
+ }
159
+ `
160
+ : ""}
161
+ ${includeChildren
162
+ ? `
163
+ rooms {
164
+ id
165
+ name
166
+ roomType
167
+ customID
168
+ capacity { max mid }
169
+ coordinates
170
+ }
171
+ zones {
172
+ id
173
+ name
174
+ roomID
175
+ customID
176
+ coordinates
177
+ }
178
+ `
179
+ : ""}
180
+ ${includeDevices
181
+ ? `
182
+ sensors {
183
+ id
184
+ name
185
+ mac_address
186
+ mode
187
+ model
188
+ roomID
189
+ hive_serial
190
+ is_online
191
+ }
192
+ hives {
193
+ id
194
+ name
195
+ serialNumber
196
+ roomID
197
+ isOnline
198
+ coordinates
199
+ }
200
+ `
201
+ : ""}
202
+ }
203
+ }
204
+ `;
205
+ case "room":
206
+ return gql `
207
+ query GetRoomDetails($id: ID!) {
208
+ room(id: $id) {
209
+ id
210
+ name
211
+ roomType
212
+ customID
213
+ capacity { max mid }
214
+ area { value unit }
215
+ coordinates
216
+ rotation
217
+ note
218
+ ${includeParentContext
219
+ ? `
220
+ floor {
221
+ id
222
+ name
223
+ floorNumber
224
+ building {
225
+ id
226
+ name
227
+ site {
228
+ id
229
+ name
230
+ }
231
+ }
232
+ }
233
+ `
234
+ : ""}
235
+ ${includeDevices
236
+ ? `
237
+ sensors {
238
+ id
239
+ name
240
+ mac_address
241
+ mode
242
+ model
243
+ is_online
244
+ hive_serial
245
+ }
246
+ `
247
+ : ""}
248
+ }
249
+ }
250
+ `;
251
+ case "zone":
252
+ return gql `
253
+ query GetZoneDetails($id: ID!) {
254
+ zone(id: $id) {
255
+ id
256
+ name
257
+ roomID
258
+ customID
259
+ capacity { max mid }
260
+ area { value unit }
261
+ coordinates
262
+ rotation
263
+ note
264
+ ${includeDevices
265
+ ? `
266
+ sensors {
267
+ id
268
+ name
269
+ mac_address
270
+ is_online
271
+ }
272
+ `
273
+ : ""}
274
+ }
275
+ }
276
+ `;
277
+ default:
278
+ throw createValidationError(`Unsupported asset type: ${type}`);
279
+ }
280
+ }
281
+ /**
282
+ * Execute get_asset_details tool
283
+ */
284
+ export async function executeGetAssetDetails(args) {
285
+ const includeChildren = args.include_children !== false; // Default true
286
+ const includeDevices = args.include_devices === true; // Default false
287
+ const includeParentContext = args.include_parent_context !== false; // Default true
288
+ if (process.env.DEBUG) {
289
+ console.error(`[get-asset-details] Fetching details for ${args.ids.length} asset(s): ${args.ids.join(", ")}`);
290
+ }
291
+ const results = [];
292
+ // Group IDs by type
293
+ const assetsByType = {};
294
+ for (const id of args.ids) {
295
+ const type = detectAssetType(id);
296
+ if (type === "unknown") {
297
+ if (process.env.DEBUG) {
298
+ console.error(`[get-asset-details] Warning: Unknown asset type for ID: ${id}`);
299
+ }
300
+ results.push({
301
+ id,
302
+ _type: "unknown",
303
+ error: `Unknown asset type for ID: ${id}. Expected prefix: site_, building_, floor_, room_, zone_`,
304
+ });
305
+ continue;
306
+ }
307
+ if (!assetsByType[type]) {
308
+ assetsByType[type] = [];
309
+ }
310
+ assetsByType[type].push(id);
311
+ }
312
+ // Fetch all assets in parallel (grouped by type for query selection)
313
+ const fetchPromises = [];
314
+ for (const [type, ids] of Object.entries(assetsByType)) {
315
+ const query = buildQuery(type, includeChildren, includeDevices, includeParentContext);
316
+ for (const id of ids) {
317
+ fetchPromises.push({
318
+ id,
319
+ type,
320
+ promise: apolloClient.query({ query, variables: { id }, fetchPolicy: "network-only" }),
321
+ });
322
+ }
323
+ }
324
+ const settled = await Promise.allSettled(fetchPromises.map((f) => f.promise));
325
+ for (let i = 0; i < settled.length; i++) {
326
+ const { id, type } = fetchPromises[i];
327
+ const outcome = settled[i];
328
+ if (outcome.status === "fulfilled") {
329
+ const { data, error } = outcome.value;
330
+ if (error) {
331
+ const mcpError = translateGraphQLError(error);
332
+ results.push({ id, error: formatMCPError(mcpError), _type: type });
333
+ continue;
334
+ }
335
+ const asset = data[type];
336
+ if (asset && typeof asset === "object") {
337
+ results.push({ ...asset, _type: type });
338
+ }
339
+ else if (process.env.DEBUG) {
340
+ console.error(`[get-asset-details] Asset not found: ${id}`);
341
+ }
342
+ }
343
+ else {
344
+ const err = outcome.reason;
345
+ if (err && (err.graphQLErrors || err.networkError)) {
346
+ const mcpError = translateGraphQLError(err);
347
+ if (process.env.DEBUG) {
348
+ console.error(`[get-asset-details] Error fetching ${id}:`, formatMCPError(mcpError));
349
+ }
350
+ results.push({ id, error: formatMCPError(mcpError), _type: type });
351
+ }
352
+ else {
353
+ throw err;
354
+ }
355
+ }
356
+ }
357
+ return {
358
+ assets: results,
359
+ total_count: results.length,
360
+ requested_count: args.ids.length,
361
+ options: {
362
+ include_children: includeChildren,
363
+ include_devices: includeDevices,
364
+ include_parent_context: includeParentContext,
365
+ },
366
+ timestamp: new Date().toISOString(),
367
+ };
368
+ }
369
+ /**
370
+ * Register butlr_get_asset_details with an McpServer instance
371
+ */
372
+ export function registerGetAssetDetails(server) {
373
+ server.registerTool("butlr_get_asset_details", {
374
+ title: "Get Butlr Asset Details",
375
+ description: GET_ASSET_DETAILS_DESCRIPTION,
376
+ inputSchema: getAssetDetailsInputShape,
377
+ annotations: {
378
+ readOnlyHint: true,
379
+ destructiveHint: false,
380
+ idempotentHint: true,
381
+ openWorldHint: true,
382
+ },
383
+ }, async (args) => {
384
+ const validated = GetAssetDetailsArgsSchema.parse(args);
385
+ const result = await executeGetAssetDetails(validated);
386
+ return {
387
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
388
+ };
389
+ });
390
+ }
391
+ //# sourceMappingURL=butlr-get-asset-details.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butlr-get-asset-details.js","sourceRoot":"","sources":["../../src/tools/butlr-get-asset-details.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { CurrentOccupancyResponse } from "../types/responses.js";
4
+ export declare const GetCurrentOccupancyArgsSchema: z.ZodObject<{
5
+ asset_ids: z.ZodArray<z.ZodString, "many">;
6
+ }, "strict", z.ZodTypeAny, {
7
+ asset_ids: string[];
8
+ }, {
9
+ asset_ids: string[];
10
+ }>;
11
+ /** Input arguments — inferred from Zod schema */
12
+ export type GetCurrentOccupancyArgs = z.output<typeof GetCurrentOccupancyArgsSchema>;
13
+ /**
14
+ * Execute unified current occupancy tool
15
+ */
16
+ export declare function executeGetCurrentOccupancy(args: GetCurrentOccupancyArgs): Promise<CurrentOccupancyResponse>;
17
+ /**
18
+ * Register butlr_get_current_occupancy with an McpServer instance
19
+ */
20
+ export declare function registerGetCurrentOccupancy(server: McpServer): void;
21
+ //# sourceMappingURL=butlr-get-current-occupancy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butlr-get-current-occupancy.d.ts","sourceRoot":"","sources":["../../src/tools/butlr-get-current-occupancy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,OAAO,KAAK,EACV,wBAAwB,EAGzB,MAAM,uBAAuB,CAAC;AAY/B,eAAO,MAAM,6BAA6B;;;;;;EAAmD,CAAC;AAE9F,iDAAiD;AACjD,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAErF;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,wBAAwB,CAAC,CA2GnC;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsBnE"}
@@ -0,0 +1,126 @@
1
+ import { ReportingRequestBuilder } from "../clients/reporting-client.js";
2
+ import { z } from "zod";
3
+ import { fetchTopologyAndSensors, resolveAssetContext, getPresenceMeasurement, getTrafficMeasurement, getPresenceCoverageNote, getTrafficCoverageNote, buildRecommendation, } from "../utils/occupancy-helpers.js";
4
+ const GET_CURRENT_OCCUPANCY_DESCRIPTION = "Get current occupancy for floors, rooms, or zones (last 5 minutes median). Automatically queries both traffic and presence measurements, " +
5
+ "analyzes which are available based on sensor configuration, and returns structured data with timezone context. " +
6
+ "Single tool call provides complete current occupancy picture.";
7
+ /** Shared shape — used by both registerTool (SDK schema) and full validation */
8
+ const getCurrentOccupancyInputShape = {
9
+ asset_ids: z.array(z.string()).min(1).max(50).describe("Floor, room, or zone IDs"),
10
+ };
11
+ export const GetCurrentOccupancyArgsSchema = z.object(getCurrentOccupancyInputShape).strict();
12
+ /**
13
+ * Execute unified current occupancy tool
14
+ */
15
+ export async function executeGetCurrentOccupancy(args) {
16
+ if (process.env.DEBUG) {
17
+ console.error(`[butlr-get-current-occupancy] Querying ${args.asset_ids.length} assets`);
18
+ }
19
+ // Fetch topology and sensors using shared helper
20
+ const ctx = await fetchTopologyAndSensors();
21
+ // Process each asset
22
+ const assets = [];
23
+ const now = new Date();
24
+ const fiveMinAgo = new Date(now.getTime() - 5 * 60 * 1000);
25
+ for (const assetId of args.asset_ids) {
26
+ const asset = resolveAssetContext(assetId, ctx);
27
+ // ---- Presence ----
28
+ const presenceData = {
29
+ available: asset.presenceSensors.length > 0,
30
+ sensor_count: asset.presenceSensors.length,
31
+ coverage_note: getPresenceCoverageNote(asset.assetType, asset.presenceSensors.length),
32
+ };
33
+ let presenceHasData = false;
34
+ if (asset.presenceSensors.length > 0) {
35
+ const measurement = getPresenceMeasurement(asset.assetType);
36
+ try {
37
+ const response = await new ReportingRequestBuilder()
38
+ .assets(asset.assetType, [assetId])
39
+ .measurements([measurement])
40
+ .timeRange(fiveMinAgo.toISOString(), now.toISOString())
41
+ .window("1m", "median")
42
+ .execute();
43
+ if (response.data && Array.isArray(response.data) && response.data.length > 0) {
44
+ const latest = response.data[response.data.length - 1];
45
+ presenceData.current_occupancy = latest.value;
46
+ presenceData.timestamp = new Date(latest.time).toISOString();
47
+ presenceHasData = true;
48
+ }
49
+ }
50
+ catch (error) {
51
+ console.error(`[current-occupancy] Presence query failed:`, error);
52
+ presenceData.warning =
53
+ "Failed to retrieve current presence data. Occupancy value may be missing.";
54
+ }
55
+ }
56
+ // ---- Traffic ----
57
+ const trafficData = {
58
+ available: asset.trafficSensors.length > 0,
59
+ entrance_sensor_count: asset.assetType === "floor" ? asset.trafficSensors.length : undefined,
60
+ sensor_count: asset.assetType === "room" ? asset.trafficSensors.length : undefined,
61
+ coverage_note: getTrafficCoverageNote(asset.assetType, asset.trafficSensors.length),
62
+ };
63
+ let trafficHasData = false;
64
+ if (asset.trafficSensors.length > 0) {
65
+ const measurement = getTrafficMeasurement(asset.assetType);
66
+ try {
67
+ const response = await new ReportingRequestBuilder()
68
+ .assets(asset.assetType, [assetId])
69
+ .measurements([measurement])
70
+ .timeRange(fiveMinAgo.toISOString(), now.toISOString())
71
+ .window("1m", "median")
72
+ .execute();
73
+ if (response.data && Array.isArray(response.data) && response.data.length > 0) {
74
+ const latest = response.data[response.data.length - 1];
75
+ trafficData.current_occupancy = latest.value;
76
+ trafficData.timestamp = new Date(latest.time).toISOString();
77
+ trafficHasData = true;
78
+ }
79
+ }
80
+ catch (error) {
81
+ console.error(`[current-occupancy] Traffic query failed:`, error);
82
+ trafficData.warning =
83
+ "Failed to retrieve current traffic data. Occupancy value may be missing.";
84
+ }
85
+ }
86
+ // ---- Recommendation (checks data success, not just sensor availability) ----
87
+ const recommendation = buildRecommendation(presenceData, trafficData, presenceHasData, trafficHasData);
88
+ assets.push({
89
+ asset_id: assetId,
90
+ asset_type: asset.assetType,
91
+ asset_name: asset.assetName,
92
+ ...asset.tzMetadata,
93
+ presence: presenceData,
94
+ traffic: trafficData,
95
+ ...recommendation,
96
+ });
97
+ }
98
+ return {
99
+ assets,
100
+ timestamp: now.toISOString(),
101
+ timezone_note: "All timestamps are UTC (ISO-8601). Use site_timezone for local conversion.",
102
+ };
103
+ }
104
+ /**
105
+ * Register butlr_get_current_occupancy with an McpServer instance
106
+ */
107
+ export function registerGetCurrentOccupancy(server) {
108
+ server.registerTool("butlr_get_current_occupancy", {
109
+ title: "Get Current Occupancy",
110
+ description: GET_CURRENT_OCCUPANCY_DESCRIPTION,
111
+ inputSchema: getCurrentOccupancyInputShape,
112
+ annotations: {
113
+ readOnlyHint: true,
114
+ destructiveHint: false,
115
+ idempotentHint: false,
116
+ openWorldHint: true,
117
+ },
118
+ }, async (args) => {
119
+ const validated = GetCurrentOccupancyArgsSchema.parse(args);
120
+ const result = await executeGetCurrentOccupancy(validated);
121
+ return {
122
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
123
+ };
124
+ });
125
+ }
126
+ //# sourceMappingURL=butlr-get-current-occupancy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butlr-get-current-occupancy.js","sourceRoot":"","sources":["../../src/tools/butlr-get-current-occupancy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import type { OccupancyTimeseriesResponse } from "../types/responses.js";
4
+ export declare const GetOccupancyTimeseriesArgsSchema: z.ZodObject<{
5
+ asset_ids: z.ZodArray<z.ZodString, "many">;
6
+ interval: z.ZodEnum<["1m", "1h", "1d"]>;
7
+ start: z.ZodString;
8
+ stop: z.ZodString;
9
+ }, "strict", z.ZodTypeAny, {
10
+ start: string;
11
+ stop: string;
12
+ asset_ids: string[];
13
+ interval: "1h" | "1m" | "1d";
14
+ }, {
15
+ start: string;
16
+ stop: string;
17
+ asset_ids: string[];
18
+ interval: "1h" | "1m" | "1d";
19
+ }>;
20
+ /** Inferred args type — no manual interface needed */
21
+ type GetOccupancyTimeseriesArgs = z.output<typeof GetOccupancyTimeseriesArgsSchema>;
22
+ /**
23
+ * Execute unified occupancy timeseries tool
24
+ */
25
+ export declare function executeGetOccupancyTimeseries(args: GetOccupancyTimeseriesArgs): Promise<OccupancyTimeseriesResponse>;
26
+ /**
27
+ * Register butlr_get_occupancy_timeseries with an McpServer instance
28
+ */
29
+ export declare function registerGetOccupancyTimeseries(server: McpServer): void;
30
+ export {};
31
+ //# sourceMappingURL=butlr-get-occupancy-timeseries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"butlr-get-occupancy-timeseries.d.ts","sourceRoot":"","sources":["../../src/tools/butlr-get-occupancy-timeseries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,OAAO,KAAK,EACV,2BAA2B,EAI5B,MAAM,uBAAuB,CAAC;AAoB/B,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;EAAsD,CAAC;AAEpG,sDAAsD;AACtD,KAAK,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAgCpF;;GAEG;AACH,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,2BAA2B,CAAC,CAwGtC;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2BtE"}