mcpField
C
Caddy MCP Server

Caddy MCP Server

本地服务
yaw.sh云与基础设施131 天前更新

关于 Caddy MCP Server

Caddy MCP Server 将 MCP 客户端连接到 Caddy 管理 API,用于管理 Web 服务器。工具和资源涵盖配置、路由、反向代理、TLS、PKI 与指标,并为并发及破坏性更改提供防护。

主要功能

  1. 01覆盖 Caddy 管理 API 端点
  2. 02管理配置与路由
  3. 03检查反向代理和指标
  4. 04管理 TLS 与 PKI
  5. 05通过 ETag 保护并发写入
  6. 06工具标注及更改快照

适用场景

  1. 01更新 Caddy 路由且避免重复添加
  2. 02检查已配置的路由与上游
  3. 03查看 TLS、PKI 或服务器指标
  4. 04安全恢复配置更改

MCP 相关

向 MCP 客户端提供 18 个工具和 4 个资源,用于封装 Caddy 管理 API。工具声明只读、破坏性及幂等提示;配置更改可使用 ETag 和快照。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"yawlabs-caddy": {
"command": "npx",
"args": [
"-y",
"@yawlabs/caddy-mcp"
]
}
}
}
启动命令npx -y @yawlabs/caddy-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@yawlabs/caddy-mcp2.6.0

工具

18

收录的工具列表 · 更新于 2 周前

参数类型必填说明
pathstring否配置路径(例如 'apps/http/servers/srv0')

详细介绍

@yawlabs/caddy-mcp

添加到 Yaw MCP

单击即可将其添加到本地 Yaw MCP 配置中,这样每次启动 Yaw Terminal 会话时都能使用。也可以在下方手动安装。

npm 版本 许可证:MIT GitHub 星标

通过 Claude Code、Cursor 和任何 MCP 客户端管理 Caddy Web 服务。 提供 18 个工具和 4 个资源,涵盖 Caddy 管理 API 参考中的所有端点,包括配置、路由、反向代理、TLS、PKI、指标和快照。

由 Yaw Labs 构建并维护。

为什么选这个?

