mcpField
H
Hetzner DNS

Hetzner DNS

本地服务
hetzner-dns-mcp.ni-c.de云与基础设施01 天前更新

关于 Hetzner DNS

Hetzner DNS 是通过 Hetzner Cloud API 管理 DNS 区域和记录集的 MCP 服务,支持区域文件导入导出、TTL 与保护设置,并为高风险变更设置确认机制。

主要功能

  1. 01管理区域和记录集
  2. 02导入和导出 BIND 区域文件
  3. 03更改 TTL 和保护设置
  4. 04跟踪异步区域操作
  5. 05高风险变更需确认

适用场景

  1. 01查看和更新 Hetzner DNS 记录
  2. 02通过区域文件迁移记录
  3. 03按部署需求筛选可用工具

MCP 相关

通过 MCP 工具提供 Hetzner Cloud DNS 区域和 RRSet 操作。客户端可启用只读访问和工具筛选;敏感变更需通过 MCP elicitation 或一次性确认令牌。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"ni-c-hetzner-dns": {
"command": "npx",
"args": [
"-y",
"hetzner-dns-mcp"
],
"env": {
"HETZNER_API_TOKEN": "<HETZNER_API_TOKEN>",
"HETZNER_READ_ONLY": "<HETZNER_READ_ONLY>",
"HETZNER_ALLOW_TOOLS": "<HETZNER_ALLOW_TOOLS>",
"HETZNER_DENY_TOOLS": "<HETZNER_DENY_TOOLS>",
"HETZNER_API_BASE_URL": "<HETZNER_API_BASE_URL>"
}
}
}
}
启动命令npx -y hetzner-dns-mcp
需要配置的环境变量
HETZNER_API_TOKEN密钥Hetzner Cloud API token (project-scoped, Cloud Console -> Security -> API tokens)
HETZNER_READ_ONLYSet to true to register only the read-only tools (default: false)
HETZNER_ALLOW_TOOLSComma-separated tool names or list_* prefixes to register; 'essential' selects a curated preset (default: all tools)
HETZNER_DENY_TOOLSComma-separated tool names or list_* prefixes to remove from whatever HETZNER_ALLOW_TOOLS left
HETZNER_API_BASE_URLOverride the Hetzner Cloud API base URL (default: https://api.hetzner.cloud/v1)

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

安装包
npmhetzner-dns-mcp0.6.0
ocighcr.io/ni-c/hetzner-dns-mcp:0.6.0

工具

22

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

参数类型必填说明
modeenum否按模式筛选区域primary | secondary
namestring否按名称筛选区域(精确匹配)
pageinteger否要返回的页码(分页)
per_pageinteger否每页条目数(1-100,默认值为 25)
label_selectorstring否按标签选择器筛选区域,例如 "env=prod"

详细介绍

hetzner-dns-mcp

CI OpenSSF Scorecard Socket Badge Glama score
npm version container image HTTP via mcp-hub
docs sponsor

一个通过 Hetzner Cloud API 管理 DNS 区域和记录的 模型上下文协议(MCP)服务。

让 Claude Code、Claude Desktop 或 Codex 等 MCP 客户端管理你的 Hetzner DNS:列出、创建、更新和删除区域及 RRSet(记录集),导入/导出区域文件,管理保护和 TTL,并跟踪异步区域操作。

工具数量以 22 个为上限,而非目标:设置 HETZNER_ALLOW_TOOLS=essential,即可改为注册经过筛选的 8 个工具。模型从 8 个工具中选择正确工具的可靠性,远高于从 22 个中选择——请参阅选择要加载的工具。

**注意:**此服务面向作为 Hetzner Cloud API(api.hetzner.cloud)一部分的当前 DNS API。旧版 DNS API(dns.hetzner.com)已于 2026 年 5 月关闭,不再受支持。

演示:列出工具、一次被拒绝的 set_records 调用,以及使用返回的确认令牌成功执行同一调用

MCP 客户端通过 stdio 与 hetzner-dns-mcp 通信;后者会验证参数,让破坏性调用先由人员确认,并通过 HTTPS 调用 Hetzner Cloud API

MCP 客户端通过 stdio 与 hetzner-dns-mcp 通信;服务提供用于管理区域和记录集的读写工具,在执行破坏性调用前征求人员确认,并使用 API 令牌通过 HTTPS 调用 Hetzner Cloud DNS API ## 它的不同之处

区域、记录集及其背后的操作。 列出、创建、更新和删除区域与 RRSets,导入和导出 BIND 区域文件,更改 TTL 和保护设置;还会跟进 Hetzner 在更改后排队执行的异步区域操作,而不是只报告成功,让你自行猜测。

不信任任何上游数据。 返回的记录值、注释和区域文件都会被标记为不可信数据;看起来像密钥的内容会被遮盖,过大的值会被截断,HTML 错误页面则会被丢弃,而不是粘贴到上下文中。

破坏性调用需要人工确认。 删除区域或替换记录集时,会通过 MCP elicitation 弹出真实对话框。如果客户端无法显示对话框,调用就会被拒绝,并附带一个随机的一次性令牌。该令牌只会出现在先前的工具结果中,因此 DNS 记录中隐藏的内容无法生成它。

要求

  • Node.js ≥ 22
  • 用于存放 DNS 区域的项目的 Hetzner Cloud API 令牌——在 Hetzner Cloud Console 中依次进入 your project → Security → API tokens 创建。要获得完整功能,请使用 read & write 令牌(只读令牌仅允许使用读取工具)。

配置

通过环境变量提供配置:

变量必需描述
HETZNER_API_TOKEN是Hetzner Cloud API 令牌(限定项目)
HETZNER_READ_ONLY否true 仅注册读取工具;写入工具将完全不存在
HETZNER_ALLOW_TOOLS否逗号分隔的工具名称、list_* 前缀,或用于精选预设的 essential
HETZNER_DENY_TOOLS否语法相同;从 HETZNER_ALLOW_TOOLS 保留的工具中移除
ELICITATION否false 会用双调用令牌取代确认对话框。不带前缀
HETZNER_API_BASE_URL否API 的基础 URL(默认值:https://api.hetzner.cloud/v1)

如果没有令牌,服务仍会启动并列出其工具(方便注册表和检查器进行自省),但每次工具调用都会失败并提供设置说明,而不会访问 API。

读取后,HETZNER_API_TOKEN 和 HETZNER_API_BASE_URL 会从进程环境中删除,因此之后的崩溃报告或诊断转储不会泄露令牌。

选择要加载的工具

HETZNER_ALLOW_TOOLS 和 HETZNER_DENY_TOOLS 接受逗号分隔的工具名称;末尾的 * 可匹配整个工具系列。essential 是一个精选预设,包含 list_zones、get_zone、list_rrsets、get_rrset、create_rrset、set_records、delete_rrset 和 export_zonefile,涵盖读取区域和更改记录,同时不包含那些少见但后果严重的工具。

HETZNER_ALLOW_TOOLS=essential
HETZNER_ALLOW_TOOLS=list_*,get_zone,set_records
HETZNER_DENY_TOOLS=delete_zone,import_zonefile

如果某个条目没有匹配任何工具,服务会中止启动并指出该条目,因此拼写错误不会悄悄隐藏工具——没人会把工具缺失追溯到环境变量。如果工具经过筛选,就不会被注册,因此它既不会出现在 tools/list 中,也无法通过 tools/call 调用,这与 HETZNER_READ_ONLY 下的写入工具完全一样。

如果你同时运行多个此类服务,mcp-hub 是另一个解决方案——它的 /hub 端点会用六个元工具替换每个服务的所有工具。

安装

Claude Code
claude mcp add hetzner-dns -s user \
  -e HETZNER_API_TOKEN=your-token \
  -- npx -y hetzner-dns-mcp
Claude Desktop

添加到你的 claude_desktop_config.json:

{
  "mcpServers": {
    "hetzner-dns": {
      "command": "npx",
      "args": ["-y", "hetzner-dns-mcp"],
      "env": {
        "HETZNER_API_TOKEN": "your-token"
      }
    }
  }
}
Codex

添加到你的 ~/.codex/config.toml:

[mcp_servers.hetzner-dns]
command = "npx"
args = ["-y", "hetzner-dns-mcp"]
env = { HETZNER_API_TOKEN = "your-token" }
从源代码安装
git clone https://github.com/ni-c/hetzner-dns-mcp.git
cd hetzner-dns-mcp
npm install
npm run build
# then use `node /path/to/hetzner-dns-mcp/dist/index.js` as the command
Docker

多架构镜像(amd64/arm64)会连同 SBOM 和构建来源证明一起发布到 GHCR:

docker run -i --rm -e HETZNER_API_TOKEN=your-token ghcr.io/ni-c/hetzner-dns-mcp

该镜像通过 stdio 使用 MCP,因此客户端需要使用 docker run -i(不会公开任何端口):

{
  "mcpServers": {
    "hetzner-dns": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "HETZNER_API_TOKEN",
        "ghcr.io/ni-c/hetzner-dns-mcp"
      ],
      "env": {
        "HETZNER_API_TOKEN": "your-token"
      }
    }
  }
}
通过 mcp-hub

