journalmcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@journalmcpwhy did cron.service fail? show its status and recent journal entries"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
journalmcp
A read-only view of systemd and the journal, for people and for models: eight
queries (units, failed units, timers, one unit's status, its unit file, the
journal, the boot list and a summary) served by one Python core through two
thin fronts, a command-line tool and an MCP server over stdio. It runs
systemctl and journalctl as the user who starts it, never through a shell,
caps what it returns, and redacts secrets from journal text before anything
leaves the process.
Why this exists
"Why did that service fail?" is a question a model can help with, but only if
it can see the unit, its journal and its unit file. Handing it a shell for that
hands it systemctl stop too. journalmcp gives a model the reading half and
nothing else: every command it can build starts with a read verb from one fixed
list, and a test builds every one of them to check.
The same queries are a CLI, because the code a model calls should be code you can run yourself and get the same answer. Both fronts call the same core functions and emit the same JSON; parity tests compare them on the same recordings.
Related MCP server: claude-systemd-mcp
What it does
CLI subcommand | MCP tool | What it reads |
|
| the units a manager has loaded, filtered by |
|
| the units in the failed state |
|
| the timers, what each activates, and when it last ran and next runs |
|
| one unit's load, active and sub state, description, result and main PID, plus its last journal entries |
|
| the unit file as |
|
| journal entries, filtered by unit, time, priority and a message pattern |
|
| the recorded boots, current boot first |
|
| the manager state, failed-unit and timer counts for both managers, and the boot time |
The MCP front also offers one prompt, triage_failed_unit, which asks the
model to call unit_status, journal and unit_file for one unit, in that
order, and report the likely cause.
Scope.
scopeisuser(yoursystemd --usermanager; the CLI's default) orsystem. Nothing else is accepted.bootsandsummarytake no scope.--json. The CLI prints a table by default;--jsonprints the result object, which is the same object the MCP tool returns as structured content.Caps.
lines(--lines) asks for 1 to 1000 entries (default 100 forjournal, 20 forstatus). Every string value is capped at 4096 bytes and every result at 65536. A cut is never silent: the result carriestruncated: true, a cut value ends in[TRUNCATED], and the CLI's text ends with a[TRUNCATED]line.Redaction. On by default, over every string taken from the journal, unit files and unit properties: PEM blocks, bearer credentials,
password=andsecret=pairs, and tokens each become a visible[REDACTED:<class>]marker. IP addresses are kept, because a firewall log is useless without them.JOURNALMCP_REDACT=offturns it off;JOURNALMCP_REDACT_PATTERNS=<file>adds your own regular expressions, one per line. Any other value of the switch is an error, so a typo cannot pass as either setting. Redaction is pattern matching:docs/security-model.mdlists the credential shapes it does not catch in this version.
./journalmcp failed --scope system
./journalmcp status --unit cron.service --scope system --lines 5
./journalmcp journal --scope system --priority err --since=-1h --jsonHow it differs from systemd-mcp
openSUSE/systemd-mcp is the closest
existing project, and it does more. Going by its README: it is built with
go build and "directly connects to systemd via its C API and so doesn't need
systemctl to run", where journalmcp is Python that runs systemctl and
journalctl as argv lists. It can change units: its tool list includes
change_unit_state ("start, stop, restart, reload, enable, disable"), and
writes "trigger a polkit request"; journalmcp has no write operation at all.
It installs with sudo make install, which places a gatekeeper in
/usr/sbin with its own systemd units and polkit policy so it can read the
whole journal; journalmcp runs from a checkout and reads only what the invoking
user can already read. It offers an HTTP transport with OAuth2 alongside stdio;
journalmcp speaks stdio only. Its tests include one "which tests authentication
with oauth2 using a keycloak container"; journalmcp's suite replays recorded
command output and touches neither systemd nor the network.
Installing
Needs Linux with systemd, Python 3.12 or newer, git and
uv.
git clone https://github.com/hilliersmmain/journalmcp.git
cd journalmcp
uv sync --frozen
./journalmcp --versionuv sync --frozen builds .venv from uv.lock exactly; nothing is resolved
afresh. The eight query subcommands and --version use only the standard
library and run under the system python3 as well. ./journalmcp serve, the
MCP server, needs the locked environment: under the system interpreter it
prints one line saying so and exits 1.
Claude Code. The server is started through a small wrapper,
tools/journalmcp-mcp, which runs it from the checkout's .venv under
env -i with only HOME, PATH=/usr/bin:/bin, XDG_RUNTIME_DIR and the two
redaction variables passed through. Copy it to a directory on your PATH,
point it at your checkout, and register it:
cp tools/journalmcp-mcp ~/.local/bin/
claude mcp add journalmcp -- ~/.local/bin/journalmcp-mcpThe wrapper looks for the checkout at $HOME/Projects/journalmcp; if yours is
elsewhere, edit the REPO= line in the copy, or set JOURNALMCP_REPO in the
server's environment. bash tools/smoke-test-mcp ~/.local/bin/journalmcp-mcp
sends one initialize request and prints PASS when the server answers
cleanly.
Other MCP clients. docs/examples/mcp.json is a server entry to copy into
your client's configuration. YOUR-USER in its path stands for your own home
directory (a JSON file can carry no comment to say so):
{
"mcpServers": {
"journalmcp": {
"command": "/home/YOUR-USER/.local/bin/journalmcp-mcp"
}
}
}The skill. skill/SKILL.md teaches Claude Code to use the CLI directly.
To use it, link it into your own skills directory, for example
ln -s "$PWD/skill" ~/.claude/skills/journalmcp.
Security model
docs/security-model.md has one section per item,
each naming the code, the test and the threat it answers:
Read-only. Every argv starts with a read verb from one fixed list.
argv only. No shell, no
shell=True, no command built by joining strings.Unit names are validated against systemd's unit-name rules before use.
Journal fields are allowlisted; hostname, machine id and command line are dropped.
Output is capped by lines and bytes, with a visible truncation marker.
Secrets are redacted from message text; configurable; IP addresses kept.
Every subprocess has a timeout (10 seconds).
No network calls; only the MCP front imports anything outside the standard library.
No privilege escalation: no
sudo, nopkexec, no setuid helper.The MCP wiring is a pinned
env -iwrapper, never a launch that resolves packages at start-up.
What journalmcp claims about itself, and the test that proves each claim:
Read-only by construction:
test_every_argv_starts_with_a_read_verb(tests/test_core.py) builds the argv of all eight operations and checks the verb;pytest -k read_verb.One core serves a CLI and an MCP server:
test_parity_cli_json_equals_mcp_structured_content(tests/test_parity.py) runs both fronts on the same recordings and compares the data;pytest -k parity.It redacts secrets from journal text:
test_redact_the_synthetic_secrets_recording(tests/test_journal.py) runs a recording of invented secrets through the core and finds none of them in the result;pytest -k redact.It ships a documented security model:
docs/security-model.md, with the ten numbered sections above, each naming its tests.Its tests run against recorded fixtures:
test_the_guard_stops_an_unmarked_test_at_the_real_runner(tests/test_runner.py) proves that a test reaching the real runner fails unless it is markedlive; the recordings are intests/fixtures/.
Tests
uv run --frozen pytest --collect-only -q | grep -c "::"prints 599 on a fresh clone. uv run --frozen pytest -q runs them; six skip
in a fresh clone, because they check the maintainer's private scrub inputs. The
tests replay command output recorded from a real machine and scrubbed of its
hostname, user names, addresses, machine id, disk and volume identifiers and
the maintainer's own unit names; a guard in tests/conftest.py
fails any test that reaches the real subprocess runner, so nothing in the run
touches systemd or the network. Three opt-in tests marked live run against
the real user manager (uv run --frozen pytest -m live); they are off by
default and CI never selects them. CI also runs ruff check .,
mypy --strict src and the launcher under an empty environment.
What it does not do
No unit changes. It cannot start, stop, restart, enable, disable, mask, edit or reload anything, in this version or through any parameter.
No privilege escalation. It reads what the invoking user can read; a user outside
admorsystemd-journalsees their own journal, not the system's.No network transport. The MCP server speaks stdio only: no HTTP, no socket, no listener.
No field selection beyond the parameters. A caller cannot name journal fields or pass
journalctloptions; filtering goes throughunit,since,until,priority,grepandlinesonly.No sandbox. Its guarantees are properties of the code, held by tests, not an operating-system boundary; the process has the invoking user's rights. What an MCP client then shows a model is the client's decision.
No escaping in the CLI's text view. Log text is printed as written, control characters included;
--jsonescapes them.
Licence
MIT; see LICENSE.
Available Tools
8 toolsbootsARead-only
The boots the journal records; index 0 is the current boot. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| boots | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the description's trailing 'Read-only' is redundant rather than additive. The genuinely useful disclosure is the index-0-is-current-boot ordering convention, which is behavior an agent cannot get from the annotations or the empty schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the resource stated first and the ordering rule immediately after. Nothing is padded, and the one arguably redundant clause ('Read-only') costs almost nothing in length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no prose explanation, and annotations cover the safety profile. The description supplies the one non-obvious piece — boot indexing — making it sufficient for correct invocation, with only the missing relationship to the journal sibling as a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool is 4. No parameter information is missing or misleading.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource (the boot sessions recorded by the journal) and a concrete semantic detail — index 0 is the current boot — which tells an agent exactly what the list contains and how it is ordered. It is clearly distinct from siblings like journal, unit_status, or failed_units, though it never explicitly contrasts itself with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The index-0 convention implies how the output is meant to be consumed (e.g., selecting a boot to query elsewhere), but there is no explicit when-to-use statement, no mention of the journal/boot relationship, and no alternatives named. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
failed_unitsARead-only
List the failed units of one manager. Read-only. scope is 'user' or 'system'.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | |
| units | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the description's 'Read-only' statement is redundant with structured data and earns no credit. It does add one piece of behavioral context — that the tool is scoped to a single manager's failed units — which is modest value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the purpose, then the safety trait, then the parameter constraint. Only 'Read-only' is arguably wasted since annotations already state it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the one required parameter's values are given. The main remaining gap is that 'manager' is never defined and no sibling routing is offered, but for a single-parameter read tool this is close to sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the sole parameter has no enum in the schema, so the description carries the full burden; it does so by spelling out the allowed values 'user' or 'system'. That is exactly the information an agent needs to call the tool, though it omits the default and what each value selects.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the failed units') and narrows scope ('of one manager'), which distinguishes it from the sibling list_units that presumably returns all units. It does not explicitly name or contrast against list_units or the other siblings, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the agent can infer this is for diagnosing failed services rather than listing everything, but the description never says when to prefer failed_units over list_units or unit_status. No alternatives or preconditions are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
journalARead-only
Journal entries, oldest first, reduced to an allowlist of fields. Read-only.
Filters: unit, since and until (such as '2026-10-03 12:00' or '-1h'), priority (such as 'err' or 'warning..crit'), grep (a regular expression on MESSAGE), lines (default 100, at most 1000). Secrets are redacted; text is capped at 4096 bytes per value and 65536 bytes in all, and a cut ends in [TRUNCATED] and sets truncated to true.
| Name | Required | Description | Default |
|---|---|---|---|
| grep | No | ||
| unit | No | ||
| lines | No | ||
| scope | Yes | ||
| since | No | ||
| until | No | ||
| priority | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| unit | Yes | |
| scope | Yes | |
| entries | Yes | |
| truncated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnlyHint and openWorldHint, but the description adds real behavioral detail: secrets are redacted, values are capped at 4096 bytes and 65536 bytes overall, a cut appends [TRUNCATED] and sets truncated to true, and results are reduced to an allowlist. That is substantial data-handling context an agent cannot get from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and read-only status are front-loaded, followed by a compact filter list and one dense paragraph on redaction and truncation. Every sentence carries information, though the truncation sentence packs several distinct facts into one run-on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be described, and the description still adds the truncated flag and allowlist behavior. The remaining gap is the undocumented required 'scope' parameter, which an agent must guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the load, and it documents six of seven parameters with concrete syntax examples for since/until ('2026-10-03 12:00' or '-1h') and priority ('err', 'warning..crit'). It omits any explanation of the required 'scope' parameter, which is the one the agent must supply.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (journal entries), states the ordering (oldest first) and the projection (allowlist of fields), so an agent knows it is a log-read tool. The verb is only implied by the noun phrase plus 'Read-only', and nothing distinguishes it from siblings such as boots or unit_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The filter list (unit, since, until, priority, grep, lines) implies how to narrow a query but never says when to choose this tool over boots or unit_status. There are no exclusions or prerequisites, so usage is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_timersBRead-only
List the timers of one manager, with next and last run times in microseconds since the epoch. Read-only. scope is 'user' or 'system'.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | |
| timers | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the 'Read-only' sentence largely repeats structured data rather than adding new context. It does add useful behavioral detail about the return format (next/last run times expressed in microseconds since the epoch), but says nothing about permissions, empty results, or pagination.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight clauses, front-loaded with the verb and resource, no filler. The scope clause is appended naturally at the end rather than buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is not needed. Combined with annotations covering the safety profile and the description supplying the scope enum values and time format, an agent has enough to invoke this correctly, with only minor gaps (permissions, behavior on empty results).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameter burden, and it does: it enumerates the valid scope values ('user' or 'system'), which the schema's bare untyped string property does not convey. It stops short of stating the default or whether scope is required, but the value domain is covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the timers of one manager') and specifies what the listing contains ('next and last run times in microseconds since the epoch'). It is unambiguous, though 'one manager' is slightly loose and there is no sibling that overlaps in resource to contrast against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites, and no routing to alternatives. Sibling list_units covers a related domain, but the description never explains when a timer listing is the right call versus a unit listing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_unitsBRead-only
List the units systemd has in memory (systemctl list-units --all). Read-only.
scope is 'user' or 'system'. state filters on a LOAD, ACTIVE or SUB state, type on a unit type such as 'service', pattern on a glob over unit names.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | ||
| scope | Yes | ||
| state | No | ||
| pattern | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | |
| units | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the description's 'Read-only.' is largely redundant. The one piece of added context is that it reflects systemd's in-memory view rather than on-disk unit files, but nothing is said about volume of output or how it scales.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Tight and front-loaded: the purpose and read-only nature come first, then one compact line per parameter. No filler sentences, though the parameter block reads as a run-on fragment list rather than clean structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described, and the zero-coverage schema is compensated for by the parameter explanations. The remaining gap is sibling routing against failed_units/list_timers, which an agent would otherwise have to guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden and largely does: it defines scope's domain ('user' or 'system'), explains state as a LOAD/ACTIVE/SUB state filter, type as a unit type such as 'service', and pattern as a glob over names. It stops short of examples or noting which parameters are optional/defaulted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the units systemd has in memory') and pins it to the underlying command with `--all`. It does not, however, differentiate itself from closely related siblings like failed_units, list_timers, or unit_status, so an agent must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance, and no mention of the sibling tools that overlap heavily (failed_units, list_timers). The only routing signal is implicit in the parameter descriptions, which is not the same as usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_summaryBRead-only
The system manager's state word, failed-unit and timer counts for both managers, and the current boot's first-entry time. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| boot_time | Yes | |
| timers_user | Yes | |
| timers_system | Yes | |
| failed_units_user | Yes | |
| failed_units_system | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, and the description merely restates 'Read-only', which adds no new safety information. It does add useful scope context by enumerating exactly which data points are returned, but omits anything about caching, staleness, or refresh behavior for a summary snapshot.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence with no filler, and it leads with the primary resource (the system manager's state). 'Both managers' is left unexpanded, which forces a small inference, but the description is otherwise tight and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no inputs and an output schema present, the definition has little left to carry, and the field enumeration is sufficient for an agent to select it. It would be fully complete with one clause routing the agent away from the per-unit sibling tools when only aggregate counts are needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description's enumeration of returned fields is not parameter semantics, but nothing is required of it here beyond confirming the absence of inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific aggregate resource — the system manager's state word, failed-unit and timer counts for both managers, and the boot's first-entry time — so an agent knows this is a roll-up view rather than a listing. However, it never differentiates itself from siblings like failed_units, list_timers, or unit_status, which appear to return the same underlying data at finer granularity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance. The word 'summary' implies an overview role, but the description never states that an agent should prefer this over calling list_units/list_timers when it only needs counts, nor does it list any prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unit_fileBRead-only
The unit file text as systemctl cat prints it. Read-only.
Redacted, and capped at 65536 bytes; a cut ends in [TRUNCATED] and sets truncated to true.
| Name | Required | Description | Default |
|---|---|---|---|
| unit | Yes | ||
| scope | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| unit | Yes | |
| scope | Yes | |
| truncated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations' readOnlyHint/openWorldHint, the description discloses redaction, a hard 65536-byte cap, the [TRUNCATED] sentinel, and that the truncated flag flips to true on a cut. That is genuinely useful operational context. It stops short of explaining why redaction occurs or whether scope affects which file is read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, front-loaded with the identity of the returned content, followed by the caveats. Nothing is padded and every clause adds information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape detail is not strictly required, and the truncation flag is still usefully surfaced. However, with two undocumented required parameters at 0% schema coverage, the definition is not complete enough for confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both required parameters, unit and scope, have zero schema description coverage, so the description carries the full burden and fails it. It never explains what 'unit' should contain (name, instance, suffix?) or what values 'scope' accepts (system vs user), leaving an agent to guess at invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (the unit file text) and anchors it to a familiar reference ('as systemctl cat prints it'), which tells an agent exactly what content comes back. It does not differentiate itself from siblings like unit_status or list_units, which also concern units, so an agent must infer the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never says when to reach for this tool versus unit_status, list_units, or journal. 'Read-only' is the only routing hint, and it is already covered by annotations, so there is effectively no usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unit_statusARead-only
One unit's load, active and sub state, result and main PID, plus its last journal entries (default 20, at most 1000). Read-only.
Text is redacted and capped at 4096 bytes per value and 65536 bytes in all; a cut value ends in [TRUNCATED] and sets truncated to true.
| Name | Required | Description | Default |
|---|---|---|---|
| unit | Yes | ||
| lines | No | ||
| scope | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| unit | Yes | |
| scope | Yes | |
| result | Yes | |
| entries | Yes | |
| sub_state | Yes | |
| truncated | Yes | |
| load_state | Yes | |
| description | Yes | |
| active_state | Yes | |
| exec_main_pid | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so 'Read-only' is redundant. However the description adds real behavioral context beyond structured data: per-value redaction, 4096-byte/65536-byte caps, the [TRUNCATED] marker, and the truncated flag — all of which affect how an agent must interpret the response.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the return payload, then the read-only note, then truncation semantics — logical ordering with no filler. The standalone 'Read-only' sentence duplicates the readOnlyHint annotation and is the one throwaway line.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape explanations are unnecessary, and the description usefully covers truncation semantics that the output schema alone would not convey. The remaining gap is the undocumented required 'scope' parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description is the only source. It explains 'lines' (default 20, max 1000) and implies 'unit' (single unit), but the required 'scope' parameter (system vs user, presumably) is never explained anywhere, leaving a required argument opaque.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource ('one unit') and enumerates exactly what status fields it returns — load, active/sub state, result, main PID, plus tailed journal entries. An agent can distinguish it from list_units, failed_units, and journal without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The single-unit framing implies 'use this for one named unit', but no sibling is named and no when-not-to-use condition is stated (e.g. use list_units to enumerate, journal for log-only retrieval). Usage is inferable but not guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
boots - First observed
failed_units - First observed
journal - First observed
list_timers - First observed
list_units - First observed
system_summary - First observed
unit_file - First observed
unit_status
TDQS
Scored across 8 tools
Most tools target distinct resources: boots, journal, unit_file, system_summary are clearly separate. However, failed_units is essentially a filtered subset of list_units, and unit_status overlaps with journal for a single unit, though descriptions clarify intended use.
Names are all lowercase snake_case and readable, with noun_phrase style (list_units, unit_status, unit_file). Minor deviation: 'boots' and 'journal' are bare nouns that don't follow the verb_noun or list_ pattern used elsewhere, but the convention is largely predictable.
Eight tools is well-scoped for a read-only systemd/journal inspection server, with each tool covering a meaningful slice of the domain without redundancy bloat.
For a read-only diagnostic surface, coverage is strong: units, failed units, timers, boots, journal filtering, unit files, and a system summary. Minor gaps like journal disk usage/rotation stats or per-boot statistics are absent but not blocking.
Maintenance
Related MCP Connectors
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Read-only access to a Lumin project's logs, metrics, uptime checks, alerts and infrastructure.
Read-only CVE intelligence, remediation playbooks, and agent setup guides. Not a scanner.
Read-only agent-commerce audit, upgrade verification, diagnosis and x402 probing.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceProvides 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-
- AlicenseNot gradedqualityCmaintenanceRead-only systemd inspection for Claude on Linux — list units, status, journal, failed units, unit files.MIT
- AlicenseNot gradedqualityCmaintenanceEnables read-only observability of a Linux host via MCP, exposing allowlisted systemd, docker, nginx, logs, disk, and cert info without shell access.MIT
- FlicenseNot gradedqualityAmaintenanceProvides structured read-only SSH/SFTP and AWS operations on a single RHEL host, with path allowlisting, output limits, and IAM-based authorization.-