内容
# 交互式终端 MCP
[](https://github.com/sairaph/interactive-terminal-mcp/releases)
[](https://github.com/sairaph/interactive-terminal-mcp/actions/workflows/ci.yml)
[](#license)
[](#what-it-does)
给任何 AI 代理一个**真正的终端** - 持久的 shell 会话,在工具调用之间保持运行,正确处理 `vim` 和 `htop`,并且您可以附加和实时查看 - 通过 **8 个 MCP 工具**,并提供一个通用的单命令安装程序,内置客户端检测和完整的 TUI。
macOS:
```bash
curl -fsSL https://github.com/sairaph/interactive-terminal-mcp/raw/main/install.sh | sh
```
Linux:
```bash
curl -fsSL https://github.com/sairaph/interactive-terminal-mcp/raw/main/install.sh | sh
```
Windows (PowerShell):
```powershell
irm https://github.com/sairaph/interactive-terminal-mcp/raw/main/install.ps1 | iex
```
安装程序会为您的操作系统/架构下载正确的二进制文件,将 `interactive-terminal-mcp` 添加到您的 `PATH` 中,然后打开一个交互式配置器:它会检测您的 AI 客户端,让您使用箭头键切换要连接的客户端,并询问要保留会话日志多长时间。您可以在任何时候运行 `interactive-terminal-mcp configure` 来更改已连接的内容。
> **在 Windows 上安装后,请打开一个新的 PowerShell 窗口。** 安装程序会将其自身添加到您的用户 `PATH` 中,但它运行的窗口保留了其启动时的 `PATH`,因此 `interactive-terminal-mcp` 在那里不可用。
## 功能
- **会话在调用结束后仍然存在** - 代理启动一个构建,做其他事情,然后返回。重启 AI 客户端不会杀死任何东西。
- **真正的终端仿真** - 完整的 VT,具有替代屏幕、滚动条和 DEC 模式,因此 `vim`、`less`、`htop` 和 `tmux` 的行为与在您自己的终端中相同,而不是近似值。
- **按键,而不仅仅是命令** - `"CTRL+C"`、` `"ESC; :wq; ENTER"`、` `"DOWN*5"`。箭头键编码为正在运行的程序所期望的,这就是为什么它们在 `vim` 内部工作,而不仅仅是在提示符下。
- **您可以观察** - 运行 `interactive-terminal-mcp` 并附加到代理使用的任何会话,实时输入。代理的终端访问是可见的,而不是发生在后台。
- **检测 13 个 AI 客户端** - Claude Desktop、Claude Code、Cursor、Codex、Gemini CLI、Windsurf、Zed、Cline、Roo Code、Amazon Q、Continue、OpenCode 和 VS Code - 并注册您选择的客户端。
- **单个静态二进制文件** - 一个 CGO-free Go 二进制文件,无需 Python、Node 或运行时依赖。Linux、macOS、Windows 支持 x64 和 arm64。
- **YAML 前面 + Markdown 输出** - 每个工具结果都是结构化和人类可读的,因此代理(和您)可以一目了然地扫描它。
- **不会静默截断** - 当响应达到其令牌预算时,回复会说明已删除多少行,并提供完整日志的绝对路径。
## 安装
**macOS / Linux** - 下载与您的操作系统/架构匹配的二进制文件到 `~/.interactive-terminal-mcp/bin` 并将其添加到您的 `PATH` 中:
```bash
curl -fsSL https://github.com/sairaph/interactive-terminal-mcp/raw/main/install.sh | sh
```
**Windows (PowerShell)** - 下载到 `%LOCALAPPDATA%\interactive-terminal-mcp` 并添加到您的用户 `PATH` 中:
```powershell
irm https://github.com/sairaph/interactive-terminal-mcp/raw/main/install.ps1 | iex
```
每个安装程序都会从最新的 [GitHub Release](https://github.com/sairaph/interactive-terminal-mcp/releases) 中选择适合您的操作系统/架构的资产。
**安装后打开一个新的终端。** 两个安装程序都会将其自身添加到您的 `PATH` 中,但 shell 仅在启动时读取 `PATH`,因此您从安装窗口无法找到该命令。要在同一个窗口中立即使用它,请使用完整路径运行二进制文件:
```powershell
& "$env:LOCALAPPDATA\interactive-terminal-mcp\interactive-terminal-mcp.exe"
```
```bash
~/.interactive-terminal-mcp/bin/interactive-terminal-mcp
```
## 工具
所有 **7 个工具** 都对持久终端会话进行操作。每个会话操作工具都使用其 ID(`t-k3f9qa`)或您为其指定的名称(`build`)。
### 会话
| 工具 | 描述 |
| --- | --- |
| `it_list` | 列出所有会话,包括正在运行和最近结束的会话,按最新活动时间排序 |
| `it_new` | 创建一个会话并返回其第一个屏幕,以及其他工具所需的 ID |
| `it_kill` | 结束一个会话(**需要**显式会话;绝不会被推断) |
### 使用会话
| 工具 | 描述 |
| --- | --- |
| `it_read` | 返回一个会话的当前屏幕,可选地调整大小 |
| `it_send` | 输入文本和/或按键,然后返回屏幕 |
| `it_tail` | 最近的日志行和实时屏幕 |
| `it_head` | 最早的日志行 |
典型的代理流程:
```js
it_list({}) // 会话已经打开吗?
it_new({"name": "dev"}) // 没有 - 创建一个
it_send({"session": "dev", "text": "npm run dev", "wait": 10})
it_read({"session": "dev"}) // 稍后检查
it_tail({"session": "dev", "lines": 50}) // 滚动过去的内容?
it_kill({"session": "dev"}) // 完成
```
### 按键
`it_send` 的 `keys` 参数采用分号分隔的和弦:
| 形式 | 示例 |
| --- | --- |
| 命名键 | `ENTER` `TAB` `ESC` `HOME` `END` `PAGE_UP` `UP` `F1`-`F20` |
| 修饰符 | `CTRL+C` `ALT+X` `SHIFT+TAB` 和组合键 |
| 重复 | `DOWN*5` |
| 原始文本 | `"hello world"` 或未加引号的运行,如 `:wq` |
```js
it_send({"keys": "i; \"hello from vim\"; ESC"})
it_send({"keys": "ESC; :wq; ENTER"})
it_send({"keys": "CTRL+B; PAGE_UP"})
```
箭头键和 Home/End 根据运行程序实际设置的模式编码,因此它们在 `vim` 和 `less` 中表现正确,而不是仅在 shell 提示符下。
### 等待是上限,不是睡眠
`wait` 是调用等待输出稳定所需的最大时间。一旦输出安静下来,它就会立即返回,因此 `wait: 30` 对于 `echo hi` 来说是毫秒级,而对于缓慢的构建仍然正确。当预算用完时,输出仍在继续,结果会显示 `settled: false` 并告诉代理再次查看 - 它永远不会悄悄地返回半绘制的屏幕。
`bash` 会话启动时会带有一个小的 shell 集成脚本,因此 shell 本身会报告每个命令的开始和结束以及状态。这提供了 `command_exit`,即在会话**内**运行命令的退出代码,并使 `busy` 成为一个报告,而不是推断。 它首先加载您的配置,并且永远不会替换您的提示;如果它失败,shell 会正常启动,工具会恢复。`shell_integration = false` 会关闭它。
如果没有它,静默输出是三个完成信号中最弱的,因为打印 nothing 的命令从开始时就静默了。`busy` 更强:它来自终端自己的前台进程组,而不是计时,因此 `busy: true` 是命令仍在运行的证据,而 `busy: false` 是没有命令的强烈证据。`wait_for` 是精确的 - 调用在给定文本出现时结束,命令的回声被折扣,因此 `it_send({"text": "make && echo BUILT", "wait_for": "BUILT"})` 在输出上结束,而不是在命令行上。
### 全屏程序
使用替代屏幕的程序的输出永远不会滚动,因此它能正确地从日志中消失。 这就是为什么 `it_tail` 默认返回实时屏幕和日志,并正确标记两者:
````markdown
~~~text
CC src/parser.o
make: *** [Makefile:42: all] Error 1
~~~
显示了请求的 138 个日志行中的最后 500 行(1842 个日志行)。为了适应响应预算,省略了 362 个较旧的行。完整的日志位于
`~/.interactive-terminal-mcp/sessions/t-k3f9qa/transcript.log`。
````
## 交互式应用
在终端中无参数运行 `interactive-terminal-mcp`:
```
╭─ interactive-terminal-mcp ──────────────────────────────────────────────╮
│ │
│ > + 新会话 │
│ │
│ ● build t-k3f9qa running 160x48 3s ago 1842 lines │
│ ● dev-server t-w81mza running 160x48 1m ago 412 lines │
│ ○ (unnamed) t-p2m8wd exit 0 160x48 26m ago 96 lines │
│ │
╰──────────────────────────────────────────────────────────────────────────╯
↑↓ navigate · enter open · n new · backspace delete · r rename
c configure · q quit
```
按 Enter 打开一个会话到一个框架终端。它表现得像一个正常的终端,具有几个附加功能:
- **一个合成器** 在框架下用于输入命令:`shift+enter` 用于换行,`↑` 用于历史记录,`ctrl+v` 用于粘贴,`tab` 用于 shell 补全。它在您输入时增长,并在窗口高度的 80% 处开始滚动。
- **自动原始模式** - 当程序使用替代屏幕时,每个按键直接发送到它,因此 `vim` 和 `htop` 直接工作。`ctrl+g` 手动切换,对于不使用替代屏幕的程序。
- **滚动条** 使用 `shift+pgup` / `shift+pgdn` 或鼠标滚轮。
- `ctrl+q` 返回列表。退出应用程序会使每个会话继续运行。
删除会先询问,并显示您将失去的内容:
```
删除会话 "build"(t-k3f9qa)?
它仍然正在运行:make -j8
其日志将被立即删除(保留:会话关闭时)。
> 取消
删除
```
从列表中按 `c` 进入与安装程序相同的设置屏幕:注册、终端大小、响应预算、日志保留、滚动条、会话限制。`d` 恢复推荐的默认值,并在显示实际更改的值后。
## 命令行界面
每个操作也是一个一次性命令:
| 命令 | 功能 |
| --- | --- |
| `ls` | 列出会话 |
| `new [name] [--cmd C]` | 创建会话(`--cwd`、`--cols`、`--rows`、`--wait`) |
| `attach <session>` | 在此终端中打开会话 |
| `read [session]` | 打印会话的屏幕(`--wait`) |
| `send [session] --text T` | 输入到会话(`--no-enter`、`--wait`) |
| `send [session] --keys K` | 发送按键 |
| `tail [session] [-n N]` | 最近的输出 |
| `head [session] [-n N]` | 最早的输出 |
| `rename <session> <name>` | 重命名会话 |
| `kill <session>` | 结束会话(`--signal TERM\|INT\|HUP\|KILL`) |
| `status` | 守护进程状态 |
| `doctor` | 诊断安装 |
| `config` | 显示设置及其路径 |
`kill` 需要一个会话,原因与 `it_kill` 相同:终止错误的终端是不可逆的。
## 工作原理
会话必须比创建它们的进程存在得更久,因此 PTY 由一个小型**守护进程**拥有。每个 MCP 服务器、CLI 命令和应用程序本身都是一个薄客户端,通过本地套接字与之交互。
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Claude Code │ │ Cursor │ │ 你(TUI) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
└──────────────────┼──────────────────┘
┌──────▼───────┐
│ 守护进程 │ 拥有 PTY、模拟器、日志
└──────┬───────┘
┌───────────┼───────────┐
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│ pty 1 │ │ pty 2 │ │ pty 3 │
└───────┘ └───────┘ └───────┘
```
它在第一次使用时自动启动,并在 60 秒内没有会话和客户端时退出。您永远不会启动或管理它,但 `interactive-terminal-mcp status` 和 `doctor` 会告诉你关于它的信息。
### 信任模型
这是一个本地工具,使用您的权限运行。`it_send` 可以运行您可以运行的任何命令:没有白名单,没有沙盒,也没有命令过滤。 这是功能 - 它是您的控制台,由您的代理访问。 通过 AI 客户端自己的权限系统控制代理可以执行的操作。
## 文档
- [`docs/tool-contract.md`](docs/tool-contract.md) - 完整的代理端合同:每个参数、每个前置字段、每个错误代码
- [`docs/app-design.md`](docs/app-design.md) - 交互式应用程序
- [`docs/implementation-plan.md`](docs/implementation-plan.md) - 架构、其背后的推理以及构建过程中的更改
## 从源代码构建
需要 [Go 1.26+](https://go.dev/dl/):
```bash
git clone https://github.com/sairaph/interactive-terminal-mcp.git
cd interactive-terminal-mcp
go test ./...
go build -o interactive-terminal-mcp .
./interactive-terminal-mcp configure
```
使用 `CGO_ENABLED=0` 交叉编译所有六个目标:
```bash
for t in linux-amd64 linux-arm64 darwin-amd64 darwin-arm64 windows-amd64 windows-arm64; do
CGO_ENABLED=0 GOOS="${t%-*}" GOARCH="${t#*-}" go build -ldflags="-s -w" -o "interactive-terminal-mcp-$t" .
done
```
发布会自动生成:增加 `VERSION` 中的版本并合并到 `main`,然后 `autorelease` 工作流标签 `v<version>` 并为所有六个目标发布二进制文件。每个 CI 作业都运行一次竞争检测器,而不仅仅是在发布时。
## 许可证
MIT。版权 © 2026 [Łael Al-Halawani](mailto:laelhalawani@gmail.com)。