AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP unreviewed MIT Self-run

Terminal Mcp

mcp-mkpvishnu-terminal-mcp · by mkpvishnu

MCP server for interactive terminal sessions (SSH, REPLs, database CLIs)

No reviews yet
0 installs
6 views
0.0% view→install

Install

$ agentstack add mcp-mkpvishnu-terminal-mcp

Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

2 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Destructive filesystem operation.
  • high Pipes remote content directly into a shell (remote code execution).

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Reliability & compatibility

Not yet reviewed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Terminal Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

MCP server for interactive terminal sessions — SSH, REPLs, database CLIs, and TUI apps.


Why This Exists

If you've hit any of these limitations with Claude Code, terminal-mcp solves them:

  • "Claude Code can't handle interactive sessions" — The built-in Bash tool runs each command in a fresh subprocess. No persistence, no back-and-forth.
  • "SSH not supported in Claude Code" — You can't SSH into a server and run multiple commands across an active connection.
  • "Claude Code Bash tool doesn't support REPLs" — Python, Node, Ruby, and other interpreters need a persistent session for multi-line interaction.
  • "How to use psql / mysql / redis-cli with Claude Code" — Database CLIs require a live connection that survives across tool calls.
  • "Interactive terminal not working in Claude Code" — TUI apps (htop, vim, ncdu, fzf) need a real PTY with special key support.
  • "Claude Code can't send arrow keys or Tab" — The Bash tool has no concept of terminal escape sequences.

terminal-mcp fills this gap by exposing MCP tools that create and manage real PTY sessions. Each session runs as a persistent child process; you send input, special keys, and control characters and read output across multiple tool calls for as long as the session lives.

Features

  • Persistent PTY sessions — real terminal sessions that survive across tool calls
  • Send + read in one callsession_interact combines send and read, halving LLM round trips
  • Regex-triggered readssession_wait_for blocks until a pattern matches in output — no more guessing timeouts
  • Dangerous command gate — detects risky commands (rm -rf, DROP TABLE, curl|sh, etc.) and requires confirmation
  • OSC 133 shell integration — auto-detects command boundaries and exit codes from modern shells
  • Special key support — arrow keys, Tab, Escape, function keys (F1–F12), Home/End, Page Up/Down
  • Control characters — Ctrl-C, Ctrl-D, Ctrl-Z, Ctrl-L, and telnet escape
  • Four read modes — stream (waits for output to settle), snapshot (pyte screen buffer), auto (auto-detects TUI apps), and diff (returns only changed screen lines)
  • Auto TUI detection — automatically detects alternate screen buffer (htop, vim, etc.) and switches to snapshot mode
  • Output diff mode — returns only changed lines since last read, minimizing tokens for TUI monitoring
  • Intelligent truncation — four truncation modes: tail (default), head_tail (preserves beginning and end), tail_only (for build logs), none
  • ANSI stripping — optional removal of escape sequences for clean text output
  • Idle cleanup — automatic session cleanup after configurable timeout
  • Session management — list, label, and manage multiple concurrent sessions
  • Dynamic resize — resize terminal dimensions on the fly with SIGWINCH support
  • Secret input — send passwords without logging them
  • Scrollback history — access terminal scrollback buffer beyond the visible screen
  • One-shot execution — run a single command without manual session management
  • Smart output truncation — four truncation strategies (tail, head_tail, tail_only, none) to prevent context overflow while preserving the most useful output
  • Env var configuration — configure all settings via TERMINAL_MCP_* environment variables
  • PyPI distribution — install directly with pip install terminal-mcp

Supported Clients

| Client | Status | Install | |--------|--------|---------| | Claude Code (CLI) | ✅ Supported | ~/.claude.json or .mcp.json | | Claude Desktop | ✅ Supported | [One-click install](#register-with-claude-desktop) | | VS Code (Copilot Chat) | ✅ Supported | One-click install or .vscode/mcp.json | | Cursor | ✅ Supported | [One-click install](cursor://anysphere.cursor-mcp/install?name=terminal-mcp&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJ0ZXJtaW5hbC1tY3AiXX0=) or Settings → MCP | | Windsurf | ✅ Supported | ~/.codeium/windsurf/mcp_config.json |

Quickstart

Install

Recommended — no install needed:

uvx terminal-mcp

Or install via pip:

pip install terminal-mcp

Or from source:

git clone https://github.com/mkpvishnu/terminal-mcp.git
cd terminal-mcp
pip install -e ".[dev]"

Register with Claude Code

Add to ~/.claude.json (or project .mcp.json):

{
  "mcpServers": {
    "terminal": {
      "command": "uvx",
      "args": ["terminal-mcp"]
    }
  }
}

Register with Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "terminal": {
      "command": "uvx",
      "args": ["terminal-mcp"]
    }
  }
}

