mcp-interactive-terminal 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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -0
  3. package/dist/index.d.ts +10 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +173 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/sandbox.d.ts +33 -0
  8. package/dist/sandbox.d.ts.map +1 -0
  9. package/dist/sandbox.js +99 -0
  10. package/dist/sandbox.js.map +1 -0
  11. package/dist/session-manager.d.ts +31 -0
  12. package/dist/session-manager.d.ts.map +1 -0
  13. package/dist/session-manager.js +158 -0
  14. package/dist/session-manager.js.map +1 -0
  15. package/dist/terminal.d.ts +24 -0
  16. package/dist/terminal.d.ts.map +1 -0
  17. package/dist/terminal.js +342 -0
  18. package/dist/terminal.js.map +1 -0
  19. package/dist/tools/close-session.d.ts +16 -0
  20. package/dist/tools/close-session.d.ts.map +1 -0
  21. package/dist/tools/close-session.js +13 -0
  22. package/dist/tools/close-session.js.map +1 -0
  23. package/dist/tools/confirm-dangerous-command.d.ts +19 -0
  24. package/dist/tools/confirm-dangerous-command.d.ts.map +1 -0
  25. package/dist/tools/confirm-dangerous-command.js +48 -0
  26. package/dist/tools/confirm-dangerous-command.js.map +1 -0
  27. package/dist/tools/create-session.d.ts +31 -0
  28. package/dist/tools/create-session.d.ts.map +1 -0
  29. package/dist/tools/create-session.js +39 -0
  30. package/dist/tools/create-session.js.map +1 -0
  31. package/dist/tools/list-sessions.d.ts +4 -0
  32. package/dist/tools/list-sessions.d.ts.map +1 -0
  33. package/dist/tools/list-sessions.js +4 -0
  34. package/dist/tools/list-sessions.js.map +1 -0
  35. package/dist/tools/read-output.d.ts +16 -0
  36. package/dist/tools/read-output.d.ts.map +1 -0
  37. package/dist/tools/read-output.js +21 -0
  38. package/dist/tools/read-output.js.map +1 -0
  39. package/dist/tools/send-command.d.ts +22 -0
  40. package/dist/tools/send-command.d.ts.map +1 -0
  41. package/dist/tools/send-command.js +101 -0
  42. package/dist/tools/send-command.js.map +1 -0
  43. package/dist/tools/send-control.d.ts +16 -0
  44. package/dist/tools/send-control.d.ts.map +1 -0
  45. package/dist/tools/send-control.js +92 -0
  46. package/dist/tools/send-control.js.map +1 -0
  47. package/dist/types.d.ts +117 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +55 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/utils/audit-logger.d.ts +23 -0
  52. package/dist/utils/audit-logger.d.ts.map +1 -0
  53. package/dist/utils/audit-logger.js +37 -0
  54. package/dist/utils/audit-logger.js.map +1 -0
  55. package/dist/utils/danger-detector.d.ts +14 -0
  56. package/dist/utils/danger-detector.d.ts.map +1 -0
  57. package/dist/utils/danger-detector.js +59 -0
  58. package/dist/utils/danger-detector.js.map +1 -0
  59. package/dist/utils/output-detector.d.ts +19 -0
  60. package/dist/utils/output-detector.d.ts.map +1 -0
  61. package/dist/utils/output-detector.js +85 -0
  62. package/dist/utils/output-detector.js.map +1 -0
  63. package/dist/utils/sanitizer.d.ts +31 -0
  64. package/dist/utils/sanitizer.d.ts.map +1 -0
  65. package/dist/utils/sanitizer.js +82 -0
  66. package/dist/utils/sanitizer.js.map +1 -0
  67. package/dist/utils/secret-redactor.d.ts +10 -0
  68. package/dist/utils/secret-redactor.d.ts.map +1 -0
  69. package/dist/utils/secret-redactor.js +36 -0
  70. package/dist/utils/secret-redactor.js.map +1 -0
  71. package/package.json +53 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mcp-interactive-terminal contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # mcp-interactive-terminal
