Skip to main content
Glama

terminal-use

An MCP server that lets an AI agent use a real terminal the way a person does: type, press keys, click, read the screen, take a screenshot.

An agent opening vim, pasting a program, saving it, running it, and taking a screenshot — each step labelled with the tool call that made it

Every frame above was drawn by terminal-use's own screenshot renderer; the caption on each is the tool call that produced it.

Most agent shell tools run a command and hand back its output. That breaks down for anything interactive — vim, htop, a REPL, an installer asking questions, git rebase -i, an SSH session. terminal-use gives the agent a shell on a real pseudo-terminal, rendered by a real terminal emulator, so full-screen and interactive programs work and the agent sees what you would see.

  • Real PTY, real emulator — colors, cursor movement and the alternate screen are interpreted, not passed along as escape codes.

  • Text and pixels — read the screen as plain text, or as a PNG when layout and color matter.

  • Waits properly — block until a command actually finishes, or until some text appears.

  • Watch along — attach your own terminal to any session and type alongside the agent.

Quick start

Requires Node.js 22.12 or newer, on macOS, Linux or Windows.

Pick your client:

Client

How to add it

Claude Code

claude mcp add terminal-use --scope user -- npx -y terminal-use

Cursor

Add to Cursor

VS Code

Add to VS Code

Codex

codex mcp add terminal-use -- npx -y terminal-use

Gemini CLI

gemini mcp add -s user terminal-use npx -y terminal-use

Claude Desktop, and any other client that takes a command: add this to its MCP configuration (for Claude Desktop: Settings → Developer → Edit Config).

{
  "mcpServers": {
    "terminal-use": {
      "command": "npx",
      "args": ["-y", "terminal-use"]
    }
  }
}

Start a new session in your client and ask it to do something in a terminal, for example: "Open vim, write a haiku into /tmp/haiku.txt, save and quit, then show me a screenshot of cat-ing it."

Server options go after the command: npx -y terminal-use --cols 100 --rows 40.

Option

Default

--shell <path>

$SHELL or /bin/bash; PowerShell on Windows

Shell to run in new sessions

--cwd <path>

where the server was started

Working directory for new sessions

--cols <n> / --rows <n>

120 / 30

Terminal size

--scrollback <n>

5000

Lines of history kept

--login

off

Start shells as login shells (see below)

"command not found" inside a session

If programs that work in your own terminal (node, brew, pyenv…) are missing inside a session, the server probably inherited a bare environment. That happens when the MCP client is started from the Dock or a launcher instead of a terminal: your PATH is set up by your shell's profile files (~/.zprofile, ~/.bash_profile, ~/.profile), and nothing has read them.

A login shell reads those files. Turn it on for every session with the --login server flag, or for one session with login: true on terminal_create. It is off by default because it makes each shell slower to start and runs whatever your profile runs. It has no effect in PowerShell or cmd.exe, which have no login mode.

Related MCP server: can-see

Tools

Every tool except terminal_create and terminal_list takes the sessionId that terminal_create returns.

Tool

What it does

terminal_create

Start a session: an interactive shell, or one program with command. Optional label, cols, rows, shell, cwd, env, login, scrollback, theme.

terminal_list

List sessions.

terminal_destroy

End a session.

terminal_type

Type text. \n presses Enter. paste: true sends it as one paste.

terminal_press

Press a key or combination: Enter, Ctrl+C, ArrowUp, Shift+Tab, Alt+Enter, F5…

terminal_wait

Wait for the running command to finish, for a regex to appear, or for output to go quiet.

terminal_read

Read the screen or scrollback as text.

terminal_screenshot

Render the screen as a PNG.

terminal_click

Left-click a cell, with a preview step.

terminal_scroll

Turn the mouse wheel over a cell.

terminal_batch

Send several inputs in one call and get the screen back once.

terminal_resize

Change the terminal size.

terminal_reset

Clear the screen and scrollback, or restart the shell with hardReset: true.

Docker

The repository has a Dockerfile for running the server in a container:

docker build -t terminal-use .
docker run -i --rm -v "$PWD":/workspace terminal-use

In an MCP client, use docker as the command with run -i --rm terminal-use as its arguments. The terminals the agent gets are then shells inside the container, not on your machine: it sees only what you mount, which is the point if you want it boxed in. Attaching from your own terminal is not available in this setup.

The skill

terminal-use comes with an Agent Skill: a short guide for the agent on how to use these tools well — when to use a command session, how to wait, how to read what is selected — plus recipes for vim, pagers, REPLs, menu-driven programs, ssh prompts and end-to-end testing of a TUI. It lives in skills/terminal-use.

  • Hosts that load skills from MCP servers get it automatically. The server implements the MCP Skills extension (io.modelcontextprotocol/skills): the skill is listed by skills/list and its files are served as skill://terminal-use/... resources. Few hosts support this yet.

  • Hosts that load skills from disk can install the same files. For Claude Code:

    cp -r "$(npx -y terminal-use skills-dir)/terminal-use" ~/.claude/skills/

The skill is optional. Without it the agent still has the tool descriptions and the server's built-in instructions.

Shell sessions and command sessions

By default a session is an interactive shell: type commands into it as you would at a prompt.

Pass command to terminal_create to run one program in the terminal instead:

{"command": "npm test -- --watch", "cwd": "/path/to/project", "env": {"CI": "1"}}

The command goes through the session's shell (sh -c, PowerShell -Command, or cmd /c), so quoting, pipes and redirection work as they do at that shell's prompt. Input goes straight to the program. When it exits:

  • its exit status is reported (by the call that was in progress, by terminal_wait, and in terminal_list);

  • the final screen stays readable with terminal_read and terminal_screenshot;

  • input tools return an error with the exit status rather than restarting anything;

  • terminal_reset with hardReset: true runs it again, and terminal_destroy removes it.

This is the mode for testing a CLI or TUI: launch it, drive it, check how it ended.