Register with VS Code / Cursor

Click the one-click install badge above, or add to .vscode/mcp.json:

{
  "servers": {
    "terminal-mcp": {
      "command": "uvx",
      "args": ["terminal-mcp"]
    }
  }
}

Verify it works

session_exec  exec="echo hello from terminal-mcp"

Demo

SSH session to a remote server

session_create  command="ssh user@myserver.example.com"  label="prod-ssh"
session_read    session_id="a1b2c3d4"  timeout=5.0
session_send    session_id="a1b2c3d4"  password="mypassword"
session_send    session_id="a1b2c3d4"  input="df -h"
session_read    session_id="a1b2c3d4"
session_close   session_id="a1b2c3d4"

Python REPL

session_create  command="python3"  label="repl"
session_read    session_id="e5f6g7h8"
session_send    session_id="e5f6g7h8"  input="import math"
session_send    session_id="e5f6g7h8"  input="print(math.sqrt(144))"
session_read    session_id="e5f6g7h8"
session_close   session_id="e5f6g7h8"

TUI navigation with special keys

session_create  command="python3 -m openclaw configure"  label="openclaw"
session_read    session_id="x1y2z3w4"  timeout=3.0
session_send    session_id="x1y2z3w4"  key="down"
session_send    session_id="x1y2z3w4"  key="down"
session_send    session_id="x1y2z3w4"  key="enter"
session_read    session_id="x1y2z3w4"
session_send    session_id="x1y2z3w4"  key="tab"
session_read    session_id="x1y2z3w4"
session_close   session_id="x1y2z3w4"

Auto TUI detection and diff mode

session_create   command="htop"  label="monitor"
session_read     session_id="a1b2c3d4"
→ auto-detects TUI, returns snapshot with mode_used="snapshot", tui_active=true

session_read     session_id="a1b2c3d4"  mode="diff"
→ returns only changed lines since last read

session_read     session_id="a1b2c3d4"  mode="diff"
→ returns only lines that changed, minimizing tokens

session_close    session_id="a1b2c3d4"

One-shot command execution

session_exec  exec="ls -la /tmp"
session_exec  exec="python3 -c 'print(42)'"  command="bash"  timeout=10.0

Send + read in one call (session_interact)

session_create   command="bash"  label="demo"
session_interact session_id="a1b2c3d4"  input="ls -la"  wait_for="\\$\\s*$"  timeout=5.0
session_interact session_id="a1b2c3d4"  input="whoami"  wait_for="\\$"
session_close    session_id="a1b2c3d4"

Wait for specific output pattern

session_create   command="bash"  label="build"
session_send     session_id="a1b2c3d4"  input="npm run build"
session_wait_for session_id="a1b2c3d4"  pattern="Build complete|ERROR"  timeout=60.0
session_close    session_id="a1b2c3d4"

Dangerous command confirmation

session_send    session_id="a1b2c3d4"  input="rm -rf /tmp/old"
→ returns: requires_confirmation=true, reason="Matched dangerous pattern: ..."

session_send    session_id="a1b2c3d4"  input="rm -rf /tmp/old"  confirmed=true
→ executes the command

Sending Ctrl-C to interrupt

session_send    session_id="a1b2c3d4"  control_char="c"
session_read    session_id="a1b2c3d4"

Tool Reference

session_create

Spawn a persistent PTY terminal session.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | command | string | Yes | — | Shell command to run (e.g. bash, python3, ssh user@host) | | label | string | No | command name | Human-readable label | | rows | integer | No | 24 | Terminal height | | cols | integer | No | 80 | Terminal width | | idle_timeout | integer | No | 1800 | Seconds before auto-close | | enable_snapshot | boolean | No | true | Deprecated: snapshot is now always enabled | | scrollback_lines | integer | No | 1000 | Scrollback history lines |

Returns: session_id, label, pid, created_at, snapshot_available

session_send

Send input text, a control character, or a special key to an active session. Only one of input, control_char, key, or password may be provided per call.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | string | Yes | — | Session ID from session_create | | input | string | No | — | Text to send | | press_enter | boolean | No | true | Append carriage return after input | | control_char | string | No | — | Control character: c d z l ] | | key | string | No | — | Special key (see table below) | | password | string | No | — | Password or secret (not logged) | | confirmed | boolean | No | false | Bypass dangerous command gate |

Returns: bytes_sent — or requires_confirmation, reason if the command matches a dangerous pattern

Supported special keys

| Key | Description | Key | Description | |-----|-------------|-----|-------------| | up | Arrow up | f1f12 | Function keys | | down | Arrow down | home | Home | | left | Arrow left | end | End | | right | Arrow right | page-up | Page Up | | tab | Tab | page-down | Page Down | | shift-tab | Shift+Tab | insert | Insert | | escape | Escape | delete | Delete | | enter | Enter | backspace | Backspace |

