@access-mcp/system-status 0.5.0 → 0.6.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/README.md +16 -132
- package/dist/__tests__/server.integration.test.js +66 -40
- package/dist/__tests__/server.test.js +183 -86
- package/dist/index.js +1 -1
- package/dist/server.d.ts +11 -56
- package/dist/server.js +135 -67
- package/dist/web-server.js +1 -1
- package/package.json +2 -2
package/dist/server.js
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
|
-
import { BaseAccessServer, handleApiError } from "@access-mcp/shared";
|
|
1
|
+
import { BaseAccessServer, handleApiError, resolveResourceId, } from "@access-mcp/shared";
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const { version } = require("../package.json");
|
|
2
5
|
export class SystemStatusServer extends BaseAccessServer {
|
|
3
6
|
constructor() {
|
|
4
|
-
super("access-mcp-system-status",
|
|
7
|
+
super("access-mcp-system-status", version, "https://operations-api.access-ci.org");
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Search for resources by name to resolve human-readable names to full IDs.
|
|
11
|
+
* Used by resolveResourceId callback.
|
|
12
|
+
*/
|
|
13
|
+
async searchResourcesByName(query) {
|
|
14
|
+
try {
|
|
15
|
+
const response = await this.httpClient.get("/wh2/cider/v1/access-active-groups/type/resource-catalog.access-ci.org/");
|
|
16
|
+
const groups = response.data.results?.active_groups || [];
|
|
17
|
+
const queryLower = query.toLowerCase();
|
|
18
|
+
return groups
|
|
19
|
+
.filter((g) => g.group_descriptive_name?.toLowerCase().includes(queryLower))
|
|
20
|
+
.map((g) => ({
|
|
21
|
+
id: g.info_groupid || "",
|
|
22
|
+
name: g.group_descriptive_name || "",
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
5
28
|
}
|
|
6
29
|
getTools() {
|
|
7
30
|
return [
|
|
@@ -13,30 +36,30 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
13
36
|
properties: {
|
|
14
37
|
query: {
|
|
15
38
|
type: "string",
|
|
16
|
-
description: "Filter by resource name (e.g., 'delta', 'bridges2')"
|
|
39
|
+
description: "Filter by resource name (e.g., 'delta', 'bridges2')",
|
|
17
40
|
},
|
|
18
41
|
time: {
|
|
19
42
|
type: "string",
|
|
20
43
|
enum: ["current", "scheduled", "past", "all"],
|
|
21
|
-
description: "
|
|
22
|
-
default: "current"
|
|
44
|
+
description: "Time filter. Values: 'current' for active outages, 'scheduled' for future/planned, 'past' for historical, 'all' for everything",
|
|
45
|
+
default: "current",
|
|
23
46
|
},
|
|
24
47
|
ids: {
|
|
25
48
|
type: "array",
|
|
26
49
|
items: { type: "string" },
|
|
27
|
-
description: "Check status for specific
|
|
50
|
+
description: "Check status for specific resources. Accepts names (e.g., 'Anvil', 'Delta') or full IDs (e.g., 'anvil.purdue.access-ci.org')",
|
|
28
51
|
},
|
|
29
52
|
limit: {
|
|
30
53
|
type: "number",
|
|
31
54
|
description: "Max results (default: 50)",
|
|
32
|
-
default: 50
|
|
55
|
+
default: 50,
|
|
33
56
|
},
|
|
34
57
|
use_group_api: {
|
|
35
58
|
type: "boolean",
|
|
36
59
|
description: "Use group API for status (with ids only)",
|
|
37
|
-
default: false
|
|
38
|
-
}
|
|
39
|
-
}
|
|
60
|
+
default: false,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
40
63
|
},
|
|
41
64
|
},
|
|
42
65
|
];
|
|
@@ -71,15 +94,16 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
71
94
|
}
|
|
72
95
|
async handleToolCall(request) {
|
|
73
96
|
const { name, arguments: args = {} } = request.params;
|
|
97
|
+
const typedArgs = args;
|
|
74
98
|
try {
|
|
75
99
|
switch (name) {
|
|
76
100
|
case "get_infrastructure_news":
|
|
77
101
|
return await this.getInfrastructureNewsRouter({
|
|
78
|
-
resource:
|
|
79
|
-
time:
|
|
80
|
-
resource_ids:
|
|
81
|
-
limit:
|
|
82
|
-
use_group_api:
|
|
102
|
+
resource: typedArgs.query,
|
|
103
|
+
time: typedArgs.time,
|
|
104
|
+
resource_ids: typedArgs.ids,
|
|
105
|
+
limit: typedArgs.limit,
|
|
106
|
+
use_group_api: typedArgs.use_group_api,
|
|
83
107
|
});
|
|
84
108
|
default:
|
|
85
109
|
return this.errorResponse(`Unknown tool: ${name}`);
|
|
@@ -95,8 +119,8 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
95
119
|
*/
|
|
96
120
|
async getInfrastructureNewsRouter(args) {
|
|
97
121
|
const { resource, time = "current", resource_ids, limit, use_group_api = false } = args;
|
|
98
|
-
// Check resource status (returns operational/affected)
|
|
99
|
-
if (resource_ids && Array.isArray(resource_ids)) {
|
|
122
|
+
// Check resource status (returns operational/affected) - only if IDs provided
|
|
123
|
+
if (resource_ids && Array.isArray(resource_ids) && resource_ids.length > 0) {
|
|
100
124
|
return await this.checkResourceStatus(resource_ids, use_group_api);
|
|
101
125
|
}
|
|
102
126
|
// Time-based routing
|
|
@@ -116,7 +140,7 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
116
140
|
async handleResourceRead(request) {
|
|
117
141
|
const { uri } = request.params;
|
|
118
142
|
switch (uri) {
|
|
119
|
-
case "accessci://system-status":
|
|
143
|
+
case "accessci://system-status": {
|
|
120
144
|
return {
|
|
121
145
|
contents: [
|
|
122
146
|
{
|
|
@@ -126,39 +150,49 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
126
150
|
},
|
|
127
151
|
],
|
|
128
152
|
};
|
|
129
|
-
|
|
153
|
+
}
|
|
154
|
+
case "accessci://outages/current": {
|
|
130
155
|
const currentOutages = await this.getCurrentOutages();
|
|
156
|
+
const content = currentOutages.content[0];
|
|
157
|
+
const text = content.type === "text" ? content.text : "";
|
|
131
158
|
return {
|
|
132
159
|
contents: [
|
|
133
160
|
{
|
|
134
161
|
uri,
|
|
135
162
|
mimeType: "application/json",
|
|
136
|
-
text
|
|
163
|
+
text,
|
|
137
164
|
},
|
|
138
165
|
],
|
|
139
166
|
};
|
|
140
|
-
|
|
167
|
+
}
|
|
168
|
+
case "accessci://outages/scheduled": {
|
|
141
169
|
const scheduledMaintenance = await this.getScheduledMaintenance();
|
|
170
|
+
const content = scheduledMaintenance.content[0];
|
|
171
|
+
const text = content.type === "text" ? content.text : "";
|
|
142
172
|
return {
|
|
143
173
|
contents: [
|
|
144
174
|
{
|
|
145
175
|
uri,
|
|
146
176
|
mimeType: "application/json",
|
|
147
|
-
text
|
|
177
|
+
text,
|
|
148
178
|
},
|
|
149
179
|
],
|
|
150
180
|
};
|
|
151
|
-
|
|
181
|
+
}
|
|
182
|
+
case "accessci://outages/past": {
|
|
152
183
|
const pastOutages = await this.getPastOutages();
|
|
184
|
+
const content = pastOutages.content[0];
|
|
185
|
+
const text = content.type === "text" ? content.text : "";
|
|
153
186
|
return {
|
|
154
187
|
contents: [
|
|
155
188
|
{
|
|
156
189
|
uri,
|
|
157
190
|
mimeType: "application/json",
|
|
158
|
-
text
|
|
191
|
+
text,
|
|
159
192
|
},
|
|
160
193
|
],
|
|
161
194
|
};
|
|
195
|
+
}
|
|
162
196
|
default:
|
|
163
197
|
throw new Error(`Unknown resource: ${uri}`);
|
|
164
198
|
}
|
|
@@ -178,9 +212,11 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
178
212
|
const severityCounts = { high: 0, medium: 0, low: 0, unknown: 0 };
|
|
179
213
|
// Enhance outages with status summary
|
|
180
214
|
const enhancedOutages = outages.map((outage) => {
|
|
181
|
-
// Track affected resources
|
|
215
|
+
// Track affected resources (use ResourceID as fallback if ResourceName is missing)
|
|
182
216
|
outage.AffectedResources?.forEach((resource) => {
|
|
183
|
-
|
|
217
|
+
const resourceIdentifier = resource.ResourceName || resource.ResourceID;
|
|
218
|
+
if (resourceIdentifier)
|
|
219
|
+
affectedResources.add(String(resourceIdentifier));
|
|
184
220
|
});
|
|
185
221
|
// Categorize severity (basic heuristic)
|
|
186
222
|
const subject = outage.Subject?.toLowerCase() || "";
|
|
@@ -188,8 +224,7 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
188
224
|
if (subject.includes("emergency") || subject.includes("critical")) {
|
|
189
225
|
severity = "high";
|
|
190
226
|
}
|
|
191
|
-
else if (subject.includes("maintenance") ||
|
|
192
|
-
subject.includes("scheduled")) {
|
|
227
|
+
else if (subject.includes("maintenance") || subject.includes("scheduled")) {
|
|
193
228
|
severity = "low";
|
|
194
229
|
}
|
|
195
230
|
else {
|
|
@@ -228,8 +263,8 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
228
263
|
}
|
|
229
264
|
// Sort by scheduled start time
|
|
230
265
|
maintenance.sort((a, b) => {
|
|
231
|
-
const dateA = new Date(a.OutageStart);
|
|
232
|
-
const dateB = new Date(b.OutageStart);
|
|
266
|
+
const dateA = new Date(a.OutageStart || "");
|
|
267
|
+
const dateB = new Date(b.OutageStart || "");
|
|
233
268
|
return dateA.getTime() - dateB.getTime();
|
|
234
269
|
});
|
|
235
270
|
// Initialize tracking variables
|
|
@@ -239,11 +274,13 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
239
274
|
const enhancedMaintenance = maintenance.map((item) => {
|
|
240
275
|
// Track affected resources
|
|
241
276
|
item.AffectedResources?.forEach((resource) => {
|
|
242
|
-
|
|
277
|
+
const resourceIdentifier = resource.ResourceName || resource.ResourceID;
|
|
278
|
+
if (resourceIdentifier)
|
|
279
|
+
affectedResources.add(String(resourceIdentifier));
|
|
243
280
|
});
|
|
244
281
|
// Check timing - use OutageStart for scheduling
|
|
245
282
|
const hasScheduledTime = !!item.OutageStart;
|
|
246
|
-
const startTime = new Date(item.OutageStart);
|
|
283
|
+
const startTime = new Date(item.OutageStart || "");
|
|
247
284
|
const now = new Date();
|
|
248
285
|
const hoursUntil = (startTime.getTime() - now.getTime()) / (1000 * 60 * 60);
|
|
249
286
|
if (hoursUntil <= 24)
|
|
@@ -256,8 +293,7 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
256
293
|
scheduled_end: item.OutageEnd,
|
|
257
294
|
hours_until_start: Math.max(0, Math.round(hoursUntil)),
|
|
258
295
|
duration_hours: item.OutageEnd && item.OutageStart
|
|
259
|
-
? Math.round((new Date(item.OutageEnd).getTime() -
|
|
260
|
-
new Date(item.OutageStart).getTime()) /
|
|
296
|
+
? Math.round((new Date(item.OutageEnd).getTime() - new Date(item.OutageStart).getTime()) /
|
|
261
297
|
(1000 * 60 * 60))
|
|
262
298
|
: null,
|
|
263
299
|
has_scheduled_time: hasScheduledTime,
|
|
@@ -291,8 +327,8 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
291
327
|
}
|
|
292
328
|
// Sort by outage end time (most recent first)
|
|
293
329
|
pastOutages.sort((a, b) => {
|
|
294
|
-
const dateA = new Date(a.OutageEnd);
|
|
295
|
-
const dateB = new Date(b.OutageEnd);
|
|
330
|
+
const dateA = new Date(a.OutageEnd || "");
|
|
331
|
+
const dateB = new Date(b.OutageEnd || "");
|
|
296
332
|
return dateB.getTime() - dateA.getTime();
|
|
297
333
|
});
|
|
298
334
|
// Apply limit
|
|
@@ -303,23 +339,25 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
303
339
|
const affectedResources = new Set();
|
|
304
340
|
const outageTypes = new Set();
|
|
305
341
|
const recentOutages = pastOutages.filter((outage) => {
|
|
306
|
-
const endTime = new Date(outage.OutageEnd);
|
|
342
|
+
const endTime = new Date(outage.OutageEnd || "");
|
|
307
343
|
const daysAgo = (Date.now() - endTime.getTime()) / (1000 * 60 * 60 * 24);
|
|
308
344
|
return daysAgo <= 30; // Last 30 days
|
|
309
345
|
});
|
|
310
346
|
// Enhance outages with calculated fields
|
|
311
347
|
const enhancedOutages = pastOutages.map((outage) => {
|
|
312
|
-
// Track affected resources
|
|
348
|
+
// Track affected resources (use ResourceID as fallback if ResourceName is missing)
|
|
313
349
|
outage.AffectedResources?.forEach((resource) => {
|
|
314
|
-
|
|
350
|
+
const resourceIdentifier = resource.ResourceName || resource.ResourceID;
|
|
351
|
+
if (resourceIdentifier)
|
|
352
|
+
affectedResources.add(String(resourceIdentifier));
|
|
315
353
|
});
|
|
316
354
|
// Track outage types
|
|
317
355
|
if (outage.OutageType) {
|
|
318
356
|
outageTypes.add(outage.OutageType);
|
|
319
357
|
}
|
|
320
358
|
// Calculate duration
|
|
321
|
-
const startTime = new Date(outage.OutageStart);
|
|
322
|
-
const endTime = new Date(outage.OutageEnd);
|
|
359
|
+
const startTime = new Date(outage.OutageStart || "");
|
|
360
|
+
const endTime = new Date(outage.OutageEnd || "");
|
|
323
361
|
const durationHours = Math.round((endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60));
|
|
324
362
|
// Calculate how long ago it ended
|
|
325
363
|
const daysAgo = Math.round((Date.now() - endTime.getTime()) / (1000 * 60 * 60 * 24));
|
|
@@ -339,9 +377,9 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
339
377
|
outage_types: Array.from(outageTypes),
|
|
340
378
|
average_duration_hours: enhancedOutages.length > 0
|
|
341
379
|
? Math.round(enhancedOutages
|
|
342
|
-
.filter((o) => o.duration_hours > 0)
|
|
343
|
-
.reduce((sum, o) => sum + o.duration_hours, 0) /
|
|
344
|
-
enhancedOutages.filter((o) => o.duration_hours > 0).length)
|
|
380
|
+
.filter((o) => o.duration_hours && o.duration_hours > 0)
|
|
381
|
+
.reduce((sum, o) => sum + (o.duration_hours || 0), 0) /
|
|
382
|
+
enhancedOutages.filter((o) => o.duration_hours && o.duration_hours > 0).length)
|
|
345
383
|
: 0,
|
|
346
384
|
outages: enhancedOutages,
|
|
347
385
|
};
|
|
@@ -363,27 +401,30 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
363
401
|
]);
|
|
364
402
|
const currentOutages = currentResponse.data.results || [];
|
|
365
403
|
const futureOutages = futureResponse.data.results || [];
|
|
366
|
-
const
|
|
404
|
+
const pastOutagesData = pastResponse.data.results || [];
|
|
367
405
|
// Filter recent past outages (last 30 days) for announcements
|
|
368
|
-
const recentPastOutages =
|
|
369
|
-
const endTime = new Date(outage.OutageEnd);
|
|
406
|
+
const recentPastOutages = pastOutagesData.filter((outage) => {
|
|
407
|
+
const endTime = new Date(outage.OutageEnd || "");
|
|
370
408
|
const daysAgo = (Date.now() - endTime.getTime()) / (1000 * 60 * 60 * 24);
|
|
371
409
|
return daysAgo <= 30;
|
|
372
410
|
});
|
|
373
411
|
// Combine all announcements and sort by most relevant date
|
|
374
412
|
const allAnnouncements = [
|
|
375
|
-
...currentOutages.map((item) => ({ ...item, category:
|
|
376
|
-
...futureOutages.map((item) => ({ ...item, category:
|
|
377
|
-
...recentPastOutages.map((item) => ({
|
|
413
|
+
...currentOutages.map((item) => ({ ...item, category: "current" })),
|
|
414
|
+
...futureOutages.map((item) => ({ ...item, category: "scheduled" })),
|
|
415
|
+
...recentPastOutages.map((item) => ({
|
|
416
|
+
...item,
|
|
417
|
+
category: "recent_past",
|
|
418
|
+
})),
|
|
378
419
|
]
|
|
379
420
|
.sort((a, b) => {
|
|
380
421
|
// Sort by most relevant date: current first, then future by start time, then past by end time
|
|
381
|
-
if (a.category ===
|
|
422
|
+
if (a.category === "current" && b.category !== "current")
|
|
382
423
|
return -1;
|
|
383
|
-
if (b.category ===
|
|
424
|
+
if (b.category === "current" && a.category !== "current")
|
|
384
425
|
return 1;
|
|
385
|
-
const dateA = new Date(a.OutageStart);
|
|
386
|
-
const dateB = new Date(b.OutageStart);
|
|
426
|
+
const dateA = new Date(a.OutageStart || "");
|
|
427
|
+
const dateB = new Date(b.OutageStart || "");
|
|
387
428
|
return dateB.getTime() - dateA.getTime(); // Most recent first
|
|
388
429
|
})
|
|
389
430
|
.slice(0, limit);
|
|
@@ -393,9 +434,9 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
393
434
|
scheduled_maintenance: futureOutages.length,
|
|
394
435
|
recent_past_outages: recentPastOutages.length,
|
|
395
436
|
categories: {
|
|
396
|
-
current: allAnnouncements.filter(a => a.category ===
|
|
397
|
-
scheduled: allAnnouncements.filter(a => a.category ===
|
|
398
|
-
recent_past: allAnnouncements.filter(a => a.category ===
|
|
437
|
+
current: allAnnouncements.filter((a) => a.category === "current").length,
|
|
438
|
+
scheduled: allAnnouncements.filter((a) => a.category === "scheduled").length,
|
|
439
|
+
recent_past: allAnnouncements.filter((a) => a.category === "recent_past").length,
|
|
399
440
|
},
|
|
400
441
|
announcements: allAnnouncements,
|
|
401
442
|
};
|
|
@@ -412,13 +453,43 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
412
453
|
if (!resourceIds || !Array.isArray(resourceIds) || resourceIds.length === 0) {
|
|
413
454
|
throw new Error("resource_ids parameter is required and must be a non-empty array of resource IDs");
|
|
414
455
|
}
|
|
456
|
+
// Resolve all resource names to IDs first
|
|
457
|
+
const resolvedIds = [];
|
|
458
|
+
const resolutionErrors = [];
|
|
459
|
+
for (const inputId of resourceIds) {
|
|
460
|
+
const resolved = await resolveResourceId(inputId, (query) => this.searchResourcesByName(query));
|
|
461
|
+
if (resolved.success) {
|
|
462
|
+
resolvedIds.push(resolved.id);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
resolutionErrors.push({ input: inputId, error: resolved.error });
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// If any resolutions failed, return errors
|
|
469
|
+
if (resolutionErrors.length > 0) {
|
|
470
|
+
return {
|
|
471
|
+
content: [
|
|
472
|
+
{
|
|
473
|
+
type: "text",
|
|
474
|
+
text: JSON.stringify({
|
|
475
|
+
error: "Could not resolve some resource names",
|
|
476
|
+
resolution_errors: resolutionErrors,
|
|
477
|
+
suggestions: [
|
|
478
|
+
"Use full resource IDs (e.g., 'anvil.purdue.access-ci.org')",
|
|
479
|
+
"Or use exact resource names (e.g., 'Anvil', 'Delta')",
|
|
480
|
+
],
|
|
481
|
+
}, null, 2),
|
|
482
|
+
},
|
|
483
|
+
],
|
|
484
|
+
};
|
|
485
|
+
}
|
|
415
486
|
if (useGroupApi) {
|
|
416
|
-
return await this.checkResourceStatusViaGroups(
|
|
487
|
+
return await this.checkResourceStatusViaGroups(resolvedIds);
|
|
417
488
|
}
|
|
418
489
|
// Efficient approach: fetch raw current outages data once
|
|
419
490
|
const response = await this.httpClient.get("/wh2/news/v1/affiliation/access-ci.org/current_outages/");
|
|
420
491
|
const rawOutages = response.data.results || [];
|
|
421
|
-
const resourceStatus =
|
|
492
|
+
const resourceStatus = resolvedIds.map((resourceId) => {
|
|
422
493
|
const affectedOutages = rawOutages.filter((outage) => outage.AffectedResources?.some((resource) => resource.ResourceID?.toString() === resourceId ||
|
|
423
494
|
resource.ResourceName?.toLowerCase().includes(resourceId.toLowerCase())));
|
|
424
495
|
let status = "operational";
|
|
@@ -462,10 +533,9 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
462
533
|
type: "text",
|
|
463
534
|
text: JSON.stringify({
|
|
464
535
|
checked_at: new Date().toISOString(),
|
|
465
|
-
resources_checked:
|
|
536
|
+
resources_checked: resolvedIds.length,
|
|
466
537
|
operational: resourceStatus.filter((r) => r.status === "operational").length,
|
|
467
|
-
affected: resourceStatus.filter((r) => r.status === "affected")
|
|
468
|
-
.length,
|
|
538
|
+
affected: resourceStatus.filter((r) => r.status === "affected").length,
|
|
469
539
|
api_method: "direct_outages_check",
|
|
470
540
|
resource_status: resourceStatus,
|
|
471
541
|
}, null, 2),
|
|
@@ -494,7 +564,7 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
494
564
|
api_method: "group_specific",
|
|
495
565
|
};
|
|
496
566
|
}
|
|
497
|
-
catch
|
|
567
|
+
catch {
|
|
498
568
|
// Fallback to general check if group API fails
|
|
499
569
|
return {
|
|
500
570
|
resource_id: resourceId,
|
|
@@ -516,10 +586,8 @@ export class SystemStatusServer extends BaseAccessServer {
|
|
|
516
586
|
checked_at: new Date().toISOString(),
|
|
517
587
|
resources_checked: resourceIds.length,
|
|
518
588
|
operational: resourceStatus.filter((r) => r.status === "operational").length,
|
|
519
|
-
affected: resourceStatus.filter((r) => r.status === "affected")
|
|
520
|
-
|
|
521
|
-
unknown: resourceStatus.filter((r) => r.status === "unknown")
|
|
522
|
-
.length,
|
|
589
|
+
affected: resourceStatus.filter((r) => r.status === "affected").length,
|
|
590
|
+
unknown: resourceStatus.filter((r) => r.status === "unknown").length,
|
|
523
591
|
api_method: "resource_group_api",
|
|
524
592
|
resource_status: resourceStatus,
|
|
525
593
|
}, null, 2),
|
package/dist/web-server.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from "path";
|
|
|
3
3
|
import { SystemStatusServer } from "./server.js";
|
|
4
4
|
export function startWebServer(port = 3000) {
|
|
5
5
|
const app = express();
|
|
6
|
-
|
|
6
|
+
new SystemStatusServer();
|
|
7
7
|
// Serve static files from public directory
|
|
8
8
|
const publicDir = path.join(__dirname, "../../../public");
|
|
9
9
|
app.use(express.static(publicDir));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@access-mcp/system-status",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "MCP server for ACCESS-CI System Status and Outages API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"node": ">=18.0.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@access-mcp/shared": "^0.
|
|
47
|
+
"@access-mcp/shared": "^0.6.0",
|
|
48
48
|
"express": "^4.18.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|