Skip to main content
Glama
io.github.crunchtools/systemd

io.github.crunchtools/systemd

by crunchtools

mcp-systemd-crunchtools

MCP server for systemd unit management via D-Bus. Manages the full lifecycle of any systemd unit — not just Podman-managed containers: listing, status, lifecycle control, unit file authoring and decommissioning, journal queries, failed-unit and job triage, timers, host info, and login sessions.

Installation

# uvx (zero-install)
uvx mcp-systemd-crunchtools

# pip
pip install mcp-systemd-crunchtools

# Container
podman run \
  -v /run/dbus/system_bus_socket:/run/dbus/system_bus_socket \
  -v /etc/systemd/system:/etc/systemd/system \
  --security-opt label=type:container_runtime_t \
  quay.io/crunchtools/mcp-systemd

The D-Bus socket mount is required for every tool. The /etc/systemd/system mount is only required for unit_file_write_tool and unit_file_remove_tool — omit it to run the server read/lifecycle-only.

Do not add :z or :Z to the unit-directory mount. Both relabel the host directory recursively — z to container_file_t, Z to a container-private MCS label — and /etc/systemd/system is not a volume, it is host state whose SELinux type is a real security boundary. One such mount rewrites the type on every unit on the host, including sshd and dbus, and it does it again on every container restart. container_runtime_t can already read and write systemd_unit_file_t, which is what the relabel was buying, so the mount needs no label option at all. Fix an already-relabeled host with restorecon -RF /etc/systemd/system (-F is required because container_file_t is a customizable type, so a plain restorecon declines).

Related MCP server: mcp-podman-crunchtools

Configuration

Variable

Required

Default

Description

DBUS_SYSTEM_BUS_SOCKET

No

/run/dbus/system_bus_socket

D-Bus system bus socket path

SYSTEMD_UNIT_DIR

No

/etc/systemd/system

Directory unit_file_write/remove operate on

SYSTEMD_EXTRA_PROTECTED_UNITS

No

—

Comma-separated units added to the built-in denylist

Protected units

unit_stop, unit_restart, unit_disable, unit_mask, and unit_file_remove refuse to act on a small built-in denylist of core system units (dbus, sshd, networking, logind, journald). This cannot be bypassed — it exists so an agent can't take down the box it's running on. Add more units with SYSTEMD_EXTRA_PROTECTED_UNITS.

Claude Code Integration

claude mcp add mcp-systemd-crunchtools \
  -- uvx mcp-systemd-crunchtools

Tools (21)

Units (3)

Tool

Description

unit_list

List loaded units or installed unit files

unit_status

Curated status (active state, PID, memory, CPU)

unit_show

Full property dump (deps, exec settings, cgroup)

Lifecycle (9)

Tool

Description

unit_start

Start a unit

unit_stop

Stop a unit (protected-list guarded)

unit_restart

Restart a unit (protected-list guarded)

unit_reload

Reload a unit's config without restarting

unit_enable

Enable a unit to start on boot

unit_disable

Disable a unit from starting on boot (protected-list guarded)

unit_mask

Mask a unit (protected-list guarded)

unit_unmask

Unmask a unit

daemon_reload

Reload systemd's unit file cache

Unit files (2)

Tool

Description

unit_file_write

Write a new unit file (backs up any file it overwrites)

unit_file_remove

Decommission: stop, disable, back up, remove (protected-list guarded)

Troubleshooting (3)

Tool

Description

journal_query

Filtered journal query (unit, priority, since/until, pattern, boot)

failed_units

List units in the 'failed' state

list_jobs

List pending/stuck jobs

Timers (1)

Tool

Description

timer_list

List timers with next/last elapse

System (2)

Tool

Description

system_status

Manager state: running/degraded, failed/job counts, version

hostinfo

Hostname, kernel, OS

Sessions (1)

Tool

Description

session_list

Who's logged in right now

License

AGPL-3.0-or-later

Available Tools

21 tools
daemon_reload_toolDaemon Reload ToolA

Reload systemd's unit file cache (equivalent to systemctl daemon-reload).

Inputs: no named parameters. Returns: object

failed_units_toolFailed Units ToolA
Read-only

List units currently in the 'failed' state — the first thing to check at 2AM.

Inputs: no named parameters. Returns: object

hostinfo_toolHostinfo ToolA
Read-only

Get host identity info: hostname, kernel, OS.

Inputs: no named parameters. Returns: object

journal_query_toolJournal Query ToolB
Read-only

Query the journal — the main 2AM troubleshooting tool.

Inputs: boot, unit, lines, since, +3 more. Returns: object

list_jobs_toolList Jobs ToolA
Read-only

List pending systemd jobs — reveals stuck starts/stops/reloads.

Inputs: no named parameters. Returns: object