Watching and typing along

terminal_create returns a command you can run in your own terminal to join the session:

node /path/to/terminal-use/bin/terminal-use.js attach 3 --socket /tmp/terminal-use-501/41234-3.sock

You see what the agent sees and can type into the same shell. It works like a shared tmux session: several people can attach at once, and Ctrl+] detaches.

  • You get the current screen and recent scrollback on connect, not a blank terminal.

  • --resize makes the session follow your window size. By default the session keeps its own.

  • --socket picks the server. Each MCP client runs its own terminal-use, and they all number sessions from 1; without --socket, attach <id> works when only one running server has that id and lists the candidates otherwise.

  • On Windows the session is reached through a named pipe instead of a socket file; the command you are given works the same way.

  • Sockets are per-user (0600, inside a 0700 directory under the system temp dir). Anyone who can connect gets a shell as you, so they are not exposed any further than that.

How it works

agent ──MCP──▶ terminal-use ──▶ node-pty ──▶ your shell
                  │
                  └─ @xterm/headless  ◀── everything the shell prints
                        │
                        ├─ terminal_read        (text)
                        └─ terminal_screenshot  (PNG)

node-pty runs the shell on a pseudo-terminal. Everything it prints is fed to a headless xterm.js emulator, and that emulator's buffer is the single source of truth: reads and screenshots both come from it, so the agent gets the rendered screen rather than a stream of escape codes.

Details

Waiting for things

terminal_type, terminal_press and terminal_click return once output has been quiet for a moment (idleMs, default 200 ms) and never wait longer than 10 seconds. That suits keystrokes. It doesn't suit a build, which can be silent for a while long before it is done. For anything slow, follow up with terminal_wait:

  • Default — wait for the command to finish. terminal-use asks the kernel which process owns the terminal's foreground. A shell hands the terminal to each command it runs and takes it back afterwards, so when the shell owns it again, the prompt is back. This needs no shell integration or prompt parsing, and works for commands that print nothing.

  • pattern — wait for a regex to match the screen. For things that never exit (Listening on port), REPL prompts, or a particular state of a TUI. ^ and $ match at line starts and ends; a leading (?i) or (?s) sets further flags.

  • until: "quiet" — wait for output to stop for quietMs (default 1 s). The same rule the typing tools use, without the 10-second cap.

In a command session, the default mode waits for the program to exit and reports its exit status.

timeoutMs defaults to 30 seconds (maximum 10 minutes). A timeout isn't an error: the response says the command is still running, and you can wait again.

On Windows there is no way to ask who owns the terminal, so in a shell session the default mode waits for two seconds of silence instead, and says it is a guess. Prefer a pattern there, or run the program as a command session, where waiting for it to exit works on every platform.

Limits worth knowing: background jobs (cmd &) don't count as running. Inside a nested program such as ssh or a REPL, the outer shell doesn't get the foreground back until that program exits, so use pattern or until: "quiet" there. No exit status is reported; run echo $?.

Reading the screen

terminal_read returns text in screen-sized pages: page: 0 is the current screen, page: 1 the one before it, and so on back through scrollback.

Lines the terminal wrapped at its right edge are joined back into the single line the program printed (joinWrapped: false gives one line per screen row).

Text can't show color, so it can't show which menu entry is selected. Reads therefore end with a list of what is highlighted on screen — text in reverse video or on a background color — with the row and columns terminal_click takes:

Highlighted on screen (reverse video or background color; screen row, columns):
  row 7, cols 3-18: "Unstaged changes"

If most of the screen is colored panels, the list is replaced by a pointer to terminal_screenshot. Turn it off with highlights: false.

The cursor is marked with ▌. On an empty cell it simply takes the place of the blank. On a character it is inserted in front of that character, which shifts the rest of that one line right by a column; the header says which character it is on. The marker is left out while the program hides the cursor (most full-screen programs do), and cursor: false returns the text untouched.

Screenshots

terminal_screenshot renders the screen with the bundled JetBrains Mono. This is what a call returns, here with a visual selection in vim:

A terminal_screenshot of vim with Python syntax highlighting and four lines selected

Sessions take a theme at creation: dark (default), light, solarized-dark or solarized-light.

JetBrains Mono covers Latin, Greek, Cyrillic, box-drawing and common symbols. Emoji, Chinese/Japanese and Korean text fall back to fonts already on the system, because bundling them would add tens of megabytes:

Emoji

CJK

Hangul

macOS

Apple Color Emoji

Hiragino Sans GB / PingFang

Apple SD Gothic Neo

Windows

Segoe UI Emoji

Microsoft YaHei / Yu Gothic

Malgun Gothic

Linux

Noto Color Emoji

Noto Sans CJK

Noto Sans CJK

macOS has these out of the box, and Windows has the emoji font (the East Asian fonts come with the matching language features). On Debian or Ubuntu, install them with apt install fonts-noto-color-emoji fonts-noto-cjk. Without them (a bare Docker image, say) those characters render as empty boxes in screenshots. Nerd Font and Powerline icons render as boxes everywhere. terminal_read is unaffected and always returns the real characters.

Typing, pasting and batching

terminal_type sends characters as keystrokes. For multi-line text going into an editor, a REPL or a shell prompt, add paste: true: programs that support bracketed paste receive it as one paste and insert it verbatim, without auto-indenting or running each line as it arrives. Programs that don't support it get the plain characters.

terminal_batch sends a list of inputs in one call and returns the screen once at the end, which saves a round trip per keystroke when the steps are already known:

{
  "sessionId": 1,
  "actions": [
    {"type": "press", "key": "ArrowDown", "count": 3},
    {"type": "press", "key": "Enter"},
    {"type": "wait", "pattern": "Commit message"},
    {"type": "type", "text": "Fix typo"},
    {"type": "press", "key": "Ctrl+S"}
  ]
}

