ssh-agent-workspace 1.0.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 (188) hide show
  1. package/README.md +319 -0
  2. package/dist/__tests__/SSHManager.test.d.ts +2 -0
  3. package/dist/__tests__/SSHManager.test.d.ts.map +1 -0
  4. package/dist/__tests__/SSHManager.test.js +134 -0
  5. package/dist/__tests__/SSHManager.test.js.map +1 -0
  6. package/dist/__tests__/SessionManager.test.d.ts +2 -0
  7. package/dist/__tests__/SessionManager.test.d.ts.map +1 -0
  8. package/dist/__tests__/SessionManager.test.js +141 -0
  9. package/dist/__tests__/SessionManager.test.js.map +1 -0
  10. package/dist/__tests__/StorageManager.test.d.ts +2 -0
  11. package/dist/__tests__/StorageManager.test.d.ts.map +1 -0
  12. package/dist/__tests__/StorageManager.test.js +171 -0
  13. package/dist/__tests__/StorageManager.test.js.map +1 -0
  14. package/dist/__tests__/ansi.test.d.ts +2 -0
  15. package/dist/__tests__/ansi.test.d.ts.map +1 -0
  16. package/dist/__tests__/ansi.test.js +41 -0
  17. package/dist/__tests__/ansi.test.js.map +1 -0
  18. package/dist/__tests__/security.test.d.ts +2 -0
  19. package/dist/__tests__/security.test.d.ts.map +1 -0
  20. package/dist/__tests__/security.test.js +87 -0
  21. package/dist/__tests__/security.test.js.map +1 -0
  22. package/dist/__tests__/validation.test.d.ts +2 -0
  23. package/dist/__tests__/validation.test.d.ts.map +1 -0
  24. package/dist/__tests__/validation.test.js +23 -0
  25. package/dist/__tests__/validation.test.js.map +1 -0
  26. package/dist/core/HostSecurityManager.d.ts +25 -0
  27. package/dist/core/HostSecurityManager.d.ts.map +1 -0
  28. package/dist/core/HostSecurityManager.js +76 -0
  29. package/dist/core/HostSecurityManager.js.map +1 -0
  30. package/dist/core/SSHManager.d.ts +48 -0
  31. package/dist/core/SSHManager.d.ts.map +1 -0
  32. package/dist/core/SSHManager.js +288 -0
  33. package/dist/core/SSHManager.js.map +1 -0
  34. package/dist/core/SessionManager.d.ts +15 -0
  35. package/dist/core/SessionManager.d.ts.map +1 -0
  36. package/dist/core/SessionManager.js +96 -0
  37. package/dist/core/SessionManager.js.map +1 -0
  38. package/dist/core/StorageManager.d.ts +27 -0
  39. package/dist/core/StorageManager.d.ts.map +1 -0
  40. package/dist/core/StorageManager.js +87 -0
  41. package/dist/core/StorageManager.js.map +1 -0
  42. package/dist/core/TmuxManager.d.ts +21 -0
  43. package/dist/core/TmuxManager.d.ts.map +1 -0
  44. package/dist/core/TmuxManager.js +110 -0
  45. package/dist/core/TmuxManager.js.map +1 -0
  46. package/dist/core/ToolConfigManager.d.ts +15 -0
  47. package/dist/core/ToolConfigManager.d.ts.map +1 -0
  48. package/dist/core/ToolConfigManager.js +57 -0
  49. package/dist/core/ToolConfigManager.js.map +1 -0
  50. package/dist/index.d.ts +3 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +169 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/server.d.ts +44 -0
  55. package/dist/server.d.ts.map +1 -0
  56. package/dist/server.js +152 -0
  57. package/dist/server.js.map +1 -0
  58. package/dist/tools/backup.d.ts +74 -0
  59. package/dist/tools/backup.d.ts.map +1 -0
  60. package/dist/tools/backup.js +152 -0
  61. package/dist/tools/backup.js.map +1 -0
  62. package/dist/tools/connect.d.ts +46 -0
  63. package/dist/tools/connect.d.ts.map +1 -0
  64. package/dist/tools/connect.js +235 -0
  65. package/dist/tools/connect.js.map +1 -0
  66. package/dist/tools/connection_status.d.ts +39 -0
  67. package/dist/tools/connection_status.d.ts.map +1 -0
  68. package/dist/tools/connection_status.js +67 -0
  69. package/dist/tools/connection_status.js.map +1 -0
  70. package/dist/tools/db_query.d.ts +103 -0
  71. package/dist/tools/db_query.d.ts.map +1 -0
  72. package/dist/tools/db_query.js +194 -0
  73. package/dist/tools/db_query.js.map +1 -0
  74. package/dist/tools/deploy.d.ts +127 -0
  75. package/dist/tools/deploy.d.ts.map +1 -0
  76. package/dist/tools/deploy.js +201 -0
  77. package/dist/tools/deploy.js.map +1 -0
  78. package/dist/tools/disconnect.d.ts +46 -0
  79. package/dist/tools/disconnect.d.ts.map +1 -0
  80. package/dist/tools/disconnect.js +77 -0
  81. package/dist/tools/disconnect.js.map +1 -0
  82. package/dist/tools/exec.d.ts +69 -0
  83. package/dist/tools/exec.d.ts.map +1 -0
  84. package/dist/tools/exec.js +188 -0
  85. package/dist/tools/exec.js.map +1 -0
  86. package/dist/tools/group_exec.d.ts +80 -0
  87. package/dist/tools/group_exec.d.ts.map +1 -0
  88. package/dist/tools/group_exec.js +150 -0
  89. package/dist/tools/group_exec.js.map +1 -0
  90. package/dist/tools/health_check.d.ts +38 -0
  91. package/dist/tools/health_check.d.ts.map +1 -0
  92. package/dist/tools/health_check.js +161 -0
  93. package/dist/tools/health_check.js.map +1 -0
  94. package/dist/tools/host_security.d.ts +52 -0
  95. package/dist/tools/host_security.d.ts.map +1 -0
  96. package/dist/tools/host_security.js +127 -0
  97. package/dist/tools/host_security.js.map +1 -0
  98. package/dist/tools/index.d.ts +24 -0
  99. package/dist/tools/index.d.ts.map +1 -0
  100. package/dist/tools/index.js +24 -0
  101. package/dist/tools/index.js.map +1 -0
  102. package/dist/tools/interrupt.d.ts +47 -0
  103. package/dist/tools/interrupt.d.ts.map +1 -0
  104. package/dist/tools/interrupt.js +77 -0
  105. package/dist/tools/interrupt.js.map +1 -0
  106. package/dist/tools/list_hosts.d.ts +15 -0
  107. package/dist/tools/list_hosts.d.ts.map +1 -0
  108. package/dist/tools/list_hosts.js +18 -0
  109. package/dist/tools/list_hosts.js.map +1 -0
  110. package/dist/tools/list_sessions.d.ts +16 -0
  111. package/dist/tools/list_sessions.d.ts.map +1 -0
  112. package/dist/tools/list_sessions.js +20 -0
  113. package/dist/tools/list_sessions.js.map +1 -0
  114. package/dist/tools/read_output.d.ts +46 -0
  115. package/dist/tools/read_output.d.ts.map +1 -0
  116. package/dist/tools/read_output.js +73 -0
  117. package/dist/tools/read_output.js.map +1 -0
  118. package/dist/tools/reconnect_to_tmux.d.ts +53 -0
  119. package/dist/tools/reconnect_to_tmux.d.ts.map +1 -0
  120. package/dist/tools/reconnect_to_tmux.js +199 -0
  121. package/dist/tools/reconnect_to_tmux.js.map +1 -0
  122. package/dist/tools/send_input.d.ts +45 -0
  123. package/dist/tools/send_input.d.ts.map +1 -0
  124. package/dist/tools/send_input.js +83 -0
  125. package/dist/tools/send_input.js.map +1 -0
  126. package/dist/tools/sftp_download.d.ts +52 -0
  127. package/dist/tools/sftp_download.d.ts.map +1 -0
  128. package/dist/tools/sftp_download.js +90 -0
  129. package/dist/tools/sftp_download.js.map +1 -0
  130. package/dist/tools/sftp_list.d.ts +46 -0
  131. package/dist/tools/sftp_list.d.ts.map +1 -0
  132. package/dist/tools/sftp_list.js +93 -0
  133. package/dist/tools/sftp_list.js.map +1 -0
  134. package/dist/tools/sftp_upload.d.ts +52 -0
  135. package/dist/tools/sftp_upload.d.ts.map +1 -0
  136. package/dist/tools/sftp_upload.js +98 -0
  137. package/dist/tools/sftp_upload.js.map +1 -0
  138. package/dist/tools/ssh_tunnel.d.ts +116 -0
  139. package/dist/tools/ssh_tunnel.d.ts.map +1 -0
  140. package/dist/tools/ssh_tunnel.js +282 -0
  141. package/dist/tools/ssh_tunnel.js.map +1 -0
  142. package/dist/tools/sync.d.ts +71 -0
  143. package/dist/tools/sync.d.ts.map +1 -0
  144. package/dist/tools/sync.js +310 -0
  145. package/dist/tools/sync.js.map +1 -0
  146. package/dist/tools/tail_log.d.ts +61 -0
  147. package/dist/tools/tail_log.d.ts.map +1 -0
  148. package/dist/tools/tail_log.js +111 -0
  149. package/dist/tools/tail_log.js.map +1 -0
  150. package/dist/tools/tools_config.d.ts +34 -0
  151. package/dist/tools/tools_config.d.ts.map +1 -0
  152. package/dist/tools/tools_config.js +98 -0
  153. package/dist/tools/tools_config.js.map +1 -0
  154. package/dist/types/index.d.ts +21 -0
  155. package/dist/types/index.d.ts.map +1 -0
  156. package/dist/types/index.js +2 -0
  157. package/dist/types/index.js.map +1 -0
  158. package/dist/utils/ansi.d.ts +2 -0
  159. package/dist/utils/ansi.d.ts.map +1 -0
  160. package/dist/utils/ansi.js +7 -0
  161. package/dist/utils/ansi.js.map +1 -0
  162. package/dist/utils/logger.d.ts +3 -0
  163. package/dist/utils/logger.d.ts.map +1 -0
  164. package/dist/utils/logger.js +8 -0
  165. package/dist/utils/logger.js.map +1 -0
  166. package/dist/utils/security.d.ts +7 -0
  167. package/dist/utils/security.d.ts.map +1 -0
  168. package/dist/utils/security.js +58 -0
  169. package/dist/utils/security.js.map +1 -0
  170. package/dist/utils/ssh.d.ts +4 -0
  171. package/dist/utils/ssh.d.ts.map +1 -0
  172. package/dist/utils/ssh.js +29 -0
  173. package/dist/utils/ssh.js.map +1 -0
  174. package/dist/utils/sshConfig.d.ts +4 -0
  175. package/dist/utils/sshConfig.d.ts.map +1 -0
  176. package/dist/utils/sshConfig.js +85 -0
  177. package/dist/utils/sshConfig.js.map +1 -0
  178. package/dist/utils/validation.d.ts +4 -0
  179. package/dist/utils/validation.d.ts.map +1 -0
  180. package/dist/utils/validation.js +12 -0
  181. package/dist/utils/validation.js.map +1 -0
  182. package/docs/SECURITY.md +213 -0
  183. package/docs/TOOLS.md +425 -0
  184. package/keygen.bat +325 -0
  185. package/package.json +48 -0
  186. package/test_check.bat +9 -0
  187. package/test_delayed.bat +12 -0
  188. package/vitest.config.ts +14 -0