session_list_toolSession List ToolA
Read-only

List logged-in sessions — who's on this box right now.

Inputs: no named parameters. Returns: object

system_status_toolSystem Status ToolA
Read-only

Get overall systemd manager state: running/degraded, failed and job counts.

Inputs: no named parameters. Returns: object

timer_list_toolTimer List ToolA
Read-only

List systemd timers with their next and last elapse times.

A null next_elapse or last_trigger means systemd gave no renderable time: unset (the timer has not run yet), infinity (it will never fire again), or a value outside the renderable range. A timer whose properties could not be read at all carries an error field instead of the two times.

Inputs: no named parameters. Returns: object

unit_disable_toolUnit Disable ToolB

Disable a unit from starting on boot. Refused for units on the protected list.

Inputs: unit_name (required). Returns: object

unit_enable_toolUnit Enable ToolC

Enable a unit to start on boot.

Inputs: unit_name (required). Returns: object

unit_file_remove_toolUnit File Remove ToolA

Decommission a unit: stop, disable, optionally mask, back up and remove its file.

Refused for units on the protected list. Best-effort on stop/disable — a unit that's already stopped or was never enabled doesn't block file removal.

Inputs: unit_name (required), mask. Returns: object

unit_file_write_toolUnit File Write ToolA

Write a new unit file for setting up a service. Backs up any file it overwrites.

Requires the host's unit directory (default /etc/systemd/system) to be bind-mounted into the container. Runs daemon-reload after writing.

Inputs: content (required), unit_name (required), start, enable. Returns: object

unit_list_toolUnit List ToolC
Read-only

List systemd units.

Inputs: mode, pattern, all_units. Returns: object

unit_mask_toolUnit Mask ToolA

Mask a unit so it cannot be started even manually. Refused for protected units.

Inputs: unit_name (required). Returns: object

unit_reload_toolUnit Reload ToolA

Ask a unit to reload its configuration without restarting.

Inputs: unit_name (required). Returns: object

unit_restart_toolUnit Restart ToolB

Restart a unit. Refused for units on the protected list.

Inputs: unit_name (required). Returns: object

unit_show_toolUnit Show ToolB
Read-only

Dump the full property set for a unit (dependencies, exec settings, cgroup, etc).

Inputs: unit_name (required). Returns: object

unit_start_toolUnit Start ToolC

Start a unit.

Inputs: unit_name (required). Returns: object

unit_status_toolUnit Status ToolB
Read-only

Get curated status for a unit: active/sub/load state, PID, memory, CPU.

Inputs: unit_name (required). Returns: object

unit_stop_toolUnit Stop ToolB

Stop a unit. Refused for units on the protected list.

Inputs: unit_name (required). Returns: object

unit_unmask_toolUnit Unmask ToolA

Unmask a previously masked unit.

Inputs: unit_name (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.3/5.0

    Scored across 21 tools

    Disambiguation4/5

    Each tool maps to a distinct systemctl verb or resource, and the descriptions clearly separate near-neighbors like unit_status (curated: state/PID/memory/CPU) vs unit_show (full property dump). The main soft spot is unit_file_remove_tool, which internally does stop/disable/mask and therefore overlaps with unit_stop/unit_disable/unit_mask, though it is framed as a composite decommission operation.

    Naming Consistency4/5

    The dominant pattern is noun_noun_verb_tool (unit_start_tool, timer_list_tool, journal_query_tool), applied consistently across the unit lifecycle. A handful of outliers (hostinfo_tool, failed_units_tool, list_jobs_tool) flip to verb-first or drop the prefix, but they remain readable and unambiguous.

    Tool Count4/5

    21 tools is on the heavy side, but systemd genuinely exposes this many orthogonal operations (unit lifecycle, timers, journal, jobs, sessions, host identity). Every tool maps to a real systemctl/journalctl capability rather than being filler.

    Completeness4/5

    Full unit lifecycle is covered: write/remove, start/stop/restart/reload, enable/disable, mask/unmask, plus diagnostics (status, show, failed units, jobs, timers, journal, daemon-reload). Minor gaps exist — no way to read a unit file's raw contents (unit cat), no journal follow/live tail, and no drop-in override editing — but agents can work around these via unit_show and journal_query.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      Not graded
      maintenance
      Provides AI assistants with safe, read-only access to Linux systemd services, including status monitoring, log querying, and dependency analysis, with optional granular permissions for service management actions.
      2
      -
    • A
      license
      A
      quality
      D
      maintenance
      An MCP server that reports on and manages systemd services using systemctl and journalctl, enabling service listing, status, logs, and control operations.
      5
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Controls a Linux host through structured interfaces like systemd, journald, and D-Bus for service management, journal queries, power operations, and more, with safety guards to prevent accidental damage.
      -