Actions are type, paste, press, click, scroll and wait (a fixed ms, or a pattern to appear). The batch is checked before anything is sent, and stops at the first action that fails, reporting how far it got.

Clicking and scrolling

  • Left button only. Coordinates are 1-indexed; (1, 1) is the top-left cell.

  • preview is on by default. A preview returns a screenshot with a ring drawn around the target cell and sends no click. Repeat the call with preview: false to click. Full-screen programs often have destructive actions one click away, so it is worth the extra step.

  • terminal_scroll turns the wheel over a cell. Programs that track the mouse get wheel events there, so the pane under the pointer scrolls; full-screen programs that don't (less, man) get arrow keys, as in a normal terminal. At a shell prompt there is nothing to scroll — read earlier output with terminal_read and page.

  • A real click needs the program to have turned on mouse reporting — vim with set mouse=a, fzf, lazygit, htop and most modern TUIs do. At a plain shell prompt the call returns an error instead of printing escape codes into your command line.

Session lifecycle

  • Sessions are independent. Calls to one session run in order; calls to different sessions don't block each other.

  • If a shell session's shell exits, the session sits idle for six hours, or the 50-session limit is reached, the session is shut down but its id stays reserved for 30 days. The next call to that id starts a fresh shell with the same size, shell, working directory and theme, and returns a notice saying what happened — including the last screen the old shell printed, if it exited on its own. The command in that call is not run; send it again if you still want it.

  • Idle means no tool calls and no output. A dev server that is still printing is not idle.

  • terminal_destroy ends a session for good; its id is not reserved.

  • When the MCP client disconnects or the server is stopped, every shell is closed and every attach socket removed.

Protocol support

Built on the official MCP TypeScript SDK (v2). Over stdio it speaks both the 2026-07-28 revision of the protocol, which is stateless, and the earlier handshake-based revisions; the client's first message decides which.

Stateless refers to the protocol, not the terminals: sessions live in the server process and are addressed by the sessionId you pass on each call. The server also provides usage instructions, titles and behavior hints for each tool, cancellation, progress updates from terminal_wait, and the Skills extension described above.

Platform support

macOS (arm64, x64)

Supported; tested in CI

Linux (arm64, x64)

Supported; tested in CI on Node 22 and 26

Windows (x64)

Supported; tested in CI against PowerShell and cmd.exe

On Windows, sessions run through ConPTY, the default shell is Windows PowerShell, and two things differ: terminal_wait cannot detect that a shell command has finished (see Waiting for things), and login does nothing.

The native dependencies (node-pty, @napi-rs/canvas) ship prebuilt binaries, so no compiler is needed to install.

Development

git clone https://github.com/computer-agent-labs/terminal-use.git
cd terminal-use
yarn install
yarn build      # compile src/ to dist/
yarn test       # build, then run the full suite

Other scripts:

yarn dev            # run the server straight from source
yarn lint           # eslint
yarn typecheck      # tsc, no output
yarn test:unit      # unit tests only
yarn test:windows   # what CI runs on Windows: shell-independent tests + tests/windows
yarn smoke          # quick end-to-end check without an MCP client
yarn demo           # regenerate docs/demo.gif (needs ffmpeg, vim and python3)

To point your MCP client at a local checkout, build it and use the path to the bin script:

claude mcp add terminal-use --scope user -- node "$PWD/bin/terminal-use.js"

The code is laid out by layer: src/pty (spawning, key and mouse encoding), src/emulator (the xterm buffer, rendering, waiting), src/session (one terminal), src/attach (the socket you attach through) and src/mcp (the tools). The agent skill is in skills/.

Security

terminal-use gives the connected client a shell on your machine, running as you, with no sandbox. Connect it only to clients you would trust with a terminal, and use your client's tool-approval settings to control what runs unprompted. It opens no network ports; attach sockets are restricted to your own user. See SECURITY.md for details and for how to report a vulnerability.

Contributing

Issues and pull requests are welcome. CONTRIBUTING.md covers setting up, running the tests, and what a good pull request looks like. This project follows the Contributor Covenant.

License

MIT. The bundled JetBrains Mono fonts are licensed under the SIL Open Font License.

Available Tools

13 tools
terminal_batchRun several terminal inputsA
Destructive

Send a sequence of inputs in one call and get the screen back once at the end — for driving a full-screen program without a round trip per keystroke (open a menu, move down three, press Enter, type a name, confirm). Actions run in order, each given a moment to take effect before the next.

Each action is an object with a type and the fields that type uses:

  • type: text — typed as keystrokes; \n presses Enter.

  • paste: text — delivered as one bracketed paste where the program supports it.

  • press: key, optional count — same key specs as terminal_press.

  • click: col, row — left click, sent immediately with no preview; needs the program to track the mouse.

  • scroll: direction, optional amount, col, row — as terminal_scroll.

  • wait: ms for a fixed pause, or pattern (optional timeoutMs) to continue once a regex matches the screen.

The batch is validated before anything is sent. It stops at the first action that fails (a pattern that never appears, a click the program cannot receive, the process exiting) and reports how far it got, with the screen as it stands. Use it when you already know the steps; when you need to look between steps, use the individual tools.

