index.js•7.74 kB
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import * as si from "systeminformation";
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
// Define our tools
const TOOLS = [
{
name: "get_process_count",
description: "Get the total number of running processes",
inputSchema: {
type: "object",
properties: {},
required: [],
},
},
{
name: "get_top_cpu_processes",
description: "Get the top N processes consuming the most CPU",
inputSchema: {
type: "object",
properties: {
limit: {
type: "number",
description: "Number of top processes to return (default: 5)",
},
},
required: [],
},
},
{
name: "get_top_memory_processes",
description: "Get the top N processes consuming the most memory",
inputSchema: {
type: "object",
properties: {
limit: {
type: "number",
description: "Number of top processes to return (default: 5)",
},
},
required: [],
},
},
{
name: "get_process_instances",
description: "Get processes grouped by name with instance counts",
inputSchema: {
type: "object",
properties: {
minInstances: {
type: "number",
description: "Only show processes with at least this many instances (default: 2)",
},
},
required: [],
},
},
{
name: "find_process_by_name",
description: "Find all processes matching a name pattern",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "Process name or pattern to search for",
},
},
required: ["name"],
},
},
];
// Create the MCP server
const server = new Server({
name: "mcp-process-monitor",
version: "1.0.0",
}, {
capabilities: {
tools: {},
},
});
// Handle tool listing
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: TOOLS };
});
// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case "get_process_count": {
const processes = await si.processes();
return {
content: [
{
type: "text",
text: `Total running processes: ${processes.all}`,
},
],
};
}
case "get_top_cpu_processes": {
const limit = args?.limit || 5;
const processes = await si.processes();
const topCpu = processes.list
.sort((a, b) => b.cpu - a.cpu)
.slice(0, limit)
.map(p => ({
name: p.name,
pid: p.pid,
cpu: `${p.cpu.toFixed(1)}%`,
memory: `${p.memRss ? (p.memRss / 1024 / 1024).toFixed(1) : "0"} MB`,
}))
.filter(p => p.pid !== 0);
return {
content: [
{
type: "text",
text: `Top ${limit} CPU consuming processes:\n${JSON.stringify(topCpu, null, 2)}`,
},
],
};
}
case "get_top_memory_processes": {
const limit = args?.limit || 5;
const processes = await si.processes();
const topMem = processes.list
.sort((a, b) => (b.memRss || 0) - (a.memRss || 0))
.slice(0, limit)
.map(p => ({
name: p.name,
pid: p.pid,
memory: `${p.memRss ? (p.memRss / 1024 / 1024).toFixed(1) : "0"} MB`,
cpu: `${p.cpu.toFixed(1)}%`,
}))
.filter(p => p.pid !== 0);
return {
content: [
{
type: "text",
text: `Top ${limit} memory consuming processes:\n${JSON.stringify(topMem, null, 2)}`,
},
],
};
}
case "get_process_instances": {
const minInstances = args?.minInstances || 2;
const processes = await si.processes();
const grouped = processes.list.reduce((acc, p) => {
acc[p.name] = (acc[p.name] || 0) + 1;
return acc;
}, {});
const filtered = Object.entries(grouped)
.filter(([_, count]) => count >= minInstances)
.sort((a, b) => b[1] - a[1])
.map(([name, count]) => ({ process: name, instances: count }));
return {
content: [
{
type: "text",
text: `Processes with ${minInstances}+ instances:\n${JSON.stringify(filtered, null, 2)}`,
},
],
};
}
case "find_process_by_name": {
const searchName = (args?.name || "").toLowerCase();
const processes = await si.processes();
const matched = processes.list
.filter(p => p.name.toLowerCase().includes(searchName))
.map(p => ({
name: p.name,
pid: p.pid,
cpu: `${p.cpu.toFixed(1)}%`,
memory: `${p.memRss ? (p.memRss / 1024 / 1024).toFixed(1) : "0"} MB`,
command: p.command,
}))
.filter(p => p.pid !== 0);
return {
content: [
{
type: "text",
text: matched.length > 0
? `Found ${matched.length} processes matching "${searchName}":\n${JSON.stringify(matched, null, 2)}`
: `No processes found matching "${searchName}"`,
},
],
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
}
catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Process Monitor Server running on stdio");
}
main().catch(error => {
console.error("Fatal error:", error);
process.exit(1);
});