ssh-mcp 1.0.7 → 1.0.8
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/README.md +3 -1
- package/build/index.js +23 -5
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://github.com/tufantunc/ssh-mcp/stargazers)
|
|
8
8
|
[](https://github.com/tufantunc/ssh-mcp/forks)
|
|
9
|
-
[](https://github.com/tufantunc/ssh-mcp/actions)
|
|
10
10
|
[](https://github.com/tufantunc/ssh-mcp/issues)
|
|
11
11
|
|
|
12
|
+
[](https://archestra.ai/mcp-catalog/tufantunc__ssh-mcp)
|
|
13
|
+
|
|
12
14
|
**SSH MCP Server** is a local Model Context Protocol (MCP) server that exposes SSH control for Linux and Windows systems, enabling LLMs and other MCP clients to execute shell commands securely via SSH.
|
|
13
15
|
|
|
14
16
|
## Contents
|
package/build/index.js
CHANGED
|
@@ -36,6 +36,26 @@ function validateConfig(config) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
validateConfig(argvConfig);
|
|
39
|
+
// Command sanitization and validation
|
|
40
|
+
function sanitizeCommand(command) {
|
|
41
|
+
if (typeof command !== 'string') {
|
|
42
|
+
throw new McpError(ErrorCode.InvalidParams, 'Command must be a string');
|
|
43
|
+
}
|
|
44
|
+
const trimmedCommand = command.trim();
|
|
45
|
+
if (!trimmedCommand) {
|
|
46
|
+
throw new McpError(ErrorCode.InvalidParams, 'Command cannot be empty');
|
|
47
|
+
}
|
|
48
|
+
// Length check
|
|
49
|
+
if (trimmedCommand.length > 1000) {
|
|
50
|
+
throw new McpError(ErrorCode.InvalidParams, 'Command is too long (max 1000 characters)');
|
|
51
|
+
}
|
|
52
|
+
return trimmedCommand;
|
|
53
|
+
}
|
|
54
|
+
// Escape command for use in shell contexts (like pkill)
|
|
55
|
+
function escapeCommandForShell(command) {
|
|
56
|
+
// Replace single quotes with escaped single quotes
|
|
57
|
+
return command.replace(/'/g, "'\"'\"'");
|
|
58
|
+
}
|
|
39
59
|
const server = new McpServer({
|
|
40
60
|
name: 'SSH MCP Server',
|
|
41
61
|
version: '1.0.7',
|
|
@@ -48,9 +68,7 @@ server.tool("exec", "Execute a shell command on the remote SSH server and return
|
|
|
48
68
|
command: z.string().describe("Shell command to execute on the remote SSH server"),
|
|
49
69
|
}, async ({ command }) => {
|
|
50
70
|
// Sanitize command input
|
|
51
|
-
|
|
52
|
-
throw new McpError(ErrorCode.InternalError, 'Command must be a non-empty string.');
|
|
53
|
-
}
|
|
71
|
+
const sanitizedCommand = sanitizeCommand(command);
|
|
54
72
|
const sshConfig = {
|
|
55
73
|
host: HOST,
|
|
56
74
|
port: PORT,
|
|
@@ -64,7 +82,7 @@ server.tool("exec", "Execute a shell command on the remote SSH server and return
|
|
|
64
82
|
const fs = await import('fs/promises');
|
|
65
83
|
sshConfig.privateKey = await fs.readFile(KEY, 'utf8');
|
|
66
84
|
}
|
|
67
|
-
const result = await execSshCommand(sshConfig,
|
|
85
|
+
const result = await execSshCommand(sshConfig, sanitizedCommand);
|
|
68
86
|
return result;
|
|
69
87
|
}
|
|
70
88
|
catch (err) {
|
|
@@ -88,7 +106,7 @@ async function execSshCommand(sshConfig, command) {
|
|
|
88
106
|
// If abort command itself times out, force close connection
|
|
89
107
|
conn.end();
|
|
90
108
|
}, 5000); // 5 second timeout for abort command
|
|
91
|
-
conn.exec('timeout 3s pkill -f
|
|
109
|
+
conn.exec('timeout 3s pkill -f \'' + escapeCommandForShell(command) + '\' 2>/dev/null || true', (err, abortStream) => {
|
|
92
110
|
if (abortStream) {
|
|
93
111
|
abortStream.on('close', () => {
|
|
94
112
|
clearTimeout(abortTimeout);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssh-mcp",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.8",
|
|
5
5
|
"description": "MCP server exposing SSH control for Linux and Windows systems via Model Context Protocol.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
"build"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
20
|
-
"ssh2": "^1.
|
|
21
|
-
"zod": "^
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
20
|
+
"ssh2": "^1.17.0",
|
|
21
|
+
"zod": "^4.1.5"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/node": "^
|
|
24
|
+
"@types/node": "^24.3.0",
|
|
25
25
|
"@types/ssh2": "^1.15.5",
|
|
26
26
|
"shx": "^0.4.0",
|
|
27
|
-
"typescript": "^5.
|
|
27
|
+
"typescript": "^5.9.2"
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/tufantunc/ssh-mcp#readme",
|
|
30
30
|
"repository": {
|