system-health-mcp 1.0.0 → 1.0.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/README.md +63 -7
- package/out/index.d.ts +2 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +201 -0
- package/out/index.js.map +1 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -15,23 +15,79 @@ A Model Context Protocol (MCP) server that provides real-time system health moni
|
|
|
15
15
|
- TypeScript
|
|
16
16
|
- npm or yarn
|
|
17
17
|
|
|
18
|
-
## Installation
|
|
18
|
+
## Installation (from npm)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
You can install and run this MCP server directly from npm:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
npm install -g system-health-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then run the server:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
system-health-mcp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or, if you want to use it locally in a project:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install system-health-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then run:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx system-health-mcp
|
|
25
42
|
```
|
|
26
43
|
|
|
27
|
-
|
|
44
|
+
You do **not** need to clone the repository if installing from npm.
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation (from source)
|
|
49
|
+
|
|
50
|
+
git clone <repository-url>
|
|
51
|
+
cd system-health-mcp
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/jvdub/system-health-mcp.git
|
|
55
|
+
cd system-health-mcp
|
|
56
|
+
npm install
|
|
57
|
+
npx tsc
|
|
58
|
+
```
|
|
30
59
|
|
|
31
60
|
## Configuration
|
|
32
61
|
|
|
33
62
|
To use this MCP server with an MCP-compatible client (like Claude Desktop), add the following configuration to your client's MCP settings file:
|
|
34
63
|
|
|
64
|
+
### If installed globally from npm:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"system-health": {
|
|
70
|
+
"command": "system-health-mcp"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### If installed locally in a project:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"system-health": {
|
|
82
|
+
"command": "npx",
|
|
83
|
+
"args": ["system-health-mcp"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### If running from source:
|
|
90
|
+
|
|
35
91
|
```json
|
|
36
92
|
{
|
|
37
93
|
"mcpServers": {
|
|
@@ -43,7 +99,7 @@ To use this MCP server with an MCP-compatible client (like Claude Desktop), add
|
|
|
43
99
|
}
|
|
44
100
|
```
|
|
45
101
|
|
|
46
|
-
**Important**:
|
|
102
|
+
**Important**: For the source install, replace `/path/to/your/project/index.js` with the absolute path to the built `index.js` file in your cloned repository.
|
|
47
103
|
|
|
48
104
|
### Example Configuration Locations
|
|
49
105
|
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":""}
|
package/out/index.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import si from 'systeminformation';
|
|
5
|
+
import psList from 'ps-list';
|
|
6
|
+
import pidusage from 'pidusage';
|
|
7
|
+
import getFolderSize from 'get-folder-size';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
const server = new Server({ name: "system-health-monitor", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
11
|
+
// Standalone handler for ListToolsRequest
|
|
12
|
+
async function handleListToolsRequest() {
|
|
13
|
+
return {
|
|
14
|
+
tools: [
|
|
15
|
+
{
|
|
16
|
+
name: "get_system_stats",
|
|
17
|
+
description: "Get real-time CPU load, memory usage, and battery status",
|
|
18
|
+
inputSchema: { type: "object", properties: {} }
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "get_hardware_details",
|
|
22
|
+
description: "Get detailed hardware info like GPU, Disk health, and Network config",
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: {
|
|
26
|
+
category: {
|
|
27
|
+
type: "string",
|
|
28
|
+
enum: ["graphics", "network", "disks", "docker"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "get_resource_hogs",
|
|
35
|
+
description: "Get top N resource hog processes by CPU usage",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
topN: { type: "number", default: 5 }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "get_largest_files_folders",
|
|
45
|
+
description: "Get top N largest files/folders in a directory",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
scanPath: { type: "string", default: "/" },
|
|
50
|
+
topN: { type: "number", default: 5 }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
server.setRequestHandler(ListToolsRequestSchema, handleListToolsRequest);
|
|
58
|
+
// 2. Implement the logic
|
|
59
|
+
// Standalone handler for CallToolRequest
|
|
60
|
+
async function handleCallToolRequest(request) {
|
|
61
|
+
// Get top N resource hog processes
|
|
62
|
+
if (request.params.name === "get_resource_hogs") {
|
|
63
|
+
const { topN = 5 } = request.params.arguments || {};
|
|
64
|
+
const processes = await psList();
|
|
65
|
+
const usages = await Promise.all(processes.map(async (proc) => {
|
|
66
|
+
try {
|
|
67
|
+
const stats = await pidusage(proc.pid);
|
|
68
|
+
return {
|
|
69
|
+
...proc,
|
|
70
|
+
cpu: stats.cpu,
|
|
71
|
+
memory: stats.memory,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
const validUsages = usages.filter((u) => !!u);
|
|
79
|
+
validUsages.sort((a, b) => ((b && b.cpu) || 0) - ((a && a.cpu) || 0));
|
|
80
|
+
return {
|
|
81
|
+
content: [{ type: "text", text: JSON.stringify(validUsages.slice(0, Number(topN)), null, 2) }]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Get top N largest files/folders in a directory
|
|
85
|
+
if (request.params.name === "get_largest_files_folders") {
|
|
86
|
+
const { scanPath = "/", topN = 5 } = request.params.arguments || {};
|
|
87
|
+
const items = [];
|
|
88
|
+
let dirents;
|
|
89
|
+
try {
|
|
90
|
+
dirents = fs.readdirSync(scanPath, { withFileTypes: true });
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text", text: `Error reading directory: ${err}` }]
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
for (const dirent of dirents) {
|
|
98
|
+
const fullPath = path.join(scanPath, dirent.name);
|
|
99
|
+
try {
|
|
100
|
+
if (dirent.isDirectory()) {
|
|
101
|
+
const size = await getFolderSize(fullPath).then((result) => result.size);
|
|
102
|
+
items.push({ name: fullPath, size, isDir: true });
|
|
103
|
+
}
|
|
104
|
+
else if (dirent.isFile()) {
|
|
105
|
+
const stats = fs.statSync(fullPath);
|
|
106
|
+
items.push({ name: fullPath, size: stats.size, isDir: false });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Ignore errors
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
items.sort((a, b) => b.size - a.size);
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: JSON.stringify(items.slice(0, Number(topN)), null, 2) }]
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (request.params.name === "get_system_stats") {
|
|
119
|
+
const [cpu, mem, battery] = await Promise.all([
|
|
120
|
+
si.currentLoad(),
|
|
121
|
+
si.mem(),
|
|
122
|
+
si.battery()
|
|
123
|
+
]);
|
|
124
|
+
const stats = {
|
|
125
|
+
cpuLoadPercentage: cpu.currentLoad.toFixed(2),
|
|
126
|
+
memoryUsedGB: (mem.active / 1024 / 1024 / 1024).toFixed(2),
|
|
127
|
+
memoryTotalGB: (mem.total / 1024 / 1024 / 1024).toFixed(2),
|
|
128
|
+
batteryLevel: battery.hasBattery ? `${battery.percent}%` : "No battery",
|
|
129
|
+
isCharging: battery.isCharging
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
content: [{ type: "text", text: JSON.stringify(stats, null, 2) }]
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (request.params.name === "get_hardware_details") {
|
|
136
|
+
const { category } = request.params.arguments;
|
|
137
|
+
let data;
|
|
138
|
+
switch (category) {
|
|
139
|
+
case "graphics":
|
|
140
|
+
data = { graphics: await si.graphics() };
|
|
141
|
+
break;
|
|
142
|
+
case "network":
|
|
143
|
+
data = await si.networkInterfaces();
|
|
144
|
+
break;
|
|
145
|
+
case "disks":
|
|
146
|
+
data = await si.fsSize();
|
|
147
|
+
break;
|
|
148
|
+
case "docker":
|
|
149
|
+
data = await si.dockerContainers();
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
data = { error: "Invalid category" };
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
throw new Error("Tool not found");
|
|
159
|
+
}
|
|
160
|
+
server.setRequestHandler(CallToolRequestSchema, handleCallToolRequest);
|
|
161
|
+
// 3. Connect the transport
|
|
162
|
+
// Single-request mode for testability
|
|
163
|
+
if (process.env.TEST_MODE === '1') {
|
|
164
|
+
process.stdin.setEncoding('utf8');
|
|
165
|
+
let input = '';
|
|
166
|
+
process.stdin.on('data', (chunk) => {
|
|
167
|
+
input += chunk;
|
|
168
|
+
if (input.includes('\n')) {
|
|
169
|
+
process.stdin.pause();
|
|
170
|
+
handleInput(input.trim());
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
async function handleInput(line) {
|
|
174
|
+
try {
|
|
175
|
+
const req = JSON.parse(line);
|
|
176
|
+
let result;
|
|
177
|
+
if (req.schema === 'ListToolsRequest') {
|
|
178
|
+
result = await handleListToolsRequest();
|
|
179
|
+
}
|
|
180
|
+
else if (req.schema === 'CallToolRequest') {
|
|
181
|
+
result = await handleCallToolRequest(req);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
throw new Error('Unknown schema');
|
|
185
|
+
}
|
|
186
|
+
process.stdout.write(JSON.stringify(result) + '\n');
|
|
187
|
+
process.exit(0);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
process.stderr.write((err && err.message ? err.message : String(err)) + '\n');
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
(async () => {
|
|
197
|
+
const transport = new StdioServerTransport();
|
|
198
|
+
await server.connect(transport);
|
|
199
|
+
})();
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=index.js.map
|
package/out/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|