mcpField
T
terminal-use

terminal-use

本地服务
github.com开发工具11 周前更新

关于 terminal-use

terminal-use 是一个 MCP 服务,为 AI Agent 提供运行在真实伪终端上的交互式 Shell。其终端模拟器可渲染文本和截图,支持普通命令输出工具难以处理的全屏及交互程序。

主要功能

  1. 01在真实 PTY 上运行交互式 Shell
  2. 02以文本或 PNG 读取终端画面
  3. 03等待进程结束或屏幕匹配
  4. 04输入文本、按键、点击和滚动
  5. 05将人工终端连接到会话

适用场景

  1. 01操作 vim 等编辑器或交互式 REPL
  2. 02完成安装程序和交互式 Git 操作
  3. 03测试 CLI 和 TUI 程序
  4. 04观察并加入 Agent 的终端会话

MCP 相关

terminal-use 将终端会话及其控制功能作为 MCP 工具提供,包括读取屏幕和获取截图。它还实现 MCP Skills 扩展,用于列出和提供可选的 Agent Skill。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"computer-agent-labs-terminal-use": {
"command": "npx",
"args": [
"-y",
"terminal-use"
]
}
}
}
启动命令npx -y terminal-use

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmterminal-use0.2.1

工具

13

收录的工具列表 · 更新于 1 周前

参数类型必填说明
idleMsinteger否最后一个操作后的稳定等待时间。默认值为 200。
actionsarray是按顺序发送的输入(1 到 50 项)。
maxWaitMsinteger否最后一个操作后的稳定等待时间上限。默认值为 5000。
sessionIdinteger是要操作的会话数字 ID。调用 terminal_create 获取 ID。使用 terminal_list 枚举当前已知的 ID。
stepIdleMsinteger否每次操作后,输出必须保持静默多久才发送下一项。默认值为 100。对于重绘较慢的程序,请调高此值。

详细介绍

terminal-use

一个 MCP 服务,让 AI Agent 像人一样使用真实终端:输入文本、按键、点击、读取屏幕、截取屏幕截图。

Agent 打开 vim、粘贴程序、保存程序、运行程序并截取屏幕截图——每个步骤都标注了触发该步骤的工具调用

上方每一帧都由 terminal-use 自带的屏幕截图渲染器绘制;每帧上的说明文字都标明了生成该帧的工具调用。

大多数 Agent shell 工具都会运行命令并返回其输出。遇到任何交互式程序时,这种方式就行不通了——例如 vim、htop、REPL、会提问的安装程序、git rebase -i 或 SSH 会话。terminal-use 为 Agent 提供了运行在真实伪终端上的 shell,并由真正的终端模拟器渲染,因此全屏和交互式程序都能正常工作,Agent 看到的内容也与你看到的一样。

  • 真实的 PTY,真实的模拟器 — 颜色、光标移动和备用屏幕都会被解析,而不是作为转义码传递。
  • 文本与像素 — 可以将屏幕读取为纯文本,也可以在布局和颜色很重要时读取为 PNG。
  • 正确等待 — 阻塞等待命令实际完成,或等待特定文本出现。
  • 同步查看 — 将自己的终端连接到任意会话,与 Agent 并排输入。

快速开始

需要在 macOS、Linux 或 Windows 上使用 Node.js 22.12 或更高版本。

选择你的客户端:

客户端添加方法
Claude Codeclaude mcp add terminal-use --scope user -- npx -y terminal-use
Cursor添加到 Cursor
VS Code添加到 VS Code
Codexcodex mcp add terminal-use -- npx -y terminal-use
Gemini CLIgemini mcp add -s user terminal-use npx -y terminal-use

Claude Desktop 以及其他接受命令的客户端:将以下内容添加到其 MCP 配置中(对于 Claude Desktop:Settings → Developer → Edit Config)。

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

在客户端中新建会话,并让它在终端中执行某项操作,例如:"打开 vim,将一首俳句写入 /tmp/haiku.txt,保存并退出,然后给我看看运行 cat 显示该文件的屏幕截图。"

服务器选项写在命令之后:npx -y terminal-use --cols 100 --rows 40。

选项默认值
--shell <path>$SHELL 或 /bin/bash;Windows 上为 PowerShell在新会话中运行的 shell
--cwd <path>启动服务时所在的位置新会话的工作目录
--cols <n> / --rows <n>120 / 30终端大小
--scrollback <n>5000保留的历史行数
--login关闭将 shell 作为登录 shell 启动(见下文)
会话中出现“command not found”

如果你在自己的终端中可以使用的程序(node、brew、pyenv……)在会话中找不到,服务可能继承了一个精简环境。这种情况会发生在 MCP 客户端从 Dock 或启动器而非终端启动时:你的 PATH 由 shell 的配置文件(~/.zprofile、~/.bash_profile、~/.profile)设置,但这些文件并未被读取。