无法启动本地进程的客户端——ChatGPT connectors、Claude 网页版、Cursor、LibreChat——可通过 mcp-hub 访问 hetzner-dns-mcp:一个容器通过 Streamable HTTP 提供多个 stdio MCP 服务,并通过单个密码登录,使用 OAuth 2.1;对于无法使用 OAuth 的客户端,则提供长期有效的令牌。它的 /hub 端点通过六个元工具提供所有服务,因此一个连接器就能访问全部服务,无需在模型上下文中放入 N×工具架构;它还同时支持两个协议修订版本——本服务提出的问题会经由它传递给另一端的用户。

它的 /config/mcp.json 使用 Claude Code 的格式,因此配置项就是你已有的这一项:

{
  "mcpServers": {
    "hetzner-dns": {
      "command": "npx",
      "args": ["-y", "hetzner-dns-mcp"],
      "env": {
        "HETZNER_API_TOKEN": "your-token",
        "HETZNER_ALLOW_TOOLS": "essential"
      },
      "denyTools": ["delete_*"]
    }
  }
}

其中的 allowTools 和 denyTools 是 hub 自身针对每个服务的筛选器,与 env 中的 *_ALLOW_TOOLS 并不相同——两者的区别以及由此引发的错误,详见客户端指南。

工具

