A Model Context Protocol (MCP) server for the Hetzner Cloud API — manage servers, volumes, firewalls, and SSH keys from Claude Code, Codex, Cursor, and any MCP client.
Project description
Hetzner Cloud MCP Server
A Model Context Protocol (MCP) server for interacting with the Hetzner Cloud API. This server allows language models to manage Hetzner Cloud resources through structured functions.
Features
- List, create, and manage Hetzner Cloud servers
- Create, attach, detach, and resize volumes
- Manage firewall rules and apply them to servers
- Create and manage private networks — subnets, routes, and server attachment
- Manage Hetzner DNS zones and records (separate DNS API token)
- Create and manage SSH keys for secure server access
- View available images, server types, and locations
- Power on/off and reboot servers
- Automatic retry with exponential backoff on API rate limits (HTTP 429)
- Works with any MCP client — Claude Code, Codex, Cursor, VS Code, Claude Desktop, and more
- Runs with a single
uvxcommand; no manual install or virtualenv required
Requirements
- A Hetzner Cloud API token (how to get one)
uv(providesuvx) — the recommended way to run the server. Install it withcurl -LsSf https://astral.sh/uv/install.sh | sh(macOS/Linux) orpowershell -c "irm https://astral.sh/uv/install.ps1 | iex"(Windows). Python 3.11+ is also supported if you preferpip/pipx.
Getting a Hetzner Cloud API token
- Open the Hetzner Cloud Console.
- Select your project → Security → API Tokens.
- Click Generate API Token, give it Read & Write permission, and copy the token (it is shown only once).
You will pass this token to the MCP server through the HCLOUD_TOKEN environment variable.
Installation
The server is published to PyPI and runs with uvx
(the Python equivalent of npx). uvx downloads the package into an isolated, cached
environment and runs it — nothing is installed globally:
uvx mcp-hetzner
Tip: To run the very latest unreleased code straight from Git instead of PyPI, replace
mcp-hetznerwith--from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetznerin any command or config below.
In every example, replace your_token_here with your real Hetzner Cloud API token
(see Getting a Hetzner Cloud API token).
Claude Code
Run this from the project where you actually want to use the server — by default claude mcp add scopes the server to your current working directory, so add it from inside whichever repo
you'll be driving Hetzner from (you don't need to clone this repo to do that; uvx mcp-hetzner
fetches the published package). Inject your token via -e:
claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
- Add
--scope userto make it available across all your projects regardless of which directory you run the command from, or--scope projectto commit it to a shared.mcp.jsonfor your team. - Verify it connected with
claude mcp list(should reporthetzner … ✔ Connected). - In a session,
/mcplists the active servers and their tools.
Codex
Add the server with the codex mcp add command:
codex mcp add hetzner --env HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
Or edit ~/.codex/config.toml directly (note the underscore in mcp_servers):
[mcp_servers.hetzner]
command = "uvx"
args = ["mcp-hetzner"]
[mcp_servers.hetzner.env]
HCLOUD_TOKEN = "your_token_here"
In the Codex TUI, run /mcp to confirm the server is active.
Cursor
Open Cursor Settings → MCP → Add new MCP Server, or add this to
~/.cursor/mcp.json (global) or <project>/.cursor/mcp.json (per-project):
{
"mcpServers": {
"hetzner": {
"command": "uvx",
"args": ["mcp-hetzner"],
"env": {
"HCLOUD_TOKEN": "your_token_here"
}
}
}
}
Other MCP clients (VS Code, Claude Desktop, Windsurf, …)
Every MCP client that supports stdio servers uses the same shape — a command, args, and an
env block. Drop the JSON above into the client's MCP config file:
- VS Code (GitHub Copilot / MCP extensions):
.vscode/mcp.json - Claude Desktop:
claude_desktop_config.json(Settings → Developer → Edit Config) - Windsurf:
~/.codeium/windsurf/mcp_config.json
PATH note: MCP clients launched from a GUI may not inherit your shell's
PATH, so a bare"command": "uvx"can fail withspawn uvx ENOENT. If that happens, use the absolute path — find it withwhich uvx(macOS/Linux) orwhere uvx(Windows), e.g./opt/homebrew/bin/uvx.
Configuration
| Environment variable | Required | Default | Description |
|---|---|---|---|
HCLOUD_TOKEN |
Yes | – | Hetzner Cloud API token (Read & Write). |
HETZNER_DNS_TOKEN |
For DNS | – | Hetzner DNS API token — required only for the DNS tools. This is a separate credential from HCLOUD_TOKEN; create one at https://dns.hetzner.com/settings/api-token. |
MCP_HETZNER_LOG_LEVEL |
No | INFO |
Log verbosity (DEBUG, INFO, WARNING, ERROR). Logs go to stderr. |
MCP_HETZNER_MAX_RETRIES |
No | 5 |
Max retries for rate-limited (HTTP 429) API calls. |
MCP_HOST |
No | localhost |
Bind host, used only by the sse transport. |
MCP_PORT |
No | 8080 |
Bind port, used only by the sse transport. |
Note: DNS tools use Hetzner's separate DNS API, so they need
HETZNER_DNS_TOKENin addition toHCLOUD_TOKEN. The Cloud tools (servers, volumes, firewalls, networks, SSH keys) work withHCLOUD_TOKENalone.
The token can be supplied three ways, in order of precedence:
- The
--tokencommand-line flag. - The
HCLOUD_TOKENenvironment variable — recommended; inject it via your MCP client'senvblock as shown above. - A
.envfile in the working directory containingHCLOUD_TOKEN=…— convenient for local development. Copy.env.exampleto.envto get started.
Running from source (development)
# Clone your fork and install in editable mode
git clone https://github.com/bcanozgur/mcp-hetzner.git
cd mcp-hetzner
pip install -e .
# Provide a token for local runs
cp .env.example .env # then edit .env and set HCLOUD_TOKEN
# Run the server (stdio is the default transport used by MCP clients)
mcp-hetzner
# or as a module
python -m mcp_hetzner
Command-line options:
mcp-hetzner --help
mcp-hetzner --token <TOKEN> # override HCLOUD_TOKEN
mcp-hetzner --transport sse --port 8000 # HTTP/SSE transport instead of stdio
To point an MCP client at your local checkout without installing, use uvx --from .:
claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- uvx --from /path/to/mcp-hetzner mcp-hetzner
The repository also ships a ready-to-use .mcp.json that runs the server from the checkout via
uvx --from . and reads HCLOUD_TOKEN from your shell environment.
Publishing to PyPI
The package uses a single-sourced version (mcp_hetzner.__version__) and is ready to publish so
that uvx mcp-hetzner works for everyone:
pip install -e ".[dev]" # installs build + twine
python -m build # produces dist/*.whl and dist/*.tar.gz
python -m twine upload dist/*
Bump __version__ in mcp_hetzner/__init__.py before each release.
Example Workflows
Basic Server Management
# List all your servers
list_servers
# Create a new server
create_server {
"name": "web-server",
"server_type": "cx11",
"image": "ubuntu-22.04"
}
# Power operations
power_off {"server_id": 12345}
power_on {"server_id": 12345}
reboot {"server_id": 12345}
# Delete a server when no longer needed
delete_server {"server_id": 12345}
Volume Management
# List all volumes
list_volumes
# Create a new volume
create_volume {
"name": "data-volume",
"size": 10,
"location": "nbg1",
"format": "ext4"
}
# Attach volume to a server
attach_volume {
"volume_id": 12345,
"server_id": 67890,
"automount": true
}
# Detach volume from server
detach_volume {
"volume_id": 12345
}
# Resize a volume (can only increase size)
resize_volume {
"volume_id": 12345,
"size": 50
}
# Delete a volume when no longer needed
delete_volume {
"volume_id": 12345
}
Firewall Management
# List all firewalls
list_firewalls
# Create a firewall for web servers
create_firewall {
"name": "web-firewall",
"rules": [
{
"direction": "in",
"protocol": "tcp",
"port": "80",
"source_ips": ["0.0.0.0/0", "::/0"]
},
{
"direction": "in",
"protocol": "tcp",
"port": "443",
"source_ips": ["0.0.0.0/0", "::/0"]
}
]
}
# Apply firewall to a server
apply_firewall_to_resources {
"firewall_id": 12345,
"resources": [
{
"type": "server",
"server_id": 67890
}
]
}
SSH Key Management
# List all SSH keys
list_ssh_keys
# Create a new SSH key
create_ssh_key {
"name": "my-laptop",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAA... user@laptop"
}
# Use the SSH key when creating a server
create_server {
"name": "secure-server",
"server_type": "cx11",
"image": "ubuntu-22.04",
"ssh_keys": [12345]
}
# Update an SSH key's name
update_ssh_key {
"ssh_key_id": 12345,
"name": "work-laptop"
}
# Delete an SSH key
delete_ssh_key {
"ssh_key_id": 12345
}
Private Network Management
# Create a private network
create_network {
"name": "internal",
"ip_range": "10.0.0.0/16"
}
# Add a subnet (required before attaching servers)
add_subnet {
"network_id": 12345,
"ip_range": "10.0.1.0/24",
"network_zone": "eu-central"
}
# Attach a server to the network
attach_server_to_network {
"network_id": 12345,
"server_id": 67890,
"ip": "10.0.1.5"
}
# Add a route
add_route {
"network_id": 12345,
"destination": "10.100.1.0/24",
"gateway": "10.0.1.1"
}
DNS Management
Requires
HETZNER_DNS_TOKEN(separate fromHCLOUD_TOKEN).
# List DNS zones
list_dns_zones
# Create a zone (domain)
create_dns_zone {
"name": "example.com"
}
# Add an A record (use "@" for the zone root)
create_dns_record {
"zone_id": "abc123",
"type": "A",
"name": "www",
"value": "203.0.113.10",
"ttl": 3600
}
# Create several records at once
bulk_create_dns_records {
"records": [
{ "zone_id": "abc123", "type": "A", "name": "@", "value": "203.0.113.10" },
{ "zone_id": "abc123", "type": "CNAME", "name": "blog", "value": "www.example.com." }
]
}
Infrastructure Planning
# Explore available resources
list_server_types
list_images
list_locations
# Get specific server information
get_server {"server_id": 12345}
Available Functions
The MCP server provides the following functions:
Server Management
list_servers: List all servers in your Hetzner Cloud accountget_server: Get details about a specific servercreate_server: Create a new serverdelete_server: Delete a serverpower_on: Power on a serverpower_off: Power off a serverreboot: Reboot a server
Volume Management
list_volumes: List all volumes in your Hetzner Cloud accountget_volume: Get details about a specific volumecreate_volume: Create a new volumedelete_volume: Delete a volumeattach_volume: Attach a volume to a serverdetach_volume: Detach a volume from a serverresize_volume: Increase the size of a volume
Firewall Management
list_firewalls: List all firewalls in your Hetzner Cloud accountget_firewall: Get details about a specific firewallcreate_firewall: Create a new firewallupdate_firewall: Update firewall name or labelsdelete_firewall: Delete a firewallset_firewall_rules: Set or update firewall rulesapply_firewall_to_resources: Apply a firewall to servers or server groupsremove_firewall_from_resources: Remove a firewall from servers or server groups
SSH Key Management
list_ssh_keys: List all SSH keys in your Hetzner Cloud accountget_ssh_key: Get details about a specific SSH keycreate_ssh_key: Create a new SSH keyupdate_ssh_key: Update SSH key name or labelsdelete_ssh_key: Delete an SSH key
Information
list_images: List available OS imageslist_server_types: List available server typeslist_locations: List available datacenter locations
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_hetzner-0.3.0.tar.gz.
File metadata
- Download URL: mcp_hetzner-0.3.0.tar.gz
- Upload date:
- Size: 28.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df14b7c812f9ae2aa1f4b5779fbf4f9c27cb889f16a891bd8cffc2bdfe6cb095
|
|
| MD5 |
9e6fc078237793780ff8505eb45c4ec0
|
|
| BLAKE2b-256 |
34026d627a2b4625e10ccf8f0f453a4873768e5e649b700f708c604b00abf829
|
File details
Details for the file mcp_hetzner-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mcp_hetzner-0.3.0-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b8d43d7e0c48915334ca8d126886251efcd2c816fdedb8dbaf8589e50276c3f
|
|
| MD5 |
b89cb79e72bc5366604afd368bbe6743
|
|
| BLAKE2b-256 |
659338cdae172742c8f4581d1c129a57e774e94c8e141dc361e5f2934a08dcca
|