@butlr/butlr-mcp-server 0.1.0 → 0.1.2
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 +1 -1
- package/README.md +20 -28
- package/dist/cache/occupancy-cache.d.ts.map +1 -1
- package/dist/cache/occupancy-cache.js +9 -20
- package/dist/cache/occupancy-cache.js.map +1 -1
- package/dist/cache/topology-cache.d.ts.map +1 -1
- package/dist/cache/topology-cache.js +7 -10
- package/dist/cache/topology-cache.js.map +1 -1
- package/dist/clients/auth-client.d.ts.map +1 -1
- package/dist/clients/auth-client.js +5 -9
- package/dist/clients/auth-client.js.map +1 -1
- package/dist/clients/graphql-client.d.ts.map +1 -1
- package/dist/clients/graphql-client.js +5 -4
- package/dist/clients/graphql-client.js.map +1 -1
- package/dist/clients/queries/topology.d.ts +0 -1
- package/dist/clients/queries/topology.d.ts.map +1 -1
- package/dist/clients/queries/topology.js +0 -1
- package/dist/clients/queries/topology.js.map +1 -1
- package/dist/clients/reporting-client.d.ts +1 -1
- package/dist/clients/reporting-client.d.ts.map +1 -1
- package/dist/clients/reporting-client.js +15 -20
- package/dist/clients/reporting-client.js.map +1 -1
- package/dist/clients/stats-client.d.ts +1 -2
- package/dist/clients/stats-client.d.ts.map +1 -1
- package/dist/clients/stats-client.js +13 -18
- package/dist/clients/stats-client.js.map +1 -1
- package/dist/clients/types.d.ts +0 -1
- package/dist/clients/types.d.ts.map +1 -1
- package/dist/clients/types.js +0 -1
- package/dist/clients/types.js.map +1 -1
- package/dist/errors/mcp-errors.d.ts +6 -0
- package/dist/errors/mcp-errors.d.ts.map +1 -1
- package/dist/errors/mcp-errors.js +21 -1
- package/dist/errors/mcp-errors.js.map +1 -1
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/tools/butlr-available-rooms.d.ts.map +1 -1
- package/dist/tools/butlr-available-rooms.js +17 -23
- package/dist/tools/butlr-available-rooms.js.map +1 -1
- package/dist/tools/butlr-fetch-entity-details.d.ts.map +1 -1
- package/dist/tools/butlr-fetch-entity-details.js +14 -14
- package/dist/tools/butlr-fetch-entity-details.js.map +1 -1
- package/dist/tools/butlr-get-asset-details.d.ts.map +1 -1
- package/dist/tools/butlr-get-asset-details.js +10 -15
- package/dist/tools/butlr-get-asset-details.js.map +1 -1
- package/dist/tools/butlr-get-current-occupancy.d.ts.map +1 -1
- package/dist/tools/butlr-get-current-occupancy.js +14 -9
- package/dist/tools/butlr-get-current-occupancy.js.map +1 -1
- package/dist/tools/butlr-get-occupancy-timeseries.d.ts.map +1 -1
- package/dist/tools/butlr-get-occupancy-timeseries.js +19 -21
- package/dist/tools/butlr-get-occupancy-timeseries.js.map +1 -1
- package/dist/tools/butlr-hardware-snapshot.d.ts.map +1 -1
- package/dist/tools/butlr-hardware-snapshot.js +7 -9
- package/dist/tools/butlr-hardware-snapshot.js.map +1 -1
- package/dist/tools/butlr-list-topology.d.ts.map +1 -1
- package/dist/tools/butlr-list-topology.js +20 -26
- package/dist/tools/butlr-list-topology.js.map +1 -1
- package/dist/tools/butlr-search-assets.d.ts.map +1 -1
- package/dist/tools/butlr-search-assets.js +19 -31
- package/dist/tools/butlr-search-assets.js.map +1 -1
- package/dist/tools/butlr-space-busyness.d.ts.map +1 -1
- package/dist/tools/butlr-space-busyness.js +14 -19
- package/dist/tools/butlr-space-busyness.js.map +1 -1
- package/dist/tools/butlr-traffic-flow.d.ts.map +1 -1
- package/dist/tools/butlr-traffic-flow.js +12 -25
- package/dist/tools/butlr-traffic-flow.js.map +1 -1
- package/dist/utils/debug.d.ts +6 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +10 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/timezone-helpers.d.ts.map +1 -1
- package/dist/utils/timezone-helpers.js +5 -10
- package/dist/utils/timezone-helpers.js.map +1 -1
- package/llms.txt +125 -0
- package/package.json +4 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@butlr/butlr-mcp-server)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
7
|
A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that connects AI assistants to [Butlr's](https://www.butlr.com) occupancy sensing platform. Query real-time space utilization, search facility assets, and analyze occupancy patterns through natural language.
|
|
8
8
|
|
|
@@ -17,9 +17,9 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that co
|
|
|
17
17
|
|
|
18
18
|
## Prerequisites
|
|
19
19
|
|
|
20
|
-
- [Node.js](https://nodejs.org/)
|
|
20
|
+
- [Node.js](https://nodejs.org/) 18 or higher
|
|
21
21
|
- An MCP-compatible client ([Claude Desktop](https://claude.ai/download), [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [VS Code](https://code.visualstudio.com/), [Cursor](https://cursor.com/), etc.)
|
|
22
|
-
- Butlr API
|
|
22
|
+
- Butlr API token — see [Getting API Credentials](#getting-api-credentials)
|
|
23
23
|
|
|
24
24
|
## Quick Start
|
|
25
25
|
|
|
@@ -36,8 +36,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
36
36
|
"args": ["-y", "@butlr/butlr-mcp-server@latest"],
|
|
37
37
|
"env": {
|
|
38
38
|
"BUTLR_CLIENT_ID": "your_client_id",
|
|
39
|
-
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
40
|
-
"BUTLR_ORG_ID": "your_org_id"
|
|
39
|
+
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
}
|
|
@@ -50,15 +49,10 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
50
49
|
<summary><strong>Claude Code</strong></summary>
|
|
51
50
|
|
|
52
51
|
```bash
|
|
53
|
-
claude mcp add butlr
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
export BUTLR_CLIENT_ID=your_client_id
|
|
60
|
-
export BUTLR_CLIENT_SECRET=your_client_secret
|
|
61
|
-
export BUTLR_ORG_ID=your_org_id
|
|
52
|
+
claude mcp add butlr \
|
|
53
|
+
-e BUTLR_CLIENT_ID=your_client_id \
|
|
54
|
+
-e BUTLR_CLIENT_SECRET=your_client_secret \
|
|
55
|
+
-- npx -y @butlr/butlr-mcp-server@latest
|
|
62
56
|
```
|
|
63
57
|
|
|
64
58
|
</details>
|
|
@@ -77,8 +71,7 @@ Add to `.vscode/mcp.json`:
|
|
|
77
71
|
"args": ["-y", "@butlr/butlr-mcp-server@latest"],
|
|
78
72
|
"env": {
|
|
79
73
|
"BUTLR_CLIENT_ID": "your_client_id",
|
|
80
|
-
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
81
|
-
"BUTLR_ORG_ID": "your_org_id"
|
|
74
|
+
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
82
75
|
}
|
|
83
76
|
}
|
|
84
77
|
}
|
|
@@ -100,8 +93,7 @@ Add to `.cursor/mcp.json`:
|
|
|
100
93
|
"args": ["-y", "@butlr/butlr-mcp-server@latest"],
|
|
101
94
|
"env": {
|
|
102
95
|
"BUTLR_CLIENT_ID": "your_client_id",
|
|
103
|
-
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
104
|
-
"BUTLR_ORG_ID": "your_org_id"
|
|
96
|
+
"BUTLR_CLIENT_SECRET": "your_client_secret"
|
|
105
97
|
}
|
|
106
98
|
}
|
|
107
99
|
}
|
|
@@ -119,7 +111,7 @@ For any MCP client that supports stdio transport, use this command:
|
|
|
119
111
|
npx -y @butlr/butlr-mcp-server@latest
|
|
120
112
|
```
|
|
121
113
|
|
|
122
|
-
Pass the required environment variables (`BUTLR_CLIENT_ID`, `BUTLR_CLIENT_SECRET
|
|
114
|
+
Pass the required environment variables (`BUTLR_CLIENT_ID`, `BUTLR_CLIENT_SECRET`) through your client's configuration.
|
|
123
115
|
|
|
124
116
|
</details>
|
|
125
117
|
|
|
@@ -144,9 +136,8 @@ All tools are **read-only** — the server cannot modify any data in your Butlr
|
|
|
144
136
|
|
|
145
137
|
| Variable | Required | Default | Description |
|
|
146
138
|
|----------|----------|---------|-------------|
|
|
147
|
-
| `BUTLR_CLIENT_ID` | **Yes** | - |
|
|
148
|
-
| `BUTLR_CLIENT_SECRET` | **Yes** | - |
|
|
149
|
-
| `BUTLR_ORG_ID` | **Yes** | - | Organization ID |
|
|
139
|
+
| `BUTLR_CLIENT_ID` | **Yes** | - | API token client ID |
|
|
140
|
+
| `BUTLR_CLIENT_SECRET` | **Yes** | - | API token client secret |
|
|
150
141
|
| `BUTLR_BASE_URL` | No | `https://api.butlr.io` | API base URL |
|
|
151
142
|
| `BUTLR_TIMEZONE` | No | `UTC` | Default timezone |
|
|
152
143
|
| `MCP_CACHE_TOPO_TTL` | No | `600` | Topology cache TTL (seconds) |
|
|
@@ -154,15 +145,16 @@ All tools are **read-only** — the server cannot modify any data in your Butlr
|
|
|
154
145
|
|
|
155
146
|
## Getting API Credentials
|
|
156
147
|
|
|
157
|
-
|
|
148
|
+
1. Log in to [app.butlr.io](https://app.butlr.io)
|
|
149
|
+
2. Click your username in the top-right corner, then **Account Settings**
|
|
150
|
+
3. Go to **API Tokens** and create a new token
|
|
151
|
+
4. Copy the **Client ID** and **Client Secret**
|
|
158
152
|
|
|
159
|
-
|
|
160
|
-
2. You will receive a **Client ID**, **Client Secret**, and **Organization ID**
|
|
161
|
-
3. These credentials provide read-only access scoped to your organization's data
|
|
153
|
+
You need **edit access** to Butlr Studio to create API tokens. If you don't have edit permissions, ask someone in your organization who does, or contact your Butlr sales representative or [submit a support ticket](https://www.butlr.com).
|
|
162
154
|
|
|
163
155
|
## Troubleshooting
|
|
164
156
|
|
|
165
|
-
**Authentication errors** — Verify your `BUTLR_CLIENT_ID
|
|
157
|
+
**Authentication errors** — Verify your `BUTLR_CLIENT_ID` and `BUTLR_CLIENT_SECRET` are correct. Tokens are refreshed automatically.
|
|
166
158
|
|
|
167
159
|
**Rate limiting** — The server handles rate limits automatically with retry logic. If you see persistent rate limit errors, reduce the frequency of requests.
|
|
168
160
|
|
|
@@ -177,7 +169,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for full development workflow and standar
|
|
|
177
169
|
```bash
|
|
178
170
|
npm install # Install dependencies
|
|
179
171
|
npm run build # Build TypeScript
|
|
180
|
-
npm test # Run tests
|
|
172
|
+
npm test # Run tests
|
|
181
173
|
npm run typecheck # Type checking
|
|
182
174
|
npm run lint # ESLint
|
|
183
175
|
npm run dev # Dev with hot-reload
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"occupancy-cache.d.ts","sourceRoot":"","sources":["../../src/cache/occupancy-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"occupancy-cache.d.ts","sourceRoot":"","sources":["../../src/cache/occupancy-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAUrC,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,gDAKzB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAanF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,IAAI,GACf,mBAAmB,GAAG,SAAS,CAcjC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,CAAC,EAAE,IAAI,GACf;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAgBA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,IAAI,GACf,IAAI,CAiBN;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC,GACD,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAa9D;AAED;;GAEG;AACH,wBAAgB,sBAAsB;;;;;EAOrC;AASD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED,wBAAgB,eAAe,IAAI;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAOA;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LRUCache } from "lru-cache";
|
|
2
|
+
import { debug } from "../utils/debug.js";
|
|
2
3
|
/**
|
|
3
4
|
* Occupancy cache configuration
|
|
4
5
|
* TTL: 60 seconds (fast-changing data)
|
|
@@ -42,15 +43,11 @@ export function getCachedOccupancy(assetId, timestamp) {
|
|
|
42
43
|
// Track cache hit/miss metrics
|
|
43
44
|
if (cached) {
|
|
44
45
|
recordCacheHit();
|
|
45
|
-
|
|
46
|
-
console.error(`[occupancy-cache] Cache HIT for ${assetId}`);
|
|
47
|
-
}
|
|
46
|
+
debug("occupancy-cache", `Cache HIT for ${assetId}`);
|
|
48
47
|
}
|
|
49
48
|
else {
|
|
50
49
|
recordCacheMiss();
|
|
51
|
-
|
|
52
|
-
console.error(`[occupancy-cache] Cache MISS for ${assetId}`);
|
|
53
|
-
}
|
|
50
|
+
debug("occupancy-cache", `Cache MISS for ${assetId}`);
|
|
54
51
|
}
|
|
55
52
|
return cached;
|
|
56
53
|
}
|
|
@@ -70,9 +67,7 @@ export function getBulkCachedOccupancy(assetIds, timestamp) {
|
|
|
70
67
|
misses.push(assetId);
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
|
-
|
|
74
|
-
console.error(`[occupancy-cache] Bulk query: ${Object.keys(hits).length} hits, ${misses.length} misses`);
|
|
75
|
-
}
|
|
70
|
+
debug("occupancy-cache", `Bulk query: ${Object.keys(hits).length} hits, ${misses.length} misses`);
|
|
76
71
|
return { hits, misses };
|
|
77
72
|
}
|
|
78
73
|
/**
|
|
@@ -88,9 +83,7 @@ export function setCachedOccupancy(assetId, occupancy, assetType, timestamp) {
|
|
|
88
83
|
asset_type: assetType,
|
|
89
84
|
};
|
|
90
85
|
occupancyCache.set(key, entry);
|
|
91
|
-
|
|
92
|
-
console.error(`[occupancy-cache] Cached occupancy for ${assetId}: ${occupancy} (TTL: ${CACHE_TTL_SECONDS / 1000}s)`);
|
|
93
|
-
}
|
|
86
|
+
debug("occupancy-cache", `Cached occupancy for ${assetId}: ${occupancy} (TTL: ${CACHE_TTL_SECONDS / 1000}s)`);
|
|
94
87
|
}
|
|
95
88
|
/**
|
|
96
89
|
* Store multiple occupancy values
|
|
@@ -99,18 +92,14 @@ export function setBulkCachedOccupancy(entries) {
|
|
|
99
92
|
for (const entry of entries) {
|
|
100
93
|
setCachedOccupancy(entry.assetId, entry.occupancy, entry.assetType, entry.timestamp);
|
|
101
94
|
}
|
|
102
|
-
|
|
103
|
-
console.error(`[occupancy-cache] Bulk cached ${entries.length} occupancy values`);
|
|
104
|
-
}
|
|
95
|
+
debug("occupancy-cache", `Bulk cached ${entries.length} occupancy values`);
|
|
105
96
|
}
|
|
106
97
|
/**
|
|
107
98
|
* Clear all cached occupancy data
|
|
108
99
|
*/
|
|
109
100
|
export function clearOccupancyCache() {
|
|
110
101
|
occupancyCache.clear();
|
|
111
|
-
|
|
112
|
-
console.error("[occupancy-cache] Cache cleared");
|
|
113
|
-
}
|
|
102
|
+
debug("occupancy-cache", "Cache cleared");
|
|
114
103
|
}
|
|
115
104
|
/**
|
|
116
105
|
* Invalidate cache for specific asset
|
|
@@ -124,8 +113,8 @@ export function invalidateAssetOccupancy(assetId) {
|
|
|
124
113
|
deleted++;
|
|
125
114
|
}
|
|
126
115
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
116
|
+
if (deleted > 0) {
|
|
117
|
+
debug("occupancy-cache", `Invalidated ${deleted} cache entries for ${assetId}`);
|
|
129
118
|
}
|
|
130
119
|
}
|
|
131
120
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"occupancy-cache.js","sourceRoot":"","sources":["../../src/cache/occupancy-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"occupancy-cache.js","sourceRoot":"","sources":["../../src/cache/occupancy-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology-cache.d.ts","sourceRoot":"","sources":["../../src/cache/topology-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"topology-cache.d.ts","sourceRoot":"","sources":["../../src/cache/topology-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AASrC,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,uCAKxB,CAAC;AAEH;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,OAAO,EACvB,YAAY,EAAE,OAAO,EACrB,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,MAAM,CAWR;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAUrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CASlF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED;;GAEG;AACH,wBAAgB,aAAa;;;;EAM5B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LRUCache } from "lru-cache";
|
|
2
|
+
import { debug } from "../utils/debug.js";
|
|
2
3
|
/**
|
|
3
4
|
* Topology cache configuration
|
|
4
5
|
*/
|
|
@@ -31,11 +32,11 @@ export function generateTopologyCacheKey(orgId, includeDevices, includeZones, si
|
|
|
31
32
|
*/
|
|
32
33
|
export function getCachedTopology(key) {
|
|
33
34
|
const cached = topologyCache.get(key);
|
|
34
|
-
if (cached
|
|
35
|
-
|
|
35
|
+
if (cached) {
|
|
36
|
+
debug("topology-cache", `Cache HIT for key: ${key}`);
|
|
36
37
|
}
|
|
37
|
-
else
|
|
38
|
-
|
|
38
|
+
else {
|
|
39
|
+
debug("topology-cache", `Cache MISS for key: ${key}`);
|
|
39
40
|
}
|
|
40
41
|
return cached;
|
|
41
42
|
}
|
|
@@ -48,18 +49,14 @@ export function setCachedTopology(key, data) {
|
|
|
48
49
|
timestamp: new Date().toISOString(),
|
|
49
50
|
};
|
|
50
51
|
topologyCache.set(key, entry);
|
|
51
|
-
|
|
52
|
-
console.error(`[topology-cache] Cached data for key: ${key} (TTL: ${CACHE_TTL_SECONDS / 1000}s)`);
|
|
53
|
-
}
|
|
52
|
+
debug("topology-cache", `Cached data for key: ${key} (TTL: ${CACHE_TTL_SECONDS / 1000}s)`);
|
|
54
53
|
}
|
|
55
54
|
/**
|
|
56
55
|
* Clear all cached topology data
|
|
57
56
|
*/
|
|
58
57
|
export function clearTopologyCache() {
|
|
59
58
|
topologyCache.clear();
|
|
60
|
-
|
|
61
|
-
console.error("[topology-cache] Cache cleared");
|
|
62
|
-
}
|
|
59
|
+
debug("topology-cache", "Cache cleared");
|
|
63
60
|
}
|
|
64
61
|
/**
|
|
65
62
|
* Get cache statistics
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology-cache.js","sourceRoot":"","sources":["../../src/cache/topology-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"topology-cache.js","sourceRoot":"","sources":["../../src/cache/topology-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C;;GAEG;AACH,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,0BAA0B;AAClH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAO9B;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,QAAQ,CAAqB;IAC5D,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;IACtB,cAAc,EAAE,IAAI,EAAE,yBAAyB;IAC/C,cAAc,EAAE,KAAK;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAa,EACb,cAAuB,EACvB,YAAqB,EACrB,OAAkB;IAElB,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE9B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAW,cAAc,EAAE,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CAAC,SAAS,YAAY,EAAE,CAAC,CAAC;IAEpC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,gBAAgB,EAAE,sBAAsB,GAAG,EAAE,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,gBAAgB,EAAE,uBAAuB,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,IAA6B;IAC1E,MAAM,KAAK,GAAe;QACxB,IAAI;QACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE9B,KAAK,CAAC,gBAAgB,EAAE,wBAAwB,GAAG,UAAU,iBAAiB,GAAG,IAAI,IAAI,CAAC,CAAC;AAC7F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,aAAa,CAAC,KAAK,EAAE,CAAC;IAEtB,KAAK,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,IAAI,EAAE,aAAa,CAAC,IAAI;QACxB,OAAO,EAAE,iBAAiB;QAC1B,GAAG,EAAE,iBAAiB,GAAG,IAAI,EAAE,sCAAsC;KACtE,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/clients/auth-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/clients/auth-client.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;;IAOtC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IA2DjC;;OAEG;IACH,UAAU,IAAI,IAAI;CAInB;AAGD,eAAO,MAAM,UAAU,iBAAwB,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dotenv from "dotenv";
|
|
2
|
+
import { debug } from "../utils/debug.js";
|
|
2
3
|
dotenv.config();
|
|
3
4
|
const BASE_URL = process.env.BUTLR_BASE_URL || "https://api.butlr.io";
|
|
4
5
|
const AUTH_ENDPOINT = `${BASE_URL}/api/v2/clients/login`;
|
|
@@ -26,14 +27,10 @@ class ButlrAuthClient {
|
|
|
26
27
|
}
|
|
27
28
|
// Return cached token if still valid (with 5 minute buffer)
|
|
28
29
|
if (this.token && this.tokenExpiry && Date.now() < this.tokenExpiry.getTime() - 5 * 60 * 1000) {
|
|
29
|
-
|
|
30
|
-
console.error("[auth-client] Using cached token");
|
|
31
|
-
}
|
|
30
|
+
debug("auth-client", "Using cached token");
|
|
32
31
|
return this.token;
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
console.error("[auth-client] Fetching new token...");
|
|
36
|
-
}
|
|
33
|
+
debug("auth-client", "Fetching new token...");
|
|
37
34
|
// Fetch new token
|
|
38
35
|
try {
|
|
39
36
|
const response = await fetch(AUTH_ENDPOINT, {
|
|
@@ -47,6 +44,7 @@ class ButlrAuthClient {
|
|
|
47
44
|
audience: "https://butlrauth/",
|
|
48
45
|
grant_type: "client_credentials",
|
|
49
46
|
}),
|
|
47
|
+
signal: AbortSignal.timeout(30_000),
|
|
50
48
|
});
|
|
51
49
|
if (!response.ok) {
|
|
52
50
|
const errorText = await response.text();
|
|
@@ -59,9 +57,7 @@ class ButlrAuthClient {
|
|
|
59
57
|
// Cache the token
|
|
60
58
|
this.token = data.access_token;
|
|
61
59
|
this.tokenExpiry = new Date(Date.now() + data.expires_in * 1000);
|
|
62
|
-
|
|
63
|
-
console.error(`[auth-client] Token acquired, expires at ${this.tokenExpiry.toISOString()}`);
|
|
64
|
-
}
|
|
60
|
+
debug("auth-client", `Token acquired, expires at ${this.tokenExpiry.toISOString()}`);
|
|
65
61
|
return this.token;
|
|
66
62
|
}
|
|
67
63
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../src/clients/auth-client.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../src/clients/auth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-client.d.ts","sourceRoot":"","sources":["../../src/clients/graphql-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"graphql-client.d.ts","sourceRoot":"","sources":["../../src/clients/graphql-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuC,MAAM,gBAAgB,CAAC;AA+EnF;;GAEG;AACH,eAAO,MAAM,YAAY,cAkCvB,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { ApolloClient, InMemoryCache, createHttpLink, from } from "@apollo/clien
|
|
|
2
2
|
import { setContext } from "@apollo/client/link/context";
|
|
3
3
|
import { onError } from "@apollo/client/link/error";
|
|
4
4
|
import { authClient } from "./auth-client.js";
|
|
5
|
+
import { debug } from "../utils/debug.js";
|
|
5
6
|
const BASE_URL = process.env.BUTLR_BASE_URL || "https://api.butlr.io";
|
|
6
7
|
const GRAPHQL_ENDPOINT = `${BASE_URL}/api/v3/graphql`;
|
|
7
8
|
/**
|
|
@@ -25,7 +26,7 @@ const authLink = setContext(async (_, { headers }) => {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
catch (error) {
|
|
28
|
-
|
|
29
|
+
debug("graphql-client", "Failed to get auth token:", error);
|
|
29
30
|
throw error;
|
|
30
31
|
}
|
|
31
32
|
});
|
|
@@ -43,21 +44,21 @@ const errorLink = onError((errorResponse) => {
|
|
|
43
44
|
const topError = resp.error;
|
|
44
45
|
if (graphQLErrors) {
|
|
45
46
|
for (const err of graphQLErrors) {
|
|
46
|
-
|
|
47
|
+
debug("graphql-client", `GraphQL error in ${operation.operationName}:`, err.message);
|
|
47
48
|
if (err.extensions?.code === "UNAUTHENTICATED") {
|
|
48
49
|
authClient.clearToken();
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
if (networkError) {
|
|
53
|
-
|
|
54
|
+
debug("graphql-client", `Network error in ${operation.operationName}:`, networkError.message);
|
|
54
55
|
if (networkError.statusCode === 401 || networkError.statusCode === 403) {
|
|
55
56
|
authClient.clearToken();
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
// Fallback for Apollo 4.x single error field
|
|
59
60
|
if (!graphQLErrors && !networkError && topError) {
|
|
60
|
-
|
|
61
|
+
debug("graphql-client", `Error in ${operation.operationName}:`, topError.message);
|
|
61
62
|
if (topError.message?.includes("UNAUTHENTICATED") ||
|
|
62
63
|
topError.message?.includes("401") ||
|
|
63
64
|
topError.message?.includes("403")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql-client.js","sourceRoot":"","sources":["../../src/clients/graphql-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"graphql-client.js","sourceRoot":"","sources":["../../src/clients/graphql-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../../../src/clients/queries/topology.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../../../src/clients/queries/topology.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,uCAY1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,uCA6B9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,uCAiE7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,uCAwB3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,uCAqBzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,uCAgEnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topology.js","sourceRoot":"","sources":["../../../src/clients/queries/topology.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC
|
|
1
|
+
{"version":3,"file":"topology.js","sourceRoot":"","sources":["../../../src/clients/queries/topology.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAA;;;;;;;;;;;;CAYhC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BpC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiEnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;CAwBjC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;CAqB/B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEzC,CAAC"}
|
|
@@ -7,7 +7,7 @@ export declare class ApiError extends Error {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* v3 Reporting API Request Structure
|
|
10
|
-
* Based on
|
|
10
|
+
* Based on Butlr's internal reporting API schema
|
|
11
11
|
*/
|
|
12
12
|
export interface ReportingRequest {
|
|
13
13
|
group_by?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporting-client.d.ts","sourceRoot":"","sources":["../../src/clients/reporting-client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"reporting-client.d.ts","sourceRoot":"","sources":["../../src/clients/reporting-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { request as httpRequest } from "undici";
|
|
2
1
|
import { authClient } from "./auth-client.js";
|
|
2
|
+
import { debug } from "../utils/debug.js";
|
|
3
3
|
/**
|
|
4
4
|
* Structured API error with status code for proper error translation
|
|
5
5
|
*/
|
|
@@ -60,19 +60,19 @@ export function getMeasurement(assetType) {
|
|
|
60
60
|
*/
|
|
61
61
|
export function normalizeTimestamp(rfc3339) {
|
|
62
62
|
if (!rfc3339) {
|
|
63
|
-
|
|
63
|
+
debug("reporting-client", `Invalid timestamp received: ${rfc3339}`);
|
|
64
64
|
return "";
|
|
65
65
|
}
|
|
66
66
|
try {
|
|
67
67
|
const date = new Date(rfc3339);
|
|
68
68
|
if (isNaN(date.getTime())) {
|
|
69
|
-
|
|
69
|
+
debug("reporting-client", `Invalid timestamp received: ${rfc3339}`);
|
|
70
70
|
return "";
|
|
71
71
|
}
|
|
72
72
|
return date.toISOString();
|
|
73
73
|
}
|
|
74
74
|
catch (error) {
|
|
75
|
-
|
|
75
|
+
debug("reporting-client", `Failed to normalize timestamp ${rfc3339}:`, error);
|
|
76
76
|
return "";
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -80,36 +80,31 @@ export function normalizeTimestamp(rfc3339) {
|
|
|
80
80
|
* Query v3 Reporting API
|
|
81
81
|
*/
|
|
82
82
|
export async function queryReporting(requestBody) {
|
|
83
|
-
|
|
84
|
-
console.error(`[reporting-client] POST ${REPORTING_ENDPOINT}`, JSON.stringify(requestBody, null, 2));
|
|
85
|
-
}
|
|
83
|
+
debug("reporting-client", `POST ${REPORTING_ENDPOINT}`, JSON.stringify(requestBody, null, 2));
|
|
86
84
|
try {
|
|
87
85
|
// Get auth token
|
|
88
86
|
const token = await authClient.getToken();
|
|
89
87
|
// Make request
|
|
90
|
-
const response = await
|
|
88
|
+
const response = await fetch(REPORTING_ENDPOINT, {
|
|
91
89
|
method: "POST",
|
|
92
90
|
headers: {
|
|
93
91
|
"Content-Type": "application/json",
|
|
94
92
|
Authorization: `Bearer ${token}`,
|
|
95
93
|
},
|
|
96
94
|
body: JSON.stringify(requestBody),
|
|
95
|
+
signal: AbortSignal.timeout(30_000),
|
|
97
96
|
});
|
|
98
|
-
if (response.
|
|
99
|
-
const errorBody = await response.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
throw new ApiError(response.statusCode, `Butlr API error (${response.statusCode}). Enable DEBUG=butlr-mcp for details.`);
|
|
104
|
-
}
|
|
105
|
-
const data = (await response.body.json());
|
|
106
|
-
if (process.env.DEBUG) {
|
|
107
|
-
console.error(`[reporting-client] Response: ${data.data?.length || 0} data points`);
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const errorBody = await response.text();
|
|
99
|
+
debug("reporting-client", `API error body: ${errorBody}`);
|
|
100
|
+
throw new ApiError(response.status, `Butlr API error (${response.status}). Enable DEBUG=butlr-mcp for details.`);
|
|
108
101
|
}
|
|
102
|
+
const data = (await response.json());
|
|
103
|
+
debug("reporting-client", `Response: ${data.data?.length || 0} data points`);
|
|
109
104
|
return data;
|
|
110
105
|
}
|
|
111
106
|
catch (error) {
|
|
112
|
-
|
|
107
|
+
debug("reporting-client", "Request failed:", error);
|
|
113
108
|
// Translate common errors using structured ApiError
|
|
114
109
|
if (error instanceof ApiError) {
|
|
115
110
|
if (error.statusCode === 401 || error.statusCode === 403) {
|
|
@@ -272,7 +267,7 @@ export async function getCurrentOccupancy(assetType, assetIds) {
|
|
|
272
267
|
const presenceResponse = presenceResult.status === "fulfilled" ? presenceResult.value : { data: [] };
|
|
273
268
|
const trafficResponse = trafficResult.status === "fulfilled" ? trafficResult.value : { data: [] };
|
|
274
269
|
if (trafficResult.status === "rejected") {
|
|
275
|
-
|
|
270
|
+
debug("reporting-client", "Traffic query failed (may not have traffic sensors):", trafficResult.reason);
|
|
276
271
|
}
|
|
277
272
|
// Normalize presence data
|
|
278
273
|
// Response structure: { "room_123": { "2025-10-10T00:00:00Z": { "max": 5 } } }
|