Skip to main content
Glama
masx200

Persistent Terminal MCP Server

by masx200
WEB_UI_FEATURE.md11.1 kB
# Web UI Feature - Terminal Management Interface ## 📋 需求概述 为 Persistent Terminal MCP Server 添加一个 Web 前端管理界面,通过浏览器可视化管理所有终端会话。 ### 背景 - 当前项目只有 MCP 工具和 REST API 接口 - 缺少直观的可视化管理界面 - 需要一个友好的 UI 来查看和操作终端 ### 目标 - 添加一个 MCP 工具 `open_terminal_ui`,调用时自动打开 Web 管理界面 - 支持多个 AI 实例同时运行(动态端口分配) - 零破坏性修改,不影响现有功能 --- ## 🎯 功能需求 ### 1. MCP 工具:`open_terminal_ui` **功能描述**: - 启动 Web 服务器并在浏览器中打开管理界面 - 自动查找可用端口(避免冲突) - 可选择是否自动打开浏览器 **参数**: - `port` (可选): 指定端口,默认从 3002 开始自动查找 - `autoOpen` (可选): 是否自动打开浏览器,默认 true **返回**: - Web 服务器 URL - 实际使用的端口 - 启动模式(新建/已存在) ### 2. Web 前端功能 #### 2.1 终端列表页面 (`/`) - 显示所有活跃终端的卡片列表 - 每个终端显示: - Terminal ID(可复制) - PID、Shell 类型、工作目录 - 创建时间、最后活动时间 - 状态(active/inactive/terminated) - 操作按钮: - 创建新终端 - 查看终端详情 - 终止终端 #### 2.2 终端详情页面 (`/terminal/:id`) - 使用 xterm.js 渲染终端输出 - 支持 ANSI 颜色和转义序列 - 实时显示终端输出(WebSocket) - 输入框发送命令 - 操作按钮: - 清空输出 - 终止终端 - 返回列表 #### 2.3 实时更新 - WebSocket 推送终端输出 - 终端状态变化实时反映 - 新终端创建自动显示 --- ## 🏗️ 技术方案 ### 架构设计 ``` MCP Client (Claude/Cursor/GPT) ↓ 调用 open_terminal_ui PersistentTerminalMcpServer ↓ 创建 WebUIManager ↓ 启动 WebUIServer (Express + WebSocket) ↓ 服务 Browser (HTML + JS + xterm.js) ``` ### 端口冲突解决方案 **问题**:多个 AI 实例同时运行会导致端口冲突 **解决方案**:动态端口分配 - 从指定端口(默认 3002)开始 - 自动检测端口是否可用 - 如果被占用,尝试下一个端口(最多尝试 100 个) - 每个 MCP 实例使用独立端口 ### 文件结构 ``` src/ ├── web-ui-manager.ts # Web UI 管理器(新增) ├── web-ui-server.ts # Web 服务器(新增) ├── mcp-server.ts # 添加 open_terminal_ui 工具(修改) └── types.ts # 添加新类型定义(扩展) public/ # 前端静态文件(新增) ├── index.html # 终端列表页面 ├── terminal.html # 终端详情页面 ├── app.js # 列表页面逻辑 ├── terminal.js # 详情页面逻辑 └── styles.css # 样式文件 ``` ### 技术栈 **后端**: - Express.js - Web 服务器 - ws - WebSocket 支持 - 复用现有的 TerminalManager **前端**: - 原生 HTML + CSS + JavaScript(无构建步骤) - xterm.js - 终端渲染(CDN) - WebSocket API - 实时通信 --- ## 🔧 实现细节 ### 1. 动态端口分配 ```typescript async findAvailablePort(startPort: number): Promise<number> { // 使用 net 模块检测端口可用性 // 从 startPort 开始,尝试最多 100 个端口 // 返回第一个可用端口 } ``` ### 2. 浏览器自动打开 ```typescript async openBrowser(url: string): Promise<void> { // 跨平台支持: // - macOS: open // - Windows: start // - Linux: xdg-open } ``` ### 3. WebSocket 实时推送 ```typescript // 监听 TerminalManager 事件 terminalManager.on("terminalOutput", (terminalId, data) => { broadcast({ type: "output", terminalId, data }); }); terminalManager.on("terminalExit", (terminalId) => { broadcast({ type: "exit", terminalId }); }); ``` ### 4. REST API 复用 - 直接使用现有的 `RestApiServer` 逻辑 - 避免代码重复 - 保持 API 一致性 --- ## 📝 修改清单 ### 需要修改的现有文件 #### `src/mcp-server.ts`(3 处修改) **修改 1**:添加 WebUIManager 属性 ```typescript private webUiManager: WebUIManager; ``` **修改 2**:在构造函数中初始化 ```typescript this.webUiManager = new WebUIManager(); ``` **修改 3**:在 setupTools() 中添加新工具 ```typescript this.server.tool('open_terminal_ui', ...); ``` **修改 4**:在 shutdown() 中清理 ```typescript await this.webUiManager.stop(); ``` ### 需要新增的文件 1. `src/web-ui-manager.ts` - Web UI 管理器 2. `src/web-ui-server.ts` - Web 服务器 3. `public/index.html` - 列表页面 4. `public/terminal.html` - 详情页面 5. `public/app.js` - 列表逻辑 6. `public/terminal.js` - 详情逻辑 7. `public/styles.css` - 样式 ### 需要安装的依赖 ```bash npm install ws npm install --save-dev @types/ws ``` --- ## ✅ 测试计划 ### 单元测试 - [ ] 端口分配逻辑测试 - [ ] WebUIManager 生命周期测试 - [ ] 浏览器打开功能测试 ### 集成测试 - [ ] MCP 工具调用测试 - [ ] Web 服务器启动测试 - [ ] WebSocket 连接测试 - [ ] 终端列表显示测试 - [ ] 终端详情显示测试 - [ ] 实时输出推送测试 ### 手动测试场景 1. **单实例测试**: - 启动 MCP 服务器 - 调用 `open_terminal_ui` - 验证浏览器自动打开 - 验证终端列表显示 2. **多实例测试**: - 启动多个 MCP 实例(Claude + Cursor) - 分别调用 `open_terminal_ui` - 验证端口不冲突 - 验证每个实例独立管理终端 3. **功能测试**: - 创建新终端 - 发送命令 - 查看实时输出 - 终止终端 - 验证 WebSocket 实时更新 --- ## 🚀 实施进度 ### Phase 1: 核心功能(MVP)✅ 已完成 - [x] 安装依赖(ws, @types/ws) - [x] 创建 `web-ui-manager.ts` - [x] 创建 `web-ui-server.ts` - [x] 修改 `mcp-server.ts`(添加 open_terminal_ui 工具) - [x] 创建基础前端页面(index.html, terminal.html) - [x] 测试端口分配(动态端口 3002-3101) - [x] 测试浏览器打开(跨平台支持) ### Phase 2: UI 实现 ✅ 已完成 - [x] 实现终端列表页面(app.js) - [x] 实现终端详情页面(terminal.js) - [x] 集成 xterm.js(CDN 方式) - [x] 实现 WebSocket 通信(实时推送) - [x] 测试完整流程(创建、查看、操作终端) ### Phase 3: 优化与文档 ⏳ 进行中 - [x] 错误处理优化 - [x] UI 样式美化(VS Code 风格) - [ ] 添加使用文档 - [ ] 更新 README --- ## ⚠️ 风险与缓解 | 风险 | 影响 | 缓解措施 | 状态 | | -------------------- | ---- | -------------------- | --------- | | 修改现有代码引入 bug | 中 | 只添加代码,充分测试 | ✅ 已验证 | | 端口冲突 | 低 | 动态端口分配 | ✅ 已实现 | | WebSocket 连接失败 | 低 | 友好错误提示 | ✅ 已实现 | | 浏览器打开失败 | 低 | 返回 URL 手动打开 | ✅ 已实现 | --- ## 📚 参考资料 - [xterm.js 文档](https://xtermjs.org/) - [WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) - [Express.js 文档](https://expressjs.com/) - [ws 库文档](https://github.com/websockets/ws) --- ## 📅 更新日志 ### 2025-10-07 #### 阶段 1: 需求分析与设计 ✅ - ✅ 创建需求文档 - ✅ 分析端口冲突问题 - ✅ 设计技术方案 - ✅ 规划文件结构 #### 阶段 2: 后端实现 ✅ - ✅ 安装依赖(ws, @types/ws) - ✅ 创建 `src/web-ui-manager.ts`(端口管理、浏览器打开) - ✅ 创建 `src/web-ui-server.ts`(Express + WebSocket) - ✅ 修改 `src/mcp-server.ts`(添加 open_terminal_ui 工具) - ✅ 扩展 `src/types.ts`(添加 Web UI 类型) - ✅ 修复 TypeScript 编译错误 #### 阶段 3: 前端实现 ✅ - ✅ 创建 `public/index.html`(终端列表页面) - ✅ 创建 `public/terminal.html`(终端详情页面) - ✅ 创建 `public/app.js`(列表页面逻辑) - ✅ 创建 `public/terminal.js`(详情页面逻辑 + xterm.js) - ✅ 创建 `public/styles.css`(VS Code 风格样式) #### 阶段 4: 测试验证 ✅ - ✅ 创建测试脚本 `src/examples/test-web-ui.ts` - ✅ 添加 npm 脚本 `test:webui` 和 `example:webui` - ✅ 编译成功(npm run build) - ✅ 功能测试通过: - ✅ Web 服务器启动成功(端口 3002) - ✅ 浏览器自动打开 - ✅ REST API 正常工作 - ✅ 前端页面可访问 - ✅ 终端列表显示正常 - ✅ 创建测试终端成功 #### 测试结果 📊 ``` ✅ Web UI started successfully! 📊 Details: URL: http://localhost:3002 Port: 3002 Mode: new Browser opened: Yes ✅ API 测试通过: GET /api/terminals - 返回 2 个终端 ✅ 前端测试通过: GET / - 返回 index.html ``` --- **当前状态**: � 已完成(MVP) **负责人**: AI Assistant **完成时间**: 2025-10-07 ## 🎉 功能已实现 ### 已实现的功能 1. ✅ **MCP 工具**: `open_terminal_ui` - 启动 Web UI 2. ✅ **动态端口分配**: 自动查找可用端口(3002-3101) 3. ✅ **浏览器自动打开**: 跨平台支持(macOS/Windows/Linux) 4. ✅ **终端列表页面**: 显示所有终端、状态、统计信息 5. ✅ **终端详情页面**: xterm.js 渲染、实时输出、命令输入 6. ✅ **WebSocket 实时推送**: 终端输出实时更新 7. ✅ **REST API**: 完整的终端管理接口 8. ✅ **响应式 UI**: VS Code 风格的暗色主题 ### 使用方法 #### 方法 1: 通过 MCP 工具(推荐) 在 Claude Desktop 或其他 MCP 客户端中调用: ``` 使用 open_terminal_ui 工具打开终端管理界面 ``` #### 方法 2: 直接运行测试脚本 ```bash npm run test:webui # 或 npm run example:webui ``` #### 方法 3: 在代码中使用 ```typescript import { WebUIManager } from "./web-ui-manager.js"; import { TerminalManager } from "./terminal-manager.js"; const terminalManager = new TerminalManager(); const webUiManager = new WebUIManager(); const result = await webUiManager.start({ port: 3002, autoOpen: true, terminalManager, }); console.log(`Web UI: ${result.url}`); ``` ### Bug 修复记录 #### 2025-10-07 - 终端详情页面加载问题 **问题**: 终端详情页面一直显示 "Loading...",无法加载终端信息 **原因**: `terminal.html` 中使用了相对路径引用 CSS 和 JS 文件,导致在 `/terminal/:id` 路径下加载失败 **解决方案**: - 将 `styles.css` 改为 `/styles.css`(绝对路径) - 将 `terminal.js?v=2` 改为 `/terminal.js?v=3`(绝对路径) **测试**: 使用 Playwright 验证所有功能正常工作 ### 下一步计划 - [x] 修复终端详情页面加载问题 - [ ] 添加截图到文档 - [ ] 考虑添加更多功能(搜索、过滤、批量操作等)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/masx200/persistent-terminal-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server