@yawlabs/caddy-mcp
@yawlabs/caddy-mcp
Gestiona servidores web Caddy desde Claude Code, Cursor y cualquier cliente MCP. 18 herramientas + 4 recursos que cubren cada endpoint de la API de administración de Caddy: configuración, rutas, proxies inversos, TLS, PKI, métricas, instantáneas.
Creado y mantenido por Yaw Labs.
Un clic añade esto a tu configuración local de Yaw MCP para que esté disponible en cada sesión de Yaw Terminal. O instálalo manualmente a continuación.
¿Por qué este?
Otros servidores MCP de Caddy envuelven la mitad de la API de administración y se tragan los errores en silencio. Este no.
Cobertura completa de la API de administración — cada endpoint documentado:
/load,/config/*,/id/*,/stop,/adapt,/pki/ca/*,/reverse_proxy/upstreams,/metrics. Sin herramientas de relleno que devuelvan 404.Escrituras concurrentes seguras — usa ETags (
If-Match) para que tus cambios nunca sobrescriban silenciosamente los de otra persona. PresentaHTTP 412 Precondition Failedcomo un mensaje claro, no como un error críptico.Mutaciones seguras por defecto —
caddy_config_setusa por defectooverwriteidempotente (PATCH), noappend(POST). Llamarlo dos veces no duplica tu ruta.Parseo defensivo —
caddy_list_routesnunca falla con configuraciones malformadas, incluso si las rutas son null, los handlers son cadenas o los matchers no son arrays. Probado con regresiones.Sin credenciales filtradas en los errores — si
CADDY_ADMIN_URLcontiene un token en la ruta/consulta, el mensaje de error de conexión muestra solo el origen.Exposición de errores de respaldo — cuando falla un PATCH de escritura TLS y también falla el respaldo POST, se devuelven ambos cuerpos de error para que sepas qué falló realmente.
Anotaciones de herramientas — cada herramienta declara
readOnlyHint,destructiveHinteidempotentHint, para que los clientes MCP puedan omitir confirmaciones en operaciones seguras.Inicio instantáneo — se distribuye como un único paquete con dos dependencias de ejecución (el SDK de MCP + Zod). Sin instalación de
node_modulesde 5 minutos.Endurecimiento de entradas — los nombres de adaptadores, los valores
@id, los nombres de servidores y los ids de CA se validan con regex y límites de longitud. Bloquea la inyección de cabeceras CRLF y ReDoS.
Related MCP server: cognigy-ai-mcp-management-server
Inicio rápido
1. Habilita la API de administración de Caddy
Caddy incluye la API de administración habilitada en localhost:2019 por defecto. Si ejecutas Caddy en Docker o en un host remoto, expónla mediante CADDY_ADMIN_URL.
2. Crea .mcp.json en la raíz de tu proyecto
macOS / Linux / WSL:
{
"mcpServers": {
"caddy": {
"command": "npx",
"args": ["-y", "@yawlabs/caddy-mcp@latest"]
}
}
}Windows:
{
"mcpServers": {
"caddy": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@yawlabs/caddy-mcp@latest"]
}
}
}¿Por qué el paso adicional en Windows? Desde Node 20,
child_process.spawnno puede ejecutar directamente archivos.cmd(eso es lo que esnpxen Windows). Envolverlo concmd /ces la solución estándar. Este archivo es seguro para confirmar: no contiene secretos.
3. Reinicia y aprueba
Reinicia Claude Code (o tu cliente MCP) y aprueba el servidor MCP de Caddy cuando se te solicite.
Eso es todo. Ahora pregúntale a tu asistente de IA:
"Proxy api.local a localhost:3000"
"¿Qué rutas están configuradas en srv0?"
"Muéstrame las métricas de Prometheus"
Configuración
Variable de entorno | Por defecto | Descripción |
|
| URL de la API de administración de Caddy. Establécelo en |
| (ninguno) | Token Bearer opcional para endpoints de administración autenticados. Solo necesario si has configurado Caddy con autenticación. |
| (ninguno) | Directorio para persistir las instantáneas de |
|
| Número de reintentos en fallos transitorios (5xx, errores de red). 4xx y 412 nunca se reintentan. Los POST a |
|
| Tiempo de espera en ms para todas las solicitudes a la API de administración excepto |
|
| Tiempo de espera en ms para el endpoint |
Endpoints de administración por socket unix:
El endurecimiento recomendado por Caddy es mover la API de administración fuera de un puerto de loopback y a un socket unix, donde el acceso se rige por los permisos del sistema de archivos:
{
admin unix//var/run/caddy-admin.sock
}Apunta CADDY_ADMIN_URL a la misma ruta (unix:///var/run/caddy-admin.sock) y las solicitudes se enviarán a través del socket en lugar de TCP. El proceso que ejecuta caddy-mcp necesita permiso de lectura/escritura sobre el archivo del socket. CADDY_API_TOKEN sigue aplicándose si tienes autenticación delante del endpoint.
Clientes MCP alternativos:
Cliente | Archivo de configuración |
Claude Code |
|
Claude Desktop |
|
Cursor |
|
Windsurf |
|
VS Code |
|
Usa el mismo bloque JSON mostrado arriba en cualquiera de estos.
Herramientas
Gestión de configuración (6)
caddy_config_get — Lee la configuración en cualquier ruta JSON (o la configuración completa).
caddy_config_set — Escribe configuración en una ruta. Modos:
overwrite(PATCH, por defecto, idempotente),append(POST),insert(PUT, para posiciones de array).caddy_config_delete — Elimina configuración en una ruta. Requiere
confirm=true(eliminar una ruta padre también elimina todos los descendientes).caddy_config_by_id — Obtiene/establece/elimina configuración por la etiqueta
@id— mucho más fácil que navegar por rutas profundas. La accióndeleterequiereconfirm=true.caddy_load — Reemplaza toda la configuración de forma atómica. Tiempo de espera de 60 segundos para el aprovisionamiento de certificados. Crea automáticamente una instantánea de la configuración anterior.
caddy_revert — Gestiona instantáneas de configuración para revertir cambios. Acciones:
list,save,apply(con confirmación). En memoria, últimas 10.
Operaciones de rutas (4)
caddy_reverse_proxy — Añade un proxy inverso en una sola llamada:
from='api.local' to=['localhost:3000']. Pasa unidopcional para escrituras idempotentes: las llamadas repetidas reemplazan la ruta en su lugar en lugar de duplicarla.caddy_add_route — Añade una ruta con control total de match/handle (cualquier handler de Caddy).
caddy_remove_route — Elimina una ruta por
@id(preferido) o por índice. Requiereconfirm=true.caddy_list_routes — Resumen de rutas legible para humanos. Defensivo: nunca falla con configuraciones extrañas.
TLS y conversión de configuración (2)
caddy_tls — Comprueba o establece ajustes TLS: correo de ACME, URL de la CA de ACME. Primero hace PATCH; en una instalación nueva, hace POST de una configuración mínima. En una configuración existente, hace una fusión profunda en la ruta del emisor y devuelve el resultado con PUT, preservando los elementos hermanos (certificados personalizados,
on_demand, políticas adicionales). Rechaza con un error específico de la forma si la estructura existente es inesperada: nunca sobrescribe.caddy_adapt — Convierte una configuración en cualquier formato de adaptador registrado a JSON de Caddy sin aplicarla.
caddyfile(integrado, por defecto) más cualquier módulo de adaptador compilado en tu binario de Caddy — p. ej.,nginx(caddy-nginx-adapter),yaml(caddy-yaml). Ideal para previsualizar o migrar desde configuraciones existentes.
Operaciones de servidor (6)
caddy_status — Comprobación de conectividad + resumen de configuración (número de servidores, rutas, modo TLS).
caddy_list_servers — Lista todos los servidores HTTP con nombres, direcciones, número de rutas y estado TLS.
caddy_upstreams — Salud de los backends del proxy inverso.
caddy_metrics — Métricas de Prometheus (recuentos de solicitudes, duraciones, conexiones, handshakes TLS). El
filteropcional (coincidencia de subcadena en el nombre de la métrica, conserva las líneas# HELP/# TYPEde las métricas retenidas) ymax_lines(por defecto 500) mantienen las respuestas compactas en servidores ocupados.caddy_pki — Información de la CA y cadenas de certificados (CA por defecto:
local).caddy_stop — Apagado ordenado. Requiere
confirm=truepara evitar accidentes.
Recursos
Datos de solo lectura navegables: los clientes MCP pueden obtenerlos directamente sin llamar a una herramienta:
caddy://config— Configuración JSON completa actual de Caddy.caddy://servers— Resumen de todos los servidores HTTP configurados.caddy://upstreams— Estado de salud de los upstreams del proxy inverso.caddy://metrics— Métricas de Prometheus (formato de exposición de texto). Limitado a las primeras 500 líneas para mantener acotado el contexto del cliente; usa la herramientacaddy_metricsconfilter/max_linespara obtener una salida filtrada o más amplia.
Ejemplos
Añadir un proxy inverso
> "Proxy api.example.com to my app on port 3000"
→ caddy_reverse_proxy({ from: "api.example.com", to: ["localhost:3000"] })Proxy inverso idempotente (seguro de volver a ejecutar desde automatización)
> "Make sure api.example.com points at localhost:3000, with a stable id"
→ caddy_reverse_proxy({ from: "api.example.com", to: ["localhost:3000"], id: "api-prod" })
# First call creates the route under @id="api-prod".
# Subsequent calls with the same id REPLACE in place — no duplicate routes.
# Refuses with a clear error if "api-prod" is already in use by a non-route
# config object (TLS issuer, server, etc.) — @ids are config-global in Caddy.Filtrar métricas de Prometheus
> "Just the HTTP request metrics, please"
→ caddy_metrics({ filter: "http_requests" })
# Keeps sample lines whose metric name contains "http_requests",
# plus their `# HELP` / `# TYPE` lines. Drops the rest.Previsualizar un Caddyfile antes de aplicarlo
> "Convert this Caddyfile to JSON so I can review it:
example.com {
reverse_proxy localhost:8080
}"
→ caddy_adapt({ config: "..." })Diagnosticar rutas lentas
> "Fetch Prometheus metrics and tell me which route is slowest"
→ caddy_metrics()Actualizar una ruta de forma segura mediante @id
> "Update the route with @id 'api-v2' to point to the new backend"
→ caddy_config_by_id({ id: "api-v2", action: "set", value: {...} })
# Uses ETags — you'll get HTTP 412 if someone else changed it firstDespliegue atómico
> "Replace the whole config with this Caddyfile"
→ caddy_adapt({ config: "..." }) # validate first
→ caddy_load({ config: adaptedJson }) # apply atomicallySolución de problemas
"No se puede conectar con la API de administración de Caddy"
Asegúrate de que Caddy esté en ejecución.
caddy runosystemctl status caddy.Comprueba el endpoint de administración. El valor predeterminado es
http://localhost:2019. Si Caddy está en Docker, usa el nombre de host del contenedor.Establece
CADDY_ADMIN_URLen elenvde tu configuración de MCP para que coincida.
"HTTP 412 Precondition Failed"
Alguien (o algo) cambió la configuración entre tu lectura y tu escritura.
La ETag en caché se ha invalidado. Vuelve a leer la configuración e inténtalo de nuevo.
"HTTP 403" al escribir en /load o /config
Tienes restricciones de
admin.listenoadmin.originsestablecidas en tu configuración de Caddy, o te falta una cabeceraAuthorization.Establece
CADDY_API_TOKENen el env de tu configuración de MCP si Caddy espera un token Bearer.
SIGUSR1 / systemctl reload caddy deja de recargar el Caddyfile
Es lo esperado, y no se debe a un error aquí. Desde Caddy 2.11.1,
SIGUSR1recarga desde el archivo en disco solo si la configuración nunca se ha cambiado a través de la API de administración. La primera escritura desde caddy-mcp (o cualquier otro cliente de API) hace que Caddy considere la configuración en ejecución como propiedad de la API, ySIGUSR1se convierte en un no-op.Elige un único propietario por instancia. Si el Caddyfile es la fuente de verdad, usa las herramientas de solo lectura de caddy-mcp (
caddy_status,caddy_list_routes,caddy_adapt) y recarga desde el archivo. Si caddy-mcp es el propietario de la configuración, aplica los cambios concaddy_loaden lugar deSIGUSR1.
Windows: el servidor MCP no se inicia
Usa el patrón
cmd /c npx ...de la sección Inicio rápido. Node 20+ no puede ejecutar archivos.cmddirectamente.
Requisitos
Node.js 20+
Caddy 2.x con la API de administración habilitada (predeterminado:
localhost:2019). Verificado con Caddy 2.11.4; la ruta de escritura@iddepende de la semánticaPATCHque la suite de integración en vivo fija por versión.
Contribución
git clone https://github.com/YawLabs/caddy-mcp.git
cd caddy-mcp
npm install
npm run lint # Biome check
npm run lint:fix # Auto-fix
npm run build # tsup bundle
npm test # Vitest (357 unit tests, +9 POSIX-only unix-socket tests; +13 live-Caddy integration tests gated by CADDY_MCP_INTEGRATION=1)
npm run typecheck # tsc --noEmitConsulta CONTRIBUTING.md para conocer el flujo de trabajo completo, incluido el proceso de lanzamiento.
Licencia
MIT
Available Tools
18 toolscaddy_adaptARead-onlyIdempotent
Convert a config in any registered adapter format to Caddy JSON without loading it. Useful for previewing what a Caddyfile produces, or for porting from nginx/yaml configs when Caddy is built with the matching adapter module ('caddyfile' is built-in; 'nginx', 'yaml', etc. require their adapter modules to be compiled into the Caddy binary). Returns the adapted JSON and any warnings separately. One exception to 'without loading it': on Caddy <= 2.11.4 a Caddyfile 'order' global option is not preview-only. It mutates that Caddy process's directive order, so it carries into every later Caddyfile adapt or load there, and an 'order' line that FAILS (unknown target, bad positional, extra arg) still removes the directive it names -- later Caddyfiles using that directive then fail with "directive 'X' is not an ordered HTTP handler" until another 'order' line re-places it or Caddy restarts. Fixed upstream in caddyserver/caddy#7995, unreleased as of v2.11.4.
| Name | Required | Description | Default |
|---|---|---|---|
| config | Yes | The raw config text (e.g., Caddyfile contents, nginx.conf, yaml) | |
| adapter | No | Config format adapter. Must match an adapter Caddy was built with. Built-in: 'caddyfile' (default). Common external adapters: 'nginx' (caddy-nginx-adapter), 'yaml' (caddy-yaml). | caddyfile |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds a crucial behavioral caveat: on Caddy <= 2.11.4, the 'order' global option mutates the process's directive order despite the preview-only claim. This goes beyond annotations and is essential for correct usage. It also explains the return format (adapted JSON and warnings).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but every part earns its place: the core purpose, the usage context, and the version-specific caveat. It is front-loaded with the primary action, and the detailed exception is justified because it materially affects behavior. Slightly dense but not verbose.
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 tool with a subtle mutation risk, the description covers the version-specific behavior, the return value (adapted JSON plus warnings), and adapter requirements. There is no output schema, so the description correctly explains what the agent will receive. Nothing essential is missing for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both config and adapter, so the baseline is 3. The description adds context about adapter module availability (built-in vs. compiled external modules), which complements the schema and helps the agent choose the right adapter. Not a large addition but useful.
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 opens with a clear verb+resource: 'Convert a config in any registered adapter format to Caddy JSON without loading it.' It distinguishes itself from siblings like caddy_load by explicitly stating 'without loading it', so an agent can tell it apart immediately.
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 states when to use the tool ('previewing what a Caddyfile produces, or for porting from nginx/yaml configs') and specifies the adapter module prerequisite. It also warns about the 'order' mutation on older versions, effectively covering a when-not-to-trust-preview-only scenario.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_add_routeA
Add a route with full control over match conditions and handlers. Supports any Caddy handler (reverse_proxy, file_server, static_response, redirect, encode, headers, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
| match | Yes | Array of match objects (e.g., [{ host: ['example.com'], path: ['/api/*'] }]) | |
| handle | Yes | Array of handler objects (e.g., [{ handler: 'file_server', root: '/var/www' }]) | |
| server | No | Caddy server name (default: srv0) | srv0 |
| terminal | No | Stop processing further routes after this one matches |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false, providing minimal safety context (not read-only, not idempotent, not destructive). The description adds capability details (supports any handler) but does not disclose behavioral traits such as whether the route is appended or overwrites existing routes, validation behavior, or reversibility. This is a moderate gap for a mutation 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?
The description is two sentences, front-loaded with the action, and contains no fluff. Every word adds relevant context about what the tool does and its flexibility.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 100% schema coverage and absence of an output schema, the description covers the tool's purpose and scope effectively. It misses some behavioral context (e.g., route ordering, interaction with terminal flag) but is reasonably complete for a config-modifying 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 100%, so the baseline is 3. The description adds value by enumerating common handler types (reverse_proxy, file_server, etc.) and emphasizing 'full control', which helps the agent understand the flexible, free-form nature of the match and handle parameters beyond the schema's minimal examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action ('Add a route') and its scope ('full control over match conditions and handlers'). It also lists specific handler types, which distinguishes it from sibling tools like caddy_remove_route and caddy_list_routes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'full control' implies this is the general-purpose tool for adding routes, and mentioning 'any Caddy handler' suggests flexibility. However, it does not explicitly state when to use this versus alternatives like caddy_reverse_proxy, nor does it provide any exclusions or when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_config_by_idADestructive
Access config by @id tag. Any config object with an '@id' field can be read, updated, or deleted by its ID instead of needing its full path. This is the recommended way to manage individual routes and config objects. The 'delete' action requires confirm=true. Every 'set' and 'delete' first asks Caddy where id resolves, and refuses an id that does not resolve inside the config tree (including an unknown one). If Caddy resolves id to the config ROOT -- normally because it is the config's own top-level '@id', string or number -- it names the ENTIRE config: 'set' and 'delete' with no subpath (or a lone '...') then act on the whole configuration exactly as caddy_config_set and caddy_config_delete do at the config root -- 'set' replaces it and 'delete' unloads it, the 'admin' block included, so Caddy's admin endpoint can move and CADDY_ADMIN_URL stop reaching it. Both then require confirm=true, snapshot the prior config first so caddy_revert can restore it, and report where the admin endpoint went. A subpath inside it (e.g. 'apps/http') is an ordinary write.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The @id value of the config object | |
| mode | No | For 'set' action: 'overwrite' = PATCH (replace the identified object, or the value at subpath; default). 'append' = POST and 'insert' = PUT behave as in caddy_config_set at the resolved path: with a subpath into an array, POST appends and PUT inserts at the index; PUT also strictly creates an object key (409 if it exists). With NO subpath: for an array element (a route) neither replaces it — POST adds the value as a new element at the end of that array, PUT inserts it just before the identified one, and both are rejected with 'duplicate ID' if the value carries the same @id; for an object held under a key (a server) POST REPLACES it wholesale and PUT fails with 409. Use 'overwrite' to replace in place. | overwrite |
| value | No | New value (required for 'set' action) | |
| action | No | Action to perform | get |
| confirm | No | Must be true to actually delete, and to 'set' when Caddy resolves `id` to the config root (that replaces the ENTIRE config). Ignored for every other 'set'. | |
| subpath | No | Optional sub-path within the identified object |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses extensive behavioral details beyond annotations: delete requires confirm=true, set/delete validate the id resolves, root-id handling replaces/unloads the entire config, snapshots for revert, and admin endpoint reporting. This exceeds the destructiveHint annotation and provides critical safety 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?
The description is dense but every sentence adds value, covering core purpose, edge cases, and safety constraints. It is front-loaded with the primary function and systematically explains special behaviors. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description explains key success/failure behaviors (refusal of unknown ids, root handling, admin endpoint relocation). All 6 parameters are documented in the schema, and the description covers the main edge cases, making it fully sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and parameter descriptions are already detailed, especially for 'mode' and 'confirm'. The description adds behavioral context (e.g., id resolution) but does not substantially extend parameter meaning beyond the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('read, updated, or deleted') and resource ('config object by @id tag'), and explicitly distinguishes it from path-based access. It also identifies it as the recommended way to manage individual routes, differentiating it from sibling tools like caddy_config_set/get.
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 clearly indicates when to use this tool (for individual config objects with @id) and explains the root-id special case where it behaves like caddy_config_set/delete. It does not explicitly name alternatives for non-root operations, but the context implies it's the go-to for individual objects, which is sufficient guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_config_deleteADestructive
Delete config at a JSON path. Removes the config node at the specified path. Deleting a parent node also deletes every descendant -- e.g. deleting 'apps/http/servers/srv0' removes that server and all of its routes. Requires confirm=true. Any path that addresses the config ROOT ('', '/', 'config', '/config/', slash-only variants of those, or any of those followed by a lone '...' segment) addresses the ENTIRE config and unloads it: every app and server goes, and so does the 'admin' block, after which Caddy re-binds its admin endpoint to its default address (localhost:2019, or $CADDY_ADMIN in Caddy's environment). If CADDY_ADMIN_URL points anywhere else, neither this server nor caddy_revert can reach Caddy afterwards. A root delete is snapshotted first, so caddy_revert can restore it while Caddy is still reachable; no other path is snapshotted. To REPLACE the config rather than unload it, use caddy_load.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Config path to delete (e.g., 'apps/http/servers/srv0/routes/0') | |
| confirm | No | Must be true to actually delete the config node (safety) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses important behaviors: deleting a parent deletes descendants, root deletes unload the entire config, only root deletes are snapshotted for caddy_revert, and the admin endpoint may rebind or become unreachable. This is substantial context that prevents catastrophic misuse.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place by clarifying dangerous edge cases, alternatives, and recovery behavior. The core action is front-loaded, with the risky root-path details following naturally. No fluff 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 destructive, high-stakes tool, the description covers outcomes, side effects, snapshot behavior, admin endpoint implications, and the alternative replacement tool. The absence of an output schema is acceptable because the behavioral consequences are fully disclosed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics for the path parameter, especially the root-path variants and their full-unload behavior, and reinforces the confirm=true requirement. This goes beyond simply restating 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?
The description clearly states the tool's action: deleting config at a JSON path and removing the config node. It distinguishes itself from caddy_load by explicitly noting that replacing the config is a different operation. The verb+resource combination is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance around the root-path danger and names caddy_load as the alternative when replacement is intended. It also states that confirm=true is required. It does not enumerate every sibling alternative, but the critical routing decision is covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_config_getARead-onlyIdempotent
Read Caddy config at any JSON path. Returns the full config when path is empty, or a subtree at a specific path (e.g., 'apps/http/servers/srv0/routes').
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Config path (e.g., 'apps/http/servers/srv0') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable behavioral context by explaining the return behavior for empty vs. specific paths, which goes beyond the structured annotations and helps the agent predict the tool's output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action, and every word adds value. It avoids needless detail while including a practical example. No redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter and no output schema, the description covers the essential behaviors: full config vs. subtree, path example, and empty path default. It doesn't mention error handling or exact output format, but these are relatively minor gaps given the tool's simplicity and strong annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the only parameter 'path', but the description enriches its meaning by explicitly stating that an empty path returns the full config and providing a concrete example ('apps/http/servers/srv0/routes'). This goes beyond the schema's generic 'Config path' description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reads Caddy config at a JSON path, with a specific verb ('Read') and resource. It distinguishes itself from siblings by being the generic config getter, while other tools handle writes, deletes, or specific lookups. The clarification of empty path returning the full config adds scope precision.
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 intended usage is implied: use this to read config by path. However, there is no explicit guidance on when to prefer this tool over alternatives like caddy_config_by_id or caddy_status, nor any exclusions. The description provides clear context but no comparative direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_config_setADestructive
Write config at a JSON path. Mode 'overwrite' (default) replaces the value at the path (PATCH) — idempotent, but it replaces the WHOLE subtree there: writing [] to '.../routes' drops every route. Mode 'append' (POST) adds to an array — NOT idempotent: calling twice with the same route duplicates it — but on a non-array key it REPLACES whatever is there, and it cannot create missing parent objects. Mode 'insert' (PUT) inserts at an array index (useful for route ordering), or strictly creates an object key together with any missing parents and fails with 409 if the key already exists — the safe way to create a server or app, including on an instance with no config at all. Any path that addresses the config ROOT ('', '/', 'config', '/config/', a slash-only variant, or any of those followed by a lone '...' segment) addresses the ENTIRE config and requires confirm=true: 'overwrite' and 'append' there REPLACE the whole configuration with value — Caddy runs it exactly as caddy_load would — so every app, server and route not in value is discarded, and so is the 'admin' block unless value carries one. Caddy then re-binds its admin endpoint to the new config's admin.listen, or to its default address (localhost:2019, or $CADDY_ADMIN in Caddy's environment) when it sets none, or to no address at all when it sets admin.disabled; if CADDY_ADMIN_URL points anywhere else, neither this server nor caddy_revert can reach Caddy afterwards. A root write is snapshotted first, so caddy_revert can restore it while Caddy is still reachable; no other path is snapshotted. 'insert' at the root only succeeds after a root caddy_config_delete (Caddy answers 409 on any other instance, including one started with no config), and 'overwrite' is the reverse: after a root caddy_config_delete it answers 404 until 'append', 'insert' or caddy_load re-creates the config. To replace the whole config deliberately, caddy_load does the same thing behind the same gate and also accepts a Caddyfile.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'overwrite' = PATCH (replace existing, default, idempotent; 404 if the key does not exist), 'append' = POST (appends to arrays, NOT idempotent; REPLACES an existing non-array key; cannot create missing parents), 'insert' = PUT (inserts at an array index, or strictly creates an object key and any missing parents; 409 if the key exists) | overwrite |
| path | Yes | Config path to write to (e.g., 'apps/http/servers/srv0/routes') | |
| value | Yes | The JSON value to set at the path | |
| confirm | No | Must be true when `path` addresses the config root ('', '/', 'config', '/config/', slash-only variants, or a lone '...' segment): that write replaces the ENTIRE config (safety). Ignored for every other path. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses major non-obvious consequences: root writes discard all apps, servers and routes not in `value`, may re-bind the admin endpoint and can make Caddy unreachable from both this server and caddy_revert; append is non-idempotent; insert at root only works after a root caddy_config_delete; and root writes are snapshotted while other paths are not. This is exactly the kind of behavioral 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?
The description is long, but every sentence carries unique operational or safety information, covering mode behavior, root-path edge cases, error codes, admin endpoint reachability, and interaction with caddy_load/caddy_revert. The core purpose is front-loaded in the first sentence, and the rest is logically grouped, making it a dense but efficient reference.
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 only a destructive annotation, the description covers error conditions (404, 409), preconditions (root delete before insert), side effects on admin endpoint connectivity, rollback capability, and interactions with sibling tools. An agent can correctly invoke this tool and anticipate all major consequences across every required mode.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds critical meaning beyond the schema's one-line mode definitions: it explains that writing [] to routes drops every route, that append replaces non-array keys and cannot create parents, that insert fails with 409 if the key exists, and the precise root path variants and confirm=true requirement. It enriches the semantics of path, mode, and confirm substantially.
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 opening sentence states a specific action and resource ('Write config at a JSON path'), and the description immediately distinguishes the three modes (overwrite/append/insert) with their HTTP semantics. It also differentiates from caddy_load by noting that tool replaces the whole config while this one targets a path (except at root), and contrasts with caddy_revert and caddy_config_delete in the behavioral descriptions.
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 provides explicit guidance for when to use each mode: 'insert' is called the safe way to create a server or app, 'append' is for arrays, and 'overwrite' for replacement. It explicitly directs whole-config replacements to caddy_load as the deliberate alternative and mentions caddy_revert for rollback after root writes, giving agents clear decision criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_list_routesARead-onlyIdempotent
List all routes on a Caddy HTTP server with a human-readable summary of matchers and handlers, followed by the raw route JSON. Both halves are capped on large servers: the summary at 500 routes, the JSON at 20000 characters (truncated on whole-route boundaries, so it always parses). When either cap trims output, a note says how many routes were omitted -- read the rest with caddy_config_get at 'apps/http/servers//routes'.
| Name | Required | Description | Default |
|---|---|---|---|
| server | No | Caddy server name (default: srv0) | srv0 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds significant behavioral detail: output caps (500 routes/20000 chars), whole-route truncation, omission note, and exact fallback path. This fully discloses edge-case behavior without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences that each add distinct value: purpose/output, caps/truncation, and fallback. No redundant filler; structure is well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list operation with one optional parameter and no output schema, the description covers output format, limits, edge-case behavior, and how to get the complete data. It is fully self-contained for an agent to invoke and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter 'server' is already documented in the schema with default 'srv0' and 100% coverage. The description does not add additional parameter-level detail but doesn't need to given 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?
Clearly states it lists all routes on a Caddy HTTP server and describes the dual output (summary + raw JSON). The use of 'all routes' and explicit reference to caddy_config_get for reading the rest distinguishes it from sibling config-read tools.
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?
Implies use when you want a quick route overview on a specific server, and explicitly directs to caddy_config_get at a specific JSON path for the full untruncated data. The cap behavior and omission note also tell the agent when the result is incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_list_serversARead-onlyIdempotent
List all configured HTTP servers with their names, listen addresses, route counts, and TLS status. Use this to discover server names before calling route tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a safe, read-only, idempotent operation. The description adds transparency about the output content (specific server attributes), which is helpful given there is no output schema. This goes beyond what annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences, front-loaded with the action and output details, followed by a practical usage hint. Every sentence contributes value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list operation with strong annotations, this description is complete. It tells the agent exactly what the tool does, what it returns, and when to invoke it, making tool selection and usage straightforward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema is fully covered by default. Per the baseline for 0-parameter tools, the description appropriately focuses on behavior and output rather than parameter explanations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the operation as listing all configured HTTP servers and specifies the exact data returned (names, listen addresses, route counts, TLS status). This distinguishes it from sibling tools like caddy_list_routes, which focus on routes rather than servers.
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 explicitly states when to use the tool: 'Use this to discover server names before calling route tools.' This provides a clear workflow context, though it does not explicitly name alternatives or exclusion cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_loadADestructiveIdempotent
Replace the entire Caddy configuration atomically. Accepts a JSON config object, or a Caddyfile string with format='caddyfile'. This is the safest way to make large config changes. Runs on CADDY_LOAD_TIMEOUT (55 s by default), like every config change; a load that times out is not retried and may still apply, so re-read the config before loading again. Requires confirm=true: this DISCARDS the entire running config, including servers and routes not present in the supplied config. The prior config is snapshotted first and can be restored with caddy_revert.
| Name | Required | Description | Default |
|---|---|---|---|
| config | Yes | Full config — JSON object or Caddyfile text string | |
| format | No | Config format: 'json' (default) or 'caddyfile' | json |
| confirm | No | Must be true to replace the running configuration (safety) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite strong annotations (destructiveHint=true, idempotentHint=true), the description adds substantial extra context: atomic replacement, disposal of the entire running config, snapshot and revert via caddy_revert, and the non-retry/may-still-apply behavior on timeout. It explicitly states confirm=true is required and clarifies the destructive impact. This goes far beyond the annotations and is directly actionable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, progressively delivering the core action, safety/timeout details, and the confirm requirement. It is front-loaded with the primary purpose and contains no filler. Every clause contributes critical information, making it highly concise and well-structured.
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 destructive, full-config replacement tool, the description covers the essential elements: action, accepted formats, timeout behavior, confirm requirement, and revert path. It omits explicit output/return information, but there is no output schema, and the caution to re-read config implies the operation's effects may not be immediately visible. This is sufficient for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all three parameters. The description mostly mirrors the schema for config and format, and for confirm it reiterates the safety requirement without adding new parameter-level meaning. The added value lies in behavioral context (timeout, discard) rather than parameter semantics, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific action: 'Replace the entire Caddy configuration atomically.' It clearly identifies the resource (entire Caddy configuration) and the verb (replace). The mention of atomicity and acceptance of JSON or Caddyfile distinguishes it from sibling tools like caddy_config_set (incremental changes) and caddy_add_route (route-specific).
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 states it is 'the safest way to make large config changes,' giving clear context for when to use it. However, it does not explicitly mention alternatives or exclusion criteria (e.g., 'for incremental changes, use caddy_config_set'). It does provide related caution about timeout and re-reading config, which supports proper usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_metricsARead-onlyIdempotent
Get Prometheus metrics from Caddy. Shows request counts, durations, TLS handshake stats, active connections, and more. Output can be megabytes on busy servers -- use filter to keep only metrics whose name contains a substring (e.g. 'http_requests' or 'tls'); HELP/TYPE comment lines for retained metrics are kept. Filter-mode drops blank lines and free-form '# comment' lines, keeping only '# HELP'/'# TYPE' lines for matching metrics; the '# EOF' end-of-file marker is always preserved. Use max_lines to cap the response (default 500); a trailing comment reports how many lines were dropped.
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | Substring to match against metric names. Keeps sample lines whose metric name contains this substring, plus their `# HELP` and `# TYPE` comment lines. Empty/absent = no filtering. Label values are NOT matched -- use a Prometheus-aware client for label filtering. | |
| max_lines | No | Maximum number of output lines (default 500). Excess lines are dropped and a summary is appended. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint. The description adds substantial behavioral context: output can be megabytes, filter-mode drops blank/free-form comments but preserves HELP/TYPE lines, '# EOF' is always kept, max_lines defaults to 500, and a trailing comment reports dropped lines. This goes well beyond the structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized—four sentences that lead with the core purpose, then dive into parameter behavior with examples. Every sentence carries unique, essential information; there is no repetition or filler. The structure flows logically from purpose to usage to edge cases.
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 tool with no output schema, the description covers the return format implicitly (Prometheus text) and explicitly covers filtering semantics, line handling, size limits, and the trailing summary. It gives the agent enough context to anticipate output characteristics and pitfalls, making it complete for invocation and result handling.
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?
Although schema coverage is 100%, the description significantly enriches parameter meaning. It explains that filter is a substring match on metric names, that HELP/TYPE lines for matching metrics are retained, and that label values are NOT matched. For max_lines, it details the default (500) and the appended summary line, which the schema does not fully convey.
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 opens with a specific verb+resource: 'Get Prometheus metrics from Caddy.' It lists concrete metric categories (request counts, durations, TLS handshake stats, active connections) and clearly distinguishes this tool from sibling tools like caddy_config_get or caddy_status, which serve different purposes.
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 provides clear guidance on when to use the filter and max_lines parameters, including examples and edge-case behavior (label values not matched). It does not explicitly contrast with alternatives, but among the siblings none offer metrics, so the context is clear enough for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_pkiARead-onlyIdempotent
Get PKI certificate authority info or the CA certificate chain.
| Name | Required | Description | Default |
|---|---|---|---|
| ca | No | CA ID (default: 'local') | local |
| certificates | No | If true, return the full CA certificate chain |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds little beyond repeating the certificates parameter's effect, and does not disclose additional behavioral traits such as output format or error behavior. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that begins with the verb and directly states the tool's purpose. No filler or redundant information, making it highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a simple read-only getter with no output schema, yet the description is vague about what 'info' includes or what the response format looks like. While annotations and schema cover parameters and safety, the description lacks contextual detail about the return value or edge cases, making it minimally adequate.
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?
Input schema coverage is 100% (both 'ca' and 'certificates' have descriptions). The description does not add any additional meaning beyond the schema, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with the verb 'Get' and clearly identifies the resource as 'PKI certificate authority info or the CA certificate chain.' This is specific and distinguishes it from siblings like caddy_config_get or caddy_status, which have different purposes.
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 its usage as a read-only query for PKI CA information, but does not explicitly state when to use it over alternatives like caddy_tls or caddy_config_get. No exclusions or alternative tool references are provided, so guidance is only implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_remove_routeADestructive
Remove a route. Target by @id (preferred — stable across reorderings) or by array index on a specific server. Index-based removal is a two-step read-then-delete and can race against concurrent edits; prefer @id when possible. Only the @id mode is idempotent: a repeat call cannot remove a different route, it just reports the id as gone. The index mode is NOT — Caddy re-packs the routes array after a removal, so calling with index 2 twice removes TWO DIFFERENT routes. @ids are config-global in Caddy (NOT route-scoped): if id resolves to a non-route object (TLS issuer, server, etc.) the call refuses rather than deleting it.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | The @id of the route to remove (preferred — stable even if routes get reordered) | |
| index | No | Zero-based index of the route in the server's routes array (only used if id is not provided) | |
| server | No | Caddy server name when using index (default: srv0). Ignored when id is provided. | srv0 |
| confirm | No | Must be true to actually remove the route (safety) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations by clarifying that idempotency is mode-dependent: @id mode is idempotent, while index mode is not and can remove different routes on repeated calls. It also discloses the two-step read-then-delete race, the config-global scope of @ids, and the refusal behavior when the id resolves to a non-route object. This is excellent behavioral disclosure for a destructive 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?
Every sentence carries essential operational or safety information. The description is front-loaded with the core action, then systematically covers target selection, idempotency differences, concurrency hazards, and scope semantics. There is no filler or repetition that does not earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent tool with no output schema, the description is remarkably complete. It addresses the main failure modes (race conditions, repeated index removal, non-route @id targets), explains the confirm-based safety mechanism indirectly through the schema, and gives the agent enough context to call the tool correctly and avoid destructive mistakes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful context beyond the schema: it explains why id is preferred, warns that index removal re-packs the routes array, and clarifies that @ids are config-global rather than route-scoped. This enriches the agent's understanding of how id and index actually behave.
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 opens with a direct, specific statement—'Remove a route'—and immediately identifies the two targeting modes (@id or index on a specific server). This clearly distinguishes it from generic config deletion tools and from route-modification siblings like caddy_add_route or caddy_list_routes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: prefer @id because it is stable across reorderings, avoid index mode when possible because it can race against concurrent edits. It does not explicitly compare this tool to alternatives like caddy_config_delete, but the contextual guidance for choosing between the tool's own modes is strong and concrete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_reverse_proxyADestructive
Add a reverse proxy route. The most common operation — just specify where traffic comes from and where it goes. Example: from='api.local' to=['localhost:3000']. When id is OMITTED the route is appended to the server's routes array — calling the tool twice with the same args produces TWO duplicate routes (non-idempotent). When id is SUPPLIED the route is written via PATCH under that @id, so repeat calls REPLACE in place (idempotent). Strongly recommended: supply a stable id for any route managed from automation or production tooling. Note: @ids are config-global in Caddy (NOT route-scoped). If id collides with an @id used by a non-route object (TLS issuer, server, etc.) the call refuses with an error rather than clobbering it. Once an @id is registered to a route under one server, subsequent calls update that route in place regardless of the server argument. Upstream scheme is honored: an https:// upstream gets a TLS transport and defaults to port 443, anything else is dialed in the clear. A to list that MIXES https:// and non-https entries is refused — the TLS transport applies to the whole handler, not per-upstream — so split those into two routes or use caddy_add_route.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Optional stable @id for the route. When set, repeat calls REPLACE the route in place (idempotent). When omitted, the route is APPENDED — calling twice with identical args creates a duplicate route. @ids are config-global in Caddy: if this id is already used by a non-route object the call refuses rather than clobbering it. | |
| to | Yes | Upstream addresses, at least one (e.g., ['localhost:3000', 'localhost:3001']). An 'https://' prefix dials the upstream over TLS (port 443 unless one is given); http:// and bare addresses are dialed in the clear. Do not mix https:// and non-https entries in one call. | |
| from | Yes | Domain, path, or domain/path to match (e.g., 'api.local', '/api/*', 'app.local/ws') | |
| server | No | Caddy server name (default: srv0) | srv0 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations supply safety hints (destructiveHint=true, idempotentHint=false), and the description adds substantial context beyond them: conditional idempotency based on `id`, duplicate-route creation on repeat calls, refusal on non-route @id collision, server argument being ignored after @id registration, and TLS transport behavior. This is rich behavioral disclosure.
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?
Dense and front-loaded with the primary purpose and example first, then edge cases. It is on the long side and repeats several schema-documented facts, but every sentence contributes operational detail rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent mutation tool with no output schema, the description is thorough: it discloses idempotency semantics, collision refusal, cross-server @id behavior, and TLS handling. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters, including the @id collision behavior and the mixed-scheme restriction. The description largely restates those semantics, adding only a concrete example; baseline 3 is appropriate when the schema carries the load.
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 ('Add a reverse proxy route') and immediately scopes it as the most common operation. It also names caddy_add_route as the alternative for the mixed-scheme case, distinguishing it from 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?
Explicitly covers when to omit vs supply `id`, gives a hard recommendation for automation/production, explains the config-global @id scope, and routes the mixed-scheme case to caddy_add_route. When-to-use and when-not-to-use are both present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_revertADestructive
Manage config snapshots for rollback. Snapshots are auto-captured before caddy_load, and before a caddy_config_delete or caddy_config_set at the config root (any path that addresses the whole config), and before a caddy_config_by_id set or delete whose @id resolves to the root with no subpath (or a lone '...'); no other delete or set is snapshotted. Last 10. By default they live in memory only and are LOST when this server restarts -- set CADDY_MCP_SNAPSHOT_DIR to a writable directory to persist them across restarts (they contain full Caddy configs, so pick the location deliberately). Actions: 'list' shows snapshots with timestamps, 'save' manually captures the current config, 'apply' restores a snapshot (requires confirm=true).
| Name | Required | Description | Default |
|---|---|---|---|
| index | No | Snapshot index for 'apply' (0 = most recent, default) | |
| action | Yes | Action to perform | |
| confirm | No | Must be true to actually apply a snapshot (safety) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations only declare destructiveHint=true, but the description adds crucial behavioral context: snapshots retain only the last 10, are memory-only by default and lost on restart, contain full Caddy configs, and apply requires confirm=true. This substantially exceeds what annotations alone communicate and helps the agent avoid destructive mistakes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place, covering auto-capture rules, retention, persistence, safety, and the action enum. It front-loads the primary purpose before diving into edge-case behavior, making it scannable for an agent.
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 destructive tool with three parameters and no output schema, the description covers the full behavioral contract: what is snapshotted, retention limits, persistence options, safety confirmation, and how each action behaves. Nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already describes all three parameters, the description enriches them: it defines what each action does, states that index 0 means most recent, and clarifies that confirm=true is a mandatory safety gate for apply. This adds real decision-making value beyond the raw 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 opens with a clear verb-resource pairing, 'Manage config snapshots for rollback,' and immediately distinguishes this tool from the config-mutation siblings by focusing on snapshot lifecycle. It then enumerates the exact actions (list, save, apply), removing any ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when snapshots are auto-captured, when they are not ('no other delete or set is snapshotted'), and how to manually invoke each action. It also gives an operational guideline for persistence via CADDY_MCP_SNAPSHOT_DIR, which is exactly the kind of conditional usage an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_statusARead-onlyIdempotent
Check Caddy connectivity and get a config summary: servers, routes, listen addresses, and TLS status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safe read-only nature is clear. The description adds valuable context about what the summary contains (servers, routes, listen addresses, TLS status), going beyond the annotations. It does not discuss failure modes, but the annotation coverage lowers the bar and the added context is meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that packs significant information: the verb ('Check'), the resource ('Caddy connectivity'), and a detailed summary content list. Every word earns its place, with no redundancy or 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?
Given the tool's simplicity (no params, no output schema), the description is complete. It explains both the action (connectivity check) and the expected return content (config summary with servers, routes, listen addresses, TLS status). Rich annotations further cover the safety profile, so the description sufficiently covers all necessary contextual information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema is trivially complete (coverage 100%). Per guidelines, 0 params receives a baseline score of 4 because there are no parameter gaps to address. The description adds no parameter info, but none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'Check Caddy connectivity and get a config summary'. It also enumerates the summary content (servers, routes, listen addresses, TLS status), which distinguishes it from sibling tools like caddy_config_get (full config) and caddy_list_servers (specific server list).
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 stating the tool provides connectivity checks and a config summary, but it does not explicitly recommend it over alternatives or mention when not to use it. It provides clear context for when this tool is appropriate, but lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_stopADestructive
Gracefully shut down the Caddy server. Requires confirm=true to prevent accidental shutdown.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | Yes | Must be true to confirm shutdown |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds meaningful context by specifying 'gracefully' shutdown and the confirm=true safeguard, which helps the agent understand the manner and safety requirement of the operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action, and every word contributes value. There is no filler or redundant elaboration beyond the necessary confirmation note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter stop operation with clear annotations and full schema coverage, the description is sufficient. It does not explain return values or edge cases, but given the low complexity and existing structured data, that is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully describes the confirm parameter with 100% coverage ('Must be true to confirm shutdown'). The description only repeats this requirement without adding new semantic detail, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'shut down' with a clear resource 'Caddy server', and it is distinct from sibling tools that handle config, status, or routes. The action and target are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies its use (to stop the server) but does not explicitly state when to use it versus alternatives or when not to use it. The confirm requirement is a prerequisite, not a usage guideline. It lacks explicit context for selection among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_tlsAIdempotent
Get or configure TLS/HTTPS settings. Actions: 'status' shows current TLS config, 'set_email' sets the ACME email, 'set_acme_ca' sets the ACME CA URL, 'set_acme_profile' sets the ACME profile (Caddy 2.10+), 'ech_status' reads the Encrypted ClientHello config at apps/tls/encrypted_client_hello (Caddy 2.10+, read-only here). Works on both fresh and existing Caddy instances, including one with no config at all: the set_* actions create apps/tls, and any missing parents, when it is not set. Writes target policies[0].issuers[0] only, and only when that issuer's module is 'acme' -- on a multi-policy TLS config, or one whose first issuer is 'internal' (Caddy's local CA), edit the intended issuer with caddy_config_set instead.
| Name | Required | Description | Default |
|---|---|---|---|
| ca | No | ACME CA URL (for 'set_acme_ca' action) | |
| No | ACME email address (for 'set_email' action) | ||
| action | Yes | Action to perform | |
| profile | No | ACME profile name (for 'set_acme_profile'). Requires Caddy 2.10+ and a CA that offers profiles; Let's Encrypt uses 'shortlived' for 6-day certificates. Valid names are defined by the CA, not by Caddy. EXPERIMENTAL upstream (the ACME profiles spec is still a draft; Caddy marks the field 'subject to change' and may rename or drop it). Caddy accepts any name on load, so a success here does not mean the CA offers it: if this issuer's CA does not advertise the name, every order from this issuer fails at issuance time, reported only in Caddy's own logs. Caddy then either falls through to the next issuer in the policy, which issues WITHOUT the profile, or -- when this is the policy's only issuer, which is the shape this tool creates -- keeps retrying and issues no certificate at all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark the tool as idempotent and non-destructive, the description reveals important side effects: set_* actions create apps/tls and missing parents, and writes only target policies[0].issuers[0] when that issuer's module is 'acme'. It also discloses version constraints (Caddy 2.10+), read-only behavior for ech_status, and the failure semantics of set_acme_profile when a CA does not support the profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence contributes operational guidance: purpose, action list, version gates, creation behavior, and the alternative path. It is front-loaded with the main purpose and action enumeration, and the longer edge-case clauses earn their 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?
The description covers version requirements, fresh-vs-existing behavior, exact mutation targets, exclusions, and the alternative tool. The only notable gap is the lack of explicit return-value shape for status/ech_status, but since there is no output schema and the read actions are described as showing/reading config, this is a minor omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining how the action parameter changes config: set_* creates missing parents and targets only the first issuer under specific conditions. It also reinforces the meaning of each action, though ca and email formats remain mostly handled by 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?
The opening line states a specific verb and resource: 'Get or configure TLS/HTTPS settings.' The description then enumerates the five actions, making the tool's scope unmistakable. It also differentiates from generic config tools by pointing to caddy_config_set as the fallback for unsupported TLS shapes.
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 explicitly says when the tool is appropriate: 'Works on both fresh and existing Caddy instances, including one with no config at all.' It also gives a clear when-not-to-use rule by instructing that on multi-policy TLS configs or with an 'internal' first issuer, you should 'edit the intended issuer with caddy_config_set instead.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
caddy_upstreamsARead-onlyIdempotent
Caddy's /reverse_proxy/upstreams array (address, num_requests, fails), returned verbatim. On Caddy 2.11.2+ it is not the configured upstream list. Dynamic-upstream backends stay listed about 1 h (up to ~65 min) after the dynamic source last returned them, even after a config change removes them, so an address may appear that no current config references. A backend with requests in flight can appear twice when its resolved address differs from the entry's text (dynamic upstreams, tcp/ or unix// dials, placeholder dials). That extra copy always shows fails 0 and repeats num_requests, so do not sum num_requests across entries.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint), the description discloses several non-obvious behaviors: the data is returned verbatim, it may not reflect the current config on certain versions, dynamic entries persist for a while, and duplicates can appear with specific characteristics. This is exactly the kind of behavioral context that prevents an agent from drawing wrong conclusions, and it does not contradict any 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?
The description is front-loaded with the core purpose and then expands into necessary caveats. It is longer than average, but every sentence adds unique operational value (version-specific behavior, persistence, duplication, summation warning). It is not wordy, though it could be tightened with bullet points for the caveats.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description carries the full burden of explaining what to expect from the tool. It covers the array shape, the fields per entry, the version caveat, the persistence timing, the duplicate-entry scenario, and the summing pitfall. This is sufficient for an agent to invoke the tool and interpret the result without being misled.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and the schema has no properties, so there is nothing for the description to explain. Baseline for 0 params is 4. The description makes no parameter claims and correctly focuses on output behavior instead.
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 opens with a precise statement of what the tool returns: Caddy's /reverse_proxy/upstreams array with the exact fields (address, num_requests, fails), returned verbatim. It also distinguishes this tool from configuration retrieval by noting that on Caddy 2.11.2+ it is not the configured upstream list, and the reader can infer it is meant for inspecting runtime upstream state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context—it tells you when the data is misleading (after config changes, with dynamic upstreams) and warns against summing num_requests. However, it never explicitly says 'use this when you need runtime upstream statistics' or contrasts it with sibling tools like caddy_config_get. The caveats are useful but the when/why 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.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v2.5.6- Changed
caddy_config_by_id1 field changed- changed
Input schema / properties / confirm / descriptionPrevious value: -"Must be true to actually delete (only enforced for action='delete')"New value: +"Must be true to actually delete, and to 'set' when Caddy resolves `id` to the config root (that replaces the ENTIRE config). Ignored for every other 'set'."
- Changed
caddy_config_set1 field changed- added
Input schema / properties / confirmAdded value: +{ + "default": false, + "description": "Must be true when `path` addresses the config root ('', '/', 'config', '/config/', slash-only variants, or a lone '...' segment): that write replaces the ENTIRE config (safety). Ignored for every other path.", + "type": "boolean" +}
1 tool update
v2.5.4- Changed
caddy_tls1 field changed- changed
Input schema / properties / profile / descriptionPrevious value: -"ACME profile name (for 'set_acme_profile'). Requires Caddy 2.10+ and a CA that offers profiles; Let's Encrypt uses 'shortlived' for 6-day certificates. Valid names are defined by the CA, not by Caddy."New value: +"ACME profile name (for 'set_acme_profile'). Requires Caddy 2.10+ and a CA that offers profiles; Let's Encrypt uses 'shortlived' for 6-day certificates. Valid names are defined by the CA, not by Caddy. EXPERIMENTAL upstream (the ACME profiles spec is still a draft; Caddy marks the field 'subject to change' and may rename or drop it). Caddy accepts any name on load, so a success here does not mean the CA offers it: if this issuer's CA does not advertise the name, every order from this issuer fails at issuance time, reported only in Caddy's own logs. Caddy then either falls through to the next issuer in the policy, which issues WITHOUT the profile, or -- when this is the policy's only issuer, which is the shape this tool creates -- keeps retrying and issues no certificate at all."
2 tool updates
v2.5.3- Changed
caddy_config_by_id1 field changed- changed
Input schema / properties / mode / descriptionPrevious value: -"For 'set' action: 'overwrite' = PATCH (replace existing, default), 'append' = POST (add to arrays, create on objects), 'insert' = PUT (insert at array index)"New value: +"For 'set' action: 'overwrite' = PATCH (replace the identified object, or the value at subpath; default). 'append' = POST and 'insert' = PUT behave as in caddy_config_set at the resolved path: with a subpath into an array, POST appends and PUT inserts at the index; PUT also strictly creates an object key (409 if it exists). With NO subpath: for an array element (a route) neither replaces it — POST adds the value as a new element at the end of that array, PUT inserts it just before the identified one, and both are rejected with 'duplicate ID' if the value carries the same @id; for an object held under a key (a server) POST REPLACES it wholesale and PUT fails with 409. Use 'overwrite' to replace in place."
- Changed
caddy_config_set1 field changed- changed
Input schema / properties / mode / descriptionPrevious value: -"'overwrite' = PATCH (replace existing, default, idempotent), 'append' = POST (add to arrays / create keys, NOT idempotent), 'insert' = PUT (insert at array index)"New value: +"'overwrite' = PATCH (replace existing, default, idempotent; 404 if the key does not exist), 'append' = POST (appends to arrays, NOT idempotent; REPLACES an existing non-array key; cannot create missing parents), 'insert' = PUT (inserts at an array index, or strictly creates an object key and any missing parents; 409 if the key exists)"
1 tool update
v2.4.0- Changed
caddy_reverse_proxy3 fields changed- changed
Input schema / properties / to / descriptionPrevious value: -"Upstream addresses (e.g., ['localhost:3000', 'localhost:3001'])"New value: +"Upstream addresses, at least one (e.g., ['localhost:3000', 'localhost:3001']). An 'https://' prefix dials the upstream over TLS (port 443 unless one is given); http:// and bare addresses are dialed in the clear. Do not mix https:// and non-https entries in one call." - added
Input schema / properties / to / items / minLengthAdded value: +1 - added
Input schema / properties / to / minItemsAdded value: +1
1 tool update
v2.3.2- Changed
caddy_tls2 fields changed- changed
Input schema / properties / action / enumPrevious value: -[ - "status", - "set_email", - "set_acme_ca" -]New value: +[ + "status", + "set_email", + "set_acme_ca", + "set_acme_profile", + "ech_status" +] - added
Input schema / properties / profileAdded value: +{ + "description": "ACME profile name (for 'set_acme_profile'). Requires Caddy 2.10+ and a CA that offers profiles; Let's Encrypt uses 'shortlived' for 6-day certificates. Valid names are defined by the CA, not by Caddy.", + "type": "string" +}
18 tool updates
v2.2.0- First observed
caddy_adapt - First observed
caddy_add_route - First observed
caddy_config_by_id - First observed
caddy_config_delete - First observed
caddy_config_get - First observed
caddy_config_set - First observed
caddy_list_routes - First observed
caddy_list_servers - First observed
caddy_load - First observed
caddy_metrics - First observed
caddy_pki - First observed
caddy_remove_route - First observed
caddy_reverse_proxy - First observed
caddy_revert - First observed
caddy_status - First observed
caddy_stop - First observed
caddy_tls - First observed
caddy_upstreams
TDQS
Scored across 18 tools
Multiple tools can write config (caddy_config_set, caddy_config_by_id, caddy_load, caddy_add_route, caddy_reverse_proxy), and delete overlaps similarly (caddy_config_delete vs caddy_remove_route), so boundaries are not perfectly clean. However, the descriptions go to great lengths to explain when each applies (low-level path vs @id vs convenience wrapper), making selection tractable for an agent.
Every tool carries the caddy_ prefix in consistent snake_case, forming recognizable families (config_get/set/delete, list_servers/routes, add_route/remove_route). Minor deviation: several tools are bare nouns (caddy_status, caddy_metrics, caddy_upstreams, caddy_pki) rather than verb_noun, but the overall pattern is predictable.
18 tools is on the heavier side but each earns a place, spanning config CRUD, route helpers, snapshots, TLS/PKI, metrics, and lifecycle. Slightly over what a minimal config server would need, but well-scoped for Caddy's breadth.
The surface covers the full config lifecycle (read, write, delete, whole-config load, snapshot/revert), route management, TLS/PKI configuration, observability (metrics, upstreams), format adaptation, and graceful shutdown. No obvious dead ends for administering Caddy via its admin API.
Maintenance
Related MCP Connectors
Zero-dependency Cloudflare Worker gateway turning websites and REST APIs into MCP tools.
Marketo MCP server for AI. 130 tools to operate Marketo from Claude, Cursor, or ChatGPT.
Remote MCP for RunComfy: ComfyUI deployments, hosted models, LoRA training. 31 tools.
214 tools for AI agents over one MCP endpoint: image, video, audio, 3D, data, storage, mail, GPUs.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables inspection and management of Caddy reverse proxy configuration via CaddyUI's REST API, including proxy hosts, redirection hosts, raw routes, and TLS certificates.3MIT
- AlicenseAqualityAmaintenanceMCP server for Cognigy.AI - 132 tools that let Claude, Cursor & other AI assistants build, configure, test & operate conversational AI agents via the Model Context Protocol.13870 npm2MIT
- AlicenseAqualityBmaintenanceMCP server for safely inspecting and operating a local Caddy admin API. Provides read-only tools and dry-run mutations for config management.7MIT
- AlicenseAqualityDmaintenanceEnables management of Caddy web server via admin API, allowing inspection of routes, upstream health, certificates, and configuration reloading.16MIT