mcp-ssh-pty 1.2.0 → 1.2.1
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/dist/shell-manager.d.ts +2 -1
- package/dist/shell-manager.js +24 -21
- package/package.json +2 -1
package/dist/shell-manager.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ShellResult, ShellConfig } from "./types.js";
|
|
|
3
3
|
export declare class ShellManager {
|
|
4
4
|
private shell;
|
|
5
5
|
private localProcess;
|
|
6
|
+
private ptyProcess;
|
|
6
7
|
private outputBuffer;
|
|
7
8
|
private outputLines;
|
|
8
9
|
private lastOutputTime;
|
|
@@ -14,7 +15,7 @@ export declare class ShellManager {
|
|
|
14
15
|
*/
|
|
15
16
|
open(client: Client): Promise<void>;
|
|
16
17
|
/**
|
|
17
|
-
* 打开本地 Shell
|
|
18
|
+
* 打开本地 Shell(使用 node-pty 创建真正的 PTY)
|
|
18
19
|
*/
|
|
19
20
|
openLocal(): Promise<void>;
|
|
20
21
|
/**
|
package/dist/shell-manager.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as pty from "node-pty";
|
|
2
2
|
const DEFAULT_CONFIG = {
|
|
3
3
|
quickTimeout: 2000,
|
|
4
4
|
maxTimeout: 5000,
|
|
@@ -8,6 +8,7 @@ const DEFAULT_CONFIG = {
|
|
|
8
8
|
export class ShellManager {
|
|
9
9
|
shell = null;
|
|
10
10
|
localProcess = null;
|
|
11
|
+
ptyProcess = null;
|
|
11
12
|
outputBuffer = "";
|
|
12
13
|
outputLines = [];
|
|
13
14
|
lastOutputTime = 0;
|
|
@@ -37,42 +38,39 @@ export class ShellManager {
|
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
|
-
* 打开本地 Shell
|
|
41
|
+
* 打开本地 Shell(使用 node-pty 创建真正的 PTY)
|
|
41
42
|
*/
|
|
42
43
|
async openLocal() {
|
|
43
44
|
return new Promise((resolve, reject) => {
|
|
44
45
|
try {
|
|
45
46
|
// 检测系统默认 shell
|
|
46
|
-
const shellPath = process.env.SHELL || (process.platform === "win32" ? "
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const shellPath = process.env.SHELL || (process.platform === "win32" ? "powershell.exe" : "/bin/sh");
|
|
48
|
+
// 使用 node-pty 创建真正的 PTY
|
|
49
|
+
const ptyProc = pty.spawn(shellPath, [], {
|
|
50
|
+
name: "xterm-256color",
|
|
51
|
+
cols: 120,
|
|
52
|
+
rows: 40,
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
env: process.env,
|
|
50
55
|
});
|
|
51
|
-
this.
|
|
56
|
+
this.ptyProcess = ptyProc;
|
|
52
57
|
this.isLocal = true;
|
|
53
58
|
// 创建统一的 stream 接口
|
|
54
59
|
const dataListeners = [];
|
|
55
60
|
const closeListeners = [];
|
|
56
61
|
const errorListeners = [];
|
|
57
|
-
|
|
58
|
-
dataListeners.forEach((l) => l(data));
|
|
62
|
+
ptyProc.onData((data) => {
|
|
63
|
+
dataListeners.forEach((l) => l(Buffer.from(data)));
|
|
59
64
|
});
|
|
60
|
-
|
|
61
|
-
dataListeners.forEach((l) => l(data));
|
|
62
|
-
});
|
|
63
|
-
proc.on("close", () => {
|
|
65
|
+
ptyProc.onExit(() => {
|
|
64
66
|
closeListeners.forEach((l) => l());
|
|
65
67
|
});
|
|
66
|
-
proc.on("error", (err) => {
|
|
67
|
-
errorListeners.forEach((l) => l(err));
|
|
68
|
-
});
|
|
69
68
|
const stream = {
|
|
70
69
|
write: (data) => {
|
|
71
|
-
|
|
70
|
+
ptyProc.write(data);
|
|
72
71
|
},
|
|
73
72
|
end: () => {
|
|
74
|
-
|
|
75
|
-
proc.kill();
|
|
73
|
+
ptyProc.kill();
|
|
76
74
|
},
|
|
77
75
|
on: ((event, listener) => {
|
|
78
76
|
if (event === "data") {
|
|
@@ -88,10 +86,10 @@ export class ShellManager {
|
|
|
88
86
|
};
|
|
89
87
|
this.shell = stream;
|
|
90
88
|
this.setupStream(stream);
|
|
91
|
-
//
|
|
89
|
+
// 等待初始提示符
|
|
92
90
|
setTimeout(() => {
|
|
93
91
|
resolve();
|
|
94
|
-
},
|
|
92
|
+
}, 500);
|
|
95
93
|
}
|
|
96
94
|
catch (error) {
|
|
97
95
|
reject(new Error(`无法打开本地 shell: ${error instanceof Error ? error.message : String(error)}`));
|
|
@@ -124,6 +122,7 @@ export class ShellManager {
|
|
|
124
122
|
stream.on("close", () => {
|
|
125
123
|
this.shell = null;
|
|
126
124
|
this.localProcess = null;
|
|
125
|
+
this.ptyProcess = null;
|
|
127
126
|
});
|
|
128
127
|
stream.on("error", (err) => {
|
|
129
128
|
console.error("Shell error:", err.message);
|
|
@@ -223,6 +222,10 @@ export class ShellManager {
|
|
|
223
222
|
this.localProcess.kill();
|
|
224
223
|
this.localProcess = null;
|
|
225
224
|
}
|
|
225
|
+
if (this.ptyProcess) {
|
|
226
|
+
this.ptyProcess.kill();
|
|
227
|
+
this.ptyProcess = null;
|
|
228
|
+
}
|
|
226
229
|
this.outputLines = [];
|
|
227
230
|
this.outputBuffer = "";
|
|
228
231
|
this.isLocal = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-ssh-pty",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "MCP Server for SSH remote command execution with PTY shell support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"@inquirer/prompts": "^8.1.0",
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
35
35
|
"commander": "^14.0.2",
|
|
36
|
+
"node-pty": "^1.1.0",
|
|
36
37
|
"ssh2": "^1.16.0",
|
|
37
38
|
"zod": "^3.24.0"
|
|
38
39
|
},
|