@access-mcp/system-status 0.2.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 +65 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +20 -0
- package/dist/server.d.ts +76 -0
- package/dist/server.js +347 -0
- package/dist/web-server.d.ts +1 -0
- package/dist/web-server.js +50 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# ACCESS-CI System Status MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server providing real-time system status information for ACCESS-CI resources.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This server provides critical operational information about ACCESS-CI systems, including current outages, scheduled maintenance, and system-wide announcements.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
### get_current_outages
|
|
12
|
+
Get current system outages and issues affecting ACCESS-CI resources.
|
|
13
|
+
|
|
14
|
+
**Parameters:**
|
|
15
|
+
- `resource_filter` (string, optional): Filter by specific resource name or ID
|
|
16
|
+
|
|
17
|
+
### get_scheduled_maintenance
|
|
18
|
+
Get scheduled maintenance and future outages for ACCESS-CI resources.
|
|
19
|
+
|
|
20
|
+
**Parameters:**
|
|
21
|
+
- `resource_filter` (string, optional): Filter by specific resource name or ID
|
|
22
|
+
|
|
23
|
+
### get_system_announcements
|
|
24
|
+
Get all system announcements (current and scheduled).
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `limit` (number, optional): Maximum number of announcements to return (default: 50)
|
|
28
|
+
|
|
29
|
+
### get_resource_status
|
|
30
|
+
Get the current operational status of a specific resource.
|
|
31
|
+
|
|
32
|
+
**Parameters:**
|
|
33
|
+
- `resource_id` (string): The resource ID to check status for
|
|
34
|
+
|
|
35
|
+
## Resources
|
|
36
|
+
|
|
37
|
+
- `accessci://system-status`: Current operational status of all ACCESS-CI resources
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g @access-mcp/system-status
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
Add to your Claude Desktop configuration:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"access-system-status": {
|
|
53
|
+
"command": "access-mcp-system-status"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## API Endpoints
|
|
60
|
+
|
|
61
|
+
This server connects to the ACCESS-CI Operations API at `https://operations-api.access-ci.org`
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { SystemStatusServer } from './server.js';
|
|
3
|
+
import { startWebServer } from './web-server.js';
|
|
4
|
+
async function main() {
|
|
5
|
+
// Check if we should run as web server (for deployment)
|
|
6
|
+
const port = process.env.PORT;
|
|
7
|
+
if (port) {
|
|
8
|
+
// Running in web mode (deployment)
|
|
9
|
+
startWebServer(parseInt(port));
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
// Running in MCP mode (stdio)
|
|
13
|
+
const server = new SystemStatusServer();
|
|
14
|
+
await server.start();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
main().catch((error) => {
|
|
18
|
+
// Log errors to a file instead of stderr to avoid interfering with JSON-RPC
|
|
19
|
+
process.exit(1);
|
|
20
|
+
});
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BaseAccessServer } from '../../shared/dist/index.js';
|
|
2
|
+
export declare class SystemStatusServer extends BaseAccessServer {
|
|
3
|
+
constructor();
|
|
4
|
+
protected getTools(): ({
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
resource_filter: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
limit?: undefined;
|
|
15
|
+
resource_ids?: undefined;
|
|
16
|
+
};
|
|
17
|
+
required: never[];
|
|
18
|
+
};
|
|
19
|
+
} | {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: string;
|
|
24
|
+
properties: {
|
|
25
|
+
limit: {
|
|
26
|
+
type: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
resource_filter?: undefined;
|
|
30
|
+
resource_ids?: undefined;
|
|
31
|
+
};
|
|
32
|
+
required: never[];
|
|
33
|
+
};
|
|
34
|
+
} | {
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: string;
|
|
39
|
+
properties: {
|
|
40
|
+
resource_ids: {
|
|
41
|
+
type: string;
|
|
42
|
+
items: {
|
|
43
|
+
type: string;
|
|
44
|
+
};
|
|
45
|
+
description: string;
|
|
46
|
+
};
|
|
47
|
+
resource_filter?: undefined;
|
|
48
|
+
limit?: undefined;
|
|
49
|
+
};
|
|
50
|
+
required: string[];
|
|
51
|
+
};
|
|
52
|
+
})[];
|
|
53
|
+
protected getResources(): {
|
|
54
|
+
uri: string;
|
|
55
|
+
name: string;
|
|
56
|
+
description: string;
|
|
57
|
+
mimeType: string;
|
|
58
|
+
}[];
|
|
59
|
+
handleToolCall(request: any): Promise<{
|
|
60
|
+
content: {
|
|
61
|
+
type: string;
|
|
62
|
+
text: string;
|
|
63
|
+
}[];
|
|
64
|
+
}>;
|
|
65
|
+
handleResourceRead(request: any): Promise<{
|
|
66
|
+
contents: {
|
|
67
|
+
uri: any;
|
|
68
|
+
mimeType: string;
|
|
69
|
+
text: string;
|
|
70
|
+
}[];
|
|
71
|
+
}>;
|
|
72
|
+
private getCurrentOutages;
|
|
73
|
+
private getScheduledMaintenance;
|
|
74
|
+
private getSystemAnnouncements;
|
|
75
|
+
private checkResourceStatus;
|
|
76
|
+
}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { BaseAccessServer, handleApiError } from '../../shared/dist/index.js';
|
|
2
|
+
export class SystemStatusServer extends BaseAccessServer {
|
|
3
|
+
constructor() {
|
|
4
|
+
super('access-mcp-system-status', '0.1.0', 'https://operations-api.access-ci.org');
|
|
5
|
+
}
|
|
6
|
+
getTools() {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
name: 'get_current_outages',
|
|
10
|
+
description: 'Get current system outages and issues affecting ACCESS-CI resources',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
resource_filter: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Optional: filter by specific resource name or ID',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: [],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'get_scheduled_maintenance',
|
|
24
|
+
description: 'Get scheduled maintenance and future outages for ACCESS-CI resources',
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
resource_filter: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Optional: filter by specific resource name or ID',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: [],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'get_system_announcements',
|
|
38
|
+
description: 'Get all system announcements (current and scheduled)',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
limit: {
|
|
43
|
+
type: 'number',
|
|
44
|
+
description: 'Maximum number of announcements to return (default: 50)',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: [],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'check_resource_status',
|
|
52
|
+
description: 'Check the operational status of specific ACCESS-CI resources',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
resource_ids: {
|
|
57
|
+
type: 'array',
|
|
58
|
+
items: { type: 'string' },
|
|
59
|
+
description: 'List of resource IDs to check status for',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
required: ['resource_ids'],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
getResources() {
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
uri: 'accessci://system-status',
|
|
71
|
+
name: 'ACCESS-CI System Status',
|
|
72
|
+
description: 'Real-time status of ACCESS-CI infrastructure, outages, and maintenance',
|
|
73
|
+
mimeType: 'application/json',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
uri: 'accessci://outages/current',
|
|
77
|
+
name: 'Current Outages',
|
|
78
|
+
description: 'Currently active outages and system issues',
|
|
79
|
+
mimeType: 'application/json',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
uri: 'accessci://outages/scheduled',
|
|
83
|
+
name: 'Scheduled Maintenance',
|
|
84
|
+
description: 'Upcoming scheduled maintenance and planned outages',
|
|
85
|
+
mimeType: 'application/json',
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
async handleToolCall(request) {
|
|
90
|
+
const { name, arguments: args = {} } = request.params;
|
|
91
|
+
try {
|
|
92
|
+
switch (name) {
|
|
93
|
+
case 'get_current_outages':
|
|
94
|
+
return await this.getCurrentOutages(args.resource_filter);
|
|
95
|
+
case 'get_scheduled_maintenance':
|
|
96
|
+
return await this.getScheduledMaintenance(args.resource_filter);
|
|
97
|
+
case 'get_system_announcements':
|
|
98
|
+
return await this.getSystemAnnouncements(args.limit);
|
|
99
|
+
case 'check_resource_status':
|
|
100
|
+
return await this.checkResourceStatus(args.resource_ids);
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: 'text',
|
|
110
|
+
text: `Error: ${handleApiError(error)}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async handleResourceRead(request) {
|
|
117
|
+
const { uri } = request.params;
|
|
118
|
+
switch (uri) {
|
|
119
|
+
case 'accessci://system-status':
|
|
120
|
+
return {
|
|
121
|
+
contents: [
|
|
122
|
+
{
|
|
123
|
+
uri,
|
|
124
|
+
mimeType: 'text/plain',
|
|
125
|
+
text: 'ACCESS-CI System Status API - Monitor real-time status, outages, and maintenance for ACCESS-CI resources.',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
case 'accessci://outages/current':
|
|
130
|
+
const currentOutages = await this.getCurrentOutages();
|
|
131
|
+
return {
|
|
132
|
+
contents: [
|
|
133
|
+
{
|
|
134
|
+
uri,
|
|
135
|
+
mimeType: 'application/json',
|
|
136
|
+
text: currentOutages.content[0].text,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
case 'accessci://outages/scheduled':
|
|
141
|
+
const scheduledMaintenance = await this.getScheduledMaintenance();
|
|
142
|
+
return {
|
|
143
|
+
contents: [
|
|
144
|
+
{
|
|
145
|
+
uri,
|
|
146
|
+
mimeType: 'application/json',
|
|
147
|
+
text: scheduledMaintenance.content[0].text,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
default:
|
|
152
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async getCurrentOutages(resourceFilter) {
|
|
156
|
+
const response = await this.httpClient.get('/wh2/news/v1/affiliation/access-ci.org/current_outages/');
|
|
157
|
+
let outages = response.data.results || [];
|
|
158
|
+
// Filter by resource if specified
|
|
159
|
+
if (resourceFilter) {
|
|
160
|
+
const filter = resourceFilter.toLowerCase();
|
|
161
|
+
outages = outages.filter((outage) => outage.Subject?.toLowerCase().includes(filter) ||
|
|
162
|
+
outage.AffectedResources?.some((resource) => resource.ResourceName?.toLowerCase().includes(filter) ||
|
|
163
|
+
resource.ResourceID?.toString().includes(filter)));
|
|
164
|
+
}
|
|
165
|
+
// Initialize tracking variables
|
|
166
|
+
const affectedResources = new Set();
|
|
167
|
+
const severityCounts = { high: 0, medium: 0, low: 0, unknown: 0 };
|
|
168
|
+
// Enhance outages with status summary
|
|
169
|
+
const enhancedOutages = outages.map((outage) => {
|
|
170
|
+
// Track affected resources
|
|
171
|
+
outage.AffectedResources?.forEach((resource) => {
|
|
172
|
+
affectedResources.add(resource.ResourceName);
|
|
173
|
+
});
|
|
174
|
+
// Categorize severity (basic heuristic)
|
|
175
|
+
const subject = outage.Subject?.toLowerCase() || '';
|
|
176
|
+
let severity = 'unknown';
|
|
177
|
+
if (subject.includes('emergency') || subject.includes('critical')) {
|
|
178
|
+
severity = 'high';
|
|
179
|
+
}
|
|
180
|
+
else if (subject.includes('maintenance') || subject.includes('scheduled')) {
|
|
181
|
+
severity = 'low';
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
severity = 'medium';
|
|
185
|
+
}
|
|
186
|
+
severityCounts[severity]++;
|
|
187
|
+
return {
|
|
188
|
+
...outage,
|
|
189
|
+
severity,
|
|
190
|
+
posted_time: outage.CreationTime,
|
|
191
|
+
last_updated: outage.LastModificationTime,
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
const summary = {
|
|
195
|
+
total_outages: outages.length,
|
|
196
|
+
affected_resources: Array.from(affectedResources),
|
|
197
|
+
severity_counts: severityCounts,
|
|
198
|
+
outages: enhancedOutages
|
|
199
|
+
};
|
|
200
|
+
return {
|
|
201
|
+
content: [
|
|
202
|
+
{
|
|
203
|
+
type: 'text',
|
|
204
|
+
text: JSON.stringify({
|
|
205
|
+
...summary,
|
|
206
|
+
affected_resources: summary.affected_resources
|
|
207
|
+
}, null, 2),
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
async getScheduledMaintenance(resourceFilter) {
|
|
213
|
+
const response = await this.httpClient.get('/wh2/news/v1/affiliation/access-ci.org/future_outages/');
|
|
214
|
+
let maintenance = response.data.results || [];
|
|
215
|
+
// Filter by resource if specified
|
|
216
|
+
if (resourceFilter) {
|
|
217
|
+
const filter = resourceFilter.toLowerCase();
|
|
218
|
+
maintenance = maintenance.filter((item) => item.Subject?.toLowerCase().includes(filter) ||
|
|
219
|
+
item.AffectedResources?.some((resource) => resource.ResourceName?.toLowerCase().includes(filter) ||
|
|
220
|
+
resource.ResourceID?.toString().includes(filter)));
|
|
221
|
+
}
|
|
222
|
+
// Sort by scheduled start time
|
|
223
|
+
maintenance.sort((a, b) => {
|
|
224
|
+
const dateA = new Date(a.OutageStartDateTime || a.CreationTime);
|
|
225
|
+
const dateB = new Date(b.OutageStartDateTime || b.CreationTime);
|
|
226
|
+
return dateA.getTime() - dateB.getTime();
|
|
227
|
+
});
|
|
228
|
+
const summary = {
|
|
229
|
+
total_scheduled: maintenance.length,
|
|
230
|
+
upcoming_24h: 0,
|
|
231
|
+
upcoming_week: 0,
|
|
232
|
+
affected_resources: new Set(),
|
|
233
|
+
maintenance: maintenance.map((item) => {
|
|
234
|
+
// Track affected resources
|
|
235
|
+
item.AffectedResources?.forEach((resource) => {
|
|
236
|
+
summary.affected_resources.add(resource.ResourceName);
|
|
237
|
+
});
|
|
238
|
+
// Check timing
|
|
239
|
+
const startTime = new Date(item.OutageStartDateTime || item.CreationTime);
|
|
240
|
+
const now = new Date();
|
|
241
|
+
const hoursUntil = (startTime.getTime() - now.getTime()) / (1000 * 60 * 60);
|
|
242
|
+
if (hoursUntil <= 24)
|
|
243
|
+
summary.upcoming_24h++;
|
|
244
|
+
if (hoursUntil <= 168)
|
|
245
|
+
summary.upcoming_week++; // 7 days * 24 hours
|
|
246
|
+
return {
|
|
247
|
+
...item,
|
|
248
|
+
scheduled_start: item.OutageStartDateTime,
|
|
249
|
+
scheduled_end: item.OutageEndDateTime,
|
|
250
|
+
hours_until_start: Math.max(0, Math.round(hoursUntil)),
|
|
251
|
+
duration_hours: item.OutageEndDateTime && item.OutageStartDateTime
|
|
252
|
+
? Math.round((new Date(item.OutageEndDateTime).getTime() -
|
|
253
|
+
new Date(item.OutageStartDateTime).getTime()) / (1000 * 60 * 60))
|
|
254
|
+
: null,
|
|
255
|
+
};
|
|
256
|
+
})
|
|
257
|
+
};
|
|
258
|
+
return {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: 'text',
|
|
262
|
+
text: JSON.stringify({
|
|
263
|
+
...summary,
|
|
264
|
+
affected_resources: summary.affected_resources
|
|
265
|
+
}, null, 2),
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
async getSystemAnnouncements(limit = 50) {
|
|
271
|
+
// Get both current and future announcements
|
|
272
|
+
const [currentResponse, futureResponse] = await Promise.all([
|
|
273
|
+
this.httpClient.get('/wh2/news/v1/affiliation/access-ci.org/current_outages/'),
|
|
274
|
+
this.httpClient.get('/wh2/news/v1/affiliation/access-ci.org/future_outages/')
|
|
275
|
+
]);
|
|
276
|
+
const currentOutages = currentResponse.data.results || [];
|
|
277
|
+
const futureOutages = futureResponse.data.results || [];
|
|
278
|
+
// Combine and sort by creation time
|
|
279
|
+
const allAnnouncements = [...currentOutages, ...futureOutages]
|
|
280
|
+
.sort((a, b) => {
|
|
281
|
+
const dateA = new Date(a.CreationTime);
|
|
282
|
+
const dateB = new Date(b.CreationTime);
|
|
283
|
+
return dateB.getTime() - dateA.getTime(); // Most recent first
|
|
284
|
+
})
|
|
285
|
+
.slice(0, limit);
|
|
286
|
+
return {
|
|
287
|
+
content: [
|
|
288
|
+
{
|
|
289
|
+
type: 'text',
|
|
290
|
+
text: JSON.stringify({
|
|
291
|
+
total_announcements: allAnnouncements.length,
|
|
292
|
+
current_outages: currentOutages.length,
|
|
293
|
+
scheduled_maintenance: futureOutages.length,
|
|
294
|
+
announcements: allAnnouncements
|
|
295
|
+
}, null, 2),
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
async checkResourceStatus(resourceIds) {
|
|
301
|
+
// Get current outages to check against resource IDs
|
|
302
|
+
const currentOutages = await this.getCurrentOutages();
|
|
303
|
+
const outageData = JSON.parse(currentOutages.content[0].text);
|
|
304
|
+
const resourceStatus = resourceIds.map(resourceId => {
|
|
305
|
+
const affectedOutages = outageData.outages.filter((outage) => outage.AffectedResources?.some((resource) => resource.ResourceID?.toString() === resourceId ||
|
|
306
|
+
resource.ResourceName?.toLowerCase().includes(resourceId.toLowerCase())));
|
|
307
|
+
let status = 'operational';
|
|
308
|
+
let severity = null;
|
|
309
|
+
if (affectedOutages.length > 0) {
|
|
310
|
+
status = 'affected';
|
|
311
|
+
// Get highest severity
|
|
312
|
+
const severities = affectedOutages.map((o) => o.severity);
|
|
313
|
+
if (severities.includes('high'))
|
|
314
|
+
severity = 'high';
|
|
315
|
+
else if (severities.includes('medium'))
|
|
316
|
+
severity = 'medium';
|
|
317
|
+
else
|
|
318
|
+
severity = 'low';
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
resource_id: resourceId,
|
|
322
|
+
status,
|
|
323
|
+
severity,
|
|
324
|
+
active_outages: affectedOutages.length,
|
|
325
|
+
outage_details: affectedOutages.map((outage) => ({
|
|
326
|
+
subject: outage.Subject,
|
|
327
|
+
severity: outage.severity,
|
|
328
|
+
posted: outage.posted_time
|
|
329
|
+
}))
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
return {
|
|
333
|
+
content: [
|
|
334
|
+
{
|
|
335
|
+
type: 'text',
|
|
336
|
+
text: JSON.stringify({
|
|
337
|
+
checked_at: new Date().toISOString(),
|
|
338
|
+
resources_checked: resourceIds.length,
|
|
339
|
+
operational: resourceStatus.filter(r => r.status === 'operational').length,
|
|
340
|
+
affected: resourceStatus.filter(r => r.status === 'affected').length,
|
|
341
|
+
resource_status: resourceStatus
|
|
342
|
+
}, null, 2),
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startWebServer(port?: number): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { SystemStatusServer } from './server.js';
|
|
4
|
+
export function startWebServer(port = 3000) {
|
|
5
|
+
const app = express();
|
|
6
|
+
const server = new SystemStatusServer();
|
|
7
|
+
// Serve static files from public directory
|
|
8
|
+
const publicDir = path.join(__dirname, '../../../public');
|
|
9
|
+
app.use(express.static(publicDir));
|
|
10
|
+
// Health check endpoint
|
|
11
|
+
app.get('/health', (req, res) => {
|
|
12
|
+
res.json({ status: 'ok', service: 'access-mcp-system-status' });
|
|
13
|
+
});
|
|
14
|
+
// API endpoint to list tools (for documentation)
|
|
15
|
+
app.get('/api/tools', (req, res) => {
|
|
16
|
+
res.json({
|
|
17
|
+
server: 'ACCESS-CI System Status MCP Server',
|
|
18
|
+
version: '0.1.0',
|
|
19
|
+
tools: [
|
|
20
|
+
{
|
|
21
|
+
name: 'get_current_outages',
|
|
22
|
+
description: 'Get current system outages and issues affecting ACCESS-CI resources'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'get_scheduled_maintenance',
|
|
26
|
+
description: 'Get scheduled maintenance and future outages for ACCESS-CI resources'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'get_system_announcements',
|
|
30
|
+
description: 'Get all system announcements (current and scheduled)'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'check_resource_status',
|
|
34
|
+
description: 'Check the operational status of specific ACCESS-CI resources'
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
resources: [
|
|
38
|
+
{
|
|
39
|
+
uri: 'accessci://system-status',
|
|
40
|
+
name: 'ACCESS-CI System Status',
|
|
41
|
+
description: 'Real-time status of ACCESS-CI infrastructure, outages, and maintenance'
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
// Start server
|
|
47
|
+
app.listen(port, () => {
|
|
48
|
+
console.log(`ACCESS-CI System Status web server running on port ${port}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@access-mcp/system-status",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "MCP server for ACCESS-CI System Status and Outages API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"access-mcp-system-status": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"access-ci",
|
|
22
|
+
"hpc",
|
|
23
|
+
"system-status",
|
|
24
|
+
"outages",
|
|
25
|
+
"monitoring"
|
|
26
|
+
],
|
|
27
|
+
"author": "ACCESS-CI",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/access-ci/access-mcp.git",
|
|
32
|
+
"directory": "packages/system-status"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/access-ci/access-mcp#readme",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@access-mcp/shared": "^0.1.0",
|
|
40
|
+
"express": "^4.18.0"
|
|
41
|
+
}
|
|
42
|
+
}
|