Supported control characters

| Char | Signal | Description | |------|--------|-------------| | c | SIGINT | Interrupt (Ctrl-C) | | d | EOF | End of file / logout (Ctrl-D) | | z | SIGTSTP | Suspend (Ctrl-Z) | | l | — | Clear screen (Ctrl-L) | | ] | — | Telnet escape |

session_resize

Resize the terminal window of an active session.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | string | Yes | — | Session ID | | rows | integer | Yes | — | New terminal height | | cols | integer | Yes | — | New terminal width |

Returns: rows, cols

session_read

Read output from a session.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | string | Yes | — | Session ID | | mode | string | No | auto | auto, stream, snapshot, or diff | | timeout | number | No | 2.0 | Settle timeout in seconds (stream/auto mode) | | strip_ansi | boolean | No | true | Strip ANSI escape sequences | | scrollback | integer | No | — | Lines of scrollback history (snapshot mode) | | truncation | string | No | config default | Truncation mode: tail, head_tail, tail_only, none |

Returns: output, bytes_read, prompt_detected, is_alive, truncated, tui_active, snapshot_available, mode_used, changed_lines (diff mode), is_first_read (diff mode), total_lines (scrollback), osc133, command_state, exit_code, command_complete (shell integration)

session_close

Terminate a session gracefully (EOF → SIGHUP → SIGKILL).

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | session_id | string | Yes | Session ID to close |

Returns: exit_status — or already_closed: true if the session was already terminated (idempotent)

session_exec

Execute a command in a temporary session and return output. The session is automatically cleaned up.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | exec | string | Yes | — | Command to execute | | command | string | No | bash | Shell to use | | timeout | number | No | 5.0 | Seconds to wait for output | | rows | integer | No | 24 | Terminal height | | cols | integer | No | 80 | Terminal width | | truncation | string | No | config default | Truncation mode: tail, head_tail, tail_only, none |

Returns: output, bytes_read, session_id, truncated

session_interact

Send input and read output in a single call. Combines session_send + session_read to halve round trips. Optionally waits for a regex pattern in the output.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | string | Yes | — | Session ID | | input | string | No | — | Text to send | | press_enter | boolean | No | true | Append carriage return after input | | control_char | string | No | — | Control character: c d z l ] | | key | string | No | — | Special key (see session_send) | | password | string | No | — | Password or secret (not logged) | | wait_for | string | No | — | Regex pattern to wait for in output | | timeout | number | No | 5.0 | Seconds to wait for output | | strip_ansi | boolean | No | true | Strip ANSI escape sequences | | confirmed | boolean | No | false | Bypass dangerous command gate | | read_mode | string | No | stream | Read mode: auto, stream, snapshot, diff | | truncation | string | No | config default | Truncation mode: tail, head_tail, tail_only, none |

Returns: output, bytes_read, bytes_sent, matched (when wait_for used), prompt_detected, is_alive, truncated, tui_active, mode_used, snapshot_available

sessionwaitfor

Read output from a session until a regex pattern matches or timeout expires. Use this instead of session_read when you know what output to expect.

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | session_id | string | Yes | — | Session ID | | pattern | string | Yes | — | Regex pattern to wait for in output | | timeout | number | No | 30.0 | Max seconds to wait | | strip_ansi | boolean | No | true | Strip ANSI escape sequences | | truncation | string | No | config default | Truncation mode: tail, head_tail, tail_only, none |

Returns: output, bytes_read, matched, prompt_detected, is_alive, truncated

session_list

List all active sessions with their status and idle time.

Returns: sessions (array with tui_active, snapshot_available per session), count

Architecture

flowchart LR
    Client[AI Client] -->|MCP JSON-RPC| Server[terminal-mcp]
    Server --> SM[Session Manager]
    SM --> S1[PTY 1: bash]
    SM --> S2[PTY 2: python3]
    SM --> S3[PTY 3: ssh user@host]
    S1 & S2 & S3 -.->|PTY output| Reader[Reader Thread]
    Reader -.->|buffer| Server
stateDiagram-v2
    [*] --> Active : session_create
    state Active {
        Idle --> Sending : session_send
        Sending --> Idle
        Idle --> Reading : session_read
        Reading --> Idle
        Idle --> Resizing : session_resize
        Resizing --> Idle
    }
    Active --> [*] : session_close
    Active --> [*] : idle_timeout

Each session is backed by a real PTY allocated via pexpect.spawn. The design has four main parts:

Background reader thread. A daemon thread continuously reads from the PTY file descriptor in 4096-byte chunks and appends bytes to an in-memory buffer. The thread is lock-protected and dies automatically when the child process exits.

Output settling (stream mode). session_read in stream mode polls the buffer until no new bytes have arrived for timeout seconds (defaul

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.