NameRequiredDescriptionDefault
idleMsNoSettle window after the last action. Default 200.
actionsYesThe inputs to send, in order (1 to 50).
maxWaitMsNoCap on the settle after the last action. Default 5000.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.
stepIdleMsNoHow long output must be quiet after each action before the next is sent. Default 100. Raise it for programs that redraw slowly.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (destructive/openWorld/non-idempotent) by disclosing that the batch is validated before anything is sent, that it halts on the first failing action with screen state reported, that clicks are sent with no preview and require mouse tracking, and how settle/idle timing works. It stops short of stating that typed input into a live shell is irreversible, which is the main behavioral risk for a destructiveHint=true tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then a compact bulleted field map, but tucks the critical routing guidance ('use the individual tools') into the final sentence. The bullet list is dense yet each line corresponds to a distinct action type, so little is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description covers the return behavior ('get the screen back once at the end', 'reports how far it got, with the screen as it stands') plus failure modes and stop conditions. Combined with the schema's 1-50 action bound and timeout defaults, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already carries the field-level detail and a 3 would be the floor. The description adds value by grouping fields by action type and cross-referencing sibling specs ('same key specs as terminal_press', 'as terminal_scroll'), which the schema does not do; the remaining field docs are largely duplicative of the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb+resource ('Send a sequence of inputs in one call and get the screen back once at the end') and immediately names the driving use case. It is clearly distinguishable from the per-keystroke siblings (terminal_type, terminal_press, terminal_click) by being the batched equivalent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when ('Use it when you already know the steps') and an explicit when-not with the alternative named ('when you need to look between steps, use the individual tools'). It also maps each action type back to its single-shot sibling (terminal_press, terminal_scroll), so routing is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_clickClick in terminalA
Destructive

Deliver a left mouse-button click at a cell in the terminal. Only works when the program currently in the foreground has opted into mouse tracking (vim with set mouse=a, fzf, lazygit, less with mouse mode, etc.) — at a plain shell prompt mouse mode is off and the click would just print escape sequences as text, so we refuse the actual click in that case.

Coordinates are 1-indexed and refer to the live screen viewport: col 1, row 1 is the top-left cell, and the bottom-right cell is (terminal width, terminal height) which you can see via terminal_read's state header.

PREVIEW MODE (default preview: true): does NOT click. Returns a PNG with a bright magenta ring + dot drawn around the target cell so you can verify your coordinates. Always do this first when you are not 100% sure where the click should land — TUIs often have destructive actions one click away (delete branch, kill process, etc.).

EXECUTE MODE (preview: false): actually sends the mouse press+release sequence and settles for output. Use this only after you've previewed and confirmed, or when you're confident.

CAVEATS: idleMs and maxWaitMs are ignored in preview mode (preview doesn't settle). When the target cell is near the right edge of the viewport, the coordinate label drawn next to the magenta ring may be clipped — the ring itself is always within frame, so trust it over the label.

NameRequiredDescriptionDefault
colYes1-indexed column. Column 1 is the leftmost cell on the visible viewport.
rowYes1-indexed row. Row 1 is the top of the visible viewport.
idleMsNo
previewNoWhen true (DEFAULT), render a PNG with a bright magenta ring around the target cell WITHOUT actually clicking. When false, deliver the click and settle for output. Set to false explicitly when you are confident about the coordinates.
filePathNoPreview only: absolute path to write the PNG to. If unset, image is inlined as base64.
maxWaitMsNo
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (destructiveHint=true, openWorldHint=true, idempotentHint=false): it discloses the refusal behavior when mouse mode is off, warns that TUIs often have destructive actions one click away, explains that idleMs/maxWaitMs are ignored in preview, and notes the coordinate-label clipping at the right edge. This is exactly the extra runtime context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action, then uses clear PREVIEW/EXECUTE/CAVEATS sections so the reader can scan to what matters. The prose is dense and slightly long (e.g. the parenthetical TUI example list), but nearly every sentence carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, non-idempotent 7-parameter tool with no output schema, the description covers the safety protocol, coordinate semantics, return artifact (PNG), and edge cases. The remaining gap is the execute-mode output and the exact semantics of idleMs/maxWaitMs outside preview.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 71%, and the description adds real meaning: it pins the coordinate frame to the live viewport, explains how to obtain terminal width/height via terminal_read, and documents that preview is the default and that idleMs/maxWaitMs are no-ops in preview. It stops short of saying what idleMs and maxWaitMs actually control in execute mode, which the schema leaves undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ("Deliver a left mouse-button click at a cell in the terminal") and scopes it to a specific coordinate system, which cleanly disambiguates it from sibling input tools like terminal_press and terminal_type. The mouse-tracking precondition further narrows exactly what this tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the precondition that gates use (foreground program must have mouse tracking on, otherwise the click is refused) and gives clear preview-first-then-execute guidance. It does not name sibling alternatives such as terminal_press, but the when/when-not conditions here are strong enough to route the agent correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_createCreate terminal sessionA

Spawn a new terminal session and return its sessionId. You must call this before any per-session tool — there is no shared default session. By default the session is an interactive shell. Pass command to run one program in the terminal instead (a TUI, a test run, a CLI under test): the session then lasts as long as that program, reports its exit status when it ends, and keeps its final screen readable until you destroy it. If the server already holds 50 live sessions, the least-recently-used one is evicted to make room (its sessionId is tombstoned and any later call against it will respawn with an 'evicted' notice).

NameRequiredDescriptionDefault
cwdNoOverride the default working directory.
envNoEnvironment variables to set for the session, on top of the server's own environment.
colsNo
rowsNo
labelNoOptional human-readable name shown in terminal_list output (e.g. "dev-server").
loginNoStart the shell as a login shell (`-l`), so it reads the profile files (~/.zprofile, ~/.bash_profile, ~/.profile) where PATH is usually set up. Use it when tools that work in the user's own terminal are "command not found" here — typical when the MCP client was started from a GUI rather than a terminal. Slower to start. No effect in PowerShell or cmd.exe. Default false (or the server's --login flag).
shellNoOverride the default shell (e.g. "/bin/zsh"; on Windows "pwsh.exe" or "cmd.exe" instead of PowerShell).
themeNoColor palette used by terminal_screenshot and terminal_click previews for THIS session. Persists across auto-respawn / hardReset. Default "dark" (VS Code Dark+). Options: "dark", "light", "solarized-dark", "solarized-light".
commandNoRun this command line instead of an interactive shell, e.g. "vim notes.txt" or "npm test". It is run through the session's shell (`sh -c`; on Windows PowerShell `-Command`, or `cmd /c`), so quoting, pipes and redirection work as at that shell's prompt. Input tools talk to the program directly. When it exits, its exit status is reported, the final screen stays readable, and nothing is restarted automatically.
scrollbackNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare a non-readonly, non-destructive, non-idempotent, closed-world write, and the description goes well beyond that: it discloses the 50-session LRU eviction with tombstoning and 'evicted' respawn behavior, plus command-mode lifecycle semantics (session lives as long as the program, exit status reported, final screen retained until destroy). This is exactly the kind of behavioral context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense paragraph, but well front-loaded: purpose and prerequisite first, command semantics second, eviction last. Every sentence carries information; it is long only because the tool genuinely has three behavioral clauses worth knowing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, zero-required, no-output-schema tool, the description covers the essential call semantics: prerequisite ordering, default interactive mode, command mode, and capacity/eviction. The only gap is the silent geometry/scrollback parameters, which are secondary to correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 70%, so the baseline is 3. The description adds real meaning for `command` (session lifetime, exit status, non-restart) and for the interactive-default contrast, but `cols`, `rows`, and `scrollback` remain undocumented in both schema and description, and `cwd`/`env` are only lightly described.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Spawn a new terminal session') and immediately declares the return value (sessionId), which is the key artifact for the siblings. It also differentiates itself from every per-session tool by establishing that it is the mandatory entry point.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the prerequisite ('You must call this before any per-session tool — there is no shared default session') and elaborates the when-to-use-command-vs-interactive-shell decision with concrete examples (TUI, test run, CLI under test). The 50-session eviction rule is stated as a condition affecting usage. Nothing critical is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_destroyDestroy terminal sessionA
Destructive