登录 shell 会读取这些文件。可以使用服务标志 --login 为每个会话启用登录 shell,也可以在 terminal_create 上设置 login: true,仅为一个会话启用。默认情况下此选项关闭,因为它会让每个 shell 启动得更慢,并运行配置文件中指定的所有内容。此选项对 PowerShell 或 cmd.exe 无效,因为它们没有登录模式。

工具

除 terminal_create 和 terminal_list 外,所有工具都需要使用 terminal_create 返回的 sessionId。

工具功能
terminal_create启动一个会话:交互式 shell,或通过 command 启动一个程序。可选参数:label、cols、rows、shell、cwd、env、login、scrollback、theme。
terminal_list列出会话。
terminal_destroy结束一个会话。
terminal_type输入文本。\n 表示按 Enter。paste: true 表示将文本作为一次粘贴发送。
terminal_press按下一个按键或组合键:Enter、Ctrl+C、ArrowUp、Shift+Tab、Alt+Enter、F5……
terminal_wait等待运行中的命令结束、出现符合正则表达式的内容,或输出停止。
terminal_read以文本形式读取屏幕或回滚缓冲区。
terminal_screenshot将屏幕渲染为 PNG。
terminal_click通过预览步骤左键单击一个单元格。
terminal_scroll在一个单元格上滚动鼠标滚轮。
terminal_batch在一次调用中发送多项输入,并获取一次屏幕内容。
terminal_resize更改终端大小。
terminal_reset清空屏幕和回滚缓冲区,或通过 hardReset: true 重启 shell。

Docker

仓库中有一个用于在容器中运行服务的 Dockerfile:

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

在 MCP 客户端中,将 docker 用作命令,并将 run -i --rm terminal-use 作为参数。Agent 使用的终端随后将是容器内的 shell,而不是你机器上的 shell:它只能看到你挂载的内容。如果你想将其限制在隔离环境中,这正是目的。在此设置中,无法从你自己的终端连接。

技能

terminal-use 附带一项 Agent 技能:一份简短指南,介绍 Agent 如何善用这些工具——何时使用命令会话、如何等待、如何读取选中的内容——还提供了 vim、分页器、REPL、菜单驱动程序、ssh 提示和 TUI 端到端测试的操作指南。它位于 skills/terminal-use。

  • 从 MCP 服务加载技能的宿主会自动获取该技能。服务实现了 MCP Skills 扩展(io.modelcontextprotocol/skills):该技能会列在 skills/list 中,其文件则以 skill://terminal-use/... 资源的形式提供。目前支持此功能的宿主很少。

  • 从磁盘加载技能的宿主可以安装相同的文件。对于 Claude Code:

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

技能是可选的。即使没有技能,Agent 仍可使用工具说明和服务内置指令。

Shell 会话和命令会话

默认情况下,会话是交互式 shell:像在提示符下那样输入命令。

向 terminal_create 传入 command,即可在终端中运行一个程序:

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

命令会通过会话的 shell 执行(sh -c、PowerShell -Command 或 cmd /c),因此引号、管道和重定向的行为与在该 shell 的提示符下一样。输入会直接传给程序。程序退出后:

  • 会报告其退出状态(通过正在进行的调用、terminal_wait 和 terminal_list);
  • 可通过 terminal_read 和 terminal_screenshot 读取最终屏幕;
  • 输入工具会返回包含退出状态的错误,而不会重启任何程序;
  • 使用 hardReset: true 调用 terminal_reset 会重新运行该程序,而 terminal_destroy 会将其移除。

此模式适用于测试 CLI 或 TUI:启动程序、与其交互,并检查其结束状态。

旁观并同步输入

terminal_create 会返回一条命令,你可以在自己的终端中运行它来加入会话:

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

你可以看到 Agent 看到的内容,并在同一个 shell 中输入内容。它的工作方式类似共享的 tmux 会话:多人可以同时连接,按 Ctrl+] 可断开连接。

  • 连接时会显示当前屏幕和近期的滚动内容,而不是空白终端。
  • --resize 会让会话跟随你的窗口大小。默认情况下,会话使用自己的大小。
  • --socket 用于选择服务。每个 MCP 客户端都有各自的 terminal-use 会话,并且都会从 1 开始为会话编号;如果不指定 --socket,只有当正在运行的服务中有一个服务拥有该 ID 时,attach <id> 才会生效,否则会列出候选项。
  • 在 Windows 上,会话通过命名管道而不是 socket 文件连接;提供给你的命令用法相同。
  • Socket 按用户隔离(0600,位于系统临时目录下的 0700 目录中)。任何能够连接的人都能以你的身份使用 shell,因此这些 socket 不会被进一步暴露。

