# How Desktop Commander MCP Process Management Works: Listing and Killing OS Processes

> Explore how Desktop Commander MCP lists and kills OS processes using its schema-validated MCP protocol layer. Master process management with these powerful tools.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-07-28

---

**Desktop Commander MCP exposes two tools—`list_processes` and `kill_process`—that enable enumeration of running system processes and termination by PID through a schema-validated MCP protocol layer.**

The `wonderwhy-er/DesktopCommanderMCP` repository implements process management functionality as part of its terminal skill set, allowing AI clients to inspect and control operating system processes via the Model Context Protocol (MCP). This capability relies on Node.js native APIs and platform-specific shell commands wrapped in type-safe handlers.

## Architecture and Tool Registration

The MCP server registers both tools in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) (lines 1095–1468) within the central tool table. The registration maps tool names to their argument schemas and handler functions from the `@modelcontextprotocol/sdk`.

- **`list_processes`** accepts no arguments, defined by `ListProcessesArgsSchema` as an empty Zod object
- **`kill_process`** requires a numeric `pid` parameter, enforced by `KillProcessArgsSchema`

When a client invokes a tool, the server's dispatcher routes the request to the appropriate handler in [`src/handlers/process-handlers.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/handlers/process-handlers.ts). This thin wrapper layer validates inputs before delegating to the core implementation:

```typescript
// src/handlers/process-handlers.ts
export async function handleListProcesses(): Promise<ServerResult> {
    return listProcesses();
}

export async function handleKillProcess(args: unknown): Promise<ServerResult> {
    const parsed = KillProcessArgsSchema.parse(args);
    return killProcess(parsed);
}

```

## Listing Processes with Platform-Specific Commands

The `listProcesses()` function in [`src/tools/process.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/process.ts) executes OS-specific commands to retrieve process information. It uses a promisified `exec` to run `tasklist` on Windows and `ps aux` on macOS/Linux, then parses the text output into structured data.

### Command Execution and Parsing

The implementation detects the platform via `os.platform()`, executes the appropriate command, and transforms the raw stdout into an array of `ProcessInfo` objects:

```typescript
// src/tools/process.ts
export async function listProcesses(): Promise<ServerResult> {
    const command = os.platform() === 'win32' ? 'tasklist' : 'ps aux';
    const { stdout } = await execAsync(command);
    const processes = stdout.split('\n')
      .slice(1)
      .filter(Boolean)
      .map(line => {
          const parts = line.split(/\s+/);
          return {
              pid: parseInt(parts[1]),
              command: parts[parts.length - 1],
              cpu: parts[2],
              memory: parts[3],
          } as ProcessInfo;
      });
    return { content: [{ type: "text", text: processes.map(p =>
            `PID: ${p.pid}, Command: ${p.command}, CPU: ${p.cpu}, Memory: ${p.memory}`
          ).join('\n') }] };
}

```

The function strips header lines, splits entries by whitespace, and extracts the PID, command name, CPU usage, and memory consumption. Results return as plain-text content within a `ServerResult` payload for direct display to users.

## Terminating Processes with Node.js Native APIs

The `killProcess()` function handles process termination through Node's built-in `process.kill()` method. Before execution, it validates arguments using `KillProcessArgsSchema` defined in [`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts) (lines 51–53), which requires a numeric `pid` field.

### Validation and Error Handling

The handler uses safe parsing to distinguish between validation failures and runtime execution errors, returning appropriate `isError` flags and descriptive messages:

```typescript
// src/tools/process.ts
export async function killProcess(args: unknown): Promise<ServerResult> {
    const parsed = KillProcessArgsSchema.safeParse(args);
    if (!parsed.success) {
        return { content: [{ type: "text",
            text: `Error: Invalid arguments for kill_process: ${parsed.error}` }],
            isError: true };
    }
    try {
        process.kill(parsed.data.pid);
        return { content: [{ type: "text",
            text: `Successfully terminated process ${parsed.data.pid}` }] };
    } catch (error) {
        return { content: [{ type: "text",
            text: `Error: Failed to kill process: ${error instanceof Error ? error.message : String(error)}` }],
            isError: true };
    }
}

```

If the PID does not exist or the server lacks permissions, the catch block returns the system error message (e.g., `EPERM: operation not permitted`) wrapped in the MCP error format.

## Schema Definitions and Type Safety

Argument schemas in [`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts) enforce type safety at runtime using Zod:

- `ListProcessesArgsSchema = z.object({})` accepts an empty object
- `KillProcessArgsSchema = z.object({ pid: z.number() })` requires a numeric process identifier

These schemas prevent malformed requests from reaching the OS-level execution layer, ensuring that `kill_process` only receives valid PIDs before invoking system calls.

## Example Request Flow

A client interaction flows from the LLM through the MCP protocol to the OS and back:

**Listing all processes:**

```json
{
  "toolName": "list_processes",
  "args": {}
}

```

**Sample response:**

```

PID: 1245, Command: node, CPU: 0.0, Memory: 42.1
PID: 2310, Command: python3, CPU: 1.2, Memory: 150.3

```

**Killing a specific process:**

```json
{
  "toolName": "kill_process",
  "args": { "pid": 2310 }
}

```

**Success response:**
`Successfully terminated process 2310`

**Permission denied response:**
`Error: Failed to kill process: EPERM: operation not permitted, kill 2310`

## Summary

- **Tool Registration**: [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) registers `list_processes` and `kill_process` with the MCP SDK, binding them to schemas and handlers in [`src/handlers/process-handlers.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/handlers/process-handlers.ts).
- **Process Enumeration**: [`src/tools/process.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/process.ts) executes platform-specific commands (`tasklist` or `ps aux`) and parses output into readable text format.
- **Process Termination**: Uses Node.js `process.kill()` with Zod validation via `KillProcessArgsSchema` to safely terminate processes by PID.
- **Error Handling**: Distinguishes between validation errors (malformed arguments) and runtime errors (permissions, missing PIDs) using the `isError` flag in `ServerResult` objects.
- **Type Safety**: Zod schemas in [`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts) enforce strict typing before OS-level execution.

## Frequently Asked Questions

### What permissions are required to kill processes with Desktop Commander MCP?

The MCP server process must run with sufficient privileges to terminate the target process. Killing system processes or processes owned by other users typically requires administrator/root access; otherwise, the `kill_process` tool returns an `EPERM` (permission denied) error.

### How does the process list differ between Windows and Unix systems?

On Windows, the tool executes `tasklist` and parses its columnar output. On macOS and Linux, it runs `ps aux`. While both return PID, command name, CPU, and memory usage, the exact formatting and available metrics differ slightly based on the underlying OS command output structure.

### Can I filter processes by name or CPU usage?

The current implementation in [`src/tools/process.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/process.ts) returns the complete process list without server-side filtering. Clients receive the full text output and must perform any filtering or searching on the client side after receiving the response from the `list_processes` tool.

### What happens if I attempt to kill a non-existent PID?

If the specified PID does not exist, Node's `process.kill()` throws an error that the handler catches and returns as a `ServerResult` with `isError: true`. The error message indicates that the process was not found, allowing the client to handle the failure gracefully.