vpsnet-mcp 2.3.12 → 2.3.14
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 +2 -0
- package/build/http-server.js +2 -1
- package/build/networking-tools.js +29 -4
- package/build/scope-catalog.js +417 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ The remote profile also includes scoped DNS, domain and certificate management,
|
|
|
25
25
|
The remote connector uses `https://mcp.vpsnet.com/mcp` and customer consent through
|
|
26
26
|
VPSnet. See [Remote AI connections](docs/REMOTE_MCP.md) for connection setup,
|
|
27
27
|
permissions and supported operations.
|
|
28
|
+
For expired or revoked authorization and unavailable consent choices, see
|
|
29
|
+
[reconnecting and requested permissions](docs/REMOTE_MCP.md#reconnect-after-losing-authorization).
|
|
28
30
|
|
|
29
31
|
The distributable [plugin README](plugin/README.md), manifests and skills are in English.
|
|
30
32
|
See [directory readiness](docs/DIRECTORY_READINESS.md) for package validation and
|
package/build/http-server.js
CHANGED
|
@@ -3,6 +3,7 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
3
3
|
import { createVpsnetServer } from "./index.js";
|
|
4
4
|
import { resolveApiBase } from "./api.js";
|
|
5
5
|
import { requireRequestAuthorization, withAuthorization } from "./request-context.js";
|
|
6
|
+
import { scopeDescriptions } from "./scope-catalog.js";
|
|
6
7
|
import { supportedScopes, orderScopes } from "./remote-policy.js";
|
|
7
8
|
function publicUrl(value) {
|
|
8
9
|
const url = new URL(value);
|
|
@@ -70,7 +71,7 @@ export function createRemoteServer(options) {
|
|
|
70
71
|
return;
|
|
71
72
|
}
|
|
72
73
|
if (req.method === 'GET' && ['/.well-known/oauth-protected-resource', '/.well-known/oauth-protected-resource/mcp'].includes(req.url ?? '')) {
|
|
73
|
-
return json(res, 200, { resource: resource.href, authorization_servers: [issuer], scopes_supported: allowedScopes, bearer_methods_supported: ['header'], resource_name: 'VPSnet' });
|
|
74
|
+
return json(res, 200, { resource: resource.href, authorization_servers: [issuer], scopes_supported: allowedScopes, scope_descriptions: scopeDescriptions(allowedScopes), bearer_methods_supported: ['header'], resource_name: 'VPSnet' });
|
|
74
75
|
}
|
|
75
76
|
if (req.url !== '/mcp')
|
|
76
77
|
return json(res, 404, { error: 'not_found' });
|
|
@@ -76,7 +76,7 @@ const policy = `${project}/networks/{network_id}/security-policy`;
|
|
|
76
76
|
const address = `${N}/public-addresses/{address_id}`;
|
|
77
77
|
const binding = `${N}/public-bindings/{binding_id}`;
|
|
78
78
|
const scope = "Requires explicit networking:read for reads or networking:manage for changes; full/read defaults do not grant networking. The backend enforces ownership, feature availability and service 2FA locks.";
|
|
79
|
-
const writes = "Read current capabilities and owned resource state first; obtain approval for the exact change. An accepted operation is pending, not proof of connectivity.
|
|
79
|
+
const writes = "Read current capabilities and owned resource state first; obtain approval for the exact change. An accepted operation is pending, not proof of connectivity. Poll the returned operation/resource on its in_progress flag, waiting next_check_seconds between reads: while in_progress is true its reason_code is what is awaited (reason_kind waiting, e.g. a queued or pending reason, or a control plane that has not answered yet), never an error; only in_progress false with reason_kind failure is a failure. Preserve reason_code. On transport uncertainty inspect state and reuse only the original key and unchanged request; never automatically retry.";
|
|
80
80
|
const paid = "Requires full API access, networking:manage, enabled paid operations, networking:order and spend caps. Choose a supported live catalog tier and its documented request kind; preserve the exact quote; disclose its gross_amount in EUR before user approval. The same Idempotency-Key is required for quote and confirmation. API-key checkout supports the advertised account-balance payment method only. Payment acceptance is not resource readiness.";
|
|
81
81
|
function tool(name, method, path, description, fields = {}, options = {}) {
|
|
82
82
|
const pathFields = [...path.matchAll(/\{([^}]+)\}/g)].map(match => match[1]);
|
|
@@ -104,7 +104,7 @@ export const networkingTools = [
|
|
|
104
104
|
tool("get_networking_overview", "GET", `${N}/overview`, "Read owned networks, quota and operation snapshot. operations_has_more signals a bounded backend feed."),
|
|
105
105
|
tool("get_networking_topology", "GET", `${N}/topology`, "Read the account topology with network-scoped identities. Optional metrics=current requests measured traffic.", { metrics: z.literal("current").optional() }, { query: ["metrics"] }),
|
|
106
106
|
tool("list_networking_operations", "GET", `${N}/operations`, "Read recent network operations and operations_has_more. This endpoint has no pagination parameter."),
|
|
107
|
-
tool("get_networking_operation", "GET", `${N}/operations/{operation_id}`, "Read an accepted network or port operation only. A successful network_graph_created operation permits checking network.port_intent_ready for the first attachment; it does not prove guest connectivity. Security-policy, appliance and public-binding operation IDs belong to different stores. Poll security policies with get_network_security_policy, appliances with get_network_appliance_operation, public bindings with get_network_public_binding, and DNS changes through get_private_network.settings.dns_change."),
|
|
107
|
+
tool("get_networking_operation", "GET", `${N}/operations/{operation_id}`, "Read an accepted network or port operation only. Poll on in_progress (true until succeeded, failed or cancelled) and wait next_check_seconds between reads; reason_kind says what reason_code is: waiting (progress, including queued, pending and control-plane-not-yet-answered reasons - not an error), failure or outcome. A port reserve (the operation an attach returns) names its activation_operation_id once the activation that finishes the attachment exists; the completed history line names both ids. A successful network_graph_created operation permits checking network.port_intent_ready for the first attachment; it does not prove guest connectivity. Security-policy, appliance and public-binding operation IDs belong to different stores. Poll security policies with get_network_security_policy, appliances with get_network_appliance_operation, public bindings with get_network_public_binding, and DNS changes through get_private_network.settings.dns_change."),
|
|
108
108
|
tool("list_private_networks", "GET", `${N}/networks`, "List owned private networks, including deletion awaiting verified cleanup. An empty list is a starting state for creating an approved network, not evidence that existing servers cannot use private networking."),
|
|
109
109
|
tool("get_private_network", "GET", networks, "Read one owned network including DHCP reservations, DNS change progress, generation and project_id."),
|
|
110
110
|
tool("create_private_network", "POST", `${N}/networks`, "Create an approved private network for existing services when no suitable owned network exists. A false new-order private_network.available or order_availability result alone does not block this route; honor this endpoint's own quota and feature refusal. Every subnet is unique on the whole platform and comes from 100.64.0.0/10. Omit subnet and the platform allocates a free block of subnet_prefix_length (28..24, default 26 = 64 addresses; capabilities.private_network.subnet_sizes lists each size with its server count and suggested block); or name an aligned /28 through /24 inside 100.64.0.0/10 that no network holds (409 subnet_in_use), never both. Creation is asynchronous: poll its operation and get_private_network until network.port_intent_ready is true, then check attachment candidates. A successful network_graph_created operation and provisioning_status=configured describe the graph stage; the first guest has not yet qualified connectivity. Never wait for applied_generation to equal generation before the first attachment. Creation does not itself attach a server or buy a public address.", { name, subnet: z.object({ cidr: z.string().regex(/^100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7])(?:\.\d{1,3}){2}\/(?:2[4-8])$/) }).strict().optional(), subnet_prefix_length: z.union([z.literal(24), z.literal(25), z.literal(26), z.literal(27), z.literal(28)]).optional().describe("Size of the allocated subnet when subnet is omitted; default 26"), settings: settings.optional(), default_policy: z.enum(["accept", "deny"]).optional() }, { idempotent: true }),
|
|
@@ -115,7 +115,7 @@ export const networkingTools = [
|
|
|
115
115
|
tool("list_private_network_ports", "GET", `${networks}/ports`, "Read owned network ports, their fixed DHCP addresses, generations and attachment states. Reserved is not connected."),
|
|
116
116
|
tool("list_service_private_ports", "GET", `${N}/services/{service_id}/ports`, "Read private ports and order attachment recovery state for one owned service order number."),
|
|
117
117
|
tool("list_network_attachment_candidates", "GET", `${networks}/attachment-candidates`, "For a network with port_intent_ready=true, check each existing service's attachment eligibility and attachment_mode; service_id selects one owned service. Follow next_cursor using after while candidates_has_more is true. Use this per-service result and its reason_code for existing-VM attachment, not new-server order_availability. Do not attach a service the backend marks ineligible.", { after: z.string().optional(), service_id: serviceId.optional() }, { query: ["after", "service_id"] }),
|
|
118
|
-
tool("attach_private_network_port", "POST", `${networks}/ports`, "Attach an eligible existing owned service to a private network with port_intent_ready=true; omit ipv4 for automatic allocation or pass a fixed usable address. Check list_network_attachment_candidates for this network and service first, including pagination and attachment_mode. Set restart=true only after the user approves a required restart. An accepted attach is pending: poll its
|
|
118
|
+
tool("attach_private_network_port", "POST", `${networks}/ports`, "Attach an eligible existing owned service to a private network with port_intent_ready=true; omit ipv4 for automatic allocation or pass a fixed usable address. Check list_network_attachment_candidates for this network and service first, including pagination and attachment_mode. Set restart=true only after the user approves a required restart. An accepted attach is pending: it returns the port's reserve operation (queued with private_port_apply_pending; reserve, activate and detach take 13-81 s through the host) - poll it with get_networking_operation on in_progress, read its activation_operation_id once the activation that finishes the attachment exists, and verify the final port and service attachment state. Honor this endpoint's own refusal and reason_code.", { service_id: serviceId, ipv4: ipv4.optional(), restart }, { idempotent: true }),
|
|
119
119
|
tool("detach_private_network_port", "DELETE", `${networks}/ports/{port_id}`, "Detach the owned server port. Use the PORT generation and confirm any required restart.", { expected_generation: generation, restart }, { idempotent: true, destructive: true }),
|
|
120
120
|
tool("retry_private_network_port", "POST", `${networks}/ports/{port_id}/retry`, "Retry the failed current port operation with the PORT generation and any required restart approval. Inspect the failed operation: a detach retry can remove the server's private connectivity.", { expected_generation: generation, restart }, { idempotent: true, destructive: true }),
|
|
121
121
|
tool("get_network_vpn_summary", "GET", `${networks}/vpn`, "Read the network's VPN summary, including truthful absence. Native site-to-site is not supported by this tool set."),
|
|
@@ -135,7 +135,7 @@ export const networkingTools = [
|
|
|
135
135
|
tool("get_network_appliance_capabilities", "GET", `${A}/capabilities`, "Read available load balancer providers/tiers, public qualification, VPN capabilities and quota. Tier availability and prices are returned by the backend, never hardcoded."),
|
|
136
136
|
tool("list_network_appliances", "GET", A, "Read owned load balancers and VPN gateways with one stream cursor."),
|
|
137
137
|
tool("get_network_appliance_billing", "GET", `${A}/billing`, "Read current customer-visible recurring appliance lines and currency."),
|
|
138
|
-
tool("get_network_appliance_operation", "GET", `${A}/operations/{operation_id}`, "Poll an accepted appliance operation. Creation succeeds only when its actual resource state and health confirm readiness."),
|
|
138
|
+
tool("get_network_appliance_operation", "GET", `${A}/operations/{operation_id}`, "Poll an accepted appliance operation on in_progress (true until succeeded, failed or cancelled), waiting next_check_seconds between reads (a load balancer or VPN change settles in a few seconds). A fresh change is queued with appliance_dispatch_pending and then waiting_dependency while the control plane answers; reason_kind waiting marks every such reason as progress, not an error. Creation succeeds only when its actual resource state and health confirm readiness."),
|
|
139
139
|
tool("list_network_load_balancers", "GET", `${A}/load-balancers`, "List private and public load balancers and customer-safe health/qualification state."),
|
|
140
140
|
tool("get_network_load_balancer", "GET", lb, "Read one owned load balancer, listeners, members, generation and health. A pending or unqualified public endpoint is not ready."),
|
|
141
141
|
tool("estimate_network_load_balancer", "POST", `${A}/load-balancers/quote`, "Read a technical load balancer estimate for this exact configuration. This does not issue a paid purchase token; buy through quote_network_product and order_network_product. Legacy POST /appliances/load-balancers refuses unpaid creation.", loadBalancerSpec, { readOnly: true }),
|
|
@@ -208,6 +208,29 @@ export function networkingRequest(definition, args) {
|
|
|
208
208
|
};
|
|
209
209
|
return { method: definition.method, path, body, headers, readOnly: definition.options.readOnly === true };
|
|
210
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* One line a client can act on without knowing the reason vocabulary (PROD QA 2026-10-14: an AI client read the
|
|
213
|
+
* waiting reason of a fresh operation as an error and stopped). Reads the operation of a receipt or of an
|
|
214
|
+
* operation read; null when the result carries no operation with a progress label.
|
|
215
|
+
*/
|
|
216
|
+
export function networkingProgressHint(data) {
|
|
217
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
218
|
+
return null;
|
|
219
|
+
const value = data;
|
|
220
|
+
const operation = value.operation && typeof value.operation === "object" ? value.operation
|
|
221
|
+
: typeof value.in_progress === "boolean" ? value : null;
|
|
222
|
+
if (!operation || typeof operation.in_progress !== "boolean")
|
|
223
|
+
return null;
|
|
224
|
+
const reason = typeof operation.reason_code === "string" && operation.reason_code !== "" ? operation.reason_code : "none";
|
|
225
|
+
if (operation.in_progress) {
|
|
226
|
+
const wait = Number.isInteger(operation.next_check_seconds) ? `${operation.next_check_seconds} s` : "a few seconds";
|
|
227
|
+
return `Operation ${operation.id ?? ""} in progress (state=${operation.state}, reason_code=${reason}, reason_kind=${operation.reason_kind ?? "waiting"}): this is progress, not an error. Poll the follow-up read again in ${wait}; do not repeat the change.`;
|
|
228
|
+
}
|
|
229
|
+
if (operation.reason_kind === "failure") {
|
|
230
|
+
return `Operation ${operation.id ?? ""} failed (state=${operation.state}, reason_code=${reason}). Do not retry automatically; report the reason_code.`;
|
|
231
|
+
}
|
|
232
|
+
return `Operation ${operation.id ?? ""} finished (state=${operation.state}, reason_code=${reason}).`;
|
|
233
|
+
}
|
|
211
234
|
/** Read-only recovery targets. IDs are copied from validated inputs or owned API results, never guessed. */
|
|
212
235
|
export function networkingFollowUpReads(definition, args, data) {
|
|
213
236
|
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
@@ -290,8 +313,10 @@ export function registerNetworkingTools(server) {
|
|
|
290
313
|
const request = networkingRequest(definition, args);
|
|
291
314
|
const result = await apiRequest(request.method, request.path, request.body, request.headers, { readOnly: request.readOnly });
|
|
292
315
|
const reads = result.status < 400 ? networkingFollowUpReads(definition, args, result.data) : [];
|
|
316
|
+
const progress = result.status < 400 ? networkingProgressHint(result.data) : null;
|
|
293
317
|
return { content: [
|
|
294
318
|
{ type: "text", text: formatJson(result.data) },
|
|
319
|
+
...(progress ? [{ type: "text", text: progress }] : []),
|
|
295
320
|
...(reads.length ? [{ type: "text", text: `Follow-up reads (do not repeat the change): ${JSON.stringify(reads)}` }] : []),
|
|
296
321
|
], ...(result.status >= 400 ? { isError: true } : {}) };
|
|
297
322
|
});
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
// Generated from backend app/Services/Mcp/scope-catalog.json.
|
|
2
|
+
// Update with scripts/sync-scope-catalog.py; OAuth policy is enforced separately.
|
|
3
|
+
export const scopeCatalog = {
|
|
4
|
+
"services:read": {
|
|
5
|
+
"label": {
|
|
6
|
+
"en": "View selected servers",
|
|
7
|
+
"lt": "Peržiūrėti pasirinktus serverius"
|
|
8
|
+
},
|
|
9
|
+
"description": {
|
|
10
|
+
"en": "View selected servers, status, graphs, history, backups and snapshots; browsing backup files may queue a saved browse operation.",
|
|
11
|
+
"lt": "Peržiūrėti pasirinktus serverius, būseną, grafikus, istoriją, atsargines ir momentines kopijas; kopijų failų naršymas gali sukurti išsaugomą užduotį."
|
|
12
|
+
},
|
|
13
|
+
"implies": [],
|
|
14
|
+
"billing": "none",
|
|
15
|
+
"legacy": false
|
|
16
|
+
},
|
|
17
|
+
"services:manage": {
|
|
18
|
+
"label": {
|
|
19
|
+
"en": "Manage selected servers",
|
|
20
|
+
"lt": "Valdyti pasirinktus serverius"
|
|
21
|
+
},
|
|
22
|
+
"description": {
|
|
23
|
+
"en": "Start, stop or restart selected servers and change their settings, including guest DNS and firewall reset. Includes viewing selected servers.",
|
|
24
|
+
"lt": "Paleisti, stabdyti ar perkrauti pasirinktus serverius ir keisti jų nustatymus, įskaitant DNS bei ugniasienės atkūrimą. Apima serverių peržiūrą."
|
|
25
|
+
},
|
|
26
|
+
"implies": [
|
|
27
|
+
"services:read"
|
|
28
|
+
],
|
|
29
|
+
"billing": "none",
|
|
30
|
+
"legacy": false
|
|
31
|
+
},
|
|
32
|
+
"applications:read": {
|
|
33
|
+
"label": {
|
|
34
|
+
"en": "View selected server applications",
|
|
35
|
+
"lt": "Peržiūrėti pasirinktų serverių programas"
|
|
36
|
+
},
|
|
37
|
+
"description": {
|
|
38
|
+
"en": "View applications, recipes, health and logs on selected servers; diagnostics may start saved inspection jobs.",
|
|
39
|
+
"lt": "Peržiūrėti pasirinktų serverių programas, receptus, būseną ir žurnalus; diagnostika gali paleisti išsaugomas patikros užduotis."
|
|
40
|
+
},
|
|
41
|
+
"implies": [],
|
|
42
|
+
"billing": "none",
|
|
43
|
+
"legacy": false
|
|
44
|
+
},
|
|
45
|
+
"applications:manage": {
|
|
46
|
+
"label": {
|
|
47
|
+
"en": "Manage selected server applications",
|
|
48
|
+
"lt": "Valdyti pasirinktų serverių programas"
|
|
49
|
+
},
|
|
50
|
+
"description": {
|
|
51
|
+
"en": "Install, configure, update, stop, remove or roll back applications and recipes on selected servers. May replace or delete application data. Includes application viewing.",
|
|
52
|
+
"lt": "Diegti, konfigūruoti, atnaujinti, stabdyti, šalinti ar atkurti pasirinktų serverių programas ir receptus. Gali pakeisti ar ištrinti programų duomenis. Apima programų peržiūrą."
|
|
53
|
+
},
|
|
54
|
+
"implies": [
|
|
55
|
+
"applications:read"
|
|
56
|
+
],
|
|
57
|
+
"billing": "none",
|
|
58
|
+
"legacy": false
|
|
59
|
+
},
|
|
60
|
+
"networking:read": {
|
|
61
|
+
"label": {
|
|
62
|
+
"en": "View account networks",
|
|
63
|
+
"lt": "Peržiūrėti paskyros tinklus"
|
|
64
|
+
},
|
|
65
|
+
"description": {
|
|
66
|
+
"en": "View existing networks, attachments, routes and network appliance status across your account.",
|
|
67
|
+
"lt": "Peržiūrėti esamus paskyros tinklus, jungtis, maršrutus ir tinklo įrenginių būseną."
|
|
68
|
+
},
|
|
69
|
+
"implies": [],
|
|
70
|
+
"billing": "none",
|
|
71
|
+
"legacy": false
|
|
72
|
+
},
|
|
73
|
+
"networking:manage": {
|
|
74
|
+
"label": {
|
|
75
|
+
"en": "Manage account networks",
|
|
76
|
+
"lt": "Valdyti paskyros tinklus"
|
|
77
|
+
},
|
|
78
|
+
"description": {
|
|
79
|
+
"en": "Create, change or remove existing-account networks, routes, attachments and appliances. May interrupt connectivity. Includes network viewing; excludes purchases and renewals.",
|
|
80
|
+
"lt": "Kurti, keisti ar šalinti paskyros tinklus, maršrutus, jungtis ir įrenginius. Gali sutrikdyti ryšį. Apima tinklų peržiūrą; pirkimai ir pratęsimai neįtraukti."
|
|
81
|
+
},
|
|
82
|
+
"implies": [
|
|
83
|
+
"networking:read"
|
|
84
|
+
],
|
|
85
|
+
"billing": "none",
|
|
86
|
+
"legacy": false
|
|
87
|
+
},
|
|
88
|
+
"functions:read": {
|
|
89
|
+
"label": {
|
|
90
|
+
"en": "View Functions and run results",
|
|
91
|
+
"lt": "Peržiūrėti Functions ir vykdymo rezultatus"
|
|
92
|
+
},
|
|
93
|
+
"description": {
|
|
94
|
+
"en": "View account Functions, their configuration, history and invocation results.",
|
|
95
|
+
"lt": "Peržiūrėti paskyros Functions, jų konfigūraciją, istoriją ir vykdymo rezultatus."
|
|
96
|
+
},
|
|
97
|
+
"implies": [],
|
|
98
|
+
"billing": "none",
|
|
99
|
+
"legacy": false
|
|
100
|
+
},
|
|
101
|
+
"functions:manage": {
|
|
102
|
+
"label": {
|
|
103
|
+
"en": "Manage Functions",
|
|
104
|
+
"lt": "Valdyti Functions"
|
|
105
|
+
},
|
|
106
|
+
"description": {
|
|
107
|
+
"en": "Create, update or delete account Functions and their code. Includes viewing Functions; running them requires separate paid execution permission.",
|
|
108
|
+
"lt": "Kurti, atnaujinti ar trinti paskyros Functions ir jų kodą. Apima Functions peržiūrą; vykdymui reikia atskiro mokamo vykdymo leidimo."
|
|
109
|
+
},
|
|
110
|
+
"implies": [
|
|
111
|
+
"functions:read"
|
|
112
|
+
],
|
|
113
|
+
"billing": "none",
|
|
114
|
+
"legacy": false
|
|
115
|
+
},
|
|
116
|
+
"functions:invoke": {
|
|
117
|
+
"label": {
|
|
118
|
+
"en": "Run Functions (usage charges)",
|
|
119
|
+
"lt": "Vykdyti Functions (mokama pagal naudojimą)"
|
|
120
|
+
},
|
|
121
|
+
"description": {
|
|
122
|
+
"en": "Run existing account Functions using your VPSnet balance. Usage charges apply; your AI subscription does not cover them. Includes viewing Functions and run results. The daily limit counts total account Functions spending, including pending runs.",
|
|
123
|
+
"lt": "Vykdyti paskyros Functions naudojant VPSnet balansą. Taikomi naudojimo mokesčiai; AI prenumerata jų nepadengia. Apima Functions ir rezultatų peržiūrą. Dienos riba apima visas paskyros Functions išlaidas, įskaitant laukiančius vykdymus."
|
|
124
|
+
},
|
|
125
|
+
"implies": [
|
|
126
|
+
"functions:read"
|
|
127
|
+
],
|
|
128
|
+
"billing": "usage_balance",
|
|
129
|
+
"legacy": false
|
|
130
|
+
},
|
|
131
|
+
"vm:diagnostics": {
|
|
132
|
+
"label": {
|
|
133
|
+
"en": "Inspect selected servers",
|
|
134
|
+
"lt": "Tikrinti pasirinktus serverius"
|
|
135
|
+
},
|
|
136
|
+
"description": {
|
|
137
|
+
"en": "Run bounded diagnostics on selected servers and save operation results. Does not grant arbitrary commands or file access.",
|
|
138
|
+
"lt": "Vykdyti ribotą pasirinktų serverių diagnostiką ir išsaugoti rezultatus. Nesuteikia savavališkų komandų ar failų prieigos."
|
|
139
|
+
},
|
|
140
|
+
"implies": [],
|
|
141
|
+
"billing": "none",
|
|
142
|
+
"legacy": false
|
|
143
|
+
},
|
|
144
|
+
"vm:files:read": {
|
|
145
|
+
"label": {
|
|
146
|
+
"en": "Read selected server files as root",
|
|
147
|
+
"lt": "Skaityti pasirinktų serverių failus root teisėmis"
|
|
148
|
+
},
|
|
149
|
+
"description": {
|
|
150
|
+
"en": "Read files on selected servers with root privileges through saved guest operations. Files may contain secrets.",
|
|
151
|
+
"lt": "Skaityti pasirinktų serverių failus root teisėmis per išsaugomas užduotis. Failuose gali būti paslapčių."
|
|
152
|
+
},
|
|
153
|
+
"implies": [],
|
|
154
|
+
"billing": "none",
|
|
155
|
+
"legacy": false
|
|
156
|
+
},
|
|
157
|
+
"vm:files:write": {
|
|
158
|
+
"label": {
|
|
159
|
+
"en": "Read and change selected server files as root",
|
|
160
|
+
"lt": "Skaityti ir keisti pasirinktų serverių failus root teisėmis"
|
|
161
|
+
},
|
|
162
|
+
"description": {
|
|
163
|
+
"en": "Create or overwrite files on selected servers with root privileges. Includes reading files; changes can replace data or affect server operation.",
|
|
164
|
+
"lt": "Kurti ar perrašyti pasirinktų serverių failus root teisėmis. Apima failų skaitymą; pakeitimai gali pakeisti duomenis ar paveikti serverio veikimą."
|
|
165
|
+
},
|
|
166
|
+
"implies": [
|
|
167
|
+
"vm:files:read"
|
|
168
|
+
],
|
|
169
|
+
"billing": "none",
|
|
170
|
+
"legacy": false
|
|
171
|
+
},
|
|
172
|
+
"vm:exec": {
|
|
173
|
+
"label": {
|
|
174
|
+
"en": "Run selected server commands as root",
|
|
175
|
+
"lt": "Vykdyti pasirinktų serverių komandas root teisėmis"
|
|
176
|
+
},
|
|
177
|
+
"description": {
|
|
178
|
+
"en": "Run arbitrary commands and install root SSH access on selected servers. Can read, change or delete data through commands. Includes bounded server diagnostics.",
|
|
179
|
+
"lt": "Vykdyti savavališkas komandas ir įdiegti root SSH prieigą pasirinktuose serveriuose. Komandos gali skaityti, keisti ar trinti duomenis. Apima ribotą serverių diagnostiką."
|
|
180
|
+
},
|
|
181
|
+
"implies": [
|
|
182
|
+
"vm:diagnostics"
|
|
183
|
+
],
|
|
184
|
+
"billing": "none",
|
|
185
|
+
"legacy": false
|
|
186
|
+
},
|
|
187
|
+
"vm:files": {
|
|
188
|
+
"label": {
|
|
189
|
+
"en": "Read and change selected server files as root (legacy)",
|
|
190
|
+
"lt": "Skaityti ir keisti pasirinktų serverių failus root teisėmis (senasis leidimas)"
|
|
191
|
+
},
|
|
192
|
+
"description": {
|
|
193
|
+
"en": "Legacy combined file permission: includes vm:files:read and vm:files:write on selected servers. Can read secrets and overwrite data. Not advertised for new connections.",
|
|
194
|
+
"lt": "Senasis jungtinis failų leidimas: apima vm:files:read ir vm:files:write pasirinktuose serveriuose. Gali skaityti paslaptis ir perrašyti duomenis. Naujiems prisijungimams neskelbiamas."
|
|
195
|
+
},
|
|
196
|
+
"implies": [
|
|
197
|
+
"vm:files:read",
|
|
198
|
+
"vm:files:write"
|
|
199
|
+
],
|
|
200
|
+
"billing": "none",
|
|
201
|
+
"legacy": true
|
|
202
|
+
},
|
|
203
|
+
"services:reinstall": {
|
|
204
|
+
"label": {
|
|
205
|
+
"en": "Reinstall selected server operating systems",
|
|
206
|
+
"lt": "Perdiegti pasirinktų serverių operacines sistemas"
|
|
207
|
+
},
|
|
208
|
+
"description": {
|
|
209
|
+
"en": "Reinstall operating systems on selected servers. This can erase existing server data.",
|
|
210
|
+
"lt": "Perdiegti pasirinktų serverių operacines sistemas. Tai gali ištrinti esamus serverio duomenis."
|
|
211
|
+
},
|
|
212
|
+
"implies": [],
|
|
213
|
+
"billing": "none",
|
|
214
|
+
"legacy": false
|
|
215
|
+
},
|
|
216
|
+
"services:restore": {
|
|
217
|
+
"label": {
|
|
218
|
+
"en": "Restore or delete selected server snapshots",
|
|
219
|
+
"lt": "Atkurti arba trinti pasirinktų serverių momentines kopijas"
|
|
220
|
+
},
|
|
221
|
+
"description": {
|
|
222
|
+
"en": "Restore selected servers from snapshots or delete snapshots. Restoring replaces current data; deleting removes a recovery point.",
|
|
223
|
+
"lt": "Atkurti pasirinktus serverius iš momentinių kopijų arba trinti kopijas. Atkūrimas pakeičia esamus duomenis; ištrynus kopiją prarandamas atkūrimo taškas."
|
|
224
|
+
},
|
|
225
|
+
"implies": [],
|
|
226
|
+
"billing": "none",
|
|
227
|
+
"legacy": false
|
|
228
|
+
},
|
|
229
|
+
"services:rescue": {
|
|
230
|
+
"label": {
|
|
231
|
+
"en": "Start or exit selected server rescue mode",
|
|
232
|
+
"lt": "Įjungti ar išjungti pasirinktų serverių atkūrimo režimą"
|
|
233
|
+
},
|
|
234
|
+
"description": {
|
|
235
|
+
"en": "Start or exit rescue mode on selected servers. May restart a server or interrupt its workload. Includes viewing selected servers.",
|
|
236
|
+
"lt": "Įjungti ar išjungti pasirinktų serverių atkūrimo režimą. Gali perkrauti serverį ar nutraukti jo darbą. Apima serverių peržiūrą."
|
|
237
|
+
},
|
|
238
|
+
"implies": [
|
|
239
|
+
"services:read"
|
|
240
|
+
],
|
|
241
|
+
"billing": "none",
|
|
242
|
+
"legacy": false
|
|
243
|
+
},
|
|
244
|
+
"dns:read": {
|
|
245
|
+
"label": {
|
|
246
|
+
"en": "View account DNS",
|
|
247
|
+
"lt": "Peržiūrėti paskyros DNS"
|
|
248
|
+
},
|
|
249
|
+
"description": {
|
|
250
|
+
"en": "View account DNS zones, records, diagnostics, DNSSEC state and zone history.",
|
|
251
|
+
"lt": "Peržiūrėti paskyros DNS zonas, įrašus, diagnostiką, DNSSEC būseną ir zonų istoriją."
|
|
252
|
+
},
|
|
253
|
+
"implies": [],
|
|
254
|
+
"billing": "none",
|
|
255
|
+
"legacy": false
|
|
256
|
+
},
|
|
257
|
+
"dns:write": {
|
|
258
|
+
"label": {
|
|
259
|
+
"en": "Manage account DNS",
|
|
260
|
+
"lt": "Valdyti paskyros DNS"
|
|
261
|
+
},
|
|
262
|
+
"description": {
|
|
263
|
+
"en": "Create, change, import or delete account DNS zones and records. Can redirect traffic or interrupt domains. Includes DNS viewing.",
|
|
264
|
+
"lt": "Kurti, keisti, importuoti ar trinti paskyros DNS zonas ir įrašus. Gali nukreipti srautą ar sutrikdyti domenų veikimą. Apima DNS peržiūrą."
|
|
265
|
+
},
|
|
266
|
+
"implies": [
|
|
267
|
+
"dns:read"
|
|
268
|
+
],
|
|
269
|
+
"billing": "none",
|
|
270
|
+
"legacy": false
|
|
271
|
+
},
|
|
272
|
+
"dnssec:manage": {
|
|
273
|
+
"label": {
|
|
274
|
+
"en": "Manage account DNSSEC",
|
|
275
|
+
"lt": "Valdyti paskyros DNSSEC"
|
|
276
|
+
},
|
|
277
|
+
"description": {
|
|
278
|
+
"en": "Change DNSSEC signing for account DNS zones. Incorrect changes can interrupt DNS resolution. Includes DNS viewing.",
|
|
279
|
+
"lt": "Keisti paskyros DNS zonų DNSSEC pasirašymą. Klaidingi pakeitimai gali sutrikdyti DNS veikimą. Apima DNS peržiūrą."
|
|
280
|
+
},
|
|
281
|
+
"implies": [
|
|
282
|
+
"dns:read"
|
|
283
|
+
],
|
|
284
|
+
"billing": "none",
|
|
285
|
+
"legacy": false
|
|
286
|
+
},
|
|
287
|
+
"domains:read": {
|
|
288
|
+
"label": {
|
|
289
|
+
"en": "View account domains",
|
|
290
|
+
"lt": "Peržiūrėti paskyros domenus"
|
|
291
|
+
},
|
|
292
|
+
"description": {
|
|
293
|
+
"en": "View account domains, nameservers, glue records, parent DS records and contacts.",
|
|
294
|
+
"lt": "Peržiūrėti paskyros domenus, vardų serverius, glue ir tėvinės zonos DS įrašus bei kontaktus."
|
|
295
|
+
},
|
|
296
|
+
"implies": [],
|
|
297
|
+
"billing": "none",
|
|
298
|
+
"legacy": false
|
|
299
|
+
},
|
|
300
|
+
"domains:manage": {
|
|
301
|
+
"label": {
|
|
302
|
+
"en": "Manage account domains",
|
|
303
|
+
"lt": "Valdyti paskyros domenus"
|
|
304
|
+
},
|
|
305
|
+
"description": {
|
|
306
|
+
"en": "Change account domain nameservers, glue records, parent DS records and contacts. Can interrupt domain resolution. Includes domain viewing; registration requires separate purchase permission.",
|
|
307
|
+
"lt": "Keisti paskyros domenų vardų serverius, glue ir tėvinės zonos DS įrašus bei kontaktus. Gali sutrikdyti domenų veikimą. Apima peržiūrą; registravimui reikia atskiro pirkimo leidimo."
|
|
308
|
+
},
|
|
309
|
+
"implies": [
|
|
310
|
+
"domains:read"
|
|
311
|
+
],
|
|
312
|
+
"billing": "none",
|
|
313
|
+
"legacy": false
|
|
314
|
+
},
|
|
315
|
+
"certificates:read": {
|
|
316
|
+
"label": {
|
|
317
|
+
"en": "View account TLS certificates",
|
|
318
|
+
"lt": "Peržiūrėti paskyros TLS sertifikatus"
|
|
319
|
+
},
|
|
320
|
+
"description": {
|
|
321
|
+
"en": "View account TLS certificates, validation and actions, and download available certificate material.",
|
|
322
|
+
"lt": "Peržiūrėti paskyros TLS sertifikatus, patvirtinimą, veiksmus ir atsisiųsti prieinamą sertifikatų medžiagą."
|
|
323
|
+
},
|
|
324
|
+
"implies": [],
|
|
325
|
+
"billing": "none",
|
|
326
|
+
"legacy": false
|
|
327
|
+
},
|
|
328
|
+
"certificates:manage": {
|
|
329
|
+
"label": {
|
|
330
|
+
"en": "Manage account TLS certificates",
|
|
331
|
+
"lt": "Valdyti paskyros TLS sertifikatus"
|
|
332
|
+
},
|
|
333
|
+
"description": {
|
|
334
|
+
"en": "Create or renew free certificates and manage existing certificates and automatic SSL subscriptions, including cancellation or revocation. Includes certificate viewing; excludes purchases.",
|
|
335
|
+
"lt": "Kurti ar pratęsti nemokamus sertifikatus ir valdyti esamus sertifikatus bei automatinio SSL prenumeratas, įskaitant atšaukimą. Apima sertifikatų peržiūrą; pirkimai neįtraukti."
|
|
336
|
+
},
|
|
337
|
+
"implies": [
|
|
338
|
+
"certificates:read"
|
|
339
|
+
],
|
|
340
|
+
"billing": "none",
|
|
341
|
+
"legacy": false
|
|
342
|
+
},
|
|
343
|
+
"ssh_keys:read": {
|
|
344
|
+
"label": {
|
|
345
|
+
"en": "View account public SSH keys",
|
|
346
|
+
"lt": "Peržiūrėti paskyros viešuosius SSH raktus"
|
|
347
|
+
},
|
|
348
|
+
"description": {
|
|
349
|
+
"en": "View public SSH keys saved in your account. Does not expose private keys.",
|
|
350
|
+
"lt": "Peržiūrėti paskyroje išsaugotus viešuosius SSH raktus. Privatūs raktai neatskleidžiami."
|
|
351
|
+
},
|
|
352
|
+
"implies": [],
|
|
353
|
+
"billing": "none",
|
|
354
|
+
"legacy": false
|
|
355
|
+
},
|
|
356
|
+
"ssh_keys:manage": {
|
|
357
|
+
"label": {
|
|
358
|
+
"en": "Manage account public SSH keys",
|
|
359
|
+
"lt": "Valdyti paskyros viešuosius SSH raktus"
|
|
360
|
+
},
|
|
361
|
+
"description": {
|
|
362
|
+
"en": "Add or delete account public SSH keys. Includes key viewing; installing a key on a server requires vm:exec permission.",
|
|
363
|
+
"lt": "Pridėti ar trinti paskyros viešuosius SSH raktus. Apima raktų peržiūrą; diegimui serveryje reikia vm:exec leidimo."
|
|
364
|
+
},
|
|
365
|
+
"implies": [
|
|
366
|
+
"ssh_keys:read"
|
|
367
|
+
],
|
|
368
|
+
"billing": "none",
|
|
369
|
+
"legacy": false
|
|
370
|
+
},
|
|
371
|
+
"orders:read": {
|
|
372
|
+
"label": {
|
|
373
|
+
"en": "View server plans and server or domain purchase results",
|
|
374
|
+
"lt": "Peržiūrėti serverių planus ir serverių ar domenų pirkimo rezultatus"
|
|
375
|
+
},
|
|
376
|
+
"description": {
|
|
377
|
+
"en": "View server plans, order options and existing server or domain purchase results. Does not submit a purchase. Available only through the separate orders profile.",
|
|
378
|
+
"lt": "Peržiūrėti serverių planus, užsakymo parinktis ir esamų serverių ar domenų pirkimų rezultatus. Pirkimo neatlieka. Prieinama tik atskirame užsakymų profilyje."
|
|
379
|
+
},
|
|
380
|
+
"implies": [],
|
|
381
|
+
"billing": "none",
|
|
382
|
+
"legacy": false
|
|
383
|
+
},
|
|
384
|
+
"orders:servers": {
|
|
385
|
+
"label": {
|
|
386
|
+
"en": "Purchase VPS servers from your balance",
|
|
387
|
+
"lt": "Pirkti VPS serverius iš balanso"
|
|
388
|
+
},
|
|
389
|
+
"description": {
|
|
390
|
+
"en": "Quote and purchase VPS servers using your VPSnet balance after approval of the final gross EUR amount and period, within this connection’s daily and monthly limits. Includes viewing order plans and purchase results. Available only through the separate orders profile.",
|
|
391
|
+
"lt": "Gauti VPS serverių pasiūlymus ir pirkti iš VPSnet balanso, patvirtinus galutinę EUR sumą su mokesčiais bei laikotarpį, neviršijant jungties dienos ir mėnesio ribų. Apima planų ir pirkimų rezultatų peržiūrą. Prieinama tik atskirame užsakymų profilyje."
|
|
392
|
+
},
|
|
393
|
+
"implies": [
|
|
394
|
+
"orders:read"
|
|
395
|
+
],
|
|
396
|
+
"billing": "purchase_balance",
|
|
397
|
+
"legacy": false
|
|
398
|
+
},
|
|
399
|
+
"orders:domains": {
|
|
400
|
+
"label": {
|
|
401
|
+
"en": "Register domains from your balance",
|
|
402
|
+
"lt": "Registruoti domenus iš balanso"
|
|
403
|
+
},
|
|
404
|
+
"description": {
|
|
405
|
+
"en": "Quote and register domains using your VPSnet balance after approval of the final gross EUR amount and period, within this connection’s daily and monthly limits. Registration may be non-refundable. Includes viewing order plans and purchase results. Available only through the separate orders profile.",
|
|
406
|
+
"lt": "Gauti domenų pasiūlymus ir registruoti iš VPSnet balanso, patvirtinus galutinę EUR sumą su mokesčiais bei laikotarpį, neviršijant jungties dienos ir mėnesio ribų. Registravimo mokestis gali būti negrąžinamas. Apima planų ir pirkimų rezultatų peržiūrą. Prieinama tik atskirame užsakymų profilyje."
|
|
407
|
+
},
|
|
408
|
+
"implies": [
|
|
409
|
+
"orders:read"
|
|
410
|
+
],
|
|
411
|
+
"billing": "purchase_balance",
|
|
412
|
+
"legacy": false
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
export function scopeDescriptions(scopes) {
|
|
416
|
+
return Object.fromEntries(scopes.map(scope => [scope, scopeCatalog[scope].description.en]));
|
|
417
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vpsnet-mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP server for managing VPSnet.com services, applications, DNS, domains, billing, and server lifecycle operations",
|
|
6
6
|
"bin": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"build/http-server.js",
|
|
36
36
|
"build/request-context.js",
|
|
37
37
|
"build/remote-policy.js",
|
|
38
|
+
"build/scope-catalog.js",
|
|
38
39
|
"build/remote-auth-error.js",
|
|
39
40
|
"build/remote-tools.js",
|
|
40
41
|
"build/remote-orders.js"
|