每个工具都声明了 outputSchema,并在文本块之外通过 structuredContent 返回结果,因此客户端无需解析文本即可使用结果。 文本中的 <untrusted-data> 围栏会保留——它是同一标记的可读呈现形式——结构化部分则将 untrusted: true 和 source: "hetzner-cloud-api" 作为字段携带。每个工具都会携带这些字段:记录值、注释、标签和区域文件都由控制该区域的人编写,因此这里没有任何工具会返回其他内容。

API 文档将其描述为开放对象,并列出 spec 保证的顶层键。API 并非由本服务承诺,而且 SDK 会在每个结果发出前根据其架构进行验证——严格限定结构会导致 Hetzner 新增字段时,工具直接失败。

超出预算的结果现在会作为错误返回。以前结果会在文档中途被截断并说明原因;对于文本块,这样没问题,但对于 structuredContent 则行不通:两个通道必须携带相同的值,而在字符串中途截断文档会导致其无法解析。

区域
工具说明
list_zones列出区域及其状态、模式、名称服务器和记录数量
get_zone获取单个区域的完整详情
create_zone创建主区域或辅助区域,可选择使用区域文件
update_zone替换区域的标签
delete_zone 👤永久删除区域
export_zonefile将区域导出为 BIND 区域文件
import_zonefile 👤导入 BIND 区域文件(替换所有记录)
change_zone_ttl更改区域的默认 TTL
change_zone_protection 👤启用或禁用删除保护——_禁用_时会询问
change_primary_nameservers 👤替换辅助区域的主服务器
RRSets(记录集)
ToolDescription
list_rrsets列出区域的 RRSets,可按名称/类型/标签筛选
get_rrset按名称和类型获取单个 RRSet
create_rrset 👤创建包含记录的新 RRSet——会询问权威记录
update_rrset替换 RRSet 的标签
delete_rrset 👤永久删除 RRSet
set_records 👤替换 RRSet 的所有记录
add_records 👤向 RRSet 添加记录(如果不存在则创建)——会询问权威记录
remove_records 👤从 RRSet 中移除指定记录
change_rrset_ttl更改 RRSet 的 TTL(或使用 null 重置为区域默认值)
change_rrset_protection 👤启用/停用变更保护——在_停用_时会询问

