MCP Directory

PiloTY

Persistent, interactive PTY terminal for AI agents over MCP — SSH, REPLs, password prompts, long-running jobs.

Unverified
stdio (local)
No auth
Python

Add to your client

Copy the config for your MCP client and paste it into its config file.

Install / run
codex mcp add piloty -- uvx --from git+https://github.com/yiwenlu66/PiloTY.git piloty

Paste into ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "piloty": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/yiwenlu66/PiloTY.git",
        "piloty"
      ]
    }
  }
}

Requires `uv` (the Python package runner). Install it from https://docs.astral.sh/uv/ if `uvx` is not found.

Step-by-step guides: Add to Claude Desktop · Add to Cursor · Add to Windsurf

Before you start

  • uv / uvx (Astral) to launch the server via `uvx`, or a local clone run with `uv --directory`
  • An MCP client that launches servers over stdio (e.g. Codex CLI, Claude)
  • Python (server is implemented in Python)

About PiloTY

PiloTY is an MCP server that gives an AI agent a persistent, interactive terminal session. One session is one real interactive terminal that stays alive across tool calls, preserving cwd, environment variables, the foreground process, remote SSH connections, and REPL/debugger state. It is meant to be launched by an MCP client over stdio and is addressed by reusing a session_id string. PiloTY keeps two representations of terminal activity — an incremental text output stream and a rendered screen/scrollback view — and exposes tools to send input (lines, raw text, control characters, signals, passwords) and to wait on output by time, regex, or shell prompt.

Tools & capabilities (10)

send_line

Submit a newline-terminated command to the terminal session (drain-based).

send_text

Send raw bytes to the terminal without an appended newline (drain-based).

send_control

Send a control character (e.g. interrupt) to the foreground process (drain-based).

send_signal

Send a signal to the session's process (drain-based).

send_password

Enter a secret for a password prompt; suppresses transcript logging and terminal echo for that send (drain-based).

wait_for_output

Wait for new PTY output for a wall-clock budget; can return partial output with outcome=deadline_exceeded if output started but never went quiet.

wait_for_regex

Wait for content matching a regex; first checks already-rendered scrollback, then waits on new PTY bytes.

wait_for_shell_prompt

Wait for the shell prompt to return (e.g. after `ssh` or other login flows), consuming and returning the PTY output it waits on.

snapshot_screen

Passively capture the current rendered terminal screen (what a human would see); does not ingest fresh PTY bytes.

snapshot_scrollback

Passively capture the rendered scrollback buffer; does not ingest fresh PTY bytes.

When to use it

  • Start long-running commands (builds, installs, migrations, test suites) once and check their output later
  • Monitor live logs across tool calls with `tail -f`, `journalctl -f`, or `kubectl logs -f`
  • Keep a REPL or debugger (`python`, `ipython`, `pdb`) open while the agent reads code and tries ideas
  • Handle interactive password prompts for `sudo`, SSH passwords, and key passphrases
  • Maintain a remote SSH login session alive across tool calls and run remote commands in the same shell
  • Drive terminal UIs such as `less`, `man`, `top`, and `vim` using screen snapshots when layout matters

Security notes

PiloTY exposes unrestricted terminal access — treat it like giving the agent your keyboard. `send_password()` suppresses transcript logging and terminal echo for that send, but does not prevent other prompts or programs from echoing secrets later. Each server instance writes session logs (raw PTY bytes, inputs, captured output) under `~/.piloty/`, with server logs defaulting to `/tmp/piloty.log`.

PiloTY FAQ

How does state persist between tool calls?

Each session is one real interactive terminal addressed by a `session_id` string. Reusing the same id keeps cwd, environment variables, the foreground process, remote SSH connections, and REPL/debugger state alive. Since MCP has no standard 'client cwd' field, the first step is always to create a session with an explicit working directory.

What is the difference between `outcome` and `terminal_state`?

`outcome` is the call result (success, deadline_exceeded, eof, error, invalid_session, terminated). `terminal_state` is a best-effort classification of the rendered terminal after the call (running, ready, password, confirm, repl, editor, pager, unknown). Terminal-state detection can be wrong, especially for custom prompts and cursor-heavy TUIs.

Is it safe to give an agent this kind of access?

PiloTY exposes unrestricted terminal access — treat it like giving the agent your keyboard. `send_password` suppresses logging/echo for that send but cannot prevent other programs from echoing secrets later. Session transcripts are written under `~/.piloty/`.

How do I install it without a public Git fetch?

You can use an SSH-based fetch (`codex mcp add piloty -- uvx --from git+ssh://git@github.com/yiwenlu66/PiloTY.git piloty`) or run a local clone (`codex mcp add piloty -- uv --directory /path/to/PiloTY run piloty`).

Alternatives to PiloTY

Compare all alternatives →

Microsoft's official browser-automation MCP using Playwright's accessibility tree (no vision model).

Featured
Verified
stdio (local)
No auth
TypeScript
12 tools
Updated 21 days agoRepo

Up-to-date, version-specific library documentation injected into your coding agent.

Verified
stdio (local)
API key
TypeScript
2 tools
Updated 25 days agoRepo

Code intelligence engine that indexes repos into a persistent knowledge graph for AI coding agents.

Unverified
stdio (local)
No auth
C
14 tools
Updated 11 hours agoRepo