vpsnet-mcp 2.3.8 → 2.3.10

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
@@ -626,12 +626,14 @@ everything else.
626
626
  | `get_application_events` | Get bounded customer-safe installation events | `applications:read` | free |
627
627
  | `get_application_health` | Run and poll a fresh container-health inspection | `applications:read` | free |
628
628
  | `get_application_logs` | Run and poll a size-bounded recent-log inspection | `applications:read` | free |
629
+ | `get_application_inspection` | Poll the exact persisted health or logs inspection returned by get_application_health or get_application_logs when it remains pending. | `applications:read` | free |
629
630
  | `list_application_restore_points` | List eligible nightly points for the exact application revision | `applications:manage` | Needs paid scope: `applications:restore` |
630
631
  | `quote_application_data_restore` | Freeze the exact selective-restore balance charge without payment | `applications:manage` | Quote: `applications:restore` |
631
632
  | `restore_application_data` | Pay and queue confirmed selective replacement of declared application data | `applications:manage` | Paid: `applications:restore` |
632
633
  | `get_application_data_restore` | Poll one tenant-bound selective data restore | `applications:read` | free |
633
634
  | `list_application_registry_credentials` | List non-secret private registry credential metadata | `applications:read` | free |
634
635
  | `validate_application_recipe` | Validate customer Compose against the target worker policy | `applications:manage` | free |
636
+ | `get_application_recipe_validation` | Poll the exact persisted customer recipe validation returned by validate_application_recipe or a pending recipe creation/revision. | `applications:read` | free |
635
637
  | `list_application_recipes` | List customer-owned immutable recipe projects | `applications:read` | free |
636
638
  | `list_application_recipe_revisions` | List immutable revisions for a customer recipe | `applications:read` | free |
637
639
  | `create_application_recipe` | Validate and save a new customer recipe without installing it | `applications:manage` | free |
@@ -639,6 +641,7 @@ everything else.
639
641
  | `export_application_recipe` | Export only a customer-owned recipe without secret values | `applications:read` | free |
640
642
  | `install_application_recipe` | Install an exact validated customer recipe revision | `applications:manage` | free |
641
643
  | `discover_service_containers` | Discover bounded read-only container metadata | `applications:read` | free |
644
+ | `get_service_container_discovery` | Poll the exact persisted service container discovery returned by discover_service_containers when it remains pending. | `applications:read` | free |
642
645
  | `prepare_application_compose_adoption` | Prepare and poll a scrubbed candidate for one discovered Compose project | `applications:manage` | free |
643
646
  | `get_application_compose_adoption` | Poll one tenant-bound Compose adoption candidate | `applications:read` | free |
644
647
  | `confirm_application_compose_adoption` | Confirm the exact source takeover after explicit approval | `applications:manage` | free |
@@ -653,6 +656,7 @@ everything else.
653
656
  | `stop_application` | Stop an application after confirming interruption | `applications:manage` | free |
654
657
  | `uninstall_application` | Delete an application after explicit data-loss approval | `applications:manage` | free |
655
658
  | `update_application` | Apply the eligible immutable update with exact version preconditions | `applications:manage` | free |
659
+ | `rollback_application` | Queue the exact reverse transition advertised as type=rollback by get_application_installation. | `applications:manage` | free |
656
660
  | `cancel_application_action` | Cancel the exact latest queued action only while the backend advertises it as cancellable | `applications:manage` | free |
657
661
 
658
662
  ### Service Actions
@@ -669,8 +673,10 @@ everything else.
669
673
  | Tool | Description | Scope | Paid |
670
674
  |------|-------------|-------|------|
671
675
  | `get_hostname` | Get current and automatic service hostname state | `services:read` | free |
676
+ | `get_guest_nameservers` | Get the server's saved guest DNS resolver configuration: nsData.type is own (VPSnet defaults) or custom, with ns1-ns4 resolver IP addresses. | `services:read` | free |
672
677
  | `change_hostname` | Change VPS hostname | `services:manage` | free |
673
678
  | `reset_hostname` | Restore the VPSnet-managed automatic hostname | `services:manage` | free |
679
+ | `set_guest_nameservers` | Change DNS resolvers inside a supported Linux server. | `services:manage` | free |
674
680
  | `change_root_password` | Change VPS root password | `services:manage` | free |
