/* Copyright (C) 2026 Moko Consulting * SPDX-License-Identifier: GPL-3.0-or-later * * Tool: windows_process_list — List running processes (#2) */ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { runPowerShell } from '../shell.js'; interface ProcessInfo { PID: number; Name: string; CPU: number; MemoryMB: number; WindowTitle: string; Path: string; } export function registerProcessTools(server: McpServer): void { server.tool( 'windows_process_list', 'List running processes with PID, name, CPU, memory, window title, and path.', { filter: z.string().optional().describe('Filter by process name (substring match)'), sort: z.enum(['cpu', 'memory', 'name']).default('memory').describe('Sort order'), limit: z.number().default(50).describe('Max results to return'), }, async ({ filter, sort, limit }) => { const filterClause = filter ? `| Where-Object { $_.Name -like '*${filter.replace(/'/g, "''")}*' }` : ''; const sortClause = sort === 'cpu' ? '| Sort-Object CPU -Descending' : sort === 'name' ? '| Sort-Object Name' : '| Sort-Object WorkingSet64 -Descending'; const ps = ` Get-Process ${filterClause} ${sortClause} | Select-Object -First ${limit} | ForEach-Object { [PSCustomObject]@{ PID = $_.Id Name = $_.ProcessName CPU = [math]::Round($_.CPU, 1) MemoryMB = [math]::Round($_.WorkingSet64 / 1MB, 1) WindowTitle = $_.MainWindowTitle Path = $_.Path } } | ConvertTo-Json -Depth 3 -Compress`; const result = await runPowerShell(ps); if (result.exitCode !== 0) { return { content: [{ type: 'text', text: `Error: ${result.stderr}` }], isError: true }; } let processes: ProcessInfo[] = []; if (result.stdout) { const parsed = JSON.parse(result.stdout); processes = Array.isArray(parsed) ? parsed : [parsed]; } const lines = processes.map(p => `${String(p.PID).padStart(7)} ${p.Name.padEnd(25).slice(0, 25)} ${String(p.CPU ?? 0).padStart(8)}s ${String(p.MemoryMB).padStart(8)} MB ${p.WindowTitle || ''}`, ); const header = `${'PID'.padStart(7)} ${'Name'.padEnd(25)} ${'CPU'.padStart(8)} ${'Memory'.padStart(8)} Window Title`; const separator = '-'.repeat(90); return { content: [{ type: 'text', text: `${header}\n${separator}\n${lines.join('\n')}\n\n${processes.length} processes`, }], }; }, ); }