返回市场
MCP-tmux服务器

MCP-tmux服务器

作者:Zdendys790 星标更新:2025-11-08

项目介绍

MCP Tmux Server

通用的MCP(模型上下文协议)服务器,用于双向tmux终端交互。

目的

使AI助手(如Claude Code)能够读取并可选地写入tmux终端面板,创建一个共享的终端会话视图。

✨ 新特性 (v1.1.0)

🔥 自然 \n → 回车键转换

自然书写命令!write_tmux_pane("ls\n") 自动按下回车键。

🛡️ 防止竞态条件

可选提示检测防止在用户输入时写入:

write_tmux_pane(session="work", text="ls\n", wait_for_prompt=True)

⏱️ 执行并等待

阻塞命令执行并自动完成检测:

execute_and_wait(session="work", command="git clone ...", timeout=30)
# 当提示符重新出现或超时时返回

📊 增强的面板信息

get_pane_info() 现在包括:

  • prompt_detected: Shell是否准备好接收输入?
  • command_running: 是否有命令正在执行?
  • last_line: 面板当前的最后一行

🔍 强制全读

获取面板的所有内容(而不仅仅是差异):

read_tmux_pane(session="work", force_full_read=True)

功能:

读取(默认,安全):

  • 捕获tmux面板的内容
  • 跟踪差异 - 返回自上次读取以来的新行
  • 内存中缓存内容,在读取后清除
  • 支持同时处理多个会话/窗口/面板
  • 新功能: 全读模式以捕获完整的面板内容

写入(可选,需要显式配置):

  • 向tmux面板发送文本/命令(就像打字一样)
  • 新功能: 自动 \n → 回车键转换
  • 新功能: 写入前可选提示检测
  • 可发送控制序列(Ctrl+C,回车键等)
  • 命令白名单支持
  • 新功能: 执行命令并等待完成

使用场景

  1. 监控长时间运行的过程 - AI可以从监控脚本中读取进度
  2. 交互式调试 - AI可以看到错误输出,并建议命令
  3. 共享终端视图 - 用户和AI看到相同的终端内容
  4. 自动化工作流 - AI可以根据终端输出执行命令

架构

┌─────────────────────────────────────────────┐
│  Claude Code (MCP 客户端)                   │
│  - 通过MCP读取终端缓冲区                    │
│  - 可选地发送命令                           │
└─────────────────┬───────────────────────────┘
                  │ JSON-RPC通过标准输入输出
┌─────────────────┴───────────────────────────┐
│  MCP Tmux Server (Python)                   │
│  - MCP协议处理器                            │
│  - 缓冲管理器(差异跟踪)                    │
│  - Tmux阅读器(捕获面板)                    │
└─────────────────┬───────────────────────────┘
                  │ tmux命令
┌─────────────────┴───────────────────────────┐
│  Tmux会话                                    │
│  - 用户的终端窗口                           │
│  - 共享视图:用户看到 + AI读取               │
└─────────────────────────────────────────────┘

MCP工具/方法

read_tmux_pane

描述: 从tmux面板读取自上次读取以来的新内容 参数:

  • session (字符串,必需) - tmux会话名称
  • window (整数,默认值:0) - 窗口索引
  • pane (整数,默认值:0) - 面板索引

返回:

{
  "target": "session:0.0",
  "new_lines": ["line1", "line2", ...],
  "total_lines": 150,
  "timestamp": "2025-10-15T16:30:00"
}

备注: 读取后清除缓冲区。仅返回自上次调用以来的新行。


get_tmux_sessions

描述: 列出所有活动的tmux会话 参数:

返回:

{
  "sessions": [
    {"name": "gm-robo", "windows": 3, "panes": 2},
    {"name": "monitoring", "windows": 1, "panes": 2}
  ],
  "count": 2
}

备注: 如果设置了allowed_sessions配置,则进行过滤。


get_pane_info

描述: 获取特定面板的详细信息 参数:

  • session (字符串,必需)
  • window (整数,默认值:0)
  • pane (整数,默认值:0)

返回:

{
  "target": "session:0.0",
  "width": 120,
  "height": 40,
  "current_command": "./monitor_diarization.sh",
  "active": true
}

clear_buffer

描述: 手动清除面板的缓冲区 参数:

  • target (字符串,可选) - 特定目标,如"session:0.0",或省略以清除所有

返回:

{"cleared": "session:0.0"}

get_server_info

描述: 获取服务器版本和功能 参数:

返回:

{
  "version": "1.0.0",
  "write_enabled": false,
  "tmux_available": true,
  "config_path": "/home/user/.config/mcp-tmux/config.json",
  "buffer_count": 3
}

