关于 Hetzner DNS
Hetzner DNS 是通过 Hetzner Cloud API 管理 DNS 区域和记录集的 MCP 服务,支持区域文件导入导出、TTL 与保护设置,并为高风险变更设置确认机制。
主要功能
- 01管理区域和记录集
- 02导入和导出 BIND 区域文件
- 03更改 TTL 和保护设置
- 04跟踪异步区域操作
- 05高风险变更需确认
适用场景
- 01查看和更新 Hetzner DNS 记录
- 02通过区域文件迁移记录
- 03按部署需求筛选可用工具
MCP 相关
通过 MCP 工具提供 Hetzner Cloud DNS 区域和 RRSet 操作。客户端可启用只读访问和工具筛选;敏感变更需通过 MCP elicitation 或一次性确认令牌。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y hetzner-dns-mcpHETZNER_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 leftHETZNER_API_BASE_URLOverride the Hetzner Cloud API base URL (default: https://api.hetzner.cloud/v1)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
22收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| mode | enum | 否 | 按模式筛选区域primary | secondary |
| name | string | 否 | 按名称筛选区域(精确匹配) |
| page | integer | 否 | 要返回的页码(分页) |
| per_page | integer | 否 | 每页条目数(1-100,默认值为 25) |
| label_selector | string | 否 | 按标签选择器筛选区域,例如 "env=prod" |
详细介绍
hetzner-dns-mcp
一个通过 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 月关闭,不再受支持。

区域、记录集及其背后的操作。 列出、创建、更新和删除区域与 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(记录集)
| Tool | Description |
|---|---|
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。
操作
| Tool | Description |
|---|---|
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必须是httpsURL(仅接受 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
发布
- 更新
package.json中的版本(npm version X.Y.Z --no-git-tag-version)。 - 将
CHANGELOG.md中的[Unreleased]部分重命名为新版本号。 - 提交,然后打标签并推送:
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
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。