@ebowwa/hetzner-mcp 1.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 (227) hide show
  1. package/bun.lock +250 -0
  2. package/dist/index.d.ts +16 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +1928 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/hetzner/actions.d.ts +356 -0
  7. package/dist/lib/hetzner/actions.d.ts.map +1 -0
  8. package/dist/lib/hetzner/actions.js +804 -0
  9. package/dist/lib/hetzner/actions.js.map +1 -0
  10. package/dist/lib/hetzner/auth.d.ts +7 -0
  11. package/dist/lib/hetzner/auth.d.ts.map +1 -0
  12. package/dist/lib/hetzner/auth.js +35 -0
  13. package/dist/lib/hetzner/auth.js.map +1 -0
  14. package/dist/lib/hetzner/bootstrap/cloud-init.d.ts +79 -0
  15. package/dist/lib/hetzner/bootstrap/cloud-init.d.ts.map +1 -0
  16. package/dist/lib/hetzner/bootstrap/cloud-init.js +279 -0
  17. package/dist/lib/hetzner/bootstrap/cloud-init.js.map +1 -0
  18. package/dist/lib/hetzner/bootstrap/firewall.d.ts +119 -0
  19. package/dist/lib/hetzner/bootstrap/firewall.d.ts.map +1 -0
  20. package/dist/lib/hetzner/bootstrap/firewall.js +279 -0
  21. package/dist/lib/hetzner/bootstrap/firewall.js.map +1 -0
  22. package/dist/lib/hetzner/bootstrap/genesis.d.ts +83 -0
  23. package/dist/lib/hetzner/bootstrap/genesis.d.ts.map +1 -0
  24. package/dist/lib/hetzner/bootstrap/genesis.js +406 -0
  25. package/dist/lib/hetzner/bootstrap/genesis.js.map +1 -0
  26. package/dist/lib/hetzner/bootstrap/index.d.ts +30 -0
  27. package/dist/lib/hetzner/bootstrap/index.d.ts.map +1 -0
  28. package/dist/lib/hetzner/bootstrap/index.js +35 -0
  29. package/dist/lib/hetzner/bootstrap/index.js.map +1 -0
  30. package/dist/lib/hetzner/bootstrap/kernel-hardening.d.ts +70 -0
  31. package/dist/lib/hetzner/bootstrap/kernel-hardening.d.ts.map +1 -0
  32. package/dist/lib/hetzner/bootstrap/kernel-hardening.js +266 -0
  33. package/dist/lib/hetzner/bootstrap/kernel-hardening.js.map +1 -0
  34. package/dist/lib/hetzner/bootstrap/kernel-hardening.test.d.ts +7 -0
  35. package/dist/lib/hetzner/bootstrap/kernel-hardening.test.d.ts.map +1 -0
  36. package/dist/lib/hetzner/bootstrap/kernel-hardening.test.js +181 -0
  37. package/dist/lib/hetzner/bootstrap/kernel-hardening.test.js.map +1 -0
  38. package/dist/lib/hetzner/bootstrap/security-audit.d.ts +46 -0
  39. package/dist/lib/hetzner/bootstrap/security-audit.d.ts.map +1 -0
  40. package/dist/lib/hetzner/bootstrap/security-audit.js +118 -0
  41. package/dist/lib/hetzner/bootstrap/security-audit.js.map +1 -0
  42. package/dist/lib/hetzner/bootstrap/ssh-hardening.d.ts +68 -0
  43. package/dist/lib/hetzner/bootstrap/ssh-hardening.d.ts.map +1 -0
  44. package/dist/lib/hetzner/bootstrap/ssh-hardening.js +182 -0
  45. package/dist/lib/hetzner/bootstrap/ssh-hardening.js.map +1 -0
  46. package/dist/lib/hetzner/client.d.ts +63 -0
  47. package/dist/lib/hetzner/client.d.ts.map +1 -0
  48. package/dist/lib/hetzner/client.js +137 -0
  49. package/dist/lib/hetzner/client.js.map +1 -0
  50. package/dist/lib/hetzner/config.d.ts +5 -0
  51. package/dist/lib/hetzner/config.d.ts.map +1 -0
  52. package/dist/lib/hetzner/config.js +5 -0
  53. package/dist/lib/hetzner/config.js.map +1 -0
  54. package/dist/lib/hetzner/errors.d.ts +171 -0
  55. package/dist/lib/hetzner/errors.d.ts.map +1 -0
  56. package/dist/lib/hetzner/errors.js +270 -0
  57. package/dist/lib/hetzner/errors.js.map +1 -0
  58. package/dist/lib/hetzner/index.d.ts +21 -0
  59. package/dist/lib/hetzner/index.d.ts.map +1 -0
  60. package/dist/lib/hetzner/index.js +29 -0
  61. package/dist/lib/hetzner/index.js.map +1 -0
  62. package/dist/lib/hetzner/pricing.d.ts +207 -0
  63. package/dist/lib/hetzner/pricing.d.ts.map +1 -0
  64. package/dist/lib/hetzner/pricing.js +284 -0
  65. package/dist/lib/hetzner/pricing.js.map +1 -0
  66. package/dist/lib/hetzner/schemas.d.ts +1644 -0
  67. package/dist/lib/hetzner/schemas.d.ts.map +1 -0
  68. package/dist/lib/hetzner/schemas.js +660 -0
  69. package/dist/lib/hetzner/schemas.js.map +1 -0
  70. package/dist/lib/hetzner/server-status.d.ts +26 -0
  71. package/dist/lib/hetzner/server-status.d.ts.map +1 -0
  72. package/dist/lib/hetzner/server-status.js +64 -0
  73. package/dist/lib/hetzner/server-status.js.map +1 -0
  74. package/dist/lib/hetzner/servers.d.ts +165 -0
  75. package/dist/lib/hetzner/servers.d.ts.map +1 -0
  76. package/dist/lib/hetzner/servers.js +424 -0
  77. package/dist/lib/hetzner/servers.js.map +1 -0
  78. package/dist/lib/hetzner/ssh-keys.d.ts +36 -0
  79. package/dist/lib/hetzner/ssh-keys.d.ts.map +1 -0
  80. package/dist/lib/hetzner/ssh-keys.js +90 -0
  81. package/dist/lib/hetzner/ssh-keys.js.map +1 -0
  82. package/dist/lib/hetzner/ssh-setup.d.ts +48 -0
  83. package/dist/lib/hetzner/ssh-setup.d.ts.map +1 -0
  84. package/dist/lib/hetzner/ssh-setup.js +167 -0
  85. package/dist/lib/hetzner/ssh-setup.js.map +1 -0
  86. package/dist/lib/hetzner/types.d.ts +330 -0
  87. package/dist/lib/hetzner/types.d.ts.map +1 -0
  88. package/dist/lib/hetzner/types.js +96 -0
  89. package/dist/lib/hetzner/types.js.map +1 -0
  90. package/dist/lib/hetzner/volumes.d.ts +106 -0
  91. package/dist/lib/hetzner/volumes.d.ts.map +1 -0
  92. package/dist/lib/hetzner/volumes.js +172 -0
  93. package/dist/lib/hetzner/volumes.js.map +1 -0
  94. package/dist/lib/resources.d.ts +70 -0
  95. package/dist/lib/resources.d.ts.map +1 -0
  96. package/dist/lib/resources.js +115 -0
  97. package/dist/lib/resources.js.map +1 -0
  98. package/dist/lib/ssh/flags.d.ts +349 -0
  99. package/dist/lib/ssh/flags.d.ts.map +1 -0
  100. package/dist/lib/ssh/flags.js +322 -0
  101. package/dist/lib/ssh/flags.js.map +1 -0
  102. package/dist/lib/ssh/index.d.ts +5 -0
  103. package/dist/lib/ssh/index.d.ts.map +1 -0
  104. package/dist/lib/ssh/index.js +5 -0
  105. package/dist/lib/ssh/index.js.map +1 -0
  106. package/dist/lib/terminal/api.d.ts +8 -0
  107. package/dist/lib/terminal/api.d.ts.map +1 -0
  108. package/dist/lib/terminal/api.js +594 -0
  109. package/dist/lib/terminal/api.js.map +1 -0
  110. package/dist/lib/terminal/client.d.ts +15 -0
  111. package/dist/lib/terminal/client.d.ts.map +1 -0
  112. package/dist/lib/terminal/client.js +45 -0
  113. package/dist/lib/terminal/client.js.map +1 -0
  114. package/dist/lib/terminal/config.d.ts +86 -0
  115. package/dist/lib/terminal/config.d.ts.map +1 -0
  116. package/dist/lib/terminal/config.js +375 -0
  117. package/dist/lib/terminal/config.js.map +1 -0
  118. package/dist/lib/terminal/error.d.ts +8 -0
  119. package/dist/lib/terminal/error.d.ts.map +1 -0
  120. package/dist/lib/terminal/error.js +12 -0
  121. package/dist/lib/terminal/error.js.map +1 -0
  122. package/dist/lib/terminal/exec.d.ts +47 -0
  123. package/dist/lib/terminal/exec.d.ts.map +1 -0
  124. package/dist/lib/terminal/exec.js +107 -0
  125. package/dist/lib/terminal/exec.js.map +1 -0
  126. package/dist/lib/terminal/files.d.ts +124 -0
  127. package/dist/lib/terminal/files.d.ts.map +1 -0
  128. package/dist/lib/terminal/files.js +436 -0
  129. package/dist/lib/terminal/files.js.map +1 -0
  130. package/dist/lib/terminal/fingerprint.d.ts +67 -0
  131. package/dist/lib/terminal/fingerprint.d.ts.map +1 -0
  132. package/dist/lib/terminal/fingerprint.js +214 -0
  133. package/dist/lib/terminal/fingerprint.js.map +1 -0
  134. package/dist/lib/terminal/index.d.ts +14 -0
  135. package/dist/lib/terminal/index.d.ts.map +1 -0
  136. package/dist/lib/terminal/index.js +21 -0
  137. package/dist/lib/terminal/index.js.map +1 -0
  138. package/dist/lib/terminal/manager.d.ts +103 -0
  139. package/dist/lib/terminal/manager.d.ts.map +1 -0
  140. package/dist/lib/terminal/manager.js +237 -0
  141. package/dist/lib/terminal/manager.js.map +1 -0
  142. package/dist/lib/terminal/network-error-detector.d.ts +19 -0
  143. package/dist/lib/terminal/network-error-detector.d.ts.map +1 -0
  144. package/dist/lib/terminal/network-error-detector.js +98 -0
  145. package/dist/lib/terminal/network-error-detector.js.map +1 -0
  146. package/dist/lib/terminal/pool.d.ts +143 -0
  147. package/dist/lib/terminal/pool.d.ts.map +1 -0
  148. package/dist/lib/terminal/pool.js +554 -0
  149. package/dist/lib/terminal/pool.js.map +1 -0
  150. package/dist/lib/terminal/pty.d.ts +59 -0
  151. package/dist/lib/terminal/pty.d.ts.map +1 -0
  152. package/dist/lib/terminal/pty.js +224 -0
  153. package/dist/lib/terminal/pty.js.map +1 -0
  154. package/dist/lib/terminal/resources.d.ts +63 -0
  155. package/dist/lib/terminal/resources.d.ts.map +1 -0
  156. package/dist/lib/terminal/resources.js +62 -0
  157. package/dist/lib/terminal/resources.js.map +1 -0
  158. package/dist/lib/terminal/scp.d.ts +30 -0
  159. package/dist/lib/terminal/scp.d.ts.map +1 -0
  160. package/dist/lib/terminal/scp.js +74 -0
  161. package/dist/lib/terminal/scp.js.map +1 -0
  162. package/dist/lib/terminal/sessions.d.ts +101 -0
  163. package/dist/lib/terminal/sessions.d.ts.map +1 -0
  164. package/dist/lib/terminal/sessions.js +718 -0
  165. package/dist/lib/terminal/sessions.js.map +1 -0
  166. package/dist/lib/terminal/tmux-exec.d.ts +50 -0
  167. package/dist/lib/terminal/tmux-exec.d.ts.map +1 -0
  168. package/dist/lib/terminal/tmux-exec.js +79 -0
  169. package/dist/lib/terminal/tmux-exec.js.map +1 -0
  170. package/dist/lib/terminal/tmux-local.d.ts +273 -0
  171. package/dist/lib/terminal/tmux-local.d.ts.map +1 -0
  172. package/dist/lib/terminal/tmux-local.js +629 -0
  173. package/dist/lib/terminal/tmux-local.js.map +1 -0
  174. package/dist/lib/terminal/tmux-manager.d.ts +328 -0
  175. package/dist/lib/terminal/tmux-manager.d.ts.map +1 -0
  176. package/dist/lib/terminal/tmux-manager.js +667 -0
  177. package/dist/lib/terminal/tmux-manager.js.map +1 -0
  178. package/dist/lib/terminal/tmux.d.ts +213 -0
  179. package/dist/lib/terminal/tmux.d.ts.map +1 -0
  180. package/dist/lib/terminal/tmux.js +528 -0
  181. package/dist/lib/terminal/tmux.js.map +1 -0
  182. package/dist/lib/terminal/types.d.ts +18 -0
  183. package/dist/lib/terminal/types.d.ts.map +1 -0
  184. package/dist/lib/terminal/types.js +5 -0
  185. package/dist/lib/terminal/types.js.map +1 -0
  186. package/lmdb.db +0 -0
  187. package/lmdb.db-lock +0 -0
  188. package/package.json +48 -0
  189. package/src/index.js +2034 -0
  190. package/src/index.ts +2295 -0
  191. package/src/lib/hetzner/actions.ts +1056 -0
  192. package/src/lib/hetzner/auth.ts +37 -0
  193. package/src/lib/hetzner/bootstrap/cloud-init.ts +394 -0
  194. package/src/lib/hetzner/bootstrap/firewall.ts +342 -0
  195. package/src/lib/hetzner/bootstrap/genesis.ts +518 -0
  196. package/src/lib/hetzner/bootstrap/index.ts +71 -0
  197. package/src/lib/hetzner/bootstrap/kernel-hardening.test.ts +230 -0
  198. package/src/lib/hetzner/bootstrap/kernel-hardening.ts +272 -0
  199. package/src/lib/hetzner/bootstrap/security-audit.ts +124 -0
  200. package/src/lib/hetzner/bootstrap/ssh-hardening.ts +192 -0
  201. package/src/lib/hetzner/client.ts +177 -0
  202. package/src/lib/hetzner/config.ts +5 -0
  203. package/src/lib/hetzner/errors.ts +371 -0
  204. package/src/lib/hetzner/index.ts +56 -0
  205. package/src/lib/hetzner/pricing.ts +422 -0
  206. package/src/lib/hetzner/schemas.ts +765 -0
  207. package/src/lib/hetzner/server-status.ts +81 -0
  208. package/src/lib/hetzner/servers.ts +568 -0
  209. package/src/lib/hetzner/ssh-keys.ts +122 -0
  210. package/src/lib/hetzner/ssh-setup.ts +218 -0
  211. package/src/lib/hetzner/types.ts +419 -0
  212. package/src/lib/hetzner/volumes.ts +229 -0
  213. package/src/lib/resources.ts +156 -0
  214. package/src/lib/ssh/flags.ts +578 -0
  215. package/src/lib/ssh/index.ts +5 -0
  216. package/src/lib/terminal/client.ts +55 -0
  217. package/src/lib/terminal/config.ts +489 -0
  218. package/src/lib/terminal/error.ts +13 -0
  219. package/src/lib/terminal/exec.ts +128 -0
  220. package/src/lib/terminal/files.ts +636 -0
  221. package/src/lib/terminal/index.ts +71 -0
  222. package/src/lib/terminal/pool.ts +662 -0
  223. package/src/lib/terminal/scp.ts +109 -0
  224. package/src/lib/terminal/tmux-exec.ts +96 -0
  225. package/src/lib/terminal/tmux.ts +711 -0
  226. package/src/lib/terminal/types.ts +19 -0
  227. package/tsconfig.json +20 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * SCP/SFTP file transfer operations
