interactive-cli

interactive-cli

Enables AI agents to interact with interactive CLI processes via a real PTY, allowing them to send keystrokes, read screen output, and handle interactive prompts.

Category
Visit Server

README

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

Tool Description Read-only
spawn Start an interactive process in a PTY No
send_input Type text (appends Enter by default) No
send_keys Send special keys in sequence (arrows, ctrl combos, etc.) No
get_screen Capture current terminal screen, optional regex search Yes
wait_for Block until a regex pattern appears in output No
wait_for_exit Block until the process exits No
resize Change terminal dimensions No
list_sessions List all active sessions Yes
close Kill process, clean up session No

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

spawn

spawn({
  command: "ssh user@server.com",   // full command string
  cwd: "/path/to/project",          // optional working directory
  env: { "NODE_ENV": "production" }, // optional extra env vars
  cols: 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 type
  pressEnter: true,      // append Enter (default true). false for password fields
  waitMs: 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 menu
  delayBetweenMs: 50,               // ms between keys (default 50)
  waitMs: 1500,                     // ms to wait after last key (default 1500)
})

Supported keys: enter tab escape space up down left right backspace delete home end page_up page_down f1f12 ctrl+c ctrl+d ctrl+z ctrl+l ctrl+a ctrl+e ctrl+r ctrl+w ctrl+u ctrl+k ctrl+p ctrl+n y n 09

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...]
  • 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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured