opnsense-guard-mcp
This MCP server provides read-only visibility, diagnostics, and security auditing for an OPNsense firewall.
Inspect system firmware/update status, host information, uptime/load, resources, and services.
Run a health/posture check that flags installed-but-not-running security services.
Check Suricata IDS/IPS status, settings, and alert-file liveness.
Review firewall rules, individual rule details, aliases, recent firewall logs, and active connection states.
View interfaces, ARP table, routing table, and DHCP leases across Kea, ISC, and dnsmasq.
Read recent OPNsense system logs.
Fetch any allowlisted OPNsense API path with
raw_get, under read-only constraints.Show the server's policy limits before planning changes.
Perform a quick security audit for risky rules and IDS issues.
All listed tools are marked read-only, idempotent, and non-destructive.
Provides a safety-first MCP server for OPNsense firewalls, with read-only tools for firewall rules and aliases, interfaces, services, ARP and routing tables, firewall states and logs, system information/resources, Suricata status, and DHCP leases. It also supports policy-checked planning and applying of firewall rule and alias changes, including diffs, human approval, verification, automatic revert, rollback, and a hash-chained audit log.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@opnsense-guard-mcpshow me the active firewall rules on WAN and recent blocked traffic"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
opnsense-guard-mcp
A safety-first MCP server for OPNsense 26.7+.
Read-only by default. Every write is planned, policy-checked, logged, and auto-reverted unless you confirm it.
Status: alpha. Tested against a live OPNsense 26.7.4 with least-privilege API users: read tools, policy file, change planning with diffs, applying changes with verification and automatic revert, crash recovery, and a hash-chained audit log, over stdio or authenticated HTTPS. See DESIGN.md.
Not affiliated with Deciso B.V. "OPNsense" is a trademark of Deciso B.V.
What makes it different
opnsense-guard-mcp | |
Default mode | read-only |
Read path | GET, plus POST to exactly two search endpoints (states, rules) with a fixed three-field body; path allowlist, verb denylist, traversal/encoding rejected, redirects not followed |
Writes | separate API user, exact endpoint allowlist, plan → policy check → human approval → apply → verify → auto-revert unless confirmed |
Rollback on 26.7+ | own object-level snapshots + revert (the savepoint API is gone in 26.7); survives restarts |
Guardrails | allowlist policy file: interfaces, networks, rule limits, anti-lockout |
Audit | hash-chained JSONL ( |
Transport | stdio, or Streamable HTTP that always needs a bearer token; optional TLS / mTLS |
Dangerous tools | none exist: no reboot, firmware, service control, SSH or XML edits |
Related MCP server: OPNsense MCP Server
Quick start (read-only)
In OPNsense (System → Access → Users), create a user with a scrambled password, no group (not
admins) and these privileges, then create an API key for it. Skip any that aren't installed; the matching tool just reports "forbidden".Privilege
Used by
Firewall: Rules [new]
firewall_rules,firewall_rule_get, planningFirewall: Aliases (view-only)
firewall_aliases, planningStatus: Interfaces
interfacesStatus: Services
service_listDiagnostics: ARP Table
arp_tableDiagnostics: Routing tables
routing_tableDiagnostics: Show States
firewall_statesDiagnostics: Logs: Firewall: Live View
firewall_logDiagnostics: Logs: System
system_logLobby: Dashboard
system_information,system_resources, health probeServices: Intrusion Detection
suricata_*Services: DHCP: Kea(v4) / Services: Dnsmasq DNS/DHCP: Settings / Status: DHCP leases (ISC)
dhcp_leases: only the one you useSystem: Firmware (optional)
system_status. It also allows installing updates, so leave it out unless you need it.Most OPNsense privileges are not view-only (Firewall: Aliases is an exception): several of these also allow edits through the API. The server only sends GET requests with this key, except a search POST to two exact endpoints (
diagnostics/firewall/query_states,firewall/filter/searchRule) with a body it builds itself (current,rowCount,searchPhrase); OPNsense answers those lists properly only over POST. Still keep the list short: the privileges are what OPNsense itself enforces.Install:
pipx install opnsense-guard-mcpConfigure (copy
.env.exampleto.env, or set env vars):OPNSENSE_URL=https://firewall.example.internal OPNSENSE_API_KEY=... OPNSENSE_API_SECRET=... OPNSENSE_CA_BUNDLE=/path/to/firewall-ca.pem # or OPNSENSE_VERIFY_SSL=falseCheck the config (does not contact the firewall):
opnsense-guard-mcp --checkAdd to your MCP client, e.g. Claude Code:
claude mcp add opnsense -- opnsense-guard-mcp --env-file /path/to/.env
HTTP mode (shared server)
HTTP never runs without authentication. The server refuses to start if:
there are no tokens, or
it binds to a non-loopback address without TLS (override with
MCP_ALLOW_PLAINTEXT=trueonly behind a TLS proxy).
Create a token per client. It is printed once; only its SHA-256 is stored:
opnsense-guard-mcp token new --name laptop --scope readtoken listshows names and scopes;token revoke --name laptoptakes effect on the next request, no restart needed.Start the server:
MCP_TRANSPORT=http MCP_HOST=0.0.0.0 MCP_PORT=8848 \ MCP_TLS_CERT=server.pem MCP_TLS_KEY=server.key \ opnsense-guard-mcpPoint the client at
https://<host>:8848/mcpwith headerAuthorization: Bearer <token>.
Variable | Default | Purpose |
|
| listen address |
|
| token hashes |
| – | serve HTTPS |
| – | require client certificates (mTLS) |
|
| accepted |
| none | browser origins allowed; any other |
|
| requests per token per minute |
|
| allow plain HTTP on a non-loopback address |
Repeated failed logins from one IP (10 a minute) are throttled with HTTP 429.
Claude Code and a private CA: Claude Code (Node) ignores the Windows/macOS
certificate store for MCP servers. Point NODE_EXTRA_CA_CERTS at your CA file
in the env block of ~/.claude/settings.json, then fully quit and reopen
Claude, or the connection fails with UNABLE_TO_VERIFY_LEAF_SIGNATURE.
Running in Docker
The image runs as a non-root user and keeps its audit log, change journal and
tokens in /data.
docker build -t opnsense-guard-mcp .
# stdio, for a local MCP client
docker run -i --rm --env-file .env -v guard-data:/data opnsense-guard-mcp
# HTTP: create a token, then serve (put the TLS files in the volume or mount them)
docker run --rm -v guard-data:/data opnsense-guard-mcp token new --name laptop --scope read
docker run -d --name opnsense-guard --env-file .env -v guard-data:/data -p 8848:8848 \
-e MCP_TRANSPORT=http -e MCP_HOST=0.0.0.0 -e MCP_ALLOWED_HOSTS=mcp.example.internal:8848 \
-e MCP_TLS_CERT=/data/tls/server.pem -e MCP_TLS_KEY=/data/tls/server.key \
opnsense-guard-mcpMount a policy file and set OPNSENSE_GUARD_POLICY to enable writes. Stop the
container with docker stop (not kill) so unconfirmed changes are reverted.
Policy and planning
Without a policy.yaml the server is read-only. To enable planning, copy
policy.example.yaml to policy.yaml (or point
OPNSENSE_GUARD_POLICY at it) and edit it. Unknown keys are an error.
Planning tools (rule_plan, alias_plan) read the current state, apply every
policy check, and return a diff plus the reasons for any refusal. They never
change the firewall. Example result for a refused rule:
+ [wan] pass in inet any from any to any '[mcp]'
interface 'wan' is not in the allowed interfaces
any -> any pass rules are forbidden
inbound pass rules on WAN are forbidden
every rule written by this server must have logging onBuilt-in guardrails: only listed interfaces/actions/directions; every IP inside
allow_networks; no any→any pass, WAN inbound pass, floating rules or rules
without logging; edit only rules tagged [mcp] (unless only_modify_own: false);
anti-lockout (no block rule that matches this server's own IP, and only new
pass rules on the interface it reaches the API through). A new block or reject
rule there is allowed when the same plan adds a pass rule with a lower
sequence that provably lets every MCP host reach the API (source covers the
host IP, destination any/(self)/the API IP, TCP, port covers the API port);
both rules need a sequence.
Applying changes
Change tools appear only when both the policy is in write mode and a second, write-capable API user is configured:
OPNSENSE_WRITE_API_KEY=... # a different OPNsense user than the read one
OPNSENSE_WRITE_API_SECRET=...Give that user exactly two privileges: Firewall: Rules [new] and
Firewall: Alias: Edit, no group. (Plain Firewall: Aliases is view-only:
it allows search/get but not addItem/setItem/delItem/reconfigure.) Over HTTP, the
change tools need a token with --scope write.
The flow:
rule_plan/alias_plan→ diff +plan_id(changes nothing).change_apply(plan_id)→ asks the human to approve the diff (MCP elicitation where the client supports it; otherwise the tool returns the diff and must be called again withuser_confirmed=true). Then it re-reads the firewall (refuses if anything drifted since planning), stores the before-state, writes, applies, reads everything back to verify, and checks the API is still reachable. Any failure → everything is reverted.The change is pending: it is reverted automatically after
confirm_timeout_s(default 60 s) unlesschange_confirmis called.change_rollbackundoes a pending or confirmed change. A revert never overwrites an object someone else edited meanwhile (statusconflict).
Unconfirmed changes are also reverted when the server stops and, after a
crash, when it starts again. Only one change can be open at a time, and
max_changes_per_hour is enforced.
Limits, stated plainly
The revert timer runs on the MCP host. If a change cuts that host off from the firewall API, the revert cannot reach it. The anti-lockout policy and the health probe right after apply exist to prevent and catch this, but they are not the same as the firewall-side savepoint older OPNsense versions had.
Without elicitation,
user_confirmed=trueis the model's word that the user agreed. The audit log records which method was used.
Audit log
Every plan (allowed or refused) and server start is written to
$OPNSENSE_GUARD_DATA_DIR/audit.jsonl (default ./data). Each line holds the
hash of the previous one, so edits, deletions and reordering are detectable:
opnsense-guard-mcp audit verify
opnsense-guard-mcp audit tail -n 20Credentials are never written to it.
Tools (read-only)
system_status, system_information, system_resources, service_list,
posture_check, suricata_status, suricata_settings, suricata_alert_status,
firewall_rules, firewall_rule_get, firewall_aliases, firewall_log,
firewall_states, system_log, interfaces, arp_table, routing_table,
dhcp_leases, raw_get, policy_show, security_audit.
In write mode also: rule_plan, alias_plan, plan_get, audit_tail.
With write credentials also: change_apply, change_confirm, change_rollback,
change_list, change_get.
firewall_rules returns one line per rule (50 by default) so a full ruleset
fits in a chat; pass detail=true for the raw OPNsense rows, or use
firewall_rule_get for one rule.
Over HTTP, a read token still sees the change tools in the tool list, but
calling one is refused (needs a token with scope 'write').
Development
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check . && mypy && pytestSecurity
See SECURITY.md. Please report vulnerabilities privately.
Licence
MIT. See LICENSE.
Available Tools
21 toolsarp_tableARead-onlyIdempotent
ARP table: IP to MAC mappings currently known to the firewall.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so safety and idempotency are covered. The description adds that the data is 'currently known to the firewall,' implying dynamic state, but does not describe freshness guarantees, return format, or other behavioral details.
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?
The description is a single, front-loaded sentence with no redundant or filler text. Every element identifies the resource and its contents.
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 parameterless, read-only tool with annotations covering safety and no output schema, the description is complete enough. It states the resource and what it returns without needing further elaboration.
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 are zero parameters, so parameter semantics are not a concern. The baseline score for a parameterless tool is 4.
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 identifies a specific resource, the ARP table, and states its contents as IP-to-MAC mappings known to the firewall. It is clearly distinct from siblings like routing_table and interfaces, though it does not explicitly use a verb such as 'list' or 'retrieve'.
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 gives no explicit guidance on when to use this tool versus alternatives such as routing_table, interfaces, or dhcp_leases. Usage is only implied by the resource name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dhcp_leasesARead-onlyIdempotent
Current DHCP leases across all backends (Kea, ISC dhcpd, dnsmasq).
Queries all three and reports which backend actually holds leases.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuine behavioral detail beyond that: this is a fan-out query across three backends that also reports which backend actually holds the leases — information an agent needs to interpret the result. It stops short of saying how partial backend failures are surfaced.
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, front-loaded with what is returned and followed by the aggregation behavior. Nothing is redundant with the annotations 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?
An output schema exists and annotations cover safety, so the description need not explain return values. The one unaddressed concern for a multi-backend query is what happens if a backend is unreachable (error vs. partial results), which the description leaves silent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-param tool 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 and resource ('Current DHCP leases') and narrows scope by naming the three backends covered (Kea, ISC dhcpd, dnsmasq). No sibling tool touches DHCP, so differentiation is implicit, but an agent knows exactly what this returns.
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 resource itself (ask for leases when you need lease data), and the second sentence hints that some backends may be empty. There is no explicit when-to-use/when-not guidance, and no alternatives named — though no DHCP alternative exists among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firewall_aliasesBRead-onlyIdempotent
Firewall aliases and their contents.
Args: search: optional text filter on alias name or description. limit: maximum aliases to return (1-1000).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| search | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds useful parameter semantics, but it does not describe return format, pagination behavior beyond the limit, or whether alias contents are expanded.
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?
The description is short, front-loaded, and wastes little space. The Args block is structured and readable, though the opening sentence is a fragment rather than an explicit action statement.
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 list tool with annotations and no output schema, the description covers selection and both parameters adequately. It only lightly describes what 'contents' means and does not explain the returned alias structure, which is 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 0%, but the description compensates by documenting both parameters: search filters on alias name or description, and limit caps results at 1-1000. It does not restate the default of 200, but the schema carries that.
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 resource and scope: firewall aliases plus their contents. It lacks an explicit verb such as 'list' and does not distinguish itself from siblings like firewall_rules or firewall_rule_get, but the purpose is clear enough for selection.
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?
It gives no when-to-use guidance, no exclusions, and no routing to alternatives such as firewall_rules. The implied use case is to inspect aliases, but that is left entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firewall_logBRead-onlyIdempotent
Recent firewall log entries (pass/block decisions).
Args: limit: number of log lines to return (1-1000). search: optional filter phrase (IP, port, interface, action).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| search | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds that results are 'recent' entries with pass/block decisions and that search filters across IP, port, interface, or action, but it does not state ordering (newest first?), truncation behavior, or how the search matches (substring vs token).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the resource and content in one line, followed by a compact args block. No filler, though the args block duplicates the parameter names rather than adding narrative around them.
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 log fetch with annotations covering safety and no output schema, the description supplies enough: what it returns, the size bound, and the filter dimensions. The remaining gaps (sort order, default limit of 100, result truncation) are minor, and the default is already in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% — the schema only carries types, titles, and defaults with no descriptions — so the description must compensate, and it largely does: it bounds limit to 1-1000 (a constraint absent from the schema) and enumerates what search can match (IP, port, interface, action). It stops short of saying whether search is a substring or multi-token match.
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-less but clear resource: 'Recent firewall log entries (pass/block decisions)' tells the agent exactly what data comes back. It implicitly distinguishes itself from siblings like system_log or firewall_states by naming the pass/block decision content, but never explicitly contrasts with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this versus system_log, firewall_states, or firewall_rules, all of which sit nearby in the sibling list. The agent must infer that this is the tool for reading log lines rather than general system logs or live connection state.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firewall_rule_getARead-onlyIdempotent
One filter rule by UUID, with all fields.
Args: uuid: rule UUID as shown by firewall_rules.
| Name | Required | Description | Default |
|---|---|---|---|
| uuid | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds that the full record is returned ("with all fields"), but says nothing about behavior when the UUID does not exist.
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 lines, with the outcome (one rule, all fields) front-loaded before the argument note. 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 one-parameter read tool with annotations covering the safety profile and no output schema, this is nearly complete; "with all fields" sets return expectations. The only gap is unspecified behavior for a missing or invalid UUID.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameter meaning, and it does: the single argument is a rule UUID and is sourced from the firewall_rules output. That is exactly the non-obvious information an agent needs to populate it.
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?
"One filter rule by UUID, with all fields" names a specific verb (retrieve) and resource (filter rule), scoped to a single record, which implicitly contrasts with the sibling firewall_rules list tool. The distinction is present but not stated as explicitly as it could be.
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 line "uuid: rule UUID as shown by firewall_rules" tells the agent to obtain the identifier from the list sibling, implying the list-then-fetch workflow. It stops short of stating when to use this versus firewall_rules or what to do when the UUID is unknown.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firewall_rulesARead-onlyIdempotent
The firewall filter ruleset, one line per rule.
Use firewall_rule_get for every field of one rule.
Args: search: optional text filter (interface, description, address). limit: maximum rules to return (1-1000). detail: return the full OPNsense rows instead of one-line summaries.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| detail | No | ||
| search | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a safe, idempotent read operation, so the bar is lower. The description still adds valuable behavioral detail: results are one-line summaries by default, and detail switches to full OPNsense rows, which tells the agent what it will actually receive.
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?
The definition is front-loaded with purpose, followed by the sibling routing guidance and then a compact Args block. Every line earns its place with no redundant or filler 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?
With no output schema, the description adequately explains the return shape (one-line summaries vs. full rows) and covers all three parameters. It could be slightly richer about ordering or pagination behavior, but it gives the agent enough to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does so well. It explains search as a text filter over interface, description, and address; limit as a 1-1000 cap on returned rules; and detail as a switch between one-line summaries and full OPNsense rows.
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 clearly identifies the resource (firewall filter ruleset) and its output shape (one line per rule), and it explicitly distinguishes itself from firewall_rule_get. However, it opens with a noun phrase rather than a specific verb, so it stops short of the strongest possible purpose statement.
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?
It explicitly names the alternative tool, firewall_rule_get, and the condition that selects it: when you need every field of one rule. That is strong routing guidance, though it doesn't cover when to prefer this tool over other firewall siblings like firewall_log or firewall_states.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firewall_statesBRead-onlyIdempotent
Active connection state table.
Args: limit: number of states to return (1-1000). search: optional filter on address or port.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| search | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds that these are *active* states (i.e., current, not historical), which meaningfully distinguishes it from the log tool, but it says nothing about whether the table is truncated, sampled, or how large the underlying table can be.
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?
Very short with the resource identified up front and parameters immediately after. The inline "Args:" block is slightly awkward inside a description but wastes no words.
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 only two optional params and no output schema, the definition covers the essentials, but it never indicates what fields a state entry contains or whether results are capped/paginated — information an agent needs to interpret an empty or truncated result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden, and it delivers: limit is given a range (1-1000) that the schema lacks, and search is explained as filtering on address or port. It omits the documented default of 25 and doesn't say what happens when more states exist than the limit.
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 phrase "Active connection state table" names the resource (live firewall connection states) but supplies no verb, so the agent must infer that this lists/returns entries. It is reasonably distinguishable from siblings like firewall_log (historical) and firewall_rules (configuration), but that distinction is left implicit.
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 instead of firewall_log, firewall_rules, or arp_table, and no stated prerequisites or exclusions. The agent must guess from the name alone whether this is the right tool for troubleshooting live connections.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
interfacesARead-onlyIdempotent
All network interfaces with status, addresses, and link state.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as read-only, idempotent, and non-destructive, so the safety profile is covered structurally. The description adds useful output context by listing status, addresses, and link state, but it does not discuss permissions, pagination, or other behavioral details.
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?
It is a single, front-loaded sentence with no filler. Every phrase contributes directly to what the tool returns.
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-parameter read-only tool with strong annotations and no output schema, the description is nearly complete: it identifies the resource and summarizes the returned fields. Additional detail about the response shape or filtering constraints would be needed for a 5.
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?
This tool takes zero parameters, so the baseline is 4. The description appropriately avoids inventing parameter semantics and instead focuses on the returned interface data.
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 clearly states the resource (network interfaces) and names the returned fields (status, addresses, link state), so the agent can identify it as a zero-parameter interface listing. It does not explicitly distinguish itself from nearby network siblings such as arp_table or routing_table.
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 or when-not-to-use guidance is provided, and no alternatives are named. With many adjacent network and firewall tools in the sibling list, the agent is left to infer when this tool is the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
policy_showARead-onlyIdempotent
What this server is allowed to change: mode, interfaces, networks, limits.
Read this before planning a change so you know the limits.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds genuine context beyond that: this is a prerequisite check whose result constrains what changes are permissible, which an agent cannot infer from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the subject scope front-loaded and the usage instruction second. Nothing repeats the title or wastes a clause.
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 parameters, an output schema present, and annotations covering the safety profile, the only real job is purpose plus timing, and both are delivered. Minor gap: it does not clarify whether the output is the enforced policy versus the editable policy definition, which matters before planning a change.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline is 4. The enumerated policy categories describe the returned content rather than arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource and its contents concretely (mode, interfaces, networks, limits) and frames it as a read of enforced policy, which separates it from operational siblings like system_status or interfaces. It never states a verb such as 'returns' or 'shows the current policy', so the read nature comes from the name and annotations rather than the prose.
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?
'Read this before planning a change so you know the limits' gives a clear, explicit precondition for calling it. It stops short of naming an alternative or stating when not to call it, but with an all-read sibling set the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
posture_checkARead-onlyIdempotent
Health snapshot: system, services, IDS state.
Flags security-relevant services that are installed but not running.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds real value beyond that by disclosing the coverage domains and the specific flagging rule for installed-but-not-running security services. It stops short of anything else behavioral, such as how deep the IDS check goes or whether missing services cause errors.
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 the domain coverage front-loaded and the salient flagging behavior immediately after. It is efficiently sized, though the second sentence is a sentence fragment and the first reads as a noun-phrase label rather than a verb statement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return structure need not be explained, and with no parameters the call mechanics are trivial. What it covers plus the one notable anomaly it reports is enough for an agent to decide to call it; only the relationship to security_audit and the depth of each domain check remain unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the baseline there is nothing the description needs to disambiguate, and it correctly adds no parameter chatter. It could have stated that no scoping (host, time range, service filter) is possible, which would have set expectations, but the omission is minor for a zero-argument call.
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 concrete resource (a health snapshot spanning system, services, and IDS state) and its distinguishing behavior: flagging security-relevant services installed but not running. That implicitly separates it from the narrower siblings system_status, service_list, and suricata_status, though it never names them explicitly, so the differentiation is left 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?
Usage is only implied: an agent can infer this is the 'give me an overall picture first' tool because it aggregates three domains, while the siblings cover each individually. There is no explicit when-to-use statement, no exclusion such as 'use security_audit for a full compliance sweep', and no note on cost or whether it is safe to call frequently.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
raw_getBRead-onlyIdempotent
GET any allowlisted OPNsense API path.
The same read-only rules apply (prefix allowlist, verb denylist, no traversal), so this cannot change firewall state.
Args: path: API path beginning with /api/, e.g. /api/core/firmware/info
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, and the description usefully goes further by naming the enforcement mechanisms (prefix allowlist, verb denylist, no traversal) and the consequence ('cannot change firewall state'). It omits what happens on a denied path and whether the body is passed through verbatim, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb and resource, then the safety guarantees, then the single arg with an example. No filler; the Args block duplicates the schema slightly but is scannable and compact.
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 escape-hatch tool with annotations covering the safety profile and no output schema, the description is adequate but not complete: an agent still lacks guidance on when this is preferable to a dedicated sibling and on how to find valid paths, which is the crux of calling it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden. It does supply the essential contract — the path must begin with /api/ and an example is given — but it does not say how to discover which paths are allowlisted or what a rejection looks like, leaving the single parameter only partially characterized.
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 (GET) and resource (any allowlisted OPNsense API path), so the agent knows this is a generic read passthrough. However, it never contrasts itself with the twenty specific siblings (system_status, firewall_rules, etc.), so the boundary between this and a dedicated read tool is left 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?
The description covers safety constraints but gives no when-to-use guidance: nothing says 'prefer the dedicated tool when one exists' or 'use this for endpoints not otherwise exposed.' With 20 specific siblings, that omission is the main routing risk. The phrase 'the same read-only rules apply' also references rules defined elsewhere, adding no standalone guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
routing_tableCRead-onlyIdempotent
The firewall's active routing table.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered by structured data. The description adds only the word 'active', hinting at live state but not explaining whether the table is a snapshot or refreshed on each call.
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?
It is a single short fragment with no padding, which is good, but the brevity reflects under-specification rather than tight writing. It front-loads the resource but gives the agent nothing to act on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and no output schema, the description carries the full burden of explaining what the agent receives — routing table columns, whether routes include gateways/interfaces, or formatting. None of this is provided, leaving a meaningful gap for a data-retrieval 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?
The tool takes zero parameters, so the baseline of 4 applies. There is nothing for the description to disambiguate on the input side.
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?
Identifies the specific resource (the firewall's routing table) and the qualifier 'active' narrows it, so an agent can tell it apart from siblings like arp_table or firewall_rules. However, no verb is stated — it is a noun fragment that leaves the agent to infer this is a read/retrieval operation.
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 mention of alternatives such as arp_table or firewall_states, and no stated preconditions. The agent must infer the invocation context 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.
security_auditARead-onlyIdempotent
Quick security review of the ruleset and IDS.
Flags any->any pass rules, inbound pass on WAN, pass rules without logging, and an IDS that is not running.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, and the description is consistent with a report-only audit ("Flags any->any pass rules..."). Beyond the annotations it adds genuine value by naming the four conditions that constitute a finding, so the agent knows what a positive result means.
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 sentences, front-loaded with the purpose and followed immediately by the enumerated checks. No filler, no restatement of the tool name, and the list form makes the findings easy to scan.
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 parameters, an output schema present, and safety fully covered by annotations, the description needs only to explain what is audited and what counts as a problem, which it does. The one gap is the unaddressed relationship to `posture_check` and the other `suricata_*` / `firewall_*` siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, which is the baseline-4 case; there is nothing for the description to disambiguate. The description correctly conveys that the audit runs against the whole ruleset with no scoping input.
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 ("security review of the ruleset and IDS") and enumerates the exact checks performed, so an agent knows precisely what it audits. It does not, however, distinguish itself from the sibling `posture_check`, which plausibly overlaps with this capability.
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 word "Quick" implies this is a lightweight, first-pass check rather than a deep audit, which hints at usage context. But there is no explicit when-to-use, when-not-to-use, or pointer to `posture_check` / `firewall_rules` for deeper investigation, so the agent must infer the routing decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_listARead-onlyIdempotent
All services OPNsense knows about and whether each is running.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds real behavioral context by clarifying the result set is complete ('All services OPNsense knows about') and includes per-service run state, which the annotations do not convey.
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 no filler, front-loading the scope ('All services') and the key returned attribute ('whether each is running'). Nothing could be removed without losing meaning.
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-parameter read-only list with no output schema, the description covers what is enumerated and the main status field. It stops short of sketching the remaining per-service fields an agent would receive, which is the only material gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing to disambiguate; the baseline for a parameterless tool applies. The description correctly implies no filtering or scoping inputs are 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 resource (OPNsense services) and the exact information returned (whether each is running). It does not explicitly differentiate itself from siblings like system_status or system_information, which a one-clause contrast would have made trivial, but the purpose itself 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?
Usage is only implied: an agent can infer that this is the tool for enumerating services, but the description never states when to pick it over system_status, system_information, or security_audit. No prerequisites, exclusions, or alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suricata_alert_statusARead-onlyIdempotent
Whether Suricata is producing alerts, from its eve.json file metadata.
OPNsense only serves alert rows over POST (queryAlerts), which a read-only server must not call. This reports liveness instead: the log file's size and last-modified time. Query alerts in your SIEM.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, idempotentHint, and destructiveHint=false. The description adds that it reads the log file's size and last-modified time to report liveness, and explains why it avoids the POST-based alert query. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purpose ('Whether Suricata is producing alerts'), followed by the rationale and mechanism. No redundant or filler content.
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?
Given no parameters, a present output schema, and rich read-only annotations, the description fully covers purpose, mechanism (file metadata), and limitation (cannot return alert rows). Error handling is the only minor omission, likely covered by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and an empty schema, so there are no parameters to document. Per the baseline rule, a 4 is 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 liveness check: whether Suricata is producing alerts via eve.json file metadata. It distinguishes itself from alert-row retrieval and directs alert queries to the SIEM, but does not explicitly name sibling suricata_status to differentiate.
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?
Explains that OPNsense serves alert rows only over POST (queryAlerts) which a read-only server must not call, and advises querying alerts in the SIEM. Implies this tool is for liveness checks only, but lacks explicit when-to-use vs the suricata_status sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suricata_settingsBRead-onlyIdempotent
Suricata configuration: enabled, IPS mode, interfaces, active rulesets.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is fully covered by structured data. The description adds only the inventory of configuration areas exposed, which functions more as a return-content hint than behavioral context; nothing is said about permissions, sensitivity, or whether it reflects live or persisted config.
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 short line with zero filler, and the resource is front-loaded before the field inventory. It is appropriately sized for a no-argument read tool.
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 parameters, no output schema, and full annotation coverage, the description carries a light load and mostly suffices by naming the config areas returned. What is missing is disambiguation from suricata_status and a note that these are read-only settings rather than live state, which is the main ambiguity an agent would face.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema imposes no semantic burden and the baseline of 4 applies. The description correctly signals a parameter-free configuration read rather than hinting at filtering options.
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 is a noun-phrase inventory ('Suricata configuration: enabled, IPS mode, interfaces, active rulesets') rather than a verb+resource statement, so the agent must infer that it reads configuration. It does list the concrete config areas covered, which helps distinguish content, but it never contrasts itself with the sibling tools suricata_status and suricata_alert_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool, and no exclusions. Given three Suricata-related siblings (suricata_status, suricata_alert_status), the absence of any routing guidance leaves the agent guessing whether settings or status is the right call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suricata_statusBRead-onlyIdempotent
Whether the Suricata IDS/IPS service is running, stopped, or disabled.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, so safety is covered. The description adds useful detail by enumerating the possible states (running, stopped, disabled), which is more than a bare status check would convey, but it says nothing about return format, refresh behavior or permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with no filler. It is front-loaded with the resource, though the 'Whether ...' phrasing reads as a sentence fragment rather than a direct statement of action.
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 output schema, the description carries the burden of explaining the return value; it partially does so by listing the three possible states, but doesn't say whether these come back as a string, an object, or with extra fields. Adequate but leaves a real gap for a zero-param query 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?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 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 the specific resource (the Suricata IDS/IPS service) and the information returned (running/stopped/disabled), so an agent knows exactly what it queries. It does not differentiate itself from siblings like suricata_alert_status or suricata_settings, leaving some ambiguity about whether this covers daemon state versus alerting state.
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 indication of when to call this versus the siblings (suricata_alert_status, suricata_settings, service_list) or any prerequisites/context. The agent must infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_informationBRead-onlyIdempotent
Hostname, uptime, load, and general system information.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds the returned data categories but does not disclose response format, rate limits, or other behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single concise sentence with no wasted words, though it is a fragment rather than a front-loaded action statement. It efficiently conveys the main data fields.
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-parameter read tool with no output schema, the description should more fully explain what is returned. It names only a few fields and leaves 'general system information' vague, though annotations cover safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the description is not expected to document any. Baseline for zero-parameter tools is 4.
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?
Lists the data returned (hostname, uptime, load) but lacks a specific verb and uses vague phrasing ('general system information'). It does not differentiate from siblings like system_status or system_resources, which likely overlap.
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?
Provides no guidance on when to use this tool versus alternatives such as system_status or system_resources. There are no stated conditions, exclusions, or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_logBRead-onlyIdempotent
Recent entries from the OPNsense system log.
Args: limit: number of lines to return (1-1000).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds little beyond that: 'recent' is undefined (time window? rotation? follow behavior?) and the return shape of log entries is undisclosed, though the idempotent/read-only framing means the omission is not risky.
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 lines with the resource stated first and the parameter note second; nothing is padded. The 'Args:' docstring residue is slightly mechanical but costs almost no tokens.
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-parameter read-only tool with no output schema, the definition covers what goes in but not what comes out — no indication of entry format or whether 'recent' is bounded. Adequate to invoke, thin for interpreting the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden, and it does supply the one thing the schema lacks: the valid range 1-1000 for limit and its meaning as a line count. It omits any note on the default of 100, which the schema does provide.
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-less but clear resource: 'Recent entries from the OPNsense system log', which tells an agent exactly what data comes back. It does not, however, distinguish itself from the sibling firewall_log, which is the most likely confusion point.
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 call this versus firewall_log or suricata_status, nor any note on cost, freshness, or prerequisites. An agent must infer usage entirely from the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_resourcesBRead-onlyIdempotent
Memory, swap, and disk utilisation of the firewall itself.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is fully covered by structured data. The description adds only the scope note ('the firewall itself') and the metric categories; it says nothing about units, freshness, or cost of the call.
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 waste, and the resource list is front-loaded. As a bare noun phrase it lacks an explicit verb, which slightly weakens structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and annotations covering safety, the remaining burden is small, but the description never states return format or units (percentages vs bytes) and gives no output schema fallback. Against several similarly named system_* siblings, that leaves the agent guessing at the payload shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. No misleading parameter implications are present.
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 the specific resources returned (memory, swap, disk utilisation) and scopes them to the firewall host itself, so an agent knows what data comes back. It does not, however, distinguish itself from close siblings like system_status or system_information, which plausibly return overlapping host metrics.
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 mention of alternatives, and no exclusion criteria. The phrase 'of the firewall itself' hints at a scope boundary but never says when to prefer this over system_status or system_information.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_statusARead-onlyIdempotent
OPNsense firmware version and pending updates (needs the System: Firmware privilege).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuinely useful context beyond the annotations: the required privilege scope, which tells the agent an auth failure mode exists. It adds nothing about response shape, but that is minor for a zero-argument status read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with what is returned and followed by the access precondition in parentheses. No filler, nothing an agent must scan past.
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 output schema and no parameters, the description carries most of the burden and does state what the call yields (firmware version plus pending updates) and what privilege it needs. Enough to call it correctly; only the exact return shape is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-parameter tool applies. The description adds no argument-level meaning because none is possible here.
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 resource (OPNsense firmware version and pending updates), making the read operation unambiguous. It does not, however, distinguish itself from the sibling system_information, which an agent could plausibly pick for a similar question.
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 by the privilege note (System: Firmware) — that hints at when the call will succeed but gives no explicit guidance on choosing this over system_information, system_resources, or posture_check.
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.
21 tool updates
v0.1.0- First observed
arp_table - First observed
dhcp_leases - First observed
firewall_aliases - First observed
firewall_log - First observed
firewall_rule_get - First observed
firewall_rules - First observed
firewall_states - First observed
interfaces - First observed
policy_show - First observed
posture_check - First observed
raw_get - First observed
routing_table - First observed
security_audit - First observed
service_list - First observed
suricata_alert_status - First observed
suricata_settings - First observed
suricata_status - First observed
system_information - First observed
system_log - First observed
system_resources - First observed
system_status
TDQS
Scored across 21 tools
Most tools target clearly distinct resources (suricata_status/settings/alert_status, firewall_rules/rule_get/log/states are well separated). Some softer overlap exists between posture_check and security_audit (both health/security snapshots) and among system_status/system_information/system_resources, but descriptions give enough signals to choose correctly.
All names are snake_case with predictable domain prefixes (system_, service_, suricata_, firewall_, dhcp_) and readable verb_noun forms for actions (posture_check, policy_show, security_audit). A few bare nouns (interfaces, arp_table, routing_table) deviate slightly but remain clear.
21 tools is on the heavy side for a read-only guard server; the suricata and system clusters each add several closely related tools. Every tool does earn a purpose, but the surface sits at the borderline of 'feels heavy'.
For a deliberately read-only server it covers system, services, IDS, firewall rules/aliases/logs/states, logs, interfaces, ARP, routing and DHCP well, with raw_get as an escape hatch for gaps. The notable gap is that policy_show references allowed changes but no mutation tools exist, which may confuse agents expecting lifecycle operations.
Maintenance
Related MCP Connectors
Checks AI agent actions before they run. Signed, RFC 3161 timestamped evidence for audits.
Supervised API-write gateway for AI agents with policy, human approval and execution receipts.
Runtime AI governance: decision gates, human approval, hash-chained audit, compliance mapping.
AI-powered threat intelligence, smart contract auditing, and cybersecurity OSINT.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables natural language interaction and management of pfSense firewalls through Claude and other GenAI applications using the Model Context Protocol. It provides advanced tools for firewall rule configuration, interface management, and intelligent log analysis via a REST API integration.1MIT
- AlicenseNot gradedqualityDmaintenanceEnables natural language management of OPNsense firewalls through AI clients, providing tools for firewall rules, system health, VPN monitoring, and more.AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables AI clients to manage OPNsense firewall, interfaces, DHCP, DNS, routes, and services via natural language through 42 MCP tools.1MIT
- FlicenseNot gradedqualityAmaintenanceEnables natural-language control of pfSense firewalls from Claude Desktop, Claude Code, or any MCP client, covering firewall rules, NAT, VPN, DNS, DHCP, routing, certificates, users, and diagnostics through 332 wire-format-verified REST API tools. Destructive changes are gated behind explicit confirmation, rate limits, config-revision backups, and audit logging so an AI can safely diagnose and reconfigure a production firewall.-