Skip to main content
Glama

hetzner-mcp

An MCP server that lets Claude operate a Hetzner estate: Cloud servers, DNS (Cloudflare and Hetzner DNS), hosts over SSH, Coolify, and multi-step recipes. Every write is a dry run until confirmed, protected servers refuse destructive calls, and every call is audited.

Status: v0.1.0. Built and tested against mocked APIs, a real SSH host, real Docker and a real Caddy. Not yet pointed at a live Hetzner project.

Modules and tools (53 with everything configured)

Module

Switched on by

Tools

fleet

always

hz_fleet_overview, hz_host_list, hz_host_register, hz_host_remove

cloud

HCLOUD_TOKEN

hz_server_list, hz_server_get, hz_catalog, hz_action_status, hz_resource_list, hz_server_create, hz_server_power, hz_server_rebuild, hz_server_delete, hz_server_resize, hz_snapshot_create, hz_snapshot_delete, hz_backup_set, hz_firewall_create, hz_firewall_rules_set, hz_firewall_attach, hz_volume_create, hz_volume_action, hz_network_create, hz_network_attach, hz_ip_set_ptr, hz_floating_ip_assign, hz_ssh_key_add

dns

CLOUDFLARE_API_TOKEN and/or HCLOUD_TOKEN

dns_zone_list, dns_records_list, dns_record_set, dns_record_delete, dns_check

host

SSH_KEY or SSH_KEY_PATH

host_status, host_docker_ps, host_logs, host_file_read, host_caddy_routes, host_file_write, host_compose_action, host_caddy_route, host_run, host_bootstrap

coolify

COOLIFY_BASE_URL + COOLIFY_API_TOKEN

coolify_list, coolify_get, coolify_deployments, coolify_env_list, coolify_deploy, coolify_app_action, coolify_env_set

recipes

SSH key (+ HCLOUD_TOKEN for new servers)

recipe_new_app_server, recipe_deploy_stack

audit

always

audit_log

hz_capabilities is always present and says which modules are on and what each one needs.

Related MCP server: hetzner-mcp-server

Safety model

  • Dry run by default. Write tools return a plan unless called with confirm: true. Delete and rebuild also need confirm_name equal to the server name.

  • Protected resources. A server is protected when it is in PROTECTED_SERVERS, has the Hetzner label protected=true, is marked protected in the host registry, or has Hetzner delete/rebuild protection on. Destructive calls on it are refused even with confirm: true.

  • Host registry. SSH only reaches hosts listed in config/hosts.json. File reads and writes stay inside each host's allowed_paths. .env files return their keys, never values.

  • Audit log. Every call (read, dry run, refused, executed) is appended to data/audit.jsonl with secrets masked.

  • Caddy edits are fenced with markers, backed up, validated and rolled back on failure before a reload.

Stack

Node 22, TypeScript (strict), @modelcontextprotocol/sdk, zod, ssh2, Express (Streamable HTTP), Biome, Vitest, pnpm, Docker.

Quickstart (local, stdio)

pnpm install
cp .env.example .env            # fill in what you have
cp config/hosts.example.json config/hosts.json
pnpm build

Claude Desktop / Claude Code config:

{
  "mcpServers": {
    "hetzner": {
      "command": "node",
      "args": ["C:\\path\\to\\hetzner-mcp\\dist\\index.js"],
      "env": { "HCLOUD_TOKEN": "…", "SSH_KEY_PATH": "C:\\Users\\you\\.ssh\\hetzner_mcp_ed25519", "HOSTS_FILE": "C:\\path\\to\\hetzner-mcp\\config\\hosts.json" }
    }
  }
}

Hosted (HTTP, behind Caddy on the app server): see docs/RUNBOOK.md.

CI checks

pnpm typecheck && pnpm lint && pnpm test

CI runs the same three plus pnpm build and a gitleaks secret scan.

Growing it

Add a folder under src/modules/<id>/ exporting a Module (status() + register()), register tools through the ToolKit (t.read / t.write), and list it in src/modules/index.ts. The guard, audit and capability report come for free. See docs/CONTRIBUTING.md.

License

MIT

Related MCP Connectors

Related MCP Servers