使用说明
MCP TUI Test
Like Playwright, but for Terminal User Interfaces
An MCP (Model Context Protocol) server that enables AI assistants to test Terminal User Interface (TUI) applications. This server provides tools to launch, interact with, and verify TUI applications programmatically.
Features
- Dual Testing Modes: Choose between stream mode (for CLI tools) or buffer mode (for full TUIs with position awareness)
- Launch TUI Applications: Start any terminal-based application with configurable dimensions
- Send Keyboard Input: Simulate user typing, special keys, and control combinations
- Capture Screen Output: Read and analyze the current terminal display
- Position-Based Testing: Verify text at specific screen coordinates (buffer mode)
- Cursor Tracking: Monitor cursor position in real-time (buffer mode)
- Wait for Text: Asynchronously wait for specific content to appear
- Assertions: Verify that expected content is present in the output
- Session Management: Run multiple TUI applications simultaneously
Testing Modes
Stream Mode (Default)
- Best for: CLI tools, command-line applications, simple interactive programs
- Uses: pexpect for stream-based testing
- Features: Text matching, pattern waiting, output capture
- Example use cases: git, npm, grep, interactive shell scripts
Buffer Mode
- Best for: Full TUI applications, ncurses apps, dialog boxes, menus
- Uses: pexpect + pyte for screen buffer emulation
- Features: All stream features PLUS position-based assertions, cursor tracking, region extraction
- Example use cases: htop, vim, dialog, interactive menus
When to use which mode:
- Use stream mode for applications that output text sequentially
- Use buffer mode for applications that draw complex UIs with cursor movement
Installation
Prerequisites
- Python 3.10 or higher
- uv
Install
Once published to PyPI, no install is needed — run it straight from uvx:
uvx mcp-tui-test
For development:
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
Go implementation
A sibling Go implementation lives in go/ — the same tool contract
(same tool names, same structured result shapes, same tui://{session_id}/screen
resource), as a single static binary with zero runtime dependencies:
go install github.com/GeorgePearse/mcp-tui-test/go/cmd/mcp-tui-test@latest
{
"mcpServers": {
"tui-test": { "command": "mcp-tui-test" }
}
}
Built on the official Go MCP SDK,
creack/pty, and vt10x for buffer-mode screen emulation. The Python package
remains the home of the pytest plugin; the two share the tool schema, so clients
can't tell them apart.
Structured results
Every tool returns structured content (with an output schema), not prose: a
success flag plus typed fields (screen, outcome, passed, row/col,
screen_excerpt on failed assertions, error when something broke). Agents and
scripts branch on fields instead of parsing ✓/✗ strings.
The current screen is also exposed as an MCP resource at
tui://{session_id}/screen.
For harness-side loops, result handling, and session ordering, see Composing TUI tests in a coding harness.
Session limits & cleanup
Sessions are capped and reaped automatically:
MCP_TUI_MAX_SESSIONS(default 8) — launching past the cap returns a structured error.MCP_TUI_SESSION_TTL_S(default 900) — sessions older than this are closed on the next access.- Dead processes are reaped on every registry access and reported by
list_sessions. - All sessions are force-closed (SIGKILL escalation) at interpreter exit — no zombies.
pytest plugin
The same engine drives deterministic CI tests with no LLM in the loop. Installing
the package registers a tui fixture:
def test_app_header(tui):
s = tui.launch("my-app --demo", mode="buffer", dimensions=(120, 40))
s.wait_until_contains("Dashboard", timeout=10)
s.assert_at("Dashboard", 0, 2)
s.send("q")
TuiHandle offers send, send_ctrl, expect, assert_contains, assert_at,
wait_until_contains, screen, line, and cursor; failures raise
AssertionError with the current screen attached. Sessions are closed at test
teardown, pass or fail.
Usage
Running the MCP Server
python server.py
Or if installed as a package:
mcp-tui-test
Configure in Claude Desktop
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"tui-test": {
"command": "uvx",
"args": ["mcp-tui-test"]
}
}
}
(A local checkout also works: "command": "python", "args": ["/path/to/mcp-tui-test/server.py"].)
## Available Tools
### `launch_tui`
Launch a TUI application for testing.
**Parameters:**
- `command` (required): The command to launch the TUI application
- `session_id` (optional): Unique identifier for this session (default: "default")
- `timeout` (optional): Command timeout in seconds (default: 30)
- `dimensions` (optional): Terminal dimensions as WIDTHxHEIGHT (default: "80x24")
- `mode` (optional): Testing mode - "stream" or "buffer" (default: "stream")
**Examples:**
```python
# Stream mode for CLI tools
launch_tui(command="python example_tui_app.py", session_id="test1")
# Buffer mode for full TUI applications
launch_tui(command="htop", session_id="test2", mode="buffer", dimensions="120x40")
send_keys
Send keyboard input to a TUI application.
Parameters:
keys(required): Keys to send. Use\nfor Enter,\tfor Tab,\x1bfor Escapesession_id(optional): Session identifier (default: "default")delay(optional): Delay in seconds after sending keys (default: 0.1)
Example:
send_keys(keys="1\n", session_id="test1")
send_ctrl
Send a Ctrl+Key combination to the TUI application.
Parameters:
key(required): The key to combine with Ctrl (e.g., 'c', 'd', 'z')session_id(optional): Session identifier (default: "default")
Example:
send_ctrl(key="c", session_id="test1")
capture_screen
Capture the current screen output of a TUI application.
Parameters:
session_id(optional): Session identifier (default: "default")include_ansi(optional): Whether to include ANSI escape codes in stream mode (default: False)use_buffer(optional): Force buffer/stream mode. Auto-detects if None (default: None)
Examples:
# Auto-detect mode based on session
capture_screen(session_id="test1")
# Force buffer mode capture
capture_screen(session_id="test1", use_buffer=True)
expect_text
Wait for specific text to appear in the TUI output.
Parameters:
pattern(required): Text or regex pattern to wait forsession_id(optional): Session identifier (default: "default")timeout(optional): Maximum time to wait in seconds (default: 10)
Example:
expect_text(pattern="Welcome", session_id="test1", timeout=5)
assert_contains
Assert that the current screen contains specific text.
Parameters:
text(required): Text to search for in the current screensession_id(optional): Session identifier (default: "default")use_buffer(optional): Check buffer/stream mode. Auto-detects if None (default: None)
Example:
assert_contains(text="Counter value: 1", session_id="test1")
assert_at_position (Buffer Mode Only)
Assert that specific text appears at a screen position.
Parameters:
text(required): Text to verify at the positionrow(required): Row number (0-indexed)col(required): Column number (0-indexed)session_id(optional): Session identifier (default: "default")
Example:
# Verify "Error" appears at row 5, column 10
assert_at_position(text="Error", row=5, col=10, session_id="test1")
get_cursor_position (Buffer Mode Only)
Get the current cursor position.
Parameters:
session_id(optional): Session identifier (default: "default")
Example:
get_cursor_position(session_id="test1")
# Returns: "Cursor position (session: test1): row 10, column 25"
get_screen_region (Buffer Mode Only)
Extract a rectangular region of the screen.
Parameters:
row_start(required): Starting row (0-indexed, inclusive)row_end(required): Ending row (0-indexed, exclusive)col_start(optional): Starting column (0-indexed, inclusive, default: 0)col_end(optional): Ending column (0-indexed, exclusive, default: end of line)session_id(optional): Session identifier (default: "default")
Example:
# Extract rows 5-10, full width
get_screen_region(row_start=5, row_end=10, session_id="test1")
# Extract rows 5-10, columns 20-60
get_screen_region(row_start=5, row_end=10, col_start=20, col_end=60, session_id="test1")
get_line (Buffer Mode Only)
Get a specific line from the screen buffer.
Parameters:
row(required): Row number (0-indexed)session_id(optional): Session identifier (default: "default")
Example:
get_line(row=3, session_id="test1")
# Returns: "Line 3 (session: test1): [line content]"
close_session
Close a TUI testing session.
Parameters:
session_id(optional): Session identifier (default: "default")
Example:
close_session(session_id="test1")
list_sessions
List all active TUI testing sessions.
Example:
list_sessions()
Example Test Scenario
Here's how you might use this MCP to test a TUI application:
-
Launch the application:
launch_tui(command="python example_tui_app.py") -
Wait for it to load:
expect_text(pattern="Welcome to the Example TUI Application") -
Interact with it:
send_keys(keys="1\n") -
Verify output:
assert_contains(text="Hello, TUI Tester!") -
Clean up:
close_session()
Testing the Example App
This repository includes an example TUI application (example_tui_app.py) that you can use to test the MCP server.
Run it directly:
python example_tui_app.py
Or test it through the MCP:
launch_tui(command="python example_tui_app.py")
send_keys(keys="1\n")
capture_screen()
Use Cases
- Automated Testing: Verify TUI applications behave correctly
- Integration Testing: Test command-line tools and interactive CLIs
- Documentation: Generate screenshots and examples from TUI apps
- Debugging: Inspect the state of TUI applications during development
- CI/CD: Add TUI testing to your continuous integration pipeline
Technical Details
This MCP server uses:
- FastMCP: For the MCP server implementation
- pexpect: For spawning and controlling terminal applications
- pyte: For terminal emulation and screen buffer management (buffer mode)
- ScreenSession wrapper: Combines pexpect and pyte for hybrid testing
Architecture
- Stream Mode: pexpect directly captures output stream
- Buffer Mode: pexpect output → pyte terminal emulator → screen buffer
- Auto-detection: Tools automatically use appropriate mode based on session
Limitations
- Currently designed for Unix-like systems (Linux, macOS)
- Windows support may require modifications (consider using
winptyor similar) - Mouse support in TUIs is not currently available
- Buffer mode requires slightly more memory for screen emulation
- Position-based assertions only work in buffer mode
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License - see LICENSE file for details
Related tools
docs/landscape.md surveys the other TUI-testing tools, what each is built on, the core ideas in each, and which of those ideas this project has or could adopt. The tools covered:
- microsoft/tui-test — Rust engine with Alacritty, Ghostty, Rio and xterm.js backends; Playwright-style locators; CLI plus Rust, Python, JS and Go bindings
- antithesishq/bombadil — property-based exploration of web and terminal UIs on
portable-ptyandlibghostty-vt, with temporal properties and trace shrinking - montanaflynn/headless-terminal (
ht) — Go daemon onlibghostty-vt; composable--wait-*flags onsend; agent skill - beorn/termless — TypeScript; twelve emulator backends with a conformance corpus; recordings replayed through the same assertions; MCP server
- vyncint/termlens — Rust; predicate waits, DEC 2026 frame-complete snapshots, grid masking, answers terminal capability queries
- mwunsch/termscope — Zig single binary on
libghostty-vt; JSON-lines session protocol - fcoury/termwright — Rust; daemon over a Unix socket, YAML step files, box detection
- charmbracelet/vhs — tape DSL to GIF/MP4 plus
.asciigolden files - charmbracelet/x
exp/teatest, ratatuiTestBackend, Textual Pilot and pytest-textual-snapshot — in-process framework test hooks with golden or SVG snapshots - testty — Rust; semantic recipes over styles, scenarios compiled to VHS tapes
- hegner123/tui-test-ghost and mjpowersjr/vterm-mcp — MCP servers on
libghostty-vt, the closest in shape to this project; tui-test-ghost records tool calls to JSONL and replays them as tests - libghostty-vt and go-libghostty — the headless VT engine most of the above sit on
- pexpect, pyte, libvterm — PTY stream matching and VT emulation; this project's Python implementation is pexpect plus pyte
Also: Playwright (the inspiration for this project) and the MCP specification.
Author
Created for testing TUI applications with AI assistance.
Documentation development
The site uses Material for MkDocs, matching VisionChain and Bayesian Filters.
uv venv .venv-docs
uv pip install --python .venv-docs/bin/python -r docs-requirements.txt
.venv-docs/bin/mkdocs serve
.venv-docs/bin/mkdocs build --strict
For a build you can open directly from disk with local search, use
MKDOCS_OFFLINE=true .venv-docs/bin/mkdocs build --strict --site-dir /tmp/mcp-tui-test-offline.
Offline builds use .html page URLs; normal builds retain the published directory URLs.