675
681
  | `get_rdns` | Get current rDNS records | `services:read` | free |
676
682
  | `change_rdns` | Change reverse DNS (PTR) record | `services:manage` | free |
@@ -712,14 +718,16 @@ everything else.
712
718
  |------|-------------|-------|------|
713
719
  | `get_order_plans` | Get available plans for an explicitly selected service product | none | free |
714
720
  | `get_order_options` | Get configurable options for a plan | none | free |
715
- | `order_service` | Order a new VPS (optionally attached to one of your private networks with `privateNetworkId`) | none | Paid: `vps:order`, `vds:order`, `ds:order` or `fc:order` (by product) |
721
+ | `order_service` | Quote a new VPS, then confirm the exact total and period after customer approval; optionally attach a private network with `privateNetworkId` | none | Paid: `vps:order`, `vds:order`, `ds:order` or `fc:order` (by product) |
716
722
 
717
723
  ### Backups
718
724
  | Tool | Description | Scope | Paid |
719
725
  |------|-------------|-------|------|
720
726
  | `get_backup_status` | Get backup status and configuration | `services:read` | free |
727
+ | `get_firecracker_backup_status` | Get nightly off-node backup status for a Firecracker VPS, including running count and the latest retained backup's consistency provenance. | `services:read` | free |
721
728
  | `get_backup_history` | Get backup history | `services:read` | free |
722
- | `create_backup` | Create a new backup (paid) | `services:manage` | Paid |
729
+ | `get_firecracker_backup_history` | Get retained nightly Firecracker VPS backup history, including failed/running attempts and consistency provenance. | `services:read` | free |
730
+ | `create_backup` | Retrieve historical Container VPS backup content with explicit payment consent and a stable request key | `services:manage` | Paid |
723
731
 
724
732
  ### Restore
725
733
  | Tool | Description | Scope | Paid |
@@ -861,20 +869,21 @@ short-lived quote token.
861
869
  | `list_service_dns_options` | List owned zones and service addresses available for DNS attachment | `dns:read` | free |
862
870
  | `attach_service_dns_record` | Point an owned-zone name at one service address | `dns:write` | free |
863
871
  | `list_dns_zones` | List forward DNS zones owned by the account | `dns:read` | free |
864
- | `create_dns_zone` | Create a native or secondary forward DNS zone | `dns:write` | free |
865
- | `get_dns_zone` | Get one DNS zone and its desired records | `dns:read` | free |
872
+ | `create_dns_zone` | Create a native or secondary zone awaiting ownership TXT verification | `dns:write` | free |
873
+ | `get_dns_zone` | Get desired records with IDs and a recoverable ownership TXT value | `dns:read` | free |
874
+ | `reapply_dns_zone` | Retry publication of a published DNS zone whose apply_state is failed. | `dns:write` | free |
866
875
  | `get_dns_zone_diagnostics` | Inspect delegation, SOA, DNSSEC, and record hygiene | `dns:read` | free |
867
876
  | `export_dns_zone` | Export a native zone as a BIND-style zone file | `dns:read` | free |
868
877
  | `import_dns_zone` | Import bounded BIND-style records into a native zone | `dns:write` | free |
869
878
  | `list_dns_templates` | List backend-defined DNS record templates | `dns:read` | free |
870
879
  | `apply_dns_template` | Preview or apply one DNS record template | `dns:write` | free |
871
880
  | `delete_dns_zone` | Delete a forward DNS zone | `dns:write` | free |
872
- | `verify_dns_zone` | Verify ownership (TXT publicly or at the previous provider) and publish a pending zone | `dns:write` | free |
873
- | `reissue_dns_zone_verification` | Replace a lost ownership TXT value for a pending zone | `dns:write` | free |
881
+ | `verify_dns_zone` | Verify ownership and publish a pending or verification-expired zone | `dns:write` | free |
882
+ | `reissue_dns_zone_verification` | Rotate ownership TXT for a pending or verification-expired zone after checking its recoverable value | `dns:write` | free |
874
883
  | `get_dnssec` | Get DNSSEC state and public DNSKEY/DS material | `dns:read` | free |
875
884
  | `set_dnssec` | Enable or safely disable DNSSEC signing | `dnssec:manage` | free |
876
- | `upsert_dns_record` | Create or replace a forward DNS desired-state record | `dns:write` | free |
877
- | `update_dns_record` | Update one existing non-system DNS record | `dns:write` | free |
885
+ | `upsert_dns_record` | Add a name/type/content tuple; an identical tuple updates TTL/comment and re-enables the record | `dns:write` | free |
886
+ | `update_dns_record` | Replace one existing non-system DNS record's content by exact record ID | `dns:write` | free |
878
887
  | `delete_dns_record` | Delete one forward DNS desired-state record | `dns:write` | free |
879
888
  | `get_dns_service_status` | Get managed DNS cluster status and published endpoints | `dns:read` | free |
880
889
  | `get_dns_zone_history` | Get recent zone and record change history | `dns:read` | free |
@@ -905,6 +914,7 @@ short-lived quote token.
905
914
  | Tool | Description | Scope | Paid |
906
915
  |------|-------------|-------|------|
907
916
  | `list_functions` | List usage-billed Firecracker Functions | `services:read` | free |
917
+ | `list_function_history` | Read paginated account-wide Firecracker Function invocation history. | `services:read` | free |
908
918
  | `get_function` | Get one function, including integrity state and protected values when readable | `services:read` | free |
909
919
  | `create_function` | Create a Firecracker Function | `services:manage` | free |
910
920
  | `update_function` | Update a function; unreadable protected values require explicit replacement approval | `services:manage` | free |
@@ -1106,10 +1116,13 @@ Each example is a request to your assistant and the tools it calls.
1106
1116
  (OS, period, resource IDs) and `list_ssh_keys` for the key ID.
1107
1117
  2. `order_service` with `plan`, `os`, `period`, `resources`, `sshKey` (or
1108
1118
  `rootPassword`, not both), `payment: { payment: 1, successUrl: '', cancelUrl: '' }`
1109
- and a stable `idempotencyKey`. With an API key it first requests the server
1110
- quote and then confirms with the returned `quoteToken` in one call, so the key
1111
- needs `vps:order` (or `vds:order`, `ds:order`, `fc:order`) and spend caps.
1112
- 3. Poll `get_service` for the returned order number; payment accepted is not
1119
+ and a stable `idempotencyKey`. The first call returns a quote without charging.
1120
+ The API key needs `vps:order` (or `vds:order`, `ds:order`, `fc:order`) and spend caps.
1121
+ 3. Show the exact gross EUR total and billing period. After the customer's approval,
1122
+ repeat the unchanged order and key with the returned `quoteToken`,
1123
+ `expected_total_eur` and `acknowledge_charge: true`. Inspect the original attempt
1124
+ in the panel if its outcome is unknown; do not create another key to retry it.
1125
+ 4. Poll `get_service` for the returned order number; payment accepted is not
1113
1126
  server ready.
1114
1127
 
1115
1128
  ### Networking (quote, then order)
@@ -1129,13 +1142,25 @@ Each example is a request to your assistant and the tools it calls.
1129
1142
 
1130
1143
  > Point www.example.com at 203.0.113.10 with a 5 minute TTL.
1131
1144
 
1132
- 1. `list_dns_zones` to find the `zone_id` (needs `dns:read`).
1133
- 2. `upsert_dns_record` with `zone_id`, `name: "www"`, `type: "A"`,
1134
- `content: "203.0.113.10"`, `ttl: 300` (needs `dns:write`). It creates the
1135
- record or replaces the existing one.
1145
+ 1. `list_dns_zones` to find the `zone_id`, then `get_dns_zone` to inspect the
1146
+ existing records and their IDs (needs `dns:read`).
1147
+ 2. To add an A value, call `upsert_dns_record` with `zone_id`, `name: "www"`,
1148
+ `type: "A"`, `content: "203.0.113.10"`, `ttl: 300` (needs `dns:write`).
1149
+ Different content adds another record and keeps existing values. An identical
1150
+ name/type/content tuple updates its TTL/comment and re-enables it if disabled.
1151
+ To replace an existing value, use `update_dns_record` with its exact
1152
+ `record_id` and the desired name, type, content and TTL.
1136
1153
  3. `get_dns_zone` to read the desired records back, or `get_dns_zone_history` to
