Server data from the Official MCP Registry
MCP server for the Hetzner Cloud API — servers, networks, volumes, firewalls, and more.
About
MCP server for the Hetzner Cloud API — servers, networks, volumes, firewalls, and more.
Security Report
This is a well-structured MCP server for Hetzner Cloud API management with proper authentication requirements and appropriate permission scoping. The code demonstrates good security practices with input validation via Zod schemas, proper HTTP request abstraction, and clear separation of concerns. No critical vulnerabilities or malicious patterns were detected. Minor code quality observations exist but do not materially impact security. Supply chain analysis found 5 known vulnerabilities in dependencies (0 critical, 1 high severity). Package verification found 1 issue.
4 files analyzed · 10 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Install
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-lazyants-hetzner": {
"args": [
"-y",
"@lazyants/hetzner-mcp-server"
],
"command": "npx"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
hetzner-mcp-server
MCP server for the Hetzner Cloud API. Manage servers, networks, volumes, firewalls, load balancers, and more through the Model Context Protocol.
185 tools across 15 resource domains, with 9 entry points so you can pick the right server for your MCP client's tool limit. A read-only API-reference Resource (reference://hetzner/api) is also exposed on every entry point.
Installation
npm install -g @lazyants/hetzner-mcp-server
Or run directly:
npx @lazyants/hetzner-mcp-server
Configuration
Set your Hetzner Cloud API token:
export HETZNER_API_TOKEN=your-token-here
Get a token from the Hetzner Cloud Console under Security > API Tokens.
The Storage Box tools call a separate host (https://api.hetzner.com/v1). They use HETZNER_STORAGE_API_TOKEN if set, otherwise fall back to HETZNER_API_TOKEN, so a single token keeps working. Set HETZNER_STORAGE_API_TOKEN only if you scope Storage Box access to a dedicated token:
export HETZNER_STORAGE_API_TOKEN=your-storage-token-here # optional
Entry Points
| Command | Domains | Tools |
|---|---|---|
hetzner-mcp-server | All 15 domains | 185 |
hetzner-mcp-servers | Servers, Datacenters/Locations/Server Types, Pricing | 34 |
hetzner-mcp-networking | Networks, Firewalls | 21 |
hetzner-mcp-load-balancers | Load Balancers, Certificates | 28 |
hetzner-mcp-ips | Floating IPs, Primary IPs | 20 |
hetzner-mcp-storage | Volumes, Images | 17 |
hetzner-mcp-storage-boxes | Storage Boxes (+ snapshots, subaccounts, types) | 29 |
hetzner-mcp-config | SSH Keys, ISOs, Placement Groups | 14 |
hetzner-mcp-dns | DNS Zones | 22 |
Use split servers to reduce context size — pick only the splits you need.
Claude Code
Add to ~/.claude/settings.json:
{
"mcpServers": {
"hetzner": {
"command": "npx",
"args": ["-y", "@lazyants/hetzner-mcp-server"],
"env": {
"HETZNER_API_TOKEN": "your-token-here"
}
}
}
}
Or use split servers (pick the splits you need):
{
"mcpServers": {
"hetzner-servers": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/hetzner-mcp-server", "hetzner-mcp-servers"],
"env": { "HETZNER_API_TOKEN": "your-token-here" }
},
"hetzner-networking": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/hetzner-mcp-server", "hetzner-mcp-networking"],
"env": { "HETZNER_API_TOKEN": "your-token-here" }
}
}
}
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"hetzner": {
"command": "npx",
"args": ["-y", "@lazyants/hetzner-mcp-server"],
"env": {
"HETZNER_API_TOKEN": "your-token-here"
}
}
}
}
Tools
Servers (27 tools) — servers
hetzner_list_servers, hetzner_get_server, hetzner_create_server, hetzner_update_server, hetzner_delete_server, hetzner_power_on, hetzner_power_off, hetzner_reboot, hetzner_reset, hetzner_shutdown, hetzner_rebuild_server, hetzner_resize_server, hetzner_enable_rescue, hetzner_disable_rescue, hetzner_get_server_metrics, hetzner_list_server_actions, hetzner_change_server_protection, hetzner_request_console, hetzner_enable_backup, hetzner_disable_backup, hetzner_change_alias_ips, hetzner_change_dns_ptr, hetzner_attach_server_to_network, hetzner_detach_server_from_network, hetzner_add_server_to_placement_group, hetzner_remove_server_from_placement_group, hetzner_reset_server_password
Images (7 tools) — storage
hetzner_list_images, hetzner_get_image, hetzner_update_image, hetzner_delete_image, hetzner_create_image, hetzner_change_image_protection, hetzner_list_image_actions
ISOs (4 tools) — config
hetzner_list_isos, hetzner_get_iso, hetzner_attach_iso, hetzner_detach_iso
Placement Groups (5 tools) — config
hetzner_list_placement_groups, hetzner_get_placement_group, hetzner_create_placement_group, hetzner_update_placement_group, hetzner_delete_placement_group
Reference Data (7 tools) — servers
hetzner_list_datacenters, hetzner_get_datacenter, hetzner_list_locations, hetzner_get_location, hetzner_list_server_types, hetzner_get_server_type, hetzner_get_pricing
hetzner_list_datacenters/hetzner_get_datacenterare deprecated by Hetzner and removed after 2026-10-01 (HTTP 410). Usehetzner_list_server_types(locations[].available/recommended) andhetzner_list_locationsinstead.
Networks (12 tools) — networking
hetzner_list_networks, hetzner_get_network, hetzner_create_network, hetzner_update_network, hetzner_delete_network, hetzner_add_subnet, hetzner_delete_subnet, hetzner_add_route, hetzner_delete_route, hetzner_change_network_protection, hetzner_change_ip_range, hetzner_list_network_actions
Firewalls (9 tools) — networking
hetzner_list_firewalls, hetzner_get_firewall, hetzner_create_firewall, hetzner_update_firewall, hetzner_delete_firewall, hetzner_set_firewall_rules, hetzner_apply_firewall, hetzner_remove_firewall, hetzner_list_firewall_actions
Load Balancers (21 tools) — load-balancers
hetzner_list_load_balancers, hetzner_get_load_balancer, hetzner_create_load_balancer, hetzner_update_load_balancer, hetzner_delete_load_balancer, hetzner_add_lb_target, hetzner_remove_lb_target, hetzner_add_lb_service, hetzner_update_lb_service, hetzner_delete_lb_service, hetzner_change_lb_algorithm, hetzner_change_lb_type, hetzner_attach_lb_to_network, hetzner_detach_lb_from_network, hetzner_get_lb_metrics, hetzner_list_lb_types, hetzner_change_load_balancer_protection, hetzner_list_load_balancer_actions, hetzner_enable_lb_public_interface, hetzner_disable_lb_public_interface, hetzner_change_lb_dns_ptr
Certificates (7 tools) — load-balancers
hetzner_list_certificates, hetzner_get_certificate, hetzner_create_certificate, hetzner_update_certificate, hetzner_delete_certificate, hetzner_retry_certificate, hetzner_list_certificate_actions
Volumes (10 tools) — storage
hetzner_list_volumes, hetzner_get_volume, hetzner_create_volume, hetzner_update_volume, hetzner_delete_volume, hetzner_attach_volume, hetzner_detach_volume, hetzner_resize_volume, hetzner_change_volume_protection, hetzner_list_volume_actions
Floating IPs (10 tools) — ips
hetzner_list_floating_ips, hetzner_get_floating_ip, hetzner_create_floating_ip, hetzner_update_floating_ip, hetzner_delete_floating_ip, hetzner_assign_floating_ip, hetzner_unassign_floating_ip, hetzner_change_floating_ip_rdns, hetzner_change_floating_ip_protection, hetzner_list_floating_ip_actions
Primary IPs (10 tools) — ips
hetzner_list_primary_ips, hetzner_get_primary_ip, hetzner_create_primary_ip, hetzner_update_primary_ip, hetzner_delete_primary_ip, hetzner_assign_primary_ip, hetzner_unassign_primary_ip, hetzner_change_primary_ip_rdns, hetzner_change_primary_ip_protection, hetzner_list_primary_ip_actions
SSH Keys (5 tools) — config
hetzner_list_ssh_keys, hetzner_get_ssh_key, hetzner_create_ssh_key, hetzner_update_ssh_key, hetzner_delete_ssh_key
DNS Zones (22 tools) — dns
hetzner_list_zones, hetzner_get_zone, hetzner_create_zone, hetzner_update_zone, hetzner_delete_zone, hetzner_change_zone_protection, hetzner_change_zone_ttl, hetzner_change_zone_primary_nameservers, hetzner_export_zonefile, hetzner_import_zonefile, hetzner_list_zone_actions, hetzner_list_zone_rrsets, hetzner_get_zone_rrset, hetzner_create_zone_rrset, hetzner_update_zone_rrset, hetzner_delete_zone_rrset, hetzner_change_zone_rrset_protection, hetzner_change_zone_rrset_ttl, hetzner_add_zone_rrset_records, hetzner_remove_zone_rrset_records, hetzner_set_zone_rrset_records, hetzner_update_zone_rrset_records
Storage Boxes (29 tools) — storage-boxes
Storage Boxes use the https://api.hetzner.com/v1 host. Token: HETZNER_STORAGE_API_TOKEN (falls back to HETZNER_API_TOKEN).
hetzner_list_storage_boxes, hetzner_create_storage_box, hetzner_get_storage_box, hetzner_update_storage_box, hetzner_delete_storage_box, hetzner_list_storage_box_folders, hetzner_list_storage_box_actions, hetzner_change_storage_box_protection, hetzner_change_storage_box_type, hetzner_reset_storage_box_password, hetzner_update_storage_box_access_settings, hetzner_rollback_storage_box_snapshot, hetzner_enable_storage_box_snapshot_plan, hetzner_disable_storage_box_snapshot_plan, hetzner_list_storage_box_types, hetzner_get_storage_box_type, hetzner_list_storage_box_snapshots, hetzner_create_storage_box_snapshot, hetzner_get_storage_box_snapshot, hetzner_update_storage_box_snapshot, hetzner_delete_storage_box_snapshot, hetzner_list_storage_box_subaccounts, hetzner_create_storage_box_subaccount, hetzner_get_storage_box_subaccount, hetzner_update_storage_box_subaccount, hetzner_delete_storage_box_subaccount, hetzner_change_storage_box_subaccount_home_directory, hetzner_reset_storage_box_subaccount_password, hetzner_update_storage_box_subaccount_access_settings
Security
- Never commit your API token to version control
- Use read-only tokens when you only need to list/get resources
- Create and delete tools cost real money — Hetzner bills for provisioned resources
- The server handles rate limiting automatically (3,600 requests/hour, exponential backoff on 429)
Disclaimer
Create, update, and delete operations may incur charges on your Hetzner Cloud account. Use read-only API tokens when possible. The authors are not responsible for any costs incurred.
Releasing
Releases ship via the GitHub Release event. Maintainer flow:
-
Bump the version in
package.jsonandserver.json(both#/versionand#/packages[0].version), then runnpm install --package-lock-onlyto syncpackage-lock.json.node scripts/check-versions.mjshard-fails unlesspackage.json#/versionmatchesserver.json#/packages[0].version;server.json#/versionis checked loosely — it may legitimately be ahead (registry-only republishes bump just that field), so a stale value passes with aWARN:line and no failure. Read the script's output rather than trusting its exit code.CHANGELOG.mdis not checked at all. -
Update
CHANGELOG.md. -
Commit, and merge the version bump to
mainbefore creating the release. Then create the tag yourself, on a SHA you have checked, and only then create the release from it:V=X.Y.Z && PR=<release-pr-number> && SHA="$(gh pr view "$PR" --json mergeCommit -q .mergeCommit.oid)" && test -n "$SHA" && git fetch origin main && git merge-base --is-ancestor "$SHA" origin/main && PKG="$(git show "$SHA:package.json")" && test "$(printf '%s' "$PKG" | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).version')" = "$V" && CL="$(git show "$SHA:CHANGELOG.md")" && printf '%s\n' "$CL" | awk -v v="$V" 'index($0,"## ["v"]")==1{f=1;next} /^## \[/{f=0} /^\[[0-9]+\.[0-9]+\.[0-9]+\]:/{f=0} f' > "/tmp/notes-v$V.md" && grep -q '[^[:space:]]' "/tmp/notes-v$V.md" && git tag -a "v$V" "$SHA" -m "v$V" && git push origin "v$V" && gh release create "v$V" --verify-tag --notes-file "/tmp/notes-v$V.md"Never run a bare
gh release create vX.Y.Z. With no existing tag it places one on the tip of the default branch, so running it while the bump is still on a release branch tags the previous release's commit. The workflow then publishes whatever version it finds in that commit'spackage.json, and you get avX.Y.ZGitHub Release that silently republishes the old version. The publish workflow now refuses to continue whenGITHUB_REF_NAMEis notv<package.json version>, so that exact scenario fails beforenpm publishrather than silently republishing. The sequence above is still required, and guards a case the workflow cannot: the workflow guard only runs once a release already exists, and it passes for any commit carrying the right version — so it catches a mis-tagged release, not the wrong commit being tagged.Each element is load-bearing:
gh pr view … .mergeCommit.oidnames the release PR's own squash commit. Do not substitutegit rev-parse origin/main— that is merely whatever is onmainat the moment you look, so an unrelated merge landing in the gap gets tagged and shipped instead.ghexits 0 and prints nothing for an unmerged PR, hence the explicittest -n.- The
&&chain stops on the first failure instead of falling through to the irreversible step. Bothgit showcalls are assigned to a variable rather than piped directly, so their exit status is actually checked — a pipeline reports only its last command's status unlesspipefailis set, which is not assumed here. git merge-base --is-ancestorproves the commit is reachable frommain. Mere existence is not enough — a commit can be present locally because some other branch was fetched.- The version test reads
package.jsonout of the target commit, not the working tree, which would still show the right version while$SHApointed elsewhere. - The
awklifts that version's section out of the commit'sCHANGELOG.mdfor--notes-file. It stops at the next## [heading or at the first link-reference definition, because the oldest entry has no heading after it and would otherwise swallow the entire link-reference block.grep -qrather thantest -sguards the result: a section empty apart from its blank line still produces a one-byte file, whichtest -saccepts.
-
The
Publish to npm + MCP Registryworkflow runs automatically: itnpm publishes with provenance, polls the registry until the tarball is available, then pushes the matchingserver.jsonto the MCP Registry viamcp-publisher.
The workflow skips npm publish cleanly if the version is already on npm (cutover guard for releases that were partially published manually).
npm authentication
Publishing uses npm Trusted Publishing: the workflow's GitHub OIDC token (id-token: write) is exchanged for a one-shot publish token at runtime. No NPM_TOKEN secret needs to live in the repo.
The binding is configured in the npm web UI (package → Trusted Publishers): provider GitHub Actions, organization lazyants, repository hetzner-mcp-server, workflow publish-registry.yml.
License
FSL-1.1-MIT — see LICENSE for the full terms. Versions 1.1.1 and earlier remain MIT-licensed.
Reviews
No reviews yet
Be the first to review this server!
More Cloud & DevOps MCP Servers
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
MarkItDown
Freeby Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
FinAgent
Freeby mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.
Google Workspace MCP
Freeby Taylorwilsdon · Productivity
Control Gmail, Calendar, Docs, Sheets, Drive, and more from your AI