Kill a session and forget the sessionId entirely. The shell process is terminated and the sessionId is not tombstoned — future calls against it will error with "Unknown sessionId". Use this when you're explicitly done with a session. Tombstones (which auto-respawn on next access) only happen for system-driven terminations: idle-kill, eviction, or shell exit.

NameRequiredDescriptionDefault
sessionIdYesNumeric id from terminal_create or terminal_list.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only flag destructiveHint=true and idempotentHint=false; the description adds the crucial non-obvious behavior that the id is not tombstoned, future calls error with 'Unknown sessionId', and that auto-respawn only applies to system-driven terminations. This is exactly the extra context annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero filler, front-loaded with the primary action before the tombstone clarification. Each sentence carries distinct information (action, id invalidation, contrast with system terminations).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by describing the post-call state and the exact error an agent will see on misuse. For a single-parameter destructive tool, nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it tells the agent what the sessionId becomes after the call (permanently invalid, errors on reuse). That is semantic value beyond the schema's 'Numeric id from terminal_create or terminal_list.'

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Kill a session') and immediately clarifies the distinguishing semantic: the sessionId is forgotten, not tombstoned. Combined with the sibling set (terminal_reset, terminal_list), an agent can tell this is the terminal teardown tool rather than a reset or query.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this when you're explicitly done with a session' gives an explicit trigger condition, and the tombstone contrast carves out system-driven terminations (idle-kill, eviction, shell exit) as cases where this tool should NOT be called. It stops short of naming terminal_reset as the alternative for keeping a session alive, so it's clear but not fully routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_listList terminal sessionsA
Read-onlyIdempotent

List every active session and every tombstoned (recently-killed but reserved) sessionId. Tombstones are reservations: the shell is gone but the sessionId can still be called against — doing so respawns a fresh shell under the same id and surfaces the original termination reason (shell-exit, idle-killed, or evicted). Tombstones expire after 30 days; after that the id is gone.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (readOnly, idempotent, non-destructive); the description goes well beyond them by disclosing that tombstones are reservations whose shell is gone, that calling one respawns a fresh shell and surfaces the original termination reason (shell-exit, idle-killed, evicted), and that tombstones expire after 30 days. This is exactly the non-obvious behavior an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core purpose, followed by the tombstone semantics that are impossible to infer from the name or schema. No filler; every sentence carries information an agent would otherwise lack.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must describe the return shape, and it does: the two categories of returned ids plus the termination-reason enum values. Combined with the rich tombstone lifecycle explanation, nothing material is missing for a zero-parameter list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. The description correctly adds no parameter detail because there is nothing to parameterize.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (terminal sessions), and immediately clarifies the two result categories: active sessions and tombstoned sessionIds. That distinction cleanly separates it from sibling tools like terminal_create or terminal_read, which act on a single session.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Listing is self-evidently the discovery entry point, and the description implicitly signals a use case by explaining that a tombstoned id can be called again. However, it never explicitly states when to reach for this tool versus a sibling (e.g. to discover a sessionId before terminal_read), nor does it name any alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_pressPress key in terminalB
Destructive

Press a single named key or key combination. Examples of supported key values: Enter, Tab, Escape, Backspace, Space, ArrowUp / ArrowDown / ArrowLeft / ArrowRight, Home, End, PageUp, PageDown, Delete, Insert, F1..F12, Ctrl+C, Ctrl+D, Ctrl+L, Ctrl+A..Ctrl+Z, Shift+Tab, Alt+B, Ctrl+ArrowLeft, Ctrl+Shift+ArrowRight, etc. Same settle behavior as terminal_type.

