vpsnet-mcp 1.0.9 → 2.1.0

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.
package/README.md CHANGED
@@ -1,16 +1,19 @@
1
1
  # vpsnet-mcp
2
2
 
3
- [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for managing [VPSnet.com](https://www.vpsnet.com) virtual private servers. Gives AI assistants full control over your VPS infrastructure — order servers, manage plans, deploy SSH keys, and directly access your servers via SSH for software installation and configuration.
3
+ [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for managing [VPSnet.com](https://www.vpsnet.com) services. Gives AI assistants access to VPS lifecycle operations, managed applications, DNS zones, domain registration and contacts, billing, API-key metadata, SSH-key provisioning, and related account tooling through the VPSNet API.
4
4
 
5
5
  ## Features
6
6
 
7
- - **49 tools** covering the entire VPSnet.com API
7
+ - **190+ tools** covering VPSNet service management, managed applications, free and paid TLS certificates, Automatic SSL subscriptions, DNS, domains, billing, API keys, and account operations
8
8
  - Account & profile management
9
9
  - VPS lifecycle (start, stop, restart, reinstall OS)
10
- - Plan changes (free upgrades/downgrades)
11
- - DNS (rDNS/PTR records)
10
+ - Plan changes (free upgrades/downgrades; KVM/Firecracker disks cannot shrink)
11
+ - Service reverse DNS (rDNS/PTR records)
12
+ - Forward DNS zones, records, DNSSEC, templates, import/export, and DDNS tokens
13
+ - Domain availability, contacts, register/transfer/renew/restore quotes, and paid confirmations
14
+ - Publication-gated managed applications with install, health, events, and typed lifecycle actions
12
15
  - SSH key management — deploy keys and gain direct server access
13
- - API key management
16
+ - API-key metadata inspection (key creation, changes, and revocation remain session-only)
14
17
  - Backups, billing, invoices
15
18
  - Ordering new VPS instances
16
19
  - System status & pricing
@@ -19,7 +22,7 @@
19
22
 
20
23
  Before installing, ensure you have:
21
24
 
22
- 1. **Node.js 18 or newer**
25
+ 1. **Node.js 20 or newer**
23
26
  - Check: `node --version`
24
27
  - Linux/macOS: [nodejs.org](https://nodejs.org) or your package manager
25
28
  - Windows: `winget install OpenJS.NodeJS.LTS` or download from [nodejs.org](https://nodejs.org)
@@ -31,6 +34,220 @@ Before installing, ensure you have:
31
34
 
32
35
  3. **Active [VPSnet.com](https://www.vpsnet.com) account** with an API key (see [Getting an API key](#getting-an-api-key))
33
36
 
37
+ ## Credential configuration paths
38
+
39
+ `VPSNET_API_KEY` is the preferred per-launch credential and takes precedence over files.
40
+ For file-based configuration, set `VPSNET_CONFIG_DIR` to the absolute directory
41
+ containing `.vpsnet-mcp-key` or `.mcp.json`. The key file takes precedence over
42
+ `mcpServers.vpsnet.env.VPSNET_API_KEY` in that JSON file. Alternatively,
43
+ `VPSNET_API_KEY_FILE` selects one absolute key-file path; an unreadable or invalid
44
+ explicit file fails startup instead of choosing another account.
45
+
46
+ Without `VPSNET_CONFIG_DIR`, files are read only from the process's launch directory
47
+ (`cwd`). This is the same for `node /path/to/vpsnet-mcp/build/index.js` and `npx
48
+ vpsnet-mcp`: the package installation/cache directory and parent directories are
49
+ never searched. Set the directory explicitly when an editor or MCP client launches
50
+ from a different working directory. Keep credential files out of version control.
51
+ `VPSNET_API_URL` takes precedence over the URL in that same `.mcp.json`; the existing
52
+ trusted-host and HTTPS checks apply to either source.
53
+
54
+ ## Managed applications
55
+
56
+ Managed Applications, manual SSH, DNS, APIs, and other deployment surfaces are
57
+ peer capabilities. Their order in this document and in the tool list is not a
58
+ recommendation. Choose the path that best matches the user's requested outcome,
59
+ target support, existing state, and explicit constraints. A catalog entry is one
60
+ available managed path, not a reason to override a valid manual or custom
61
+ deployment request. Catalog applications run as Docker containers in the
62
+ customer's server and use typed installation and lifecycle tools.
63
+
64
+ Application reads require `applications:read`. Installation and lifecycle
65
+ changes require `applications:manage` and an idempotency key; ordinary
66
+ application lifecycle changes are not paid
67
+ API-key operations. CPU, RAM, and disk figures are sizing recommendations, not
68
+ installation gates: a supported application remains selectable during ordering
69
+ and installable below those figures. Product, OS, architecture, and runtime
70
+ compatibility remain hard requirements. Changes are asynchronous, so verify them
71
+ with `get_application_installation` and `get_application_events`. Use
72
+ `get_application_health` for a fresh container-health inspection and
73
+ `get_application_logs` for recent size-bounded troubleshooting logs, optionally
74
+ limited to one exact Compose service. Log inspections accept at most 500 lines
75
+ and 131,072 bytes. These two read-scoped inspections create short-lived
76
+ inspection jobs, so the API key must permit POST requests.
77
+
78
+ Installation detail includes bounded application and per-container CPU, memory,
79
+ network, restart, and storage history when the worker reports it. Containers are
80
+ identified only by Compose service and ordinal. Use
81
+ `configure_application_resource_thresholds` after explicit confirmation to
82
+ replace optional display thresholds. Omitted values clear a threshold; the
83
+ thresholds only highlight measurements and do not enforce resources, trigger
84
+ server actions, or affect billing. Set `email_enabled` after explicit
85
+ confirmation to send one account email when a threshold is reached and one when
86
+ it recovers; repeated measurements above the same threshold do not resend.
87
+
88
+ Use `configure_application_access` to change how an installed application is
89
+ reached. Read the installation first and pass its current revision with a new
90
+ idempotency key. `platform_https` allocates an opaque VPSnet hostname with
91
+ automatic DNS and HTTPS, `private` has no public listener, `public_http` uses
92
+ the server's public IP over HTTP, and `managed_https` uses an eligible
93
+ VPSnet-managed DNS zone. `external_https` records an existing customer-managed
94
+ HTTPS address; VPSnet does not configure or validate its DNS, TLS certificate,
95
+ or reverse proxy.
96
+
97
+ `list_application_registry_credentials` exposes only private registry credential
98
+ metadata. Registry token creation and rotation are intentionally not MCP tools:
99
+ use the VPSnet panel or direct REST API so a token never enters a model prompt or
100
+ tool argument. Metadata can identify Docker Hub, GHCR, or an exact custom HTTPS
101
+ registry hostname.
102
+
103
+ Customer recipes are customer-owned Compose definitions, separate from VPSnet
104
+ catalog blueprints. They can be validated on the target worker, saved as
105
+ immutable revisions, installed through the managed lifecycle, and exported
106
+ without secret values. VPSnet catalog recipes are never exportable. Container
107
+ discovery is bounded and read-only: it reports customer and managed containers
108
+ without returning environment values or mounts, and it never adopts or modifies
109
+ detected containers. Controlled adoption is a separate prepare, inspect, and
110
+ explicit-confirm flow for an eligible Compose project. The initial takeover is
111
+ one-time, but its exact external-volume binding remains signed into later
112
+ lifecycle actions. Recovery restarts the source only after the managed
113
+ replacement is conclusively contained; uncertain outcomes fail closed.
114
+
115
+ An immutable update is available only when `get_application_installation`
116
+ returns an `available_actions` entry with `type: "update"`. After explicit user
117
+ confirmation, call `manage_application` with `action: "update"`, the exact
118
+ advertised `expected_blueprint_version` and `expected_upstream_version`, and a
119
+ new idempotency key. Keys are client-global: reuse a key only to replay the
120
+ exact same request, never for another service or operation. The
121
+ backend selects and freezes the eligible published release; the caller does not
122
+ submit an image, tag, or target version.
123
+
124
+ No separate application backup is created. On supported Firecracker services,
125
+ `list_application_restore_points` returns opaque application-consistent nightly
126
+ whole-VM points for the exact current installation revision.
127
+ Viewing points is free, but API keys require `applications:manage`, paid
128
+ operations enabled, `applications:restore` paid scope, and full access because
129
+ the response includes the account balance.
130
+ `quote_application_data_restore` freezes the exact
131
+ charge without debiting the account. `restore_application_data` requires the
132
+ returned quote token, the same idempotency key, and explicit confirmation of
133
+ both payment and data replacement. Paid API keys also require
134
+ `applications:restore`, paid operations enabled, and daily/monthly spend caps.
135
+ It replaces only
136
+ worker-derived declared application data, excludes secrets and unrelated
137
+ Docker/server data, and requires rollback capacity. Poll
138
+ `get_application_data_restore`; `needs_attention` remains locked and must not
139
+ be treated as success. These tools never accept or expose PBS credentials,
140
+ archive names, devices, or filesystem paths.
141
+
142
+ Installation list and detail responses carry a per-platform `capabilities`
143
+ block — `data_restore`, `console`, `compose_adoption`, `custom_projects` and
144
+ `log_service_filter` — plus a separate `access.capabilities.can_configure`
145
+ flag. Treat those flags as the authority on what an installation supports
146
+ rather than attempting an action and reading the failure.
147
+
148
+ Uninstall permanently deletes the managed containers, configuration, saved
149
+ credentials, and application data; existing server backups are retained. The
150
+ `manage_application` call requires `acknowledge_data_loss=true` for uninstall,
151
+ and it must only be set after explicit user confirmation.
152
+
153
+ The MCP surface is task-oriented rather than a one-to-one mirror of every REST
154
+ route. Legacy SMS micro-payment and macro-payment callback integrations remain
155
+ available through the documented REST API and control panel, but are
156
+ intentionally not exposed as MCP tools. Public pre-login order and domain-search
157
+ routes likewise have authenticated MCP equivalents where an account operation
158
+ needs them.
159
+
160
+ ## TLS certificates and Automatic SSL
161
+
162
+ Certificate products are not limited to managed applications. Portable DV, OV,
163
+ and EV orders can be installed on customer-controlled web servers, proxies,
164
+ mail servers, load balancers, APIs, or other TLS-capable systems. Automatic SSL
165
+ subscriptions instead connect a compatible ACME client on VPSnet or another
166
+ provider and keep short-lived certificates current during the paid term.
167
+
168
+ Eligible accounts can also request no-cost portable DV certificates through
169
+ `get_free_certificate_eligibility` → `preflight_free_certificate` →
170
+ `create_free_certificate`. For API or assistant deployment, create a CSR on the
171
+ destination and keep its private key there; MCP accepts only the public CSR and
172
+ later returns only the public certificate chain. VPSnet-managed keys support
173
+ unattended early renewal, but their export remains portal-only behind two-factor
174
+ verification. Free certificates, paid certificate files, paid Automatic SSL,
175
+ and application Managed HTTPS are separate products and lifecycle surfaces.
176
+
177
+ Use `list_certificate_catalog` to distinguish `portable_certificate` from
178
+ `acme_subscription` offers. Automatic SSL follows
179
+ `quote_automatic_ssl_subscription` → `order_automatic_ssl_subscription`, with
180
+ the exact unchanged request, quote token, idempotency key, and explicit payment
181
+ approval. Read state with `list_automatic_ssl_subscriptions` and
182
+ `get_automatic_ssl_subscription`. Additional names use
183
+ `quote_automatic_ssl_domain` → `order_automatic_ssl_domain`; the API prevents
184
+ paying twice for names already covered by base/www or wildcard/base rules.
185
+ During the final 30 days, an eligible next term uses
186
+ `quote_automatic_ssl_renewal` → `order_automatic_ssl_renewal` and is prepaid
187
+ from account balance only after the exact EUR total is approved. Cancellation,
188
+ domain removal, and same-type correction use `manage_automatic_ssl_subscription`;
189
+ ambiguous state is reconciled with `refresh_automatic_ssl_subscription`, never
190
+ by inventing a second mutation. Private ACME server and EAB credentials stay
191
+ in the two-factor-protected customer portal and are intentionally unavailable
192
+ to API keys and MCP, so they cannot enter model context.
193
+ ## Restoring a whole service
194
+
195
+ `request_restore` is paid and destructive: it charges the restore price from the
196
+ account balance and overwrites the **whole** service disk with the backup point,
197
+ losing everything written since. It is a confirmation call, not a price
198
+ enquiry — the API refuses a body that does not carry an explicit confirmation,
199
+ and refuses the charge outright if the price has moved since it was disclosed.
200
+
201
+ There is no dialog on this surface to collect that confirmation, so the tool
202
+ does not manufacture it. `acknowledge_data_replacement` and
203
+ `acknowledge_restore_charge` must each be `true`, and are only to be set after
204
+ the user has actually approved the disk replacement and the charge — the same
205
+ rule as `acknowledge_data_loss` on `manage_application`. Omitting either is a
206
+ schema error, so an unattended caller cannot fall through to a charge: nothing
207
+ is even quoted.
208
+
209
+ `expected_total_charged` is the VAT-inclusive `total_charged` you read from
210
+ `get_restore_status` and showed the user, passed back **unchanged**. Do not
211
+ re-read it just before the call: it is meant to be the figure the customer
212
+ agreed to, and a freshly fetched number would agree with whatever the price has
213
+ become and defeat the check entirely. If the price has moved, the restore is
214
+ refused as `restoreQuoteChanged` with the current total and nothing is charged;
215
+ disclose the new figure, get approval again, and retry.
216
+
217
+ ## Browsing inside a backup
218
+
219
+ Looking inside a backup is free and completely separate from paying to restore
220
+ one. `list_restore_file_points`, `browse_restore_files` and
221
+ `get_restore_file_browse` only read a backup's directory listing: they never
222
+ charge the account, never overwrite the disk, and never put a file back on the
223
+ server. Initially supported on Firecracker VPS.
224
+
225
+ Browsing is asynchronous. `browse_restore_files` returns a browse id in a
226
+ pending state; poll `get_restore_file_browse` until `state` is `succeeded`.
227
+ Entries exist only in that state — a `failed` browse carries an `errorCode` and
228
+ no listing, and must not be presented as an empty directory.
229
+
230
+ Directories can hold an enormous number of files, so the server selects pages
231
+ of 200 or 1,000 entries according to the worker capability. When
232
+ `result.nextOffset` is non-null, call again with the same `sourceBrowseId` and
233
+ `directoryEntryId` and set `offset` to that cursor. Use `result.pageSize`
234
+ rather than assuming 200 when moving backwards. Subdirectories are entered
235
+ with the opaque `id` of a
236
+ `type: "directory"` entry; filesystem paths are never accepted. Entry types are
237
+ `file`, `directory`, `symlink` and `unsupported`.
238
+
239
+ Folder search (the `filter` argument) matches entry **names** in the one
240
+ directory being listed — case-insensitive substring, never a path, never
241
+ recursive. It depends on a worker capability that older nodes do not report, so
242
+ `list_restore_file_points` returns `searchAvailable`. `browse_restore_files`
243
+ checks that flag before sending a filter and **fails with
244
+ `serviceFileBrowseSearchUnavailable` when search is unsupported**, rather than
245
+ quietly returning an unfiltered listing that would be mistaken for search
246
+ results. Plain browsing keeps working on those nodes.
247
+
248
+ Restoring selected files back onto the server is a paid operation and is
249
+ deliberately **not** exposed here; use the VPSnet panel for it.
250
+
34
251
  ## SSH access workflow
35
252
 
36
253
  This MCP server manages your VPS infrastructure through the VPSnet.com API, including SSH key provisioning. Once an SSH key is deployed to a VPS, the AI assistant can connect directly using its environment's terminal (e.g. Claude Code's Bash tool, Cline's terminal).
@@ -85,7 +302,8 @@ The standard config works across most MCP clients:
85
302
  "command": "npx",
86
303
  "args": ["-y", "vpsnet-mcp"],
87
304
  "env": {
88
- "VPSNET_API_KEY": "your_api_key_here"
305
+ "VPSNET_API_KEY": "your_api_key_here",
306
+ "VPSNET_API_TIMEOUT_MS": "45000"
89
307
  }
90
308
  }
91
309
  }
@@ -103,6 +321,7 @@ Set the environment variable before running:
103
321
 
104
322
  ```bash
105
323
  export VPSNET_API_KEY="your_api_key_here"
324
+ export VPSNET_API_TIMEOUT_MS="45000"
106
325
  ```
107
326
 
108
327
  </details>
@@ -198,7 +417,7 @@ args = ["-y", "vpsnet-mcp"]
198
417
  VPSNET_API_KEY = "your_api_key_here"
199
418
  ```
200
419
 
201
- **If your system's default Node.js is older than 18** (common with nvm — check with `node --version`), wrap the command so nvm loads the right version:
420
+ **If your system's default Node.js is older than 20** (common with nvm — check with `node --version`), wrap the command so nvm loads the right version:
202
421
 
203
422
  ```bash
204
423
  codex mcp add vpsnet --env VPSNET_API_KEY=your_api_key_here -- bash -lc 'source ~/.nvm/nvm.sh >/dev/null 2>&1 && nvm use --silent 20 && npx -y vpsnet-mcp'
@@ -287,7 +506,14 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
287
506
  | Variable | Required | Description |
288
507
  |----------|----------|-------------|
289
508
  | `VPSNET_API_KEY` | Yes | Your VPSnet.com API key |
290
- | `VPSNET_API_URL` | No | API base URL (defaults to `https://api.vpsnet.com`) |
509
+ | `VPSNET_API_URL` | No | API base URL (defaults to `https://api.vpsnet.com`); any `https://*.vpsnet.com` host, e.g. a staging API |
510
+ | `VPSNET_API_TIMEOUT_MS` | No | Per-request timeout (default 45000) |
511
+
512
+ Requests go out from the machine that runs this server, not from your browser. A
513
+ host that admits only listed addresses (a staging API does) answers such a
514
+ request with an HTML `403` page from its web server; the tool result then says
515
+ so (`non_api_response: true`, `http_status: 403`) instead of passing the page on.
516
+ Every error result carries `http_status`; a `429` also carries `retry_after`.
291
517
 
292
518
  ## Tools
293
519
 
@@ -302,24 +528,64 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
302
528
  |------|-------------|
303
529
  | `list_services` | List all active VPS services |
304
530
  | `get_service` | Get detailed info for a service |
305
- | `get_service_graphs` | Get performance graphs (CPU, RAM, disk, network) |
531
+ | `get_service_graphs` | Get one graph series: metric (cpu, ram, ssd, net, io, …) and period (5m … 1y) |
532
+ | `get_event` | Read an async action's state by its `event` id or `noty` UUID |
533
+ | `wait_for_event` | Poll an async action until completed or error (or a timeout) |
306
534
  | `get_service_history` | Get action history for a service |
307
535
 
536
+ ### Managed Applications
537
+ | Tool | Description |
538
+ |------|-------------|
539
+ | `list_application_catalog` | List published applications compatible with a service |
540
+ | `list_service_applications` | List installed applications and pending checkout selection |
541
+ | `get_application_installation` | Get observed state, health, drift, endpoints, components, resource history, and thresholds |
542
+ | `get_application_events` | Get bounded customer-safe installation events |
543
+ | `get_application_health` | Run and poll a fresh container-health inspection |
544
+ | `get_application_logs` | Run and poll a size-bounded recent-log inspection |
545
+ | `list_application_restore_points` | List eligible nightly points for the exact application revision |
546
+ | `quote_application_data_restore` | Freeze the exact selective-restore balance charge without payment |
547
+ | `restore_application_data` | Pay and queue confirmed selective replacement of declared application data |
548
+ | `get_application_data_restore` | Poll one tenant-bound selective data restore |
549
+ | `list_application_registry_credentials` | List non-secret private registry credential metadata |
550
+ | `validate_application_recipe` | Validate customer Compose against the target worker policy |
551
+ | `list_application_recipes` | List customer-owned immutable recipe projects |
552
+ | `list_application_recipe_revisions` | List immutable revisions for a customer recipe |
553
+ | `create_application_recipe` | Validate and save a new customer recipe without installing it |
554
+ | `create_application_recipe_revision` | Validate and save a later immutable customer recipe revision |
555
+ | `export_application_recipe` | Export only a customer-owned recipe without secret values |
556
+ | `install_application_recipe` | Install an exact validated customer recipe revision |
557
+ | `discover_service_containers` | Discover bounded read-only container metadata |
558
+ | `prepare_application_compose_adoption` | Prepare and poll a scrubbed candidate for one discovered Compose project |
559
+ | `get_application_compose_adoption` | Poll one tenant-bound Compose adoption candidate |
560
+ | `confirm_application_compose_adoption` | Confirm the exact source takeover after explicit approval |
561
+ | `install_application` | Queue a confirmed, version-pinned managed installation |
562
+ | `configure_application_access` | Queue a confirmed platform-hostname, private, public-IP, managed-HTTPS, or customer-managed external-HTTPS access change |
563
+ | `configure_application_resource_thresholds` | Replace confirmed non-enforcing application resource thresholds and reached/recovered email preference |
564
+ | `manage_application` | Queue a confirmed lifecycle action, including an eligible immutable update; uninstall also requires explicit data-loss acknowledgement |
565
+ | `cancel_application_action` | Cancel the exact latest queued action only while the backend advertises it as cancellable |
566
+
308
567
  ### Service Actions
309
568
  | Tool | Description |
310
569
  |------|-------------|
311
570
  | `start_service` | Start a stopped VPS |
312
571
  | `stop_service` | Stop a running VPS |
313
572
  | `restart_service` | Restart a VPS |
573
+ | `console_service` | Request an out-of-band console session for a running VPS |
574
+ | `suspend_service` | Suspend a running Cloud VPS |
575
+ | `resume_service` | Resume a suspended Cloud VPS |
314
576
 
315
577
  ### Service Settings
316
578
  | Tool | Description |
317
579
  |------|-------------|
580
+ | `get_hostname` | Get current and automatic service hostname state |
318
581
  | `change_hostname` | Change VPS hostname |
582
+ | `reset_hostname` | Restore the VPSnet-managed automatic hostname |
319
583
  | `change_root_password` | Change VPS root password |
320
584
  | `get_rdns` | Get current rDNS records |
321
585
  | `change_rdns` | Change reverse DNS (PTR) record |
586
+ | `clear_rdns` | Clear a PTR override and restore the automatic value |
322
587
  | `flush_iptables` | Flush iptables rules (useful when locked out) |
588
+ | `get_title` | Get the current service display title |
323
589
  | `change_title` | Change service display title |
324
590
  | `toggle_ipv6` | Enable or disable IPv6 |
325
591
  | `toggle_extra_settings` | Toggle ppp, fuse, tuntap, or nfs |
@@ -334,9 +600,9 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
334
600
  ### Plan Changes (free)
335
601
  | Tool | Description |
336
602
  |------|-------------|
337
- | `get_plan_options` | Get available plans for upgrade/downgrade |
603
+ | `get_plan_options` | Get available plans for upgrade/downgrade; KVM/Firecracker targets that would shrink disk are unavailable |
338
604
  | `get_plan_resources` | Get configurable resources for a plan |
339
- | `calculate_plan_change` | Preview plan change cost and new expiry |
605
+ | `calculate_plan_change` | Preview a plan change: no payment, the remaining value is converted, so an upgrade moves the expiry earlier |
340
606
  | `change_plan` | Change VPS plan |
341
607
 
342
608
  ### Renewal & Billing
@@ -348,11 +614,12 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
348
614
  | `list_invoices` | List invoices |
349
615
  | `get_invoice` | Get a specific invoice |
350
616
  | `list_payments` | List payment history |
617
+ | `get_usage_statements` | List itemized metered-usage statements separately from invoices |
351
618
 
352
619
  ### Ordering
353
620
  | Tool | Description |
354
621
  |------|-------------|
355
- | `get_order_plans` | Get available plans for new VPS |
622
+ | `get_order_plans` | Get available plans for an explicitly selected service product |
356
623
  | `get_order_options` | Get configurable options for a plan |
357
624
  | `order_service` | Order a new VPS |
358
625
 
@@ -363,6 +630,16 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
363
630
  | `get_backup_history` | Get backup history |
364
631
  | `create_backup` | Create a new backup (paid) |
365
632
 
633
+ ### Restore
634
+ | Tool | Description |
635
+ |------|-------------|
636
+ | `get_restore_status` | Get retention, restore price, and any restore in progress |
637
+ | `list_restore_points` | List whole-service restore points |
638
+ | `request_restore` | **Paid and destructive:** restore the whole service disk from a point |
639
+ | `list_restore_file_points` | List browsable backup points and whether folder search is available (free) |
640
+ | `browse_restore_files` | Queue a listing of one directory inside a backup (free, read-only) |
641
+ | `get_restore_file_browse` | Poll a queued backup directory listing (free, read-only) |
642
+
366
643
  ### SSH Keys
367
644
  | Tool | Description |
368
645
  |------|-------------|
@@ -374,10 +651,188 @@ Follow the [Windsurf MCP documentation](https://docs.windsurf.com/windsurf/mcp).
374
651
  ### API Keys
375
652
  | Tool | Description |
376
653
  |------|-------------|
377
- | `list_api_keys` | List all API keys |
378
- | `create_api_key` | Create a new API key |
379
- | `update_api_key` | Update an existing API key |
380
- | `revoke_api_key` | Revoke (delete) an API key |
654
+ | `list_api_keys` | Show the API key authenticating this MCP connection |
655
+ | `get_api_key` | Get one active key's non-secret metadata |
656
+ | `get_api_key_activity` | Get the calling key's bounded retained request activity and recorded totals |
657
+ | `get_api_key_inference_usage` | Get the calling inference key's exact paid VPSnet AI usage and cap state |
658
+
659
+ API-key creation, changes, and revocation require a browser/session login. They
660
+ cannot be performed by an MCP connection authenticated with an API key.
661
+
662
+ ### Free TLS certificates
663
+ | Tool | Description |
664
+ |------|-------------|
665
+ | `get_free_certificate_eligibility` | Check account eligibility, quota, key modes, and currently ready public CAs |
666
+ | `preflight_free_certificate` | Plan exact names, validation, delivery, custody, and CA without issuing |
667
+ | `list_free_certificates` | List owned no-cost certificate requests and lifecycle state |
668
+ | `get_free_certificate` | Get one owned request, renewal schedule, and safe timeline |
669
+ | `get_free_certificate_instruction` | Read automatic-DNS status or every required external-DNS CNAME |
670
+ | `create_free_certificate` | Create one explicitly approved, idempotent no-cost DV request |
671
+ | `download_free_certificate` | Retrieve only the issued public leaf and chain, never a private key |
672
+ | `manage_free_certificate` | Renew, revoke, recheck, or cancel an eligible request |
673
+
674
+ For portable API or assistant installation, use `customer_csr` and retain the
675
+ private key where the CSR was generated. A managed request can renew unattended,
676
+ but MCP cannot export its private key. Issuance is asynchronous and quota-bound:
677
+ poll `get_free_certificate`, follow `get_free_certificate_instruction`, and do
678
+ not treat a queued request as issued.
679
+
680
+ ### Automatic SSL subscriptions
681
+ | Tool | Description |
682
+ |------|-------------|
683
+ | `list_automatic_ssl_subscriptions` | List customer-owned Automatic SSL subscriptions without exposing ACME credentials |
684
+ | `get_automatic_ssl_subscription` | Get one owned subscription, its domain set, renewal state, and readiness |
685
+ | `quote_automatic_ssl_subscription` | Quote an exact domain set in EUR without charging |
686
+ | `order_automatic_ssl_subscription` | Confirm and pay for the explicitly approved subscription quote |
687
+ | `list_automatic_ssl_actions` | List customer-visible subscription and DNS-name changes |
688
+ | `refresh_automatic_ssl_subscription` | Schedule an authoritative read-only status refresh |
689
+ | `quote_automatic_ssl_domain` | Quote one additional DNS name in EUR without charging |
690
+ | `order_automatic_ssl_domain` | Confirm and pay for the explicitly approved DNS-name quote |
691
+ | `quote_automatic_ssl_renewal` | Quote the next eligible subscription term in EUR |
692
+ | `order_automatic_ssl_renewal` | Prepay the explicitly approved next term from account balance |
693
+ | `manage_automatic_ssl_subscription` | Cancel, remove a name, or correct an eligible name idempotently |
694
+
695
+ Automatic SSL is a portable paid ACME subscription. It works with a compatible
696
+ client on VPSnet or another provider; it is not limited to managed
697
+ applications. The private ACME server URL and EAB credentials are revealed only
698
+ in the two-factor-protected customer portal. They are intentionally not an MCP
699
+ tool or API-key response, so an assistant cannot copy them into model context.
700
+
701
+ ### Paid TLS certificates
702
+ | Tool | Description |
703
+ |------|-------------|
704
+ | `list_certificate_catalog` | List published DV/OV/EV products and final customer offers in EUR |
705
+ | `get_certificate_catalog_product` | Get one published product, its capabilities, and current offers |
706
+ | `list_certificates` | List customer-owned paid certificate orders and issuance state |
707
+ | `get_certificate` | Get one owned paid certificate order |
708
+ | `quote_certificate` | Quote an exact certificate or renewal without charging |
709
+ | `order_certificate` | Confirm and pay for an explicitly approved certificate quote |
710
+ | `get_certificate_validation` | Read per-name validation state and an owner-visible pending challenge |
711
+ | `download_certificate` | Download the issued public leaf and chain; private keys are never returned |
712
+ | `list_certificate_actions` | List durable customer-visible management actions |
713
+ | `refresh_certificate` | Schedule a read-only certificate-authority status reconciliation |
714
+ | `manage_certificate` | Queue an idempotent cancellation, validation, or same-name reissue action |
715
+
716
+ Paid certificates are portable account products: customers may install them on
717
+ Nginx, Apache, lighttpd, OpenLiteSpeed, HAProxy, Caddy, mail, API, load-balancer,
718
+ or other TLS endpoints. They are separate from automatic HTTPS attached to a
719
+ VPSnet-managed application. The MCP accepts only a public PKCS#10 CSR; the
720
+ private key must remain under customer control and must never enter a tool
721
+ argument or model context. Quote responses contain the final customer price in
722
+ EUR, and ordering requires explicit approval plus the same idempotency key and
723
+ short-lived quote token.
724
+
725
+ ### Domains
726
+ | Tool | Description |
727
+ |------|-------------|
728
+ | `list_domains` | List domains owned by the account |
729
+ | `get_domain` | Get one owned domain and its pending action |
730
+ | `list_domain_tlds` | List TLDs currently enabled for ordering |
731
+ | `check_domain_availability` | Check domain availability without ordering |
732
+ | `get_domain_ordering_status` | Get non-secret domain-ordering readiness |
733
+ | `set_domain_nameservers` | Queue a nameserver change for an owned domain |
734
+ | `list_domain_glue_records` | List same-domain nameserver address records |
735
+ | `create_domain_glue_record` | Queue creation or update of a nameserver address record |
736
+ | `delete_domain_glue_record` | Queue deletion of a nameserver address record |
737
+ | `get_domain_parent_ds` | List parent-zone DNSSEC DS records |
738
+ | `add_domain_parent_ds` | Queue addition of parent-zone DS records |
739
+ | `delete_domain_parent_ds` | Queue deletion of parent-zone DS records |
740
+ | `list_domain_contacts` | List domain contacts owned by the account |
741
+ | `create_domain_contact` | Create a domain contact |
742
+ | `update_domain_contact` | Update an existing domain contact |
743
+ | `delete_domain_contact` | Delete an unused domain contact |
744
+ | `quote_domain_register` | Quote a domain registration without charging |
745
+ | `confirm_domain_register` | Confirm and pay for an exact registration quote |
746
+ | `quote_domain_transfer` | Quote a domain transfer without charging |
747
+ | `confirm_domain_transfer` | Confirm and pay for an exact transfer quote |
748
+ | `quote_domain_renew` | Quote renewal of an owned domain without charging |
749
+ | `confirm_domain_renew` | Confirm and pay for an exact renewal quote |
750
+ | `quote_domain_restore` | Quote restoration of a domain in redemption without charging |
751
+ | `confirm_domain_restore` | Confirm and pay for an exact restoration quote |
752
+ | `set_domain_auto_renew` | Enable or disable automatic renewal for an owned domain |
753
+ | `get_registrar_lock` | Get registrar transfer-lock state; changes remain panel-only |
754
+
755
+ ### DNS
756
+ | Tool | Description |
757
+ |------|-------------|
758
+ | `list_service_dns_options` | List owned zones and service addresses available for DNS attachment |
759
+ | `attach_service_dns_record` | Point an owned-zone name at one service address |
760
+ | `list_dns_zones` | List forward DNS zones owned by the account |
761
+ | `create_dns_zone` | Create a native or secondary forward DNS zone |
762
+ | `get_dns_zone` | Get one DNS zone and its desired records |
763
+ | `get_dns_zone_diagnostics` | Inspect delegation, SOA, DNSSEC, and record hygiene |
764
+ | `export_dns_zone` | Export a native zone as a BIND-style zone file |
765
+ | `import_dns_zone` | Import bounded BIND-style records into a native zone |
766
+ | `list_dns_templates` | List backend-defined DNS record templates |
767
+ | `apply_dns_template` | Preview or apply one DNS record template |
768
+ | `delete_dns_zone` | Delete a forward DNS zone |
769
+ | `verify_dns_zone` | Verify ownership (TXT publicly or at the previous provider) and publish a pending zone |
770
+ | `reissue_dns_zone_verification` | Replace a lost ownership TXT value for a pending zone |
771
+ | `get_dnssec` | Get DNSSEC state and public DNSKEY/DS material |
772
+ | `set_dnssec` | Enable or safely disable DNSSEC signing |
773
+ | `upsert_dns_record` | Create or replace a forward DNS desired-state record |
774
+ | `update_dns_record` | Update one existing non-system DNS record |
775
+ | `delete_dns_record` | Delete one forward DNS desired-state record |
776
+ | `get_dns_service_status` | Get managed DNS cluster status and published endpoints |
777
+ | `get_dns_zone_history` | Get recent zone and record change history |
778
+ | `list_ddns_tokens` | List non-secret DDNS and ACME token metadata |
779
+ | `create_ddns_token` | Create a narrow DDNS or ACME updater token |
780
+ | `revoke_ddns_token` | Revoke a DDNS or ACME updater token |
781
+
782
+ ### Snapshots
783
+ | Tool | Description |
784
+ |------|-------------|
785
+ | `list_snapshots` | List Cloud VPS disk snapshots and billing policy |
786
+ | `create_snapshot` | Create a Cloud VPS disk snapshot |
787
+ | `rollback_snapshot` | Destructively roll a Cloud VPS back to a snapshot |
788
+ | `delete_snapshot` | Delete a Cloud VPS disk snapshot and stop its keep billing |
789
+ | `list_firecracker_snapshots` | List temporary Firecracker VPS snapshots and expiry |
790
+ | `create_firecracker_snapshot` | Create a temporary Firecracker VPS snapshot |
791
+ | `rollback_firecracker_snapshot` | Destructively roll a Firecracker VPS back to a snapshot |
792
+ | `delete_firecracker_snapshot` | Delete a Firecracker VPS snapshot and stop its keep billing |
793
+
794
+ ### Service Rescue
795
+ | Tool | Description |
796
+ |------|-------------|
797
+ | `get_service_rescue` | Get rescue capability and current durable rescue session |
798
+ | `enter_service_rescue` | Restart an eligible service into an advertised rescue image |
799
+ | `exit_service_rescue` | Restore the exact pre-rescue boot configuration and state |
800
+
801
+ ### Firecracker Functions
802
+ | Tool | Description |
803
+ |------|-------------|
804
+ | `list_functions` | List usage-billed Firecracker Functions |
805
+ | `get_function` | Get one function, including integrity state and protected values when readable |
806
+ | `create_function` | Create a Firecracker Function |
807
+ | `update_function` | Update a function; unreadable protected values require explicit replacement approval |
808
+ | `delete_function` | Delete a Firecracker Function |
809
+ | `invoke_function` | Invoke a function with metered CPU and memory usage; one stable Idempotency-Key prevents exact retries from running or billing twice |
810
+ | `list_function_invocations` | List a function's invocations, status, duration, and cost |
811
+ | `get_function_invocation` | Get one invocation's output, logs, and usage cost |
812
+
813
+ ### On-demand servers
814
+ | Tool | Description |
815
+ |------|-------------|
816
+ | `get_temp_vm_options` | Get launch state, profiles, compatibility pricing inputs, and exact storage/network policy |
817
+ | `quote_temp_vm` | Inspect the disabled quote operation and its coming-soon response |
818
+ | `list_temp_vms` | List the account's on-demand server sessions and current options |
819
+ | `create_temp_vm` | Inspect the disabled create operation; no payment or allocation occurs while the product is coming soon |
820
+ | `get_temp_vm` | Get one tenant-owned on-demand server session |
821
+ | `delete_temp_vm` | Permanently delete an on-demand server after explicit data-loss acknowledgement; no customer refund is initiated |
822
+
823
+ Customer ordering is disabled while the on-demand server lifecycle is being
824
+ validated. Current options disclose that automatic backups and snapshots are
825
+ not included and outbound connections to mail-delivery TCP ports 25, 2525,
826
+ 465, and 587 are restricted. Existing internal test sessions remain available
827
+ through list/get/delete for cleanup. Fixed-TTL and prepaid fields in the
828
+ disabled compatibility schema are not a launch promise; the flexible duration
829
+ and metered-billing contract must be published consistently before ordering is
830
+ enabled.
831
+
832
+ ### Guest Agent
833
+ | Tool | Description |
834
+ |------|-------------|
835
+ | `get_guest_agent_status` | Check QEMU guest-agent availability on a Cloud VPS |
381
836
 
382
837
  ### History
383
838
  | Tool | Description |
@@ -438,7 +893,19 @@ For Claude Code extension, environment variables **must** be in the `env` object
438
893
 
439
894
  ### API key errors
440
895
 
441
- - Verify the key is correct (starts with `vpsnet_`)
896
+ This server needs a **management** API key. Every failure below is reported by
897
+ the tools with an `auth_problem` object containing the cause and the fix, so
898
+ read that rather than guessing from the HTTP status.
899
+
900
+ | What you see | What it means | Fix |
901
+ |---|---|---|
902
+ | `aiScopedApiKeyCannotManageAccount` (403) | The key is an **AI-scoped key**. Those are issued only for VPSnet AI assistant inference and are deliberately refused on the entire account API. Granting scopes cannot change this — the restriction is on the key type. | Create a separate key with scope `full` (or `read` for GET-only use) and use that here. Keep the AI-scoped key for inference. |
903
+ | `apiKeyRejected` (401) | The key failed authentication outright. The API returns one identical 401 for every cause, so it is one of: unknown, revoked, expired, malformed, or your source IP is not on the key's IP allowlist. | Check the key is active and copied whole, and that any IP allowlist includes the address this server calls from. |
904
+ | `readOnlyApiKeyCannotWrite` (401) | A read-scoped key was used for a write; read keys are limited to GET. | Use a full-scope key, or stay on read-only tools. |
905
+ | `apiKeyScopeMissing` (403) | The key authenticated but lacks the granular scope named in `requiredScope`. | Add that scope in Account > API Keys. |
906
+ | `apiKeyForbidden` (403) | The endpoint refuses API keys entirely. API keys never grant admin access. | Use the panel with a signed-in session. |
907
+
908
+ - Verify the key is correct (starts with `vpsnet_` followed by 43 characters)
442
909
  - Keys are shown only once at creation — if lost, create a new one
443
910
  - Check that the key hasn't expired (Account > API Keys)
444
911
 
@@ -449,9 +916,9 @@ For Claude Code extension, environment variables **must** be in the `env` object
449
916
 
450
917
  ### `fetch is not defined` or unexpected errors
451
918
 
452
- This server requires **Node.js 18+** (uses the built-in `fetch` API). If your default `node` is older (common with nvm setups), either:
919
+ This server requires **Node.js 20+**. If your default `node` is older (common with nvm setups), either:
453
920
 
454
- - Set Node 18+ as default: `nvm alias default 20`
921
+ - Set Node 20+ as default: `nvm alias default 20`
455
922
  - Or use the nvm wrapper shown in the [Codex](#codex) section
456
923
 
457
924
  ## License