mcp-hetzner 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,427 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-hetzner
3
+ Version: 0.2.0
4
+ Summary: 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.
5
+ Author: bcanozgur
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/bcanozgur/mcp-hetzner
8
+ Project-URL: Repository, https://github.com/bcanozgur/mcp-hetzner
9
+ Project-URL: Bug Tracker, https://github.com/bcanozgur/mcp-hetzner/issues
10
+ Keywords: mcp,model-context-protocol,hetzner,hetzner-cloud,hcloud,llm,claude,claude-code,codex,cursor,ai,devops,infrastructure
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: System :: Systems Administration
22
+ Requires-Python: >=3.11
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: mcp>=1.0.0
26
+ Requires-Dist: hcloud>=1.24.0
27
+ Requires-Dist: python-dotenv>=1.0.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: build; extra == "dev"
30
+ Requires-Dist: twine; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # Hetzner Cloud MCP Server
34
+
35
+ 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.
36
+
37
+ ![MCP Hetzner Demo](media/mcp-hetzner.gif)
38
+
39
+ ## Features
40
+
41
+ - List, create, and manage Hetzner Cloud servers
42
+ - Create, attach, detach, and resize volumes
43
+ - Manage firewall rules and apply them to servers
44
+ - Create and manage SSH keys for secure server access
45
+ - View available images, server types, and locations
46
+ - Power on/off and reboot servers
47
+ - Works with any MCP client — Claude Code, Codex, Cursor, VS Code, Claude Desktop, and more
48
+ - Runs with a single `uvx` command; no manual install or virtualenv required
49
+
50
+ ## Requirements
51
+
52
+ - A Hetzner Cloud API token ([how to get one](#getting-a-hetzner-cloud-api-token))
53
+ - [`uv`](https://docs.astral.sh/uv/) (provides `uvx`) — the recommended way to run the server.
54
+ Install it with `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS/Linux) or
55
+ `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"` (Windows).
56
+ Python 3.11+ is also supported if you prefer `pip`/`pipx`.
57
+
58
+ ## Getting a Hetzner Cloud API token
59
+
60
+ 1. Open the [Hetzner Cloud Console](https://console.hetzner.cloud).
61
+ 2. Select your project → **Security** → **API Tokens**.
62
+ 3. Click **Generate API Token**, give it **Read & Write** permission, and copy the token
63
+ (it is shown only once).
64
+
65
+ You will pass this token to the MCP server through the `HCLOUD_TOKEN` environment variable.
66
+
67
+ ## Installation
68
+
69
+ The server is distributed as a Python package and runs with `uvx` (the Python equivalent of
70
+ `npx`). `uvx` downloads the package into an isolated, cached environment and runs it — nothing
71
+ is installed globally. Once published to PyPI you can reference it simply as `mcp-hetzner`; until
72
+ then (or to always track the latest code), reference it straight from the Git repository:
73
+
74
+ ```bash
75
+ # From PyPI (once published)
76
+ uvx mcp-hetzner
77
+
78
+ # Straight from the Git repository (works today, no PyPI needed)
79
+ uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
80
+ ```
81
+
82
+ The sections below show how to register it with each MCP client. Everywhere you see
83
+ `"args": ["mcp-hetzner"]` (or `-- uvx mcp-hetzner`), that is the **PyPI form**.
84
+
85
+ > **⚠️ Not on PyPI yet?** Until the package is published, `uvx mcp-hetzner` will fail with
86
+ > "package not found". Use the **Git form** instead — swap `mcp-hetzner` for
87
+ > `--from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner` in any command or config
88
+ > below. Each section shows the exact Git-form command so you can copy‑paste it directly.
89
+
90
+ In every example, replace `your_token_here` with your real Hetzner Cloud API token
91
+ (see [Getting a Hetzner Cloud API token](#getting-a-hetzner-cloud-api-token)).
92
+
93
+ ### Claude Code
94
+
95
+ Add the server with the built-in `claude mcp add` command, injecting your token via `-e`:
96
+
97
+ ```bash
98
+ # PyPI form (once published)
99
+ claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
100
+
101
+ # Git form (works right now, before publishing)
102
+ claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- \
103
+ uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
104
+ ```
105
+
106
+ - Add `--scope user` to make it available across all your projects, or `--scope project` to
107
+ commit it to a shared `.mcp.json` for your team.
108
+ - Verify it connected with `claude mcp list` (should report `hetzner … ✔ Connected`).
109
+ - In a session, `/mcp` lists the active servers and their tools.
110
+
111
+ ### Codex
112
+
113
+ Add the server with the `codex mcp add` command:
114
+
115
+ ```bash
116
+ # PyPI form (once published)
117
+ codex mcp add hetzner --env HCLOUD_TOKEN=your_token_here -- uvx mcp-hetzner
118
+
119
+ # Git form (works right now, before publishing)
120
+ codex mcp add hetzner --env HCLOUD_TOKEN=your_token_here -- \
121
+ uvx --from git+https://github.com/bcanozgur/mcp-hetzner.git mcp-hetzner
122
+ ```
123
+
124
+ Or edit `~/.codex/config.toml` directly (note the underscore in `mcp_servers`):
125
+
126
+ ```toml
127
+ [mcp_servers.hetzner]
128
+ command = "uvx"
129
+ # PyPI form: args = ["mcp-hetzner"]
130
+ # Git form (before publishing):
131
+ args = ["--from", "git+https://github.com/bcanozgur/mcp-hetzner.git", "mcp-hetzner"]
132
+
133
+ [mcp_servers.hetzner.env]
134
+ HCLOUD_TOKEN = "your_token_here"
135
+ ```
136
+
137
+ In the Codex TUI, run `/mcp` to confirm the server is active.
138
+
139
+ ### Cursor
140
+
141
+ Open **Cursor Settings → MCP → Add new MCP Server**, or add this to
142
+ `~/.cursor/mcp.json` (global) or `<project>/.cursor/mcp.json` (per-project):
143
+
144
+ ```json
145
+ {
146
+ "mcpServers": {
147
+ "hetzner": {
148
+ "command": "uvx",
149
+ "args": ["--from", "git+https://github.com/bcanozgur/mcp-hetzner.git", "mcp-hetzner"],
150
+ "env": {
151
+ "HCLOUD_TOKEN": "your_token_here"
152
+ }
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ > Once the package is on PyPI, simplify `args` to just `["mcp-hetzner"]`.
159
+
160
+ ### Other MCP clients (VS Code, Claude Desktop, Windsurf, …)
161
+
162
+ Every MCP client that supports stdio servers uses the same shape — a `command`, `args`, and an
163
+ `env` block. Drop the JSON above into the client's MCP config file:
164
+
165
+ - **VS Code** (GitHub Copilot / MCP extensions): `.vscode/mcp.json`
166
+ - **Claude Desktop**: `claude_desktop_config.json` (Settings → Developer → Edit Config)
167
+ - **Windsurf**: `~/.codeium/windsurf/mcp_config.json`
168
+
169
+ > **PATH note:** MCP clients launched from a GUI may not inherit your shell's `PATH`, so a bare
170
+ > `"command": "uvx"` can fail with `spawn uvx ENOENT`. If that happens, use the absolute path —
171
+ > find it with `which uvx` (macOS/Linux) or `where uvx` (Windows), e.g.
172
+ > `/opt/homebrew/bin/uvx`.
173
+
174
+ ## Configuration
175
+
176
+ | Environment variable | Required | Default | Description |
177
+ | ----------------------- | -------- | ----------- | ------------------------------------------------------------------ |
178
+ | `HCLOUD_TOKEN` | **Yes** | – | Hetzner Cloud API token (Read & Write). |
179
+ | `MCP_HETZNER_LOG_LEVEL` | No | `INFO` | Log verbosity (`DEBUG`, `INFO`, `WARNING`, `ERROR`). Logs go to stderr. |
180
+ | `MCP_HOST` | No | `localhost` | Bind host, used only by the `sse` transport. |
181
+ | `MCP_PORT` | No | `8080` | Bind port, used only by the `sse` transport. |
182
+
183
+ The token can be supplied three ways, in order of precedence:
184
+
185
+ 1. The `--token` command-line flag.
186
+ 2. The `HCLOUD_TOKEN` environment variable — **recommended**; inject it via your MCP client's
187
+ `env` block as shown above.
188
+ 3. A `.env` file in the working directory containing `HCLOUD_TOKEN=…` — convenient for local
189
+ development. Copy `.env.example` to `.env` to get started.
190
+
191
+ ## Running from source (development)
192
+
193
+ ```bash
194
+ # Clone your fork and install in editable mode
195
+ git clone https://github.com/bcanozgur/mcp-hetzner.git
196
+ cd mcp-hetzner
197
+ pip install -e .
198
+
199
+ # Provide a token for local runs
200
+ cp .env.example .env # then edit .env and set HCLOUD_TOKEN
201
+
202
+ # Run the server (stdio is the default transport used by MCP clients)
203
+ mcp-hetzner
204
+ # or as a module
205
+ python -m mcp_hetzner
206
+ ```
207
+
208
+ Command-line options:
209
+
210
+ ```bash
211
+ mcp-hetzner --help
212
+ mcp-hetzner --token <TOKEN> # override HCLOUD_TOKEN
213
+ mcp-hetzner --transport sse --port 8000 # HTTP/SSE transport instead of stdio
214
+ ```
215
+
216
+ To point an MCP client at your local checkout without installing, use `uvx --from .`:
217
+
218
+ ```bash
219
+ claude mcp add hetzner -e HCLOUD_TOKEN=your_token_here -- uvx --from /path/to/mcp-hetzner mcp-hetzner
220
+ ```
221
+
222
+ The repository also ships a ready-to-use `.mcp.json` that runs the server from the checkout via
223
+ `uvx --from .` and reads `HCLOUD_TOKEN` from your shell environment.
224
+
225
+ ## Publishing to PyPI
226
+
227
+ The package uses a single-sourced version (`mcp_hetzner.__version__`) and is ready to publish so
228
+ that `uvx mcp-hetzner` works for everyone:
229
+
230
+ ```bash
231
+ pip install -e ".[dev]" # installs build + twine
232
+ python -m build # produces dist/*.whl and dist/*.tar.gz
233
+ python -m twine upload dist/*
234
+ ```
235
+
236
+ Bump `__version__` in `mcp_hetzner/__init__.py` before each release.
237
+
238
+ ## Example Workflows
239
+
240
+ ### Basic Server Management
241
+
242
+ ```
243
+ # List all your servers
244
+ list_servers
245
+
246
+ # Create a new server
247
+ create_server {
248
+ "name": "web-server",
249
+ "server_type": "cx11",
250
+ "image": "ubuntu-22.04"
251
+ }
252
+
253
+ # Power operations
254
+ power_off {"server_id": 12345}
255
+ power_on {"server_id": 12345}
256
+ reboot {"server_id": 12345}
257
+
258
+ # Delete a server when no longer needed
259
+ delete_server {"server_id": 12345}
260
+ ```
261
+
262
+ ### Volume Management
263
+
264
+ ```
265
+ # List all volumes
266
+ list_volumes
267
+
268
+ # Create a new volume
269
+ create_volume {
270
+ "name": "data-volume",
271
+ "size": 10,
272
+ "location": "nbg1",
273
+ "format": "ext4"
274
+ }
275
+
276
+ # Attach volume to a server
277
+ attach_volume {
278
+ "volume_id": 12345,
279
+ "server_id": 67890,
280
+ "automount": true
281
+ }
282
+
283
+ # Detach volume from server
284
+ detach_volume {
285
+ "volume_id": 12345
286
+ }
287
+
288
+ # Resize a volume (can only increase size)
289
+ resize_volume {
290
+ "volume_id": 12345,
291
+ "size": 50
292
+ }
293
+
294
+ # Delete a volume when no longer needed
295
+ delete_volume {
296
+ "volume_id": 12345
297
+ }
298
+ ```
299
+
300
+ ### Firewall Management
301
+
302
+ ```
303
+ # List all firewalls
304
+ list_firewalls
305
+
306
+ # Create a firewall for web servers
307
+ create_firewall {
308
+ "name": "web-firewall",
309
+ "rules": [
310
+ {
311
+ "direction": "in",
312
+ "protocol": "tcp",
313
+ "port": "80",
314
+ "source_ips": ["0.0.0.0/0", "::/0"]
315
+ },
316
+ {
317
+ "direction": "in",
318
+ "protocol": "tcp",
319
+ "port": "443",
320
+ "source_ips": ["0.0.0.0/0", "::/0"]
321
+ }
322
+ ]
323
+ }
324
+
325
+ # Apply firewall to a server
326
+ apply_firewall_to_resources {
327
+ "firewall_id": 12345,
328
+ "resources": [
329
+ {
330
+ "type": "server",
331
+ "server_id": 67890
332
+ }
333
+ ]
334
+ }
335
+ ```
336
+
337
+ ### SSH Key Management
338
+
339
+ ```
340
+ # List all SSH keys
341
+ list_ssh_keys
342
+
343
+ # Create a new SSH key
344
+ create_ssh_key {
345
+ "name": "my-laptop",
346
+ "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAA... user@laptop"
347
+ }
348
+
349
+ # Use the SSH key when creating a server
350
+ create_server {
351
+ "name": "secure-server",
352
+ "server_type": "cx11",
353
+ "image": "ubuntu-22.04",
354
+ "ssh_keys": [12345]
355
+ }
356
+
357
+ # Update an SSH key's name
358
+ update_ssh_key {
359
+ "ssh_key_id": 12345,
360
+ "name": "work-laptop"
361
+ }
362
+
363
+ # Delete an SSH key
364
+ delete_ssh_key {
365
+ "ssh_key_id": 12345
366
+ }
367
+ ```
368
+
369
+ ### Infrastructure Planning
370
+
371
+ ```
372
+ # Explore available resources
373
+ list_server_types
374
+ list_images
375
+ list_locations
376
+
377
+ # Get specific server information
378
+ get_server {"server_id": 12345}
379
+ ```
380
+
381
+ ## Available Functions
382
+
383
+ The MCP server provides the following functions:
384
+
385
+ ### Server Management
386
+ - `list_servers`: List all servers in your Hetzner Cloud account
387
+ - `get_server`: Get details about a specific server
388
+ - `create_server`: Create a new server
389
+ - `delete_server`: Delete a server
390
+ - `power_on`: Power on a server
391
+ - `power_off`: Power off a server
392
+ - `reboot`: Reboot a server
393
+
394
+ ### Volume Management
395
+ - `list_volumes`: List all volumes in your Hetzner Cloud account
396
+ - `get_volume`: Get details about a specific volume
397
+ - `create_volume`: Create a new volume
398
+ - `delete_volume`: Delete a volume
399
+ - `attach_volume`: Attach a volume to a server
400
+ - `detach_volume`: Detach a volume from a server
401
+ - `resize_volume`: Increase the size of a volume
402
+
403
+ ### Firewall Management
404
+ - `list_firewalls`: List all firewalls in your Hetzner Cloud account
405
+ - `get_firewall`: Get details about a specific firewall
406
+ - `create_firewall`: Create a new firewall
407
+ - `update_firewall`: Update firewall name or labels
408
+ - `delete_firewall`: Delete a firewall
409
+ - `set_firewall_rules`: Set or update firewall rules
410
+ - `apply_firewall_to_resources`: Apply a firewall to servers or server groups
411
+ - `remove_firewall_from_resources`: Remove a firewall from servers or server groups
412
+
413
+ ### SSH Key Management
414
+ - `list_ssh_keys`: List all SSH keys in your Hetzner Cloud account
415
+ - `get_ssh_key`: Get details about a specific SSH key
416
+ - `create_ssh_key`: Create a new SSH key
417
+ - `update_ssh_key`: Update SSH key name or labels
418
+ - `delete_ssh_key`: Delete an SSH key
419
+
420
+ ### Information
421
+ - `list_images`: List available OS images
422
+ - `list_server_types`: List available server types
423
+ - `list_locations`: List available datacenter locations
424
+
425
+ ## License
426
+
427
+ MIT