Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

6 Commits

Repository files navigation

interactive-cli

MCP server that lets AI coding agents interact with interactive CLI processes. Uses a real PTY + xterm headless to render terminal output as clean text — no ANSI escape soup.

Works with Claude Code, Cursor, Windsurf, or any MCP-compatible client.

Why

AI agents can run shell commands, but they choke on anything interactive:

$ eas build --platform ios
✔ Select a build profile › (waiting for input...)

This MCP server bridges that gap — spawn the process, read the screen, send keystrokes.

Quick Start

Claude Code

claude mcp add-json interactive-cli '{"command":"npx","args":["-y","interactive-cli-mcp"]}'

Or add to ~/.claude/settings.json manually:

{
"mcpServers": {
"interactive-cli": {
"command": "npx",
"args": ["-y", "interactive-cli-mcp"]
}
}
}

From Source

git clone https://github.com/ohernandezdev/interactive-cli.git
cd interactive-cli
npm install && npm run build
claude mcp add-json interactive-cli '{"command":"node","args":["/absolute/path/to/interactive-cli/dist/index.js"]}'

Other MCP Clients

Point your client's MCP config at:

command: node
args: ["/path/to/interactive-cli/dist/index.js"]
transport: stdio

Tools

ToolDescriptionRead-only
spawnStart an interactive process in a PTYNo
send_inputType text (appends Enter by default)No
send_keysSend special keys in sequence (arrows, ctrl combos, etc.)No
get_screenCapture current terminal screen, optional regex searchYes
wait_forBlock until a regex pattern appears in outputNo
wait_for_exitBlock until the process exitsNo
resizeChange terminal dimensionsNo
list_sessionsList all active sessionsYes
closeKill process, clean up sessionNo

Typical Flow

sequenceDiagram
participant Agent as AI Agent
participant MCP as interactive-cli
participant PTY as Process (PTY)
Agent->>MCP: spawn("eas build --platform ios")
MCP->>PTY: Start process in PTY
PTY-->>MCP: Initial output
MCP-->>Agent: sessionId + screen
Agent->>MCP: get_screen(sessionId)
MCP-->>Agent: "Select profile: ❯ dev staging prod"
Agent->>MCP: send_keys(["down","down","enter"])
MCP->>PTY: ↓ ↓ ⏎
PTY-->>MCP: "✔ Selected: production"
MCP-->>Agent: updated screen
Agent->>MCP: wait_for("Build complete|error", 600s)
loop Every 1s
MCP->>PTY: check output
end
PTY-->>MCP: "Build complete"
MCP-->>Agent: matched + screen
Agent->>MCP: close(sessionId)
MCP->>PTY: SIGTERM
MCP-->>Agent: final screen + exit code
Loading

spawn

spawn({command: "ssh user@server.com",// full command stringcwd: "/path/to/project",// optional working directoryenv: {"NODE_ENV": "production"},// optional extra env varscols: 120,// terminal width (default 120)rows: 30,// terminal height (default 30)waitMs: 3000,// ms to wait for initial output (default 2000)})

Commands run through your shell ($SHELL or /bin/zsh), so pipes, redirects, and builtins work.

send_input

send_input({sessionId: "s1",text: "yes",// text to typepressEnter: true,// append Enter (default true). false for password fieldswaitMs: 2000,// ms to wait for response (default 2000)})

send_keys

Send one or more keys in sequence with a small delay between each:

send_keys({sessionId: "s1",keys: ["down","down","enter"],// navigate menudelayBetweenMs: 50,// ms between keys (default 50)waitMs: 1500,// ms to wait after last key (default 1500)})

Supported keys:entertabescapespaceupdownleftrightbackspacedeletehomeendpage_uppage_downf1f12ctrl+cctrl+dctrl+zctrl+lctrl+actrl+ectrl+rctrl+wctrl+uctrl+kctrl+pctrl+nyn09

get_screen

get_screen({sessionId: "s1",search: "error|warning",// optional regex to highlight matching lines})// Returns: { screen, cursor: { row, col }, searchResults, stats }

wait_for

wait_for({sessionId: "s1",pattern: "\\$|#|>",// regex to match (case-insensitive)timeoutMs: 30000,// max wait (default 30s)intervalMs: 1000,// check interval (default 1s)})// Returns: { matched: true/false, screen, elapsed }

wait_for_exit

wait_for_exit({sessionId: "s1",timeoutMs: 60000,})// Returns: { alive: false, exitCode: 0, screen }

Resources

Sessions are exposed as MCP resources:

  • interactive-cli://sessions — JSON list of all sessions
  • interactive-cli://sessions/{id}/screen — live screen content

Prompt Templates

Pre-built prompt templates for common flows (appear as slash commands in Claude Code):

  • eas_build — EAS build with credential handling
  • ssh_session — SSH connection with command execution
  • repl_session — Start a REPL (Python, Node, psql, etc.)
  • docker_interactive — Run an interactive Docker container

How It Works

graph LR
A[AI Agent] <-->|MCP Protocol| B[interactive-cli server]
B --> C[Session Manager]
C --> D[node-pty<br/><i>real PTY</i>]
C --> E[xterm headless<br/><i>screen render</i>]
C --> F[Truncation<br/><i>80K limit</i>]
D <--> G[Child Process<br/>ssh, eas, python...]
Loading
  • node-pty spawns a real pseudo-terminal, so the child process thinks it's talking to a human
  • xterm headless maintains a virtual terminal buffer that renders ANSI sequences into a clean 2D text grid
  • Output is truncated at 80K chars (MCP clients like Claude Code cap at 100K) with smart middle-truncation preserving start and end
  • Tool annotations (readOnlyHint, destructiveHint) tell the client which tools are safe to run in parallel and which need permission

Requirements

  • Node.js >= 18
  • macOS or Linux (node-pty uses native PTY)

License

MIT

About

MCP server that lets AI coding agents interact with interactive CLI processes via PTY + xterm headless

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages