Full Command Reference
Every tool, resource, and resource template mcpd exposes, with real output captured live on an Ubuntu 24.04 VPS (host name and public addresses replaced with example ones). Mutating calls - creating and changing files, permissions, kernel parameters, services - are shown but were not run for this page; their output is what they print.
files
$ linuxctl get files list /etc --output table
NAME TYPE MODE MODE_OCTAL LINKS OWNER GROUP UID GID SIZE MODIFIED IS_DIR
adduser.conf file -rw-r--r-- 0644 1 root root 0 0 3444 2023-07-05 17:42:39 false
alternatives dir drwxr-xr-x 0755 2 root root 0 0 4096 2026-09-26 08:11:15 true
apparmor dir drwxr-xr-x 0755 2 root root 0 0 4096 2024-04-23 09:40:29 true
apparmor.d dir drwxr-xr-x 0755 9 root root 0 0 4096 2026-09-23 06:29:33 true
apport dir drwxr-xr-x 0755 3 root root 0 0 4096 2026-06-13 06:35:52 true
apt dir drwxr-xr-x 0755 9 root root 0 0 4096 2024-06-27 11:32:09 true
bash.bashrc file -rw-r--r-- 0644 1 root root 0 0 2319 2024-03-31 08:41:03 false
...
$ linuxctl get files /etc/hosts
# Generated by SolusVM
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
203.0.113.117 vps.example.com
$ linuxctl create files /tmp/note.txt --content "hello"
Successfully created and wrote to /tmp/note.txt
$ linuxctl update files /tmp/note.txt --content " world" --append true
Successfully appended to /tmp/note.txt
$ linuxctl get files find /var/log --name "*.log"
2006 /var/log/alternatives.log
0 /var/log/apport.log
12741 /var/log/apt/history.log
72030 /var/log/apt/term.log
28474543 /var/log/auth.log
1560 /var/log/disk.log
101544 /var/log/dpkg.log
86794 /var/log/kern.log
...
$ linuxctl get files filetype /etc/hosts
text/plain
$ linuxctl describe files /etc/hosts
=== stat ===
{
"name": "hosts",
"size": 126,
"mode": "-rw-r--r--",
"modified_time": "2026-06-12 12:15:48",
"is_dir": false
}
...
Note: get files list /var/log needs the explicit list keyword (unlike every other bare-reachable case in this table) because files has two candidates that could otherwise both plausibly claim a bare path (files/list, a directory listing, vs files/read, file content), and the client can't stat() a path that lives on the remote system to tell which one you mean. files/read keeps the bare form (get files /etc/hosts).
$ linuxctl chmod files /srv/app/deploy.sh u+x
/srv/app/deploy.sh: 0644 (-rw-r--r--) -> 0744 (-rwxr--r--)
$ linuxctl chmod files /srv/app go-rwx --recursive true
# ... one line per change, then:
changed 4, unchanged 0, skipped 1 symlink(s) (never followed): /srv/app/passwd-link
$ linuxctl chown files /srv/app www-data:www-data --recursive true --privileged true
# positional args fill the tool's required fields (path, then mode/owner);
# any path containing a symlink is refused - see the files/chmod and files/chown pages
disks
$ linuxctl get disks --output table
BLOCKDEVICES:
NAME KNAME MAJ:MIN RM SIZE SIZE_BYTES RO TYPE MOUNTPOINTS
sr0 sr0 11:0 true 1073741312 1073741312 true rom []
vda vda 253:0 false 16106127360 16106127360 false disk []
$ linuxctl get disks free / --output table
FREE_BYTES 7217455104
PATH /
TOTAL_BYTES 15764316160
USE_PERCENT 54.216503711633244
USED_BYTES 8546861056
$ linuxctl get disks usage /var/log
Total size of /var/log: 1993072640
$ linuxctl get disks mounts --output table
# every mounted filesystem, one row per mount
$ linuxctl get disks partitions vda --output json
[
{
"device": "vda1",
"parent_disk": "vda",
"number": 1,
"start_sector": 2048,
"size_sectors": 31455232,
"size_bytes": 16105078784
...
$ linuxctl get disks health vda
{
"json_format_version": [
1,
0
],
"smartctl": {
"version": [
7,
...
# a virtual disk has no SMART data to report - this is the expected real-hardware failure mode, not a tool bug
$ linuxctl get disks performance # all devices (many results)
$ linuxctl get disks performance vda # one device (one result) - same tool, filtered
$ linuxctl describe disks vda
[
{
"major": 253,
"minor": 0,
"device_name": "vda",
"reads_completed": 24634,
"reads_merged": 5200,
"sectors_read": 2303904,
...
processes
$ linuxctl get processes --sort_by mem --limit 3 --output table
PID USER COMM STATE PPID RSS_BYTES CMDLINE
967 root dockerd S 1 99966976 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
813 root containerd S 1 60051456 /usr/bin/containerd
274 root systemd-journal S 1 52318208 /usr/lib/systemd/systemd-journald
$ linuxctl get processes 1
PID PPID USER STAT RSS COMMAND
1 0 root S 13963264 /sbin/init
# same tool as the bare form above, filtered to one PID - not a separate endpoint; sizes in bytes (--human_readable true for 13Mi)
$ linuxctl get processes top --limit 3
top - 08:13:26 up 14:49, 0 users, load average: 0.47, 0.17, 0.06
Tasks: 111 total, 1 running, 110 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.0 us, 1.0 sy, 0.0 ni, 98.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
B Mem : 2063577088 total, 164601856 free, 289001472 used, 1609973760 buff/cache
B Swap: 536866816 total, 536592384 free, 274432 used. 1567088640 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7565 root 20 0 1940738048 43810816 4251648 S 1.0 2.1 3:20.73 amneziawg-go
...
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6939 privile+ 20 0 1366347776 12296192 7057408 R 6.0 0.6 0:00.08 mcpd
4661 root 20 0 0 0 0 R 1.0 0.0 0:00.04 kworker/u64:4-events_power_efficient
1 root 20 0 23105536 14053376 9785344 S 0.0 0.7 0:05.31 systemd
# the processes/top tool: top's header and all its columns, %CPU sampled over 1s; memory in bytes (--human_readable true for top's MiB/KiB)
$ linuxctl describe processes 1
=== status ===
Name: systemd
Umask: 0000
State: S (sleeping)
Tgid: 1
Ngid: 0
Pid: 1
PPid: 0
...
# environ is deliberately never included - describe never leaks secret-shaped data by default
linuxctl delete processes 1234 --signal SIGTERM --privileged true # mutating, not run here
system
$ linuxctl get system hostname
vps.example.com
$ linuxctl get system timezone
Time zone: Etc/UTC
Abbreviation: UTC
UTC offset: +0.0
Current local time: Sat, 26 Sep 2026 08:13:29 UTC
$ linuxctl get system locale
Source: /etc/default/locale
LANG=en_US.UTF-8
$ linuxctl get system release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
...
$ linuxctl get system uname
Sysname: Linux
Nodename: vps.example.com
Release: 6.8.0-142-generic
Version: #142-Ubuntu SMP PREEMPT_DYNAMIC Wed Sep 2 14:24:27 UTC 2026
Machine: x86_64
$ linuxctl get system os-release
OS Release Info:
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
...
$ linuxctl get system packages --output json
[
{
"name": "adduser",
"version": "3.137ubuntu1",
"architecture": "all"
},
{
"name": "adwaita-icon-theme",
...
$ linuxctl get system services --pattern "ssh*" --privileged true --output json
[
{
"active_state": "active",
"description": "OpenBSD Secure Shell server",
"load_state": "loaded",
"name": "ssh.service",
"sub_state": "running"
}
...
$ linuxctl describe system services ssh
{
"name": "ssh.service",
"description": "OpenBSD Secure Shell server",
"load_state": "loaded",
"active_state": "active",
"sub_state": "running",
"fragment_path": "/usr/lib/systemd/system/ssh.service"
}
linuxctl restart system services nginx.service --privileged true # mutating - see the warning above; not something to run against a real service casually
linuxctl start system services nginx.service --privileged true
linuxctl stop system services nginx.service --privileged true
linuxctl enable system services nginx.service --privileged true
linuxctl disable system services nginx.service --privileged true
Note: get system release/get system uname are the os://release/os://uname resources; get system os-release is the separate system/os-release tool (combined kernel+distro text) - both stay reachable since neither is purely redundant with the other.
network
$ linuxctl get network connections --output table
NETID STATE RECV_Q SEND_Q LOCAL_ADDRESS LOCAL_PORT PEER_ADDRESS PEER_PORT UID INODE
tcp LISTEN 0 0 0.0.0.0 22 0.0.0.0 0 0 6639
tcp LISTEN 0 0 127.0.0.1 45861 0.0.0.0 0 0 9339
tcp ESTAB 0 0 127.0.0.1 44620 127.0.0.1 9091 0 312697
tcp ESTAB 0 0 203.0.113.117 22 198.51.100.10 2639 0 312601
tcp SYN-RECV 0 0 203.0.113.117 22 198.51.100.11 56086 0 0
tcp ESTAB 0 0 127.0.0.1 44632 127.0.0.1 9091 0 312700
tcp LISTEN 0 0 :: 22 :: 0 0 6643
...
$ linuxctl get network ping 8.8.8.8 --port 53
{
"host": "8.8.8.8",
"port": 53,
"success": true,
"latency_ms": 11.372
}
# egress to 8.8.8.8 is blocked in this sandboxed environment - a real network fact, not a tool bug
$ linuxctl get network curl http://127.0.0.1:9091/ping
{
"status_code": 400,
"status": "400 Bad Request",
"headers": {},
"body": "Client sent an HTTP request to an HTTPS server.\n"
}
$ linuxctl get network nslookup google.com
{
"host": "google.com",
"records": [
{
"type": "CNAME",
"value": "google.com."
},
{
...
$ linuxctl get network arp --output table
IP_ADDRESS HW_TYPE FLAGS HW_ADDRESS MASK DEVICE
172.29.172.2 0x1 0x2 52:db:73:89:f9:26 * amn0
172.17.0.3 0x1 0x2 6a:14:de:e7:cd:85 * docker0
172.29.172.4 0x1 0x0 00:00:00:00:00:00 * amn0
172.17.0.4 0x1 0x2 56:ba:02:c2:62:9a * docker0
203.0.113.3 0x1 0x2 04:69:8f:d1:c0:c8 * eth0
203.0.113.1 0x1 0x2 00:00:5e:00:01:44 * eth0
$ linuxctl get network trace-path 1.1.1.1 --max_hops 3
traceroute to 1.1.1.1 (1.1.1.1), 3 hops max, 60 byte packets
1 198.51.100.13 (198.51.100.13) 0.561 ms 0.540 ms 0.550 ms
2 198.51.100.14 (198.51.100.14) 1.093 ms 1.101 ms 1.124 ms
3 198.51.100.15 (198.51.100.15) 0.659 ms 0.683 ms 0.659 ms
$ linuxctl get network interfaces --output table
$ linuxctl get network routes --output table
$ linuxctl describe network interfaces eth0
{
"addresses": [
"203.0.113.117/24",
"fe80::216:3cff:fe43:d371/64"
],
"flags": "up|broadcast|multicast|running",
"index": 2,
"mac": "00:16:3c:43:d3:71",
...
devices
$ linuxctl get devices usb --output table
BUS_ID VENDOR_ID PRODUCT_ID MANUFACTURER PRODUCT
usb1 1d6b 0001 Linux 6.8.0-142-generic uhci_hcd UHCI Host Controller
$ linuxctl get devices pci --output table
$ linuxctl get devices dmi
# fails with "DMI data not available on this system" on some VMs (including this one) - a real environmental limitation, not a bug
kernel
$ linuxctl get kernel sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
$ linuxctl update kernel sysctl net.ipv4.ip_forward 1 --privileged true
net.ipv4.ip_forward = 1
# get and update resolve to the SAME tool (kernel/system-control) - it reads
# when no value is given, writes when one is, so both verbs reach it
$ linuxctl get kernel modules --output table
logs
$ linuxctl get logs dmesg --privileged true
[WARNING: Output truncated to last 30KB]
...
[ +0.001999] systemd[1]: Listening on multipathd.socket - multipathd control socket.
[ +0.001930] systemd[1]: Listening on syslog.socket - Syslog Socket.
[ +0.001984] systemd[1]: Listening on systemd-fsckd.socket - fsck to fsckd communication Socket.
[ +0.001756] systemd[1]: Listening on systemd-initctl.socket - initctl Compatibility Named Pipe.
[ +0.001262] systemd[1]: Listening on systemd-journald-dev-log.socket - Journal Socket (/dev/log).
...
$ linuxctl get logs journal --unit cron.service --lines 3 --privileged true
Sep 26 08:05:01 vps.example.com CRON[29847]: pam_unix(cron:session): session opened for user root(uid=0) by root(uid=0)
Sep 26 08:05:01 vps.example.com CRON[29848]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)
Sep 26 08:05:01 vps.example.com CRON[29847]: pam_unix(cron:session): session closed for user root
$ linuxctl get logs journal --lines 2 --boot true --privileged true
Sep 26 08:14:38 vps.example.com mcpd[29372]: 2026-09-26T08:14:38.682Z INFO access client=127.0.0.1 user=privileged method=POST uri="/message?session_id=af8fde8f64f1ef97-91" status=202 duration_ms=0
Sep 26 08:14:38 vps.example.com mcpd[29372]: 2026-09-26T08:14:38.683Z INFO access client=127.0.0.1 user=privileged method=POST uri="/message?session_id=af8fde8f64f1ef97-91" status=202 duration_ms=0
# current boot only (journalctl -b)
$ linuxctl get logs logins --privileged true
root pts/0 198.51.100.10 Fri Sep 25 18:01 - 20:35 (02:33)
reboot system boot 6.8.0-142-generi Fri Sep 25 17:24 still running
reboot system boot 6.8.0-139-generi Sat Sep 12 16:12 - 17:23 (13+01:11)
reboot system boot 6.8.0-139-generi Sat Sep 12 16:10 - 16:12 (00:02)
root pts/0 198.51.100.11 Fri Jun 12 12:55 - 20:33 (07:38)
reboot system boot 6.8.0-36-generic Fri Jun 12 12:16 - 01:56 (91+13:40)
# last/lastb-equivalent login records
users / cpu / memory / auth
Each of these groups has exactly one tool, so no target keyword is ever needed:
$ linuxctl get users --min_uid 1000 --output table
# real OS accounts (/etc/passwd + /etc/group), UID >= 1000, never /etc/shadow
$ linuxctl get cpu --output table
# per-core topology
$ linuxctl get cpu load-average
Load Average: 0.31, 0.16, 0.06
$ linuxctl get memory usage
total used free shared buff/cache available
Mem: 2063577088 285945856 167026688 4005888 1610604544 1569984512
Swap: 536866816 274432 536592384
$ linuxctl get auth sudo-rules
Your authorized privileged tools:
{
"Tools": {
"auth/sudo-rules": {
"Allowed": true,
"Paths": null,
"Network": null,
"Sysctl": null
...
daemon
Only for users granted daemon/reload-config in mcp-sudo.yaml - see daemon/reload-config.
$ linuxctl reload daemon
Reloaded configs/daemon.yaml, configs/users.yaml and configs/mcp-sudo.yaml.
Changes:
user testuser: added
grants testuser: + disks/usage (root; paths [/var])
Editing the config files themselves is local-only: linuxctl <verb> mcpd user ... and linuxctl edit mcpd config ... - see Daemon User Administration.
Resource templates directly (bypassing the verb grammar)
The resource <uri> command still works as a direct escape hatch to any resource, including templates:
$ linuxctl resource file:///etc/hosts/stat
{
"name": "hosts",
"size": 126,
"mode": "-rw-r--r--",
"modified_time": "2026-06-12 12:15:48",
"is_dir": false
}
$ linuxctl resource file:///etc/hosts/type
text/plain
$ linuxctl resource network://interfaces/eth0
{
"addresses": [
"203.0.113.117/24",
"fe80::216:3cff:fe43:d371/64"
],
"flags": "up|broadcast|multicast|running",
"index": 2,
"mac": "00:16:3c:43:d3:71",
...
$ linuxctl resource service://ssh.service/status
{
"name": "ssh.service",
"description": "OpenBSD Secure Shell server",
"load_state": "loaded",
"active_state": "active",
"sub_state": "running",
"fragment_path": "/usr/lib/systemd/system/ssh.service"
}