proxy-aiops
This server provides a governed, unified read/write interface to Traefik, Caddy, and HAProxy reverse proxies via MCP or CLI.
Multi-platform reads: proxy overview, version info, entrypoints/listeners, routes, services, upstreams, middlewares, TLS certificates, traffic stats, error counters, and config snapshots/search across Traefik, Caddy, and HAProxy.
Flagship analyses:
backend_health_rca,cert_expiry_sweep,error_rate_rca, androute_conflict_analysiswith transparent, numbers-backed findings.Governed writes: set/delete/load Caddy config values, and set HAProxy server state/weight — all with dry-run previews, audit logging, risk tiers, and reversible undo tokens.
Undo support:
undo_listandundo_applyto replay recorded inverse operations.Safety and governance: built-in audit database, token/call budgets, circuit breaker, secret encryption, output sanitisation, and support-matrix teaching errors instead of silent no-ops.
Provides integration with Caddy's admin API, enabling AI agents to read and manage the live Caddy configuration, including routes, services, certificates, and config tree operations (get/set/delete/load) with reversible undo and audit logging.
Proxy AIops
Governed, audited AI-ops for Traefik, Caddy and HAProxy reverse proxies / load balancers — for AI agents (via MCP) and humans (via CLI).
Disclaimer: Community-maintained open-source project. Not affiliated with, endorsed by, or sponsored by Traefik Labs, the Caddy project, HAProxy Technologies, or the HAProxy project. Traefik, Caddy and HAProxy are trademarks of their respective owners. MIT licensed.
proxy-aiops speaks to three proxy platforms behind one MCP server — Traefik
(its API under /api/..., metrics-text counters via /metrics), Caddy (the
admin API, default localhost:2019) and HAProxy (the Data Plane API v2 under
/v2/..., HTTP Basic auth) — with the same tools working on all three. Each
target in the config names its own platform; a name-keyed platform registry
selects the API shape (auth + resource paths), and an explicit support matrix
raises teaching errors for ops a platform genuinely cannot do — e.g. Traefik
writes point you at its providers (file, container labels, orchestrator CRDs), never
a silent no-op.
Every tool runs through a built-in governance harness (vendored, zero external dependency): audit log, token/call budget with runaway circuit-breaker, descriptive risk-tier labelling, undo-token recording, and output sanitisation.
Why this exists
One server, three proxies — Traefik, Caddy and HAProxy in a mixed edge, spoken to through identical tool names. Adding another proxy later is a new platform descriptor, not a rewrite.
Read the whole edge — version, entrypoints/listeners, routes (routers / caddy routes / frontends) with parsed hosts+paths, services and server-level upstream health, middlewares, TLS domain inventory, traffic/error counters, and the live config tree (snapshot + search).
Flagship RCA analyses — transparent heuristics that show their numbers, never a black-box verdict:
backend_health_rca(down upstreams → cause class L4/L6/L7/DNS/maint + action),cert_expiry_sweep(days-to-expiry buckets + per-platform renewal hints),error_rate_rca(5xx share vs the fleet baseline, dominant code → 502/503/504/500 cause), androute_conflict_analysis(shadowed routes, dead routes, redirect loops).Governed writes — caddy config
set/delete/ fullload(the prior subtree/config is fetched first, so the recorded undo replays a real restore) and haproxy runtime serverstate(ready/drain/maint) andweight(undo restores the prior value) — all withdry_runpreviews; delete/load are risk=high with double confirmation at the CLI.
Related MCP server: observability-aiops
What this tool does, and does not, decide
It delivers proxy operations — reads and writes — accurately and efficiently, and records every one of them. It does not decide whether a write is allowed to happen. That is the agent's judgement, or the permission of the account you connect it with: give the HAProxy Data Plane API a read-only role, or scope down the Traefik/Caddy admin API you point it at, and the writes fail at the server — the place that actually owns the permission.
So there is no read-only switch, no policy file, no approval gate to configure.
The one thing the tool guarantees is that nothing is silent: every call, over
MCP and over the CLI alike, lands an audit row in ~/.proxy-aiops/audit.db,
and reversible writes still capture their before-state and record an inverse.
Each tool declares a
risk_level, kept in agreement with its[READ]/[WRITE]documentation tag by a test, and carried into the audit row as a descriptive tier — so a reviewer can see at a glance that a row was a high-risk delete. It is a label, not a gate.
Running a smaller / local model? See agent-guardrails.md — it lists the guardrails this tool now enforces for you (so you don't spend prompt budget restating them) and gives a ready-made system prompt for what's left.
Tool inventory (28 tools)
Domain | Tools | # | Kind |
Status |
| 3 | read |
Routes |
| 3 | read |
Services |
| 5 | read |
Certificates |
| 1 | read |
Traffic |
| 2 | read |
Config |
| 3 | read |
Flagship analyses |
| 4 | read |
Writes (caddy) |
| 1 | write (med) |
Writes (caddy) |
| 2 | write (high) |
Writes (haproxy) |
| 2 | write (med) |
Undo |
| 2 | read / write |
Reversible writes record an inverse undo descriptor built from the real fetched
before-state (set_config_value restores the prior subtree; delete_config_path
re-creates it; load_config re-loads the snapshotted config; server state/weight
restore the prior value). The undo params match each tool's own signature, so the
descriptor replays as-is.
Per-platform support matrix
Capability | traefik | caddy | haproxy |
Routes / services / upstream health | ✅ | ✅ | ✅ |
Middlewares list | ✅ | teaching note (inline handlers) | teaching note (haproxy.cfg) |
TLS cert inventory + expiry sweep | ✅ | ✅ | teaching note (.pem files) |
Error counters / error-rate RCA | ✅ (/metrics) | teaching note (no per-route counters) | ✅ (stats) |
Config snapshot / search | ✅ (rawdata, read-only) | ✅ | teaching note |
Config writes | teaching error → edit the provider | ✅ (the write surface) | teaching error → runtime writes |
Runtime server state / weight | teaching error → provider | teaching error → config tree | ✅ |
Unsupported combinations raise a teaching error that says what to use instead — never a silent empty result.
Install
uv tool install proxy-aiops # or: pipx install proxy-aiopsQuick start
As a Claude Code plugin
One install gives an agent both the skill and the MCP server:
/plugin marketplace add AIops-tools/marketplace
/plugin install proxy-aiops@aiops-toolsThe MCP server is fetched with uv and pinned to the
package version this plugin declares, so an audit row can be traced back to the
code that wrote it. Credentials are still configured with proxy-aiops init — see below.
As an OpenClaw plugin
The same bundle is published on ClawHub, where one install delivers the skill and its MCP server together:
openclaw plugins install clawhub:@zw008/proxy-aiops
openclaw skills info proxy-aiops # expect: Visible to model: yesRestart the OpenClaw gateway afterwards so it loads the plugin. The MCP server is
fetched with uv, pinned to this exact release, so
uvx has to be on PATH — without it the skill still installs but reports
Visible to model: no. Credentials are configured exactly as below.
As a CLI or standalone MCP server
proxy-aiops init # wizard: pick platform (traefik/caddy/haproxy) + optional encrypted secret
proxy-aiops doctor # verify config, secrets, and connectivity
proxy-aiops overview # one-shot: version + route/service counts + upstream health
proxy-aiops routes list # normalised route table
proxy-aiops services upstreams # server-level upstream health
proxy-aiops analyze health # backend/upstream health RCA
proxy-aiops analyze errors # 5xx error-rate RCA
proxy-aiops analyze conflicts # shadowed/dead routes, redirect loops
proxy-aiops certs --sweep # TLS cert expiry sweep (traefik/caddy)
proxy-aiops server state app web1 drain --dry-run # governed haproxy write preview
proxy-aiops config set apps/http/servers/srv0 '{"listen":[":8080"]}' --dry-runRun the MCP server (stdio) for an agent:
proxy-aiops mcp # or: proxy-aiops-mcpMCP client config
{
"mcpServers": {
"proxy-aiops": {
"command": "uvx",
"args": ["--from", "proxy-aiops", "proxy-aiops-mcp"],
"env": { "PROXY_AIOPS_MASTER_PASSWORD": "your-master-password" }
}
}
}Env-block caveat: the
envblock is only needed when a credential is stored (haproxy always; traefik/caddy only behind Basic auth). MCP clients do not inherit your shell profile — setPROXY_AIOPS_MASTER_PASSWORD(andPROXY_AIOPS_CONFIG/PROXY_AIOPS_HOMEif you relocated them) explicitly in the client config, or the server cannot unlocksecrets.enc.
Configuration
~/.proxy-aiops/config.yaml (non-secret connection details only):
targets:
- name: edge1
platform: traefik # traefik | caddy | haproxy
base_url: http://192.0.2.10:8080
verify_ssl: true
- name: caddy1
platform: caddy
base_url: http://127.0.0.1:2019
- name: lb1
platform: haproxy
base_url: http://192.0.2.20:5555
username: dpapi # Data Plane API userThe secret — the HAProxy Data Plane API password, or an optional Basic-auth
password in front of Traefik/Caddy — is stored encrypted in
~/.proxy-aiops/secrets.enc (Fernet + scrypt-derived key), never plaintext on
disk. Traefik and Caddy commonly run unauthenticated on localhost, so their
secret is optional (like a local socket); HAProxy's is required. Set it with
proxy-aiops secret set <target> or the init wizard. The store is unlocked by
a master password from PROXY_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or
an interactive prompt (CLI on a TTY). A legacy plaintext env var
PROXY_<TARGET>_SECRET is honoured as a fallback (migrate with
proxy-aiops secret migrate).
Governance
Every MCP tool — and every CLI write, which routes through the same governed
functions — passes through @governed_tool. It records; it does not authorize
(see above).
Audit — every call is logged to
~/.proxy-aiops/audit.db(tool, params with secrets redacted, status, duration, risk tier, and any operator-supplied approver/rationale). The CLI writes the same row the MCP path does — there is no unaudited entry point.Budget / runaway guard — a safety backstop, not an authorization gate: per-process token/call caps and a repeat-call circuit breaker stop a stuck agent from burning unbounded calls/time (
PROXY_MAX_TOOL_CALLS,PROXY_RUNAWAY_MAX, …; disable the breaker withPROXY_RUNAWAY_MAX=0).Undo recording — reversible writes record an inverse descriptor to
~/.proxy-aiops/undo.dbfrom the fetched before-state (recording only; an external orchestrator executes it). Undo params match the target tool's own signature, so the descriptor replays as-is.Risk tier — a descriptive label on the audit row derived from
risk_level; it gates nothing.Sanitisation — all proxy-returned text is bounded + control-character sanitised before it reaches the agent.
Platform support & verification status
Platforms: Traefik (API + /metrics), Caddy (admin API), HAProxy (Data Plane API v2).
Test coverage: behaviour is validated against mocked JSON/metrics responses — every module imports, every MCP tool carries the governance marker, the four flagship analyses are unit-tested against synthetic telemetry, the support matrix is asserted to raise teaching errors (never a silent no-op), and reversible writes are asserted to record the correct inverse undo descriptor. The concrete REST paths are modelled from each project's public API and have not yet been exercised against a live proxy. See docs/VERIFICATION.md for the checklist a live run must satisfy. All three platforms are free and self-hostable (a small container-compose lab with traefik + caddy + haproxy/dataplaneapi is a one-evening setup), and
proxy-aiops doctor— a health/info probe per platform — is the fastest live check.Routing note: this tool operates reverse proxies / load balancers. Do NOT use it for firewall rules — use firewall-aiops.
Missing a capability? Open an issue or PR at github.com/AIops-tools/Proxy-AIops — contributions and feedback welcome.
License
MIT — see LICENSE.
Available Tools
28 toolsbackend_health_rcaARead-only
[READ] Down upstreams grouped per service, each mapped to cause + action.
The flagship availability RCA: pulls server-level upstream health, groups per service, and classifies each outage/degradation (connection refused, L4/L7 health-check failure class, DNS, admin maint/drain, all-servers-down) with a recommended action. Every finding carries its numbers. Pass 'upstreams' for pure analysis, or a target to pull live.
Args: service: Optional service/backend filter when pulling live. upstreams: Injected rows {service, server, address, status, checkInfo}; skips the live pull. target: Proxy target name from config; omit for the default.
Returns dict: {servicesEvaluated, outages, degraded, findings:[{service, serversTotal, up, down, maint, failingServers, cause, action}], note}.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | ||
| service | No | ||
| upstreams | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and the description is consistent with a read operation. Beyond that it adds real behavioral detail: injecting 'upstreams' skips the live pull, and outages are classified into named causes (connection refused, L4/L7 health-check failure, DNS, admin maint/drain, all-servers-down) each with a recommended action.
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 core behavior is front-loaded in the first sentence, followed by an Args block and a Returns block. Slightly longer than needed and the return-dict detail is verbose, but every section maps to something an agent 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?
No output schema exists, yet the description documents the return dict (servicesEvaluated, outages, degraded, findings with per-service fields and cause/action, note), and all three parameters are explained. For a three-mode read-only RCA tool this is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden and does: 'service' is an optional filter that only applies when pulling live, 'upstreams' is documented with its row shape {service, server, address, status, checkInfo} and the fact that it bypasses the live pull, and 'target' is a proxy target name from config with a default fallback.
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 (pulls server-level upstream health, groups per service, classifies each outage) and resource, and the opening line names the diagnostic scope. It is clearly distinguishable from siblings like error_rate_rca or upstream_detail.
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?
Explicitly says to pass 'upstreams' for pure analysis versus a target to pull live, and that 'service' filters live pulls only. It gives clear mode-selection guidance but never names a sibling or a when-not-to-use condition relative to the adjacent error_rate_rca tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cert_expiry_sweepARead-only
[READ] TLS cert inventory bucketed by days-to-expiry + renewal hints.
The flagship cert sweep for traefik/caddy targets: collects the TLS domain inventory, live-probes each domain's served leaf cert (bounded handshake), and buckets by expiry: expired / critical / warning / ok — with a platform-specific renewal hint (ACME resolver / storage checks). Pass 'certs' for pure analysis over {domain, daysToExpiry} rows. haproxy targets return the support matrix's teaching note.
Args: warn_days: Days-to-expiry at/below which a cert is a warning (default 30). critical_days: Days at/below which a cert is critical (default 7). port: TLS port to probe (default 443). certs: Injected rows {domain, daysToExpiry, notAfter?}; skips pull+probe. target: Proxy target name from config; omit for the default.
Returns dict: {certsEvaluated, expired, critical, warning, ok, unknown, certificates (soonest first), thresholds, renewalHint, note}.
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | ||
| certs | No | ||
| target | No | ||
| warn_days | No | ||
| critical_days | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already covers the safety profile, but the description adds real behavior beyond annotations: it performs a bounded TLS handshake against each domain, buckets into expired/critical/warning/ok/unknown, and emits platform-specific renewal hints. This is substantive disclosure of what the tool actually does.
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 [READ] tag and a one-line summary, then structured into prose, Args, and Returns. It is somewhat verbose and the Returns block is dense, but every sentence carries information and nothing is wasted on tautology.
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?
No output schema exists, so the description explains the return dict keys (counts by bucket, soonest-first certificates, thresholds, renewalHint, note), and the Args section fully documents all parameters. An agent has everything needed to call and interpret this read-only 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 description coverage is 0%, so the description must carry all five parameters, and it does: warn_days (default 30), critical_days (default 7), port (default 443), certs (injected {domain, daysToExpiry} rows that skip pull+probe), and target (config name, omit for default). It adds behavior the schema can't express, notably that certs bypasses collection and probing.
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+scope: a TLS cert inventory that live-probes leaf certs and buckets them by days-to-expiry. It differentiates itself from the sibling list_certificates by framing this as the 'flagship cert sweep' that actually probes rather than just lists.
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?
Gives clear context on when it applies (traefik/caddy targets) and how it degrades (haproxy returns the support matrix's teaching note), plus the 'pass certs for pure analysis' shortcut. It never names list_certificates as the alternative for a plain listing, so routing between the two cert tools is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
config_snapshotARead-only
[READ] The live config tree (caddy /config/) or merged dynamic state (traefik /api/rawdata), sanitised and bounded. haproxy returns the support matrix's teaching note.
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=true annotation, the description adds real behavioral context: output is 'sanitised and bounded', and its content varies by proxy (caddy returns /config/, traefik returns merged /api/rawdata, haproxy returns a teaching note). This tells the agent what to expect from the payload, which the annotation alone does not.
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 [READ] tag front-loads the operation type, followed by two purposeful sentences and a compact Args block. The haproxy clause is slightly opaque but compact. No filler; every element 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 single-optional-param read tool with no output schema and no annotations beyond readOnlyHint, the description covers the return content, per-proxy variance, and the param. It stops short of defining exactly what 'bounded' limits or what is stripped by sanitisation, but is otherwise complete enough to invoke 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% (the schema only has a title and null default), so the description carries the burden and does so adequately: 'target: Proxy target name from config; omit for the default.' It explains both the parameter's meaning and the default behavior, though it doesn't enumerate valid target values.
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 read action: the live config tree or merged dynamic state, with per-proxy source paths (caddy /config/, traefik /api/rawdata). It clearly distinguishes this snapshot tool from siblings like get_config_value or search_config, though the phrasing is noun-heavy ('The live config tree...') rather than verb-led.
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 or named alternative among the many config-related siblings (search_config, get_config_value, proxy_overview). The only contextual hint is the target arg semantics, which the agent must infer usage from. No exclusions or prerequisites are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_config_pathADestructive
[WRITE][risk=high] Delete a caddy config subtree; reversible — the subtree is captured first and the undo re-creates it.
Pass dry_run=True to preview.
Refuses the 'admin' subtree and the config root: both remove the admin API this tool speaks to, leaving the undo with no way to reach the server. The refusal applies under dry_run too, which must report it rather than preview a call that will be refused.
Args: path: Slash-separated config path to delete. dry_run: If True, preview without deleting. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| target | No | ||
| dry_run | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true/readOnlyHint=false, yet the description adds substantial context: the operation is reversible because the subtree is captured first, the undo re-creates it, dry_run previews, and the admin/root refusal applies even under dry_run and must be reported rather than previewed. This is behavior an agent could not infer from annotations alone.
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 a risk/tag banner and the core action, followed by refusal semantics and an Args block. All sentences earn their place; the only cost is mild redundancy in restating parameter meaning twice.
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 3-param mutation tool with no output schema, the description covers reversibility, dry-run behavior, and the critical refusal case that would otherwise cause a confusing failure. Nothing an agent needs to call 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 0%, so the description carries the burden, and it defines all three params: path (slash-separated config path), dry_run (preview without deleting), and target (proxy target name, omit for default). It adds meaningful format and default semantics, though not exhaustively.
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 (delete a caddy config subtree) with an explicit risk marker, and reads distinctly from siblings like get_config_value or set_config_value. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear when-to-use guidance (dry_run=True to preview) and explicit when-not-to-use conditions (refuses the 'admin' subtree and config root, including under dry_run). It does not name a sibling alternative, but the conditional guidance is specific and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
error_countersARead-only
[READ] Per-service request/status-code counters (feeds error_rate_rca).
traefik: parsed from the /metrics text endpoint (per-code); haproxy: Data Plane stats (per-class hrsp_*); caddy: teaching note (no per-route counters).
Args: target: Proxy target name from config; omit for the default.
Returns an envelope: {"services": [...], "returned": N, "limit": L, "truncated": bool, "total": T}. When "truncated" is true this proxy serves more services than were returned (only the busiest services are returned).
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses substantial behavioral detail: per-backend parsing semantics (traefik per-code, haproxy per-class, caddy has no per-route counters) and, critically, the truncation behavior — only the busiest services are returned when truncated is true. This tells an agent exactly what data it may and may not get 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?
Front-loaded with the [READ] marker and a one-line purpose, followed by structured Args and Returns sections. Every block carries real information, though the dense per-backend parsing breakdown adds some length for a single-parameter 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?
Even without an output schema, the description supplies the return envelope shape (services, returned, limit, truncated, total) and the meaning of truncation, plus proxy-specific data caveats. An agent has everything needed to call it and interpret 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 must compensate, and it does: it explains that target is a 'Proxy target name from config' and that omitting it selects the default. The one gap is that it doesn't say whether the config name matches route/service naming elsewhere.
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+resource: per-service request/status-code counters, and marks it as a read tool. It distinguishes itself from siblings by noting it feeds error_rate_rca and by breaking down exactly how each proxy backend (traefik, haproxy, caddy) is parsed.
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?
Naming error_rate_rca as the consumer implies the tool's role as a raw data source, which is useful context, but the description never states explicitly when to use this tool versus alternatives like traffic_stats or error_rate_rca itself. Usage is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
error_rate_rcaARead-only
[READ] Rank services by 5xx share vs the fleet baseline, cause + action.
The flagship error RCA: reads per-service status-code counters (traefik /metrics, haproxy stats), flags services whose 5xx rate crosses the threshold with enough traffic, and maps the dominant code to a cause (503 no-upstream / 502 conn-fail / 504 timeout / 500 app error). Every entry carries its numbers and its multiple vs the fleet baseline. Pass 'counters' for pure analysis. caddy targets return the support matrix's teaching note (no per-route counters).
Args: error_rate_pct: 5xx %% at/above which a service is flagged (default 5.0). min_requests: Minimum requests before a service can be flagged (default 30). counters: Injected rows {service, total, codes:{...}} and/or classes:{"5xx": n}; skips the live pull. target: Proxy target name from config; omit for the default.
Returns dict: {servicesEvaluated, flaggedCount, fleetErrorRatePct, thresholds, flagged:[{service, requestsTotal, errors5xx, errorRatePct, dominantCode, vsBaselineX, severity, cause, action}], note}.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | ||
| counters | No | ||
| min_requests | No | ||
| error_rate_pct | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint already covers the safety profile, but the description adds real behavioral context: it reads traefik/haproxy counters, applies threshold+traffic gating, maps dominant codes to causes, and warns that caddy targets return only a teaching note. No return format gaps remain unexplained.
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 read tag and one-line summary, then Args and Returns blocks. Some prose is dense but each section earns its place; nothing is redundant 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?
With no output schema, the description fully specifies the return dict (servicesEvaluated, flaggedCount, fleetErrorRatePct, thresholds, flagged entries with cause/action/severity). Threshold defaults, injection mode, and the caddy limitation are all covered.
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 burden and does so well: it documents error_rate_pct (default 5.0), min_requests (default 30), counters (injected rows with codes/classes), and target (proxy target from config). Semantics of each param are clear.
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 precise verb and resource ('Rank services by 5xx share vs the fleet baseline'), plus the diagnostic outputs (cause + action). The [READ] tag and 'flagship error RCA' framing make it easy to distinguish from raw-counter tools like error_counters.
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 the counters-injection path ('Pass counters for pure analysis') and the caddy caveat, but never states when to prefer this over sibling RCA tools such as backend_health_rca or error_counters. 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.
find_routeARead-only
[READ] Which routes would serve a host/path (static match, best first).
Args: host: Hostname to match (e.g. app.example.com). path: Request path to match (default /). target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | ||
| path | No | / | |
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already establishes this is a safe read, and the '[READ]' tag merely repeats that. The description does add genuine behavioral detail beyond the annotation: matching is static (not runtime/dynamic) and results are ordered best-first, which tells the agent how to interpret the returned list.
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 one-line summary followed by a compact args block; every sentence is functional and there is no filler. The '[READ]' prefix is slight redundancy against readOnlyHint, but it costs almost nothing.
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?
No output schema exists, yet the description implies the return is an ordered list of matching routes, and it compensates for 0% schema coverage by documenting all three parameters. It stops short of describing the result shape precisely or clarifying what 'static match' excludes (e.g. regex/dynamic routing), which an agent might want.
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 largely succeeds: host is defined as the hostname to match with an example, path as the request path with its '/' default, and target as a proxy target name with 'omit for the default'. Minor gap: no format hints beyond the example, but all three parameters are given meaning.
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: it resolves which routes would serve a given host/path, and the parenthetical '(static match, best first)' clarifies it is a prediction/lookup rather than a live-router query. This distinguishes it from siblings like list_routes, route_detail, and route_conflict_analysis, though it never names an alternative directly.
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 framing ('which routes WOULD serve a host/path') – you call it to test-match a request against configuration. However, there is no explicit when-to-use, no when-not-to-use, and no mention of which sibling to prefer for enumerating routes (list_routes) or inspecting a single one (route_detail).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_config_valueARead-only
[READ] One value out of the caddy config tree by config path (e.g. apps/http/servers/srv0/routes/0). Off-caddy platforms return the support matrix's teaching note.
Args: path: Slash-separated config path (dot-segments rejected). target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description is consistent with that. It adds genuine behavioral context beyond the annotation: off-caddy platforms return the support matrix's teaching note instead of an error, and dot-segments in the path are rejected.
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 core behavior and the example path are front-loaded, and the Args block is compact. The trailing parenthetical about off-caddy platforms is slightly awkwardly placed but still 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?
No output schema exists, and the description implies the return is a single config value plus the off-caddy teaching note, which is adequate. It does not describe what happens for a non-existent path, a minor remaining 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%, so the description carries the burden, and it does: 'path' is a slash-separated config path with dot-segments rejected, and 'target' is a proxy target name that can be omitted for the default. Both parameters gain meaning absent from 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 (get) and resource (one value from the caddy config tree) and gives a concrete example path. It contrasts implicitly with the write/delete siblings via the [READ] tag, though it never names an alternative like search_config or route_detail.
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 [READ] tag and the exact-path framing imply this is the exact-lookup tool, but there is no explicit 'use this when / use search_config instead' guidance. The off-caddy fallback note is a useful edge-case rule but not a when-to-use rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_certificatesARead-only
[READ] TLS domain inventory for a traefik/caddy target; optionally handshake-probe each domain for its live expiry.
On haproxy this returns the support matrix's teaching note (certs are .pem files in haproxy.cfg).
Args: probe: If True, TLS-handshake each domain (bounded) to read expiry. port: TLS port to probe (default 443). target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | ||
| probe | No | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds genuine behavioral context beyond that: the haproxy target returns a teaching note instead of probing, and probing is described as "bounded." These are real traits an agent should know before calling.
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 [READ] tag and core purpose, followed by a compact target note and an Args block that maps one-to-one to the parameters. The awkward line-wrapping adds noise but every sentence carries 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?
With no output schema, the description does sketch what comes back (domain inventory and, on haproxy, a teaching note). For a safe read-only tool with all three optional params documented, this is nearly complete, missing only the shape of the inventory result on non-haproxy targets.
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 parameter burden and does so reasonably: probe (handshake each domain, bounded), port (TLS port, default 443), and target (proxy target name from config, omit for default). All three params gain meaning beyond the bare schema, though valid ranges/formats are not specified.
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 ("TLS domain inventory") and clarifies behavior per target type (traefik/caddy vs haproxy). However, it never explicitly distinguishes itself from the very similar sibling cert_expiry_sweep, which also deals with expiry probing, so sibling differentiation 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?
Usage is implied: an agent can infer this is for inventorying TLS domains and optionally probing expiry, and the target-type notes give context. But there is no explicit when-to-use-vs-alternatives guidance, no exclusions, and no routing toward cert_expiry_sweep or list_routes for related needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_entrypointsARead-only
[READ] Listeners: traefik entrypoints / caddy server listen addresses / haproxy frontends — where traffic enters this proxy.
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already declares the safety profile, so the '[READ]' tag adds little. The description does contribute semantic context by mapping entrypoints to traefik/caddy/haproxy terminology, but says nothing about return volume, ordering, or behavior when a target has no listeners.
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 blocks, concept first, argument second, with zero filler. Every phrase (the per-proxy terminology list, the 'omit for default' note) 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 single optional-parameter read tool with annotations covering safety, this is nearly sufficient. The one gap is that, with no output schema, the description never indicates what a returned entrypoint looks like (name plus address/port), leaving the agent to guess 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?
Schema coverage is 0% and the schema is a bare nullable string, so the description carries the full burden — and it does: it explains that 'target' is a proxy name from config and that omitting it selects the default. It does not say where valid target names can be discovered.
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 (entrypoints/listeners) and defines the concept as 'where traffic enters this proxy', which cleanly separates it from route/service-level siblings. It does not explicitly name an alternative tool, so it stops just short of 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: a reader infers you call this to inspect the proxy's inbound listeners. The one concrete guideline ('omit for the default') is about the parameter, not about tool selection versus list_routes, find_route, or proxy_overview.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_middlewaresARead-only
[READ] Middlewares (traefik). On caddy/haproxy this returns the support matrix's teaching note (their equivalents live inside routes / haproxy.cfg).
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true so the safety profile is covered. The description goes beyond that by disclosing platform-dependent behavior: on caddy/haproxy it returns the support matrix's teaching note because their equivalents live inside routes/haproxy.cfg. That is genuine behavioral context an agent could not infer from structured fields. It omits return shape/pagination, keeping it from 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 [READ] tag and resource name, then the platform caveat, then a compact Args block. Every line earns its place with little filler. The parenthetical is slightly dense but functional.
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-optional-param read-only list tool with no output schema, this covers purpose, parameter semantics, platform quirks, and relies on annotations for safety. Little an agent needs to invoke it correctly is missing; only explicit sibling routing is 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 coverage is 0%, so the description must carry the parameter meaning – and it does: 'target: Proxy target name from config; omit for the default.' That explains both the value source and the omit-for-default behavior beyond the bare schema default of null.
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?
Combined with the name, the description states a specific verb+resource: listing traefik middlewares, and scopes it by platform (traefik vs caddy/haproxy). It is clear what the tool returns and it is differentiated from the routes/services siblings by being middleware-specific. It stops short of explicitly contrasting with those siblings, so a 4 rather than 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 note that caddy/haproxy return a support-matrix teaching note instead is a useful context hint, but there is no explicit when-to-use or when-not-to-use guidance, and no alternative is named (e.g. use route_detail to see middleware bindings). 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.
list_routesBRead-only
[READ] Routes normalised across platforms: {name, hosts, paths, priority, service, tls, enabled, redirectTo}.
Traefik router names and caddy config paths (apps/http/servers/...) come back exactly as the other tools expect them.
Args: host: Optional hostname filter (keeps host-less catch-alls). target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| host | No | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The '[READ]' prefix and readOnlyHint annotation agree, so no new safety information is added. It does add useful interoperability context: Traefik router names and Caddy config paths come back in the exact form other tools expect, which tells the agent the output is safe to feed into sibling tools. No rate limits, pagination, or failure behavior is discussed.
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 read-only marker, the resource, and the returned field set, then a compact Args section. The field list is justified because there is no output schema. Only minor redundancy in re-explaining the default target.
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 sensibly enumerates the returned fields and documents both parameters; annotations already cover the read-only nature. It is close to complete for a simple list tool, with the main gap being guidance on how results relate to the other route-listing 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?
Schema coverage is 0%, so the description carries the full parameter burden and does it reasonably well: 'host' is described as an optional hostname filter with the non-obvious detail that host-less catch-alls are retained, and 'target' as a config proxy target whose omission selects the default. Both semantics are non-inferable from the bare schema, though format examples are absent.
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 operation and resource: it lists routes and, importantly, states they are 'normalised across platforms' with the exact field set returned. That distinguishes it from find_route and route_detail, which imply single-route lookups, though the sibling differentiation is implicit 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 or when-not-to-use guidance. It never says to prefer this over find_route, route_detail, or route_conflict_analysis, nor does it state any prerequisite (e.g. loaded config). The only conditional behavior mentioned is per-parameter, not tool-level.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_servicesBRead-only
[READ] Services / backends with per-service server-up counts.
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true is consistent with the '[READ]' tag, so no contradiction. The description does add value beyond annotations by disclosing that the response includes per-service server-up counts, which is otherwise unavailable given there is no output schema, but it says nothing about auth, limits, or result shape.
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?
Short and front-loaded, with the resource and key return detail stated before the Args block. The Args formatting is slightly redundant for a single optional parameter but not wasteful.
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 listing tool with no output schema, the description supplies the essential return-content hint and the parameter default. It still omits the shape of the service list and any pagination or filtering behavior an agent might need.
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% for the single 'target' parameter, so the description must compensate. It does explain that 'target' is a proxy target name from config and that omitting it uses the default, which is genuinely useful, but it does not say what a valid target value looks like or where to find one.
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 (services/backends) and adds a differentiating detail: per-service server-up counts. This separates it from richer siblings like service_detail, though it never names them explicitly.
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 '[READ]' tag implies a safe read operation but there is no guidance on when to use this versus list_upstreams, service_detail, or proxy_overview. The agent must infer the choice from tool names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_upstreamsARead-only
[READ] Server-level upstream health rows: {service, server, address, status(up/down/maint/drain), checkInfo, weight}. Feeds backend_health_rca.
Args: service: Optional service/backend filter. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | ||
| service | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description reinforces this with the '[READ]' tag and by disclosing the exact row fields returned, including the status enum (up/down/maint/drain). It omits any note on scope limits, ordering, or pagination, which keeps it 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 read tag and the resource, then the return shape, then the args. The row spec in braces is dense but per-field meaningful; nothing reads as 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?
With no output schema, the description compensates by enumerating the returned row fields, and both optional parameters are explained. Health/status semantics and any listing limits are left implicit, so it is complete but not exhaustive.
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 mostly succeeds: it explains that 'service' is an optional backend filter and that 'target' is a proxy config target name that defaults when omitted. It does not give the accepted name format or an example, leaving a small gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list upstream health rows) and even enumerates the returned row shape with status values, which is far more informative than the bare name. It does not, however, distinguish itself from the closely named sibling upstream_detail, so an agent still has to infer which one to reach for.
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 rather than stated: 'Feeds backend_health_rca' hints at the downstream workflow and the args imply a filtering use case, but there is no explicit when-to-use guidance or contrast with siblings like upstream_detail or list_services.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_configADestructive
[WRITE][risk=high] Replace caddy's FULL running config; reversible — the prior config is snapshotted first and the undo re-loads it.
Pass dry_run=True to preview.
Refuses a config that disables the admin API or moves admin.listen off the configured base_url — the undo re-POSTs the snapshot over that same API. Send the admin block unchanged, or omit it. The refusal applies under dry_run too, which must report it rather than preview a refused call.
Args: config: The full config tree to load (a JSON object). dry_run: If True, preview without loading. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| config | Yes | ||
| target | No | ||
| dry_run | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say non-readonly/non-idempotent/destructive; the description goes well beyond that, disclosing that the prior config is snapshotted so the call is reversible via undo, the exact refusal conditions, and that the refusal also applies under dry_run (which must report rather than preview). For a destructive write that is precisely the extra context an agent needs.
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 [WRITE][risk=high] severity tag, then reversibility, then caveats, then an Args block. Mostly tight, though the dry_run/refusal interplay is restated twice and could be tightened; no sentence is pure 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?
No output schema exists, and the description still covers replacement semantics, reversibility, refusal handling, and parameter roles, so an agent can call it safely. The one gap is that the nested structure of the config tree is not characterized at all, which matters given the nested-object 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 description coverage is 0%, so the description carries the burden and does: config is the full config tree as a JSON object, dry_run previews without loading, target is a proxy target name that defaults when omitted. It does not describe the shape of the nested config tree, but it correctly disambiguates all three parameters.
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?
Opens with a specific verb+resource+scope: 'Replace caddy's FULL running config'. The 'FULL' qualifier and the sibling set (set_config_value, set_config_value, delete_config_path) make it clear this is a wholesale replacement rather than a path-level edit.
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?
Gives clear trigger conditions ('Pass dry_run=True to preview') and a hard guardrail explaining that configs disabling the admin API or moving admin.listen are refused. It does not name a sibling alternative (e.g. set_config_value for partial edits), so it stops short of explicit routing, but the context is otherwise unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
proxy_overviewARead-only
[READ] One-shot summary: platform/version + route/service counts + upstream up/down health.
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already establishes this as a safe read, and the '[READ]' tag merely restates it. It does add value by disclosing what the summary aggregates (version, counts, up/down health), but says nothing about cost, freshness, or pagination behavior beyond that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in one dense sentence covering all three returned data groups, followed by a minimal Args block. Only waste is the '[READ]' tag, which duplicates the annotation.
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 summary tool with no output schema, the description adequately conveys what will be returned and how the lone argument behaves. Missing only minor details such as output shape or refresh behavior.
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 single 'target' property has no description at all in the schema. The description compensates well by explaining that target comes from the config and that omitting it selects the default, which is the key semantic an agent needs.
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 ('One-shot summary') and enumerates the exact contents returned: platform/version, route/service counts, and upstream up/down health. This aggregation scope implicitly separates it from the list_routes/list_services/list_upstreams siblings, though no sibling is named explicitly.
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 guidance is the parameter note 'omit for the default', which is actionable but addresses the argument rather than when to choose this tool over alternatives like version_info or the individual list tools. Usage context is implied, not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
route_conflict_analysisARead-only
[READ] Shadowed routes, dead routes, and redirect loops (static).
The flagship routing hygiene analysis: fetches the route table and service list and statically finds (1) routes fully covered by an earlier/higher- priority route (they can never match), (2) routes pointing at a missing service or one with zero servers up, and (3) redirect chains that loop. Every finding names the covering route / missing service. Pass 'routes' (and optionally 'services') for pure analysis.
Args: routes: Injected rows {name, hosts, paths, priority, service, enabled, redirectTo}; skips the live pull. services: Injected rows {name, serversTotal, serversUp} for dead-route detection. target: Proxy target name from config; omit for the default.
Returns dict: {routesEvaluated, shadowedCount, deadCount, redirectLoopCount, shadowedRoutes, deadRoutes, redirectLoops, note}.
| Name | Required | Description | Default |
|---|---|---|---|
| routes | No | ||
| target | No | ||
| services | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true, so the description adds real value by disclosing that the analysis is static, that it fetches the route table and service list, and that injecting routes 'skips the live pull.' It also describes what each finding reports (naming the covering route / missing service), going beyond the safety 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?
Front-loaded with a one-line summary followed by the analysis breakdown, args, and returns; almost every sentence earns its place. It is somewhat long, but the structure (summary / Args / Returns) keeps it navigable rather than wasteful.
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 steps in by enumerating the return dict keys (routesEvaluated, shadowedCount, deadCount, redirectLoopCount, and the finding lists). A three-parameter read tool with light annotations is well covered, though the 'note' field is left unexplained.
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: it defines the field shape of injected routes ({name, hosts, paths, priority, service, enabled, redirectTo}) and services ({name, serversTotal, serversUp}) and clarifies target as a proxy target name that defaults when omitted. This fully compensates for the absent schema descriptions.
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 ('statically finds') and enumerates the three exact findings: shadowed routes, dead routes, and redirect loops. It is clearly distinguishable from siblings like list_routes, route_detail, and find_route, which merely enumerate rather than analyze conflicts.
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 explains how to invoke it ('Pass routes and optionally services for pure analysis') and that omitting routes triggers the live pull, which is operational guidance. However, it never explicitly contrasts itself with siblings such as find_route or list_routes, so the when-to-use-vs-alternative decision is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
route_detailARead-only
[READ] One route's full detail by name (from list_routes).
Args: name: Route name — traefik router name, caddy route config path, or haproxy frontend name. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already declares this as a safe read, so the bar is lower. The description reinforces read scope but adds no rate limits, auth needs, or output characteristics; 'full detail' is undisclosed. Modest added value over 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?
Front-loaded one-line summary followed by a compact Args block; each line earns its place. Minor redundancy between the summary and the name arg note, but nothing wasteful.
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 should hint at what 'full detail' returns, and it does not; there is also no target enumeration despite backend-specific routing. Adequate for a read tool whose annotation covers safety, but the return shape is left entirely to inference.
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 burden and does so well: it explains that name is a route name presented as a traefik router name, caddy config path, or haproxy frontend name, and that target defaults when omitted. This meaningfully exceeds the schema's bare string typing.
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 ('One route's full detail') and anchors the name to list_routes, so an agent can distinguish it from list_routes and find_route. It stops short of explaining how it differs from find_route, so it's clear but not fully disambiguated among siblings.
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?
Tells the agent the name comes from list_routes and that target can be omitted for the default, which is useful implied usage. It never states when to prefer this over find_route or route_conflict_analysis, so the guidance is partial.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_configARead-only
[READ] Search the config tree for a string; returns matching config paths (on caddy, directly usable by get/set_config_value).
Args: query: Case-insensitive substring to find in keys and values. target: Proxy target name from config; omit for the default.
Returns an envelope: {"matches": [...], "returned": N, "limit": L, "truncated": bool}. When "truncated" is true there is more than was returned — narrow the query rather than treating these as every match.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=true), so the bar is lower, and the description goes beyond them by disclosing the return envelope shape and — importantly — that 'truncated: true' means more matches exist and the agent should narrow the query rather than trust the list as complete. That is real operational behavior an agent needs; it stops short of naming the limit source or pagination mechanics.
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 return format, then args. The Args block largely restates schema fields, which is mildly redundant, but every line adds a constraint (case-insensitivity, omit-for-default, truncation handling) so it stays efficient.
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?
No output schema exists, and the description compensates by documenting the exact response envelope (matches, returned, limit, truncated) and how to react when truncated. Combined with full parameter coverage and the read annotation, an agent has everything needed to call and interpret 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 0% (only titles), so the description must carry the burden and does: 'query' is a case-insensitive substring found in both keys and values, and 'target' is a proxy target name that should be omitted for the default. Both parameters are given meaning the schema alone does not 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 and resource ('Search the config tree for a string') plus the concrete return ('matching config paths'), and even flags the [READ] nature and that results are directly usable by get/set_config_value, which separates it from sibling mutation tools like set_config_value and delete_config_path.
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 usage by noting results feed into get/set_config_value, giving an implicit workflow, but it never states when to prefer search_config over alternatives such as find_route or route_detail, nor any when-not conditions. Usage is inferable rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_detailARead-only
[READ] One service/backend's full detail by name (from list_services).
Args: name: Service name — traefik service name, caddy route config path, or haproxy backend name. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint=true annotation already establishes the safe-read profile, and the '[READ]' prefix merely restates it. The description adds no behavior beyond that: no mention of what happens when the name is unknown, no error/empty handling, and no output-shape note. With annotations covering safety, a 3 is appropriate.
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 one-line purpose, followed by a compact Args block that documents each parameter with no filler. Well-sized for a two-parameter 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?
Covers the operation, both parameters, and their value formats, which is appropriate for a single-record read with no output schema and only one required parameter. The absence of any not-found/empty behavior note is the only meaningful 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 coverage is 0%, so the description carries the full parameter burden it must. It explains that 'name' is a traefik service name, caddy route config path, or haproxy backend name — clarifying provider-specific value formats — and that 'target' is the proxy target name, omitted for the default.
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 ('One service/backend's full detail by name') and pins down scope (single, by name), with the parenthetical '(from list_services)' linking it to its list counterpart. It does not differentiate from other detail siblings like upstream_detail or route_detail, so it falls just 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?
'From list_services' implies the discover-then-detail workflow, which is useful implied usage. However, there is no explicit when-to-use/when-not and no guidance on choosing this over sibling detail tools, so usage is only inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_config_valueADestructive
[WRITE][risk=medium] Set a caddy config subtree (e.g. a route's upstreams); reversible — the prior subtree is fetched first and the undo restores it.
Caddy applies the change immediately. On traefik/haproxy this raises the support matrix's teaching error. Pass dry_run=True to preview.
Refuses the 'admin' subtree: that configures the admin API this tool speaks to, so disabling or moving it would end the connection the undo needs. Change the admin block in caddy's own config file and reload locally. The refusal applies under dry_run too — a preview whose real call would be refused must report that, not a green 'wouldSet'.
Args: path: Slash-separated config path (from search_config / list_routes, e.g. apps/http/servers/srv0/routes/0/handle/0/upstreams). value: The JSON value to write at that path. insert: Insert into an array at that index instead of replacing. This is what re-creating a deleted array element requires — Caddy rejects a create at an index past the (now shorter) array. dry_run: If True, preview without changing. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| value | Yes | ||
| insert | No | ||
| target | No | ||
| dry_run | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations (readOnlyHint=false, idempotentHint=false, destructiveHint=true): it discloses reversibility mechanics (prior subtree fetched, undo restores), immediate application, medium risk, the admin-subtree refusal with its rationale, and that the refusal also applies under dry_run. This is unusually rich behavioral context.
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 [WRITE][risk] tags and behavior before the Args block, and every sentence carries information. It is on the verbose side for a config setter, but no sentence is 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?
With no output schema, the description supplies most of what an agent needs, including hints about the return shape ('a green wouldSet'), refusal reporting, and preview behavior. Minor gap: it doesn't fully describe the success/response payload, but annotations plus prose cover the essentials.
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 does so: it documents path format with an example, the insert flag's array-index semantics (including why it's needed when re-creating a deleted element), dry_run preview, and target omission defaulting. All five params gain meaning beyond the bare 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+resource ('Set a caddy config subtree') and scopes it with an example (a route's upstreams), plus the [WRITE][risk=medium] tag. An agent can immediately distinguish this from get_config_value, delete_config_path, and config_snapshot.
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?
Gives clear context: use for setting subtrees, preview via dry_run=True, unsupported on traefik/haproxy (teaches via matrix error), and points to search_config/list_routes for sourcing the path. It does not explicitly compare itself against delete_config_path or the undo_* siblings, so routing guidance is strong but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_server_stateADestructive
[WRITE][risk=medium] Set an haproxy server's admin state (ready / drain / maint); reversible — the prior admin state is fetched first and the undo restores it.
drain finishes in-flight sessions but takes no new ones; maint removes the server immediately; ready returns it to rotation. On traefik/caddy this raises the support matrix's teaching error. Pass dry_run=True to preview.
Args: backend: Backend name (from list_services). server: Server name inside the backend (from list_upstreams). state: One of ready, drain, maint. dry_run: If True, preview without changing. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| state | Yes | ||
| server | Yes | ||
| target | No | ||
| backend | Yes | ||
| dry_run | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false), the description discloses that the operation is reversible, that the prior admin state is fetched first, and that undo restores it, plus the exact runtime effect of each state. This is meaningful behavioral context the annotations cannot 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?
Front-loaded with [WRITE][risk=medium] and the core action, then state semantics, then a structured Args block. Every section earns its place given the zero schema coverage, though the Args list is somewhat verbose relative to the prose.
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 5-parameter mutation tool with no output schema and no schema descriptions, the definition supplies everything an agent needs: purpose, risk level, reversibility/undo behavior, per-state semantics, valid values, and the preview flag.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the schema defines no enums, so the description must carry all parameter meaning — and it does: it documents all five params, gives the valid state values, points to list_services/list_upstreams for backend/server, and explains dry_run and target (omit for default).
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 (set) and resource (an haproxy server's admin state) with the exact value space (ready/drain/maint). It is clearly distinguishable from siblings like set_server_weight and set_config_value, which act on different resources.
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 when each state applies (drain = finish in-flight, no new sessions; maint = remove immediately; ready = return to rotation) and warns that traefik/caddy raises the support-matrix teaching error. It also recommends dry_run=True for preview. It stops short of naming a fallback tool for the traefik/caddy case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_server_weightADestructive
[WRITE][risk=medium] Set an haproxy server's load-balancing weight (0-256); reversible — the prior weight is fetched first and the undo restores it.
Weight 0 stops new traffic to the server without a state change. On traefik/caddy this raises the support matrix's teaching error. Pass dry_run=True to preview.
Args: backend: Backend name (from list_services). server: Server name inside the backend (from list_upstreams). weight: New weight, 0-256. dry_run: If True, preview without changing. target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| server | Yes | ||
| target | No | ||
| weight | Yes | ||
| backend | Yes | ||
| dry_run | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the prior weight is fetched and the undo restores it (reversibility), the special meaning of weight 0, the cross-proxy error on traefik/caddy, and the dry_run escape hatch. The destructiveHint/idempotentHint flags are enriched rather than merely restated.
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 [WRITE][risk=medium] tag and the core reversible behavior before the secondary notes and Args list. Slightly more verbose than needed in the traefik/caddy aside, but every sentence carries usable 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 mutation tool with no output schema and no schema-level param docs, the description covers purpose, reversibility, error conditions, and preview mode. It could say more about the return shape or permission requirements, but nothing essential to calling 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 0%, so the Args block carries the entire burden, and it documents all five parameters including provenance (backend from list_services, server from list_upstreams, target from config, omit for default) and the weight range. It is strong but omits edge details such as out-of-range handling.
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 (Set) and resource (an haproxy server's load-balancing weight), plus the value domain (0-256). An agent immediately knows what state this mutates and the range it accepts, which distinguishes it from sibling setters like set_server_state or set_config_value.
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?
Gives clear operational context: weight 0 stops new traffic without a state change, traefik/caddy raise a teaching error, and dry_run=True previews. It even names list_services and list_upstreams as sources for the required args. It stops short of explicitly contrasting with the sibling set_server_state, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
traffic_statsARead-only
[READ] Per-service traffic snapshot: requests, latency/rate/sessions where the platform exposes it (traefik /metrics, haproxy stats; caddy returns the support matrix's teaching note).
Args: target: Proxy target name from config; omit for the default.
Returns an envelope: {"services": [...], "returned": N, "limit": L, "truncated": bool, "total": T}. When "truncated" is true this proxy serves more services than were returned.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true; the description goes further by disclosing which backends actually expose metrics (traefik /metrics, haproxy stats) and that caddy returns a 'teaching note' instead — valuable expectation-setting. It also explains the truncation semantics of the envelope, though it omits auth/permission requirements. Strong added value beyond the annotation.
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 a bracketed read marker and the core purpose, followed by compact Args/Returns sections. A couple of parenthetical asides (e.g. the caddy note) could be tightened, but the structure is readable and mostly earns its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by documenting the return envelope fields (services, returned, limit, truncated, total) and the truncation meaning. Combined with the backend coverage caveat, an agent has enough to invoke and interpret it correctly; only cross-tool usage context is thin.
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% for the single optional 'target' param, so the description carries the load. It explains that the value comes from the config and that omitting it selects the default, which meaningfully extends the bare string|null 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?
The description names a specific verb+resource ('Per-service traffic snapshot') and enumerates the metrics returned (requests, latency, rate, sessions), which clearly separates it from config-oriented siblings like list_services and service_detail. It stops short of explicitly naming a sibling it is not, so it lands at 4 rather than 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?
There is no guidance on when to use this tool versus the many related siblings (error_rate_rca, backend_health_rca, error_counters, proxy_overview). The only usage note is about omitting 'target' for the default, which is a parameter detail, not a use-case routing rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_applyADestructive
[WRITE][risk=medium] Apply a recorded undo by dispatching its inverse tool.
The inverse runs through its own governed tool, so it is audited under its own risk tier. Pass dry_run=True to preview the inverse call without executing it. A token can only be applied once.
Args:
undo_id: The undoId from undo_list (or an _undo_id in a write result).
dry_run: If True, preview the inverse tool + params without running it.
target: Passed through to the inverse tool when it accepts a target.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | ||
| dry_run | No | ||
| undo_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true, idempotent=false, readOnly=false; the description adds that the inverse executes through its own governed tool and risk tier (audit behavior) and that tokens are single-use. Useful beyond the annotations, though it doesn't say what the inverse might mutate.
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 [WRITE][risk=medium] tag front-loads the mode and risk, and the body is tight. The Args block partially restates the schema titles, but each line adds semantics, so little is wasted.
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?
No output schema, but the description explains the dispatch model, the dry-run preview path, and the one-time token constraint, which covers the essentials for a mutation tool. It could clarify failure behavior (e.g., applying an already-used token) to be fully 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?
Schema description coverage is 0%, so the description must carry the load, and it documents all three params: undo_id's source, dry_run's preview semantics, and target's pass-through role. The 'target' explanation ('when it accepts a target') is a bit thin but directionally complete.
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 ('apply') and resource ('a recorded undo') plus the mechanism (dispatching its inverse tool). This clearly distinguishes it from the sibling undo_list, which only enumerates tokens.
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?
Gives concrete guidance: undo_id comes from undo_list or an _undo_id in a write result, use dry_run=True to preview, and a token can only be applied once. It stops short of saying when not to use it or when preview is mandatory, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_listARead-only
[READ] List recorded, not-yet-applied undo tokens (most recent first).
Each entry names the original tool, the inverse tool that undo_apply
would run, and a human note. Use the undoId with undo_apply.
Returns {"undos": [...], "returned": N, "limit": L, "truncated": bool}.
truncated is measured (one extra row is fetched), not guessed from a
length coincidence: when it is true there are MORE tokens than shown, so
re-run with a higher limit rather than reporting the list as complete.
Each entry carries effectVerified. False means the original write lost
its response, so the change it reverses is PROBABLE, not confirmed — check
the live state before applying, and do not report the result as a restore
of a state that may never have been reached.
Args: limit: Max rows to return (default 50, capped at 500). target: Unused (undo state is host-local); accepted for CLI uniformity.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only supply readOnlyHint=true; the description goes well beyond that by disclosing the return shape, that truncation is *measured* via an extra-row fetch, and that effectVerified=false means the reversed change is only PROBABLE, with a caution to check live state and not over-report. This is meaningful operational context the annotations cannot carry.
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 purpose and the sibling handoff, then structured paragraphs for return value and the effectVerified caveat. Every sentence carries information, though the emphasis on truncation being 'measured, not guessed from a length coincidence' is slightly verbose for the value it adds.
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 present, the description supplies the return JSON shape, the meaning of every field an agent must act on (returned, limit, truncated, effectVerified), and the follow-up behavior for truncation. Nothing needed to call or interpret 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 0% and no param has an enum, so the description must compensate, and it does fully: limit is documented as default 50 / capped at 500, and target is documented as ignored with the reason (host-local undo state, kept for CLI uniformity).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List recorded, not-yet-applied undo tokens') plus ordering ('most recent first'). The [READ] tag and the reference to undo_apply make it clearly distinguishable from the sibling that actually applies tokens.
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?
Explicitly routes the agent: 'Use the undoId with undo_apply.' and tells it to re-run with a higher limit when truncated rather than reporting a partial list as complete. It lacks an explicit 'when not to use this' condition, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upstream_detailARead-only
[READ] One upstream server's health/state row.
Args: service: Service/backend name. server: Server name or address (from list_upstreams). target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| server | Yes | ||
| target | No | ||
| service | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already covers the safety profile, and the '[READ]' tag simply restates it. Beyond that the description only mentions the default-target behavior, adding no information about error handling, missing servers, or response characteristics for a lookup tool.
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 purpose sentence followed by a tight args list; every line carries needed information and there is no filler or repetition.
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 three-parameter read tool with no output schema, the description covers the purpose, every parameter, and the default-target case. Return-shape information is unnecessary given no output schema, leaving only minor gaps around failure behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the parameter burden, and it does: it names all three parameters and explains each — service/backend name, server name or address sourced from list_upstreams, and target with its omit-for-default semantics. Only type-level detail is absent, which is trivial for string args.
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: retrieving one upstream server's health/state row, which clearly separates it from list_upstreams. It does not explicitly distinguish itself from other singular-detail siblings such as service_detail or route_detail, but the 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?
Usage is implied rather than stated: the description notes 'server' comes from list_upstreams and that omitting target yields the default, which gives workflow context. It never says when to prefer this over list_upstreams or backend_health_rca, so guidance remains implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
version_infoARead-only
[READ] Version / build info (traefik /api/version, haproxy /v2/info; caddy returns a teaching note — its admin API has no version endpoint).
Args: target: Proxy target name from config; omit for the default.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, but the description adds real behavioral value beyond them: it discloses per-target response differences (traefik and haproxy return version data, caddy returns a teaching note because its admin API lacks a version endpoint) and names the source endpoints. It does not describe error behavior when a target is unreachable.
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 operation type and resource, followed by the endpoint detail and an Args block. The caddy parenthetical is slightly verbose but earns its place by preempting a surprising response, so there is little waste.
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 parameterless-or-one-param read probe with no output schema, the description is largely sufficient: it tells the agent what comes back per target and that the target argument is optional. The main residual gap is that no output shape or failure mode is described, which matters a little given there is no 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?
Schema coverage is 0%, so the description must carry the param, and it does: 'target: Proxy target name from config; omit for the default' explains the value's origin (config) and the default semantics. It does not enumerate valid target names, but the single param is otherwise well explained.
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 combination (retrieve version/build info) and goes further to name the underlying endpoints per proxy (traefik /api/version, haproxy /v2/info). No sibling tool performs this function, so it is trivially distinguishable, and the [READ] tag makes the operation type explicit.
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 rather than stated: an agent infers it should call this when it needs build/version data. The only concrete guidance is 'omit for the default,' which is parameter-level, and there are no explicit when-not conditions or named alternatives — though no sibling offers an equivalent capability.
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.
1 tool update
v0.7.0- Changed
set_config_value1 field changed- added
Input schema / properties / insertAdded value: +{ + "default": false, + "title": "Insert", + "type": "boolean" +}
28 tool updates
v0.6.0- First observed
backend_health_rca - First observed
cert_expiry_sweep - First observed
config_snapshot - First observed
delete_config_path - First observed
error_counters - First observed
error_rate_rca - First observed
find_route - First observed
get_config_value - First observed
list_certificates - First observed
list_entrypoints - First observed
list_middlewares - First observed
list_routes - First observed
list_services - First observed
list_upstreams - First observed
load_config - First observed
proxy_overview - First observed
route_conflict_analysis - First observed
route_detail - First observed
search_config - First observed
service_detail - First observed
set_config_value - First observed
set_server_state - First observed
set_server_weight - First observed
traffic_stats - First observed
undo_apply - First observed
undo_list - First observed
upstream_detail - First observed
version_info
TDQS
Scored across 28 tools
Most tools target a distinct resource+action, and the raw-list vs RCA-analysis pattern is consistent. However, pairs like list_certificates/cert_expiry_sweep and traffic_stats/error_counters overlap enough that an agent may need to read descriptions to choose.
All names use snake_case and follow recognizable patterns (list_X, X_detail, set_X, *_rca). Some tools are noun phrases rather than verb_noun (config_snapshot, route_conflict_analysis, undo_apply), so the convention is mostly but not perfectly consistent.
28 tools is heavy for one server, and several granular list/detail pairs plus platform-specific wrappers inflate the surface. Each tool maps to a real operation, but consolidation would improve usability, making this borderline rather than well-scoped.
The surface covers broad proxy diagnostics (health, config, certs, routes, errors, traffic) and includes caddy config writes and haproxy server controls with undo. Gaps remain: no log/restart/reload tools, no traefik config writes, and certificate renewal is only hinted at rather than actionable.
Maintenance
Related MCP Connectors
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
LLM cost optimization gateway, repo token-waste auditor & model arbitrage MCP server.
LLM cost optimization gateway, repo token-waste auditor & model arbitrage MCP server.
Related MCP Servers
- AlicenseAqualityBmaintenanceSecurity, cost, and health governance proxy for MCP infrastructure. Enforces YAML-configurable security policies (blocklists, rate limits, token budgets), tracks real token costs via tiktoken, monitors server health with live JSON-RPC probes. Features OAuth 2.1/OIDC with RBAC, web dashboard, payload normalization, semantic shell AST analysis, mTLS, and a formal STRIDE threat model.459 npm4MIT
- AlicenseAqualityAmaintenanceGoverned Prometheus + Grafana operations — firing-alert and scrape-target RCA, alert noise/flapping analysis, silences, and dashboards, with unbypassable audit logging (MCP + CLI), budget/runaway guards, dry-run, and undo/rollback.39MIT
- AlicenseAqualityAmaintenanceGoverned OPNsense + pfSense firewall operations — gateway-health, rule-shadow, and blocked-traffic RCA, with guarded rule/alias writes, unbypassable audit logging (MCP + CLI), budget/runaway guards, dry-run, and undo/rollback.351MIT
- AlicenseAqualityAmaintenanceGoverned SSO/IAM operations for Keycloak and Authentik — login-failure, stale-permission, client-config, and MFA RCA, with unbypassable audit logging (MCP + CLI), budget/runaway guards, dry-run, and undo/rollback.29MIT