Read-only access to per-process Linux state via /proc. Sister to cgroup-mcp: process-mcp answers 'which processes,' cgroup-mcp answers 'which cgroups.' Tools return structured JSON; the agent does prose. Each call is a point-in-time snapshot.
Four well-defined tools with comprehensive descriptions (194 - 392 chars, well above baseline 194 avg). All tools have explicit input schemas with typed parameters and descriptions. Tool names follow verb_noun convention (pids_in_cgroup, top_processes, process_info, process_tree). Descriptions explain WHAT, WHEN, and output shape. Security-conscious: cmdline redaction is built-in with clear opt-out. Schemas are complete with required fields marked. Gaps: no tool annotations (readOnlyHint/destructiveHint/idempotentHint), no pagination support for large result sets, error handling is generic (internal_error with format string), and no recovery guidance in error messages.
Returns the processes inside a given cgroup. Takes a cgroup_path in normalized form (relative to /sys/fs/cgroup, no leading slash, empty string for the root cgroup) and returns each process with comm, cmdline, state, ppid, and rss_bytes. Use this to drill into a cgroup identified via cgroup-mcp's tools. The cgroup_path from any cgroup-mcp output can be passed here verbatim; both servers use the same identifier convention. Results are sorted descending by rss_bytes, with null values (kernel threads with no userspace memory map) last. cmdline args matching *key*=*, *token*=*, *password*=*, *secret*=* are redacted by default; set redact_args=false to receive them verbatim. The `skipped` field counts PIDs encountered in /proc that could not be fully read (transient process death, permission denied). Non-zero means the snapshot may be incomplete.
Returns the full per-PID drill-down bundle for one process. Includes the same identifier fields as pids_in_cgroup (pid, comm, cmdline, state, ppid, rss_bytes, cgroup_path) plus uid, num_threads, fd_count, a smaps_rollup memory breakdown (Rss/Pss/Shared/Private/Anon/Swap), and IO counters. Use this after identifying a PID of interest via pids_in_cgroup or top_processes. The `memory.pss_bytes` field is the fairest single number for 'this process's memory cost' when pages are shared with other processes (browser tabs, JVM workers, etc.). Permission-gated fields are nullable when the kernel rejects the read: `fd_count` and `io` typically require ptrace capability or matching uid; `memory` is null for kernel threads. Cmdline args matching *key=*, *token=*, *password=*, *secret=* are redacted by default; pass `redact_args=false` to receive them verbatim. Errors if the PID does not exist.
Returns a parent/child process forest. Two mutually exclusive modes: 1. Pass `root_pid` to root the tree at one PID. The result is a single-element forest with that PID at top, every descendant nested underneath. Useful for unpacking Chrome's main + renderer + GPU process model, systemd-managed supervisor trees, language runtimes that fork many workers, etc. 2. Pass `cgroup_path` to get the forest of processes inside a cgroup, organized by in-cgroup parent/child relationships. A PID whose parent is outside the cgroup becomes a forest root. Useful for understanding the structure of a heavy cgroup identified via cgroup-mcp. Each node carries the same identifier fields as other tools (pid, comm, cmdline, state, ppid, rss_bytes, cgroup_path) plus a `children` array. Children are sorted by rss_bytes desc with nulls last. Cmdline redaction and the `skipped` count work the same as the other tools.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All four tools are read-only but lack explicit annotation in schema, forcing LLMs to infer safety from descriptions alone.
Error handling is generic (McpError::internal_error with format string). No recovery guidance, error classification, or actionable next steps for LLMs. E.g., 'PID does not exist' should suggest 'Call top_processes() to find valid PIDs.'
top_processes lacks pagination. Default n=10 is reasonable, but no limit cap or guidance on max result size. If n is unbounded, large requests could exhaust context or timeout.
process_tree has mutually exclusive parameters (root_pid vs cgroup_path) but no explicit validation or error message if both/neither are provided. LLMs may pass both, causing ambiguous behavior.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Returns the top N processes ranked by resident memory (rss_bytes), descending. Use this to answer 'what's using the most memory on this box.' Pass `cgroup_prefix` to scope the search to a cgroup subtree. The match is path-aware: `system.slice` matches `system.slice` itself and any descendant (e.g. `system.slice/nginx.service`), but NOT siblings like `system.slice2`. Take cgroup paths verbatim from any cgroup-mcp tool output. Results are returned with the same shape as `pids_in_cgroup`: pid, comm, cmdline (redacted by default; pass `redact_args=false` for verbatim), state, ppid, rss_bytes, and cgroup_path. Kernel threads (null rss_bytes) sort last. Default n is 10. CPU-based ranking is planned but not yet implemented; current sort is memory only.
Output schemas are not explicitly documented in code. Descriptions mention fields (pid, comm, cmdline, state, ppid, rss_bytes, cgroup_path, memory, io) but no formal JSON Schema for responses. LLMs cannot validate or plan downstream calls with certainty.