hetzner-mcp-server
Health Uyari
- License — License: NOASSERTION
- No description — Repository has no description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Uyari
- fs module — File system access in package.json
- network request — Outbound network request in package.json
- network request — Outbound network request in scripts/check-versions.mjs
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
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, Locations/Server Types, Pricing | 33 |
hetzner-mcp-networking |
Networks, Firewalls | 23 |
hetzner-mcp-load-balancers |
Load Balancers, Certificates | 29 |
hetzner-mcp-ips |
Floating IPs, Primary IPs | 21 |
hetzner-mcp-storage |
Volumes, Images | 18 |
hetzner-mcp-storage-boxes |
Storage Boxes (+ snapshots, subaccounts, types) | 30 |
hetzner-mcp-config |
SSH Keys, ISOs, Placement Groups | 15 |
hetzner-mcp-dns |
DNS Zones | 23 |
Every entry point includes hetzner_wait_for_action; the full server registers it once.
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
Primary list tools expose sort for servers, volumes, networks, firewalls, load balancers, IPs, certificates, SSH keys, and placement groups. Image listing also supports bound_to (one server ID or an array) and include_deprecated. Server and load-balancer metrics accept step in seconds; network creation accepts expose_routes_to_vswitch.
Set resource on hetzner_get_pricing to server_types, load_balancer_types, volume, floating_ips, primary_ips, traffic, image, or server_backup to reduce the response. Filtered results preserve currency and VAT; traffic selects location-specific included traffic and additional traffic prices for server and load-balancer types.
Action waiting (1 shared tool) — every entry point
hetzner_wait_for_action accepts domain, resource_id, action_id, and an optional timeout in seconds (default 300, maximum 3600). It polls paginated per-resource action history and returns the full action when its status becomes success or error; missing or unknown statuses keep waiting until timeout. Supported domains are servers, load_balancers, volumes, networks, firewalls, floating_ips, primary_ips, certificates, images, zones, and storage_boxes; Storage Boxes use their separate API host. The deadline bounds requests and rate-limit delays, and MCP cancellation stops the wait.
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 (5 tools) — servers
hetzner_list_locations, hetzner_get_location, hetzner_list_server_types, hetzner_get_server_type, hetzner_get_pricing
Hetzner removed the /datacenters endpoints after 2026-10-01 (HTTP 410), and this server no longer exposes hetzner_list_datacenters or hetzner_get_datacenter. Use hetzner_list_server_types (locations[].available/recommended) and hetzner_list_locations for availability and region information.
Networks (13 tools) — networking
hetzner_list_networks, hetzner_list_network_members, 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
hetzner_list_network_members returns attached servers and load balancers with IPs, aliases, subnet, and attachment status. Pass a string or array for type, subnet, status, and sort; arrays produce repeated query keys. Results include the API's pagination metadata.
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.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi