@ebowwa/terminal 0.2.1 → 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.
- package/dist/index.js +6855 -28130
- package/dist/mcp/index.js +7244 -27317
- package/package.json +1 -1
- package/src/api.js +0 -861
- package/src/client.js +0 -92
- package/src/config.js +0 -490
- package/src/error.js +0 -32
- package/src/exec.js +0 -183
- package/src/files.js +0 -521
- package/src/fingerprint.js +0 -336
- package/src/index.js +0 -127
- package/src/manager.js +0 -358
- package/src/mcp/index.js +0 -555
- package/src/mcp/stdio.js +0 -840
- package/src/network-error-detector.js +0 -101
- package/src/pool.js +0 -840
- package/src/pty.js +0 -344
- package/src/resources.js +0 -64
- package/src/scp.js +0 -166
- package/src/sessions.js +0 -895
- package/src/tmux-exec.js +0 -169
- package/src/tmux-local.js +0 -937
- package/src/tmux-manager.js +0 -1026
- package/src/tmux.js +0 -826
- package/src/types.js +0 -5
package/src/mcp/index.js
DELETED
|
@@ -1,555 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* Terminal MCP Server
|
|
5
|
-
*
|
|
6
|
-
* Exposes terminal session management via Model Context Protocol
|
|
7
|
-
* Integrates with tmux, SSH, PTY, and file operations
|
|
8
|
-
*/
|
|
9
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
10
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
11
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
12
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
13
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
14
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
15
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
19
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
20
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
21
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
22
|
-
function step(op) {
|
|
23
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
24
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
25
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
26
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
27
|
-
switch (op[0]) {
|
|
28
|
-
case 0: case 1: t = op; break;
|
|
29
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
30
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
31
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
32
|
-
default:
|
|
33
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
34
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
35
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
36
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
37
|
-
if (t[2]) _.ops.pop();
|
|
38
|
-
_.trys.pop(); continue;
|
|
39
|
-
}
|
|
40
|
-
op = body.call(thisArg, _);
|
|
41
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
42
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
// Re-export terminal functions
|
|
47
|
-
var index_js_1 = require("../index.js");
|
|
48
|
-
// ==============
|
|
49
|
-
// MCP Tools
|
|
50
|
-
//=============
|
|
51
|
-
/**
|
|
52
|
-
* List all active terminal sessions
|
|
53
|
-
*/
|
|
54
|
-
function listSessionsTool() {
|
|
55
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
56
|
-
var sessions, lines, _i, sessions_1, session, active;
|
|
57
|
-
return __generator(this, function (_a) {
|
|
58
|
-
sessions = (0, index_js_1.getAllSessionInfo)();
|
|
59
|
-
lines = [
|
|
60
|
-
"🖥️ Active Terminal Sessions",
|
|
61
|
-
"=".repeat(50),
|
|
62
|
-
"",
|
|
63
|
-
"Total sessions: ".concat(sessions.length),
|
|
64
|
-
"",
|
|
65
|
-
];
|
|
66
|
-
for (_i = 0, sessions_1 = sessions; _i < sessions_1.length; _i++) {
|
|
67
|
-
session = sessions_1[_i];
|
|
68
|
-
active = session.active ? "🟢" : "⚪";
|
|
69
|
-
lines.push("".concat(active, " ").concat(session.id));
|
|
70
|
-
lines.push(" Host: ".concat(session.host));
|
|
71
|
-
lines.push(" Type: ".concat(session.type));
|
|
72
|
-
lines.push(" Created: ".concat(new Date(session.createdAt).toLocaleString()));
|
|
73
|
-
if (session.lastActivity) {
|
|
74
|
-
lines.push(" Last activity: ".concat(new Date(session.lastActivity).toLocaleString()));
|
|
75
|
-
}
|
|
76
|
-
lines.push("");
|
|
77
|
-
}
|
|
78
|
-
return [2 /*return*/, lines.join("\n")];
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Get detailed info about a specific session
|
|
84
|
-
*/
|
|
85
|
-
function getSessionInfoTool(sessionId) {
|
|
86
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
87
|
-
var info, lines, session, error_1;
|
|
88
|
-
return __generator(this, function (_a) {
|
|
89
|
-
switch (_a.label) {
|
|
90
|
-
case 0:
|
|
91
|
-
_a.trys.push([0, 2, , 3]);
|
|
92
|
-
return [4 /*yield*/, (0, index_js_1.getSessionInfo)(sessionId)];
|
|
93
|
-
case 1:
|
|
94
|
-
info = _a.sent();
|
|
95
|
-
lines = [
|
|
96
|
-
"\uD83D\uDCCB Session: ".concat(sessionId),
|
|
97
|
-
"=".repeat(50),
|
|
98
|
-
"",
|
|
99
|
-
"Host: ".concat(info.host),
|
|
100
|
-
"Type: ".concat(info.type),
|
|
101
|
-
"Active: ".concat(info.active ? "Yes" : "No"),
|
|
102
|
-
"Created: ".concat(new Date(info.createdAt).toLocaleString()),
|
|
103
|
-
];
|
|
104
|
-
if (info.lastActivity) {
|
|
105
|
-
lines.push("Last activity: ".concat(new Date(info.lastActivity).toLocaleString()));
|
|
106
|
-
}
|
|
107
|
-
session = (0, index_js_1.getSession)(sessionId);
|
|
108
|
-
if (session) {
|
|
109
|
-
lines.push("");
|
|
110
|
-
lines.push("PTY session: ".concat(session.ptyId || "N/A"));
|
|
111
|
-
lines.push("WebSocket attached: ".concat(session.wsAttached ? "Yes" : "No"));
|
|
112
|
-
}
|
|
113
|
-
return [2 /*return*/, lines.join("\n")];
|
|
114
|
-
case 2:
|
|
115
|
-
error_1 = _a.sent();
|
|
116
|
-
throw new Error("Failed to get session info: ".concat(error_1));
|
|
117
|
-
case 3: return [2 /*return*/];
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Create a new terminal session
|
|
124
|
-
*/
|
|
125
|
-
function createSessionTool(host_1) {
|
|
126
|
-
return __awaiter(this, arguments, void 0, function (host, type, command) {
|
|
127
|
-
var session, error_2;
|
|
128
|
-
if (type === void 0) { type = "ssh"; }
|
|
129
|
-
return __generator(this, function (_a) {
|
|
130
|
-
switch (_a.label) {
|
|
131
|
-
case 0:
|
|
132
|
-
_a.trys.push([0, 2, , 3]);
|
|
133
|
-
return [4 /*yield*/, (0, index_js_1.getOrCreateSession)(host, {
|
|
134
|
-
type: type,
|
|
135
|
-
command: command,
|
|
136
|
-
})];
|
|
137
|
-
case 1:
|
|
138
|
-
session = _a.sent();
|
|
139
|
-
return [2 /*return*/, "\u2713 Created session ".concat(session.id, " for ").concat(host, " (").concat(type, ")")];
|
|
140
|
-
case 2:
|
|
141
|
-
error_2 = _a.sent();
|
|
142
|
-
throw new Error("Failed to create session: ".concat(error_2));
|
|
143
|
-
case 3: return [2 /*return*/];
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Write a command to a session
|
|
150
|
-
*/
|
|
151
|
-
function writeCommandTool(sessionId, command) {
|
|
152
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
153
|
-
var session, error_3;
|
|
154
|
-
return __generator(this, function (_a) {
|
|
155
|
-
switch (_a.label) {
|
|
156
|
-
case 0:
|
|
157
|
-
_a.trys.push([0, 2, , 3]);
|
|
158
|
-
session = (0, index_js_1.getSession)(sessionId);
|
|
159
|
-
if (!session) {
|
|
160
|
-
throw new Error("Session ".concat(sessionId, " not found"));
|
|
161
|
-
}
|
|
162
|
-
return [4 /*yield*/, (0, index_js_1.writeToSession)(sessionId, command)];
|
|
163
|
-
case 1:
|
|
164
|
-
_a.sent();
|
|
165
|
-
return [2 /*return*/, "\u2713 Command sent to session ".concat(sessionId)];
|
|
166
|
-
case 2:
|
|
167
|
-
error_3 = _a.sent();
|
|
168
|
-
throw new Error("Failed to write command: ".concat(error_3));
|
|
169
|
-
case 3: return [2 /*return*/];
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Resize a session
|
|
176
|
-
*/
|
|
177
|
-
function resizeSessionTool(sessionId, rows, cols) {
|
|
178
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
179
|
-
var error_4;
|
|
180
|
-
return __generator(this, function (_a) {
|
|
181
|
-
switch (_a.label) {
|
|
182
|
-
case 0:
|
|
183
|
-
_a.trys.push([0, 2, , 3]);
|
|
184
|
-
return [4 /*yield*/, (0, index_js_1.resizeSession)(sessionId, rows, cols)];
|
|
185
|
-
case 1:
|
|
186
|
-
_a.sent();
|
|
187
|
-
return [2 /*return*/, "\u2713 Resized session ".concat(sessionId, " to ").concat(rows, "x").concat(cols)];
|
|
188
|
-
case 2:
|
|
189
|
-
error_4 = _a.sent();
|
|
190
|
-
throw new Error("Failed to resize session: ".concat(error_4));
|
|
191
|
-
case 3: return [2 /*return*/];
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Close a session
|
|
198
|
-
*/
|
|
199
|
-
function closeSessionTool(sessionId) {
|
|
200
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
201
|
-
var error_5;
|
|
202
|
-
return __generator(this, function (_a) {
|
|
203
|
-
switch (_a.label) {
|
|
204
|
-
case 0:
|
|
205
|
-
_a.trys.push([0, 2, , 3]);
|
|
206
|
-
return [4 /*yield*/, (0, index_js_1.closeSession)(sessionId)];
|
|
207
|
-
case 1:
|
|
208
|
-
_a.sent();
|
|
209
|
-
return [2 /*return*/, "\u2713 Closed session ".concat(sessionId)];
|
|
210
|
-
case 2:
|
|
211
|
-
error_5 = _a.sent();
|
|
212
|
-
throw new Error("Failed to close session: ".concat(error_5));
|
|
213
|
-
case 3: return [2 /*return*/];
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Execute a command via SSH
|
|
220
|
-
*/
|
|
221
|
-
function execSSHTool(host, command, options) {
|
|
222
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
223
|
-
var result, error_6;
|
|
224
|
-
return __generator(this, function (_a) {
|
|
225
|
-
switch (_a.label) {
|
|
226
|
-
case 0:
|
|
227
|
-
_a.trys.push([0, 2, , 3]);
|
|
228
|
-
return [4 /*yield*/, (0, index_js_1.execSSH)(host, command, options)];
|
|
229
|
-
case 1:
|
|
230
|
-
result = _a.sent();
|
|
231
|
-
return [2 /*return*/, result.stdout || result.stderr || "Command executed"];
|
|
232
|
-
case 2:
|
|
233
|
-
error_6 = _a.sent();
|
|
234
|
-
throw new Error("SSH command failed: ".concat(error_6));
|
|
235
|
-
case 3: return [2 /*return*/];
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Test SSH connection
|
|
242
|
-
*/
|
|
243
|
-
function testConnectionTool(host) {
|
|
244
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
245
|
-
var result, error_7;
|
|
246
|
-
return __generator(this, function (_a) {
|
|
247
|
-
switch (_a.label) {
|
|
248
|
-
case 0:
|
|
249
|
-
_a.trys.push([0, 2, , 3]);
|
|
250
|
-
return [4 /*yield*/, (0, index_js_1.testSSHConnection)(host)];
|
|
251
|
-
case 1:
|
|
252
|
-
result = _a.sent();
|
|
253
|
-
if (result.success) {
|
|
254
|
-
return [2 /*return*/, "\u2713 Connection to ".concat(host, " successful\nLatency: ").concat(result.latency, "ms")];
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
throw new Error(result.error || "Connection failed");
|
|
258
|
-
}
|
|
259
|
-
return [3 /*break*/, 3];
|
|
260
|
-
case 2:
|
|
261
|
-
error_7 = _a.sent();
|
|
262
|
-
throw new Error("Connection test failed: ".concat(error_7));
|
|
263
|
-
case 3: return [2 /*return*/];
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* List tmux sessions
|
|
270
|
-
*/
|
|
271
|
-
function listTmuxSessionsTool() {
|
|
272
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
273
|
-
var sessions, lines, _i, sessions_2, session, error_8;
|
|
274
|
-
return __generator(this, function (_a) {
|
|
275
|
-
switch (_a.label) {
|
|
276
|
-
case 0:
|
|
277
|
-
_a.trys.push([0, 3, , 4]);
|
|
278
|
-
return [4 /*yield*/, (0, index_js_1.ensureTmux)()];
|
|
279
|
-
case 1:
|
|
280
|
-
_a.sent();
|
|
281
|
-
return [4 /*yield*/, (0, index_js_1.listTmuxSessions)()];
|
|
282
|
-
case 2:
|
|
283
|
-
sessions = _a.sent();
|
|
284
|
-
lines = [
|
|
285
|
-
"🎬 Tmux Sessions",
|
|
286
|
-
"=".repeat(50),
|
|
287
|
-
"",
|
|
288
|
-
];
|
|
289
|
-
if (sessions.length === 0) {
|
|
290
|
-
lines.push("No active tmux sessions");
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
for (_i = 0, sessions_2 = sessions; _i < sessions_2.length; _i++) {
|
|
294
|
-
session = sessions_2[_i];
|
|
295
|
-
lines.push("".concat(session.name));
|
|
296
|
-
lines.push(" Windows: ".concat(session.windows));
|
|
297
|
-
lines.push(" Created: ".concat(new Date(session.created).toLocaleString()));
|
|
298
|
-
lines.push("");
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return [2 /*return*/, lines.join("\n")];
|
|
302
|
-
case 3:
|
|
303
|
-
error_8 = _a.sent();
|
|
304
|
-
throw new Error("Failed to list tmux sessions: ".concat(error_8));
|
|
305
|
-
case 4: return [2 /*return*/];
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* List files on remote host
|
|
312
|
-
*/
|
|
313
|
-
function listFilesTool(host_1) {
|
|
314
|
-
return __awaiter(this, arguments, void 0, function (host, path) {
|
|
315
|
-
var files, lines, _i, files_1, file, icon, size, error_9;
|
|
316
|
-
if (path === void 0) { path = "."; }
|
|
317
|
-
return __generator(this, function (_a) {
|
|
318
|
-
switch (_a.label) {
|
|
319
|
-
case 0:
|
|
320
|
-
_a.trys.push([0, 2, , 3]);
|
|
321
|
-
return [4 /*yield*/, (0, index_js_1.listFiles)(host, path)];
|
|
322
|
-
case 1:
|
|
323
|
-
files = _a.sent();
|
|
324
|
-
lines = [
|
|
325
|
-
"\uD83D\uDCC1 Files on ".concat(host, ":").concat(path),
|
|
326
|
-
"=".repeat(50),
|
|
327
|
-
"",
|
|
328
|
-
];
|
|
329
|
-
for (_i = 0, files_1 = files; _i < files_1.length; _i++) {
|
|
330
|
-
file = files_1[_i];
|
|
331
|
-
icon = file.type === "directory" ? "📁" : "📄";
|
|
332
|
-
size = file.size ? " (".concat(file.size, " bytes)") : "";
|
|
333
|
-
lines.push("".concat(icon, " ").concat(file.name).concat(size));
|
|
334
|
-
}
|
|
335
|
-
return [2 /*return*/, lines.join("\n")];
|
|
336
|
-
case 2:
|
|
337
|
-
error_9 = _a.sent();
|
|
338
|
-
throw new Error("Failed to list files: ".concat(error_9));
|
|
339
|
-
case 3: return [2 /*return*/];
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Upload file via SCP
|
|
346
|
-
*/
|
|
347
|
-
function uploadFileTool(host, localPath, remotePath) {
|
|
348
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
349
|
-
var error_10;
|
|
350
|
-
return __generator(this, function (_a) {
|
|
351
|
-
switch (_a.label) {
|
|
352
|
-
case 0:
|
|
353
|
-
_a.trys.push([0, 2, , 3]);
|
|
354
|
-
return [4 /*yield*/, (0, index_js_1.scpUpload)(host, { localPath: localPath, remotePath: remotePath })];
|
|
355
|
-
case 1:
|
|
356
|
-
_a.sent();
|
|
357
|
-
return [2 /*return*/, "\u2713 Uploaded ".concat(localPath, " to ").concat(host, ":").concat(remotePath)];
|
|
358
|
-
case 2:
|
|
359
|
-
error_10 = _a.sent();
|
|
360
|
-
throw new Error("SCP upload failed: ".concat(error_10));
|
|
361
|
-
case 3: return [2 /*return*/];
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Download file via SCP
|
|
368
|
-
*/
|
|
369
|
-
function downloadFileTool(host, remotePath, localPath) {
|
|
370
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
371
|
-
var error_11;
|
|
372
|
-
return __generator(this, function (_a) {
|
|
373
|
-
switch (_a.label) {
|
|
374
|
-
case 0:
|
|
375
|
-
_a.trys.push([0, 2, , 3]);
|
|
376
|
-
return [4 /*yield*/, (0, index_js_1.scpDownload)(host, { remotePath: remotePath, localPath: localPath })];
|
|
377
|
-
case 1:
|
|
378
|
-
_a.sent();
|
|
379
|
-
return [2 /*return*/, "\u2713 Downloaded ".concat(host, ":").concat(remotePath, " to ").concat(localPath)];
|
|
380
|
-
case 2:
|
|
381
|
-
error_11 = _a.sent();
|
|
382
|
-
throw new Error("SCP download failed: ".concat(error_11));
|
|
383
|
-
case 3: return [2 /*return*/];
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Get active SSH connections
|
|
390
|
-
*/
|
|
391
|
-
function getActiveConnectionsTool() {
|
|
392
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
393
|
-
var pool, connections, lines, _i, connections_1, conn;
|
|
394
|
-
return __generator(this, function (_a) {
|
|
395
|
-
try {
|
|
396
|
-
pool = (0, index_js_1.getSSHPool)();
|
|
397
|
-
connections = (0, index_js_1.getActiveSSHConnections)();
|
|
398
|
-
lines = [
|
|
399
|
-
"🔗 Active SSH Connections",
|
|
400
|
-
"=".repeat(50),
|
|
401
|
-
"",
|
|
402
|
-
"Total connections: ".concat(connections.length),
|
|
403
|
-
"",
|
|
404
|
-
];
|
|
405
|
-
for (_i = 0, connections_1 = connections; _i < connections_1.length; _i++) {
|
|
406
|
-
conn = connections_1[_i];
|
|
407
|
-
lines.push("".concat(conn.host));
|
|
408
|
-
lines.push(" Connected: ".concat(conn.connected ? "Yes" : "No"));
|
|
409
|
-
lines.push(" Port: ".concat(conn.port || 22));
|
|
410
|
-
lines.push("");
|
|
411
|
-
}
|
|
412
|
-
return [2 /*return*/, lines.join("\n")];
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
throw new Error("Failed to get connections: ".concat(error));
|
|
416
|
-
}
|
|
417
|
-
return [2 /*return*/];
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
// ==============
|
|
422
|
-
// MCP Server
|
|
423
|
-
//=============
|
|
424
|
-
var MCP_PORT = parseInt(process.env.MCP_PORT || "8913");
|
|
425
|
-
Bun.serve({
|
|
426
|
-
port: MCP_PORT,
|
|
427
|
-
fetch: function (req) { return __awaiter(void 0, void 0, void 0, function () {
|
|
428
|
-
var url, body, tool, args, result, _a, error_12;
|
|
429
|
-
return __generator(this, function (_b) {
|
|
430
|
-
switch (_b.label) {
|
|
431
|
-
case 0:
|
|
432
|
-
url = new URL(req.url);
|
|
433
|
-
// Health check
|
|
434
|
-
if (url.pathname === "/health") {
|
|
435
|
-
return [2 /*return*/, Response.json({ status: "ok", port: MCP_PORT, service: "terminal-mcp" })];
|
|
436
|
-
}
|
|
437
|
-
if (!(url.pathname === "/mcp")) return [3 /*break*/, 33];
|
|
438
|
-
if (!(req.method === "POST")) return [3 /*break*/, 32];
|
|
439
|
-
return [4 /*yield*/, req.json()];
|
|
440
|
-
case 1:
|
|
441
|
-
body = _b.sent();
|
|
442
|
-
tool = body.tool, args = body.args;
|
|
443
|
-
_b.label = 2;
|
|
444
|
-
case 2:
|
|
445
|
-
_b.trys.push([2, 31, , 32]);
|
|
446
|
-
result = void 0;
|
|
447
|
-
_a = tool;
|
|
448
|
-
switch (_a) {
|
|
449
|
-
case "list_sessions": return [3 /*break*/, 3];
|
|
450
|
-
case "get_session_info": return [3 /*break*/, 5];
|
|
451
|
-
case "create_session": return [3 /*break*/, 7];
|
|
452
|
-
case "write_command": return [3 /*break*/, 9];
|
|
453
|
-
case "resize_session": return [3 /*break*/, 11];
|
|
454
|
-
case "close_session": return [3 /*break*/, 13];
|
|
455
|
-
case "exec_ssh": return [3 /*break*/, 15];
|
|
456
|
-
case "test_connection": return [3 /*break*/, 17];
|
|
457
|
-
case "list_tmux_sessions": return [3 /*break*/, 19];
|
|
458
|
-
case "list_files": return [3 /*break*/, 21];
|
|
459
|
-
case "upload_file": return [3 /*break*/, 23];
|
|
460
|
-
case "download_file": return [3 /*break*/, 25];
|
|
461
|
-
case "get_active_connections": return [3 /*break*/, 27];
|
|
462
|
-
}
|
|
463
|
-
return [3 /*break*/, 29];
|
|
464
|
-
case 3: return [4 /*yield*/, listSessionsTool()];
|
|
465
|
-
case 4:
|
|
466
|
-
result = _b.sent();
|
|
467
|
-
return [3 /*break*/, 30];
|
|
468
|
-
case 5: return [4 /*yield*/, getSessionInfoTool(args === null || args === void 0 ? void 0 : args.session_id)];
|
|
469
|
-
case 6:
|
|
470
|
-
result = _b.sent();
|
|
471
|
-
return [3 /*break*/, 30];
|
|
472
|
-
case 7: return [4 /*yield*/, createSessionTool(args === null || args === void 0 ? void 0 : args.host, args === null || args === void 0 ? void 0 : args.type, args === null || args === void 0 ? void 0 : args.command)];
|
|
473
|
-
case 8:
|
|
474
|
-
result = _b.sent();
|
|
475
|
-
return [3 /*break*/, 30];
|
|
476
|
-
case 9: return [4 /*yield*/, writeCommandTool(args === null || args === void 0 ? void 0 : args.session_id, args === null || args === void 0 ? void 0 : args.command)];
|
|
477
|
-
case 10:
|
|
478
|
-
result = _b.sent();
|
|
479
|
-
return [3 /*break*/, 30];
|
|
480
|
-
case 11: return [4 /*yield*/, resizeSessionTool(args === null || args === void 0 ? void 0 : args.session_id, args === null || args === void 0 ? void 0 : args.rows, args === null || args === void 0 ? void 0 : args.cols)];
|
|
481
|
-
case 12:
|
|
482
|
-
result = _b.sent();
|
|
483
|
-
return [3 /*break*/, 30];
|
|
484
|
-
case 13: return [4 /*yield*/, closeSessionTool(args === null || args === void 0 ? void 0 : args.session_id)];
|
|
485
|
-
case 14:
|
|
486
|
-
result = _b.sent();
|
|
487
|
-
return [3 /*break*/, 30];
|
|
488
|
-
case 15: return [4 /*yield*/, execSSHTool(args === null || args === void 0 ? void 0 : args.host, args === null || args === void 0 ? void 0 : args.command, args === null || args === void 0 ? void 0 : args.options)];
|
|
489
|
-
case 16:
|
|
490
|
-
result = _b.sent();
|
|
491
|
-
return [3 /*break*/, 30];
|
|
492
|
-
case 17: return [4 /*yield*/, testConnectionTool(args === null || args === void 0 ? void 0 : args.host)];
|
|
493
|
-
case 18:
|
|
494
|
-
result = _b.sent();
|
|
495
|
-
return [3 /*break*/, 30];
|
|
496
|
-
case 19: return [4 /*yield*/, listTmuxSessionsTool()];
|
|
497
|
-
case 20:
|
|
498
|
-
result = _b.sent();
|
|
499
|
-
return [3 /*break*/, 30];
|
|
500
|
-
case 21: return [4 /*yield*/, listFilesTool(args === null || args === void 0 ? void 0 : args.host, args === null || args === void 0 ? void 0 : args.path)];
|
|
501
|
-
case 22:
|
|
502
|
-
result = _b.sent();
|
|
503
|
-
return [3 /*break*/, 30];
|
|
504
|
-
case 23: return [4 /*yield*/, uploadFileTool(args === null || args === void 0 ? void 0 : args.host, args === null || args === void 0 ? void 0 : args.local_path, args === null || args === void 0 ? void 0 : args.remote_path)];
|
|
505
|
-
case 24:
|
|
506
|
-
result = _b.sent();
|
|
507
|
-
return [3 /*break*/, 30];
|
|
508
|
-
case 25: return [4 /*yield*/, downloadFileTool(args === null || args === void 0 ? void 0 : args.host, args === null || args === void 0 ? void 0 : args.remote_path, args === null || args === void 0 ? void 0 : args.local_path)];
|
|
509
|
-
case 26:
|
|
510
|
-
result = _b.sent();
|
|
511
|
-
return [3 /*break*/, 30];
|
|
512
|
-
case 27: return [4 /*yield*/, getActiveConnectionsTool()];
|
|
513
|
-
case 28:
|
|
514
|
-
result = _b.sent();
|
|
515
|
-
return [3 /*break*/, 30];
|
|
516
|
-
case 29: return [2 /*return*/, Response.json({ error: "Unknown tool: ".concat(tool) }, { status: 400 })];
|
|
517
|
-
case 30: return [2 /*return*/, Response.json({ result: result })];
|
|
518
|
-
case 31:
|
|
519
|
-
error_12 = _b.sent();
|
|
520
|
-
return [2 /*return*/, Response.json({ error: String(error_12) }, { status: 500 })];
|
|
521
|
-
case 32:
|
|
522
|
-
// GET returns available tools
|
|
523
|
-
return [2 /*return*/, Response.json({
|
|
524
|
-
name: "terminal-mcp",
|
|
525
|
-
version: "1.0.0",
|
|
526
|
-
description: "Terminal session management with tmux, SSH, PTY, and file operations",
|
|
527
|
-
tools: [
|
|
528
|
-
// Session management
|
|
529
|
-
{ name: "list_sessions", description: "List all active terminal sessions" },
|
|
530
|
-
{ name: "get_session_info", description: "Get detailed info about a session", args: ["session_id"] },
|
|
531
|
-
{ name: "create_session", description: "Create a new terminal session", args: ["host", "type?", "command?"] },
|
|
532
|
-
{ name: "write_command", description: "Write a command to a session", args: ["session_id", "command"] },
|
|
533
|
-
{ name: "resize_session", description: "Resize a session terminal", args: ["session_id", "rows", "cols"] },
|
|
534
|
-
{ name: "close_session", description: "Close a terminal session", args: ["session_id"] },
|
|
535
|
-
// SSH operations
|
|
536
|
-
{ name: "exec_ssh", description: "Execute command via SSH", args: ["host", "command", "options?"] },
|
|
537
|
-
{ name: "test_connection", description: "Test SSH connection", args: ["host"] },
|
|
538
|
-
// Tmux operations
|
|
539
|
-
{ name: "list_tmux_sessions", description: "List all tmux sessions" },
|
|
540
|
-
// File operations
|
|
541
|
-
{ name: "list_files", description: "List files on remote host", args: ["host", "path?"] },
|
|
542
|
-
{ name: "upload_file", description: "Upload file via SCP", args: ["host", "local_path", "remote_path"] },
|
|
543
|
-
{ name: "download_file", description: "Download file via SCP", args: ["host", "remote_path", "local_path"] },
|
|
544
|
-
// Connection management
|
|
545
|
-
{ name: "get_active_connections", description: "Get active SSH connections" },
|
|
546
|
-
]
|
|
547
|
-
})];
|
|
548
|
-
case 33: return [2 /*return*/, Response.json({ error: "Not found" }, { status: 404 })];
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}); },
|
|
552
|
-
});
|
|
553
|
-
console.log("\uD83D\uDE80 Terminal MCP Server running on port ".concat(MCP_PORT));
|
|
554
|
-
console.log(" Health: http://localhost:".concat(MCP_PORT, "/health"));
|
|
555
|
-
console.log(" MCP: http://localhost:".concat(MCP_PORT, "/mcp"));
|