nandi-proxmox-mcp 0.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.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/src/cli/doctor.d.ts +2 -0
  4. package/dist/src/cli/doctor.d.ts.map +1 -0
  5. package/dist/src/cli/doctor.js +127 -0
  6. package/dist/src/cli/doctor.js.map +1 -0
  7. package/dist/src/cli/main.d.ts +3 -0
  8. package/dist/src/cli/main.d.ts.map +1 -0
  9. package/dist/src/cli/main.js +30 -0
  10. package/dist/src/cli/main.js.map +1 -0
  11. package/dist/src/cli/report.d.ts +7 -0
  12. package/dist/src/cli/report.d.ts.map +1 -0
  13. package/dist/src/cli/report.js +9 -0
  14. package/dist/src/cli/report.js.map +1 -0
  15. package/dist/src/cli/setup.d.ts +2 -0
  16. package/dist/src/cli/setup.d.ts.map +1 -0
  17. package/dist/src/cli/setup.js +150 -0
  18. package/dist/src/cli/setup.js.map +1 -0
  19. package/dist/src/config/env.d.ts +3 -0
  20. package/dist/src/config/env.d.ts.map +1 -0
  21. package/dist/src/config/env.js +19 -0
  22. package/dist/src/config/env.js.map +1 -0
  23. package/dist/src/config/fileConfig.d.ts +4 -0
  24. package/dist/src/config/fileConfig.d.ts.map +1 -0
  25. package/dist/src/config/fileConfig.js +13 -0
  26. package/dist/src/config/fileConfig.js.map +1 -0
  27. package/dist/src/config/installDescriptor.d.ts +36 -0
  28. package/dist/src/config/installDescriptor.d.ts.map +1 -0
  29. package/dist/src/config/installDescriptor.js +91 -0
  30. package/dist/src/config/installDescriptor.js.map +1 -0
  31. package/dist/src/config/templates.d.ts +15 -0
  32. package/dist/src/config/templates.d.ts.map +1 -0
  33. package/dist/src/config/templates.js +21 -0
  34. package/dist/src/config/templates.js.map +1 -0
  35. package/dist/src/config/validate.d.ts +40 -0
  36. package/dist/src/config/validate.d.ts.map +1 -0
  37. package/dist/src/config/validate.js +15 -0
  38. package/dist/src/config/validate.js.map +1 -0
  39. package/dist/src/guardian/errorMap.d.ts +3 -0
  40. package/dist/src/guardian/errorMap.d.ts.map +1 -0
  41. package/dist/src/guardian/errorMap.js +35 -0
  42. package/dist/src/guardian/errorMap.js.map +1 -0
  43. package/dist/src/guardian/guardian.d.ts +8 -0
  44. package/dist/src/guardian/guardian.d.ts.map +1 -0
  45. package/dist/src/guardian/guardian.js +38 -0
  46. package/dist/src/guardian/guardian.js.map +1 -0
  47. package/dist/src/guardian/result.d.ts +20 -0
  48. package/dist/src/guardian/result.d.ts.map +1 -0
  49. package/dist/src/guardian/result.js +17 -0
  50. package/dist/src/guardian/result.js.map +1 -0
  51. package/dist/src/guardian/retryPolicy.d.ts +9 -0
  52. package/dist/src/guardian/retryPolicy.d.ts.map +1 -0
  53. package/dist/src/guardian/retryPolicy.js +15 -0
  54. package/dist/src/guardian/retryPolicy.js.map +1 -0
  55. package/dist/src/guardian/timeout.d.ts +2 -0
  56. package/dist/src/guardian/timeout.d.ts.map +1 -0
  57. package/dist/src/guardian/timeout.js +10 -0
  58. package/dist/src/guardian/timeout.js.map +1 -0
  59. package/dist/src/index.d.ts +2 -0
  60. package/dist/src/index.d.ts.map +1 -0
  61. package/dist/src/index.js +35 -0
  62. package/dist/src/index.js.map +1 -0
  63. package/dist/src/logging/logger.d.ts +6 -0
  64. package/dist/src/logging/logger.d.ts.map +1 -0
  65. package/dist/src/logging/logger.js +16 -0
  66. package/dist/src/logging/logger.js.map +1 -0
  67. package/dist/src/logging/redaction.d.ts +2 -0
  68. package/dist/src/logging/redaction.d.ts.map +1 -0
  69. package/dist/src/logging/redaction.js +13 -0
  70. package/dist/src/logging/redaction.js.map +1 -0
  71. package/dist/src/proxmox/auth.d.ts +3 -0
  72. package/dist/src/proxmox/auth.d.ts.map +1 -0
  73. package/dist/src/proxmox/auth.js +4 -0
  74. package/dist/src/proxmox/auth.js.map +1 -0
  75. package/dist/src/proxmox/client.d.ts +21 -0
  76. package/dist/src/proxmox/client.d.ts.map +1 -0
  77. package/dist/src/proxmox/client.js +70 -0
  78. package/dist/src/proxmox/client.js.map +1 -0
  79. package/dist/src/proxmox/endpoints.d.ts +13 -0
  80. package/dist/src/proxmox/endpoints.d.ts.map +1 -0
  81. package/dist/src/proxmox/endpoints.js +13 -0
  82. package/dist/src/proxmox/endpoints.js.map +1 -0
  83. package/dist/src/proxmox/errors.d.ts +10 -0
  84. package/dist/src/proxmox/errors.d.ts.map +1 -0
  85. package/dist/src/proxmox/errors.js +33 -0
  86. package/dist/src/proxmox/errors.js.map +1 -0
  87. package/dist/src/proxmox/types.d.ts +29 -0
  88. package/dist/src/proxmox/types.d.ts.map +1 -0
  89. package/dist/src/proxmox/types.js +2 -0
  90. package/dist/src/proxmox/types.js.map +1 -0
  91. package/dist/src/server/mcpServer.d.ts +10 -0
  92. package/dist/src/server/mcpServer.d.ts.map +1 -0
  93. package/dist/src/server/mcpServer.js +25 -0
  94. package/dist/src/server/mcpServer.js.map +1 -0
  95. package/dist/src/server/schemas.d.ts +103 -0
  96. package/dist/src/server/schemas.d.ts.map +1 -0
  97. package/dist/src/server/schemas.js +41 -0
  98. package/dist/src/server/schemas.js.map +1 -0
  99. package/dist/src/server/toolRegistry.d.ts +4 -0
  100. package/dist/src/server/toolRegistry.d.ts.map +1 -0
  101. package/dist/src/server/toolRegistry.js +47 -0
  102. package/dist/src/server/toolRegistry.js.map +1 -0
  103. package/dist/src/ssh/batchDiagnostics.d.ts +8 -0
  104. package/dist/src/ssh/batchDiagnostics.d.ts.map +1 -0
  105. package/dist/src/ssh/batchDiagnostics.js +36 -0
  106. package/dist/src/ssh/batchDiagnostics.js.map +1 -0
  107. package/dist/src/ssh/pctExec.d.ts +3 -0
  108. package/dist/src/ssh/pctExec.d.ts.map +1 -0
  109. package/dist/src/ssh/pctExec.js +13 -0
  110. package/dist/src/ssh/pctExec.js.map +1 -0
  111. package/dist/src/ssh/sshClient.d.ts +14 -0
  112. package/dist/src/ssh/sshClient.d.ts.map +1 -0
  113. package/dist/src/ssh/sshClient.js +22 -0
  114. package/dist/src/ssh/sshClient.js.map +1 -0
  115. package/dist/src/tools/control.d.ts +7 -0
  116. package/dist/src/tools/control.d.ts.map +1 -0
  117. package/dist/src/tools/control.js +14 -0
  118. package/dist/src/tools/control.js.map +1 -0
  119. package/dist/src/tools/diagnostics.d.ts +4 -0
  120. package/dist/src/tools/diagnostics.d.ts.map +1 -0
  121. package/dist/src/tools/diagnostics.js +6 -0
  122. package/dist/src/tools/diagnostics.js.map +1 -0
  123. package/dist/src/tools/inventory.d.ts +8 -0
  124. package/dist/src/tools/inventory.d.ts.map +1 -0
  125. package/dist/src/tools/inventory.js +21 -0
  126. package/dist/src/tools/inventory.js.map +1 -0
  127. package/dist/src/tools/operations.d.ts +7 -0
  128. package/dist/src/tools/operations.d.ts.map +1 -0
  129. package/dist/src/tools/operations.js +37 -0
  130. package/dist/src/tools/operations.js.map +1 -0
  131. package/dist/src/tools/status.d.ts +6 -0
  132. package/dist/src/tools/status.d.ts.map +1 -0
  133. package/dist/src/tools/status.js +11 -0
  134. package/dist/src/tools/status.js.map +1 -0
  135. package/dist/src/utils/parsing.d.ts +3 -0
  136. package/dist/src/utils/parsing.d.ts.map +1 -0
  137. package/dist/src/utils/parsing.js +14 -0
  138. package/dist/src/utils/parsing.js.map +1 -0
  139. package/dist/src/utils/safeExec.d.ts +7 -0
  140. package/dist/src/utils/safeExec.d.ts.map +1 -0
  141. package/dist/src/utils/safeExec.js +31 -0
  142. package/dist/src/utils/safeExec.js.map +1 -0
  143. package/dist/src/utils/time.d.ts +2 -0
  144. package/dist/src/utils/time.d.ts.map +1 -0
  145. package/dist/src/utils/time.js +2 -0
  146. package/dist/src/utils/time.js.map +1 -0
  147. package/mcp-manifest.json +19 -0
  148. package/package.json +49 -0
  149. package/scripts/setup-win.ps1 +14 -0
  150. package/scripts/validate-manifest.mjs +26 -0
  151. package/scripts/verify-config.ps1 +22 -0
  152. package/templates/env.template +11 -0
  153. package/templates/mcp.config.template.json +13 -0
  154. package/templates/vscode.mcp.template.json +11 -0
  155. package/templates/vscode.user.mcp.template.json +11 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NANDI Services
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # nandi-proxmox-mcp
2
+
3
+ Open source MCP Server for Proxmox, powered by NANDI Services.
4
+
5
+ `nandi-proxmox-mcp` lets users connect to their own Proxmox server and operate nodes, VMs, and CT/LXC securely via MCP tools in VS Code.
6
+
7
+ ## Important: API token ownership
8
+ The Proxmox API token is **not** delivered by npm, VS Code, or this MCP package.
9
+ Each user must create a token in their own Proxmox environment with minimum ACL permissions.
10
+
11
+ ## 5-minute Quickstart (Windows)
12
+ 1. Install Node.js 20+.
13
+ 2. Run `npm install -g nandi-proxmox-mcp`.
14
+ 3. Run `nandi-proxmox-mcp setup` and complete guided onboarding.
15
+ 4. Run `nandi-proxmox-mcp doctor --check mcp-config,nodes,vms,cts,node-status,remote-op`.
16
+ 5. Open VS Code and confirm MCP server is registered (`.vscode/mcp.json`).
17
+
18
+ Alternative direct run:
19
+ - `npx nandi-proxmox-mcp setup`
20
+ - `npx nandi-proxmox-mcp run`
21
+
22
+ ## VS Code / Codex plug-and-play paths
23
+ - Custom server: use `.vscode/mcp.json` (root `servers` format).
24
+ - Manifest install: use `mcp-manifest.json`.
25
+ - User-level config template: `templates/vscode.user.mcp.template.json`.
26
+
27
+ ## MCP tools included
28
+ - Inventory: `listNodes`, `listVMs`, `listContainers`
29
+ - Status: `getNodeStatus`, `getVMStatus`, `getContainerStatus`
30
+ - Control: `startVM`, `stopVM`, `startContainer`, `stopContainer`
31
+ - CT operations: `execInContainer`, `dockerPsInContainer`, `dockerLogsInContainer`, `runRemoteDiagnostic`, `sshBatchDiagnostics`
32
+
33
+ ## Security principles
34
+ - No hardcoded host/token secrets in versioned files.
35
+ - Local sensitive config generated in `.nandi-proxmox-mcp/config.json`.
36
+ - Templates with placeholders only.
37
+ - CI includes secret scanning and dependency scanning.
38
+
39
+ ## Docs
40
+ - [Quickstart](docs/QUICKSTART.md)
41
+ - [Windows Installation](docs/INSTALL_WINDOWS.md)
42
+ - [Proxmox Token + ACL Setup](docs/PROXMOX_SETUP.md)
43
+ - [SSH Setup and Batch Validation](docs/SSH_SETUP.md)
44
+ - [VS Code MCP Setup](docs/VSCODE_SETUP.md)
45
+ - [Marketplace Go-Live](docs/MARKETPLACE_GO_LIVE.md)
46
+ - [Security Guide](docs/SECURITY.md)
47
+ - [Troubleshooting](docs/TROUBLESHOOTING.md)
48
+ - [FAQ](docs/FAQ.md)
49
+ - [CI Secrets Policy](docs/CI_SECRETS.md)
50
+
51
+ ## Development
52
+ - `npm ci`
53
+ - `npm run lint`
54
+ - `npm run typecheck`
55
+ - `npm test`
56
+ - `npm run build`
57
+
58
+ ## License
59
+ MIT. See LICENSE.
60
+
@@ -0,0 +1,2 @@
1
+ export declare const runDoctor: (checksArg?: string) => Promise<void>;
2
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/doctor.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,SAAS,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CA4HhE,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { loadFileConfig } from "../config/fileConfig.js";
4
+ import { ProxmoxClient } from "../proxmox/client.js";
5
+ import { printReport } from "./report.js";
6
+ import { runSshBatch } from "../ssh/sshClient.js";
7
+ import { pctExec } from "../ssh/pctExec.js";
8
+ import { normalizeMcpConfigDocument, validateMcpConfig, validateMcpManifest } from "../config/installDescriptor.js";
9
+ const parseRequestedChecks = (value) => {
10
+ if (!value) {
11
+ return new Set(["mcp-config", "nodes", "vms", "cts", "node-status", "remote-op"]);
12
+ }
13
+ return new Set(value.split(",").map((segment) => segment.trim()).filter(Boolean));
14
+ };
15
+ export const runDoctor = async (checksArg) => {
16
+ const checks = parseRequestedChecks(checksArg);
17
+ const report = [];
18
+ const config = await loadFileConfig();
19
+ const client = new ProxmoxClient(config);
20
+ let firstNode = "";
21
+ if (checks.has("mcp-config")) {
22
+ try {
23
+ const mcpPath = resolve(process.cwd(), ".vscode", "mcp.json");
24
+ const manifestPath = resolve(process.cwd(), "mcp-manifest.json");
25
+ const mcpRaw = await readFile(mcpPath, "utf8");
26
+ const normalized = normalizeMcpConfigDocument(mcpRaw);
27
+ const configValidation = validateMcpConfig(normalized.normalized);
28
+ if (!configValidation.ok) {
29
+ throw new Error(configValidation.errors.join(" | "));
30
+ }
31
+ const manifestRaw = await readFile(manifestPath, "utf8");
32
+ const manifestValidation = validateMcpManifest(JSON.parse(manifestRaw));
33
+ if (!manifestValidation.ok) {
34
+ throw new Error(`Manifest invalid: ${manifestValidation.errors.join(" | ")}`);
35
+ }
36
+ report.push({ check: "mcpConfig", ok: true, detail: "MCP config and manifest are valid" });
37
+ }
38
+ catch (error) {
39
+ report.push({ check: "mcpConfig", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
40
+ }
41
+ }
42
+ if (checks.has("nodes")) {
43
+ try {
44
+ const nodes = await client.listNodes();
45
+ firstNode = nodes[0]?.node ?? "";
46
+ report.push({ check: "listNodes", ok: true, detail: `Found ${nodes.length} nodes` });
47
+ }
48
+ catch (error) {
49
+ report.push({
50
+ check: "listNodes",
51
+ ok: false,
52
+ detail: error instanceof Error ? error.message : "Unknown error"
53
+ });
54
+ }
55
+ }
56
+ if (checks.has("vms") && firstNode) {
57
+ try {
58
+ const vms = await client.listVms(firstNode);
59
+ report.push({ check: "listVMs", ok: true, detail: `Found ${vms.length} VMs on ${firstNode}` });
60
+ }
61
+ catch (error) {
62
+ report.push({ check: "listVMs", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
63
+ }
64
+ }
65
+ if (checks.has("cts") && firstNode) {
66
+ try {
67
+ const cts = await client.listContainers(firstNode);
68
+ report.push({ check: "listContainers", ok: true, detail: `Found ${cts.length} CTs on ${firstNode}` });
69
+ }
70
+ catch (error) {
71
+ report.push({ check: "listContainers", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
72
+ }
73
+ }
74
+ if (checks.has("node-status") && firstNode) {
75
+ try {
76
+ const status = await client.getNodeStatus(firstNode);
77
+ const keyCount = Object.keys(status).length;
78
+ report.push({ check: "getNodeStatus", ok: true, detail: `Status keys: ${keyCount}` });
79
+ }
80
+ catch (error) {
81
+ report.push({ check: "getNodeStatus", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
82
+ }
83
+ }
84
+ if (checks.has("remote-op")) {
85
+ try {
86
+ const sshRes = await runSshBatch({
87
+ host: config.sshHost,
88
+ port: config.sshPort,
89
+ user: config.sshUser,
90
+ keyPath: config.sshKeyPath,
91
+ timeoutMs: 15_000
92
+ }, "echo ssh-batch-ok");
93
+ if (sshRes.exitCode !== 0) {
94
+ throw new Error(`SSH batch failed. Interactive may still work. stderr=${sshRes.stderr.trim()}`);
95
+ }
96
+ report.push({ check: "sshBatch", ok: true, detail: "Batch SSH succeeded" });
97
+ }
98
+ catch (error) {
99
+ report.push({ check: "sshBatch", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
100
+ }
101
+ const ctid = Number.parseInt(process.env.NANDI_DOCTOR_CTID ?? "0", 10);
102
+ if (Number.isFinite(ctid) && ctid > 0) {
103
+ try {
104
+ await pctExec({
105
+ host: config.sshHost,
106
+ port: config.sshPort,
107
+ user: config.sshUser,
108
+ keyPath: config.sshKeyPath,
109
+ timeoutMs: 20_000
110
+ }, ctid, "echo ct-remote-ok");
111
+ report.push({ check: "pctExec", ok: true, detail: `pct exec succeeded for CT ${ctid}` });
112
+ }
113
+ catch (error) {
114
+ report.push({ check: "pctExec", ok: false, detail: error instanceof Error ? error.message : "Unknown error" });
115
+ }
116
+ }
117
+ else {
118
+ report.push({
119
+ check: "pctExec",
120
+ ok: false,
121
+ detail: "Set NANDI_DOCTOR_CTID environment variable to validate CT remote operation"
122
+ });
123
+ }
124
+ }
125
+ printReport("Doctor report", report);
126
+ };
127
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAEpH,MAAM,oBAAoB,GAAG,CAAC,KAAc,EAAe,EAAE;IAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AACpF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,SAAkB,EAAiB,EAAE;IACnE,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,SAAS,GAAG,EAAE,CAAC;IAEnB,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACtD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAClE,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACvD,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAY,CAAC,CAAC;YACnF,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,qBAAqB,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChF,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACnH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACvC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,KAAK,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC;QACvF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,WAAW;gBAClB,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aACjE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,MAAM,WAAW,SAAS,EAAE,EAAE,CAAC,CAAC;QACjG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACjH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,MAAM,WAAW,SAAS,EAAE,EAAE,CAAC,CAAC;QACxG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,SAAS,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,QAAQ,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACvH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B;gBACE,IAAI,EAAE,MAAM,CAAC,OAAO;gBACpB,IAAI,EAAE,MAAM,CAAC,OAAO;gBACpB,IAAI,EAAE,MAAM,CAAC,OAAO;gBACpB,OAAO,EAAE,MAAM,CAAC,UAAU;gBAC1B,SAAS,EAAE,MAAM;aAClB,EACD,mBAAmB,CACpB,CAAC;YAEF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,wDAAwD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAClG,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAClH,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,OAAO,CACX;oBACE,IAAI,EAAE,MAAM,CAAC,OAAO;oBACpB,IAAI,EAAE,MAAM,CAAC,OAAO;oBACpB,IAAI,EAAE,MAAM,CAAC,OAAO;oBACpB,OAAO,EAAE,MAAM,CAAC,UAAU;oBAC1B,SAAS,EAAE,MAAM;iBAClB,EACD,IAAI,EACJ,mBAAmB,CACpB,CAAC;gBAEF,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,6BAA6B,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3F,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;YACjH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,SAAS;gBAChB,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,4EAA4E;aACrF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { runSetup } from "./setup.js";
4
+ import { runDoctor } from "./doctor.js";
5
+ import { loadFileConfig } from "../config/fileConfig.js";
6
+ import { startMcpServer } from "../server/mcpServer.js";
7
+ const program = new Command();
8
+ program.name("nandi-proxmox-mcp").description("Proxmox MCP server - open source, powered by NANDI Services").version("0.1.0");
9
+ program
10
+ .command("setup")
11
+ .description("Run interactive Windows-first setup")
12
+ .action(async () => {
13
+ await runSetup();
14
+ });
15
+ program
16
+ .command("doctor")
17
+ .description("Run post-install checks")
18
+ .option("--check <checks>", "Comma-separated checks: mcp-config,nodes,vms,cts,node-status,remote-op")
19
+ .action(async (options) => {
20
+ await runDoctor(options.check);
21
+ });
22
+ program
23
+ .command("run")
24
+ .description("Run MCP server over stdio")
25
+ .action(async () => {
26
+ const config = await loadFileConfig();
27
+ await startMcpServer(config);
28
+ });
29
+ void program.parseAsync(process.argv);
30
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,WAAW,CAAC,6DAA6D,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9H,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,QAAQ,EAAE,CAAC;AACnB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,kBAAkB,EAAE,wEAAwE,CAAC;KACpG,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IACtC,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEL,KAAK,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type ReportItem = {
2
+ check: string;
3
+ ok: boolean;
4
+ detail: string;
5
+ };
6
+ export declare const printReport: (title: string, items: ReportItem[]) => void;
7
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/report.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,EAAE,OAAO,UAAU,EAAE,KAAG,IAQhE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export const printReport = (title, items) => {
2
+ process.stdout.write(`\n${title}\n`);
3
+ process.stdout.write(`${"-".repeat(title.length)}\n`);
4
+ for (const item of items) {
5
+ const light = item.ok ? "GREEN" : "RED";
6
+ process.stdout.write(`[${light}] ${item.check}: ${item.detail}\n`);
7
+ }
8
+ };
9
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/cli/report.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,KAAmB,EAAQ,EAAE;IACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IACrE,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const runSetup: () => Promise<void>;
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/setup.ts"],"names":[],"mappings":"AA+JA,eAAO,MAAM,QAAQ,QAAa,OAAO,CAAC,IAAI,CAsB7C,CAAC"}
@@ -0,0 +1,150 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { stdin as input, stdout as output } from "node:process";
5
+ import { ProxmoxClient } from "../proxmox/client.js";
6
+ import { runtimeConfigSchema } from "../config/validate.js";
7
+ import { printReport } from "./report.js";
8
+ import { runSshBatch } from "../ssh/sshClient.js";
9
+ import { buildWorkspaceMcpConfig, normalizeMcpConfigDocument, validateMcpConfig } from "../config/installDescriptor.js";
10
+ const defaultConfigDir = resolve(process.cwd(), ".nandi-proxmox-mcp");
11
+ const defaultConfigPath = resolve(defaultConfigDir, "config.json");
12
+ const ask = async () => {
13
+ const rl = createInterface({ input, output });
14
+ const proxmoxHost = (await rl.question("Proxmox host (IP/FQDN): ")).trim();
15
+ const proxmoxPort = Number.parseInt((await rl.question("Proxmox port [8006]: ")).trim() || "8006", 10);
16
+ const proxmoxUser = (await rl.question("Proxmox user (without realm, e.g. svc_mcp): ")).trim();
17
+ const proxmoxRealm = (await rl.question("Proxmox realm [pve]: ")).trim() || "pve";
18
+ const tokenName = (await rl.question("API token name (e.g. nandi-mcp): ")).trim();
19
+ const tokenSecret = (await rl.question("API token secret: ")).trim();
20
+ const allowInsecureTls = ((await rl.question("Allow insecure TLS for self-signed cert? [no]: ")).trim() || "no")
21
+ .toLowerCase()
22
+ .startsWith("y");
23
+ const sshHost = (await rl.question("SSH host [same as Proxmox host]: ")).trim() || proxmoxHost;
24
+ const sshPort = Number.parseInt((await rl.question("SSH port [22]: ")).trim() || "22", 10);
25
+ const sshUser = (await rl.question("SSH user [root]: ")).trim() || "root";
26
+ const sshKeyPath = (await rl.question("SSH private key path [~/.ssh/id_ed25519]: ")).trim() ||
27
+ resolve(process.env.USERPROFILE ?? process.env.HOME ?? ".", ".ssh", "id_ed25519");
28
+ rl.close();
29
+ return runtimeConfigSchema.parse({
30
+ proxmoxHost,
31
+ proxmoxPort,
32
+ proxmoxUser,
33
+ proxmoxRealm,
34
+ tokenName,
35
+ tokenSecret,
36
+ allowInsecureTls,
37
+ sshHost,
38
+ sshPort,
39
+ sshUser,
40
+ sshKeyPath
41
+ });
42
+ };
43
+ const validatePrereqs = async () => {
44
+ const checks = [];
45
+ checks.push({
46
+ check: "Node.js",
47
+ ok: Number(process.versions.node.split(".")[0]) >= 20,
48
+ detail: `Detected ${process.versions.node}`
49
+ });
50
+ const npmUserAgent = process.env.npm_config_user_agent;
51
+ checks.push({
52
+ check: "npm",
53
+ ok: Boolean(npmUserAgent),
54
+ detail: npmUserAgent ?? "npm user agent not detected"
55
+ });
56
+ return checks;
57
+ };
58
+ const writeVscodeConfig = async () => {
59
+ const vscodeDir = resolve(process.cwd(), ".vscode");
60
+ await mkdir(vscodeDir, { recursive: true });
61
+ const mcpPath = resolve(vscodeDir, "mcp.json");
62
+ const resolvedConfigPath = resolve(process.cwd(), ".nandi-proxmox-mcp", "config.json");
63
+ let config = buildWorkspaceMcpConfig(resolvedConfigPath);
64
+ let migratedLegacy = false;
65
+ try {
66
+ const existing = await readFile(mcpPath, "utf8");
67
+ const normalized = normalizeMcpConfigDocument(existing);
68
+ config = normalized.normalized;
69
+ migratedLegacy = normalized.migratedLegacy;
70
+ }
71
+ catch {
72
+ // No previous config or invalid JSON, fall back to generated structure.
73
+ }
74
+ config.servers["nandi-proxmox-mcp"] = {
75
+ command: "npx",
76
+ args: ["nandi-proxmox-mcp", "run"],
77
+ env: {
78
+ NANDI_PROXMOX_CONFIG: resolvedConfigPath
79
+ }
80
+ };
81
+ const validation = validateMcpConfig(config);
82
+ if (!validation.ok) {
83
+ throw new Error(`Generated MCP config failed validation: ${validation.errors.join(" | ")}`);
84
+ }
85
+ await writeFile(mcpPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
86
+ if (migratedLegacy) {
87
+ process.stdout.write("Migrated legacy `.vscode/mcp.json` format to root `servers` format.\n");
88
+ }
89
+ };
90
+ const connectivityChecks = async (config) => {
91
+ const client = new ProxmoxClient(config);
92
+ const checks = [];
93
+ try {
94
+ const nodes = await client.listNodes();
95
+ checks.push({
96
+ check: "Proxmox API token connectivity",
97
+ ok: true,
98
+ detail: `Connected. Nodes discovered: ${nodes.length}`
99
+ });
100
+ }
101
+ catch (error) {
102
+ checks.push({
103
+ check: "Proxmox API token connectivity",
104
+ ok: false,
105
+ detail: error instanceof Error ? error.message : "Unknown Proxmox connectivity error"
106
+ });
107
+ }
108
+ try {
109
+ const ssh = await runSshBatch({
110
+ host: config.sshHost,
111
+ port: config.sshPort,
112
+ user: config.sshUser,
113
+ keyPath: config.sshKeyPath,
114
+ timeoutMs: 12_000
115
+ }, "echo ssh-batch-ok");
116
+ checks.push({
117
+ check: "SSH batch (non-interactive)",
118
+ ok: ssh.exitCode === 0 && ssh.stdout.includes("ssh-batch-ok"),
119
+ detail: ssh.exitCode === 0 ? "Batch SSH command succeeded" : ssh.stderr.trim()
120
+ });
121
+ }
122
+ catch (error) {
123
+ checks.push({
124
+ check: "SSH batch (non-interactive)",
125
+ ok: false,
126
+ detail: error instanceof Error ? error.message : "Unknown SSH batch error"
127
+ });
128
+ }
129
+ return checks;
130
+ };
131
+ export const runSetup = async () => {
132
+ process.stdout.write("nandi-proxmox-mcp setup wizard\n");
133
+ process.stdout.write("The API token is NOT provided by npm or MCP. You must create it in your own Proxmox server.\n\n");
134
+ const prereq = await validatePrereqs();
135
+ printReport("Prerequisites", prereq);
136
+ const config = await ask();
137
+ await mkdir(defaultConfigDir, { recursive: true });
138
+ await writeFile(defaultConfigPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
139
+ await writeVscodeConfig();
140
+ const connectivity = await connectivityChecks(config);
141
+ printReport("Connectivity", connectivity);
142
+ const allOk = [...prereq, ...connectivity].every((item) => item.ok);
143
+ process.stdout.write(`\nFinal status: ${allOk ? "GREEN" : "RED"}\n`);
144
+ process.stdout.write(`Local config created at: ${defaultConfigPath}\n`);
145
+ process.stdout.write("\nNext steps for VS Code/Codex:\n");
146
+ process.stdout.write("1. Open MCP settings and verify `nandi-proxmox-mcp` appears.\n");
147
+ process.stdout.write("2. If needed, use `.vscode/mcp.json` generated by setup as your custom server source.\n");
148
+ process.stdout.write("3. Run `nandi-proxmox-mcp doctor --check mcp-config,nodes,vms,cts,node-status,remote-op`.\n");
149
+ };
150
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/cli/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type RuntimeConfig } from "./validate.js";
2
+ export declare const loadEnvConfig: () => RuntimeConfig;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAGxE,eAAO,MAAM,aAAa,QAAO,aAgBhC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { runtimeConfigSchema } from "./validate.js";
2
+ import { parseBool, parseInteger } from "../utils/parsing.js";
3
+ export const loadEnvConfig = () => {
4
+ const candidate = {
5
+ proxmoxHost: process.env.PROXMOX_HOST,
6
+ proxmoxPort: parseInteger(process.env.PROXMOX_PORT, 8006),
7
+ proxmoxUser: process.env.PROXMOX_USER,
8
+ proxmoxRealm: process.env.PROXMOX_REALM,
9
+ tokenName: process.env.PROXMOX_TOKEN_NAME,
10
+ tokenSecret: process.env.PROXMOX_TOKEN_SECRET,
11
+ allowInsecureTls: parseBool(process.env.PROXMOX_ALLOW_INSECURE_TLS, false),
12
+ sshHost: process.env.PROXMOX_SSH_HOST ?? process.env.PROXMOX_HOST,
13
+ sshPort: parseInteger(process.env.PROXMOX_SSH_PORT, 22),
14
+ sshUser: process.env.PROXMOX_SSH_USER ?? "root",
15
+ sshKeyPath: process.env.PROXMOX_SSH_KEY_PATH ?? ""
16
+ };
17
+ return runtimeConfigSchema.parse(candidate);
18
+ };
19
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAsB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,aAAa,GAAG,GAAkB,EAAE;IAC/C,MAAM,SAAS,GAAG;QAChB,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACrC,WAAW,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC;QACzD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACrC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;QACvC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QACzC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAC7C,gBAAgB,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,KAAK,CAAC;QAC1E,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QACjE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACvD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,MAAM;QAC/C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;KACnD,CAAC;IAEF,OAAO,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type RuntimeConfig } from "./validate.js";
2
+ export declare const defaultConfigPath: () => string;
3
+ export declare const loadFileConfig: (explicitPath?: string) => Promise<RuntimeConfig>;
4
+ //# sourceMappingURL=fileConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileConfig.d.ts","sourceRoot":"","sources":["../../../src/config/fileConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAExE,eAAO,MAAM,iBAAiB,QAAO,MAEpC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,aAAa,CAKjF,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { runtimeConfigSchema } from "./validate.js";
4
+ export const defaultConfigPath = () => {
5
+ return resolve(process.cwd(), ".nandi-proxmox-mcp", "config.json");
6
+ };
7
+ export const loadFileConfig = async (explicitPath) => {
8
+ const path = explicitPath ?? process.env.NANDI_PROXMOX_CONFIG ?? defaultConfigPath();
9
+ const raw = await readFile(path, "utf8");
10
+ const parsed = JSON.parse(raw);
11
+ return runtimeConfigSchema.parse(parsed);
12
+ };
13
+ //# sourceMappingURL=fileConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileConfig.js","sourceRoot":"","sources":["../../../src/config/fileConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAsB,MAAM,eAAe,CAAC;AAExE,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAW,EAAE;IAC5C,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC;AACrE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,YAAqB,EAA0B,EAAE;IACpF,MAAM,IAAI,GAAG,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,iBAAiB,EAAE,CAAC;IACrF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IAC1C,OAAO,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ export type McpServerEntry = {
2
+ command: string;
3
+ args: string[];
4
+ env?: Record<string, string>;
5
+ };
6
+ export type McpConfigFile = {
7
+ servers: Record<string, McpServerEntry>;
8
+ };
9
+ export type McpManifest = {
10
+ schema_version: string;
11
+ id: string;
12
+ display_name: string;
13
+ description: string;
14
+ transport: "stdio";
15
+ runtime: McpServerEntry;
16
+ docs: {
17
+ quickstart: string;
18
+ security: string;
19
+ troubleshooting: string;
20
+ };
21
+ };
22
+ export declare const serverId = "nandi-proxmox-mcp";
23
+ export declare const buildWorkspaceMcpConfig: (configPath: string) => McpConfigFile;
24
+ export declare const normalizeMcpConfigDocument: (raw: string) => {
25
+ normalized: McpConfigFile;
26
+ migratedLegacy: boolean;
27
+ };
28
+ export declare const validateMcpConfig: (value: unknown) => {
29
+ ok: boolean;
30
+ errors: string[];
31
+ };
32
+ export declare const validateMcpManifest: (value: unknown) => {
33
+ ok: boolean;
34
+ errors: string[];
35
+ };
36
+ //# sourceMappingURL=installDescriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installDescriptor.d.ts","sourceRoot":"","sources":["../../../src/config/installDescriptor.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAE5C,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,KAAG,aAU3D,CAAC;AAEH,eAAO,MAAM,0BAA0B,GAAI,KAAK,MAAM,KAAG;IACvD,UAAU,EAAE,aAAa,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC;CAiCzB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAkCjF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAmBnF,CAAC"}