工作原理

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

node-pty 会在伪终端上运行 shell。它输出的所有内容都会交给无头 xterm.js 模拟器处理,该模拟器的缓冲区是唯一真实来源:读取和截图都来自这里,因此 Agent 获取的是渲染后的屏幕,而不是转义码流。

详细信息

等待任务完成

terminal_type、terminal_press 和 terminal_click 会在输出短暂静止后返回(idleMs,默认为 200 ms),且等待时间不会超过 10 秒。这适合用于按键操作,但不适合构建任务,因为构建过程可能会在完成前长时间没有输出。对于任何耗时较长的操作,请继续调用 terminal_wait:

  • 默认模式——等待命令完成。 terminal-use 会询问内核哪个进程拥有终端前台。shell 会将终端交给它运行的每个命令,并在命令结束后取回终端,因此 shell 重新拥有终端时,提示符就会重新出现。此模式无需 shell 集成或解析提示符,并且适用于不输出内容的命令。
  • pattern——等待屏幕匹配正则表达式。 适用于不会退出的程序(Listening on port)、REPL 提示符,或 TUI 的特定状态。^ 和 $ 分别匹配行首和行尾;开头的 (?i) 或 (?s) 可设置其他标志。
  • until: "quiet"——等待输出停止,持续时间为 quietMs(默认为 1 s)。规则与输入工具使用的相同,但没有 10 秒上限。

在命令会话中,默认模式会等待程序退出,并报告其退出状态。

timeoutMs 默认为 30 秒(最长 10 分钟)。超时并不代表出错:响应会说明命令仍在运行,你可以再次等待。

在 Windows 上,无法查询哪个进程拥有终端,因此在 shell 会话中,默认模式会改为等待两秒无输出,并说明这只是估计。建议在此处使用 pattern,或将程序作为命令会话运行;命令会话在所有平台上都可以通过等待程序退出来实现等待。

需要注意的限制:后台任务(cmd &)不视为仍在运行。在 ssh 或 REPL 等嵌套程序中,外层 shell 要等该程序退出后才能重新获得前台,因此请在此类场景中使用 pattern 或 until: "quiet"。不会报告退出状态;请运行 echo $?。

阅读屏幕

terminal_read 按屏幕大小分页返回文本:page: 0 是当前屏幕,page: 1 是前一屏,以此类推,直到滚动缓冲区的开头。

终端在右侧边缘换行的文本会重新合并为程序输出的单行文本(joinWrapped: false 则每个屏幕行返回一行)。

文本无法显示颜色,因此无法显示当前选中的菜单项。因此,读取结果末尾会列出屏幕上所有高亮内容——反显或带背景色的文本,以及 terminal_click 所需的行和列:

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

如果屏幕大部分是彩色面板,列表会替换为指向 terminal_screenshot 的提示。使用 highlights: false 可关闭此功能。

光标以 ▌ 标记。在空白单元格中,它会直接替代空白。在字符上时,它会插入该字符前面,使该行剩余内容向右移动一列;标题会说明光标所在的字符。当程序隐藏光标时(大多数全屏程序都会这样做),不会显示此标记;cursor: false 则会原样返回文本。

屏幕截图

terminal_screenshot 使用捆绑的 JetBrains Mono 字体渲染屏幕。以下是一次调用的返回结果,其中 vim 中有一段文本被选中:

一张 vim 的 terminal_screenshot,显示 Python 语法高亮和四行选中文本

创建会话时可以指定 theme:dark(默认)、light、solarized-dark 或 solarized-light。

JetBrains Mono 支持拉丁字母、希腊字母、西里尔字母、制表符和常用符号。Emoji、中文/日文和韩文文本会回退到系统已有字体,因为捆绑这些字体会增加数十 MB 的体积:

EmojiCJK谚文
macOSApple Color EmojiHiragino Sans GB / PingFangApple SD Gothic Neo
WindowsSegoe UI EmojiMicrosoft YaHei / Yu GothicMalgun Gothic
LinuxNoto Color EmojiNoto Sans CJKNoto Sans CJK

macOS 默认自带这些字体;Windows 自带 Emoji 字体(东亚字体则随相应语言功能提供)。在 Debian 或 Ubuntu 上,可使用 apt install fonts-noto-color-emoji fonts-noto-cjk 安装这些字体。如果没有安装(例如使用精简的 Docker 镜像),这些字符在屏幕截图中会显示为空方框。Nerd Font 和 Powerline 图标在所有系统上都会显示为空方框。terminal_read 不受影响,始终会返回实际字符。

输入、粘贴和批处理

