MCP server that gives AI agents eyes on your terminal — PNG screenshots, visual diffs, GIF recording, and full keyboard/text interaction
can-see demonstrates solid tool design with 18 well-named, action-verb tools (launch, screenshot, send_keys, close). All tools have descriptions (avg ~100 chars) and explicit Zod schemas with typed parameters. Error handling returns structured responses with isError flags. However, output schemas are not formally documented, responses are inferred from code (image/text content arrays). Parameter descriptions are present but terse (avg ~50 chars), lacking guidance on constraints, ranges, or when to use related tools. No tool annotations (readOnlyHint/destructiveHint). Missing idempotency guidance for retry-heavy workflows. Composition is strong: tools chain well (launch→screenshot→send_keys→close), and session IDs flow correctly between calls.
Snapshot current terminal state for later diff comparison (screenshot also auto-captures a baseline)
Close a terminal session and clean up resources. IMPORTANT: Always close sessions when done.
Compare current terminal state against the baseline, return PNG with changed cells highlighted in red
Query character, colors, and text attributes at a specific cell or range of cells
Launch a CLI app in a virtual terminal. IMPORTANT: You MUST call 'close' when done with this session.
List all active terminal sessions
Read text that scrolled above the visible viewport (scrollback buffer)
Output schemas not formally documented. Tool responses return {content: [{type, data/text}]} but this structure is inferred from code, not declared in tool definitions. LLMs cannot plan downstream calls without knowing return field names and types.
Parameter descriptions lack constraint guidance. E.g., 'cols' and 'rows' have no min/max bounds; 'timeoutMs' parameters lack guidance on valid ranges; 'color' in wait_for_color lacks format specification (hex vs ANSI name). LLMs may pass invalid values.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). 'launch' and 'send_keys' are destructive/stateful; 'screenshot' and 'read_text' are read-only. Annotations help LLMs reason about retry safety and side effects.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Read text from a row or range of rows in the viewport
Capture the terminal as a PNG image
Capture a specific rectangular area of the visible terminal as a PNG image
Find text in the viewport and capture the surrounding area as a PNG. Searches visible viewport only (single-line match, returns first match top-to-bottom).
Send keyboard input to the terminal (special keys like Enter, Tab, Escape, arrow keys, Ctrl+X, etc.)
Send raw text input to the terminal (no special key interpretation)
Start recording terminal output as an animated GIF
Stop recording and return the GIF (inline if small, or file path if large)
Block until a specific foreground or background color appears in the viewport or timeout
Block until terminal output stops for a duration or timeout
Block until text appears in the viewport or timeout
Error messages are generic. Code returns {isError: true, content: [{type: 'text', text: message}]} but does not categorize errors as retryable, user-fixable, or fatal. LLMs cannot decide whether to retry, ask user, or abort.
No guidance on tool dependencies or sequencing. Instructions mention workflow but do not document that 'screenshot' requires a prior 'launch' call, or that 'close' must follow 'launch'. Implicit dependencies invite misuse.