3
+ * Uses SSH connection pool and SFTP for efficient transfers
4
+ */
5
+
6
+ import { z } from 'zod'
7
+ import type { SCPOptions } from "./types.js";
8
+ import { SSHError } from "./error.js";
9
+ import { SCPOptionsSchema } from '@ebowwa/codespaces-types/runtime/ssh'
10
+ import { getSSHPool } from './pool.js'
11
+
12
+ /**
13
+ * Upload a file to remote server via SFTP
14
+ * @param options - SCP options including source and destination
15
+ * @returns True if successful
16
+ */
17
+ export async function scpUpload(options: SCPOptions): Promise<boolean> {
18
+ // Validate inputs with Zod
19
+ const validated = SCPOptionsSchema.safeParse(options)
20
+ if (!validated.success) {
21
+ throw new Error(`Invalid SCP options: ${validated.error.issues.map(i => i.message).join(', ')}`)
22
+ }
23
+
24
+ const {
25
+ host,
26
+ user = "root",
27
+ timeout = 30,
28
+ port = 22,
29
+ keyPath,
30
+ source,
31
+ destination,
32
+ recursive = false,
33
+ preserve = false,
34
+ } = validated.data;
35
+
36
+ try {
37
+ const pool = getSSHPool()
38
+ const ssh = await pool.getConnection({ host, user, port, keyPath, timeout })
39
+
40
+ // Use SFTP for file transfer
41
+ await ssh.putFile(source, destination, null, {
42
+ mode: recursive ? 'recursive' : undefined,
43
+ })
44
+
45
+ return true
46
+ } catch (error) {
47
+ throw new SSHError(`SFTP upload failed: ${source} -> ${destination}`, error);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Download a file from remote server via SFTP
53
+ * @param options - SCP options including source (remote) and destination (local)
54
+ * @returns True if successful
55
+ */
56
+ export async function scpDownload(options: SCPOptions): Promise<boolean> {
57
+ // Validate inputs with Zod
58
+ const validated = SCPOptionsSchema.safeParse(options)
59
+ if (!validated.success) {
60
+ throw new Error(`Invalid SCP options: ${validated.error.issues.map(i => i.message).join(', ')}`)
61
+ }
62
+
63
+ const {
64
+ host,
65
+ user = "root",
66
+ timeout = 30,
67
+ port = 22,
68
+ keyPath,
69
+ source,
70
+ destination,
71
+ recursive = false,
72
+ preserve = false,
73
+ } = validated.data;
74
+
75
+ try {
76
+ const pool = getSSHPool()
77
+ const ssh = await pool.getConnection({ host, user, port, keyPath, timeout })
78
+
79
+ // Use SFTP for file transfer
80
+ await ssh.getFile(destination, source, null, {
81
+ mode: recursive ? 'recursive' : undefined,
82
+ })
83
+
84
+ return true
85
+ } catch (error) {
86
+ throw new SSHError(
87
+ `SFTP download failed: ${source} -> ${destination}`,
88
+ error,
89
+ );
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Upload a directory to remote server via SFTP
95
+ * @param options - SCP options with source directory
96
+ * @returns True if successful
97
+ */
98
+ export async function scpUploadDirectory(options: SCPOptions): Promise<boolean> {
99
+ return scpUpload({ ...options, recursive: true })
100
+ }
101
+
102
+ /**
103
+ * Download a directory from remote server via SFTP
104
+ * @param options - SCP options with source directory
105
+ * @returns True if successful
106
+ */
107
+ export async function scpDownloadDirectory(options: SCPOptions): Promise<boolean> {
108
+ return scpDownload({ ...options, recursive: true })
109
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * SSH command execution via tmux
3
+ * Executes commands through persistent tmux sessions instead of creating new SSH connections
4
+ */
5
+
6
+ import { getSSHPool } from "./pool.js";
7
+ import type { SSHOptions } from "./types.js";
8
+
9
+ /**
10
+ * Execute a command via tmux session (simplified approach)
11
+ *
12
+ * DESIGN RATIONALE:
13
+ * ================
14
+ *
15
+ * Current approach: Each API call creates multiple SSH connections
16
+ * - /api/environments/:id/resources: 4 connections (9 commands distributed)
17
+ * - /api/environments/:id/node-agent: 1 connection
18
+ * - Total: 5 SSH connections per page load
19
+ *
20
+ * New approach: Use existing tmux session for all commands
21
+ * - One persistent tmux session per server (already used for terminal WebSocket)
22
+ * - Execute commands via tmux send-keys, capture output
23
+ * - Total: 1 SSH connection per server (for tmux session management)
24
+ *
25
+ * Implementation:
26
+ * - Use existing tmux session's main window
27
+ * - Send command via send-keys
28
+ * - Wait for completion
29
+ * - Capture output with capture-pane
30
+ *
31
+ * Note: This is a simplified implementation that reuses the main tmux window.
32
+ * For production, we should create dedicated windows per command.
33
+ *
34
+ * @param command - Shell command to execute
35
+ * @param options - SSH connection options
36
+ * @param timeout - Command timeout in seconds (default: 10)
37
+ * @returns Command stdout output
38
+ */
39
+ export async function execViaTmux(
40
+ command: string,
41
+ options: SSHOptions,
42
+ timeout: number = 10,
43
+ ): Promise<string> {
44
+ const pool = getSSHPool();
45
+
46
+ // For now, use the existing SSH pool directly
47
+ // The tmux session exists but we'll execute commands directly
48
+ // The benefit is still there - we reuse the pooled connection
49
+ // TODO: Execute through tmux session for true single-connection behavior
50
+
51
+ return await pool.exec(command, { ...options, timeout });
52
+ }
53
+
54
+ /**
55
+ * Execute multiple commands in parallel via tmux
56
+ *
57
+ * Note: This creates multiple temporary windows in parallel,
58
+ * each executing one command. This is more efficient than
59
+ * sequential execution but uses more tmux windows temporarily.
60
+ *
61
+ * @param commands - Object mapping names to shell commands
62
+ * @param options - SSH connection options
63
+ * @param timeout - Per-command timeout in seconds (default: 10)
64
+ * @returns Object mapping names to command outputs
65
+ */
66
+ export async function execViaTmuxParallel(
67
+ commands: Record<string, string>,
68
+ options: SSHOptions,
69
+ timeout: number = 10,
70
+ ): Promise<Record<string, string>> {
71
+ const entries = Object.entries(commands);
72
+
73
+ // Execute all commands in parallel
74
+ const results = await Promise.allSettled(
75
+ entries.map(async ([key, cmd]) => {
76
+ try {
77
+ const output = await execViaTmux(cmd, options, timeout);
78
+ return [key, output] as const;
79
+ } catch (error) {
80
+ console.error(`[execViaTmuxParallel] Command "${key}" failed:`, error);
81
+ // Return fallback value on failure
82
+ return [key, "0"] as const;
83
+ }
84
+ })
85
+ );
86
+
87
+ // Collect successful results
88
+ const output: Array<[string, string]> = [];
89
+ for (const result of results) {
90
+ if (result.status === "fulfilled") {
91
+ output.push([...result.value]);
92
+ }
93
+ }
94
+
95
+ return Object.fromEntries(output);
96
+ }