👤 通过 MCP elicitation 向用户询问 · 如果客户端无法显示对话框,则回退到两次调用 confirm_token。

操作
ToolDescription
list_zone_actions列出区域的异步操作(例如导入),可按状态筛选
get_zone_action按 ID 获取单个操作以检查其状态
安全性

需要征求用户同意,而不只是告知用户。 每个不可逆工具——delete_zone、 delete_rrset、import_zonefile、set_records、remove_records、 change_primary_nameservers,以及会_移除_保护的 change_zone_protection/change_rrset_protection——都会通过 MCP elicitation 触发真实对话框(如果客户端支持)。模型无法代替用户作答,只有收到答复后才会执行操作。

另外三个工具会_视情况_征求同意,因为在 DNS 中,危险操作是声明而不是撤销声明:对于决定由谁响应的名称或类型(NS、DS、MX、CNAME、CAA、TLSA、SVCB、 HTTPS、SRV、顶点 @、通配符),create_rrset 和 add_records 会征求同意;当调用包含 primary_nameservers 或 zonefile 时,create_zone 也会征求同意——这些参数与 change_primary_nameservers 和 import_zonefile 受保护的参数相同。确认会绑定调用将写入的每个字段,包括 TTL 和标签,因此,针对某个 TTL 签发的令牌不能用于另一个 TTL。

如果客户端无法显示对话框,工具会拒绝首次调用,并返回一个随机、单次使用、有效期为五分钟的令牌;第二次调用必须重复完全相同的参数并传入该令牌:

1. set_records(zone: "example.com", name: "www", type: "A", records: [{value: "198.51.100.1"}])
   → error: Refusing to replace the records … confirm_token: "3f9c…"
2. set_records(…same arguments…, confirm_token: "3f9c…")
   → executed

这并非模型可以自行设置的布尔值:令牌只会出现在_之前_的工具结果中,因此,隐藏在 TXT 记录或区域文件注释中的指令无法伪造令牌。但它只能证明该调用使用相同参数执行了两次,仅此而已;回退提示会明确说明这一点,而不会暗示有人已批准。

无论采用哪种方式,批准都与具体操作绑定。对于 set_records、 remove_records 和 import_zonefile,绑定对象是确切载荷的哈希值:批准写入 ["198.51.100.1"] 的操作,不会写入 ["198.51.100.66"]。

ELICITATION=false 会有意使用回退路径,适用于计划任务或测试框架。它绝不会移除保护措施。请参阅 征求用户同意。

对话框是防护措施,而非安全边界——安全边界是 MCP 宿主的权限提示。请勿自动批准这些工具。

不可信的上游数据。 API 返回的所有内容都会封装在 <untrusted-data> 中,因为记录值、注释、标签和区域文件都由控制该区域的人编写。确认消息绝不会引用这些内容;它们只会报告数量和 TTL。看起来像密钥的字段(tsig_key、token、secret、password)会从结果中隐藏,超长值会被截断,中间代理返回的 HTML 错误页面会被丢弃,而不会粘贴到模型上下文中。

最小权限。 设置 HETZNER_READ_ONLY=true,只注册七个读取工具——写入工具将完全不存在于协议中,而不是在调用时才失败。搭配只读的 Hetzner 令牌,即可实现真正的只读设置。

其他保障措施。

  • 工具带有 MCP 注释(readOnlyHint、destructiveHint、idempotentHint),以便宿主采用适当的权限策略。
  • HETZNER_API_BASE_URL 必须是 https URL(仅接受 localhost 使用 http),且不得包含凭据;配置非默认主机时会打印警告,因为 API 令牌会发送到该主机。
  • 区域标识符和 RRSet 名称会根据严格的字符集进行验证——不允许使用斜杠、百分号、单独的 . 或 ..——因此请求无法逃出预期的 API 路径;请求绝不会跟随重定向,因此 Bearer 标头不会被转发到其他位置。
  • 传递给 create_zone/change_primary_nameservers 的 TSIG 密钥会成为对话上下文和客户端记录的一部分——请将其视为机密;如有疑虑,请轮换密钥。
  • Hetzner 端的资源保护会得到遵守:受保护的区域/RRSet 会返回错误,并提示使用相应的 change_*_protection 工具。