NameRequiredDescriptionDefault
keyYesKey spec like "Enter", "Ctrl+C", "Shift+Tab", "ArrowUp", "F5", "Ctrl+Shift+ArrowLeft".
countNoPress the key this many times in a row (e.g. ArrowUp x 5). Default 1.
idleMsNo
maxWaitMsNo
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, idempotentHint=false, and openWorldHint=true, so the safety profile is covered. The description adds one useful behavioral detail (shared settle behavior with terminal_type), but says nothing about repeat semantics, timing/idle behavior, or failure on unsupported keys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, followed by examples and the settle note. The long example enumeration is justified because there is no enum on `key`, though it is verbose enough to slightly dilute the entry message.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so return values need not be explained, and annotations cover the safety profile. Still, two of five parameters are undocumented and the meaning of 'settle behavior' is left to the agent to infer, which is a noticeable gap for a mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60%, and the description substantially expands the `key` vocabulary well beyond the schema's brief examples, adding genuine value. However, idleMs and maxWaitMs remain entirely undocumented in both schema and description, and the `count` behavior is only covered by the schema itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('Press a single named key or key combination'), which cleanly separates it from sibling terminal_type (text input) and terminal_click (mouse). The extensive example list of supported key values reinforces exactly what kind of input this tool consumes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description never states when to choose this over terminal_type or terminal_click, nor any prerequisites such as needing a live session. The 'Same settle behavior as terminal_type' line hints at a relationship but provides no explicit selection guidance or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_readRead terminal textA
Read-onlyIdempotent

Read a window of the terminal buffer. The buffer is the full xterm-emulated state (scrollback + visible viewport) in one contiguous index space. The window is paged from the bottom upward in multiples of rows. rows defaults to the current screen height and is capped at 1000. page: 0 is the most recent screen-sized chunk; page: 1 is the screen before that, and so on. Trailing blank rows are trimmed implicitly.

NameRequiredDescriptionDefault
pageNo0 = newest screen-sized window. N = scroll up N pages (each page = `rows` lines). Past-top clamps.
rowsNoWindow height. Default = current screen height. Max 1000.
cursorNoWhen true (default), mark the cursor inline with "▌". On an empty cell it takes the place of the blank; on a character it is inserted in front of that character, which shifts the rest of that one line right by a column. Nothing is overwritten. Skipped automatically while the program has the cursor hidden. Set to false if you need the unmodified text.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.
highlightsNoWhen true (default), list text on the current screen that is drawn in reverse video or on a background color — how TUIs show the selected menu entry, tab or button — with its screen row and columns. Plain text cannot show this otherwise.
joinWrappedNoWhen true (default), rows the terminal soft-wrapped at its right edge are joined back into the single long line the program printed. Set to false to get one line per screen row.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: the contiguous scrollback+viewport index space, bottom-up paging in `rows` multiples, the 1000-row cap, and implicit trimming of trailing blank rows. It stops short of describing the return payload shape or any error/empty-buffer behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then the buffer/window model, then paging semantics, then the trimming note. Every sentence carries information an agent needs to page correctly; nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining what comes back, and it does reasonably well (a window of buffer text, blank rows trimmed, cursor/highlight/wrap defaults documented in the schema). It could be more explicit about the returned structure (lines vs rows array) for a read tool with several formatting flags, but the model is clear enough to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter and the baseline is 3. The description adds genuine framing on top — that pages are counted upward from the bottom, that rows defaults to the current screen height and is capped at 1000, and that page 0 is the newest chunk — which clarifies the interaction between `page` and `rows`.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read a window of the terminal buffer') and immediately defines what the buffer is, which cleanly separates it from siblings like terminal_screenshot (renders) and terminal_scroll (moves the viewport). An agent can tell what this returns and from where without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The paging model implicitly tells the agent this is the way to walk back through scrollback, but there is no explicit when-to-use/when-not guidance and no sibling is named (e.g., vs terminal_screenshot or terminal_scroll). Usage must be inferred from the described semantics.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_resetReset terminalA
Destructive

Wipe the terminal buffer and scrollback. By default the shell process keeps running (env vars, cwd, history all preserved). Pass hardReset: true to kill the current shell and spawn a brand-new one — anything mid-execution gets killed. When hardReset: true, you can also override cols, rows, shell, and cwd. In a session created with command, a hard reset runs that command again.

NameRequiredDescriptionDefault
cwdNohardReset only: working directory for the new shell.
colsNohardReset only: spawn at this width.
rowsNohardReset only: spawn at this height.
shellNohardReset only: shell command (default $SHELL).
hardResetNoKill + respawn the shell instead of just clearing the buffer. Default false.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructive=true and non-idempotent, but the description adds substantial context beyond them: what is preserved on a soft reset (env vars, cwd, history), what is lost on a hard reset (mid-execution processes), and the command-session re-run side effect. This is exactly the kind of consequence disclosure a destructive tool needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences, front-loaded with the primary effect before the optional mode, and every sentence carries distinct information (default behavior, hard-reset behavior, overrides, command-session edge case). No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and full annotation coverage, the description supplies everything needed to call this correctly: default vs hard mode, what each destroys, and the parameters that only take effect in hard mode. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and each parameter already documents 'hardReset only' plus defaults ($SHELL, false). The description restates the grouping of the hardReset-only overrides rather than adding new syntax or format detail, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Wipe the terminal buffer and scrollback') and immediately distinguishes its two modes (soft clear vs hardReset kill/respawn), which separates it from siblings like terminal_resize or terminal_read. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly states the default behavior and the condition that selects the alternative ('Pass hardReset: true to kill...'), plus a non-obvious edge case (a session created with `command` re-runs it). It never names a sibling as the alternative or states when *not* to reset, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_resizeResize terminalA
Idempotent

Change the terminal size. Both cols and rows are optional; omitting one preserves the current value. Resizes both the PTY and the emulator (so programs running inside see the change via SIGWINCH).

NameRequiredDescriptionDefault
colsNoNew column count (1..1000). Omit to keep current cols.
rowsNoNew row count (1..1000). Omit to keep current rows.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare it is a non-read-only, idempotent, non-destructive operation. The description adds meaningful behavior beyond that: it resizes both the PTY and the emulator and propagates change via SIGWINCH to running programs, which an agent cannot infer from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler. The core action is front-loaded, and the parameter behavior and propagation detail follow in service of the primary statement.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but for a resize tool the critical behavioral facts (partial update semantics, dual PTY/emulator resize, SIGWINCH propagation) are covered. Minor gaps remain around error conditions for invalid sessions or out-of-range sizes, though the schema bounds cols/rows.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents cols, rows, and sessionId fully. The description restates the omit-to-preserve semantics already present in the schema, adding no new syntax or format detail. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Change the terminal size'), which an agent can immediately distinguish from siblings like terminal_read or terminal_type. The scope is precise and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the partial-update behavior (omitting cols/rows preserves current values), which is useful contextual guidance. However, it gives no when-to-use or when-not-to-use signals relative to alternatives such as terminal_reset or terminal_create.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_screenshotScreenshot terminalA
Read-onlyIdempotent