1137
1154
  see the change.
1138
1155
 
1156
+ For a waiting zone whose ownership TXT value was lost, first read
1157
+ `get_dns_zone.zone.verification.record.value`. Use
1158
+ `reissue_dns_zone_verification` only if that value is null/unrecoverable or the
1159
+ customer requests rotation. It supports both `pending_verification` and
1160
+ `verification_expired`; the previous value stops being accepted. Update the TXT
1161
+ at the location given by `zone.verification.next_step`, then call
1162
+ `verify_dns_zone`. Reissuing alone does not verify the zone or reset its status.
1163
+
1139
1164
  ### Order a paid certificate
1140
1165
 
1141
1166
  > Buy a one-year DV certificate for example.com; I generated the CSR myself.
@@ -27,8 +27,9 @@ export const applicationActionSchema = z
27
27
  "stop",
28
28
  "uninstall",
29
29
  "update",
30
+ "rollback",
30
31
  ])
31
- .describe("Supported lifecycle action. Update applies the backend-selected newer immutable release. Selective data restore is a separate revision-bound operation.");
32
+ .describe("Supported lifecycle action. Update and rollback apply the exact backend-advertised immutable release. Selective data restore is a separate revision-bound operation.");
32
33
  export const applicationActionIdSchema = z
33
34
  .string()
34
35
  .uuid()
@@ -37,7 +38,7 @@ export const applicationExpectedVersionSchema = z
37
38
  .string()
38
39
  .max(96)
39
40
  .regex(/^[\x21-\x7E]{1,96}$/)
