enterprise-ssh-mcp-server 0.3.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.
@@ -0,0 +1,67 @@
1
+ let compactJson = false;
2
+ export class McpToolError extends Error {
3
+ code;
4
+ details;
5
+ constructor(code, message, details) {
6
+ super(message);
7
+ this.name = "McpToolError";
8
+ this.code = code;
9
+ if (details !== undefined) {
10
+ this.details = details;
11
+ }
12
+ }
13
+ }
14
+ export function setCompactJsonResponse(enabled) {
15
+ compactJson = enabled;
16
+ }
17
+ export function jsonResponse(payload) {
18
+ return {
19
+ content: [
20
+ {
21
+ type: "text",
22
+ text: stringifyPayload(payload),
23
+ },
24
+ ],
25
+ };
26
+ }
27
+ export async function toToolResult(task) {
28
+ try {
29
+ return jsonResponse(await task());
30
+ }
31
+ catch (error) {
32
+ return {
33
+ isError: true,
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: stringifyPayload({ ok: false, error: serializeError(error) }),
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ }
43
+ export function serializeError(error) {
44
+ if (error instanceof McpToolError) {
45
+ const payload = {
46
+ code: error.code,
47
+ message: error.message,
48
+ };
49
+ if (error.details !== undefined) {
50
+ payload.details = error.details;
51
+ }
52
+ return payload;
53
+ }
54
+ return {
55
+ code: "internal_error",
56
+ message: error.message,
57
+ };
58
+ }
59
+ export function assertNonEmpty(value, fieldName) {
60
+ if (value.trim().length === 0) {
61
+ throw new McpToolError("invalid_argument", `${fieldName} must not be empty`, { fieldName });
62
+ }
63
+ }
64
+ function stringifyPayload(payload) {
65
+ return compactJson ? JSON.stringify(payload) : JSON.stringify(payload, null, 2);
66
+ }
67
+ //# sourceMappingURL=tool-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-result.js","sourceRoot":"","sources":["../src/tool-result.ts"],"names":[],"mappings":"AAEA,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrB,IAAI,CAAS;IACb,OAAO,CAAU;IAEjC,YAAmB,IAAY,EAAE,OAAe,EAAE,OAAgB;QAChE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,WAAW,GAAG,OAAO,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC;aAChC;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAA2B;IAC5D,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gBAAgB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;iBACpE;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAA2B;IACxD,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;QAClC,MAAM,OAAO,GAAwD;YACnE,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC;QACF,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAClC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,SAAiB;IAC7D,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,GAAG,SAAS,oBAAoB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,60 @@
1
+ import type { SshSession } from "./ssh-session.js";
2
+ export type TransferKind = "upload" | "download";
3
+ export type TransferState = "queued" | "running" | "completed" | "failed" | "cancelled";
4
+ export interface UploadStartInput {
5
+ sessionId: string;
6
+ localPath: string;
7
+ remotePath: string;
8
+ resume: boolean;
9
+ overwrite: boolean;
10
+ atomic: boolean;
11
+ remoteTempPath?: string;
12
+ mode?: number;
13
+ chunkSizeBytes: number;
14
+ }
15
+ export interface DownloadStartInput {
16
+ sessionId: string;
17
+ remotePath: string;
18
+ localPath: string;
19
+ resume: boolean;
20
+ overwrite: boolean;
21
+ atomic: boolean;
22
+ localTempPath?: string;
23
+ chunkSizeBytes: number;
24
+ }
25
+ export interface TransferSummary {
26
+ id: string;
27
+ sessionId: string;
28
+ kind: TransferKind;
29
+ state: TransferState;
30
+ localPath: string;
31
+ remotePath: string;
32
+ totalBytes: number;
33
+ transferredBytes: number;
34
+ resumeOffsetBytes: number;
35
+ percent: number;
36
+ bytesPerSecond: number;
37
+ etaSeconds: number | null;
38
+ createdAt: string;
39
+ startedAt?: string;
40
+ updatedAt: string;
41
+ finishedAt?: string;
42
+ error?: string;
43
+ atomic: boolean;
44
+ tempPath?: string;
45
+ }
46
+ export declare class TransferManager {
47
+ private readonly jobs;
48
+ startUpload(session: SshSession, input: UploadStartInput): TransferSummary;
49
+ startDownload(session: SshSession, input: DownloadStartInput): TransferSummary;
50
+ get(transferId: string): TransferSummary;
51
+ list(sessionId?: string): TransferSummary[];
52
+ cancel(transferId: string): TransferSummary;
53
+ private runUpload;
54
+ private runDownload;
55
+ private getJob;
56
+ private markRunning;
57
+ private markCompleted;
58
+ private markCancelled;
59
+ private markFailedOrCancelled;
60
+ }
@@ -0,0 +1,339 @@
1
+ import { createReadStream, createWriteStream } from "node:fs";
2
+ import { mkdir, rename as renameLocal, stat as statLocal } from "node:fs/promises";
3
+ import { randomUUID } from "node:crypto";
4
+ import { dirname, resolve } from "node:path";
5
+ import { pipeline } from "node:stream/promises";
6
+ import { isMissingPathError, sftpRename, sftpStat } from "./sftp-ops.js";
7
+ import { McpToolError } from "./tool-result.js";
8
+ export class TransferManager {
9
+ jobs = new Map();
10
+ startUpload(session, input) {
11
+ const job = createBaseJob(input.sessionId, "upload", resolve(input.localPath), input.remotePath, input.atomic);
12
+ if (input.remoteTempPath !== undefined) {
13
+ job.tempPath = input.remoteTempPath;
14
+ }
15
+ this.jobs.set(job.id, job);
16
+ void this.runUpload(session, input, job);
17
+ return summarizeJob(job);
18
+ }
19
+ startDownload(session, input) {
20
+ const job = createBaseJob(input.sessionId, "download", resolve(input.localPath), input.remotePath, input.atomic);
21
+ if (input.localTempPath !== undefined) {
22
+ job.tempPath = resolve(input.localTempPath);
23
+ }
24
+ this.jobs.set(job.id, job);
25
+ void this.runDownload(session, input, job);
26
+ return summarizeJob(job);
27
+ }
28
+ get(transferId) {
29
+ return summarizeJob(this.getJob(transferId));
30
+ }
31
+ list(sessionId) {
32
+ return [...this.jobs.values()]
33
+ .filter((job) => sessionId === undefined || job.sessionId === sessionId)
34
+ .map((job) => summarizeJob(job));
35
+ }
36
+ cancel(transferId) {
37
+ const job = this.getJob(transferId);
38
+ if (job.state === "completed" || job.state === "failed" || job.state === "cancelled") {
39
+ return summarizeJob(job);
40
+ }
41
+ job.cancelRequested = true;
42
+ job.state = "cancelled";
43
+ job.updatedAt = new Date().toISOString();
44
+ job.localStream?.destroy();
45
+ job.remoteStream?.destroy();
46
+ return summarizeJob(job);
47
+ }
48
+ async runUpload(session, input, job) {
49
+ try {
50
+ this.markRunning(job);
51
+ const sftp = await session.getSftp();
52
+ const localStats = await statLocal(job.localPath);
53
+ if (!localStats.isFile()) {
54
+ throw new McpToolError("local_path_not_file", "Local upload path is not a file", { localPath: job.localPath });
55
+ }
56
+ job.totalBytes = localStats.size;
57
+ const targetRemotePath = input.atomic ? job.tempPath ?? `${input.remotePath}.mcp-uploading` : input.remotePath;
58
+ if (input.atomic) {
59
+ job.tempPath = targetRemotePath;
60
+ }
61
+ const resumeOffset = await resolveRemoteResumeOffset(sftp, targetRemotePath, input.remotePath, localStats.size, input);
62
+ job.resumeOffsetBytes = resumeOffset;
63
+ job.transferredBytes = resumeOffset;
64
+ job.updatedAt = new Date().toISOString();
65
+ if (job.cancelRequested) {
66
+ this.markCancelled(job);
67
+ return;
68
+ }
69
+ const localStream = createReadStream(job.localPath, {
70
+ start: resumeOffset,
71
+ highWaterMark: input.chunkSizeBytes,
72
+ });
73
+ const flags = resumeOffset > 0 ? "r+" : "w";
74
+ const writeOptions = input.mode === undefined
75
+ ? {
76
+ flags,
77
+ start: resumeOffset,
78
+ highWaterMark: input.chunkSizeBytes,
79
+ }
80
+ : {
81
+ flags,
82
+ start: resumeOffset,
83
+ mode: input.mode,
84
+ highWaterMark: input.chunkSizeBytes,
85
+ };
86
+ const remoteStream = sftp.createWriteStream(targetRemotePath, writeOptions);
87
+ job.localStream = localStream;
88
+ job.remoteStream = remoteStream;
89
+ localStream.on("data", (chunk) => {
90
+ job.transferredBytes += Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(chunk);
91
+ job.updatedAt = new Date().toISOString();
92
+ });
93
+ await pipeline(localStream, remoteStream);
94
+ if (job.cancelRequested) {
95
+ this.markCancelled(job);
96
+ return;
97
+ }
98
+ if (input.atomic) {
99
+ await ensureRemoteOverwritePolicy(sftp, input.remotePath, input.overwrite);
100
+ await sftpRename(sftp, targetRemotePath, input.remotePath);
101
+ }
102
+ this.markCompleted(job);
103
+ }
104
+ catch (error) {
105
+ this.markFailedOrCancelled(job, error);
106
+ }
107
+ finally {
108
+ delete job.localStream;
109
+ delete job.remoteStream;
110
+ }
111
+ }
112
+ async runDownload(session, input, job) {
113
+ try {
114
+ this.markRunning(job);
115
+ const sftp = await session.getSftp();
116
+ const remoteStats = await sftpStat(sftp, input.remotePath, true);
117
+ if (!remoteStats.isFile()) {
118
+ throw new McpToolError("remote_path_not_file", "Remote download path is not a file", {
119
+ remotePath: input.remotePath,
120
+ });
121
+ }
122
+ const targetLocalPath = input.atomic ? job.tempPath ?? `${job.localPath}.mcp-downloading` : job.localPath;
123
+ if (input.atomic) {
124
+ job.tempPath = targetLocalPath;
125
+ }
126
+ await mkdir(dirname(targetLocalPath), { recursive: true });
127
+ job.totalBytes = remoteStats.size;
128
+ const resumeOffset = await resolveLocalResumeOffset(targetLocalPath, remoteStats.size, input);
129
+ job.resumeOffsetBytes = resumeOffset;
130
+ job.transferredBytes = resumeOffset;
131
+ job.updatedAt = new Date().toISOString();
132
+ if (job.cancelRequested) {
133
+ this.markCancelled(job);
134
+ return;
135
+ }
136
+ const remoteStream = sftp.createReadStream(input.remotePath, {
137
+ start: resumeOffset,
138
+ highWaterMark: input.chunkSizeBytes,
139
+ });
140
+ const localStream = createWriteStream(targetLocalPath, {
141
+ flags: resumeOffset > 0 ? "r+" : "w",
142
+ start: resumeOffset,
143
+ highWaterMark: input.chunkSizeBytes,
144
+ });
145
+ job.localStream = localStream;
146
+ job.remoteStream = remoteStream;
147
+ remoteStream.on("data", (chunk) => {
148
+ job.transferredBytes += Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(chunk);
149
+ job.updatedAt = new Date().toISOString();
150
+ });
151
+ await pipeline(remoteStream, localStream);
152
+ if (job.cancelRequested) {
153
+ this.markCancelled(job);
154
+ return;
155
+ }
156
+ if (input.atomic) {
157
+ await ensureLocalOverwritePolicy(job.localPath, input.overwrite);
158
+ await renameLocal(targetLocalPath, job.localPath);
159
+ }
160
+ this.markCompleted(job);
161
+ }
162
+ catch (error) {
163
+ this.markFailedOrCancelled(job, error);
164
+ }
165
+ finally {
166
+ delete job.localStream;
167
+ delete job.remoteStream;
168
+ }
169
+ }
170
+ getJob(transferId) {
171
+ const job = this.jobs.get(transferId);
172
+ if (job === undefined) {
173
+ throw new McpToolError("transfer_not_found", "Transfer job id was not found", { transferId });
174
+ }
175
+ return job;
176
+ }
177
+ markRunning(job) {
178
+ job.state = "running";
179
+ job.startedAt = new Date().toISOString();
180
+ job.updatedAt = job.startedAt;
181
+ }
182
+ markCompleted(job) {
183
+ job.state = "completed";
184
+ job.transferredBytes = job.totalBytes;
185
+ job.updatedAt = new Date().toISOString();
186
+ job.finishedAt = job.updatedAt;
187
+ }
188
+ markCancelled(job) {
189
+ job.state = "cancelled";
190
+ job.updatedAt = new Date().toISOString();
191
+ job.finishedAt = job.updatedAt;
192
+ }
193
+ markFailedOrCancelled(job, error) {
194
+ if (job.cancelRequested || job.state === "cancelled") {
195
+ this.markCancelled(job);
196
+ return;
197
+ }
198
+ job.state = "failed";
199
+ job.error = error.message;
200
+ job.updatedAt = new Date().toISOString();
201
+ job.finishedAt = job.updatedAt;
202
+ }
203
+ }
204
+ async function resolveRemoteResumeOffset(sftp, targetRemotePath, finalRemotePath, localSize, input) {
205
+ if (!input.resume) {
206
+ await ensureRemoteOverwritePolicy(sftp, input.atomic ? finalRemotePath : targetRemotePath, input.overwrite);
207
+ return 0;
208
+ }
209
+ if (input.atomic) {
210
+ await ensureRemoteOverwritePolicy(sftp, finalRemotePath, input.overwrite);
211
+ }
212
+ try {
213
+ const stats = await sftpStat(sftp, targetRemotePath, true);
214
+ if (stats.size > localSize) {
215
+ throw new McpToolError("remote_file_larger_than_local", "Remote file is larger than the local upload source", {
216
+ remotePath: targetRemotePath,
217
+ remoteBytes: stats.size,
218
+ localBytes: localSize,
219
+ });
220
+ }
221
+ return stats.size;
222
+ }
223
+ catch (error) {
224
+ if (isMissingPathError(error)) {
225
+ return 0;
226
+ }
227
+ throw error;
228
+ }
229
+ }
230
+ async function resolveLocalResumeOffset(localPath, remoteSize, input) {
231
+ if (!input.resume) {
232
+ await ensureLocalOverwritePolicy(localPath, input.overwrite);
233
+ return 0;
234
+ }
235
+ try {
236
+ const stats = await statLocal(localPath);
237
+ if (stats.size > remoteSize) {
238
+ throw new McpToolError("local_file_larger_than_remote", "Local file is larger than the remote download source", {
239
+ localPath,
240
+ localBytes: stats.size,
241
+ remoteBytes: remoteSize,
242
+ });
243
+ }
244
+ return stats.size;
245
+ }
246
+ catch (error) {
247
+ const nodeError = error;
248
+ if (nodeError.code === "ENOENT") {
249
+ return 0;
250
+ }
251
+ throw error;
252
+ }
253
+ }
254
+ async function ensureRemoteOverwritePolicy(sftp, remotePath, overwrite) {
255
+ if (overwrite) {
256
+ return;
257
+ }
258
+ try {
259
+ await sftpStat(sftp, remotePath, true);
260
+ }
261
+ catch (error) {
262
+ if (isMissingPathError(error)) {
263
+ return;
264
+ }
265
+ throw error;
266
+ }
267
+ throw new McpToolError("remote_path_exists", "Remote path exists and overwrite=false", { remotePath });
268
+ }
269
+ async function ensureLocalOverwritePolicy(localPath, overwrite) {
270
+ if (overwrite) {
271
+ return;
272
+ }
273
+ try {
274
+ await statLocal(localPath);
275
+ }
276
+ catch (error) {
277
+ const nodeError = error;
278
+ if (nodeError.code === "ENOENT") {
279
+ return;
280
+ }
281
+ throw error;
282
+ }
283
+ throw new McpToolError("local_path_exists", "Local path exists and overwrite=false", { localPath });
284
+ }
285
+ function createBaseJob(sessionId, kind, localPath, remotePath, atomic) {
286
+ const now = new Date().toISOString();
287
+ return {
288
+ id: randomUUID(),
289
+ sessionId,
290
+ kind,
291
+ state: "queued",
292
+ localPath,
293
+ remotePath,
294
+ totalBytes: 0,
295
+ transferredBytes: 0,
296
+ resumeOffsetBytes: 0,
297
+ createdAt: now,
298
+ updatedAt: now,
299
+ atomic,
300
+ cancelRequested: false,
301
+ };
302
+ }
303
+ function summarizeJob(job) {
304
+ const elapsedSeconds = job.startedAt === undefined ? 0 : Math.max((Date.now() - Date.parse(job.startedAt)) / 1_000, 0.001);
305
+ const bytesThisRun = Math.max(job.transferredBytes - job.resumeOffsetBytes, 0);
306
+ const bytesPerSecond = job.state === "running" ? Math.round(bytesThisRun / elapsedSeconds) : 0;
307
+ const remainingBytes = Math.max(job.totalBytes - job.transferredBytes, 0);
308
+ const summary = {
309
+ id: job.id,
310
+ sessionId: job.sessionId,
311
+ kind: job.kind,
312
+ state: job.state,
313
+ localPath: job.localPath,
314
+ remotePath: job.remotePath,
315
+ totalBytes: job.totalBytes,
316
+ transferredBytes: job.transferredBytes,
317
+ resumeOffsetBytes: job.resumeOffsetBytes,
318
+ percent: job.totalBytes === 0 ? 0 : Number(((job.transferredBytes / job.totalBytes) * 100).toFixed(2)),
319
+ bytesPerSecond,
320
+ etaSeconds: bytesPerSecond > 0 ? Math.ceil(remainingBytes / bytesPerSecond) : null,
321
+ createdAt: job.createdAt,
322
+ updatedAt: job.updatedAt,
323
+ atomic: job.atomic,
324
+ };
325
+ if (job.startedAt !== undefined) {
326
+ summary.startedAt = job.startedAt;
327
+ }
328
+ if (job.finishedAt !== undefined) {
329
+ summary.finishedAt = job.finishedAt;
330
+ }
331
+ if (job.error !== undefined) {
332
+ summary.error = job.error;
333
+ }
334
+ if (job.tempPath !== undefined) {
335
+ summary.tempPath = job.tempPath;
336
+ }
337
+ return summary;
338
+ }
339
+ //# sourceMappingURL=transfer-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer-manager.js","sourceRoot":"","sources":["../src/transfer-manager.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "enterprise-ssh-mcp-server",
3
+ "version": "0.3.0",
4
+ "description": "Enterprise SSH/SFTP MCP server with persistent sessions, interactive shells, transfer jobs, and port forwarding.",
5
+ "type": "module",
6
+ "keywords": [
7
+ "mcp",
8
+ "ssh",
9
+ "sftp",
10
+ "model-context-protocol"
11
+ ],
12
+ "homepage": "https://github.com/wyksean448/enterprise-ssh-mcp-server#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/wyksean448/enterprise-ssh-mcp-server/issues"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/wyksean448/enterprise-ssh-mcp-server.git"
19
+ },
20
+ "bin": {
21
+ "enterprise-ssh-mcp": "dist/index.js"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "scripts": {
28
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
29
+ "build": "npm run clean && tsc -p tsconfig.json",
30
+ "typecheck": "tsc -p tsconfig.json --noEmit",
31
+ "test": "vitest run",
32
+ "prepublishOnly": "npm run typecheck && npm test && npm run build",
33
+ "start": "node dist/index.js",
34
+ "dev": "tsx src/index.ts"
35
+ },
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.29.0",
38
+ "ssh2": "^1.17.0",
39
+ "zod": "^3.25.76"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^24.0.15",
43
+ "@types/ssh2": "^1.15.5",
44
+ "tsx": "^4.20.3",
45
+ "typescript": "^5.8.3",
46
+ "vitest": "^3.2.4"
47
+ },
48
+ "engines": {
49
+ "node": ">=20.0.0"
50
+ },
51
+ "license": "MIT"
52
+ }