mcp-terminal-runner 0.2.2 → 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.
Files changed (48) hide show
  1. package/README.md +49 -3
  2. package/dist/index.d.ts +1 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +7 -184
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.test.js +63 -0
  7. package/dist/index.test.js.map +1 -1
  8. package/dist/server.d.ts +3 -0
  9. package/dist/server.d.ts.map +1 -0
  10. package/dist/server.js +15 -0
  11. package/dist/server.js.map +1 -0
  12. package/dist/services/SessionManager.d.ts +26 -0
  13. package/dist/services/SessionManager.d.ts.map +1 -0
  14. package/dist/services/SessionManager.js +97 -0
  15. package/dist/services/SessionManager.js.map +1 -0
  16. package/dist/services/session-manager.d.ts +26 -0
  17. package/dist/services/session-manager.d.ts.map +1 -0
  18. package/dist/services/session-manager.js +105 -0
  19. package/dist/services/session-manager.js.map +1 -0
  20. package/dist/tools/execute.d.ts +3 -0
  21. package/dist/tools/execute.d.ts.map +1 -0
  22. package/dist/tools/execute.js +50 -0
  23. package/dist/tools/execute.js.map +1 -0
  24. package/dist/tools/index.d.ts +3 -0
  25. package/dist/tools/index.d.ts.map +1 -0
  26. package/dist/tools/index.js +11 -0
  27. package/dist/tools/index.js.map +1 -0
  28. package/dist/tools/session.d.ts +3 -0
  29. package/dist/tools/session.d.ts.map +1 -0
  30. package/dist/tools/session.js +151 -0
  31. package/dist/tools/session.js.map +1 -0
  32. package/dist/types.d.ts +6 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +3 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/utils/command.d.ts +7 -0
  37. package/dist/utils/command.d.ts.map +1 -0
  38. package/dist/utils/command.js +63 -0
  39. package/dist/utils/command.js.map +1 -0
  40. package/dist/utils/env.d.ts +2 -0
  41. package/dist/utils/env.d.ts.map +1 -0
  42. package/dist/utils/env.js +14 -0
  43. package/dist/utils/env.js.map +1 -0
  44. package/dist/utils/paths.d.ts +4 -0
  45. package/dist/utils/paths.d.ts.map +1 -0
  46. package/dist/utils/paths.js +87 -0
  47. package/dist/utils/paths.js.map +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sessionManager = exports.SessionManager = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ class SessionManager {
6
+ sessions = new Map();
7
+ createSession(process) {
8
+ const id = (0, node_crypto_1.randomUUID)();
9
+ const session = {
10
+ id,
11
+ process,
12
+ stdoutBuffer: [],
13
+ stderrBuffer: [],
14
+ createdAt: Date.now(),
15
+ outputListeners: [],
16
+ };
17
+ process.stdout?.setEncoding('utf8');
18
+ process.stderr?.setEncoding('utf8');
19
+ const notifyListeners = () => {
20
+ const listeners = session.outputListeners;
21
+ session.outputListeners = [];
22
+ for (const listener of listeners) {
23
+ listener();
24
+ }
25
+ };
26
+ process.stdout?.on('data', (chunk) => {
27
+ session.stdoutBuffer.push(chunk);
28
+ notifyListeners();
29
+ });
30
+ process.stderr?.on('data', (chunk) => {
31
+ session.stderrBuffer.push(chunk);
32
+ notifyListeners();
33
+ });
34
+ this.sessions.set(id, session);
35
+ return { sessionId: id, pid: process.pid ?? -1 };
36
+ }
37
+ getSession(id) {
38
+ return this.sessions.get(id);
39
+ }
40
+ readOutput(id, timeout = 0) {
41
+ const session = this.sessions.get(id);
42
+ if (!session) {
43
+ throw new Error(`Session not found: ${id}`);
44
+ }
45
+ const flush = () => {
46
+ const stdout = session.stdoutBuffer.join('');
47
+ const stderr = session.stderrBuffer.join('');
48
+ session.stdoutBuffer = [];
49
+ session.stderrBuffer = [];
50
+ const isActive = session.process.exitCode === null &&
51
+ session.process.signalCode === null;
52
+ return { stdout, stderr, isActive };
53
+ };
54
+ // If there is data or no timeout, return immediately
55
+ if (session.stdoutBuffer.length > 0 ||
56
+ session.stderrBuffer.length > 0 ||
57
+ timeout <= 0) {
58
+ return Promise.resolve(flush());
59
+ }
60
+ // Wait for data or timeout
61
+ return new Promise((resolvePromise) => {
62
+ let timeoutTimer;
63
+ let debounceTimer;
64
+ const finish = () => {
65
+ clearTimeout(timeoutTimer);
66
+ clearTimeout(debounceTimer);
67
+ // Remove listener
68
+ session.outputListeners = session.outputListeners.filter((l) => l !== onData);
69
+ resolvePromise(flush());
70
+ };
71
+ const onData = () => {
72
+ // When data arrives, wait a bit (debounce) to collect subsequent chunks
73
+ if (debounceTimer) {
74
+ clearTimeout(debounceTimer);
75
+ }
76
+ debounceTimer = setTimeout(finish, 50); // 50ms debounce
77
+ };
78
+ // Global timeout
79
+ timeoutTimer = setTimeout(finish, timeout);
80
+ session.outputListeners.push(onData);
81
+ });
82
+ }
83
+ writeInput(id, input) {
84
+ const session = this.sessions.get(id);
85
+ if (!session) {
86
+ throw new Error(`Session not found: ${id}`);
87
+ }
88
+ if (session.process.stdin) {
89
+ session.process.stdin.write(input);
90
+ }
91
+ else {
92
+ throw new Error('Process stdin is not available');
93
+ }
94
+ }
95
+ stopSession(id, signal = 'SIGTERM') {
96
+ const session = this.sessions.get(id);
97
+ if (!session) {
98
+ throw new Error(`Session not found: ${id}`);
99
+ }
100
+ session.process.kill(signal);
101
+ }
102
+ }
103
+ exports.SessionManager = SessionManager;
104
+ exports.sessionManager = new SessionManager();
105
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/services/session-manager.ts"],"names":[],"mappings":";;;AACA,6CAAyC;AAWzC,MAAa,cAAc;IACR,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEvD,aAAa,CAAC,OAAqB;QACjC,MAAM,EAAE,GAAG,IAAA,wBAAU,GAAE,CAAC;QACxB,MAAM,OAAO,GAAY;YACvB,EAAE;YACF,OAAO;YACP,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,EAAE;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,eAAe,EAAE,EAAE;SACpB,CAAC;QAEF,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAEpC,MAAM,eAAe,GAAG,GAAG,EAAE;YAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC;YAC1C,OAAO,CAAC,eAAe,GAAG,EAAE,CAAC;YAC7B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC,CAAC;QAEF,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC3C,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,eAAe,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC3C,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,eAAe,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,UAAU,CACR,EAAU,EACV,OAAO,GAAG,CAAC;QAMX,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAE7C,OAAO,CAAC,YAAY,GAAG,EAAE,CAAC;YAC1B,OAAO,CAAC,YAAY,GAAG,EAAE,CAAC;YAE1B,MAAM,QAAQ,GACZ,OAAO,CAAC,OAAO,CAAC,QAAQ,KAAK,IAAI;gBACjC,OAAO,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC;YAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC,CAAC;QAEF,qDAAqD;QACrD,IACE,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YAC/B,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YAC/B,OAAO,IAAI,CAAC,EACZ,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,2BAA2B;QAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;YACpC,IAAI,YAA4B,CAAC;YACjC,IAAI,aAA6B,CAAC;YAElC,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC3B,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC5B,kBAAkB;gBAClB,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CACtD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CACpB,CAAC;gBACF,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;YAC1B,CAAC,CAAC;YAEF,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,wEAAwE;gBACxE,IAAI,aAAa,EAAE,CAAC;oBAClB,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC9B,CAAC;gBACD,aAAa,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB;YAC1D,CAAC,CAAC;YAEF,iBAAiB;YACjB,YAAY,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE3C,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,EAAU,EAAE,KAAa;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,WAAW,CAAC,EAAU,EAAE,SAAyB,SAAS;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;CACF;AAjID,wCAiIC;AAEY,QAAA,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerExecuteTool: (server: McpServer) => void;
3
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/tools/execute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,eAAO,MAAM,mBAAmB,GAAI,QAAQ,SAAS,SAsDpD,CAAC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerExecuteTool = void 0;
4
+ const js_yaml_1 = require("js-yaml");
5
+ const zod_1 = require("zod");
6
+ const command_js_1 = require("../utils/command.js");
7
+ const registerExecuteTool = (server) => {
8
+ server.tool('execute_command', 'Execute a shell command. Note: This tool is for non-interactive, short-lived commands. For interactive or long-running processes, use start_command instead.', {
9
+ command: zod_1.z.string().describe('The shell command to execute'),
10
+ cwd: zod_1.z
11
+ .string()
12
+ .optional()
13
+ .describe('Optional working directory to execute the command within'),
14
+ input: zod_1.z
15
+ .string()
16
+ .optional()
17
+ .describe('Optional input to write to stdin. Useful for commands that require user interaction.'),
18
+ }, async (args) => {
19
+ try {
20
+ const { command: finalCommand, cwd: finalCwd } = await (0, command_js_1.prepareCommand)(args.command, args.cwd);
21
+ const result = await (0, command_js_1.runCommand)(finalCommand, finalCwd, args.input);
22
+ return {
23
+ content: [
24
+ {
25
+ type: 'text',
26
+ text: (0, js_yaml_1.dump)({
27
+ exit_code: result.exitCode,
28
+ stdout: result.stdout,
29
+ stderr: result.stderr,
30
+ }),
31
+ },
32
+ ],
33
+ };
34
+ }
35
+ catch (error) {
36
+ const errorMessage = error instanceof Error ? error.message : String(error);
37
+ return {
38
+ content: [
39
+ {
40
+ type: 'text',
41
+ text: `Error executing command: ${errorMessage}`,
42
+ },
43
+ ],
44
+ isError: true,
45
+ };
46
+ }
47
+ });
48
+ };
49
+ exports.registerExecuteTool = registerExecuteTool;
50
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/tools/execute.ts"],"names":[],"mappings":";;;AACA,qCAA+B;AAC/B,6BAAwB;AACxB,oDAAiE;AAE1D,MAAM,mBAAmB,GAAG,CAAC,MAAiB,EAAE,EAAE;IACvD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,8JAA8J,EAC9J;QACE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC5D,GAAG,EAAE,OAAC;aACH,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;QACvE,KAAK,EAAE,OAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sFAAsF,CACvF;KACJ,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAA,2BAAc,EACnE,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,GAAG,CACT,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAU,EAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAEpE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,cAAI,EAAC;4BACT,SAAS,EAAE,MAAM,CAAC,QAAQ;4BAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;4BACrB,MAAM,EAAE,MAAM,CAAC,MAAM;yBACtB,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEzD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,4BAA4B,YAAY,EAAE;qBACjD;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC,CAAC;AAtDW,QAAA,mBAAmB,uBAsD9B"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerTools: (server: McpServer) => void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,SAG9C,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTools = void 0;
4
+ const execute_js_1 = require("./execute.js");
5
+ const session_js_1 = require("./session.js");
6
+ const registerTools = (server) => {
7
+ (0, execute_js_1.registerExecuteTool)(server);
8
+ (0, session_js_1.registerSessionTools)(server);
9
+ };
10
+ exports.registerTools = registerTools;
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":";;;AACA,6CAAmD;AACnD,6CAAoD;AAE7C,MAAM,aAAa,GAAG,CAAC,MAAiB,EAAE,EAAE;IACjD,IAAA,gCAAmB,EAAC,MAAM,CAAC,CAAC;IAC5B,IAAA,iCAAoB,EAAC,MAAM,CAAC,CAAC;AAC/B,CAAC,CAAC;AAHW,QAAA,aAAa,iBAGxB"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerSessionTools: (server: McpServer) => void;
3
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS,SA8LrD,CAAC"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerSessionTools = void 0;
7
+ const cross_spawn_1 = __importDefault(require("cross-spawn"));
8
+ const js_yaml_1 = require("js-yaml");
9
+ const zod_1 = require("zod");
10
+ const session_manager_js_1 = require("../services/session-manager.js");
11
+ const command_js_1 = require("../utils/command.js");
12
+ const registerSessionTools = (server) => {
13
+ server.tool('start_command', 'Start a background command session. Use this for interactive commands or long-running processes.', {
14
+ command: zod_1.z.string().describe('The shell command to execute'),
15
+ cwd: zod_1.z
16
+ .string()
17
+ .optional()
18
+ .describe('Optional working directory to execute the command within'),
19
+ timeout: zod_1.z
20
+ .number()
21
+ .optional()
22
+ .describe('Maximum time (in milliseconds) to wait for initial output. Default is 0 (no wait).'),
23
+ }, async (args) => {
24
+ try {
25
+ const { command: finalCommand, cwd: finalCwd } = await (0, command_js_1.prepareCommand)(args.command, args.cwd);
26
+ const child = (0, cross_spawn_1.default)(finalCommand, {
27
+ cwd: finalCwd,
28
+ shell: true,
29
+ windowsHide: true,
30
+ stdio: ['pipe', 'pipe', 'pipe'],
31
+ });
32
+ const { sessionId, pid } = session_manager_js_1.sessionManager.createSession(child);
33
+ const result = { sessionId, pid };
34
+ if (args.timeout && args.timeout > 0) {
35
+ const output = await session_manager_js_1.sessionManager.readOutput(sessionId, args.timeout);
36
+ result.stdout = output.stdout;
37
+ result.stderr = output.stderr;
38
+ }
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text',
43
+ text: (0, js_yaml_1.dump)(result),
44
+ },
45
+ ],
46
+ };
47
+ }
48
+ catch (error) {
49
+ return {
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: `Error starting command: ${error instanceof Error ? error.message : String(error)}`,
54
+ },
55
+ ],
56
+ isError: true,
57
+ };
58
+ }
59
+ });
60
+ server.tool('read_output', 'Read buffered output from a command session', {
61
+ sessionId: zod_1.z.string().describe('The ID of the session'),
62
+ timeout: zod_1.z
63
+ .number()
64
+ .optional()
65
+ .describe('Maximum time (in milliseconds) to wait for new output if the buffer is empty. Default is 0 (no wait).'),
66
+ }, async (args) => {
67
+ try {
68
+ const result = await session_manager_js_1.sessionManager.readOutput(args.sessionId, args.timeout);
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: (0, js_yaml_1.dump)(result),
74
+ },
75
+ ],
76
+ };
77
+ }
78
+ catch (error) {
79
+ return {
80
+ content: [
81
+ {
82
+ type: 'text',
83
+ text: `Error reading output: ${error instanceof Error ? error.message : String(error)}`,
84
+ },
85
+ ],
86
+ isError: true,
87
+ };
88
+ }
89
+ });
90
+ server.tool('write_input', 'Write input to a command session', {
91
+ sessionId: zod_1.z.string().describe('The ID of the session'),
92
+ input: zod_1.z.string().describe('The input to write'),
93
+ }, async (args) => {
94
+ try {
95
+ await Promise.resolve();
96
+ session_manager_js_1.sessionManager.writeInput(args.sessionId, args.input);
97
+ return {
98
+ content: [
99
+ {
100
+ type: 'text',
101
+ text: (0, js_yaml_1.dump)({ success: true }),
102
+ },
103
+ ],
104
+ };
105
+ }
106
+ catch (error) {
107
+ return {
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: `Error writing input: ${error instanceof Error ? error.message : String(error)}`,
112
+ },
113
+ ],
114
+ isError: true,
115
+ };
116
+ }
117
+ });
118
+ server.tool('stop_command', 'Stop a command session', {
119
+ sessionId: zod_1.z.string().describe('The ID of the session'),
120
+ signal: zod_1.z
121
+ .string()
122
+ .optional()
123
+ .describe('The signal to send (default: SIGTERM)'),
124
+ }, async (args) => {
125
+ try {
126
+ await Promise.resolve();
127
+ session_manager_js_1.sessionManager.stopSession(args.sessionId, args.signal ?? 'SIGTERM');
128
+ return {
129
+ content: [
130
+ {
131
+ type: 'text',
132
+ text: (0, js_yaml_1.dump)({ success: true }),
133
+ },
134
+ ],
135
+ };
136
+ }
137
+ catch (error) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: 'text',
142
+ text: `Error stopping session: ${error instanceof Error ? error.message : String(error)}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
148
+ });
149
+ };
150
+ exports.registerSessionTools = registerSessionTools;
151
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":";;;;;;AACA,8DAAgC;AAChC,qCAA+B;AAC/B,6BAAwB;AACxB,uEAAgE;AAChE,oDAAqD;AAE9C,MAAM,oBAAoB,GAAG,CAAC,MAAiB,EAAE,EAAE;IACxD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,kGAAkG,EAClG;QACE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC5D,GAAG,EAAE,OAAC;aACH,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;QACvE,OAAO,EAAE,OAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,oFAAoF,CACrF;KACJ,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAA,2BAAc,EACnE,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,GAAG,CACT,CAAC;YAEF,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,YAAY,EAAE;gBAChC,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,IAAI;gBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YAEH,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,mCAAc,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAE/D,MAAM,MAAM,GAKR,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;YAEvB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBACrC,MAAM,MAAM,GAAG,MAAM,mCAAc,CAAC,UAAU,CAC5C,SAAS,EACT,IAAI,CAAC,OAAO,CACb,CAAC;gBACF,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC9B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAChC,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,cAAI,EAAC,MAAM,CAAC;qBACnB;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,2BACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,6CAA6C,EAC7C;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACvD,OAAO,EAAE,OAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,uGAAuG,CACxG;KACJ,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,mCAAc,CAAC,UAAU,CAC5C,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,OAAO,CACb,CAAC;YACF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,cAAI,EAAC,MAAM,CAAC;qBACnB;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,yBACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,kCAAkC,EAClC;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACvD,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;KACjD,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,mCAAc,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACtD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,cAAI,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;qBAC9B;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,wBACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,wBAAwB,EACxB;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACvD,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uCAAuC,CAAC;KACrD,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,mCAAc,CAAC,WAAW,CACxB,IAAI,CAAC,SAAS,EACb,IAAI,CAAC,MAAyB,IAAI,SAAS,CAC7C,CAAC;YACF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,cAAI,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;qBAC9B;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,2BACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC,CAAC;AA9LW,QAAA,oBAAoB,wBA8L/B"}
@@ -0,0 +1,6 @@
1
+ export interface CommandResult {
2
+ exitCode: number;
3
+ stdout: string;
4
+ stderr: string;
5
+ }
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { CommandResult } from '../types.js';
2
+ export declare const runCommand: (command: string, cwd?: string, input?: string) => Promise<CommandResult>;
3
+ export declare const prepareCommand: (command: string, cwd?: string) => Promise<{
4
+ command: string;
5
+ cwd?: string;
6
+ }>;
7
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/utils/command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,eAAO,MAAM,UAAU,GACrB,SAAS,MAAM,EACf,MAAM,MAAM,EACZ,QAAQ,MAAM,KACb,OAAO,CAAC,aAAa,CAsCpB,CAAC;AAEL,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,MAAM,MAAM,KACX,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CA8B3C,CAAC"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.prepareCommand = exports.runCommand = void 0;
7
+ const args_tokenizer_1 = require("args-tokenizer");
8
+ const cross_spawn_1 = __importDefault(require("cross-spawn"));
9
+ const env_js_1 = require("./env.js");
10
+ const paths_js_1 = require("./paths.js");
11
+ const runCommand = async (command, cwd, input) => new Promise((resolvePromise, rejectPromise) => {
12
+ const child = (0, cross_spawn_1.default)(command, {
13
+ cwd,
14
+ shell: true,
15
+ windowsHide: true,
16
+ stdio: ['pipe', 'pipe', 'pipe'],
17
+ });
18
+ if (input) {
19
+ child.stdin?.write(input);
20
+ child.stdin?.end();
21
+ }
22
+ let stdout = '';
23
+ let stderr = '';
24
+ child.stdout?.setEncoding('utf8');
25
+ child.stderr?.setEncoding('utf8');
26
+ child.stdout?.on('data', (chunk) => {
27
+ stdout += chunk;
28
+ });
29
+ child.stderr?.on('data', (chunk) => {
30
+ stderr += chunk;
31
+ });
32
+ child.on('error', (error) => {
33
+ rejectPromise(error);
34
+ });
35
+ child.on('close', (code) => {
36
+ resolvePromise({
37
+ exitCode: typeof code === 'number' ? code : 1,
38
+ stdout,
39
+ stderr,
40
+ });
41
+ });
42
+ });
43
+ exports.runCommand = runCommand;
44
+ const prepareCommand = async (command, cwd) => {
45
+ const [bin] = (0, args_tokenizer_1.tokenizeArgs)(command);
46
+ const allowedCommands = (0, env_js_1.parseCommaSeparatedEnv)(process.env.ALLOWED_COMMANDS);
47
+ if (!(allowedCommands.includes('*') || allowedCommands.includes(bin))) {
48
+ throw new Error(`Command "${bin}" is not allowed, allowed commands: ${allowedCommands.length > 0 ? allowedCommands.join(', ') : '(none)'}`);
49
+ }
50
+ const cwdToUse = cwd ?? (0, paths_js_1.getWslCwd)();
51
+ const cwdResolved = cwdToUse
52
+ ? await (0, paths_js_1.resolveAndValidateCwd)(cwdToUse)
53
+ : undefined;
54
+ let finalCommand = command;
55
+ let finalCwd = cwdResolved;
56
+ if (process.platform === 'win32' && cwdResolved?.startsWith('/')) {
57
+ finalCommand = `wsl --cd "${cwdResolved}" -- bash -c "${command.replace(/"/g, '\\"')}"`;
58
+ finalCwd = undefined;
59
+ }
60
+ return { command: finalCommand, cwd: finalCwd };
61
+ };
62
+ exports.prepareCommand = prepareCommand;
63
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/utils/command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const parseCommaSeparatedEnv: (value: string | undefined) => string[];
2
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,EAQxE,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseCommaSeparatedEnv = void 0;
4
+ const parseCommaSeparatedEnv = (value) => {
5
+ if (!value) {
6
+ return [];
7
+ }
8
+ return value
9
+ .split(',')
10
+ .map((item) => item.trim())
11
+ .filter((item) => item.length > 0);
12
+ };
13
+ exports.parseCommaSeparatedEnv = parseCommaSeparatedEnv;
14
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":";;;AAAO,MAAM,sBAAsB,GAAG,CAAC,KAAyB,EAAY,EAAE;IAC5E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC;AARW,QAAA,sBAAsB,0BAQjC"}
@@ -0,0 +1,4 @@
1
+ export declare const isWithinRoot: (root: string, target: string) => boolean;
2
+ export declare const resolveAndValidateCwd: (cwdInput: string) => Promise<string>;
3
+ export declare const getWslCwd: () => string | undefined;
4
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,KAAG,OAQ3D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,MAAM,KACf,OAAO,CAAC,MAAM,CAiEhB,CAAC;AAEF,eAAO,MAAM,SAAS,QAAO,MAAM,GAAG,SAgBrC,CAAC"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWslCwd = exports.resolveAndValidateCwd = exports.isWithinRoot = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const promises_1 = require("node:fs/promises");
6
+ const node_path_1 = require("node:path");
7
+ const env_js_1 = require("./env.js");
8
+ const isWithinRoot = (root, target) => {
9
+ const rel = (0, node_path_1.relative)(root, target);
10
+ if (rel === '') {
11
+ return true;
12
+ }
13
+ const isOutsideRoot = rel.startsWith('..') || (0, node_path_1.isAbsolute)(rel);
14
+ return !isOutsideRoot;
15
+ };
16
+ exports.isWithinRoot = isWithinRoot;
17
+ const resolveAndValidateCwd = async (cwdInput) => {
18
+ if (process.platform === 'win32' && cwdInput.startsWith('/')) {
19
+ const allowedRoots = (0, env_js_1.parseCommaSeparatedEnv)(process.env.ALLOWED_CWD_ROOTS);
20
+ if (allowedRoots.length === 0) {
21
+ return cwdInput;
22
+ }
23
+ const cwdNormalized = node_path_1.posix.normalize(cwdInput);
24
+ const allowed = allowedRoots.some((root) => {
25
+ const rel = node_path_1.posix.relative(root, cwdNormalized);
26
+ return rel === '' || !(rel.startsWith('..') || node_path_1.posix.isAbsolute(rel));
27
+ });
28
+ if (!allowed) {
29
+ throw new Error('cwd is not allowed by ALLOWED_CWD_ROOTS');
30
+ }
31
+ return cwdInput;
32
+ }
33
+ const cwdResolved = (0, node_path_1.resolve)(process.cwd(), cwdInput);
34
+ try {
35
+ const cwdStat = await (0, promises_1.stat)(cwdResolved);
36
+ if (!cwdStat.isDirectory()) {
37
+ throw new Error(`cwd is not a directory: ${cwdInput}`);
38
+ }
39
+ }
40
+ catch (error) {
41
+ if (error instanceof Error &&
42
+ error.message.includes('cwd is not a directory')) {
43
+ throw error;
44
+ }
45
+ throw new Error(`cwd does not exist: ${cwdInput}`);
46
+ }
47
+ const cwdCanonical = await (0, promises_1.realpath)(cwdResolved);
48
+ const allowedRoots = (0, env_js_1.parseCommaSeparatedEnv)(process.env.ALLOWED_CWD_ROOTS);
49
+ if (allowedRoots.length === 0) {
50
+ return cwdResolved;
51
+ }
52
+ const canonicalRoots = await Promise.all(allowedRoots.map(async (root) => {
53
+ const rootResolved = (0, node_path_1.resolve)(process.cwd(), root);
54
+ try {
55
+ return await (0, promises_1.realpath)(rootResolved);
56
+ }
57
+ catch {
58
+ throw new Error(`Invalid configuration: ALLOWED_CWD_ROOTS contains an invalid root: ${root}`);
59
+ }
60
+ }));
61
+ const allowed = canonicalRoots.some((root) => (0, exports.isWithinRoot)(root, cwdCanonical));
62
+ if (!allowed) {
63
+ throw new Error('cwd is not allowed by ALLOWED_CWD_ROOTS');
64
+ }
65
+ return cwdResolved;
66
+ };
67
+ exports.resolveAndValidateCwd = resolveAndValidateCwd;
68
+ const getWslCwd = () => {
69
+ if (process.platform !== 'win32') {
70
+ return;
71
+ }
72
+ try {
73
+ // Try to convert current working directory to WSL path
74
+ const wslPath = (0, node_child_process_1.execSync)(`wsl wslpath -u "${process.cwd()}"`)
75
+ .toString()
76
+ .trim();
77
+ if (wslPath.startsWith('/')) {
78
+ return wslPath;
79
+ }
80
+ }
81
+ catch {
82
+ // Ignore errors if wsl/wslpath is not available or fails
83
+ }
84
+ return;
85
+ };
86
+ exports.getWslCwd = getWslCwd;
87
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-terminal-runner",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "main": "index.js",
5
5
  "bin": {
6
6
  "mcp-terminal-runner": "dist/index.js"