有意不提供

仅支持 Hetzner Cloud DNS API。 独立的 dns.hetzner.com API 已于 2026 年 5 月关闭,且未实现——仍在使用它的脚本会出问题,原因与此服务无关。

HETZNER_API_BASE_URL 不是用于切换提供商的选项。 它用于在开发期间指向本地模拟服务,并且经过验证(仅限 HTTPS、URL 中不得包含凭据、主机非默认值时发出警告),正是因为你的令牌会发送到该地址。请求格式遵循 Hetzner 的规范。

安全

  • DNS 记录由持有令牌的人编辑,因此上游值、注释和区域文件都标记为不可信数据——在两个通道中都会提示报告这些数据,绝不可遵循,并且数据无法越过隔离边界。密钥会根据规范化名称的后缀进行脱敏(password、secret、token、apikey、privatekey、passphrase、tsigkey);超过 4 000 个字符的值会被截断,控制字符会被剥除,HTML 错误页面会被丢弃,而不会粘贴到上下文中。
  • 删除区域或替换记录集时,需要由人员确认:通过 MCP elicitation 发起真实对话框,并绑定到确切的目标。如果客户端无法显示对话框,则拒绝调用,并附带一个随机的一次性令牌;该令牌只会在之前的工具结果中出现。
  • HETZNER_READ_ONLY=true 只会注册七个读取工具,不会注册其他工具——此时写入工具不会出现在 tools/list 中,而不是在调用时才被拒绝。
  • 请求会经过加固,而非盲目信任:区域标识符会进行模式匹配,防止路径越界;拒绝重定向,确保 Authorization 标头不会随重定向发送;每个请求都会在 30 秒后超时;请求正文仅由命名字段构建;并且在发送令牌前会验证基础 URL(HTTPS、无凭据)。令牌本身的格式也会在到达 HTTP 层之前检查,否则 HTTP 层可能会在错误中原样引用令牌;响应正文会在大小上限内读取,并首先确定状态;每个响应都会进行格式检查,而非直接类型转换,因此代理的响应会生成易读结果,而不是产生没有原因说明的架构违规错误。

文档

完整指南、工具参考和安全说明位于 hetzner-dns-mcp.ni-c.de(源码位于 docs/)。

开发

npm install
npm run build     # compile TypeScript to dist/
npm test          # run the vitest test suite
npm run lint      # oxlint + prettier check
发布
  1. 更新 package.json 中的版本(npm version X.Y.Z --no-git-tag-version)。
  2. 将 CHANGELOG.md 中的 [Unreleased] 部分重命名为新版本号。
  3. 提交,然后打标签并推送:git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin main vX.Y.Z。

随后,发布工作流会运行测试,通过 Trusted Publishing(附带 provenance)发布到 npm,使用 CHANGELOG 中的说明创建 GitHub 发布版本,并更新官方 MCP Registry 中的条目(io.github.ni-c/hetzner-dns-mcp,通过 GitHub OIDC)。

发布

发布由标签驱动。更新 package.json,将 CHANGELOG.md 中的 [Unreleased] 说明移至新版本下,提交,然后:

git tag -s vX.Y.Z -m "vX.Y.Z"
git push origin main vX.Y.Z

发布工作流通过 Trusted Publishing(OIDC,附带 provenance)发布到 npm,将多架构容器镜像推送到 GHCR,根据 CHANGELOG 中的部分创建 GitHub 发布版本,并更新官方 MCP Registry 中的条目。

贡献

欢迎提交问题、参与讨论和发起拉取请求——请参阅 CONTRIBUTING.md。如需报告漏洞,请使用 私密报告渠道, 不要公开提交问题;相关政策见 SECURITY.md。

许可证

MIT © Willi Thiel

评论

支持 Markdown

第一次接触 MCP?

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

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