terminal_type 会将字符作为按键发送。要向编辑器、REPL 或 shell 提示符输入多行文本,请添加 paste: true:支持括号粘贴的程序会将其作为一次粘贴接收并原样插入,不会自动缩进,也不会在每行到达时立即运行。不支持的程序则会收到普通字符。

terminal_batch 会在一次调用中发送一组输入,并在最后返回一次屏幕内容。如果步骤已确定,这样可以减少每次按键所需的往返次数:

{
  "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"}
  ]
}

操作包括 type、paste、press、click、scroll 和 wait(等待固定的 ms 时长,或等待指定的 pattern 出现)。批处理会在发送任何内容前进行检查,并在第一个失败的操作处停止,同时报告已执行到哪一步。

点击和滚动
  • 仅支持左键。坐标从 1 开始;(1, 1) 是左上角单元格。
  • 默认开启 preview。 预览会返回一张截图,并在目标单元格周围画一个圆环,不会发送点击。将 preview: false 再调用一次即可点击。全屏程序通常只需点击一次就会触发破坏性操作,因此多这一步很值得。
  • terminal_scroll 会在某个单元格上滚动滚轮。会跟踪鼠标的程序会在该位置接收滚轮事件,因此指针下方的窗格会滚动;不跟踪鼠标的全屏程序(less、man)则会像普通终端一样接收方向键。在 shell 提示符处没有内容可滚动——使用 terminal_read 和 page 查看较早的输出。
  • 要进行实际点击,程序必须启用鼠标报告功能——vim 使用 set mouse=a 时,以及 fzf、lazygit、htop 和大多数现代 TUI 都支持。在普通 shell 提示符处调用会返回错误,而不会将转义码打印到命令行中。
会话生命周期
  • 会话彼此独立。对同一会话的调用按顺序执行;对不同会话的调用不会相互阻塞。
  • 如果 shell 会话中的 shell 退出、会话空闲六小时,或达到 50 个会话的上限,该会话就会关闭,但其 ID 会保留 30 天。下次调用该 ID 时,会启动一个新的 shell,沿用相同的尺寸、shell、工作目录和主题,并返回一条说明发生了什么的通知——如果旧 shell 是自行退出的,还会包含它最后打印的屏幕内容。该次调用中的命令不会运行;如果仍需要执行,请重新发送。
  • 空闲是指没有工具调用且没有输出。仍在输出内容的开发服务器不算空闲。
  • terminal_destroy 会彻底结束会话;其 ID 不会被保留。
  • MCP 客户端断开连接或服务停止时,所有 shell 都会关闭,所有 attach 套接字都会被移除。
协议支持

基于官方 MCP TypeScript SDK(v2)构建。通过 stdio 通信时,支持 2026-07-28 版无状态协议,也支持更早的、基于握手的版本;由客户端的第一条消息决定使用哪种版本。

无状态指的是协议,而不是终端:会话存放在服务进程中,并通过每次调用时传入的 sessionId 寻址。服务还会为每个工具提供用法说明、标题和行为提示,支持取消,并提供来自 terminal_wait 的进度更新,以及上文所述的 Skills 扩展。

平台支持

macOS(arm64、x64)支持;已在 CI 中测试
Linux(arm64、x64)支持;已在 Node 22 和 26 上通过 CI 测试
Windows(x64)支持;已在 CI 中针对 PowerShell 和 cmd.exe 测试

在 Windows 上,会话通过 ConPTY 运行,默认 shell 为 Windows PowerShell,并且有两处不同:terminal_wait 无法检测 shell 命令是否已完成(请参阅等待任务完成),而 login 不执行任何操作。

原生依赖(node-pty、@napi-rs/canvas)都附带预构建二进制文件,因此安装时无需编译器。

开发

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

其他脚本:

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)

若要让 MCP 客户端使用本地检出版本,请先构建,然后使用 bin 脚本的路径:

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

代码按层组织:src/pty(启动进程、按键和鼠标编码)、src/emulator(xterm 缓冲区、渲染、等待)、src/session(单个终端)、src/attach(用于连接的套接字)以及 src/mcp(工具)。Agent 技能位于 skills/。

安全

terminal-use 会在你的机器上以你的身份为已连接的客户端提供一个 shell,且没有沙箱。只将它连接到你愿意授予终端访问权限的客户端,并使用客户端的工具审批设置来控制哪些操作可以在未经提示的情况下运行。它不会开放网络端口;attach 套接字仅限你自己的用户访问。详情以及漏洞报告方式请参阅 SECURITY.md。

贡献

欢迎提交问题和拉取请求。CONTRIBUTING.md 介绍了环境配置、运行测试以及优质拉取请求的标准。本项目遵循 Contributor Covenant。

许可证

MIT。随附的 JetBrains Mono 字体采用 SIL Open Font License 许可。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。