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 SSH keys for secure server access
- View available images, server types, and locations
- Power on/off and reboot servers
- 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 distributed as a Python package 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. Once published to PyPI you can reference it simply as mcp-hetzner; until
then (or to always track the latest code), reference it straight from the Git repository:
# From PyPI (once published)
uvx mcp-hetzner
# Straight from the Git repository (works today, no PyPI needed)
uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
The sections below show how to register it with each MCP client. Everywhere you see
"args": ["mcp-hetzner"] (or -- uvx mcp-hetzner), that is the PyPI form.
⚠️ Not on PyPI yet? Until the package is published,
uvx mcp-hetznerwill fail with "package not found". Use the Git form instead — swapmcp-hetznerfor--from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetznerin any command or config below. Each section shows the exact Git-form command so you can copy‑paste it directly.
In every example, replace your_token_here with your real Hetzner Cloud API token
(see Getting a Hetzner Cloud API token).
Claude Code
Add the server with the built-in claude mcp add command, injecting your token via -e:
# PyPI form (once published)
claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
# Git form (works right now, before publishing)
claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- \
uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
- Add
--scope userto make it available across all your projects, 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:
# PyPI form (once published)
codex mcp add hetzner --env HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
# Git form (works right now, before publishing)
codex mcp add hetzner --env HCLOUD_TOKEN=your_token_here -- \
uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
Or edit ~/.codex/config.toml directly (note the underscore in mcp_servers):
[mcp_servers.hetzner]
command = "uvx"
# PyPI form: args = ["mcp-hetzner"]
# Git form (before publishing):
args = ["--from", "git+https://github.com/bcanozgur/mcp-hetzner.git", "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": ["--from", "git+https://github.com/bcanozgur/mcp-hetzner.git", "mcp-hetzner"],
"env": {
"HCLOUD_TOKEN": "your_token_here"
}
}
}
}
Once the package is on PyPI, simplify
argsto just["mcp-hetzner"].
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). |
MCP_HETZNER_LOG_LEVEL |
No | INFO |
Log verbosity (DEBUG, INFO, WARNING, ERROR). Logs go to stderr. |
MCP_HOST |
No | localhost |
Bind host, used only by the sse transport. |
MCP_PORT |
No | 8080 |
Bind port, used only by the sse transport. |
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
}
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.2.0.tar.gz.
File metadata
- Download URL: mcp_hetzner-0.2.0.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d467179b0f84745586d9c12bfd9837ef1027e9d9fcd64631aede502ae94e0c89
|
|
| MD5 |
4bb741915bf7d5decfd91c9ea46dca5d
|
|
| BLAKE2b-256 |
f8c21b974daf7f0308345409ceced0703e9f8239f7030a5a70014c8a49e9c732
|
File details
Details for the file mcp_hetzner-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_hetzner-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.5 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 |
bf6284ca367ac01dff6fce9abf62ac748a0b93c204e94d435c42ac2993ee8db6
|
|
| MD5 |
1e5de54a9b59e2181ea4166f9eda046c
|
|
| BLAKE2b-256 |
ee02a6f9c73934a2d3bec09c4e43e506698708ed53f76effa0e9e2708452defc
|