Render a screen-sized window of the terminal to a PNG. Height is always the current screen height (term.rows); use page to walk back through scrollback in screen-sized increments at the same dimensions as the live screen. If filePath is set, the PNG is written there and the path is returned. Large images (>2097152 bytes) are also spilled to a temp file automatically.

NameRequiredDescriptionDefault
pageNo0 = current live screen. N = the screen-sized window N screens earlier. Past-top clamps.
filePathNoAbsolute path to write the PNG to. If unset, image is inlined as base64.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), yet the description adds real behavior: height is always term.rows, output is inlined as base64 unless filePath is set, and images over 2097152 bytes are auto-spilled to a temp file. That spill behavior is the kind of non-obvious side effect worth crediting, though no pagination or size limits on page depth are discussed beyond the schema's clamp note.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each front-loaded and earning its place: output format first, then paging semantics, then file/inline behavior. No filler or restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does carry the return-value burden and handles it: path returned when filePath is set, base64 otherwise, temp-file spill for large images. Combined with annotations covering safety, an agent has what it needs; only the absence of any guidance on choosing between text readers and screenshots is a slight gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds semantics the schema lacks: page windows are rendered 'at the same dimensions as the live screen,' clarifying that paged screenshots are dimensionally consistent with page 0. That is a genuine addition beyond the parameter's own text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with output format: 'Render a screen-sized window of the terminal to a PNG.' This distinguishes it cleanly from terminal_read (text extraction) and other siblings without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains how to use `page` to walk scrollback, which is useful operational context, but it never states when to choose this tool over terminal_read or terminal_scroll for retrieving terminal content. Usage is implied rather than routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_scrollScroll in terminalA

Turn the mouse wheel over a cell of a full-screen program: scroll a pager, a file list, a log pane. Behaves as a terminal emulator does — programs that track the mouse receive wheel events at that cell (so the pane under it scrolls); full-screen programs that do not (less, man) receive arrow keys instead. At a plain shell prompt there is nothing to scroll and the call fails: earlier output is read with terminal_read and its page argument, not by scrolling.

NameRequiredDescriptionDefault
colNo1-indexed column the pointer is over. Matters when panes scroll independently. Default: screen center.
rowNo1-indexed row the pointer is over. Default: screen center.
amountNoWheel notches. Most programs move about 3 lines per notch. Default 3.
idleMsNo
directionYes"up" moves toward earlier content, "down" toward later.
maxWaitMsNo
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare this is a non-read-only, non-idempotent action, and the description goes well beyond them by disclosing the emulation semantics: mouse-tracking programs receive wheel events at the cell while non-tracking programs (less, man) receive arrow keys instead, plus the failure mode at a bare prompt. It stops short of describing timing behavior for idleMs/maxWaitMs or what the call returns on success.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the mechanism and progressively narrowing to the dual-mode behavior and then the failure case. Every clause carries information an agent needs; no restatement of the tool name or schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema and no annotation coverage of behavior, the description covers the hard parts: what it does, how programs respond, and when it fails. It leaves the timing parameters and the success response undefined, which is a modest but real gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 71%, and the description reinforces the coordinate model by explaining that the target cell matters 'when panes scroll independently' — which clarifies row/col intent beyond the raw bounds. However, it says nothing about amount, idleMs, or maxWaitMs, whose schema entries are terse or absent, so the coverage gap is not compensated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and mechanism ('turn the mouse wheel over a cell of a full-screen program') and enumerates the resources it acts on (pager, file list, log pane). It also explicitly distinguishes itself from the sibling terminal_read, so an agent can choose between them without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives positive conditions (full-screen program pane under the cell), an explicit when-not (a plain shell prompt has nothing to scroll and the call fails), and names the alternative for that case: terminal_read with its `page` argument. This is close to a complete decision rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_typeType into terminalA
Destructive

Type literal characters into the terminal as if a human were pressing keys. Embedded \n is normalized to \r so "git push\n" actually submits. Always waits for the buffer to settle (or to time out) before returning. The wait is capped at 10s; for anything slower (builds, installs, test runs) follow up with terminal_wait, which blocks until the command actually finishes.

NameRequiredDescriptionDefault
textYesCharacters to type. Embedded \n becomes Enter.
pasteNoDeliver the text as a single paste instead of keystrokes. Use it for multi-line text going into an editor, a REPL or a shell prompt: programs that support bracketed paste insert it verbatim (no auto-indent, lines are not run one by one), and nothing is submitted until you press Enter. Programs that do not support it receive the plain characters. Default false.
idleMsNoSettle window: silence this long after the last byte counts as settled. Default 200.
maxWaitMsNoOverall cap on the settle wait. Default 5000, clamped to 10000. Use terminal_wait for longer.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing the newline normalization quirk (\n -> \r, with a worked example), the settle-wait blocking behavior, and the hard 10s cap on the wait. These are exactly the traits an agent needs to avoid mis-timing follow-up calls, and none of them appear in the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the core action, then the normalization rule, then the blocking semantics, then the escape hatch. No filler and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and a destructive, non-idempotent annotation profile, the description covers the key behavioral risks (blocking, timeout, follow-up tool). It stops short of saying what the call actually returns (settled buffer output vs. nothing), which is a minor remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents text, paste, idleMs, maxWaitMs and sessionId. The description only adds the \r-vs-Enter nuance for `text` and reinforces the wait cap; it does not expand meaning on paste, idleMs or sessionId. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Type literal characters into the terminal') and immediately scopes it against the alternative keystroke/settle behavior, naming terminal_wait as the escalation path. An agent can distinguish it from terminal_press and terminal_batch from the text alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context for the slow-command case ('for anything slower (builds, installs, test runs) follow up with terminal_wait') and for paste mode (multi-line into editor/REPL/shell). It does not state when NOT to use it versus siblings like terminal_press or terminal_batch, so it stops short of explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