2
+
3
+ MCP server for interactive shell sessions. Run REPLs, SSH, database clients, and any interactive CLI through AI agents like Claude Code, Cursor, and others.
4
+
5
+ ## The Problem
6
+
7
+ AI coding agents can't handle interactive commands — no PTY, no stdin streaming. You can't run `rails console`, `python`, `psql`, `ssh`, or any REPL through them.
8
+
9
+ ## The Solution
10
+
11
+ This MCP server spawns real pseudo-terminals (PTY) and uses xterm-headless (the same terminal emulator as VS Code) to render clean text output. The AI sees exactly what a human would see — no raw ANSI escape codes.
12
+
13
+ ```
14
+ AI Agent (Claude Code, Cursor, etc.)
15
+ ↕ MCP (JSON-RPC over stdio)
16
+ MCP Terminal Server
17
+ ↕ node-pty (pseudo-terminal)
18
+ Interactive Process (rails console, python, psql, ssh, bash...)
19
+ ↕ xterm-headless (terminal emulation)
20
+ Clean text output
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ### Claude Code
26
+
27
+ ```bash
28
+ claude mcp add terminal -- npx -y mcp-interactive-terminal
29
+ ```
30
+
31
+ ### Manual Configuration
32
+
33
+ Add to `~/.claude.json` or `.mcp.json`:
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "terminal": {
39
+ "command": "npx",
40
+ "args": ["-y", "mcp-interactive-terminal"]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Tools
47
+
48
+ ### `create_session` — Spawn an interactive process
49
+
50
+ ```json
51
+ { "command": "python3", "name": "my-python", "cwd": "/project" }
52
+ → { "session_id": "a1b2c3d4", "name": "my-python", "pid": 12345 }
53
+ ```
54
+
55
+ **Parameters:** `command` (required), `args?`, `name?`, `cwd?`, `env?`, `cols?` (default 120), `rows?` (default 40)
56
+
57
+ ### `send_command` — Send input and get output
58
+
59
+ ```json
60
+ { "session_id": "a1b2c3d4", "input": "1 + 1" }
61
+ → { "output": "2", "is_complete": true, "is_alive": true }
62
+ ```
63
+
64
+ **Parameters:** `session_id`, `input`, `timeout_ms?` (default 5000), `max_output_chars?`
65
+
66
+ Dangerous commands (rm -rf, DROP TABLE, curl|bash, etc.) are blocked and require `confirm_dangerous_command` first.
67
+
68
+ ### `read_output` — Read terminal screen (read-only)
69
+
70
+ ```json
71
+ { "session_id": "a1b2c3d4" }
72
+ → { "output": ">>> ", "is_alive": true }
73
+ ```
74
+
75
+ **Parameters:** `session_id`, `full_screen?` (default false)
76
+
77
+ ### `list_sessions` — List active sessions (read-only)
78
+
79
+ ```json
80
+ → [{ "session_id": "a1b2c3d4", "name": "my-python", "command": "python3", "pid": 12345, "is_alive": true, "created_at": "..." }]
81
+ ```
82
+
83
+ ### `close_session` — Kill a session
84
+
85
+ ```json
86
+ { "session_id": "a1b2c3d4" }
87
+ → { "success": true }
88
+ ```
89
+
90
+ **Parameters:** `session_id`, `signal?` (default SIGTERM)
91
+
92
+ ### `send_control` — Send control characters
93
+
94
+ ```json
95
+ { "session_id": "a1b2c3d4", "control": "ctrl+c" }
96
+ → { "output": "^C\n>>>" }
97
+ ```
98
+
99
+ **Supported keys:** ctrl+c, ctrl+d, ctrl+z, ctrl+l, ctrl+r, tab, escape, up, down, left, right, enter, backspace, delete, home, end, and more.
100
+
101
+ ### `confirm_dangerous_command` — Two-step safety confirmation
102
+
103
+ ```json
104
+ { "session_id": "a1b2c3d4", "input": "rm -rf /tmp/old", "justification": "Cleaning up stale temp files from failed build" }
105
+ → { "output": "...", "is_complete": true, "is_alive": true }
106
+ ```
107
+
108
+ Required when `send_command` detects a dangerous pattern. The AI must provide a justification.
109
+
110
+ ## Security
111
+
112
+ Seven-layer defense-in-depth model:
113
+
114
+ | Layer | What It Does | Default |
115
+ |-------|-------------|---------|
116
+ | MCP Tool Annotations | `readOnlyHint`/`destructiveHint` on each tool | Always on |
117
+ | Confirmation flow | Dangerous patterns require `confirm_dangerous_command` | Always on |
118
+ | Input pattern detection | Detect rm -rf, DROP TABLE, curl\|bash, etc. | Always on |
119
+ | Command blocklist/allowlist | Block/allow specific commands | Configurable |
120
+ | OS-level sandbox | Kernel-level process sandboxing | Off (opt-in) |
121
+ | Secret redaction | Redact AWS keys, tokens, private keys in output | Off (opt-in) |
122
+ | Resource limits | Max sessions, output cap, idle timeout | Always on |
123
+
124
+ **Recommended permission configuration** — only auto-approve read-only tools:
125
+
126
+ ```json
127
+ {
128
+ "permissions": {
129
+ "allow": [
130
+ "mcp__terminal__list_sessions",
131
+ "mcp__terminal__read_output"
132
+ ]
133
+ }
134
+ }
135
+ ```
136
+
137
+ ## Configuration
138
+
139
+ All configuration via environment variables:
140
+
141
+ | Variable | Default | Description |
142
+ |----------|---------|-------------|
143
+ | `MCP_TERMINAL_MAX_SESSIONS` | `10` | Max concurrent sessions |
144
+ | `MCP_TERMINAL_MAX_OUTPUT` | `20000` | Max output chars per read |
145
+ | `MCP_TERMINAL_DEFAULT_TIMEOUT` | `5000` | Default wait timeout (ms) |
146
+ | `MCP_TERMINAL_BLOCKED_COMMANDS` | (none) | Comma-separated blocklist |
147
+ | `MCP_TERMINAL_ALLOWED_COMMANDS` | (none) | Comma-separated allowlist |
148
+ | `MCP_TERMINAL_REDACT_SECRETS` | `false` | Redact detected secrets |
149
+ | `MCP_TERMINAL_LOG_INPUTS` | `false` | Log all inputs to stderr |
150
+ | `MCP_TERMINAL_IDLE_TIMEOUT` | `0` | Auto-close idle sessions (ms, 0=disabled) |
151
+ | `MCP_TERMINAL_DANGER_DETECTION` | `true` | Enable dangerous command detection |
152
+
153
+ Example with env vars:
154
+
155
+ ```json
156
+ {
157
+ "mcpServers": {
158
+ "terminal": {
159
+ "command": "npx",
160
+ "args": ["-y", "mcp-interactive-terminal"],
161
+ "env": {
162
+ "MCP_TERMINAL_ALLOWED_COMMANDS": "bash,python3,node,psql",
163
+ "MCP_TERMINAL_REDACT_SECRETS": "true",
164
+ "MCP_TERMINAL_IDLE_TIMEOUT": "300000"
165
+ }
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ ## How It Works
172
+
173
+ ### Clean Output via xterm-headless
174
+
175
+ Instead of dumping raw ANSI escape codes, PTY output is fed into xterm-headless (the same terminal emulator used by VS Code, but headless). The buffer is read as plain text — properly wrapped, cursor-positioned, clean.
176
+
177
+ ### Smart "Command Done" Detection
178
+
179
+ Layered strategy (most to least reliable):
180
+
181
+ 1. **Process exit** — If the process died, command is done
182
+ 2. **Prompt detection** — Auto-detects the session's prompt at startup (bash `$`, python `>>>`, psql `#`, etc.), watches for it to reappear
183
+ 3. **Output settling** — No new output for 300ms
184
+ 4. **Timeout** — Always returns after `timeout_ms` with `is_complete: false`
185
+
186
+ ## Development
187
+
188
+ ```bash
189
+ npm install
190
+ npm run build
191
+ npm test
192
+ ```
193
+
194
+ Test with MCP Inspector:
195
+
196
+ ```bash
197
+ npx @modelcontextprotocol/inspector dist/index.js
198
+ ```
199
+
200
+ ## License
201
+
202
+ MIT
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Interactive Terminal Server
4
+ *
5
+ * Provides AI agents with interactive terminal sessions via the
6
+ * Model Context Protocol. Supports REPLs, SSH, databases, and
7
+ * any interactive CLI.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
package/dist/index.js ADDED
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Interactive Terminal Server
4
+ *
5
+ * Provides AI agents with interactive terminal sessions via the
6
+ * Model Context Protocol. Supports REPLs, SSH, databases, and
7
+ * any interactive CLI.
8
+ */
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { loadConfig } from "./types.js";
12
+ import { SessionManager } from "./session-manager.js";
13
+ import { createSessionSchema, handleCreateSession } from "./tools/create-session.js";
14
+ import { sendCommandSchema, handleSendCommand } from "./tools/send-command.js";
15
+ import { readOutputSchema, handleReadOutput } from "./tools/read-output.js";
16
+ import { handleListSessions } from "./tools/list-sessions.js";
17
+ import { closeSessionSchema, handleCloseSession } from "./tools/close-session.js";
18
+ import { sendControlSchema, handleSendControl } from "./tools/send-control.js";
19
+ import { confirmDangerousCommandSchema, handleConfirmDangerousCommand, } from "./tools/confirm-dangerous-command.js";
20
+ import { initSandbox, resetSandbox } from "./sandbox.js";
21
+ import { configureAudit, audit } from "./utils/audit-logger.js";
22
+ const config = loadConfig();
23
+ const sessionManager = new SessionManager(config);
24
+ const server = new McpServer({
25
+ name: "mcp-interactive-terminal",
26
+ version: "1.0.0",
27
+ });
28
+ // --- Tool Registration ---
29
+ server.tool("create_session", "Spawn an interactive terminal session (REPL, shell, database client, SSH, etc.). Returns a session_id for subsequent commands.", createSessionSchema.shape, { title: "Create Session", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ command, args, name, cwd, env, cols, rows }) => {
30
+ try {
31
+ const result = await handleCreateSession({ command, args, name, cwd, env, cols, rows }, sessionManager, config);
32
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
33
+ }
34
+ catch (err) {
35
+ return {
36
+ content: [{ type: "text", text: `Error: ${err.message}` }],
37
+ isError: true,
38
+ };
39
+ }
40
+ });
41
+ server.tool("send_command", "Send a command/input to an interactive session and wait for output. Appends newline automatically. Returns clean text output (no ANSI codes). If a dangerous command is detected, you must use confirm_dangerous_command first.", sendCommandSchema.shape, { title: "Send Command", readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }, async ({ session_id, input, timeout_ms, max_output_chars }) => {
42
+ try {
43
+ const result = await handleSendCommand({ session_id, input, timeout_ms, max_output_chars }, sessionManager, config);
44
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
45
+ }
46
+ catch (err) {
47
+ return {
48
+ content: [{ type: "text", text: `Error: ${err.message}` }],
49
+ isError: true,
50
+ };
51
+ }
52
+ });
53
+ server.tool("read_output", "Read the current terminal screen without sending any input. Safe read-only operation.", readOutputSchema.shape, { title: "Read Output", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async ({ session_id, full_screen }) => {
54
+ try {
55
+ const result = await handleReadOutput({ session_id, full_screen }, sessionManager, config);
56
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
57
+ }
58
+ catch (err) {
59
+ return {
60
+ content: [{ type: "text", text: `Error: ${err.message}` }],
61
+ isError: true,
62
+ };
63
+ }
64
+ });
65
+ server.tool("list_sessions", "List all active interactive terminal sessions. Safe read-only operation.", {}, { title: "List Sessions", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async () => {
66
+ try {
67
+ const result = await handleListSessions(sessionManager);
68
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
69
+ }
70
+ catch (err) {
71
+ return {
72
+ content: [{ type: "text", text: `Error: ${err.message}` }],
73
+ isError: true,
74
+ };
75
+ }
76
+ });
77
+ server.tool("close_session", "Close/kill an interactive terminal session.", closeSessionSchema.shape, { title: "Close Session", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }, async ({ session_id, signal }) => {
78
+ try {
79
+ const result = await handleCloseSession({ session_id, signal }, sessionManager);
80
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
81
+ }
82
+ catch (err) {
83
+ return {
84
+ content: [{ type: "text", text: `Error: ${err.message}` }],
85
+ isError: true,
86
+ };
87
+ }
88
+ });
89
+ server.tool("send_control", "Send a control character or special key to a session (e.g., ctrl+c to interrupt, ctrl+d to send EOF, arrow keys, tab for completion).", sendControlSchema.shape, { title: "Send Control", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async ({ session_id, control }) => {
90
+ try {
91
+ const result = await handleSendControl({ session_id, control }, sessionManager, config);
92
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
93
+ }
94
+ catch (err) {
95
+ return {
96
+ content: [{ type: "text", text: `Error: ${err.message}` }],
97
+ isError: true,
98
+ };
99
+ }
100
+ });
101
+ server.tool("confirm_dangerous_command", "Execute a command that was flagged as dangerous by send_command. Requires a justification explaining WHY the command is necessary. This is a separate confirmation step for safety.", confirmDangerousCommandSchema.shape, { title: "Confirm Dangerous Command", readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }, async ({ session_id, input, justification }) => {
102
+ try {
103
+ const result = await handleConfirmDangerousCommand({ session_id, input, justification }, sessionManager, config);
104
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
105
+ }
106
+ catch (err) {
107
+ return {
108
+ content: [{ type: "text", text: `Error: ${err.message}` }],
109
+ isError: true,
110
+ };
111
+ }
112
+ });
113
+ // --- Lifecycle ---
114
+ async function main() {
115
+ const transport = new StdioServerTransport();
116
+ // Initialize audit logger
117
+ if (config.auditLog) {
118
+ configureAudit(config.auditLog);
119
+ }
120
+ // Initialize sandbox if enabled
121
+ if (config.sandbox) {
122
+ await initSandbox(config);
123
+ }
124
+ // Cleanup on shutdown
125
+ process.on("SIGINT", async () => {
126
+ audit("server_stop");
127
+ sessionManager.closeAll();
128
+ await resetSandbox();
129
+ process.exit(0);
130
+ });
131
+ process.on("SIGTERM", async () => {
132
+ audit("server_stop");
133
+ sessionManager.closeAll();
134
+ await resetSandbox();
135
+ process.exit(0);
136
+ });
137
+ console.error("[mcp-terminal] Starting MCP Interactive Terminal Server v1.0.0");
138
+ console.error(`[mcp-terminal] Config: maxSessions=${config.maxSessions}, maxOutput=${config.maxOutput}, defaultTimeout=${config.defaultTimeout}ms`);
139
+ if (config.dangerDetection) {
140
+ console.error("[mcp-terminal] Dangerous command detection: ENABLED");
141
+ }
142
+ if (config.redactSecrets) {
143
+ console.error("[mcp-terminal] Secret redaction: ENABLED");
144
+ }
145
+ if (config.blockedCommands.length > 0) {
146
+ console.error(`[mcp-terminal] Blocked commands: ${config.blockedCommands.join(", ")}`);
147
+ }
148
+ if (config.allowedCommands.length > 0) {
149
+ console.error(`[mcp-terminal] Allowed commands: ${config.allowedCommands.join(", ")}`);
150
+ }
151
+ if (config.allowedPaths.length > 0) {
152
+ console.error(`[mcp-terminal] Allowed paths: ${config.allowedPaths.join(", ")}`);
153
+ }
154
+ if (config.auditLog) {
155
+ console.error(`[mcp-terminal] Audit log: ${config.auditLog}`);
156
+ }
157
+ audit("server_start", undefined, {
158
+ maxSessions: config.maxSessions,
159
+ dangerDetection: config.dangerDetection,
160
+ sandbox: config.sandbox,
161
+ redactSecrets: config.redactSecrets,
162
+ allowedCommands: config.allowedCommands,
163
+ blockedCommands: config.blockedCommands,
164
+ allowedPaths: config.allowedPaths,
165
+ });
166
+ await server.connect(transport);
167
+ }
168
+ main().catch((err) => {
169
+ console.error("[mcp-terminal] Fatal error:", err);
170
+ sessionManager.closeAll();
171
+ process.exit(1);
172
+ });
173
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Optional OS-level sandbox integration via @anthropic-ai/sandbox-runtime.
3
+ *
4
+ * When enabled (MCP_TERMINAL_SANDBOX=true), wraps spawned commands with
5
+ * kernel-level filesystem and network restrictions using sandbox-exec (macOS)
6
+ * or bubblewrap (Linux).
7
+ *
8
+ * This is an optional feature — if the package isn't installed or the platform
9
+ * isn't supported, it logs a warning and falls back to unsandboxed execution.
10
+ */
11
+ import type { ServerConfig } from "./types.js";
12
+ /**
13
+ * Initialize the sandbox if enabled in config.
14
+ * Call this once at startup. Safe to call even if the package isn't installed.
15
+ */
16
+ export declare function initSandbox(config: ServerConfig): Promise<boolean>;
17
+ /**
18
+ * Wrap a command string with sandbox restrictions.
19
+ * Returns the original command unchanged if sandbox is not available.
20
+ */
21
+ export declare function wrapCommand(command: string): Promise<{
22
+ command: string;
23
+ useShell: boolean;
24
+ }>;
25
+ /**
26
+ * Check if sandbox is currently active.
27
+ */
28
+ export declare function isSandboxActive(): boolean;
29
+ /**
30
+ * Cleanup sandbox resources on shutdown.
31
+ */
32
+ export declare function resetSandbox(): Promise<void>;
33
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C;;;GAGG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CA+CxE;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAYlG;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAQlD"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Optional OS-level sandbox integration via @anthropic-ai/sandbox-runtime.
3
+ *
4
+ * When enabled (MCP_TERMINAL_SANDBOX=true), wraps spawned commands with
5
+ * kernel-level filesystem and network restrictions using sandbox-exec (macOS)
6
+ * or bubblewrap (Linux).
7
+ *
8
+ * This is an optional feature — if the package isn't installed or the platform
9
+ * isn't supported, it logs a warning and falls back to unsandboxed execution.
10
+ */
11
+ import { audit } from "./utils/audit-logger.js";
12
+ // Lazy-loaded sandbox manager instance
13
+ let sandboxManager = null;
14
+ let sandboxInitialized = false;
15
+ let sandboxAvailable = false;
16
+ /**
17
+ * Initialize the sandbox if enabled in config.
18
+ * Call this once at startup. Safe to call even if the package isn't installed.
19
+ */
20
+ export async function initSandbox(config) {
21
+ if (!config.sandbox)
22
+ return false;
23
+ try {
24
+ const { SandboxManager } = await import("@anthropic-ai/sandbox-runtime");
25
+ sandboxManager = SandboxManager;
26
+ // Check platform support
27
+ if (!SandboxManager.isSupportedPlatform()) {
28
+ console.error("[mcp-terminal] Sandbox: platform not supported, sandbox disabled");
29
+ return false;
30
+ }
31
+ // Build config from our env vars
32
+ const allowWrite = config.sandboxAllowWrite.length > 0
33
+ ? config.sandboxAllowWrite
34
+ : ["/tmp"];
35
+ const allowedDomains = config.sandboxAllowNetwork[0] === "*"
36
+ ? [] // Empty = no restriction (but sandbox-runtime treats empty as "block all")
37
+ : config.sandboxAllowNetwork;
38
+ // If user wants unrestricted network ("*"), we use a permissive config
39
+ const networkConfig = config.sandboxAllowNetwork[0] === "*"
40
+ ? { allowedDomains: ["*"], deniedDomains: [] }
41
+ : { allowedDomains, deniedDomains: [] };
42
+ await SandboxManager.initialize({
43
+ network: networkConfig,
44
+ filesystem: {
45
+ denyRead: [],
46
+ allowWrite,
47
+ denyWrite: [],
48
+ },
49
+ allowPty: true,
50
+ });
51
+ sandboxInitialized = true;
52
+ sandboxAvailable = true;
53
+ audit("sandbox_init", undefined, { allowWrite, network: config.sandboxAllowNetwork });
54
+ console.error(`[mcp-terminal] Sandbox: ENABLED (write: ${allowWrite.join(", ")}, network: ${config.sandboxAllowNetwork.join(", ")})`);
55
+ return true;
56
+ }
57
+ catch (err) {
58
+ audit("sandbox_fail", undefined, { error: String(err) });
59
+ console.error(`[mcp-terminal] Sandbox: failed to initialize (${err}). Sandbox disabled.`);
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Wrap a command string with sandbox restrictions.
65
+ * Returns the original command unchanged if sandbox is not available.
66
+ */
67
+ export async function wrapCommand(command) {
68
+ if (!sandboxAvailable || !sandboxManager) {
69
+ return { command, useShell: false };
70
+ }
71
+ try {
72
+ const wrapped = await sandboxManager.wrapWithSandbox(command);
73
+ return { command: wrapped, useShell: true };
74
+ }
75
+ catch (err) {
76
+ console.error(`[mcp-terminal] Sandbox: wrapWithSandbox failed (${err}), running unsandboxed`);
77
+ return { command, useShell: false };
78
+ }
79
+ }
80
+ /**
81
+ * Check if sandbox is currently active.
82
+ */
83
+ export function isSandboxActive() {
84
+ return sandboxAvailable;
85
+ }
86
+ /**
87
+ * Cleanup sandbox resources on shutdown.
88
+ */
89
+ export async function resetSandbox() {
90
+ if (sandboxManager && sandboxInitialized) {
91
+ try {
92
+ await sandboxManager.reset();
93
+ }
94
+ catch {
95
+ // Ignore cleanup errors
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Session lifecycle management.
3
+ * Handles creation, lookup, idle cleanup, and resource limits.
4
+ */
5
+ import { type TerminalOptions } from "./terminal.js";
6
+ import type { Session, SessionInfo, ServerConfig } from "./types.js";
7
+ export declare class SessionManager {
8
+ private config;
9
+ private sessions;
10
+ private idleTimers;
11
+ constructor(config: ServerConfig);
12
+ get sessionCount(): number;
13
+ createSession(options: TerminalOptions & {
14
+ name?: string;
15
+ }): Promise<Session>;
16
+ getSession(id: string): Session;
17
+ listSessions(): SessionInfo[];
18
+ closeSession(id: string, signal?: string): void;
19
+ closeAll(): void;
20
+ touchSession(id: string): void;
21
+ /**
22
+ * Check if an absolute path is within the allowed paths list.
23
+ * Returns true if no allowedPaths are configured (unrestricted).
24
+ */
25
+ isPathAllowed(targetPath: string): boolean;
26
+ private validatePath;
27
+ private validateCommand;
28
+ private resetIdleTimer;
29
+ private clearIdleTimer;
30
+ }
31
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGrE,qBAAa,cAAc;IAIb,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,UAAU,CAAoD;gBAElD,MAAM,EAAE,YAAY;IAExC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAEK,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IA+CnF,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAU/B,YAAY,IAAI,WAAW,EAAE;IAW7B,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAS/C,QAAQ,IAAI,IAAI;IAUhB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAU9B;;;OAGG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAS1C,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,cAAc;CAOvB"}