40
- .describe("Exact version copied from the current advertised update capability; this is an execution precondition, not a caller-selected target");
41
+ .describe("Exact version copied from the advertised update or rollback capability; this is an execution precondition, not a caller-selected target");
41
42
  const externalHttpsUrlSchema = z.string().max(500).refine((value) => {
42
43
  const addressMatch = /^https:\/\/[^/?#]+(\/[^?#]*)?$/i.exec(value);
43
44
  if (value !== value.trim() ||
@@ -239,9 +240,9 @@ export function applicationInstallRequestBody(params) {
239
240
  };
240
241
  }
241
242
  export function applicationLifecycleRequestBody(action, acknowledgeDataLoss, expectedUpdate) {
242
- if (action === "update") {
243
+ if (action === "update" || action === "rollback") {
243
244
  if (!expectedUpdate?.blueprintVersion || !expectedUpdate.upstreamVersion) {
244
- throw new Error("An exact advertised update release is required.");
245
+ throw new Error(`An exact advertised ${action} release is required.`);
245
246
  }
246
247
  return {
247
248
  action,
@@ -459,6 +460,9 @@ export function safeApplicationDataRestorePointsPayload(status, data) {
459
460
  return {
460
461
  success: true,
461
462
  points,
463
+ incompatible_points: boundedInteger(payload.incompatiblePoints, Number.MAX_SAFE_INTEGER),
464
+ failed_captures: boundedInteger(payload.failedCaptures, Number.MAX_SAFE_INTEGER),
465
+ last_failed_capture_at: timestamp(payload.lastFailedCaptureAt),
462
466
  quote,
463
467
  active_restore: payload.activeRestore === null
464
468
  ? null
@@ -729,6 +729,7 @@ function safeAcmeSubscriptionRenewal(value) {
729
729
  const renewalAt = text(source.renewal_at, 64);
730
730
  const state = [
731
731
  "awaiting_payment",
732
+ "processing",
732
733
  "prepaid",
733
734
  "settled",
734
735
  "refund_pending",
@@ -781,6 +782,7 @@ function safeAcmeSubscriptionAction(value) {
781
782
  "awaiting_payment",
782
783
  "queued",
783
784
  "submitting",
785
+ "processing",
784
786
  "reconciling",
785
787
  "reconciliation_required",
786
788
  "succeeded",
@@ -1203,6 +1205,15 @@ function safeFreeTimelineEvent(value) {
1203
1205
  }
1204
1206
  return { event, actor: source.actor, created_at: createdAt };
1205
1207
  }
1208
+ // Mirrors FreeCertificateFailureCode::all(); never pass stored/internal CA prose.
1209
+ const freeCertificateFailureReasons = new Set([
1210
+ "dns_validation_failed", "rate_limited", "validation_unauthorized",
1211
+ "validation_record_mismatch", "caa_forbids_issuance", "hostname_rejected",
1212
+ "validation_connection_failed", "csr_rejected", "authority_unavailable",
1213
+ "authority_protocol_error", "request_malformed", "authority_account_problem",
1214
+ "dns_name_not_found", "dns_propagation_pending", "authority_credentials_changed",
1215
+ "issuance_failed",
1216
+ ]);
1206
1217
  function safeFreeRequest(value) {
1207
1218
  const source = record(value);
1208
1219
  const id = freeCertificateRequestIdSchema.safeParse(source.id);
@@ -1219,6 +1230,11 @@ function safeFreeRequest(value) {
1219
1230
  const authorityName = source.certificate_authority === null
1220
1231
  ? null
1221
1232
  : text(source.certificate_authority, 64);
1233
+ const failureReason = source.failure_reason == null
1234
+ ? null
1235
+ : typeof source.failure_reason === "string" && freeCertificateFailureReasons.has(source.failure_reason)
1236
+ ? source.failure_reason
1237
+ : "issuance_failed";
1222
1238
  const deliveryOrderId = nullableInteger(source.delivery_order_id);
1223
1239
  const timeline = source.timeline === undefined
1224
1240
  ? undefined
@@ -1271,6 +1287,8 @@ function safeFreeRequest(value) {
1271
1287
  not_before: timestamp(source.not_before),
1272
1288
  not_after: timestamp(source.not_after),
1273
1289
  renewal_due_at: timestamp(source.renewal_due_at),
1290
+ failure_reason: failureReason,
1291
+ failure_at: failureReason === null ? null : timestamp(source.failure_at),
1274
1292
  certificate_authority_id: authorityId !== null && authorityId.success ? authorityId.data : null,
1275
1293
  certificate_authority: authorityName,
1276
1294
  download_available: source.download_available,
@@ -262,6 +262,12 @@ export function safeCustomProjectInstallPayload(status, data, portalPath) {
262
262
  },
263
263
  };
264
264
  }
265
+ const CUSTOM_PROJECT_VALIDATION_ERROR_CODES = new Set([
266
+ "applicationCustomProjectValidationFailed",
267
+ "applicationCustomProjectValidationDispatchFailed",
268
+ "applicationCustomProjectValidationExpired",
269
+ "applicationCustomProjectValidationTimedOut",
270
+ ]);
265
271
  export function safeCustomProjectValidationPayload(status, data) {
266
272
  const payload = record(data);
267
273
  const validation = record(payload.validation);
@@ -273,7 +279,10 @@ export function safeCustomProjectValidationPayload(status, data) {
273
279
  };
274
280
  }
275
281
  const valid = validation.valid === true;
276
- const resolvedCompose = valid && typeof validation.resolved_compose_yaml === "string"
282
+ // Keep the caller's resolved definition while the authoritative worker is
283
+ // pending, so a later GET can complete this exact validation without a new POST.
284
+ const pending = validation.state === "queued" || validation.state === "awaiting_reply";
285
+ const resolvedCompose = (valid || pending) && typeof validation.resolved_compose_yaml === "string"
277
286
  ? validation.resolved_compose_yaml.slice(0, 262144)
278
287
  : null;
279
288
  const resolutions = valid && Array.isArray(validation.image_resolutions)
@@ -295,6 +304,12 @@ export function safeCustomProjectValidationPayload(status, data) {
295
304
  validation: {
296
305
  id: boundedString(validation.id, 64),
297
306
  state: boundedString(validation.state, 32),
307
+ compose_digest: typeof validation.compose_digest === "string"
308
+ && /^[a-f0-9]{64}$/.test(validation.compose_digest)
309
+ ? validation.compose_digest : null,
310
+ error_code: typeof validation.error_code === "string"
311
+ && CUSTOM_PROJECT_VALIDATION_ERROR_CODES.has(validation.error_code)
312
+ ? validation.error_code : null,
298
313
  valid: typeof validation.valid === "boolean" ? validation.valid : null,
299
314
  errors: Array.isArray(validation.errors)
300
315
  ? validation.errors