其他 Caddy MCP 服务只包装了半数管理 API,而且会悄悄吞掉错误。这个不会。

  • 完整覆盖管理 API — 涵盖 Caddy 管理 API 参考中的所有端点:/load、/config/*、/id/*、/stop、/adapt、/pki/ca/*、/reverse_proxy/upstreams、/metrics。没有会返回 404 的占位工具。刻意不包装 Caddy 的 Go 运行时调试端点(/debug/pprof/*、/debug/vars)——如需查看泄漏趋势,可使用带有 filter: "go_goroutines" 或 "go_memstats" 的 caddy_metrics,这些数据来自同一个管理注册表;如需堆栈转储、CPU 性能分析和跟踪,请直接 curl 管理端点(Caddy 性能分析文档)。
  • 并发写入安全 — 使用 ETag(If-Match),确保更改不会悄悄覆盖其他人的内容。遇到 HTTP 412 Precondition Failed 时会显示清晰的提示,而非晦涩的错误。
  • 默认安全的修改操作 — caddy_config_set 默认使用幂等的 overwrite(PATCH),而不是 append(POST)。重复调用不会产生重复路由。对配置根节点的写入会替换整个配置,包括管理端点,因此除非设置 confirm=true,否则会拒绝该操作;并且会像 caddy_load 一样先创建快照。
  • 防御性解析 — 即使路由为 null、处理器为字符串或匹配器不是数组,caddy_list_routes 也不会因格式错误的配置而崩溃。已通过回归测试。
  • 错误中不会泄露凭据 — 如果 CADDY_ADMIN_URL 的路径或查询参数中包含令牌,连接失败消息只会显示来源地址。
  • 提供备用错误信息 — TLS 写入的 PATCH 失败且 PUT 备用请求也失败时,会返回两者的错误正文,让你了解实际出了什么问题。
  • 工具注解 — 每个工具都声明了 readOnlyHint、destructiveHint 和 idempotentHint,因此 MCP 客户端可以跳过对安全操作的确认。
  • 即时启动 — 以单个 bundle 发布,只有两个运行时依赖(MCP SDK 和 Zod)。无需花 5 分钟安装 node_modules。
  • 强化输入校验 — 适配器名称、@id 值、服务名称和 CA ID 均经过正则校验并设有长度上限。可阻止 CRLF 标头注入和 ReDoS。

快速开始

1. 启用 Caddy 管理 API

Caddy 默认会在 localhost:2019 上启用管理 API。如果你在 Docker 中或远程主机上运行 Caddy,请通过 CADDY_ADMIN_URL 将其公开。

2. 在项目根目录中创建 .mcp.json

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"]
    }
  }
}

为什么 Windows 需要额外步骤? 从 Node 20 开始,child_process.spawn 无法直接执行 .cmd 文件(Windows 上的 npx 就是这种文件)。使用 cmd /c 包装是标准的解决方法。此文件可以安全提交,因为其中不包含机密信息。

3. 重启并批准

重启 Claude Code(或你的 MCP 客户端),并在收到提示时批准 Caddy MCP 服务。

就是这样。现在可以向你的 AI 助手提问:

“将 api.local 代理到 localhost:3000”

“srv0 上配置了哪些路由?”

“显示 Prometheus 指标”

配置

环境变量默认值描述
CADDY_ADMIN_URLhttp://localhost:2019Caddy 管理 API URL。在 Docker 内设置为 http://caddy:2019,或设置为 TLS 终止反向代理后方管理端点的 https URL——有关 Caddy 对非自身回环地址应用的 Host / Origin 规则,请参阅故障排除。Caddy 原生远程管理监听器(admin.remote,默认值为 :2021)不受支持:它要求 TLS 客户端证书,而 caddy-mcp 不会提供该证书。也接受 Unix 套接字,格式可以是 unix:///var/run/caddy-admin.sock,也可以是 Caddy 自己使用的 unix//var/run/caddy-admin.sock 写法——见下文。
CADDY_API_TOKEN(无)可选的 Bearer 令牌,每个请求都会以 Authorization: Bearer <token> 的形式发送。Caddy 的管理 API 本身没有令牌身份验证功能,并会忽略此标头——只有在管理端点前方有身份验证代理时才需要它;如果 caddy-mcp 直接连接 Caddy,请不要设置此值。如果此标头确实到达管理监听器,Caddy 2.0 到 2.11.2 会在 INFO 级别的 admin.api“received request”日志行中以明文记录它——除 /metrics 外的所有路径均如此;自 2.2.1 起,/metrics 只会在 DEBUG 级别记录。请运行 Caddy 2.11.3 或更高版本(该版本会将其记录为 REDACTED),或者在代理完成身份验证后让代理移除此标头(Caddy:header_up -Authorization;nginx:proxy_set_header Authorization "";)。
CADDY_MCP_SNAPSHOT_DIR(无)用于持久化 caddy_revert 快照的目录。未设置时,快照仅存储在内存中,服务器重启后会丢失。快照是完整的 Caddy 配置,可能包含机密,因此该目录需显式选择,而非使用默认值。
CADDY_MAX_RETRIES2瞬时故障的重试次数:网络错误以及 502/503/504(只有 Caddy 前方的代理会发送这些状态码)。Caddy 自身返回的 500 是确定性拒绝,永远不会重试,4xx 和 412 也不会重试。可能因重放而改变结果的请求同样会跳过重试:对 /config/* 和 /id/* 的 POST 请求(它们会追加内容或替换已有键——重试可能导致路由重复),以及对数组索引(如 .../routes/0)执行的 PUT 或 DELETE 请求(重放会插入第二条路由,或删除滑入该索引的路由)。这也包括对裸路径 /id/<id> 的 PUT 请求,Caddy 会将其解析为已识别元素的数组索引。无论路径采用何种写法,这些请求都会被匹配——包括带尾部斜杠的路径,或带有 Caddy 在选择方法前会移除的尾部 /... 段的路径,因此 .../routes/0/... 和 PUT /id/<id>/... 也包含在内。超时触发的配置更改永远不会重试(见 CADDY_LOAD_TIMEOUT)。连接被拒绝时,所有方法都会重试,因为没有发送任何内容。对 /load、/adapt、/stop 的 POST 请求仍会重试。重试次数硬性上限为 5;超过上限的值会触发一次性 stderr 提示,以便看出已应用上限。设置为 0 可禁用重试。
CADDY_TIMEOUT10000不更改配置的管理 API 请求超时时间,单位为毫秒:GET 请求、/adapt、/stop、PKI、上游和指标。配置更改使用 CADDY_LOAD_TIMEOUT。非数值、<= 0 或小于 1ms 的小数值都会回退到默认值。
CADDY_LOAD_TIMEOUT55000所有更改配置的请求的超时时间,单位为毫秒:POST /load,以及 /config/* 和 /id/* 下的所有 POST/PUT/PATCH/DELETE 请求。每个请求都会在 Caddy 内执行一次完整的同步重载;这可能需要较长时间——每当更改关闭一个监听器时,Caddy 都会在重载期间休眠 apps.http.shutdown_delay 指定的时间,而且更改也可能需要等待另一次重载完成。此处发生超时后永远不会重试:即使客户端放弃,Caddy 仍会继续应用更改,因此错误会说明结果未知,并提示重试前重新读取配置(在这种情况下,caddy_load 和 caddy_revert 会保留其快照)。请将此值设为低于 MCP 客户端的请求超时时间(MCP SDK 默认值为 60 s),否则错误会在客户端放弃请求后才到达,因此永远不会显示;默认值比它低 5 s。非数值、<= 0 或小于 1ms 的小数值都会回退到默认值。
Unix socket 管理端点:

Caddy 建议通过将管理 API 从 loopback 端口迁移到 unix socket 来加强安全性,并通过文件系统权限控制访问:

{
  admin unix//var/run/caddy-admin.sock
}

将 CADDY_ADMIN_URL 指向同一路径(unix:///var/run/caddy-admin.sock),请求就会通过 socket 而不是 TCP 发送。运行 caddy-mcp 的进程需要对 socket 文件具有读写权限。此处请勿设置 CADDY_API_TOKEN,除非该 socket 上实际监听着一个需要身份验证的代理:通过 unix 路径时,caddy-mcp 通常连接的是 Caddy 自己的 socket,此时令牌不起作用;而在 Caddy 2.11.3 之前,令牌还会以明文形式记录在日志中。

运行时(oam 或 Node):

caddy-mcp 命令会优先使用可用的 oam,否则使用 Node 运行。它绝不会在低于 0.18.0 的 oam 上运行服务。

环境变量默认值说明
CADDY_MCP_RUNTIMEautoauto:使用版本为 0.18.0 或更高的最新 oam,否则使用 Node。oam:使用 oam,否则报错退出。node:始终使用 Node——当问题只在 oam 下出现时,可用此选项绕过。
CADDY_MCP_SANDBOX(未设置)1 表示在 oam 的 --permission 沙箱下运行服务:网络访问仅限于 CADDY_ADMIN_URL 的主机和端口,文件系统访问仅限于 CADDY_MCP_SNAPSHOT_DIR,且不允许创建子进程。需要 oam;在 auto 模式下,没有 oam 的机器会以非沙箱模式运行,因此如果必须确保启用沙箱,请同时设置 CADDY_MCP_RUNTIME=oam。沙箱目前无法访问基于 unix socket 的 CADDY_ADMIN_URL。
OAM_BIN(未设置)要使用的 oam 二进制文件路径。否则,启动器会检查 OAM_INSTALL_DIR、已安装的位置(~/.oam/bin,以及 Windows 上的 %LOCALAPPDATA%\oam\bin)和 PATH,并选择最新版本。

可通过 oam self-update 更新过时的 oam。在默认使用 oam 运行服务的 Yaw MCP 下,可通过 yaw-mcp set <namespace> runtime=node 将此服务切换到 Node。

其他 MCP 客户端:

客户端配置文件
Claude Code.mcp.json(项目根目录)或 ~/.claude.json(全局)
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.json(macOS)
Cursor~/.cursor/mcp.json
Windsurf~/.codeium/windsurf/mcp_config.json
VS Code.vscode/mcp.json

在以上任一客户端中使用上面展示的同一 JSON 代码块。

工具

配置管理(6)
  • caddy_config_get — 读取任意 JSON 路径上的配置(或完整配置)。
  • caddy_config_set — 在指定路径写入配置。模式:overwrite(PATCH,默认模式,幂等;键必须存在,并替换该路径下的整个子树)、append(POST:向数组追加内容,但会替换现有的非数组键,且无法创建缺失的父级)、insert(PUT:在数组位置插入,或严格地连同所有缺失的父级一起创建键;若键已存在则返回 409——这是创建服务器或应用的方式,即使实例没有配置也可使用)。在以 /... 结尾的路径上(例如 apps/http/servers/srv0/routes/...)使用 append 并提供数组值时,会在一次请求中追加每个元素——要么全部成功,要么全部失败,只重新加载一次;若路径不以 /... 结尾,数组值会作为单个元素添加,而 Caddy 会拒绝加载 routes 或 listen 等带类型的数组。指向配置根目录的路径(''、'/'、'config'、'/config/'、仅含斜杠的变体,或上述任一路径后接单独的 ... 段)表示整个配置,并要求 confirm=true:在根目录上使用 overwrite 和 append 会像 caddy_load 一样用 value 替换整个配置,包括 admin 块,除非 value 中包含该块——随后 Caddy 会将其管理端点重新绑定到新配置的 admin.listen;若未设置,则绑定到默认地址;若设置了 admin.disabled,则不绑定任何地址。指向其他地址的 CADDY_ADMIN_URL 将停止工作。根目录写入会先自动为之前的配置创建快照(如果能够读取),以便 caddy_revert 还原;其他路径均不会创建快照。只有在根目录执行 caddy_config_delete 后,才能在根目录使用 insert(否则返回 409);而 overwrite 正好相反:根目录删除后会返回 404,直到通过 append、insert 或 caddy_load 重新创建配置。
  • caddy_config_delete — 删除指定路径上的配置。需要 confirm=true(删除父路径也会移除所有后代路径)。指向配置根目录的路径(''、'/'、'config'、'/config/'、仅含斜杠的变体,或上述任一路径后接单独的 ... 段)表示整个配置:它会卸载所有应用和服务器以及 admin 块,之后 Caddy 会将其管理端点重新绑定到默认地址(localhost:2019,或 Caddy 环境中的 $CADDY_ADMIN)——如果 CADDY_ADMIN_URL 指向其他地址,之后 caddy-mcp 和 caddy_revert 都将无法访问 Caddy。根目录删除会先自动为之前的配置创建快照(如果能够读取),以便 Caddy 仍可访问时由 caddy_revert 还原;其他路径均不会创建快照。若要替换配置而不是卸载它,请使用 caddy_load。
  • caddy_config_by_id — 通过 @id 标签获取、设置或删除配置,比在深层路径中导航容易得多。delete 操作需要 confirm=true。每次 set 和 delete 都会先询问 Caddy id 的解析位置,并拒绝不在配置树内解析的 id。如果它解析到配置根目录——通常是因为它就是配置自身的顶层 @id,值为字符串或数字——则表示整个配置:不带子路径(或仅带 ...)的 set 和 delete 会替换或卸载整个配置,行为与根目录上的 caddy_config_set / caddy_config_delete 完全相同——两者都要求 confirm=true,都会先为之前的配置创建快照,并报告管理端点的位置。其内部的子路径则是普通写入。
  • caddy_load — 原子性地替换整个配置。与每次配置更改一样,此操作受 CADDY_LOAD_TIMEOUT 限制(默认 55 秒)。会自动为之前的配置创建快照;若加载超时且结果未知,则保留该快照。会列出 Caddyfile 适配器的警告,并将失败的加载报告为错误,即使 Caddy 返回了 HTTP 200——Caddy 2.11.4 在 Caddyfile 适配出现警告时就会如此处理(caddyserver/caddy#7246)。format 可以是 json(默认)或 caddyfile;标准版 Caddy 只注册了 caddyfile 适配器,因此对于编译到自定义构建中的其他适配器,请先使用 caddy_adapt 进行适配,再加载 JSON(参见下方的原子部署示例)。
  • caddy_revert — 管理用于回滚的配置快照。操作:list、save、apply(需确认)。快照保存在内存中,最多保留最近 10 个。在执行 caddy_load 之前,以及在执行指向配置根目录的 caddy_config_delete、caddy_config_set 或 caddy_config_by_id 之前自动捕获快照。若 apply 超时且结果未知,则会将回滚前的配置保留为快照 [0],所有较旧的快照索引依次加 1;错误信息会指出目标快照现在所在的位置。
路由操作(4)
  • caddy_reverse_proxy — 一次调用即可添加反向代理:from='api.local' to=['localhost:3000']。可传入可选的 id,以实现幂等写入——重复调用会原位替换路由,而不是创建重复项。
  • caddy_add_route — 添加具有完整匹配/处理控制的路由(任何 Caddy 处理器)。
  • caddy_remove_route — 按 @id(首选)或索引移除路由。需要 confirm=true。
  • caddy_list_routes — 以易读的形式概述路由。具有防御性:遇到异常配置也绝不会崩溃。
TLS 与配置转换(2)
  • caddy_tls — 检查或设置 TLS 参数。操作包括:status、set_email(ACME 邮箱)、set_acme_ca(ACME CA URL)、set_acme_profile(ACME 配置档案,Caddy 2.10+——上游实验性功能:ACME 配置档案规范仍是草案,且 Caddy 标记该字段可能会变更。Caddy 加载时接受任何配置档案名称,因此如果 CA 未提供该名称,只有在签发时才会失败,错误会记录在 Caddy 自身的日志中),以及只读操作 ech_status(位于 apps/tls/encrypted_client_hello 的加密客户端问候配置,Caddy 2.10+)。设置操作会先执行 PATCH;如果尚未设置 apps/tls,则会 PUT 一个最小配置,同时创建所有缺失的父级,因此即使实例完全没有配置也能使用。对于已有配置,会将更改深度合并到签发方路径,再 PATCH 回去,并保留同级配置(自定义证书、on_demand、其他策略)。如果现有结构不符合预期,则会返回针对该结构的错误——绝不覆盖配置。
  • caddy_adapt — 将任何已注册适配器格式的配置转换为 Caddy JSON,但不应用配置。caddyfile(内置,默认),以及编译进 Caddy 二进制文件的任何适配器模块——例如 nginx(caddy-nginx-adapter)、yaml(caddy-yaml)。非常适合预览或从现有配置迁移。有一点需要注意:在 Caddy 2.11.4 及更早版本中,Caddyfile 的 order 全局选项并非仅用于预览。它会修改该 Caddy 进程的指令顺序,因此会影响同一进程中后续的 Caddyfile 适配和加载;即使 order 行执行失败,它仍会移除其中指定的指令(caddyserver/caddy#7995,上游已修复,但截至 2.11.4 尚未发布)。
服务端操作(6)
  • caddy_status — 连通性检查和配置摘要(服务数量、路由、TLS 模式)。TLS 标签会根据存储的配置重现 Caddy 自身的自动 HTTPS 规则,而不是根据监听端口推测,因此可能显示为 enabled、enabled (no listener gets TLS: all are on the HTTP port)、auto (HTTPS)、auto (HTTPS: host matchers on a non-HTTP port)、mixed (TLS on non-HTTP listeners only)、off (HTTP only)、off (no host matchers)、off (automatic HTTPS disabled) 或 off (empty tls_connection_policies)。两个带说明的 enabled 状态源于 Caddy 按套接字而非按服务处理 TLS(app.go:535):HTTP 端口监听器会忽略连接策略,因此,仅绑定该端口的服务虽配置了 TLS,却不会提供 TLS。
  • caddy_list_servers — 列出所有 HTTP 服务的名称、地址、路由数量和 TLS 状态。标签与 caddy_status 相同,但此工具只读取 apps/http/servers,因此假定默认的 http_port 80 / https_port 443——对于使用自定义端口的实例,只有 caddy_status 能正确显示标签。
  • caddy_upstreams — 反向代理后端健康状态,即 Caddy 的 /reverse_proxy/upstreams 数组原样返回。在 Caddy 2.11.2+ 中,这并非已配置的 upstream 列表:动态 upstream 在动态来源最后一次返回后仍会保留约 1 小时(因此,某个地址可能在引用它的配置失效后仍然存在);如果某个后端有正在处理的请求,且其解析后的地址与条目的拨号文本不同,该后端可能会出现两次。额外副本始终显示 fails 0,并重复显示 num_requests——请勿对各条目的 num_requests 求和。
  • caddy_metrics — Prometheus 指标(请求数量、持续时间、连接数、TLS 握手)。可选的 filter(按指标名称子字符串匹配,保留所筛选指标对应的 # HELP / # TYPE 行)和 max_lines(默认值为 500)可让繁忙服务的响应保持精简。
  • caddy_pki — CA 信息和证书链(默认 CA:local)。
  • caddy_stop — 平滑关闭。需要设置 confirm=true 以防误操作。

资源

可浏览的只读数据——MCP 客户端无需调用工具即可直接获取:

  • caddy://config — 当前完整的 Caddy JSON 配置。
  • caddy://servers — 所有已配置 HTTP 服务的摘要。
  • caddy://upstreams — 反向代理 upstream 健康状态,原样返回。与 caddy_upstreams 相同,受 2.11.2+ 版本注意事项影响:动态 upstream 会残留,正在处理请求的条目可能重复;请勿对 num_requests 求和。
  • caddy://metrics — Prometheus 指标(文本展示格式)。为限制客户端上下文大小,最多返回前 500 行;如需筛选或获取更多内容,请使用 caddy_metrics 工具并设置 filter / max_lines。

示例

添加反向代理
> "Proxy api.example.com to my app on port 3000"
→ caddy_reverse_proxy({ from: "api.example.com", to: ["localhost:3000"] })
幂等反向代理(可安全地通过自动化重复运行)
> "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.
筛选 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.
应用前预览 Caddyfile
> "Convert this Caddyfile to JSON so I can review it:
   example.com {
     reverse_proxy localhost:8080
   }"
→ caddy_adapt({ config: "..." })
诊断缓慢的路由
> "Fetch Prometheus metrics and tell me which route is slowest"
→ caddy_metrics()
按 @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 first
原子部署
> "Replace the whole config with this Caddyfile"
→ caddy_adapt({ config: "..." })  # validate first
→ caddy_load({ config: adaptedJson })  # apply atomically

故障排除

“无法连接到 Caddy 管理 API”

  • 确保 Caddy 正在运行。使用 caddy run 或 systemctl status caddy。
  • 检查管理端点。默认地址为 http://localhost:2019。如果 Caddy 在 Docker 中运行,请使用容器主机名。
  • 在 MCP 配置的 env 中设置 CADDY_ADMIN_URL,使其与之匹配。
  • 使用 SSH 隧道时,两端映射相同的端口(ssh -L 2019:localhost:2019 <host>),并将 CADDY_ADMIN_URL 保持为默认值。Caddy 会检查 Host 标头是否与自身的监听地址一致,因此隧道使用不同的本地端口时,会返回 403 host not allowed: localhost:<port>。
  • 如果位于反向代理之后,请将代理的 host:port 添加到远程 Caddy 的 admin.origins 中。Caddy 会同时检查 Host 和 Origin,而设置 admin.origins 会替换默认的 localhost / 127.0.0.1 / ::1 条目,因此如果本地工具仍需访问,也要列出 localhost:2019。非环回或通配符 admin.listen(例如上文 Docker 中的 http://caddy:2019)同样不允许任意 Host,因此也需要设置 admin.origins。
  • 将 CADDY_ADMIN_URL 指向 Caddy 原生的远程管理监听器(admin.remote,默认值为 :2021)会在进行任何 HTTP 交换前失败,因为该监听器要求提供 TLS 客户端证书,而 caddy-mcp 不会提供证书。即使 Caddy 正在运行并已接受连接,也会显示此消息。

“HTTP 412 Precondition Failed”

  • 在你读取配置后、写入之前,有人(或某个程序)更改了配置。
  • 缓存的 ETag 已失效。请重新读取配置并重试。

任何请求都返回“HTTP 401”或“HTTP 403”

  • Caddy 自身的检查会在每个管理请求中运行,包括读取请求,并且总会返回 JSON {"error":...} 响应体。如果你收到此错误,问题出在 Caddy:admin.listen / admin.origins 允许列表(host not allowed: ...、client is not allowed to access from origin ...、required Origin header is missing or invalid——参见上文关于隧道和代理的条目),或者在 admin.remote 上,其 mTLS 身份和权限检查。
  • 没有响应体的 401/403 来自 Caddy 前面的某个组件,例如代理、网关或 SSO 层。CADDY_API_TOKEN 仅适用于此处,因此缺少令牌或令牌错误可能是原因之一,代理的其他访问规则也可能是原因。
  • Caddy 的管理 API 本身不支持 bearer 令牌身份验证,因此设置 CADDY_API_TOKEN 无法解决包含 Caddy 错误响应体的 401/403。

caddy_adapt 或 format: "caddyfile" 的 caddy_load 返回 “directive 'X' is not an ordered HTTP handler”

  • 有两种原因,Caddy 的错误信息无法区分:
    • 该指令没有已注册的顺序——通常是插件指令。请添加 order 全局选项,或将其包装在 route 块中。
    • 在 Caddy 2.11.4 及更早版本中,如果同一 Caddy 进程中较早发生或并发发生的 Caddyfile 适配使用了 order,就会从进程级指令顺序中移除该指令。重启 Caddy 可恢复默认顺序(caddyserver/caddy#7995,尚未发布)。
  • 第二种原因会导致刚在一分钟前完成适配的 Caddyfile,在未做任何修改的情况下开始失败。Caddy 自身的建议(“尝试使用 order 全局选项”)能修复第一种原因,也能掩盖第二种原因。

SIGUSR1 / systemctl reload caddy 停止重新加载 Caddyfile

  • 这是预期行为,并非此处存在错误。自 Caddy 2.11.1 起,只有在从未通过管理 API 更改过配置时,SIGUSR1 才会从磁盘上的文件重新加载配置。caddy-mcp(或任何其他 API 客户端)首次写入后,Caddy 会将运行中的配置视为由 API 管理,SIGUSR1 因而不再执行任何操作。
  • 每个实例只指定一个管理方。如果 Caddyfile 是事实来源,请使用 caddy-mcp 的只读工具(caddy_status、caddy_list_routes、caddy_adapt),并从文件重新加载配置。如果由 caddy-mcp 管理配置,请使用 caddy_load 应用更改,而不是使用 SIGUSR1。
  • 关于 Caddy 2.11.4 及更早版本,还有一点需要说明:caddy_adapt 对配置是只读的,但对适配器并非如此。Caddyfile 的 order 全局选项会改变该进程中的指令顺序,而无效的 order 行可能导致后续进程内适配失败——SIGUSR1 重新加载和 caddy run --watch 都会进行进程内适配。打包提供的 systemctl reload caddy 会运行 caddy reload,它在 CLI 进程中进行适配,因此不受影响。

Windows:MCP 服务无法启动

  • 使用快速入门部分中的 cmd /c npx ... 模式。Node 20+ 无法直接启动 .cmd 文件。

要求

  • Node.js 20+

  • Caddy 2.11.3 或更高版本,并启用管理 API(默认值:localhost:2019)。 建议使用最新的 2.11.x;已针对 Caddy 2.11.4 验证。该最低版本要求有两个与管理端有关的原因:

    • Caddy 2.11.2 及更早版本会以 INFO 级别记录每个管理请求的标头,因此,如果来自 CADDY_API_TOKEN 的 Authorization 标头到达管理监听器,令牌就会以明文形式写入 Caddy 日志 (caddyserver/caddy#7578)。
    • Caddy 2.11.1 及更早版本会静默接受重复的 @id。并发执行的 caddy_reverse_proxy 创建操作,或对路由 id 使用 mode: "insert" 的 caddy_config_by_id 设置操作,都会导致两个元素共享同一个 @id,而 /id/ 只会解析到其中一个。

    较旧的 2.x 版本大多可用,但有两个例外,都与 Caddy 发送 ETag 的方式有关。Caddy 2.8.0 及更高版本会将它作为响应标头发送。Caddy 2.5.2 至 2.7.x 会将它作为 HTTP 尾部发送,而此客户端无法读取;更早版本则不会发送。因此,在 Caddy 2.8.0 之前:

    • If-Match(ETag)并发保护处于停用状态,因为不会缓存 ETag 并将其回传;
    • 每个 caddy_config_by_id 的 set 和 delete 操作都会被拒绝,因为该工具会读取 ETag,以确定 Caddy 在写入前将 @id 解析到何处;如果无法读取,则会安全地拒绝操作。

    @id 写入路径依赖 PATCH 语义,实时集成测试套件会针对各个版本固定验证这些语义。

贡献

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 (782 unit tests, +39 POSIX-only unix-socket and launcher tests; +39 live-Caddy integration tests gated by CADDY_MCP_INTEGRATION=1)
npm run typecheck  # tsc --noEmit

完整工作流(包括发布流程)请参阅 CONTRIBUTING.md。

许可证

MIT

在 X 上关注 @YawLabs

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。