terminal_waitWait for terminalA
Read-onlyIdempotent

Block until the terminal reaches a state, instead of guessing with sleeps or polling terminal_read. Use it after terminal_type for anything that outlives the settle window: builds, installs, test runs, servers starting up.

DEFAULT (no pattern): waits for the running command to finish — i.e. for the shell to take the terminal's foreground back and its prompt to go quiet. This asks the kernel who owns the terminal, so it works with any prompt and stays correct while a command is silent (sleep 60) or chatty. Returns immediately if the shell is already at its prompt. On Windows this cannot be detected in a shell session: the call waits for a stretch of silence instead and says so — prefer pattern there. In a session created with command, it waits for that command to exit and reports its exit status. Background jobs (cmd &) do not count as running, and inside a nested program (ssh, a REPL, a TUI) the outer shell never regains the foreground until that program exits — use pattern there.

until: "quiet": waits until nothing has been printed for quietMs (default 1000), whatever owns the terminal. This is the same "settled" rule terminal_type uses, without its 10s cap — for nested programs where completion cannot be detected and no pattern fits.

WITH pattern: waits until the regex matches the text on screen (the viewport plus the 200 rows above it). Use this for servers that never exit ("Listening on"), REPL prompts, or TUI states. Text that is already on screen counts, so pick a pattern that only the new output can satisfy.

Returns the screen when the condition is met, or when timeoutMs runs out (not an error — the response says the command is still running). In a shell session this does not report an exit status; run echo $? afterwards if you need it.

NameRequiredDescriptionDefault
untilNo"command" (default): the running command has finished and the shell is back at its prompt. "quiet": output has been silent for `quietMs`. Ignored when `pattern` is given.
patternNoJavaScript regular expression matched against the screen text, lines joined with "\n" (e.g. "Listening on .*:3000", "^>>>\\s*$", "(?i)error"). `^` and `$` match at the start and end of each line; trailing spaces are trimmed from screen lines, so do not match a space after a prompt. Omit to wait for command completion.
quietMsNoHow long the output must stay silent. With until="command" (default 300) it applies once the shell is back in the foreground, so the prompt has finished drawing; with until="quiet" (default 1000) it is the whole condition.
sessionIdYesNumeric id of the session to target. Get one by calling terminal_create. Use terminal_list to enumerate currently-known ids.
timeoutMsNoGive up after this long. Default 30000, max 600000.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnly, idempotent, non-destructive), yet the description adds substantial behavior the annotations cannot: kernel-level foreground detection, platform-specific Windows fallback, background-job handling, nested-program limitations, and the critical fact that a timeout is not an error and reports the command still running. It even notes no exit status is reported in shell sessions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The text is long but well-structured, with labeled sections (DEFAULT, until: "quiet", WITH pattern) and the core purpose front-loaded. Most sentences carry a distinct edge case, though a few restate schema-documented details, keeping it just short of fully waste-free.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description steps in to explain the return ("Returns the screen when the condition is met, or when timeoutMs runs out") and the timeout semantics. Combined with the mode-specific behavior, an agent has everything needed to call it correctly across scenarios.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents each parameter, setting a baseline of 3. The description adds real guidance beyond the schema, such as the viewport-plus-200-rows match scope and the gotcha "pick a pattern that only the new output can satisfy," which meaningfully shapes correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: "Block until the terminal reaches a state." It explicitly distinguishes itself from the sibling terminal_read ("instead of guessing with sleeps or polling terminal_read"), so an agent can tell the tools apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ("after terminal_type for anything that outlives the settle window: builds, installs, test runs, servers starting up") and when-not (complex nested programs, Windows shells, servers that never exit). It also names the alternative rule (terminal_type's settle window) and routes to `pattern` where the default cannot work.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 13 tool updatesv0.2.0
    • First observedterminal_batch
    • First observedterminal_click
    • First observedterminal_create
    • First observedterminal_destroy
    • First observedterminal_list
    • First observedterminal_press
    • First observedterminal_read
    • First observedterminal_reset
    • First observedterminal_resize
    • First observedterminal_screenshot
    • First observedterminal_scroll
    • First observedterminal_type
    • First observedterminal_wait

TDQS

A4.1/5.0

Scored across 13 tools

Disambiguation4/5

Each tool has a clearly distinct purpose: session lifecycle (create/destroy/list/reset/resize), input (type/press/click/scroll/batch), output (read/screenshot), and synchronization (wait). The main overlap is terminal_batch, which can perform everything type/press/click/scroll do, but descriptions explicitly steer the agent (batch for known sequences, individual tools when you need to look between steps), so confusion is limited.

Naming Consistency5/5

Every tool follows the same terminal_<verb> snake_case pattern (terminal_create, terminal_read, terminal_wait, etc.), with no deviations in case or verb style. The naming is entirely predictable.

Tool Count5/5

13 tools is comfortably within the ideal 3-15 range for a terminal automation server. Each tool maps to a genuine, non-redundant capability (session management, multiple input modalities, output capture, and blocking waits).

Completeness4/5

The surface covers the full session lifecycle (create/destroy/list/reset/resize) plus input, output, and synchronization primitives, which is close to complete for driving a terminal. Minor gaps remain, such as no standalone paste tool outside batch and no explicit signal/interrupt tool beyond terminal_press Ctrl+C.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers