# pty-mcp

A lightweight PTY runner for MCP (Model Context Protocol).

`pty-mcp` provides terminal session tools over MCP so clients can spawn commands in a pseudo-terminal, read interactive output, send input, resize terminal windows, and manage process lifecycle safely.

## Features

- Spawn shell commands in a real PTY
- Read incremental output from a ring buffer
- Wait for pattern matching (`read_until`)
- Wait for any pattern (`read_until_any`)
- Send interactive input (`write`)
- Send input and wait for prompt (`prompt`)
- Resize terminal (`cols` / `rows`)
- Process control (`status`, `wait`, `signal`, `close`)
- Stream split reads (`read_stdout`, `read_stderr`)
- Read with offset (`read_at`)
- Session tags (`tag`, `owner`)
- Dynamic defaults (`set_default_cwd`)
- Runtime limits (`set_limits`)
- Metrics and health (`metrics`, `health`)

## Requirements

- Python 3.10+

## Installation

```bash
pip install pty-mcp
```

## CLI Entrypoint

After installation, the package exposes:

```bash
pty-mcp
```

This starts the MCP server over stdio.

## MCP Tools

- `pty_spawn`
- `pty_read`
- `pty_read_stdout`
- `pty_read_stderr`
- `pty_read_at`
- `pty_read_until`
- `pty_read_until_any`
- `pty_prompt`
- `pty_write`
- `pty_resize`
- `pty_close`
- `pty_close_all`
- `pty_status`
- `pty_wait`
- `pty_signal`
- `pty_list`
- `set_default_cwd`
- `get_default_cwd`
- `set_limits`
- `get_limits`
- `pty_metrics`
- `pty_health`

## New Parameters

### `pty_spawn`

- `cwd` — working directory
- `separate_streams` — split stdout/stderr into separate buffers
- `tag`, `owner` — session labels for filtering
- `scope` — `read-only` or `read-write`
- `max_output_bytes` — ring buffer cap
- `spawn_timeout_sec` — session runtime cap
- `rate_limit_bps` — output rate limit
- `input_rate_bps` — input rate limit
- `read_timeout_ms` — default read timeout per session
- `env` — per-session environment overrides

### `pty_read` / `pty_read_stdout` / `pty_read_stderr`

- `format` — `json` or `text` (default)

## Examples

### Set default cwd

```json
{"name":"set_default_cwd","arguments":{"cwd":"/root/aa"}}
```

### Spawn with stream split

```json
{"name":"pty_spawn","arguments":{"command":"ls","separate_streams":true}}
```

### Read stdout only

```json
{"name":"pty_read_stdout","arguments":{"session_id":"..."}}
```

### Wait for any prompt

```json
{"name":"pty_read_until_any","arguments":{"session_id":"...","patterns":["OK","ERROR"]}}
```

### Prompt helper

```json
{"name":"pty_prompt","arguments":{"session_id":"...","data":"y\n","patterns":["done","error"]}}
```

## Notes

- PTY sessions are in-memory and have idle timeout cleanup.
- The server is intended for local trusted environments.
- `separate_streams=true` makes stdout/stderr non-tty (some commands may change output).
- If `command` is an absolute path, cwd is inferred from its directory.

## License

MIT