@@ -0,0 +1,110 @@
1
+ import { logger } from '../utils/logger.js';
2
+ export const MCP_PROMPT = '__MCP_PROMPT__> ';
3
+ function q(value) {
4
+ return `'${value.replace(/'/g, "'\\''")}'`;
5
+ }
6
+ export class TmuxManager {
7
+ sshManager;
8
+ constructor(sshManager) {
9
+ this.sshManager = sshManager;
10
+ }
11
+ async isInstalled(ssh) {
12
+ try {
13
+ const result = await this.sshManager.exec(ssh, 'tmux -V');
14
+ return result.code === 0;
15
+ }
16
+ catch (err) {
17
+ logger.debug({ error: err.message }, 'tmux check failed');
18
+ return false;
19
+ }
20
+ }
21
+ async createOrAttachSession(ssh, sessionName) {
22
+ const result = await this.sshManager.exec(ssh, `tmux new-session -A -s ${q(sessionName)} -d`);
23
+ if (result.code !== 0) {
24
+ throw new Error(`Failed to create/attach tmux session '${sessionName}': ${result.stderr || result.stdout}`);
25
+ }
26
+ logger.info({ sessionName }, 'Tmux session created/attached');
27
+ }
28
+ async applyOptions(ssh, sessionName) {
29
+ await this.sshManager.exec(ssh, `tmux set-option -t ${q(sessionName)} history-limit 50000`);
30
+ await this.sshManager.exec(ssh, `tmux set-option -t ${q(sessionName)} mouse off`);
31
+ logger.info({ sessionName }, 'Applied tmux options (history-limit=50000, mouse=off)');
32
+ }
33
+ async detectShell(ssh, sessionName) {
34
+ const result = await this.sshManager.exec(ssh, `tmux display-message -t ${q(sessionName)} -p '#{pane_current_command}'`);
35
+ if (result.code !== 0) {
36
+ return null;
37
+ }
38
+ const shell = result.stdout.trim().toLowerCase();
39
+ logger.info({ sessionName, shell }, 'Shell detected');
40
+ return shell;
41
+ }
42
+ async injectPrompt(ssh, sessionName) {
43
+ const cmd = `export PS1='${MCP_PROMPT}'`;
44
+ await this.sendCommand(ssh, sessionName, cmd);
45
+ logger.info({ sessionName }, 'Injected deterministic prompt');
46
+ }
47
+ async healthCheck(ssh, sessionName) {
48
+ const result = await this.sshManager.exec(ssh, `tmux has-session -t ${q(sessionName)}`);
49
+ if (result.code !== 0) {
50
+ logger.warn({ sessionName }, 'Tmux health check failed: session missing');
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+ async sendInput(ssh, sessionName, input) {
56
+ const base64 = Buffer.from(input).toString('base64');
57
+ const command = `printf '%s' ${q(base64)} | base64 -d | tmux load-buffer - && tmux paste-buffer -t ${q(sessionName)} -d`;
58
+ const result = await this.sshManager.exec(ssh, command);
59
+ if (result.code !== 0) {
60
+ throw new Error(`Failed to send input to tmux session '${sessionName}': ${result.stderr || result.stdout}`);
61
+ }
62
+ }
63
+ async sendCommand(ssh, sessionName, command) {
64
+ const base64 = Buffer.from(command + '\n').toString('base64');
65
+ const shellCommand = `printf '%s' ${q(base64)} | base64 -d | tmux load-buffer - && tmux paste-buffer -t ${q(sessionName)} -d`;
66
+ const result = await this.sshManager.exec(ssh, shellCommand);
67
+ if (result.code !== 0) {
68
+ throw new Error(`Failed to send command to tmux session '${sessionName}': ${result.stderr || result.stdout}`);
69
+ }
70
+ }
71
+ async sendSignal(ssh, sessionName, signal) {
72
+ const key = signal === 'SIGINT' ? 'C-c' : 'C-c';
73
+ const result = await this.sshManager.exec(ssh, `tmux send-keys -t ${q(sessionName)} ${key}`);
74
+ if (result.code !== 0) {
75
+ throw new Error(`Failed to send signal ${signal} to tmux session '${sessionName}': ${result.stderr || result.stdout}`);
76
+ }
77
+ logger.info({ sessionName, signal }, 'Signal sent to tmux pane');
78
+ }
79
+ async capturePane(ssh, sessionName, lines) {
80
+ const result = await this.sshManager.exec(ssh, `tmux capture-pane -t ${q(sessionName)} -p -S -${lines}`);
81
+ if (result.code !== 0) {
82
+ throw new Error(`Failed to capture tmux pane '${sessionName}': ${result.stderr || result.stdout}`);
83
+ }
84
+ return result.stdout;
85
+ }
86
+ async hasSession(ssh, sessionName) {
87
+ const result = await this.sshManager.exec(ssh, `tmux has-session -t ${q(sessionName)}`);
88
+ return result.code === 0;
89
+ }
90
+ async listSessions(ssh) {
91
+ const result = await this.sshManager.exec(ssh, 'tmux list-sessions -F "#{session_name}"');
92
+ if (result.code !== 0) {
93
+ return [];
94
+ }
95
+ return result.stdout
96
+ .split('\n')
97
+ .map((s) => s.trim())
98
+ .filter(Boolean);
99
+ }
100
+ async killSession(ssh, sessionName) {
101
+ const result = await this.sshManager.exec(ssh, `tmux kill-session -t ${q(sessionName)}`);
102
+ if (result.code !== 0) {
103
+ logger.warn({ sessionName, error: result.stderr }, 'Failed to kill tmux session');
104
+ }
105
+ else {
106
+ logger.info({ sessionName }, 'Tmux session killed');
107
+ }
108
+ }
109
+ }
110
+ //# sourceMappingURL=TmuxManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TmuxManager.js","sourceRoot":"","sources":["../../src/core/TmuxManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface ToolConfig {
2
+ [toolName: string]: boolean;
3
+ }
4
+ export declare class ToolConfigManager {
5
+ private config;
6
+ private configPath;
7
+ constructor(configDir?: string);
8
+ private load;
9
+ private save;
10
+ isEnabled(toolName: string): boolean;
11
+ setEnabled(toolName: string, enabled: boolean): void;
12
+ reset(): void;
13
+ getAll(): ToolConfig;
14
+ }
15
+ //# sourceMappingURL=ToolConfigManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolConfigManager.d.ts","sourceRoot":"","sources":["../../src/core/ToolConfigManager.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAKD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAS;gBAEf,SAAS,CAAC,EAAE,MAAM;IAK9B,OAAO,CAAC,IAAI;IAYZ,OAAO,CAAC,IAAI;IAYZ,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAMpC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAKpD,KAAK,IAAI,IAAI;IAKb,MAAM,IAAI,UAAU;CAGrB"}
@@ -0,0 +1,57 @@
1
+ import { logger } from '../utils/logger.js';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+ const DEFAULT_DIR = path.join(os.homedir(), '.dynamic-ssh-mcp');
6
+ const CONFIG_FILE = 'tools.json';
7
+ export class ToolConfigManager {
8
+ config;
9
+ configPath;
10
+ constructor(configDir) {
11
+ this.configPath = path.join(configDir || DEFAULT_DIR, CONFIG_FILE);
12
+ this.config = this.load();
13
+ }
14
+ load() {
15
+ try {
16
+ if (fs.existsSync(this.configPath)) {
17
+ const raw = fs.readFileSync(this.configPath, 'utf-8');
18
+ return JSON.parse(raw);
19
+ }
20
+ }
21
+ catch (err) {
22
+ logger.warn({ err }, 'Failed to load tool config, using defaults');
23
+ }
24
+ return {};
25
+ }
26
+ save() {
27
+ try {
28
+ const dir = path.dirname(this.configPath);
29
+ if (!fs.existsSync(dir)) {
30
+ fs.mkdirSync(dir, { recursive: true });
31
+ }
32
+ fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
33
+ }
34
+ catch (err) {
35
+ logger.error({ err }, 'Failed to save tool config');
36
+ }
37
+ }
38
+ isEnabled(toolName) {
39
+ if (toolName === 'tools_config')
40
+ return true;
41
+ if (!(toolName in this.config))
42
+ return true;
43
+ return this.config[toolName];
44
+ }
45
+ setEnabled(toolName, enabled) {
46
+ this.config[toolName] = enabled;
47
+ this.save();
48
+ }
49
+ reset() {
50
+ this.config = {};
51
+ this.save();
52
+ }
53
+ getAll() {
54
+ return { ...this.config };
55
+ }
56
+ }
57
+ //# sourceMappingURL=ToolConfigManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolConfigManager.js","sourceRoot":"","sources":["../../src/core/ToolConfigManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAMzB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAChE,MAAM,WAAW,GAAG,YAAY,CAAC;AAEjC,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAa;IACnB,UAAU,CAAS;IAE3B,YAAY,SAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,WAAW,EAAE,WAAW,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAEO,IAAI;QACV,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBACtD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,4CAA4C,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,IAAI;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,4BAA4B,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,SAAS,CAAC,QAAgB;QACxB,IAAI,QAAQ,KAAK,cAAc;YAAE,OAAO,IAAI,CAAC;QAC7C,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,UAAU,CAAC,QAAgB,EAAE,OAAgB;QAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from './server.js';
3
+ import { StorageManager } from './core/StorageManager.js';
4
+ import { SSHManager } from './core/SSHManager.js';
5
+ import { TmuxManager, MCP_PROMPT } from './core/TmuxManager.js';
6
+ import { listHostAliases, getHostConfig } from './utils/sshConfig.js';
7
+ import { buildSshConfig } from './utils/ssh.js';
8
+ import { isHostAllowed } from './utils/security.js';
9
+ import { logger } from './utils/logger.js';
10
+ const RESTORE_ENABLED = process.env.MCP_SSH_RESTORE_SESSIONS !== 'false';
11
+ async function restoreSessions(storage, sshManager, tmuxManager, sessionManager) {
12
+ if (!RESTORE_ENABLED) {
13
+ logger.info('Session restore disabled (MCP_SSH_RESTORE_SESSIONS=false)');
14
+ return 0;
15
+ }
16
+ // Strategy 1: Restore from persistent storage (known sessions from last run)
17
+ const storedSessions = storage.list();
18
+ const hosts = [...new Set(storedSessions.map((s) => s.host))];
19
+ // Also scan all configured hosts in case storage is empty or incomplete
20
+ const allAliases = listHostAliases();
21
+ for (const alias of allAliases) {
22
+ if (!hosts.includes(alias) && isHostAllowed(alias)) {
23
+ hosts.push(alias);
24
+ }
25
+ }
26
+ if (hosts.length === 0) {
27
+ logger.debug('No hosts to restore');
28
+ return 0;
29
+ }
30
+ logger.info({ hosts }, 'Attempting session restore');
31
+ let restored = 0;
32
+ const knownTmuxSessions = new Set(storage.listTmuxSessions());
33
+ for (const host of hosts) {
34
+ if (!isHostAllowed(host))
35
+ continue;
36
+ const hostConfig = getHostConfig(host);
37
+ if (!hostConfig) {
38
+ logger.debug({ host }, 'Skip restore: no SSH config');
39
+ continue;
40
+ }
41
+ const baseSshConfig = buildSshConfig(hostConfig, 15000);
42
+ if (!baseSshConfig) {
43
+ logger.warn({ host }, 'Skip restore: failed to build SSH config');
44
+ continue;
45
+ }
46
+ // First, connect temporarily to discover mcp_* tmux sessions
47
+ let probeSsh;
48
+ try {
49
+ probeSsh = await sshManager.connect({ ...baseSshConfig });
50
+ }
51
+ catch (err) {
52
+ logger.warn({ host, error: err.message }, 'Restore: SSH probe failed');
53
+ continue;
54
+ }
55
+ const tmuxInstalled = await tmuxManager.isInstalled(probeSsh);
56
+ if (!tmuxInstalled) {
57
+ sshManager.disconnect(probeSsh);
58
+ logger.debug({ host }, 'Restore: tmux not installed, skipping');
59
+ continue;
60
+ }
61
+ let tmuxSessions = [];
62
+ try {
63
+ tmuxSessions = await tmuxManager.listSessions(probeSsh);
64
+ }
65
+ catch (err) {
66
+ sshManager.disconnect(probeSsh);
67
+ logger.warn({ host, error: err.message }, 'Restore: list sessions failed');
68
+ continue;
69
+ }
70
+ // Filter for MCP-managed sessions (mcp_ prefix)
71
+ const mcpSessions = tmuxSessions.filter((s) => s.startsWith('mcp_'));
72
+ sshManager.disconnect(probeSsh);
73
+ if (mcpSessions.length === 0) {
74
+ logger.debug({ host }, 'Restore: no mcp_* tmux sessions found');
75
+ continue;
76
+ }
77
+ // Reconnect to each MCP tmux session with its own SSH connection
78
+ for (const tmuxSession of mcpSessions) {
79
+ const storedSession = storedSessions.find((s) => s.host === host && s.tmuxSession === tmuxSession);
80
+ // Each restored session gets its own SSH connection
81
+ let ssh;
82
+ try {
83
+ ssh = await sshManager.connect({ ...baseSshConfig });
84
+ }
85
+ catch (err) {
86
+ logger.warn({ host, tmuxSession, error: err.message }, 'Restore: SSH session connect failed');
87
+ continue;
88
+ }
89
+ try {
90
+ const exists = await tmuxManager.hasSession(ssh, tmuxSession);
91
+ if (!exists) {
92
+ sshManager.disconnect(ssh);
93
+ if (storedSession)
94
+ storage.remove(storedSession.id);
95
+ continue;
96
+ }
97
+ // Check and inject prompt if missing
98
+ try {
99
+ const output = await tmuxManager.capturePane(ssh, tmuxSession, 5);
100
+ if (!output.includes(MCP_PROMPT)) {
101
+ await tmuxManager.injectPrompt(ssh, tmuxSession);
102
+ await new Promise((r) => setTimeout(r, 300));
103
+ }
104
+ }
105
+ catch {
106
+ logger.warn({ host, tmuxSession }, 'Restore: prompt check failed, continuing');
107
+ }
108
+ const session = sessionManager.create(host, ssh, tmuxSession, storedSession?.shell, storedSession?.id);
109
+ logger.info({ sessionId: session.id, host, tmuxSession }, 'Session restored');
110
+ restored++;
111
+ knownTmuxSessions.add(tmuxSession);
112
+ }
113
+ catch (err) {
114
+ sshManager.disconnect(ssh);
115
+ logger.warn({ host, tmuxSession, error: err.message }, 'Restore: session skipped');
116
+ }
117
+ }
118
+ }
119
+ // Clean up stale storage entries for sessions that no longer exist
120
+ for (const stored of storedSessions) {
121
+ if (!knownTmuxSessions.has(stored.tmuxSession)) {
122
+ storage.remove(stored.id);
123
+ logger.debug({ sessionId: stored.id, tmuxSession: stored.tmuxSession }, 'Cleaned up stale session record');
124
+ }
125
+ }
126
+ logger.info({ restored }, 'Session restore complete');
127
+ return restored;
128
+ }
129
+ async function main() {
130
+ const storage = new StorageManager();
131
+ const { server, sessionManager, transport } = createServer(storage);
132
+ const sshManager = new SSHManager();
133
+ const tmuxManager = new TmuxManager(sshManager);
134
+ // Prevent silent crashes from unhandled errors
135
+ process.on('uncaughtException', (err) => {
136
+ logger.fatal({ error: err.message, stack: err.stack }, 'Uncaught exception');
137
+ process.exit(1);
138
+ });
139
+ process.on('unhandledRejection', (reason) => {
140
+ logger.fatal({ error: reason?.message || String(reason) }, 'Unhandled rejection');
141
+ });
142
+ // Restore previous sessions on startup (fire-and-forget, doesn't block MCP)
143
+ restoreSessions(storage, sshManager, tmuxManager, sessionManager).catch((err) => {
144
+ logger.error({ error: err.message }, 'Session restore failed');
145
+ });
146
+ // Graceful shutdown
147
+ const cleanup = () => {
148
+ logger.info('Shutting down...');
149
+ sessionManager.disconnectAll();
150
+ storage.shutdown();
151
+ server
152
+ .close()
153
+ .then(() => {
154
+ process.exit(0);
155
+ })
156
+ .catch(() => {
157
+ process.exit(1);
158
+ });
159
+ };
160
+ process.on('SIGINT', cleanup);
161
+ process.on('SIGTERM', cleanup);
162
+ await server.connect(transport);
163
+ logger.info('Dynamic SSH MCP server running on stdio');
164
+ }
165
+ main().catch((err) => {
166
+ logger.error({ error: err.message }, 'Fatal error');
167
+ process.exit(1);
168
+ });
169
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { SessionManager } from './core/SessionManager.js';
4
+ import { StorageManager } from './core/StorageManager.js';
5
+ export declare function createServer(storage?: StorageManager): {
6
+ server: Server<{
7
+ method: string;
8
+ params?: {
9
+ [x: string]: unknown;
10
+ _meta?: {
11
+ [x: string]: unknown;
12
+ progressToken?: string | number | undefined;
13
+ "io.modelcontextprotocol/related-task"?: {
14
+ taskId: string;
15
+ } | undefined;
16
+ } | undefined;
17
+ } | undefined;
18
+ }, {
19
+ method: string;
20
+ params?: {
21
+ [x: string]: unknown;
22
+ _meta?: {
23
+ [x: string]: unknown;
24
+ progressToken?: string | number | undefined;
25
+ "io.modelcontextprotocol/related-task"?: {
26
+ taskId: string;
27
+ } | undefined;
28
+ } | undefined;
29
+ } | undefined;
30
+ }, {
31
+ [x: string]: unknown;
32
+ _meta?: {
33
+ [x: string]: unknown;
34
+ progressToken?: string | number | undefined;
35
+ "io.modelcontextprotocol/related-task"?: {
36
+ taskId: string;
37
+ } | undefined;
38
+ } | undefined;
39
+ }>;
40
+ sessionManager: SessionManager;
41
+ storageManager: StorageManager;
42
+ transport: StdioServerTransport;
43
+ };
44
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAOjF,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAsF1D,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoIpD"}
package/dist/server.js ADDED
@@ -0,0 +1,152 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
4
+ import { SessionManager } from './core/SessionManager.js';
5
+ import { SSHManager } from './core/SSHManager.js';
6
+ import { TmuxManager } from './core/TmuxManager.js';
7
+ import { StorageManager } from './core/StorageManager.js';
8
+ import { ToolConfigManager } from './core/ToolConfigManager.js';
9
+ import { HostSecurityManager } from './core/HostSecurityManager.js';
10
+ import { setHostSecurityManager } from './utils/security.js';
11
+ import { logger } from './utils/logger.js';
12
+ import { listHostsTool, handleListHosts, connectTool, handleConnect, reconnectTool, handleReconnect, sendInputTool, handleSendInput, readOutputTool, handleReadOutput, execTool, handleExec, interruptTool, handleInterrupt, disconnectTool, handleDisconnect, listSessionsTool, handleListSessions, sftpUploadTool, handleSftpUpload, sftpDownloadTool, handleSftpDownload, sftpListTool, handleSftpList, connectionStatusTool, handleConnectionStatus, healthCheckTool, handleHealthCheck, tailLogTool, handleTailLog, tunnelOpenTool, tunnelCloseTool, tunnelListTool, handleTunnelOpen, handleTunnelClose, handleTunnelList, deployTool, handleDeploy, backupTool, handleBackup, syncTool, handleSync, groupExecTool, handleGroupExec, dbQueryTool, handleDbQuery, toolsConfigTool, handleToolsConfig, hostSecurityTool, handleHostSecurity, } from './tools/index.js';
13
+ const allTools = [
14
+ listHostsTool,
15
+ connectTool,
16
+ reconnectTool,
17
+ sendInputTool,
18
+ readOutputTool,
19
+ execTool,
20
+ interruptTool,
21
+ disconnectTool,
22
+ listSessionsTool,
23
+ sftpUploadTool,
24
+ sftpDownloadTool,
25
+ sftpListTool,
26
+ connectionStatusTool,
27
+ healthCheckTool,
28
+ tailLogTool,
29
+ tunnelOpenTool,
30
+ tunnelCloseTool,
31
+ tunnelListTool,
32
+ deployTool,
33
+ backupTool,
34
+ syncTool,
35
+ groupExecTool,
36
+ dbQueryTool,
37
+ toolsConfigTool,
38
+ hostSecurityTool,
39
+ ];
40
+ export function createServer(storage) {
41
+ const storageManager = storage || new StorageManager();
42
+ const server = new Server({
43
+ name: 'dynamic-ssh-mcp',
44
+ version: '1.0.0',
45
+ }, {
46
+ capabilities: {
47
+ tools: {},
48
+ },
49
+ });
50
+ const sessionManager = new SessionManager(storageManager);
51
+ const sshManager = new SSHManager();
52
+ const tmuxManager = new TmuxManager(sshManager);
53
+ const toolConfigManager = new ToolConfigManager();
54
+ const hostSecurityManager = new HostSecurityManager();
55
+ setHostSecurityManager(hostSecurityManager);
56
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
57
+ tools: allTools.filter((t) => toolConfigManager.isEnabled(t.name)),
58
+ }));
59
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
60
+ const { name, arguments: args } = request.params;
61
+ logger.info({ tool: name }, 'Tool called');
62
+ try {
63
+ switch (name) {
64
+ case 'list_hosts': {
65
+ return await handleListHosts();
66
+ }
67
+ case 'connect': {
68
+ return await handleConnect(args, sessionManager, sshManager, tmuxManager);
69
+ }
70
+ case 'reconnect_to_tmux': {
71
+ return await handleReconnect(args, sessionManager, sshManager, tmuxManager);
72
+ }
73
+ case 'send_input': {
74
+ return await handleSendInput(args, sessionManager, tmuxManager);
75
+ }
76
+ case 'read_output': {
77
+ return await handleReadOutput(args, sessionManager, tmuxManager);
78
+ }
79
+ case 'exec': {
80
+ return await handleExec(args, sessionManager, tmuxManager);
81
+ }
82
+ case 'interrupt': {
83
+ return await handleInterrupt(args, sessionManager, tmuxManager);
84
+ }
85
+ case 'disconnect': {
86
+ return await handleDisconnect(args, sessionManager, tmuxManager);
87
+ }
88
+ case 'list_sessions': {
89
+ return await handleListSessions(sessionManager);
90
+ }
91
+ case 'sftp_upload': {
92
+ return await handleSftpUpload(args, sessionManager, sshManager);
93
+ }
94
+ case 'sftp_download': {
95
+ return await handleSftpDownload(args, sessionManager, sshManager);
96
+ }
97
+ case 'sftp_list': {
98
+ return await handleSftpList(args, sessionManager, sshManager);
99
+ }
100
+ case 'connection_status': {
101
+ return await handleConnectionStatus(args, sessionManager, sshManager, tmuxManager);
102
+ }
103
+ case 'health_check': {
104
+ return await handleHealthCheck(args, sessionManager, sshManager);
105
+ }
106
+ case 'tail_log': {
107
+ return await handleTailLog(args, sessionManager, sshManager);
108
+ }
109
+ case 'ssh_tunnel_open': {
110
+ return await handleTunnelOpen(args, sessionManager, sshManager);
111
+ }
112
+ case 'ssh_tunnel_close': {
113
+ return await handleTunnelClose(args);
114
+ }
115
+ case 'ssh_tunnel_list': {
116
+ return await handleTunnelList();
117
+ }
118
+ case 'deploy': {
119
+ return await handleDeploy(args, sessionManager, sshManager);
120
+ }
121
+ case 'backup': {
122
+ return await handleBackup(args, sessionManager, sshManager);
123
+ }
124
+ case 'sync': {
125
+ return await handleSync(args, sessionManager, sshManager);
126
+ }
127
+ case 'group_exec': {
128
+ return await handleGroupExec(args, sessionManager, tmuxManager);
129
+ }
130
+ case 'db_query': {
131
+ return await handleDbQuery(args, sessionManager, sshManager);
132
+ }
133
+ case 'tools_config': {
134
+ return await handleToolsConfig(args, toolConfigManager);
135
+ }
136
+ case 'host_security': {
137
+ return await handleHostSecurity(args, hostSecurityManager);
138
+ }
139
+ default: {
140
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
141
+ }
142
+ }
143
+ }
144
+ catch (err) {
145
+ const message = err instanceof Error ? err.message : String(err);
146
+ logger.error({ tool: name, error: message }, 'Unhandled tool error');
147
+ throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${message}`);
148
+ }
149
+ });
150
+ return { server, sessionManager, storageManager, transport: new StdioServerTransport() };
151
+ }
152
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}