终端管理服务

一个通过MCP协议暴露终端(PTY)管理API的轻量级服务,支持创建、管理和交互式操作本地PTY终端。

  • by JoshuaWink
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 JoshuaWink/terminal-mcp-server

使用说明

终端-MCP服务器

一个小型的FastMCP服务器,通过MCP暴露终端(PTY)管理API。

此热修复程序中的新增内容概要

  • 增加了支持创建具有特定工作目录的终端的功能cwd)。
  • terminal_create 现在始终返回结构化的JSON:{"terminalId":..., "cwd":...}。
  • terminal_send 当被调用且未指定时,将创建一个终端 terminalId 并返回包含已创建终端信息的JSON cwd。
  • terminal_list 现在包含了每个PTY的(信息/数据/情况等) cwd。
  • 修复了推荐的virtualenv安装问题,并使示例更加清晰。

特点/功能

  • 从MCP客户端创建并管理本地PTY支持的终端。
  • 非阻塞发送/读取终端输出。
  • 中断(Ctrl-C)、清除、释放终端,并列出活动的伪终端(PTY)。

可用工具(概要)

  • terminal_create(name?, cwd?) 创建一个伪终端(PTY)并返回JSON对象 {terminalId, cwd}
  • terminal_send(terminalId?, text) -> 向PTY发送文本;如果 terminalId 省略了PTY的创建并将其作为JSON返回
  • terminal_read(terminalId, {strip_ansi:true, lines:N}) 读取缓冲输出
  • terminal_interrupt(terminalId) -> 发送 Ctrl-C
  • terminal_clear(terminalId) -> 清除缓冲区
  • terminal_dispose(terminalId) 终止并清理
  • terminal_list() -> 列出已知的伪终端(PTYs)(包括 cwd 现在
  • terminal_events({terminalId?, since_ts?, limit?, types?}) -> 获取最近的结构化事件(创建、命令、标准输出、清除、中断、处置)

生活质量(详细/元响应) 您可以通过包含其中一个标志来选择接收结构化的回复指导 verbose: true, meta: true或者 return_meta: true 在……里面 payload 论点;争论点 你传递给一个工具。这会保持默认(最小)响应不变,对于 现有客户端,而受益于提示的代理可以请求更丰富的JSON数据。

示例

创建(详细模式):

{
	"terminalId": "[mcp] bright-otter",
	"cwd": "/Users/me",
	"created": true,
	"hint": "Use terminal_send to run commands, then terminal_read to fetch output.",
	"next": ["terminal_send", "terminal_read", "terminal_list"]
}

发送(自动生成 + 详细信息):

{
	"terminalId": "[mcp] bright-otter",
	"status": "created",
	"cwd": "/Users/me",
	"hint": "Use terminal_read to fetch output.",
	"next": ["terminal_read", "terminal_clear", "terminal_interrupt"]
}

发送(现有终端,详细模式):

{
	"terminalId": "[mcp] bright-otter",
	"status": "sent",
	"bytes": 15,
	"hint": "Call terminal_read to view buffered output."
}

读取(详细模式,非空):

{
	"output": "HELLO_WORLD\n",
	"lines": 1,
	"terminalId": "[mcp] bright-otter",
	"empty": false,
	"hint": "Use lines parameter to tail recent output."
}

读取(详细模式,空缓冲区):

{
	"output": "",
	"lines": 0,
	"terminalId": "[mcp] bright-otter",
	"empty": true,
	"hint": "Buffer empty. Use terminal_send to execute a command."
}

错误(详细发送时未提供文本):

{
	"error": "text required",
	"hint": "Provide shell input in the \"text\" parameter."
}

这些新增功能是向后兼容的:省略这些标志即可保留原有功能 简洁的字符串/纯文本输出响应。

事件流与内省

服务器维护一个内存中的环形缓冲区(大小为2000),用于存储最近的事件 同时,也写入到一个以换行符分隔的 JSON 日志中,位于 .terminal-mcp/events.log (可以 使用...禁用 TERMINAL_MCP_EVENT_LOG_ENABLED=0)。

事件类型:

  • create – 终端已创建
  • cmd – 一条命令被编写(在输出出现之前)
  • stdout – 捕获了一段终端输出
  • clear – 缓冲区通过工具清除
  • interrupt – 发送了 Ctrl-C
  • dispose – 已安装终端(现包括 exitCode (如有可用时)

使用 terminal_events 用于投票的工具:

// Example payload
{
	"terminalId": "[mcp] bright-otter",
	"since_ts": "2025-09-28T12:34:56.789Z",
	"limit": 100,
	"types": ["cmd", "stdout"]
}

回答:

{
	"events": [
		{"terminalId": "[mcp] bright-otter", "type": "cmd", "text": "echo hi", "ts": "..."},
		{"terminalId": "[mcp] bright-otter", "type": "stdout", "text": "hi\n", "ts": "..."}
	],
	"count": 2
}

现在,当启用详细输出时,Dispose 方法会返回退出代码:

{
	"terminalId": "[mcp] bright-otter",
	"disposed": true,
	"exitCode": 0
}

快速入门

  1. 创建一个虚拟环境并安装依赖项:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
  1. 运行服务器(在此文件夹中):
python server.py
  1. 使用FastMCP客户端或MCP检查器来调用上述工具。

测试 运行测试套件以验证功能:

# Run smoke test (basic functionality)
python test_smoke.py

# Run comprehensive test suite
python -m pytest test_terminal.py -v

# Run all tests
python -m pytest -v

测试套件涵盖:

  • 终端的创建和销毁
  • 命令执行和输出读取
  • 缓冲区管理(清除、读取选项)
  • 中断功能
  • 多终端管理
  • 错误处理

使用示例

  • 在仓库目录中创建一个终端,并检查返回的JSON数据:
# payload example sent to the MCP server
payload = {"name": "repo-pty", "cwd": "/path/to/repo"}
# server returns: {"terminalId": "repo-pty", "cwd": "/path/to/repo"}
  • 发送时不提供显式的terminalId(服务器将创建一个并返回JSON):
# calling terminal_send with only text
# returns: {"terminalId": "mcp-terminal-...,", "status": "created", "cwd": "/home/user"}
  • 读取输出(默认去除ANSI序列):
# terminal_read(terminalId, {"strip_ansi": True, "lines": 200})

示例 mcp.json 片段;碎片 在您的MCP客户端配置中使用此代码片段,以便检查器或客户端知道如何通过标准输入输出(stdio)在本地运行此服务器:

{
	"servers": {
		"terminal-mcp": {
			"command": "/path/to/your/venv/bin/python",
			"args": ["/path/to/terminal-mcp-server/server.py"],
			"type": "stdio",
			"description": "MCP stdio server exposing terminal commands",
			"dev": { "watch": "/path/to/terminal-mcp-server/app/**/*.py" }
		}
	}
}
## Adding This Server To `mcp.json` (Expanded Guide)

Below are several common configuration patterns you can paste into your client-side `mcp.json` (used by MCP Inspector, compatible agents, or orchestration layers). Adjust paths to match your system.

### 1. Local Clone + Virtualenv (Recommended for Development)
Clone the repository and create a virtual environment in the project root:

```bash
git clone https://github.com/your-org/terminal-mcp-server.git
cd terminal-mcp-server
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Then point `mcp.json` at the python executable and `server.py`:

```jsonc
{
	"servers": {
		"terminal-mcp": {
			"command": "/absolute/path/to/terminal-mcp-server/.venv/bin/python",
			"args": ["/absolute/path/to/terminal-mcp-server/server.py"],
			"type": "stdio",
			"description": "Local terminal management MCP server (dev virtualenv)",
			"dev": { "watch": "/absolute/path/to/terminal-mcp-server/app/**/*.py" }
		}
	}
}
```

Tip: Run `pwd` inside the repo to copy the absolute path; then append `/.venv/bin/python` and `/server.py` accordingly.

### 2. Editable Install in a Shared Environment
If this repo is part of a monorepo or shared dev environment you may prefer an editable install:

```bash
pip install -e /absolute/path/to/terminal-mcp-server
```

Then you can invoke using module-style execution (optional). Update `mcp.json`:

```jsonc
{
	"servers": {
		"terminal-mcp": {
			"command": "/path/to/python",
			"args": ["/absolute/path/to/terminal-mcp-server/server.py"],
			"type": "stdio",
			"description": "Terminal MCP (editable install)"
		}
	}
}
```

### 3. Windows (PowerShell) Example
Paths differ and the virtualenv python lives under `Scripts`:

```jsonc
{
	"servers": {
		"terminal-mcp": {
			"command": "C:/path/to/terminal-mcp-server/.venv/Scripts/python.exe",
			"args": ["C:/path/to/terminal-mcp-server/server.py"],
			"type": "stdio",
			"description": "Terminal MCP on Windows"
		}
	}
}
```

### 4. Using `uv` (Fast Python Installer)
If you prefer `uv` for environment management (https://github.com/astral-sh/uv):

```bash
uv venv .venv
source .venv/bin/activate
uv pip install -r requirements.txt
```

Then the `mcp.json` is the same as (1) – just ensure you still reference the venv Python path.

### 5. Multiple Terminal Servers (Namespacing)
You can register more than one server (e.g. one for local machine and one for a remote wrapper) by adding multiple entries under `servers`:

```jsonc
{
	"servers": {
		"terminal-local": { "command": "/local/venv/bin/python", "args": ["/local/terminal-mcp/server.py"], "type": "stdio" },
		"terminal-alt":   { "command": "/alt/venv/bin/python",   "args": ["/alt/terminal-mcp/server.py"],   "type": "stdio" }
	}
}
```

### 6. Environment Variables (Optional)
You can influence runtime behavior via environment variables in future expansions or by wrapping the command. For event log control today:

| Variable | Purpose | Default |
|----------|---------|---------|
| `TERMINAL_MCP_EVENT_LOG_ENABLED` | Enable/disable persistent event log | `1` |
| `TERMINAL_MCP_EVENT_DIR` | Custom directory for the event log | `.terminal-mcp/` under repo |
| `TERMINAL_MCP_EVENT_LOG` | Override full path to event log file | `<EVENT_DIR>/events.log` |

If your MCP host supports per-server environment injection you may extend the `servers.terminal-mcp` object with an `env` field (syntax depends on the host). Example (conceptual):

```jsonc
{
	"servers": {
		"terminal-mcp": {
			"command": "/venv/bin/python",
			"args": ["/repo/server.py"],
			"type": "stdio",
			"env": {
				"TERMINAL_MCP_EVENT_LOG_ENABLED": "0"
			}
		}
	}
}
```

### 7. Verifying Setup
After editing `mcp.json`, restart your MCP-enabled client / inspector and look for a server named "terminal-mcp" (or the name you chose). List tools; you should see:

```
terminal_create, terminal_send, runCommand, terminal_read, terminal_interrupt, terminal_clear, terminal_dispose, terminal_list, terminal_events
```

Run a quick sanity cycle:
1. Call `terminal_create` (optionally with `{ "payload": { "verbose": true } }`).
2. Call `terminal_send` with a simple command (e.g. `echo hello`).
3. Call `terminal_read` to confirm output buffering.
4. Poll `terminal_events` to observe `create`, `cmd`, and `stdout` entries.
5. Call `terminal_dispose` (verbose) to verify `exitCode` appears.

### 8. Troubleshooting
| Symptom | Likely Cause | Fix |
|---------|--------------|-----|
| No tools appear | Wrong path to python or server file | Verify absolute paths in `command` and `args` |
| Empty output after send | Command still running / buffering | Add a short sleep then `terminal_read`; or run simpler command |
| Missing events | Pagination cursor set too high | Remove `after` or lower it; check `oldestSeq/newestSeq` in response |
| Permission error launching | CWD or python not accessible | Use a directory you own; ensure executable bit | 

If issues persist, run the server manually (`python server.py`) and observe stderr/stdout for import or runtime errors.

---

This section aims to make integration copy/paste friendly. If you use a different MCP host that requires a slightly different schema, adapt the key names but keep the `command`, `args`, and `type: stdio` trio intact.

备注

  • cwd 在支持的环境中启动shell时,会显示荣誉信息;如果平台不接受 cwd 对于Popen调用,服务器仍会存储所请求的(数据/信息) cwd 并返回它(外壳程序可能会在默认目录中启动)。
  • 默认情况下,读取操作是非破坏性的;调用 terminal_clear 清空缓冲区。
  • 这台服务器特意仅暴露与终端相关的工具,以便它可以单独包含或部署,而无需依赖于更大的MCP服务器。

关键词:终端、伪终端(pty)、MCP(可能是指某种特定的控制或管理程序)、FastMCP(一种快速的MCP或类似功能的程序)、shell(命令行解释器)、远程shell、终端-MCP(终端与MCP的结合或特定功能)