write_tmux_pane (可选,需要write_enabled: true)

描述: 向tmux面板发送文本(就像打字一样) 参数:

  • session (字符串,必需)
  • window (整数,默认值:0)
  • pane (整数,默认值:0)
  • text (字符串,必需) - 要发送的文本(使用\n表示回车键)

返回:

{
  "target": "session:0.0",
  "sent": "ls -la\n",
  "timestamp": "2025-10-15T16:30:00"
}

安全性: 需要在配置中设置write_enabled: true。建议使用命令白名单。


send_keys_tmux (可选,需要write_enabled: true)

描述: 向tmux面板发送特殊键/键盘快捷键 参数:

  • session (字符串,必需)
  • window (整数,默认值:0)
  • pane (整数,默认值:0)
  • key (字符串,必需) - 特殊键或键组合

支持的键:

  • 控制键: C-c (Ctrl+C),C-u (清除行),C-kC-wC-aC-eC-lC-dC-z
  • 特殊键: EnterEscapeTabBSpace (退格),Space
  • 方向键: UpDownLeftRight
  • 功能键: F1F12

返回:

{
  "target": "session:0.0",
  "key": "C-u",
  "timestamp": "2025-10-15T16:30:00"
}

示例:

# 清除当前命令行
send_keys_tmux(session="work", key="C-u")

# 中断正在运行的过程
send_keys_tmux(session="work", key="C-c")

# 清屏
send_keys_tmux(session="work", key="C-l")

# 导航历史记录
send_keys_tmux(session="work", key="Up")

安全性: 需要在配置中设置write_enabled: true

安装

# 在~/workplace克隆/创建
cd ~/workplace/mcp-tmux-server

# 安装依赖项
pip install -r requirements.txt

# 运行服务器(JSON-RPC通过标准输入输出)
python3 src/mcp_server.py

配置

位置: ~/.config/mcp-tmux/config.json

默认配置(自动创建):

{
  "version": "1.0.0",
  "write_enabled": false,
  "allowed_sessions": [],
  "buffer_size": 1000,
  "auth_token": null
}

选项:

  • write_enabled (布尔值) - 启用写入功能(默认值:false)
  • allowed_sessions (数组) - 会话名称白名单(空 = 允许所有)
  • buffer_size (整数) - 每个面板缓冲区的最大行数
  • auth_token (字符串) - 写操作的身份验证令牌

带有安全性的示例:

{
  "version": "1.0.0",
  "write_enabled": true,
  "allowed_sessions": ["gm-robo-monitor", "diarization"],
  "buffer_size": 2000,
  "auth_token": "your-secret-token-here"
}

使用示例

设置(用户)

# 开始tmux会话用于监控
tmux new -s gm-robo-monitor

# 运行你的程序
./monitor_diarization.sh

# 在另一个终端启动MCP服务器
cd ~/workplace/mcp-tmux-server
python3 src/mcp_server.py

Claude Code集成

添加到Claude Code的MCP配置(~/.config/claude-code/mcp.json):

{
  "mcpServers": {
    "tmux": {
      "command": "python3",
      "args": ["/home/zdendys/workplace/mcp-tmux-server/src/mcp_server.py"]
    }
  }
}

从Claude Code使用

用户: "监控中发生了什么?"
Claude: [调用read_tmux_pane(session="gm-robo-monitor")]
        "Worker 0 正在处理 dummy_2024-02-20_session_1.m4a 的95%"

安全注意事项

  1. 默认只读 - 写入必须明确启用
  2. 会话白名单 - 限制哪些tmux会话可以访问
  3. 身份验证 - 写操作的可选令牌
  4. 无shell注入 - 所有tmux命令都使用子进程且参数为数组
  5. 缓冲区限制 - 防止因大量输出导致内存溢出
  6. 用户控制 - 用户明确启动服务器(不会自动启动)

开发

文件结构

mcp-tmux-server/
├── src/
│   ├── mcp_server.py       # 主MCP协议处理器
│   ├── tmux_reader.py      # Tmux命令包装器
│   ├── buffer_manager.py   # 差异跟踪和缓冲区管理
│   └── __init__.py
├── config/
│   └── example_config.json # 示例配置
├── tests/
│   ├── test_tmux_reader.py
│   ├── test_buffer_manager.py
│   └── test_mcp_protocol.py
├── docs/
│   └── API.md              # 详细的API文档
├── README.md               # 本文件
├── CLAUDE.md               # Claude Code在此项目上的规则
├── requirements.txt        # Python依赖项
└── setup.py               # 安装脚本

