ssh-mcp-pro 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.
- package/AGENTS.md +127 -0
- package/ARCHITECTURE.md +145 -0
- package/LICENSE +21 -0
- package/LICENSES/MIT.txt +21 -0
- package/MIGRATION.md +14 -0
- package/README.md +175 -0
- package/REGISTRY_SUBMISSION.md +38 -0
- package/SECURITY.md +40 -0
- package/SECURITY_DECISIONS.md +59 -0
- package/dist/agent-bin.d.ts +3 -0
- package/dist/agent-bin.d.ts.map +1 -0
- package/dist/agent-bin.js +8 -0
- package/dist/agent-bin.js.map +1 -0
- package/dist/audit.d.ts +25 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +50 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth.d.ts +4 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +33 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +103 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +490 -0
- package/dist/config.js.map +1 -0
- package/dist/connector-credentials.d.ts +8 -0
- package/dist/connector-credentials.d.ts.map +1 -0
- package/dist/connector-credentials.js +132 -0
- package/dist/connector-credentials.js.map +1 -0
- package/dist/connector-profile.d.ts +17 -0
- package/dist/connector-profile.d.ts.map +1 -0
- package/dist/connector-profile.js +81 -0
- package/dist/connector-profile.js.map +1 -0
- package/dist/container.d.ts +18 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +52 -0
- package/dist/container.js.map +1 -0
- package/dist/detect.d.ts +7 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +271 -0
- package/dist/detect.js.map +1 -0
- package/dist/ensure.d.ts +17 -0
- package/dist/ensure.d.ts.map +1 -0
- package/dist/ensure.js +531 -0
- package/dist/ensure.js.map +1 -0
- package/dist/errors.d.ts +54 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +84 -0
- package/dist/errors.js.map +1 -0
- package/dist/fs-tools.d.ts +26 -0
- package/dist/fs-tools.d.ts.map +1 -0
- package/dist/fs-tools.js +599 -0
- package/dist/fs-tools.js.map +1 -0
- package/dist/http-rate-limit.d.ts +9 -0
- package/dist/http-rate-limit.d.ts.map +1 -0
- package/dist/http-rate-limit.js +41 -0
- package/dist/http-rate-limit.js.map +1 -0
- package/dist/http-security.d.ts +22 -0
- package/dist/http-security.d.ts.map +1 -0
- package/dist/http-security.js +88 -0
- package/dist/http-security.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +201 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.d.ts +52 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +180 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp.d.ts +16 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +159 -0
- package/dist/mcp.js.map +1 -0
- package/dist/metrics.d.ts +95 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +204 -0
- package/dist/metrics.js.map +1 -0
- package/dist/oauth.d.ts +14 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +105 -0
- package/dist/oauth.js.map +1 -0
- package/dist/policy.d.ts +64 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +368 -0
- package/dist/policy.js.map +1 -0
- package/dist/process.d.ts +24 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +212 -0
- package/dist/process.js.map +1 -0
- package/dist/prompts.d.ts +49 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +191 -0
- package/dist/prompts.js.map +1 -0
- package/dist/rate-limiter.d.ts +57 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +141 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/remote/agent-cli.d.ts +2 -0
- package/dist/remote/agent-cli.d.ts.map +1 -0
- package/dist/remote/agent-cli.js +270 -0
- package/dist/remote/agent-cli.js.map +1 -0
- package/dist/remote/agent-executor.d.ts +26 -0
- package/dist/remote/agent-executor.d.ts.map +1 -0
- package/dist/remote/agent-executor.js +400 -0
- package/dist/remote/agent-executor.js.map +1 -0
- package/dist/remote/config.d.ts +3 -0
- package/dist/remote/config.d.ts.map +1 -0
- package/dist/remote/config.js +52 -0
- package/dist/remote/config.js.map +1 -0
- package/dist/remote/control-plane.d.ts +57 -0
- package/dist/remote/control-plane.d.ts.map +1 -0
- package/dist/remote/control-plane.js +1248 -0
- package/dist/remote/control-plane.js.map +1 -0
- package/dist/remote/crypto.d.ts +38 -0
- package/dist/remote/crypto.d.ts.map +1 -0
- package/dist/remote/crypto.js +143 -0
- package/dist/remote/crypto.js.map +1 -0
- package/dist/remote/mcp-tools.d.ts +10 -0
- package/dist/remote/mcp-tools.d.ts.map +1 -0
- package/dist/remote/mcp-tools.js +201 -0
- package/dist/remote/mcp-tools.js.map +1 -0
- package/dist/remote/policy.d.ts +11 -0
- package/dist/remote/policy.d.ts.map +1 -0
- package/dist/remote/policy.js +94 -0
- package/dist/remote/policy.js.map +1 -0
- package/dist/remote/schemas.d.ts +298 -0
- package/dist/remote/schemas.d.ts.map +1 -0
- package/dist/remote/schemas.js +111 -0
- package/dist/remote/schemas.js.map +1 -0
- package/dist/remote/scopes.d.ts +6 -0
- package/dist/remote/scopes.d.ts.map +1 -0
- package/dist/remote/scopes.js +24 -0
- package/dist/remote/scopes.js.map +1 -0
- package/dist/remote/store.d.ts +45 -0
- package/dist/remote/store.d.ts.map +1 -0
- package/dist/remote/store.js +355 -0
- package/dist/remote/store.js.map +1 -0
- package/dist/remote/types.d.ts +183 -0
- package/dist/remote/types.d.ts.map +1 -0
- package/dist/remote/types.js +103 -0
- package/dist/remote/types.js.map +1 -0
- package/dist/remote/util.d.ts +6 -0
- package/dist/remote/util.d.ts.map +1 -0
- package/dist/remote/util.js +45 -0
- package/dist/remote/util.js.map +1 -0
- package/dist/remote/websocket.d.ts +26 -0
- package/dist/remote/websocket.d.ts.map +1 -0
- package/dist/remote/websocket.js +167 -0
- package/dist/remote/websocket.js.map +1 -0
- package/dist/render-http.d.ts +2 -0
- package/dist/render-http.d.ts.map +1 -0
- package/dist/render-http.js +14 -0
- package/dist/render-http.js.map +1 -0
- package/dist/resources.d.ts +19 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +96 -0
- package/dist/resources.js.map +1 -0
- package/dist/retry.d.ts +45 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +120 -0
- package/dist/retry.js.map +1 -0
- package/dist/safety.d.ts +31 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +174 -0
- package/dist/safety.js.map +1 -0
- package/dist/server-http.d.ts +2 -0
- package/dist/server-http.d.ts.map +1 -0
- package/dist/server-http.js +432 -0
- package/dist/server-http.js.map +1 -0
- package/dist/session.d.ts +116 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +666 -0
- package/dist/session.js.map +1 -0
- package/dist/shell.d.ts +10 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +83 -0
- package/dist/shell.js.map +1 -0
- package/dist/ssh-config.d.ts +94 -0
- package/dist/ssh-config.d.ts.map +1 -0
- package/dist/ssh-config.js +234 -0
- package/dist/ssh-config.js.map +1 -0
- package/dist/streaming.d.ts +36 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +140 -0
- package/dist/streaming.js.map +1 -0
- package/dist/telemetry.d.ts +17 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +101 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tools/connector.provider.d.ts +28 -0
- package/dist/tools/connector.provider.d.ts.map +1 -0
- package/dist/tools/connector.provider.js +360 -0
- package/dist/tools/connector.provider.js.map +1 -0
- package/dist/tools/ensure.provider.d.ts +18 -0
- package/dist/tools/ensure.provider.d.ts.map +1 -0
- package/dist/tools/ensure.provider.js +173 -0
- package/dist/tools/ensure.provider.js.map +1 -0
- package/dist/tools/fs.provider.d.ts +21 -0
- package/dist/tools/fs.provider.d.ts.map +1 -0
- package/dist/tools/fs.provider.js +259 -0
- package/dist/tools/fs.provider.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +68 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/metadata.d.ts +11 -0
- package/dist/tools/metadata.d.ts.map +1 -0
- package/dist/tools/metadata.js +10 -0
- package/dist/tools/metadata.js.map +1 -0
- package/dist/tools/output-schemas.d.ts +217 -0
- package/dist/tools/output-schemas.d.ts.map +1 -0
- package/dist/tools/output-schemas.js +300 -0
- package/dist/tools/output-schemas.js.map +1 -0
- package/dist/tools/process.provider.d.ts +22 -0
- package/dist/tools/process.provider.d.ts.map +1 -0
- package/dist/tools/process.provider.js +146 -0
- package/dist/tools/process.provider.js.map +1 -0
- package/dist/tools/registry.d.ts +12 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +163 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/results.d.ts +4 -0
- package/dist/tools/results.d.ts.map +1 -0
- package/dist/tools/results.js +5 -0
- package/dist/tools/results.js.map +1 -0
- package/dist/tools/session.provider.d.ts +23 -0
- package/dist/tools/session.provider.d.ts.map +1 -0
- package/dist/tools/session.provider.js +299 -0
- package/dist/tools/session.provider.js.map +1 -0
- package/dist/tools/system.provider.d.ts +18 -0
- package/dist/tools/system.provider.d.ts.map +1 -0
- package/dist/tools/system.provider.js +81 -0
- package/dist/tools/system.provider.js.map +1 -0
- package/dist/tools/transfer.provider.d.ts +16 -0
- package/dist/tools/transfer.provider.d.ts.map +1 -0
- package/dist/tools/transfer.provider.js +85 -0
- package/dist/tools/transfer.provider.js.map +1 -0
- package/dist/tools/tunnel.provider.d.ts +18 -0
- package/dist/tools/tunnel.provider.d.ts.map +1 -0
- package/dist/tools/tunnel.provider.js +142 -0
- package/dist/tools/tunnel.provider.js.map +1 -0
- package/dist/tools/types.d.ts +16 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/transfer.d.ts +40 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +363 -0
- package/dist/transfer.js.map +1 -0
- package/dist/tunnel.d.ts +37 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +234 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/types.d.ts +341 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +184 -0
- package/dist/types.js.map +1 -0
- package/docs/docker.md +22 -0
- package/examples/README.md +77 -0
- package/mcp.json +21 -0
- package/package.json +147 -0
- package/registry/ssh-mcp-pro/mcp.json +21 -0
- package/server.json +76 -0
package/dist/fs-tools.js
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createFilesystemError, createLimitError, wrapError } from "./errors.js";
|
|
3
|
+
import { logger } from "./logging.js";
|
|
4
|
+
import { buildRemoteCommand } from "./shell.js";
|
|
5
|
+
import { ErrorCode } from "./types.js";
|
|
6
|
+
function shellQuote(value) {
|
|
7
|
+
return `'${String(value).replace(/'/g, `'"'"'`)}'`;
|
|
8
|
+
}
|
|
9
|
+
function createDirListResult(entries, nextToken) {
|
|
10
|
+
return nextToken ? { entries, nextToken } : { entries };
|
|
11
|
+
}
|
|
12
|
+
function hasSftp(session) {
|
|
13
|
+
return !!session?.sftp;
|
|
14
|
+
}
|
|
15
|
+
function tempPathFor(targetPath) {
|
|
16
|
+
const normalizedPath = targetPath.replace(/\\/g, "/");
|
|
17
|
+
const slashIndex = normalizedPath.lastIndexOf("/");
|
|
18
|
+
const directory = slashIndex >= 0 ? normalizedPath.slice(0, slashIndex + 1) : "";
|
|
19
|
+
const baseName = slashIndex >= 0 ? normalizedPath.slice(slashIndex + 1) : normalizedPath;
|
|
20
|
+
const safeBaseName = baseName.length > 0 ? baseName : "write";
|
|
21
|
+
return `${directory}.${safeBaseName}.${randomUUID()}.tmp`;
|
|
22
|
+
}
|
|
23
|
+
function getSftpOrThrow(session) {
|
|
24
|
+
if (!session.sftp) {
|
|
25
|
+
throw createFilesystemError("SFTP subsystem is unavailable for this session");
|
|
26
|
+
}
|
|
27
|
+
return session.sftp;
|
|
28
|
+
}
|
|
29
|
+
function sftpReadFile(sftp, path) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
sftp.readFile(path, (err, data) => {
|
|
32
|
+
if (err) {
|
|
33
|
+
reject(err);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
resolve(data);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function sftpWriteFile(sftp, path, data) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
sftp.writeFile(path, data, {}, (err) => {
|
|
43
|
+
if (err) {
|
|
44
|
+
reject(err);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
resolve();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function sftpStat(sftp, path) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
sftp.stat(path, (err, stats) => {
|
|
54
|
+
if (err) {
|
|
55
|
+
reject(err);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
resolve(stats);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function sftpReaddir(sftp, path) {
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
sftp.readdir(path, (err, list) => {
|
|
65
|
+
if (err) {
|
|
66
|
+
reject(err);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
resolve(list);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function sftpMkdir(sftp, path) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
sftp.mkdir(path, (err) => {
|
|
76
|
+
if (err) {
|
|
77
|
+
reject(err);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function sftpRmdir(sftp, path) {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
sftp.rmdir(path, (err) => {
|
|
87
|
+
if (err) {
|
|
88
|
+
reject(err);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
resolve();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function sftpUnlink(sftp, path) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
sftp.unlink(path, (err) => {
|
|
98
|
+
if (err) {
|
|
99
|
+
reject(err);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
resolve();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function sftpRename(sftp, oldPath, newPath) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
sftp.rename(oldPath, newPath, (err) => {
|
|
109
|
+
if (err) {
|
|
110
|
+
reject(err);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
resolve();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function sftpChmod(sftp, path, mode) {
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
sftp.chmod(path, mode, (err) => {
|
|
120
|
+
if (err) {
|
|
121
|
+
reject(err);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
resolve();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async function sftpMkdirRecursive(sftp, dirPath) {
|
|
129
|
+
const parts = dirPath.split("/").filter((part) => part);
|
|
130
|
+
let currentPath = dirPath.startsWith("/") ? "" : ".";
|
|
131
|
+
for (const part of parts) {
|
|
132
|
+
currentPath = currentPath === "" ? `/${part}` : `${currentPath}/${part}`;
|
|
133
|
+
try {
|
|
134
|
+
await sftpStat(sftp, currentPath);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
try {
|
|
138
|
+
await sftpMkdir(sftp, currentPath);
|
|
139
|
+
}
|
|
140
|
+
catch (mkdirErr) {
|
|
141
|
+
if (mkdirErr?.code !== 4) {
|
|
142
|
+
throw mkdirErr;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function sftpRmdirRecursive(sftp, dirPath) {
|
|
149
|
+
const entries = await sftpReaddir(sftp, dirPath);
|
|
150
|
+
for (const entry of entries) {
|
|
151
|
+
const entryPath = `${dirPath}/${entry.filename}`;
|
|
152
|
+
const mode = entry.attrs.mode ?? 0;
|
|
153
|
+
const isDir = (mode & 0o170000) === 0o040000;
|
|
154
|
+
if (isDir) {
|
|
155
|
+
await sftpRmdirRecursive(sftp, entryPath);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
await sftpUnlink(sftp, entryPath);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
await sftpRmdir(sftp, dirPath);
|
|
162
|
+
}
|
|
163
|
+
const PORTABLE_STAT_FIELDS_COMMAND = 'type=other; if [ -L "$target" ]; then type=symlink; elif [ -d "$target" ]; then type=directory; elif [ -f "$target" ]; then type=file; fi; size=$( (stat -c %s "$target" 2>/dev/null || stat -f %z "$target" 2>/dev/null || wc -c < "$target" 2>/dev/null) | tr -d " " | head -n 1); mtime=$( (stat -c %Y "$target" 2>/dev/null || stat -f %m "$target" 2>/dev/null || echo 0) | head -n 1); mode=$( (stat -c %a "$target" 2>/dev/null || stat -f %Lp "$target" 2>/dev/null || echo 0) | head -n 1)';
|
|
164
|
+
const PORTABLE_STAT_COMMAND = `${PORTABLE_STAT_FIELDS_COMMAND}; printf "%s\\t%s\\t%s\\t%s" "$type" "\${size:-0}" "\${mtime:-0}" "\${mode:-0}"`;
|
|
165
|
+
export function createFsService({ sessionManager, metrics, config, policy, }) {
|
|
166
|
+
async function execFallback(sessionId, command) {
|
|
167
|
+
const session = sessionManager.getSession(sessionId);
|
|
168
|
+
if (!session) {
|
|
169
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
170
|
+
}
|
|
171
|
+
const osInfo = await sessionManager.getOSInfo(sessionId);
|
|
172
|
+
const shellCommand = buildRemoteCommand(command, osInfo);
|
|
173
|
+
const result = await session.ssh.execCommand(shellCommand);
|
|
174
|
+
if ((result.code ?? 0) !== 0) {
|
|
175
|
+
throw new Error(result.stderr || result.stdout || `Remote command failed with code ${result.code}`);
|
|
176
|
+
}
|
|
177
|
+
return result.stdout ?? "";
|
|
178
|
+
}
|
|
179
|
+
async function readFile(sessionId, path, encoding = "utf8", maxBytes) {
|
|
180
|
+
logger.debug("Reading file", { sessionId, path, encoding });
|
|
181
|
+
const session = sessionManager.getSession(sessionId);
|
|
182
|
+
if (!session) {
|
|
183
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
policy.assertAllowed({
|
|
187
|
+
action: "fs.read",
|
|
188
|
+
path,
|
|
189
|
+
mode: session.info.policyMode,
|
|
190
|
+
});
|
|
191
|
+
const effectiveMaxBytes = maxBytes ?? config.maxFileSize;
|
|
192
|
+
const size = await getFileSizeInternal(sessionId, path);
|
|
193
|
+
if (size > effectiveMaxBytes) {
|
|
194
|
+
throw createLimitError(`File ${path} is ${size} bytes, which exceeds the ${effectiveMaxBytes} byte read limit`, "Use file_download for large files or raise SSH_MCP_MAX_FILE_SIZE intentionally.");
|
|
195
|
+
}
|
|
196
|
+
if (!hasSftp(session)) {
|
|
197
|
+
const data = await execFallback(sessionId, `cat ${shellQuote(path)}`);
|
|
198
|
+
metrics.recordFileRead(Buffer.byteLength(data, "utf8"));
|
|
199
|
+
logger.debug("File read successfully via SSH fallback", {
|
|
200
|
+
sessionId,
|
|
201
|
+
path,
|
|
202
|
+
size: data.length,
|
|
203
|
+
});
|
|
204
|
+
return data;
|
|
205
|
+
}
|
|
206
|
+
const sftp = getSftpOrThrow(session);
|
|
207
|
+
const data = await sftpReadFile(sftp, path);
|
|
208
|
+
const result = data.toString(encoding);
|
|
209
|
+
metrics.recordFileRead(data.length);
|
|
210
|
+
logger.debug("File read successfully", {
|
|
211
|
+
sessionId,
|
|
212
|
+
path,
|
|
213
|
+
size: result.length,
|
|
214
|
+
});
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
logger.error("Failed to read file", { sessionId, path, error });
|
|
219
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to read file ${path}. Check if the file exists and is readable.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async function writeFile(sessionId, path, data, mode) {
|
|
223
|
+
logger.debug("Writing file", { sessionId, path, size: data.length, mode });
|
|
224
|
+
const session = sessionManager.getSession(sessionId);
|
|
225
|
+
if (!session) {
|
|
226
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const decision = policy.assertAllowed({
|
|
230
|
+
action: "fs.write",
|
|
231
|
+
path,
|
|
232
|
+
mode: session.info.policyMode,
|
|
233
|
+
});
|
|
234
|
+
if (decision.mode === "explain") {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
const writeBytes = Buffer.byteLength(data, "utf8");
|
|
238
|
+
if (writeBytes > config.maxFileWriteBytes) {
|
|
239
|
+
throw createLimitError(`Write payload is ${writeBytes} bytes, which exceeds the ${config.maxFileWriteBytes} byte write limit`, "Use file_upload for large files or raise SSH_MCP_MAX_FILE_WRITE_BYTES intentionally.");
|
|
240
|
+
}
|
|
241
|
+
if (!hasSftp(session)) {
|
|
242
|
+
const tempPath = tempPathFor(path);
|
|
243
|
+
const chmodCommand = mode !== undefined ? `chmod ${mode.toString(8)} ${shellQuote(tempPath)}\n` : "";
|
|
244
|
+
await execFallback(sessionId, `printf %s ${shellQuote(data)} > ${shellQuote(tempPath)}\n${chmodCommand}mv ${shellQuote(tempPath)} ${shellQuote(path)}`);
|
|
245
|
+
metrics.recordFileWrite(writeBytes);
|
|
246
|
+
logger.debug("File written successfully via SSH fallback", {
|
|
247
|
+
sessionId,
|
|
248
|
+
path,
|
|
249
|
+
});
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
const sftp = getSftpOrThrow(session);
|
|
253
|
+
const tempPath = tempPathFor(path);
|
|
254
|
+
const dataBuffer = Buffer.from(data, "utf8");
|
|
255
|
+
try {
|
|
256
|
+
await sftpWriteFile(sftp, tempPath, dataBuffer);
|
|
257
|
+
if (mode !== undefined) {
|
|
258
|
+
await sftpChmod(sftp, tempPath, mode);
|
|
259
|
+
}
|
|
260
|
+
await sftpRename(sftp, tempPath, path);
|
|
261
|
+
metrics.recordFileWrite(writeBytes);
|
|
262
|
+
logger.debug("File written successfully", { sessionId, path });
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
catch (writeError) {
|
|
266
|
+
try {
|
|
267
|
+
await sftpUnlink(sftp, tempPath);
|
|
268
|
+
logger.debug("Cleaned up temp file after error", { tempPath });
|
|
269
|
+
}
|
|
270
|
+
catch (cleanupError) {
|
|
271
|
+
logger.warn("Failed to clean up temp file", {
|
|
272
|
+
tempPath,
|
|
273
|
+
cleanupError,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
throw writeError;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
logger.error("Failed to write file", { sessionId, path, error });
|
|
281
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to write file ${path}. Check directory permissions and disk space.`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async function statFileInternal(sessionId, path) {
|
|
285
|
+
const session = sessionManager.getSession(sessionId);
|
|
286
|
+
if (!session) {
|
|
287
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
288
|
+
}
|
|
289
|
+
if (!hasSftp(session)) {
|
|
290
|
+
const output = await execFallback(sessionId, `target=${shellQuote(path)}; ${PORTABLE_STAT_COMMAND}`);
|
|
291
|
+
const [type = "other", size = "0", mtime = "0", mode = "0"] = output.trim().split("\t");
|
|
292
|
+
return {
|
|
293
|
+
size: Number(size),
|
|
294
|
+
mtime: new Date(Number(mtime) * 1000),
|
|
295
|
+
mode: parseInt(mode, 8),
|
|
296
|
+
type: type,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const sftp = getSftpOrThrow(session);
|
|
300
|
+
const stats = await sftpStat(sftp, path);
|
|
301
|
+
let type = "other";
|
|
302
|
+
const mode = stats.mode ?? 0;
|
|
303
|
+
if ((mode & 0o170000) === 0o100000) {
|
|
304
|
+
type = "file";
|
|
305
|
+
}
|
|
306
|
+
else if ((mode & 0o170000) === 0o040000) {
|
|
307
|
+
type = "directory";
|
|
308
|
+
}
|
|
309
|
+
else if ((mode & 0o170000) === 0o120000) {
|
|
310
|
+
type = "symlink";
|
|
311
|
+
}
|
|
312
|
+
else if (typeof stats.isFile === "function") {
|
|
313
|
+
if (stats.isFile()) {
|
|
314
|
+
type = "file";
|
|
315
|
+
}
|
|
316
|
+
else if (stats.isDirectory()) {
|
|
317
|
+
type = "directory";
|
|
318
|
+
}
|
|
319
|
+
else if (stats.isSymbolicLink?.()) {
|
|
320
|
+
type = "symlink";
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const statInfo = {
|
|
324
|
+
size: stats.size ?? 0,
|
|
325
|
+
mtime: new Date(typeof stats.mtime === "number" ? stats.mtime * 1000 : Date.now()),
|
|
326
|
+
mode,
|
|
327
|
+
type,
|
|
328
|
+
};
|
|
329
|
+
logger.debug("File stats retrieved", {
|
|
330
|
+
sessionId,
|
|
331
|
+
path,
|
|
332
|
+
type,
|
|
333
|
+
size: stats.size,
|
|
334
|
+
});
|
|
335
|
+
return statInfo;
|
|
336
|
+
}
|
|
337
|
+
async function statFile(sessionId, path) {
|
|
338
|
+
logger.debug("Getting file stats", { sessionId, path });
|
|
339
|
+
const session = sessionManager.getSession(sessionId);
|
|
340
|
+
if (!session) {
|
|
341
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
342
|
+
}
|
|
343
|
+
try {
|
|
344
|
+
policy.assertAllowed({
|
|
345
|
+
action: "fs.stat",
|
|
346
|
+
path,
|
|
347
|
+
mode: session.info.policyMode,
|
|
348
|
+
});
|
|
349
|
+
return await statFileInternal(sessionId, path);
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
logger.error("Failed to get file stats", { sessionId, path, error });
|
|
353
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to get stats for ${path}. Check if the path exists.`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
async function listDirectory(sessionId, path, page, limit = 100) {
|
|
357
|
+
logger.debug("Listing directory", { sessionId, path, page, limit });
|
|
358
|
+
const session = sessionManager.getSession(sessionId);
|
|
359
|
+
if (!session) {
|
|
360
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
policy.assertAllowed({
|
|
364
|
+
action: "fs.list",
|
|
365
|
+
path,
|
|
366
|
+
mode: session.info.policyMode,
|
|
367
|
+
});
|
|
368
|
+
if (!hasSftp(session)) {
|
|
369
|
+
const output = await execFallback(sessionId, `dir=${shellQuote(path)}; for item in "$dir"/* "$dir"/.[!.]* "$dir"/..?*; do [ -e "$item" ] || continue; name=$(basename "$item"); target="$item"; ${PORTABLE_STAT_FIELDS_COMMAND}; printf "%s\\t%s\\t%s\\t%s\\n" "$name" "$type" "\${size:-0}" "\${mtime:-0}"; done`);
|
|
370
|
+
const entries = output
|
|
371
|
+
.split(/\r?\n/)
|
|
372
|
+
.filter(Boolean)
|
|
373
|
+
.map((line) => {
|
|
374
|
+
const [name = "", typeName = "other", size = "0", mtime = "0"] = line.split("\t");
|
|
375
|
+
return {
|
|
376
|
+
name,
|
|
377
|
+
type: typeName,
|
|
378
|
+
size: Number(size),
|
|
379
|
+
mtime: new Date(Number(mtime) * 1000),
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
if (page !== undefined) {
|
|
383
|
+
const startIndex = page * limit;
|
|
384
|
+
const endIndex = startIndex + limit;
|
|
385
|
+
return createDirListResult(entries.slice(startIndex, endIndex), endIndex < entries.length ? String(page + 1) : undefined);
|
|
386
|
+
}
|
|
387
|
+
return { entries };
|
|
388
|
+
}
|
|
389
|
+
const sftp = getSftpOrThrow(session);
|
|
390
|
+
const fileList = await sftpReaddir(sftp, path);
|
|
391
|
+
const entries = fileList.map((item) => {
|
|
392
|
+
let type = "other";
|
|
393
|
+
const attrs = item.attrs;
|
|
394
|
+
const mode = attrs.mode ?? 0;
|
|
395
|
+
if ((mode & 0o170000) === 0o100000) {
|
|
396
|
+
type = "file";
|
|
397
|
+
}
|
|
398
|
+
else if ((mode & 0o170000) === 0o040000) {
|
|
399
|
+
type = "directory";
|
|
400
|
+
}
|
|
401
|
+
else if ((mode & 0o170000) === 0o120000) {
|
|
402
|
+
type = "symlink";
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
name: item.filename,
|
|
406
|
+
type,
|
|
407
|
+
size: attrs.size,
|
|
408
|
+
mtime: new Date(typeof attrs.mtime === "number" ? attrs.mtime * 1000 : Date.now()),
|
|
409
|
+
mode: attrs.mode,
|
|
410
|
+
};
|
|
411
|
+
});
|
|
412
|
+
if (page !== undefined) {
|
|
413
|
+
const startIndex = page * limit;
|
|
414
|
+
const endIndex = startIndex + limit;
|
|
415
|
+
const paginatedEntries = entries.slice(startIndex, endIndex);
|
|
416
|
+
const hasMore = endIndex < entries.length;
|
|
417
|
+
logger.debug("Directory listed with pagination", {
|
|
418
|
+
sessionId,
|
|
419
|
+
path,
|
|
420
|
+
total: entries.length,
|
|
421
|
+
page,
|
|
422
|
+
returned: paginatedEntries.length,
|
|
423
|
+
hasMore,
|
|
424
|
+
});
|
|
425
|
+
return createDirListResult(paginatedEntries, hasMore ? String(page + 1) : undefined);
|
|
426
|
+
}
|
|
427
|
+
logger.debug("Directory listed", {
|
|
428
|
+
sessionId,
|
|
429
|
+
path,
|
|
430
|
+
count: entries.length,
|
|
431
|
+
});
|
|
432
|
+
return { entries };
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
logger.error("Failed to list directory", { sessionId, path, error });
|
|
436
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to list directory ${path}. Check if the directory exists and is readable.`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async function makeDirectories(sessionId, path) {
|
|
440
|
+
logger.debug("Creating directories", { sessionId, path });
|
|
441
|
+
const session = sessionManager.getSession(sessionId);
|
|
442
|
+
if (!session) {
|
|
443
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
const decision = policy.assertAllowed({
|
|
447
|
+
action: "fs.mkdir",
|
|
448
|
+
path,
|
|
449
|
+
mode: session.info.policyMode,
|
|
450
|
+
});
|
|
451
|
+
if (decision.mode === "explain") {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
if (!hasSftp(session)) {
|
|
455
|
+
await execFallback(sessionId, `mkdir -p ${shellQuote(path)}`);
|
|
456
|
+
logger.debug("Directories created successfully via SSH fallback", {
|
|
457
|
+
sessionId,
|
|
458
|
+
path,
|
|
459
|
+
});
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
const sftp = getSftpOrThrow(session);
|
|
463
|
+
await sftpMkdirRecursive(sftp, path);
|
|
464
|
+
logger.debug("Directories created successfully", { sessionId, path });
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
logger.error("Failed to create directories", { sessionId, path, error });
|
|
469
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to create directories ${path}. Check parent directory permissions.`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
async function removeRecursive(sessionId, path) {
|
|
473
|
+
logger.debug("Removing path recursively", { sessionId, path });
|
|
474
|
+
const session = sessionManager.getSession(sessionId);
|
|
475
|
+
if (!session) {
|
|
476
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
const decision = policy.assertAllowed({
|
|
480
|
+
action: "fs.remove",
|
|
481
|
+
path,
|
|
482
|
+
mode: session.info.policyMode,
|
|
483
|
+
destructive: true,
|
|
484
|
+
});
|
|
485
|
+
if (decision.mode === "explain") {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
if (!hasSftp(session)) {
|
|
489
|
+
await execFallback(sessionId, `rm -rf ${shellQuote(path)}`);
|
|
490
|
+
logger.debug("Path removed successfully via SSH fallback", {
|
|
491
|
+
sessionId,
|
|
492
|
+
path,
|
|
493
|
+
});
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
const sftp = getSftpOrThrow(session);
|
|
497
|
+
const stats = await sftpStat(sftp, path);
|
|
498
|
+
const mode = stats.mode ?? 0;
|
|
499
|
+
const isDirectory = (mode & 0o170000) === 0o040000;
|
|
500
|
+
if (isDirectory) {
|
|
501
|
+
await sftpRmdirRecursive(sftp, path);
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
await sftpUnlink(sftp, path);
|
|
505
|
+
}
|
|
506
|
+
logger.debug("Path removed successfully", { sessionId, path });
|
|
507
|
+
metrics.recordFileDelete();
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
logger.error("Failed to remove path", { sessionId, path, error });
|
|
512
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to remove ${path}. Check if the path exists and you have write permissions.`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
async function renameFile(sessionId, from, to) {
|
|
516
|
+
logger.debug("Renaming file", { sessionId, from, to });
|
|
517
|
+
const session = sessionManager.getSession(sessionId);
|
|
518
|
+
if (!session) {
|
|
519
|
+
throw new Error(`Session ${sessionId} not found or expired`);
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
const decision = policy.assertAllowed({
|
|
523
|
+
action: "fs.rename",
|
|
524
|
+
path: from,
|
|
525
|
+
secondaryPath: to,
|
|
526
|
+
mode: session.info.policyMode,
|
|
527
|
+
});
|
|
528
|
+
if (decision.mode === "explain") {
|
|
529
|
+
return true;
|
|
530
|
+
}
|
|
531
|
+
if (!hasSftp(session)) {
|
|
532
|
+
await execFallback(sessionId, `mv ${shellQuote(from)} ${shellQuote(to)}`);
|
|
533
|
+
logger.debug("File renamed successfully via SSH fallback", {
|
|
534
|
+
sessionId,
|
|
535
|
+
from,
|
|
536
|
+
to,
|
|
537
|
+
});
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
const sftp = getSftpOrThrow(session);
|
|
541
|
+
await sftpRename(sftp, from, to);
|
|
542
|
+
logger.debug("File renamed successfully", { sessionId, from, to });
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
logger.error("Failed to rename file", { sessionId, from, to, error });
|
|
547
|
+
throw wrapError(error, ErrorCode.EFS, `Failed to rename ${from} to ${to}. Check if the source exists and destination is writable.`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
async function pathExists(sessionId, path) {
|
|
551
|
+
try {
|
|
552
|
+
await statFile(sessionId, path);
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async function getFileSize(sessionId, path) {
|
|
560
|
+
const stats = await statFile(sessionId, path);
|
|
561
|
+
return stats.size;
|
|
562
|
+
}
|
|
563
|
+
async function getFileSizeInternal(sessionId, path) {
|
|
564
|
+
const stats = await statFileInternal(sessionId, path);
|
|
565
|
+
return stats.size;
|
|
566
|
+
}
|
|
567
|
+
async function isDirectory(sessionId, path) {
|
|
568
|
+
try {
|
|
569
|
+
const stats = await statFile(sessionId, path);
|
|
570
|
+
return stats.type === "directory";
|
|
571
|
+
}
|
|
572
|
+
catch {
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
async function isFile(sessionId, path) {
|
|
577
|
+
try {
|
|
578
|
+
const stats = await statFile(sessionId, path);
|
|
579
|
+
return stats.type === "file";
|
|
580
|
+
}
|
|
581
|
+
catch {
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
readFile,
|
|
587
|
+
writeFile,
|
|
588
|
+
statFile,
|
|
589
|
+
listDirectory,
|
|
590
|
+
makeDirectories,
|
|
591
|
+
removeRecursive,
|
|
592
|
+
renameFile,
|
|
593
|
+
pathExists,
|
|
594
|
+
getFileSize,
|
|
595
|
+
isDirectory,
|
|
596
|
+
isFile,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
//# sourceMappingURL=fs-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-tools.js","sourceRoot":"","sources":["../src/fs-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ServerResponse } from "node:http";
|
|
2
|
+
import type { ServerConfig } from "./config.js";
|
|
3
|
+
import type { RateLimiter } from "./rate-limiter.js";
|
|
4
|
+
type RateLimitResponseConfig = Pick<ServerConfig["rateLimit"], "enabled" | "maxRequests" | "windowMs">;
|
|
5
|
+
type RateLimitUsageSource = Pick<RateLimiter, "getUsage">;
|
|
6
|
+
export declare function buildRateLimitHeaders(rateLimiter: RateLimitUsageSource, rateLimit: RateLimitResponseConfig, key?: string, now?: number): Record<string, string>;
|
|
7
|
+
export declare function attachRateLimitHeaders(res: ServerResponse, buildHeaders: () => Record<string, string>): void;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=http-rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-rate-limit.d.ts","sourceRoot":"","sources":["../src/http-rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,KAAK,uBAAuB,GAAG,IAAI,CACjC,YAAY,CAAC,WAAW,CAAC,EACzB,SAAS,GAAG,aAAa,GAAG,UAAU,CACvC,CAAC;AACF,KAAK,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAE1D,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,oBAAoB,EACjC,SAAS,EAAE,uBAAuB,EAClC,GAAG,SAAW,EACd,GAAG,SAAa,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBxB;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,cAAc,EACnB,YAAY,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,IAAI,CAuBN"}
|