opsgate
opsgate is an MCP server that lets an AI agent inspect and operate real servers through fixed, typed tools (never freeform shell strings), with policy modes, approval gates, and a tamper-evident audit log.
Inspect (read-only, always available):
Host health:
system_info(kernel, uptime, load, memory),disk_usage(df -h),process_top(top processes by CPU/mem),listening_ports(sockets + owning processes).systemd:
service_list(running/failed/all),service_status(state + recent log lines).Logs:
journal_tail(filter by unit,since, priority),journal_errors(recent err-and-worse triage).Docker:
docker_ps,docker_logs,docker_inspect(health, restart count, image, mounts),docker_stats(CPU/mem snapshot),compose_ps(services in a compose project dir).Files:
file_read,dir_list,file_grep— all confined to configuredfiles.allow_paths.nginx:
nginx_testto validate config without applying it.
Change state (refused in observe, human-approval-gated in operate):
systemd:
service_restart,service_start,service_stop,service_reload.Docker:
docker_restart,docker_start,docker_stop.nginx:
nginx_reload— runsnginx -tfirst and refuses a broken config.
Operational characteristics:
Every call takes an optional
hostnaming a target from the opsgate config (defaults to the default host).Commands are built as
argvarrays, so agent input can never become shell syntax; target names are allowlist-restricted per tool.Every call, including refusals, is appended to a hash-chained JSONL audit log (mutations log
intentbefore andoutcomeafter);opsgate audit verifydetects tampering.shell_exec(freeform shell) exists but is disabled unless explicitly enabled and is always approval-gated.
opsgate
The safety gate between AI agents and your servers.
An MCP server that lets Claude, Cursor, or any AI agent operate real infrastructure — without handing it a root shell.
What it looks like · 30-second try · Break it yourself · Tools · Security model · Contributing
What it looks like
You ask a question. The agent investigates with read-only tools and answers.
You: Something's listening on port 8000 on my server and I don't remember what. Check it.
▸ listening_ports(host: "hetzner")
Netid State Recv-Q Send-Q Local Address:Port Process
tcp LISTEN 0 511 0.0.0.0:443 users:(("nginx",pid=249619),…)
tcp LISTEN 0 511 0.0.0.0:80 users:(("nginx",pid=249619),…)
tcp LISTEN 0 4096 0.0.0.0:22 users:(("sshd",pid=237597),…)
tcp LISTEN 0 151 127.0.0.1:3306 users:(("mysqld",pid=237695),…)
tcp LISTEN 0 5 127.0.0.1:8000 users:(("python3",pid=237608),…)
▸ service_list(host: "hetzner", state: "running")
docker.service loaded active running Docker Application Container Engine
mysql.service loaded active running MySQL Community Server
nginx.service loaded active running A high performance web server…
php8.3-fpm.service loaded active running The PHP 8.3 FastCGI Process Manager
pm2-root.service loaded active running PM2 process managerClaude: Port 8000 is a bare
python3process (pid 237608) bound to localhost only, so it isn't reachable from outside. It's not managed by systemd — no unit owns it — which means it won't survive a reboot. It's most likely something started by hand in a shell.
Now something that changes state. In operate mode the agent cannot just do it:
You: OK, nginx config changed. Reload it.
▸ nginx_test(host: "hetzner")
nginx: configuration file /etc/nginx/nginx.conf test is successful
▸ nginx_reload(host: "hetzner")
┌─ opsgate: approval required ─────────────────────────────────┐
│ allow nginx_reload on host "hetzner"? │
│ │
│ The nginx configuration passed validation. │
│ This will reload nginx. │
│ │
│ Command: 'nginx' '-s' 'reload' │
│ [ Approve ] [ Deny ] │
└─────────────────────────────────────────────────────────────┘You click Deny, and nothing happens — the agent is told the operator refused. Approve, and it runs and lands in the audit log. Either way you saw the exact command first.
(Tool output above is real output from a live server; the prompt is rendered by your MCP client, so it looks however that client draws it.)
Related MCP server: AgentGate
Try it in 30 seconds (no server needed)
opsgate runs with no config file at all — local machine, read-only:
go install github.com/polymatx/opsgate/cmd/opsgate@latest
opsgate serveopsgate v0.1.3 | mode=observe | default_host=local | audit=~/.opsgate/audit.jsonlThat's it. No config, no SSH, and it defaults to observe — so it can read your disk usage
and journal, and it will refuse to change anything:
▸ disk_usage() → works
▸ service_restart(...) → Refused by opsgate policy: host is in observe modePoint your client at it and ask "what's using disk space on this machine?" When you're
ready for real hosts, opsgate init writes a starter config to ~/.opsgate/config.yaml.
Which clients can reach it
opsgate runs on your machine (or on the server itself) and holds your SSH key, so the transport you need depends on where your client actually executes:
Client | Transport | Works because |
Claude Code (terminal) | stdio | Runs natively on your machine and launches the binary |
Claude Desktop, Cursor, VS Code | stdio | Same — a local process |
Cloud or sandboxed surfaces (web chat, VM-backed agents) | HTTP | They cannot launch a local process, or even see your SSH key — they can only reach a URL |
If your client reports it has no access to your servers, it is almost certainly one of the sandboxed kind. Serve over HTTP instead of stdio.
Before publishing that endpoint, read the warning there: it puts an infrastructure-management API on whatever network you expose it to.
Wire it up to your client
As a plugin: the MCP server, a server-ops skill that teaches the agent to diagnose before
it acts and to treat refusals as final, and a read-only /opsgate:health-check [host] command.
/plugin marketplace add polymatx/opsgate
/plugin install opsgate@opsgateThe plugin runs opsgate serve, which reads ~/.opsgate/config.yaml (opsgate init writes a
starter one). It never reads a config from the project you have open.
Or add just the MCP server:
claude mcp add opsgate -- opsgate serve --config ~/.opsgate/config.yaml{
"mcpServers": {
"opsgate": {
"command": "opsgate",
"args": ["serve", "--config", "/absolute/path/to/opsgate.yaml"]
}
}
}For hosts reached over SSH. Inside a container, local is the container itself.
docker run -i --rm \
-v ~/.opsgate:/root/.opsgate \
-v ~/.ssh:/root/.ssh:ro \
ghcr.io/polymatx/opsgate serveThe image is also how opsgate is listed in the MCP Registry
as io.github.polymatx/opsgate.
http:
addr: "127.0.0.1:8080"
auth_token: "a-long-random-token" # sent as: Authorization: Bearer <token>opsgate serve --http 127.0.0.1:8080The tidiest deployment is to run opsgate on the server it manages — then it needs no SSH
key at all (default_host: local) — behind a TLS-terminating reverse proxy:
client ──HTTPS──▶ nginx / Caddy ──▶ 127.0.0.1:8080 opsgate
+ Bearer tokenopsgate refuses to serve HTTP on a non-loopback address unless http.auth_token is set.
Exposing this endpoint puts an infrastructure-management API on that network, and the
bearer token becomes the only thing protecting it. If you must publish it: keepmode: observe, generate 32+ bytes of randomness for the token, require TLS, and add an
IP allowlist at the proxy. Binding it to a VPN interface (WireGuard, Tailscale) instead of
the public internet is strictly safer — your own devices reach it, nobody else can.
Note also that operate mode expects a human who can answer an approval prompt. An
unattended HTTP deployment usually means observe.
The problem this solves
Letting an AI agent run your servers today means giving it exec("<any string>") over SSH.
The usual mitigation is a denylist of commands that look dangerous.
That does not work. Denylists are guesswork against an adversary with infinite phrasings:
rm -rf / → blocked
r''m -rf / → not blocked
echo cm0gLXJmIC8K | base64 -d | sh → not blockedAnd "dangerous-looking" isn't even the hard part. systemctl restart nginx is a perfectly
ordinary command that is catastrophic at 3pm on Black Friday.
The approach
opsgate does not filter strings. It never gives the agent a string to fill in.
The agent gets 25 typed tools — service_restart(name), docker_logs(container),
journal_tail(unit, since, priority) — and opsgate builds the command itself as an argv
array. There is no shell to inject into, because no shell string is ever assembled from
agent input.
// What opsgate does — the name is one argv element, whatever it contains
argv := []string{"systemctl", "restart", in.Name}
// What it never does
argv := []string{"sh", "-c", "systemctl restart " + in.Name}Send nginx; rm -rf / as the service name and systemctl receives it as a single literal
argument and fails as an unknown unit. Nothing else runs.
Every call then passes through four gates:
flowchart LR
A[Agent calls a tool] --> B{Policy<br/>mode + allowlist}
B -->|deny| X[Refused<br/>+ audited]
B -->|allow| D[Build argv]
B -->|needs approval| C{Human}
C -->|deny| X
C -->|approve| D
D --> E[Execute]
E --> F[Audit<br/>hash-chained]Layer | What it does |
Structured tools | Commands are built as |
Deny-by-default policy | Three modes — |
Human approval gates | Mutating calls pause and ask you, showing the exact command. Needs a client that supports MCP elicitation; if it cannot ask, the call is refused rather than run. |
Tamper-evident audit | Every call — including every refusal — appended to a hash-chained JSONL log. Editing or deleting any line is detectable. |
The default mode is observe. Out of the box, an agent can diagnose your servers and
change nothing.
Break it yourself
Don't take the claims on faith. Start opsgate in observe mode with
files.allow_paths: [/var/log] and try these — every one is refused, and the refusal is
logged:
Try this | What happens |
| Refused — invalid characters in a target name |
| Refused — outside the allowed paths |
| Refused — outside the allowed paths |
| Searched as a literal string; nothing executes |
| Refused — observe mode cannot mutate |
| Refused — omitting the unit would read the whole journal |
| Refused — the tool isn't even registered unless you opt in |
Then confirm nothing landed:
$ ls /tmp/pwned
ls: cannot access '/tmp/pwned': No such file or directory
$ opsgate audit verify
audit chain OK: 6 records verified in ~/.opsgate/audit.jsonl(Six, not seven: shell_exec isn't a registered tool at all when it's disabled, so that
call is rejected by the protocol before it reaches a gate.)
Found something that does get through? That's a security bug — please report it.
Modes
mode: observe # read-only. Mutating tools are refused outright.
mode: operate # reads run freely; every write asks you first. ← recommended
mode: full # writes run unprompted. Still fully audited.Pin production tighter than everything else:
mode: operate
hosts:
prod:
addr: 10.0.0.1
mode: observe # prod is read-only even though the default is operate
staging:
addr: 10.0.0.2 # inherits operateRestrict what a tool may touch:
tools:
service_restart:
allow_targets: ["nginx", "myapp*"] # postgresql is not restartable, period
service_stop:
enabled: false # remove the tool entirely
shell_exec:
enabled: true # opt in to freeform shell (still approval-gated)Setting allow_targets also makes the target mandatory for that tool: omitting it is
usually broader than any allowed value — journal_tail with no unit reads the whole
journal — so an unconstrained call is refused rather than silently permitted.
Docker tools accept only exact container names, never IDs or ID prefixes, so a pattern
like db* matches what you see in docker ps and nothing else. files.allow_paths: []
turns file access off entirely; leaving the key out keeps the defaults.
See configs/opsgate.example.yaml for every option.
Tools
Observe — always available
system_info · disk_usage · process_top · listening_ports · service_list ·
service_status · docker_ps · docker_logs · docker_inspect · docker_stats ·
compose_ps · journal_tail · journal_errors · file_read · dir_list ·
file_grep · nginx_test
Mutate — refused in observe, approval-gated in operate
service_restart · service_start · service_stop · service_reload ·
docker_restart · docker_start · docker_stop · nginx_reload
Opt-in
shell_exec — freeform shell. Disabled unless you enable it; always approval-gated. It
exists for the genuine long tail, and everything above exists so you rarely need it.
nginx_reload runs nginx -t first and refuses to reload a config that does not parse.
Things worth asking your agent
"Why is nginx throwing 502s on web1?" — correlates
service_status,journal_tail,docker_ps"What filled up the disk on prod?" —
disk_usagethendir_listunder allowed paths"Did anything crash overnight?" —
journal_errorsacross hosts"Which containers are unhealthy and how many times have they restarted?" —
docker_inspect"Compare staging and prod: what's running on one but not the other?" —
service_liston both
The audit log
Every call appends one JSON line embedding the hash of the previous record:
{"seq":41,"time":"2026-07-29T11:02:14Z","host":"web1","tool":"service_status","decision":"allow","exit_code":0,…,"prev_hash":"9f2c…","hash":"41ab…"}
{"seq":42,"time":"2026-07-29T11:02:31Z","host":"web1","tool":"file_read","args":{"path":"/root/.ssh/id_rsa"},"decision":"deny","error":"outside the allowed paths",…}
{"seq":43,"time":"2026-07-29T11:03:02Z","host":"web1","tool":"service_restart","phase":"intent","decision":"needs_approval","approved":true,…}
{"seq":44,"time":"2026-07-29T11:03:02Z","host":"web1","tool":"service_restart","phase":"outcome","decision":"needs_approval","approved":true,"exit_code":0,…}Refusals are recorded too — a blocked attempt to read a private key is exactly what you want to find later.
A state-changing call writes two records: phase: intent before the command runs and
phase: outcome after. If the intent record cannot be written, opsgate refuses to act — so
an action that happened can never be missing from the log.
$ opsgate audit verify
audit chain OK: 143 records verified in ~/.opsgate/audit.jsonlEdit, delete, or reorder any earlier line and verification fails at exactly that point:
$ opsgate audit verify
opsgate: audit chain INVALID after 41 records: line 42: record tampered (hash mismatch)Splicing in a forged field doesn't work either — verification decodes strictly:
opsgate: audit chain INVALID after 2 records: line 3: json: unknown field "approved_by"The chain cannot show records cut off the end of the file, or a log rewritten from scratch by someone with write access; ship it off the box or to append-only storage if that matters (see the threat model).
Arguments named like password or token are redacted before they are written; everything
else, including a shell_exec command, is logged as sent, so keep secrets out of tool
arguments. Very long values are cut to a short prefix plus their length and SHA-256. Only
the SHA-256 of command output is stored — never the output itself.
How this compares
Other SSH-over-MCP servers exist and are useful; they make a different trade.
Freeform-shell MCP servers | opsgate | |
What the agent sends | a command string | typed arguments to a fixed tool |
Injection defense | regex denylists on the string | no shell string is built — argv only |
Approval | none, or client-side auto-approve | per-call, server-side, shows the exact command |
Read-only guarantee | convention |
|
Audit | varies | hash-chained, includes refusals, intent-before-execution |
Runtime | usually Node | single static Go binary, no runtime |
The honest trade: opsgate's tool set is finite, so something you need may not be covered
yet. That's what shell_exec and contributions are for.
Security model
opsgate reduces blast radius. It is not a sandbox, and it does not make an untrusted agent safe to point at production.
What it guarantees
Agent input never becomes shell syntax. Commands are
argv; the SSH transport single-quotes every element, so each argument stays one literal word. Target names that start with-are refused, so they cannot turn into command-line options.observemode cannot mutate. There is no code path from a read-only mode to a state-changing command.File tools cannot escape
files.allow_paths— paths are cleaned before the prefix check, so/var/log/../../etc/shadowis refused.SSH host keys are verified against
known_hosts. Unknown keys are refused, never trusted on first use.Every decision is audited, including refusals, and a mutating action is recorded before it runs.
An approval answers one prompt for one exact call (host, tool, command) and is used once; a client cannot pre-approve a call it was never asked about.
opsgate reads its config only from
--configor~/.opsgate/config.yaml, never from the directory it starts in, so a repository cannot ship a config that widens the policy.
What it does not
Tools run with the privileges of your SSH user. If that is root, an approved call is a root call. Give opsgate its own least-privilege user.
shell_exec, once enabled and approved, is arbitrary code execution. That is its purpose.fullmode removes the human. Use it only where you accept that.A prompt-injected agent can still call allowed tools with plausible arguments. The policy is what bounds the damage — keep
allow_targetstight.The path check is lexical: a symlink inside an allowed directory pointing outside it will be followed.
Approval is only as honest as the MCP client that shows the prompt. A client that answers "accept" on its own defeats it; use a client you trust.
See docs/threat-model.md for adversaries, controls, and limits in detail.
Why this exists
I run my own infrastructure and I wanted to point Claude at it. Every existing option asked me to choose between "useless" and "here is a root shell, good luck." opsgate is the middle: the agent gets real capability, I keep the veto and the receipts.
Contributing
Contributions are genuinely welcome, and the architecture makes new tools easy — most are ~20 lines. Read CONTRIBUTING.md for the one rule that matters (commands are argv, never concatenated strings).
Good first contributions
More structured tools — Kubernetes (
kubectl get/describe/logs), PostgreSQL and MySQL status, Caddy, Traefik,ufw/iptablesstatus, certificate expiry,apt/dnfpending updatesPolicy primitives — time windows ("no restarts during business hours"), rate limits, per-tool concurrency caps
Audit sinks — syslog, append-only S3, webhook
Client compatibility reports — tell us how the approval prompt renders in your MCP client
go test -race ./...
go vet ./...
gofmt -l . # must print nothingIf opsgate is useful to you, a ⭐ helps other people running their own infrastructure find it.
License
MIT — see LICENSE.
Available Tools
25 toolscompose_psC
List services of a Docker Compose project in a directory.
| Name | Required | Description | Default |
|---|---|---|---|
| dir | Yes | directory containing the compose file | |
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'List' weakly implies a read-only operation, but nothing is said about behavior when the directory lacks a compose file, whether a Docker daemon/host connection is needed, or what shape the result takes.
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 sentence with the scope front-loaded and no filler. It is efficient, though its brevity is partly the cause of the missing guidance rather than a virtue of restraint.
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?
For a simple two-parameter list operation with full schema coverage and no output schema, the core intent is conveyed. Still missing are failure conditions (no compose file, unreachable host) and any tie-breaker against the closely named docker_ps sibling.
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 100% and both parameters (dir, host) are documented in the schema, so the baseline is 3. The description adds nothing about parameter meaning beyond restating the directory scope.
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?
Specific verb ('List') plus a precisely scoped resource ('services of a Docker Compose project in a directory'). It is distinguishable from docker_ps by the project/directory scope, though it never explicitly contrasts itself with that sibling.
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 statement of when to use this versus docker_ps or service_list, and no prerequisites (e.g. that the directory must contain a compose file). Usage is only inferable from the scope phrase 'in a directory'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dir_listB
List a directory under one of the configured allowed paths.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| path | Yes | absolute directory path to list |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden. It usefully discloses the access boundary (only configured allowed paths are listable), but says nothing about recursion depth, hidden files, symlink handling, ordering, or what an error on a disallowed path looks like.
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 front-loaded sentence with no filler and the access constraint placed immediately after the verb. Its brevity is efficient, though it borders on under-specification for a tool with no annotations.
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 annotations, no output schema, and no return-shape documentation, the description leaves the agent guessing about recursion behavior and result format. The access constraint is the only real context provided, which is thin for a filesystem tool.
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 100% and both parameters (host, path) are documented in the schema, including the default-host behavior for the optional one. The description adds no format or semantics beyond that, so the baseline of 3 applies.
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 ('List') and resource ('a directory') plus a scoping constraint ('under one of the configured allowed paths'), so an agent can tell it apart from read-oriented siblings like file_read and file_grep. It never names a sibling explicitly, so differentiation is inferential rather than stated.
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: you use it to enumerate a directory, and the 'configured allowed paths' phrase hints at the sandbox boundary. There is no when-to-use vs. when-not guidance and no routing to file_read or file_grep for content retrieval.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disk_usageA
Show mounted filesystem usage (df -h) for a host.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. Referencing "df -h" usefully signals a read-only snapshot with human-readable output, but it never states that the operation is non-destructive, what permissions it needs, or how the default-host fallback behaves. Adds some behavioral context but leaves real gaps.
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 front-loaded sentence with zero filler; the scope qualifier ("for a host") is placed where it matters. Nothing could be trimmed without losing 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?
For a one-optional-parameter read-only tool with no output schema, the definition is nearly sufficient; the df -h reference hints at the return shape. It would be fully complete with an explicit read-only/permission note.
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 single host parameter has 100% schema description coverage, including the "omit for the default host" default behavior, so the schema does the heavy lifting. The description only echoes "for a host" and adds no syntax or format detail beyond it; baseline 3 applies.
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 ("Show") and resource ("mounted filesystem usage") scoped to "a host", which is enough to distinguish it from diagnostic siblings like system_info or listening_ports. It does not explicitly name a sibling it is not, so it stops 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 implied by the self-evident purpose, but there is no explicit when-to-use, when-not-to-use, or named alternative among the many ops siblings. An agent can infer the use case, but the definition provides no routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_inspectA
Inspect a container's health, restart count, image and mounts.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| container | Yes | container name or ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Inspect' reasonably implies a read-only operation and the description discloses the returned fields, but it says nothing about permissions, whether stopped containers can be inspected, or what happens if the container name/ID is invalid.
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 front-loaded sentence with zero filler; the resource comes first and the returned fields are packed into the same clause. Nothing is redundant.
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?
For a simple two-parameter read tool with full schema coverage, the description covers what the tool does and roughly what it yields. The only gap is behavioral context (auth/state requirements) that no annotation supplies, which is a minor omission given the tool's simplicity.
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 100% – both 'host' and 'container' are documented in the schema, including the default-host behavior. The description adds no syntax or format detail beyond that, so the baseline 3 applies.
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 ('Inspect') and resource ('a container') and enumerates the fields returned (health, restart count, image, mounts), which lets an agent distinguish it from docker_logs or docker_stats. It never names a sibling or scopes itself against them, so differentiation is inferred rather than stated.
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 listed fields (health, restart count) imply a diagnostic use case, but the description gives no explicit when-to-use, when-not-to-use, or alternative tool. An agent must infer that this is the tool for pulling container metadata rather than metrics or logs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_logsC
Read the recent logs of a Docker container.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| lines | No | how many trailing log lines (default 100, max 2000) | |
| container | Yes | container name or ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It says 'recent logs', which hints at a bounded tail rather than a stream, but it does not state that the operation is read-only/non-mutating, does not mention that it requires Docker daemon or socket access, and does not disclose behavior for a stopped or nonexistent container.
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 front-loaded sentence with no filler or repetition of the name. It is efficient, though it is arguably minimal to the point of under-specification rather than maximally informative conciseness.
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?
For a simple 3-parameter read tool with fully documented parameters and no output schema, the description is nearly sufficient. What is missing is behavioral context — read-only status, host/daemon requirements, and the meaning of 'recent' relative to the lines default of 100 — which no structured field supplies.
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 100%, so all three parameters (host, lines, container) are already documented with defaults and limits in the schema itself. The description adds no parameter-level meaning beyond the schema, so the baseline 3 applies.
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 states a specific verb and resource ('Read the recent logs of a Docker container'), which is clearly distinct from sibling operations like docker_inspect, docker_ps, and docker_stats. However, it does not explicitly name or contrast itself with the nearest sibling (docker_inspect for container metadata), so sibling differentiation is implied rather than stated.
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 alternatives are named. An agent must infer from the tool name that this is the log-reading option rather than, say, docker_inspect or journal_tail, and nothing indicates prerequisites such as the container needing to be running.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_psB
List Docker containers with status, image and ports.
| Name | Required | Description | Default |
|---|---|---|---|
| all | No | include stopped containers (default false) | |
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It usefully discloses the returned columns (status, image, ports) but says nothing about read-only safety, whether it can block, or how it behaves on an unreachable host — the schema covers the stopped-container default but not the safety profile.
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 front-loaded sentence with zero filler; the resource and its return fields are stated immediately with no redundancy.
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?
The description partially compensates for the missing output schema by naming the returned fields, and the parameter schema is complete. However, with no annotations and no usage context, an agent still lacks guidance on safety and on choosing between this and compose_ps or docker_stats.
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 100% with two well-documented parameters, so the schema already explains 'all' and 'host'. The description adds no further parameter meaning, which is the correct baseline when the schema does the heavy lifting.
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 ("List") and resource ("Docker containers") plus the notable output columns (status, image, ports), so the agent knows exactly what this tool returns. It does not distinguish itself from the near-identical sibling compose_ps, leaving that differentiation to inference.
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 statement of when to use this tool versus alternatives such as compose_ps, docker_inspect, or docker_stats, nor any prerequisites or exclusions. Usage is only implied by the name and the 'all' parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_restartC
Restart a Docker container.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| container | Yes | container name or ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it discloses nothing beyond the verb. It does not say whether the restart is graceful (SIGTERM then start), whether it causes downtime, what happens if the container is already stopped, or how failures are reported.
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 short sentence with the verb and resource front-loaded and zero filler. It is efficient, though arguably terse enough that it is under-specified rather than optimally concise.
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?
For a two-parameter tool with full schema coverage and no output schema, the definition is minimally adequate. However, with no annotations and no mention of restart semantics or failure modes, it leaves gaps an agent would need 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 description coverage is 100%, with both 'container' and the optional 'host' parameter documented (including the opsgate config default). The description adds no meaning beyond the schema, so the baseline 3 applies.
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 ('Restart') and resource ('Docker container'), which cleanly separates it from docker_start, docker_stop, and docker_ps in the sibling set. It does not explicitly contrast itself with those siblings, but the verb alone is unambiguous.
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 guidance on when to use this over docker_start/docker_stop or service_restart, and no preconditions stated (e.g., container must exist or be running). The agent must infer usage entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_startC
Start a stopped Docker container.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| container | Yes | container name or ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, yet it only repeats that the container is 'stopped'. It says nothing about behavior on an already-running container, required Docker/host permissions, or side effects of starting.
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 front-loaded sentence with no wasted words. It is efficient, though arguably too terse to carry the guidance a mutation-class tool needs.
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?
The tool is simple (two params, one required), so the description is close to sufficient. But with no annotations and no output schema, it should still say what happens on an already-running container and confirm the operation's effect.
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 100%, so 'container' and 'host' are fully documented in the schema, including the host-default behavior. The description adds no meaning beyond that, making the baseline 3 appropriate.
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 (Start) and resource (stopped Docker container), so the action is unambiguous. It does not, however, distinguish itself from siblings like docker_restart or docker_stop, which an agent must infer from the names alone.
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 guidance on when to use this versus docker_restart, or that the container must already exist and be stopped. No prerequisites, no exclusions, no named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_statsB
Show a one-shot snapshot of container CPU and memory usage.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose one real behavioral trait: the call is a one-shot snapshot rather than a stream. It omits other behavior an agent needs, such as whether stats cover every container on the host, whether any filtering is possible, and whether the daemon/host must be reachable.
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 front-loaded sentence with no filler; the key qualifier ('one-shot snapshot') is placed immediately after the verb, so the reader gets scope and behavior in one pass.
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?
For a simple one-parameter read tool with no output schema, the description is minimally adequate but thin: it never indicates the granularity (per-container vs. aggregate), the metrics returned, or how results are scoped to the host. Nothing is wrong, but more could reasonably be said.
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 100% and the single 'host' parameter is fully documented in the schema (opsgate config host name, optional). The description adds no extra meaning about the parameter, so the baseline 3 applies.
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 (Show) and resource (container CPU and memory usage), and the phrase 'one-shot snapshot' distinguishes it from streaming/log-tailing siblings like docker_logs. It does not explicitly name a sibling, but the snapshot framing makes its role against docker_ps/docker_inspect reasonably clear.
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 explicit when-to-use guidance: nothing says whether it covers all containers or one, when to prefer it over docker_ps, docker_inspect, or process_top, or what prerequisites exist. The only hint is the implicit contrast of 'one-shot' versus continuous monitoring.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docker_stopC
Stop a running Docker container.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| container | Yes | container name or ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does not disclose whether the stop is graceful (SIGTERM) or forced, what happens on an already-stopped container, whether state is preserved, or whether elevated permissions are required. For a mutating lifecycle tool this is a significant gap.
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 efficient, front-loaded sentence with no wasted words. It is arguably too terse, but that is a completeness issue rather than a conciseness flaw.
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?
For a mutation tool with no annotations and no output schema, the description is inadequate: it omits behavioral outcome, error conditions, and any routing to related lifecycle tools. An agent knows what it does but not how it behaves or when to choose it.
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 100%, so both parameters (host and container) are already fully documented in the schema. The description adds no syntax, format, or defaulting detail beyond that, so the baseline 3 applies.
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 (Stop) and resource (Docker container), scoping to a 'running' container. It is clearly separable from docker_start and docker_restart by name and semantics, though it never explicitly names a sibling or the boundary between stopping vs restarting.
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 phrase 'a running container' weakly implies the operation only applies to running containers, but there is no explicit when-to-use, when-not-to-use, or alternative guidance. No mention of when to prefer this over docker_restart or service_stop.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_grepB
Search a file for a fixed string. Useful for finding an error in a large log.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| path | Yes | absolute file path to search | |
| lines | No | maximum matching lines to return (default 100, max 1000) | |
| pattern | Yes | fixed string to search for (not a regular expression) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It mentions the fixed-string (non-regex) semantics, but that only restates the schema; it discloses nothing about case sensitivity, permissions, multi-host behavior, or what matching output looks like, which are exactly the traits an agent needs here.
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 short sentences with zero filler, and the core action (search a file for a fixed string) is front-loaded before the use-case hint. Nothing could be cut without losing 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?
For a simple read-only grep the essentials are present, but with no annotations and no output schema, the description should say something about the return shape (matching lines, line numbers, truncation at the lines cap). Those gaps leave an agent guessing about 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 100%, so all four parameters (host, path, lines, pattern) are already documented in the schema, including the fixed-string caveat and the lines default/max. The description adds no parameter meaning beyond that, so the baseline 3 applies.
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+resource: search a file for a fixed string. It is distinguishable from file_read (read whole file) and journal/docker log tools by the 'search a file' framing, but it never names or contrasts any sibling, 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?
'Useful for finding an error in a large log' implies a use case, but offers no when-not guidance and never mentions alternatives such as file_read for whole-file reads or journal_errors/docker_logs for log search over other sources. Usage is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_readA
Read a file under one of the configured allowed paths (see files.allow_paths).
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| path | Yes | absolute path of the file to read | |
| lines | No | read only the last N lines instead of the whole file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It does disclose a meaningful trait — reads are sandboxed to configured allowed paths — which is genuine context beyond the schema. It says nothing about large-file behavior, encoding, truncation, or error cases, so gaps remain for a tool with zero annotation coverage.
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 front-loaded sentence that names the action and the key constraint with zero filler. Nothing in it is redundant with the title or schema.
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?
For a simple three-parameter read with full schema coverage and no output schema, the core is covered. The absence of any behavioral notes on file size, encoding, or failure modes leaves the definition merely adequate given there are no annotations to fill those gaps.
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 100%, so host, path, and lines are all documented in the schema itself; the description adds no format or syntax detail beyond that. Baseline 3 is appropriate when the schema does the heavy lifting.
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 ('Read a file') and adds the scoping constraint of configured allowed paths. It does not explicitly contrast with siblings like file_grep or dir_list, but the verb/resource is unambiguous enough that an agent can distinguish a plain read from a content search or a directory listing.
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 implies when the tool is applicable via the 'allowed paths' constraint (see files.allow_paths), which is a real precondition. However, it gives no guidance on when to prefer file_read over file_grep for content lookups, nor any exclusion conditions, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
journal_errorsA
Show recent error-and-worse journal entries across the system — a fast triage starting point.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full behavioral burden. "Show" implies a non-mutating read and the severity filter and system-wide scope are genuinely useful disclosure, but "recent" is undefined (no time window or entry cap) and the description never says how the optional host default is resolved or whether results are truncated.
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 sentence, zero filler, with the resource and its filter front-loaded before the triage framing. Nothing could be removed without losing 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?
Low-complexity read tool with one optional parameter and no output schema, so the description need not explain returns. It is nearly complete, with the only real omissions being the "recent" window and any routing hint toward journal_tail.
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 100% and the single host parameter is fully documented in the schema, so baseline 3 applies. The description adds no extra meaning about host, though for a one-optional-param tool little more is needed.
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 (Show) plus resource (journal entries) with a server-side filter (error-and-worse) and scope (across the system). This implicitly separates it from journal_tail, but the sibling is never named, so the distinction rests on the reader inferring what journal_tail does.
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?
"A fast triage starting point" hints at the intended use case and gives the agent a reason to reach for this first, but there is no explicit when-not guidance and no mention of journal_tail as the alternative for unfiltered/following log inspection. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
journal_tailB
Read recent systemd journal entries, optionally filtered by unit, time and priority.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| unit | No | systemd unit to filter by; omit for the whole journal | |
| lines | No | how many trailing lines (default 100, max 2000) | |
| since | No | systemd time expression such as '1 hour ago' or '2026-07-29 10:00' | |
| priority | No | minimum priority: emerg, alert, crit, err, warning, notice, info, debug |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden; it does make the read-only nature explicit via 'Read', which is the key behavioral fact. However, it discloses nothing beyond that — no return format, no behavior when the host is unreachable, no indication that line counts are capped (the max of 2000 lives only in the 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 well-formed sentence with the action and scope front-loaded and no filler. Nothing in it is wasted text.
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?
For a simple read-only log tail with five fully documented parameters and no output schema, the description covers the essentials. It could add a note on output shape or pagination behavior for very large journals, but nothing critical to invoking it correctly is missing.
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 100%, so every parameter (including host and lines, which the description never mentions) is already documented in the schema. The description restates three of the five filters without adding syntax or format detail beyond what the schema provides, so the baseline 3 applies.
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 (Read) and resource (systemd journal entries) with scope (recent) and filter dimensions (unit, time, priority). It is clear what the tool does, though it never names or distinguishes itself from the sibling journal_errors, leaving that differentiation to be inferred from the priority parameter.
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 phrase 'optionally filtered by unit, time and priority' hints at how to call it, but there is no when-to-use guidance, no prerequisites (e.g. host availability), and no routing to journal_errors for an error-only view. The agent must guess which of the two journal tools fits a given request.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listening_portsB
List listening TCP/UDP sockets and the processes owning them.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses what is returned (sockets plus owning processes), which implies a read-only operation, but says nothing about elevated privileges typically needed to resolve process owners, output format, or whether UDP results differ from TCP.
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 front-loaded sentence with no filler. Every word earns its place and the resource/return is stated up front.
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?
For a one-parameter, read-only listing tool with no output schema, the description is largely sufficient. A brief note about privilege requirements or output shape would make it complete.
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?
Only one parameter and schema description coverage is 100%, so the schema already fully documents 'host' and its opsgate-config source. The description adds no syntax, default, or semantics beyond that, so the baseline 3 applies.
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 ('List') and a precise resource ('listening TCP/UDP sockets and the processes owning them'), which is clearly distinct from siblings like process_top, docker_ps, or service_list. It does not explicitly say how it differs from those siblings, so it stops 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?
No when-to-use, when-not-to-use, or alternative tools are named. The agent must infer that this is the right tool for port/process-ownership questions rather than, say, service_status or process_top.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nginx_reloadA
Reload nginx. Validates the configuration first and refuses to reload a broken config.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose one genuinely valuable, non-obvious trait: a pre-validation gate that aborts on bad config. It leaves other significant behaviors unstated, such as whether reload causes connection drops, whether elevated privileges are required, or how a rejected config is reported back.
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 short sentences, the action stated first and the safety guarantee immediately after. No filler, no restatement of the tool name.
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?
For a single-optional-parameter tool with no output schema and no annotations, the description covers the core action and the main safety behavior. It is only slightly thin on failure semantics — an agent cannot tell whether the nginx -t output is surfaced when a reload is refused.
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?
There is one optional parameter (host) and schema description coverage is 100%, so the schema already explains that it comes from the opsgate config and defaults when omitted. The description adds nothing about host selection or multi-host behavior, which is the expected baseline when the schema does the work.
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 verb and resource (reload nginx) and adds scope-defining behavior (validates first). It implicitly separates itself from the sibling nginx_test, which only validates, but never names that sibling or any other, so the differentiation is inferred rather than stated.
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 explicit when-to-use, when-not-to-use, or alternative selection guidance. The claim that it validates first and refuses a broken config implicitly tells the agent it can use this instead of a separate test step, which is useful implied guidance but falls short of explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nginx_testA
Validate the nginx configuration (nginx -t) without applying it.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses the key trait that the config is not applied (non-mutating), but says nothing about permission requirements, whether a failure surfaces as an error or a validation message, or how results are returned.
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 tight sentence with the action front-loaded and no filler. Every word earns its place, and the non-applying constraint is stated immediately.
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?
For a zero-required-parameter, read-only validation tool with full schema coverage and no output schema, the description covers the essentials: what runs and that it doesn't mutate state. Only the failure/reporting behavior is left unstated, 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?
Schema description coverage is 100% and the single 'host' parameter is fully documented in the schema, including the 'omit for default host' behavior. The description adds no parameter meaning beyond that, so the baseline 3 applies.
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 verb and resource — 'Validate the nginx configuration (nginx -t)' — and clarifies the scope with 'without applying it', which implicitly separates it from nginx_reload. It stops short of naming the sibling outright, so it's clear but not maximally differentiating.
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?
'Without applying it' implies this is the dry-run/pre-check step, but the description never states when to prefer it over nginx_reload or service_reload, nor any prerequisite such as needing a valid config file present. Usage is implied rather than instructed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
process_topB
List the top processes on a host by CPU or memory usage.
| Name | Required | Description | Default |
|---|---|---|---|
| by | No | sort processes by cpu or mem (default cpu) | |
| host | No | target host name from the opsgate config; omit for the default host | |
| limit | No | how many processes to return (default 15, max 50) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'List' implies a read-only operation, but the description does not explicitly state safety, required permissions, rate limits, or what the return format looks like.
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, front-loaded sentence with no wasted words. It states the core purpose efficiently.
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?
For a simple read tool with full schema coverage and no output schema, the description is minimally adequate. It omits usage context relative to sibling process-listing tools and lacks any behavioral disclosure, but the schema supplies all parameter details.
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 100%, so the schema already documents all three parameters including defaults and max. The description adds no parameter meaning beyond what the schema provides, so the baseline of 3 applies.
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 ('List'), resource ('top processes'), scope ('on a host'), and sort criterion ('by CPU or memory usage'). It is clear but does not explicitly distinguish itself from container-oriented siblings like docker_ps or compose_ps, which also list processes.
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 when-not-to-use conditions, and no alternatives named. The agent must infer that this is for host-level process inspection rather than container process inspection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_listB
List systemd services on a host, optionally filtered to running or failed units.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| state | No | filter by state: running, failed, or all (default running) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. 'List' reasonably implies a read-only, non-destructive operation, which is the key trait, but nothing is said about permissions/auth needs, output volume, or pagination. It conveys the safety profile implicitly rather than explicitly.
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 tight sentence with the resource front-loaded and the optional filter appended. Nothing is wasted and there is no filler.
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?
For a low-complexity read tool with two fully documented parameters and no output schema, the description covers the essentials. Minor gaps: it doesn't note the default state or the 'all' value the schema supports, and with no output schema an agent gets no hint of what a listing returns.
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 100%, so both parameters (host and state) are already fully documented in the schema, including the default host and the state default of running. The description adds only the 'running or failed' filter framing and actually omits the 'all' option the schema lists, so it adds no meaningful semantics beyond the schema.
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 (List) and resource (systemd services on a host), immediately distinguishing it from mutation siblings like service_restart or service_stop. It does not explicitly name service_status as the single-unit alternative, but the list scope is unambiguous.
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 describes the filter capability but gives no when-to-use guidance: it never says to reach for this over service_status for a single unit, nor when each filter state is appropriate. Usage is only implied by the tool name and verb.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_reloadA
Reload a systemd service's configuration without restarting it.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| name | Yes | systemd unit name, for example nginx or docker.service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the key behavioral trait — the service is not restarted, so the reload is non-disruptive — but says nothing about required privileges (systemd/root access), whether the unit must be running, or what happens on reload failure.
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 sentence with the scope and the critical non-restart distinction front-loaded. No filler, nothing that fails to earn its place.
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?
Parameters are fully covered by the schema and no output schema exists, so little is required. However, for an unannotated mutation tool, the absence of permission requirements and failure semantics leaves a meaningful gap for an agent deciding whether it can safely call it.
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 100%: 'name' and 'host' are both fully documented in the schema, including the opsgate-config sourcing of host. The description adds no syntax or format detail beyond that, so the baseline 3 applies.
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?
Specific verb (reload) plus resource (systemd service configuration) with the key differentiator from the closest sibling stated explicitly: 'without restarting it' contrasts directly with service_restart. It does not clarify its relationship to nginx_reload, a specialized variant, but the core purpose is unambiguous.
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 'without restarting' phrasing implies when to prefer this over service_restart (avoiding downtime), but the description never states a when-to-use rule or names the alternative tool. Usage is inferable rather than guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_restartC
Restart a systemd service.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| name | Yes | systemd unit name, for example nginx or docker.service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does not disclose that a restart implies downtime (stop then start), that elevated privileges are typically required, or what happens to in-flight connections or dependents. For a mutation tool with zero annotation coverage this is a meaningful gap.
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 short sentence with no filler, and the verb+resource is front-loaded. It is efficient, though its brevity contributes to the transparency gaps noted elsewhere rather than being a virtue in itself.
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?
For a mutation tool with no annotations and no output schema, the description should at least mention privileges, downtime, or side effects. The simple two-parameter surface limits the damage, but the definition leaves an agent without the operational context needed to invoke a restart safely.
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 100%, and both parameters (host, name) are documented in the schema with examples. The description adds no syntax, format, or default information beyond what the schema already provides, so the baseline of 3 applies.
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?
"Restart a systemd service" states a specific verb (restart) and resource (systemd service), which cleanly separates it from siblings like service_start, service_stop, service_reload, and service_status. It does not explicitly name those siblings, but the verb alone is unambiguous enough to route correctly.
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 is given. With siblings service_reload, service_start, and service_stop present, an agent needs to know when a full restart is preferable to a reload or a start/stop pair, and the description offers nothing. Usage must be inferred entirely from the verb.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_startB
Start a stopped systemd service.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| name | Yes | systemd unit name, for example nginx or docker.service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden and falls short. It does not state whether the operation is idempotent, whether elevated permissions/sudo are required, whether it enables the unit at boot, or what happens on failure or if the service is already running.
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 six-word sentence that front-loads the verb and the state precondition. Nothing is padded or redundant.
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?
For a simple two-parameter mutation with a fully documented schema, the basics are covered, but with zero annotations the description should disclose permission requirements and behavior when the service is already running. Those operational facts are missing.
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 100% – both 'host' and 'name' are documented with format examples in the schema. The description adds no syntax or defaulting detail beyond what the schema already supplies, so the baseline 3 applies.
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 (Start) and resource (systemd service), with the added precondition that the target is stopped. It implicitly separates itself from sibling mutations like service_restart and service_stop, though it does not name those alternatives.
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 phrase 'a stopped service' implies the usage condition, but there is no explicit when-to-use guidance or routing to service_restart/service_stop for other states. Usage must be inferred from the state adjective alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_statusB
Show the status of one systemd service, including recent log lines.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| name | Yes | systemd unit name, for example nginx or docker.service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present the description carries the full burden. 'Show' correctly implies a non-destructive read, and it discloses a real behavioral trait — that recent log lines are bundled into the response — but it says nothing about permissions, failure behavior for unknown/missing units, or how many log lines are returned.
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 front-loaded sentence with no filler, and the scope ('one service') plus the extra payload ('including recent log lines') both land immediately.
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?
For a two-parameter read-only diagnostic with no output schema, the description covers what the tool acts on and what it returns (status plus log lines). Given the absence of annotations it could say more about error cases, but nothing critical for correct invocation is missing.
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 100%, so the schema already documents both 'host' (default host fallback) and 'name' (unit name with examples); the description adds no further parameter meaning. Baseline 3 applies when the schema does all the work.
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 ('Show the status of one systemd service') and scopes it to a single unit, which implicitly separates it from the plural sibling service_list. It never names an alternative, so it stops 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?
The only usage signal is implied by the verb 'show' — there is no stated when-to-use, no prerequisite (does the unit need to be running?), and no mention of siblings like journal_tail or journal_errors that an agent might otherwise pick for log inspection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_stopC
Stop a running systemd service.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host | |
| name | Yes | systemd unit name, for example nginx or docker.service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden, and it says almost nothing: no indication that stopping a service is disruptive, whether it requires root/sudo, whether it blocks until shutdown completes, or how it handles dependent units. The single adjective 'running' is the only behavioral hint.
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?
One front-loaded sentence starting with the action verb, with zero filler or redundancy. Nothing could be trimmed without losing the verb or resource.
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?
This is a privileged mutation (stopping a live service) with no annotations and no output schema, yet the description omits permissions, disruption risk, and side effects. The schema covers inputs adequately, but the behavioral surface needed for safe invocation is essentially absent.
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 100%, so both 'host' and 'name' are already documented with examples. The description adds no parameter meaning beyond the schema, which is the expected baseline when the schema does the heavy lifting.
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 (stop) and resource (systemd service), which naturally distinguishes it from container siblings like docker_stop and from service_start/service_restart. No explicit sibling routing is given, but the resource qualifier makes the target unambiguous.
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 guidance, no prerequisites (e.g. elevated privileges), and no mention of alternatives such as service_restart or docker_stop. Usage is only inferable from the name and the word 'systemd'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_infoB
Show kernel, uptime, load average and memory usage for a host.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | target host name from the opsgate config; omit for the default host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'Show' plus the enumerated read-only metrics reasonably implies a non-mutating inspection call, but it says nothing about permissions required, behavior on an unreachable host, or timing/rate characteristics.
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?
One sentence, front-loaded with the verb and the returned fields, with zero filler. Every word earns its place.
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?
For a simple read-only inspection tool with a fully documented single parameter and no output schema, the description lists the concrete return fields (kernel, uptime, load, memory), which usefully compensates for the missing output schema. Only the absence of any usage framing keeps it short of complete.
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 single 'host' parameter is fully documented in the schema (100% coverage), including the default-host fallback. The description adds no host syntax, formatting, or resolution detail, so the schema does the work and baseline 3 applies.
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 ('Show') and enumerates the exact resources returned: kernel, uptime, load average, memory usage. This content list distinguishes it functionally from siblings like disk_usage or process_top, though it never names or explicitly contrasts those alternatives.
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 guidance on when to reach for system_info versus neighbors such as process_top, service_status, or disk_usage. The only usage-like cue is the host parameter's 'omit for the default host' behavior, which lives in the schema rather than the description.
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.
25 tool updates
v0.1.2- First observed
compose_ps - First observed
dir_list - First observed
disk_usage - First observed
docker_inspect - First observed
docker_logs - First observed
docker_ps - First observed
docker_restart - First observed
docker_start - First observed
docker_stats - First observed
docker_stop - First observed
file_grep - First observed
file_read - First observed
journal_errors - First observed
journal_tail - First observed
listening_ports - First observed
nginx_reload - First observed
nginx_test - First observed
process_top - First observed
service_list - First observed
service_reload - First observed
service_restart - First observed
service_start - First observed
service_status - First observed
service_stop - First observed
system_info
TDQS
Scored across 25 tools
Most tools target a clearly distinct resource+action (docker_start/stop/restart, service_start/stop/restart/reload, nginx_test/reload). A couple of pairs overlap, notably journal_errors vs journal_tail (the former is just a filtered convenience view) and service_status's embedded log lines vs journal_tail, but descriptions mostly disambiguate.
Strong resource_action pattern throughout (docker_*, service_*, file_*, journal_*, nginx_*), so an agent can predict names. Minor deviations: compose_ps uses 'ps' like docker_ps while systemd uses service_list, and a few tools (disk_usage, listening_ports, system_info) are descriptive rather than verb-form.
25 tools is at the heavy end but spread across seven genuine domains (Docker, Compose, systemd, nginx, files, journal, network/system), so each tool earns its place. It sits just above the comfortable 3-15 band but the breadth justifies it.
Covers the core lifecycle for containers and services (list/status/start/stop/restart/reload/inspect/logs/stats) plus diagnostics and config validation for nginx. Gaps are minor and largely intentional (no file write, no docker exec, no compose up/down), which an agent can work around via service/file tools.
Maintenance
Related MCP Connectors
- emisarOAuthdev.emisar
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Security gateway for AI agents: policy, approval, and audited execution, no secrets shared.
Zero-trust gateway for AI agents: score tool calls, verify agent cards, enforce policy, audit.
Context and control for any AI. Agent identity, scoped access, and proof across tools.
Related MCP Servers
- AlicenseAqualityBmaintenanceLocal zero-trust permission gateway for AI agents. Enforces policy-based tool authorization, human approvals, scoped permissions, and cryptographically verifiable audit logs.466 PyPI5Apache 2.0
- AlicenseAqualityCmaintenanceHuman-in-the-loop approval gateway for agent tool calls: agents request, policies decide, humans approve via Slack/Discord/web — with an OWASP-LLM-Top-10-tagged audit trail. Self-hostable.1018 npm33MIT
- AlicenseBqualityCmaintenanceEnables AI tools to perform server operations such as log inspection, system monitoring, code management, Nginx and certificate management, with support for local and remote SSH modes and built-in security controls.2353 npmMIT
- AlicenseAqualityBmaintenanceEnables AI agents to securely connect to and manage remote servers via SSH, with tools for running commands, file operations, log inspection, service management, and system monitoring under configurable access controls and audit logging.1211 npm1MIT