依赖项

  • Python 3.8+
  • tmux(系统上已安装)
  • 不需要外部Python包(仅使用标准库)

测试

自动化测试(尚未实现):

# 运行所有测试
python3 -m pytest tests/ -v

# 运行特定测试
python3 -m pytest tests/test_buffer_manager.py -v

# 包含覆盖率
python3 -m pytest tests/ --cov=src --cov-report=html

手动测试检查清单:

  1. 创建测试tmux会话:tmux new -s test
  2. 启动服务器:python3 src/mcp_server.py
  3. 通过标准输入发送测试请求:
    echo '{"jsonrpc":"2.0","id":1,"method":"get_server_info","params":{}}' | python3 src/mcp_server.py
    
  4. 验证JSON-RPC响应格式
  5. 测试错误处理(无效参数,缺少会话)
  6. 测试缓冲区差异跟踪:
    • 读取面板:echo '{"jsonrpc":"2.0","id":2,"method":"read_tmux_pane","params":{"session":"test"}}' | python3 src/mcp_server.py
    • 在tmux面板中输入一些内容
    • 再次读取 - 应该仅返回新行
  7. 测试多个面板/窗口
  8. 检查标准错误中的错误

代码架构

类职责

MCPTmuxServer (mcp_server.py)

  • 主MCP协议处理器(JSON-RPC 2.0)
  • 加载和验证配置
  • 会话白名单强制执行
  • 分派请求给TmuxReader和BufferManager
  • 标准输入输出循环(逐行读取标准输入,写入标准输出)

TmuxReader (tmux_reader.py)

  • 包装所有tmux子进程调用
  • 方法:capture_pane()list_sessions()get_pane_info()send_keys()
  • 强制执行超时(默认5秒)
  • 从不使用shell=True(安全性 - 总是数组参数)
  • 返回解析的数据结构(而不是原始字符串)

BufferManager (buffer_manager.py)

  • 跟踪每个面板的缓冲区(由"session:window.pane"标识)
  • 实现差异算法:_find_new_lines()
  • 仅返回自上次读取以来的新行
  • 强制执行最大行数限制(默认1000)
  • 处理边缘情况:滚动,换行,清屏

数据流

用户在tmux面板中输入
    ↓
AI调用read_tmux_pane(session="foo")
    ↓
MCPTmuxServer._read_tmux_pane()
    ↓
TmuxReader.capture_pane("foo:0.0") → List[str]
    ↓
BufferManager.get_new_lines("foo:0.0", current_lines)
    ├─ 与存储的缓冲区比较
    ├─ 查找新行(差异算法)
    └─ 更新缓冲区以反映当前状态
    ↓
仅返回新行给AI

差异算法

问题: 终端输出滚动和换行。如何找到仅有的新行?

解决方案(BufferManager._find_new_lines):

  1. 简单追加情况: 如果旧内容是新内容的前缀 → 返回后缀
  2. 滚动情况: 查找最长公共后缀 → 新行在那之后
  3. 清屏: 如果新内容少于旧内容 → 返回所有新内容

示例 - 简单追加:

旧缓冲区:["line1", "line2", "line3"]
新内容:["line1", "line2", "line3", "line4", "line5"]
结果:["line4", "line5"]  # 仅返回新行

示例 - 滚动:

旧缓冲区:["line1", "line2", "line3"]  # 终端显示最后3行中的50行
新内容:["line2", "line3", "line4"]  # 向上滚动,line1消失
结果:["line4"]  # 查找公共后缀(line2,line3),返回其后的内容

MCP协议细节

通信: 标准输入输出(标准输入/标准输出) 格式: JSON-RPC 2.0(每行一个请求)

请求格式:

{"jsonrpc":"2.0","id":1,"method":"read_tmux_pane","params":{"session":"foo"}}

成功响应:

{"jsonrpc":"2.0","id":1,"result":{"target":"foo:0.0","new_lines":["..."]}}

错误响应:

{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"未找到会话"}}

重要事项:

  • 服务器按行逐行读取标准输入,在阻塞循环中
  • 每一行必须是一个完整的JSON对象
  • 服务器将响应写入标准输出
  • 调试/信息消息发送到标准错误

JSON-RPC错误码:

  • -32700 解析错误
  • -32600 无效请求
  • -32601 方法未找到
  • -32602 无效参数
  • -32603 内部错误
  • -32000 自定义错误(未找到tmux,未找到会话等)

错误处理

所有tmux操作优雅地处理错误:

  • 未安装tmux → 显示清晰消息的RuntimeError
  • 会话不存在 → JSON-RPC错误 -32