docs: redesign Phase 9 Serial MCP as GUI-owned port + named pipe bridge
GUI holds the COM port exclusively; ETTerms.SerialMcp becomes a thin client that bridges over a local named pipe (SerialBridgeServer). AI TX/RX flows through the GUI channel so it is visible live in the terminal view. Tools change from open/close to attach/detach.
This commit is contained in:
+56
-33
@@ -32,7 +32,7 @@ ETTerms 是一個給工程師 / 韌體 / 硬體驗證人員用的**單一視窗
|
||||
| 祕密儲存 | **Windows Credential Manager**(DPAPI / CredMan) | 連線密碼、SSH key passphrase,不落地明碼 |
|
||||
| PDU 控制(選用) | **SnmpSharpNet** | 沿用 MyTeraTerm PDU 控制(`pductrl` / `pduconnect`) |
|
||||
| 日誌 | 自製 **AppLogger**(從 MyTeraTerm 移植) | 檔案 + Debug 雙輸出 |
|
||||
| AI / MCP 整合(選用) | **stdio MCP server**(官方 C# SDK `ModelContextProtocol`) | 獨立行程把 serial port 暴露成 AI 可呼叫工具(Kiro CLI / Claude CLI),見 [AI / MCP Integration](#ai--mcp-integrationserial-mcp-server) |
|
||||
| AI / MCP 整合(選用) | **stdio MCP server**(官方 C# SDK `ModelContextProtocol`) | 獨立行程,但不自己開 port——經本機 named pipe 橋接到 GUI 持有的 serial session,把收發暴露成 AI 可呼叫工具(Kiro CLI / Claude CLI),見 [AI / MCP Integration](#ai--mcp-integrationserial-mcp-server) |
|
||||
| 打包 | `dotnet publish` + (選用)Inno Setup / MSIX | 單機安裝,current-user |
|
||||
|
||||
> **與舊版 MyTeraTerm 的關鍵差異:** 舊版是把真正的 `ttermpro.exe`(TeraTerm)嵌進 Panel,靠 **com0com 虛擬 COM 對**攔截 serial 來跑腳本。ETTerms 改走**全原生**:SSH.NET 做 SSH、`System.IO.Ports` 做 serial、自繪 VT100 控制項做終端機畫面,**不再依賴外部 TeraTerm exe,也不再需要 com0com**。腳本引擎從「驅動 com0com bridge」改成「驅動原生 `ISessionChannel`」。
|
||||
@@ -141,7 +141,8 @@ ETTerms/
|
||||
│ ├── SerialChannel.cs # System.IO.Ports 實作
|
||||
│ ├── ShellChannel.cs # Windows ConPTY 本機 Shell
|
||||
│ ├── SessionPage.cs # 一個分頁 = TerminalView + Channel + 狀態
|
||||
│ └── SessionManager.cs # 開 / 關 / 列舉所有 active session
|
||||
│ ├── SessionManager.cs # 開 / 關 / 列舉所有 active session
|
||||
│ └── SerialBridgeServer.cs# 🔜 本機 named pipe server:把 serial session 的讀寫橋接給 MCP(Phase 9)
|
||||
│
|
||||
├── Connections/ # ── 連線資料 ──
|
||||
│ ├── Connection.cs # 連線 metadata 模型
|
||||
@@ -160,9 +161,10 @@ ETTerms/
|
||||
├── AppSettings.cs # 使用者偏好 (JSON, %LocalAppData%\ETTerms\settings.json)
|
||||
└── NativeTheme.cs # 深色標題列 (DWM)
|
||||
│
|
||||
└── ETTerms.SerialMcp/ # 🔜 Serial MCP server(stdio,給 AI agent 直接操作 serial)
|
||||
└── ETTerms.SerialMcp/ # 🔜 Serial MCP server(stdio)——不自己開 port,經 named pipe 橋接 GUI
|
||||
├── Program.cs # stdio MCP host 進入點
|
||||
├── SerialTools.cs # serial_list / open / write / read / close 工具
|
||||
├── SerialBridgeClient.cs # 連 GUI 的 named pipe,轉發 write / 接收 RX
|
||||
├── SerialTools.cs # serial_list / attach / write / read / detach 工具(轉發到 pipe)
|
||||
└── ETTerms.SerialMcp.csproj# net8.0 console + ModelContextProtocol SDK
|
||||
```
|
||||
|
||||
@@ -354,40 +356,59 @@ ScriptRunner.RunAsync(scriptText, activeChannel)
|
||||
|
||||
## AI / MCP Integration(Serial MCP Server)
|
||||
|
||||
> 讓 **Kiro CLI / Claude CLI** 等 AI agent 直接對 serial port 下指令、讀輸出。ETTerms 額外提供一支獨立的 **stdio MCP server**(`src/ETTerms.SerialMcp/`),把 serial port 包成 AI 可呼叫的工具。它與 WinForms 主程式**各自獨立行程**:由 MCP client(Kiro CLI / Claude CLI)啟動並維持整個 session 存活,因此能**持續持有 COM port**——連線狀態可跨多次工具呼叫保留,也能接收裝置主動推送的非同步輸出。
|
||||
> 讓 **Kiro CLI / Claude CLI** 等 AI agent 收發 serial,**且使用者能在 ETTerms GUI 即時看到 AI 的每筆收發**。
|
||||
>
|
||||
> **關鍵設計:COM port 由 GUI 唯一持有,MCP server 不自己開 port。** 一個 COM port 同一時間只能被一個行程開啟;若讓 MCP server 自己開,GUI 就無法同時開、使用者也看不到。因此改成 **GUI 當 port 的唯一擁有者**,在 GUI 內跑一支本機 **named pipe server**(`SerialBridgeServer`);獨立的 `ETTerms.SerialMcp`(由 Kiro/Claude CLI 啟動)退化成**瘦客戶端**,所有 `write` / `read` 都經 pipe 轉發給 GUI,由 GUI 代為讀寫實體 port。
|
||||
|
||||
**為何要獨立常駐行程?** CLI agent 的每條 shell 指令都是一個新行程,`open→write→read` 無法跨呼叫保留狀態(port 一關就斷)。常駐的 MCP server 才能維持一條連線、累積 RX。
|
||||
### 全閉迴路(推薦用法)
|
||||
|
||||
整個迴路可全部跑在 ETTerms GUI 內,使用者一邊看、AI 一邊操作:
|
||||
|
||||
```
|
||||
┌── Kiro CLI / Claude CLI (MCP client) ──┐
|
||||
│ AI 呼叫工具:serial_open / write... │
|
||||
└───────────────┬─────────────────────────┘
|
||||
│ stdio (JSON-RPC 2.0)
|
||||
┌───────────────┴─────────────────────────┐
|
||||
│ ETTerms.SerialMcp (常駐行程) │
|
||||
│ 背景 reader 累積 RX → serial_read 取出 │
|
||||
│ │ System.IO.Ports.SerialPort │
|
||||
└────────┼─────────────────────────────────┘
|
||||
│ ← COM 互斥:與 GUI 不可同開同一 port →
|
||||
[ 實體 COM port / UART / 開發板 ]
|
||||
ETTerms GUI(單一行程,唯一開 COM3 的人)
|
||||
│
|
||||
├─ Tab1: Serial 連線 ── SerialChannel 實體持有 COM3
|
||||
│ TerminalView 即時顯示(AI 的 TX 以 [AI] 標色,RX 照常顯示)
|
||||
│
|
||||
├─ SerialBridgeServer(本機 named pipe: \\.\pipe\etterms-serial)
|
||||
│ ▲ write 轉發 / RX 廣播
|
||||
│ │
|
||||
└─ Tab2: PowerShell (ConPTY) 跑 kiro-cli
|
||||
└─ kiro 啟動子行程 ETTerms.SerialMcp(stdio / JSON-RPC)
|
||||
└─ 不開 COM,連上面的 pipe → 收發都流經 GUI 的 channel
|
||||
```
|
||||
|
||||
**資料流:**
|
||||
- **AI 送資料:** `serial_write` → pipe → GUI `SerialChannel.Write()` 送出 COM3,**同時把這段 echo 進 Tab1 TerminalView(`[AI]` 標色)** → 使用者看得到 AI 打了什麼。
|
||||
- **裝置回資料:** COM3 RX → GUI 一邊顯示在 Tab1、一邊經 pipe 廣播 → `serial_read` 取出 → AI 讀到。
|
||||
|
||||
因為 RX/TX 物理上都流經 GUI 的 channel,**使用者在 GUI 看到的就是 AI 看到的**,完全同步。
|
||||
|
||||
### 暴露的工具
|
||||
|
||||
| 工具 | 參數 | 說明 |
|
||||
|------|------|------|
|
||||
| `serial_list` | — | 列出可用 COM port(`SerialPort.GetPortNames()`) |
|
||||
| `serial_open` | portName, baudRate, dataBits, parity, stopBits, handshake, newLine | 開啟並持有 port(啟動背景 reader 累積 RX) |
|
||||
| `serial_write` | text, appendNewLine? | 送出文字(可選附加換行) |
|
||||
| `serial_read` | waitFor?, timeoutMs? | 取出 RX 緩衝;可等待特定字串或逾時 |
|
||||
| `serial_close` | — | 關閉 port |
|
||||
| `serial_list` | — | 列出 **GUI 目前開著的 serial session**(名稱 + COM port + baud),供 AI 選定要操作哪一個 |
|
||||
| `serial_attach` | portName \| sessionName | 經 pipe 綁定到 GUI 某個已開啟的 serial session(之後 read/write 都對它) |
|
||||
| `serial_write` | text, appendNewLine? | 經 pipe 請 GUI 對綁定的 session 送出文字(GUI 同步 echo 到 TerminalView) |
|
||||
| `serial_read` | waitFor?, timeoutMs? | 取出該 session 累積的 RX;可等待特定字串或逾時 |
|
||||
| `serial_detach` | — | 解除綁定(**不關閉 GUI 的 port**,GUI 仍持有) |
|
||||
|
||||
> 與舊版規劃的差異:不再有「MCP 自己 `serial_open` / `serial_close` 實體 port」;改為 `serial_attach` / `serial_detach` 綁定 / 解除 GUI 既有 session。port 的開關一律在 GUI 操作。
|
||||
|
||||
### named pipe 協議(精簡)
|
||||
|
||||
- **傳輸:** Windows named pipe(`\\.\pipe\etterms-serial`),純本機、不開網路埠。
|
||||
- **訊息:** 換行分隔的 JSON,例:`{"op":"write","session":"COM3","data":"...","newline":true}` / `{"op":"read","session":"COM3","waitFor":"OK","timeoutMs":3000}` / `{"op":"list"}`。
|
||||
- **RX 推送:** GUI 主動把 RX 以 `{"op":"rx","session":"COM3","data":"..."}` 推給已連線的 client,client 端累積成 buffer 供 `serial_read` 消費。
|
||||
- **找不到 session:** AI `attach` / `write` 一個 GUI 沒開的 port 時,回明確錯誤(要求使用者先在 GUI 開啟)。
|
||||
|
||||
### 設計重點
|
||||
|
||||
- **技術:** .NET 8 console(`net8.0`,無 WinForms)+ 官方 C# MCP SDK(`ModelContextProtocol`),stdio / JSON-RPC 2.0。
|
||||
- **參數語意:** 直接用 `System.IO.Ports.SerialPort`,與主程式的 `SerialSettings` 同一組參數(PortName / BaudRate / DataBits / Parity / StopBits / Handshake / NewLine)。
|
||||
- **COM 互斥:** MCP server 開了某 port 時,ETTerms GUI 不可同時開同一 port(反之亦然)——一個 COM 同時只能被一個行程開啟。
|
||||
- **安全:** 本機、無雲、不碰 credential;僅操作硬體 serial。
|
||||
- **技術:** `ETTerms.SerialMcp` 為 .NET 8 console(`net8.0`,無 WinForms)+ 官方 C# MCP SDK(`ModelContextProtocol`),stdio / JSON-RPC;GUI 端的 `SerialBridgeServer` 用 `System.IO.Pipes`。
|
||||
- **port 擁有權單一化:** 實體 `SerialPort` 只有 GUI 開,根除「兩個行程搶同一 COM」的問題。
|
||||
- **可視性:** AI 的 TX 在 GUI 以 `[AI]` 標色,與使用者手打的輸入區分;RX 兩邊同源。
|
||||
- **安全:** 本機、無雲、不碰 credential;pipe 僅限本機行程,只搬 serial bytes。
|
||||
|
||||
### 註冊(Kiro CLI)
|
||||
|
||||
@@ -396,7 +417,7 @@ kiro-cli mcp add --name serial --command dotnet `
|
||||
--args "run --project src\ETTerms.SerialMcp\ETTerms.SerialMcp.csproj"
|
||||
```
|
||||
|
||||
或寫進 agent.json 的 `mcpServers`;Claude CLI 則用其對應的 `mcpServers` 設定。註冊後直接對 AI 說「列出 COM port、開 COM3 115200、送 AT 看回應」即可。
|
||||
或寫進 agent.json 的 `mcpServers`;Claude CLI 則用其對應的 `mcpServers` 設定。**使用前提:先在 ETTerms GUI 開好要操作的 serial 連線**,AI 才能 `serial_attach` 上去。註冊後即可對 AI 說「列出目前 serial session → 接上 COM3 → 送指令看回應」。
|
||||
|
||||
---
|
||||
|
||||
@@ -563,14 +584,16 @@ dotnet publish src\ETTerms\ETTerms.csproj -c Release -r win-x64 --self-contained
|
||||
- [ ] `dotnet publish` + Inno Setup / MSIX 安裝程式(待使用者指示)
|
||||
**驗收條件:** ✅ PDU 指令可用;Settings 重啟保留;Local Shell 行為正常(ConPTY);SFTP 可瀏覽遠端目錄。打包待後續。
|
||||
|
||||
### Phase 9 — AI 整合:Serial MCP Server(工作量:S)🔜 規劃中
|
||||
**目標:** 提供獨立 stdio MCP server,讓 Kiro CLI / Claude CLI 等 AI agent 直接對 serial port 下指令、讀輸出。
|
||||
### Phase 9 — AI 整合:Serial MCP Server(GUI 橋接模式)(工作量:M)🔜 規劃中
|
||||
**目標:** 讓 Kiro CLI / Claude CLI 等 AI agent 收發 serial,且**使用者能在 GUI 即時看到 AI 的收發**。COM port 由 GUI 唯一持有,MCP 經本機 named pipe 橋接(見 [AI / MCP Integration](#ai--mcp-integrationserial-mcp-server))。
|
||||
**包含:**
|
||||
- [ ] GUI:`Sessions/SerialBridgeServer.cs`——本機 named pipe server,暴露 list / attach / write / read,並把 serial session 的 RX 廣播給 client
|
||||
- [ ] GUI:TerminalView 支援把 MCP 來源的 TX 以 `[AI]` 標色 echo,使用者可區分 AI 與手打輸入
|
||||
- [ ] `src/ETTerms.SerialMcp/`:.NET 8 console + 官方 C# MCP SDK(`ModelContextProtocol`),stdio / JSON-RPC
|
||||
- [ ] 工具:`serial_list` / `serial_open` / `serial_write` / `serial_read`(含 `waitFor` + `timeout`)/ `serial_close`
|
||||
- [ ] 常駐持有 COM port + 背景 reader 累積 RX(跨呼叫保留狀態、可收 async 輸出)
|
||||
- [ ] 註冊說明(`kiro-cli mcp add` / agent.json `mcpServers`)寫入 README
|
||||
**驗收條件:** 在 Kiro CLI 註冊後,能透過 AI 對話「列 COM port → 開 COM3 115200 → 送指令 → 讀回應」完成一輪 serial 互動;同一 COM port 不與 GUI 同時開啟。
|
||||
- [ ] `SerialBridgeClient.cs`:連 GUI pipe、轉發 write、累積 RX
|
||||
- [ ] 工具:`serial_list` / `serial_attach` / `serial_write` / `serial_read`(含 `waitFor` + `timeoutMs`)/ `serial_detach`
|
||||
- [ ] 註冊說明(`kiro-cli mcp add` / agent.json `mcpServers`)寫入 README,含「需先在 GUI 開好 port」前提
|
||||
**驗收條件:** GUI 開一條 Serial(COM3)→ 另一分頁 PowerShell 跑 kiro → AI 經 MCP `serial_attach` COM3 → `serial_write` 送指令、`serial_read` 讀回應,**整個過程在 GUI Tab1 即時可見(AI 的 TX 有 `[AI]` 標色)**;全程只有 GUI 開該 port。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ ETTerms 是一個 **C# .NET 8 WinForms** 的原生 Windows 終端機工作台,
|
||||
|
||||
**開發策略:GUI 先行** — 先把視窗外殼 + 分頁 + 連線清單做出來,再逐步補 Serial → SSH → VT100 → 腳本引擎 → Settings/About → PDU/Shell/SFTP。
|
||||
|
||||
**進度:** Phase 1–5 ✅、Phase 6 ✅(TTL 引擎 + Group 同步,SSH 待驗收)、Phase 7 ✅(Settings/About)、Phase 8 ✅(PDU + Shell/ConPTY + SFTP + Settings 擴充)、Phase 9 🔜(Serial MCP server,讓 AI 直接操作 serial)。打包待指示。
|
||||
**進度:** Phase 1–5 ✅、Phase 6 ✅(TTL 引擎 + Group 同步,SSH 待驗收)、Phase 7 ✅(Settings/About)、Phase 8 ✅(PDU + Shell/ConPTY + SFTP + Settings 擴充)、Phase 9 🔜(Serial MCP server:**GUI 持有 COM port,MCP 經本機 named pipe 橋接**,AI 收發的資料即時顯示在 GUI)。打包待指示。
|
||||
|
||||
**v0.1.2:** 新增 `sprintf2`(TeraTerm 相容 C printf 格式化);`wait` 改為命中關鍵字後須等裝置安靜(`SettleMs` 預設 300ms)才接受並取「最後一次」出現,排除輸出中途的指令回顯(避免腳本搶跑)。
|
||||
|
||||
@@ -23,7 +23,7 @@ ETTerms 是一個 **C# .NET 8 WinForms** 的原生 Windows 終端機工作台,
|
||||
- **連線儲存:** SQLite(`Microsoft.Data.Sqlite`)
|
||||
- **密碼儲存:** Windows Credential Manager(不落地明碼)
|
||||
- **PDU:** SnmpSharpNet(iPoMan II/III via SNMP)
|
||||
- **AI / MCP(選用):** 獨立 stdio MCP server(`ETTerms.SerialMcp`,官方 C# SDK `ModelContextProtocol`)把 serial port 暴露給 Kiro CLI / Claude CLI
|
||||
- **AI / MCP(選用):** stdio MCP server(`ETTerms.SerialMcp`,官方 C# SDK `ModelContextProtocol`)。**不自己開 COM port**,而是經本機 named pipe 接上 GUI 持有的 serial session,把 serial 收發暴露給 Kiro CLI / Claude CLI;AI 的 TX/RX 同步顯示在 GUI
|
||||
- **設定持久化:** JSON → `%LocalAppData%\ETTerms\settings.json`
|
||||
|
||||
## 常用指令
|
||||
@@ -57,7 +57,7 @@ kiro-cli mcp add --name serial --command dotnet --args "run --project src\ETTerm
|
||||
- 🚫 **不嵌 TeraTerm、不依賴 com0com** —— ETTerms 走全原生(這是與舊版 MyTeraTerm 的關鍵差異)。
|
||||
- 🚫 不要把 `For_AI/` 內容 commit 進 git。
|
||||
- ⚠️ Serial COM port 同時只能被一個 session 開啟,開啟前檢查可用性。
|
||||
- ⚠️ Serial MCP server(`ETTerms.SerialMcp`)與 GUI **不可同時開同一個 COM port**;AI 操作該 port 前,先關掉 GUI 對它的連線(反之亦然)。
|
||||
- ⚠️ COM port 由 **GUI 唯一持有**;Serial MCP server(`ETTerms.SerialMcp`)**不自己開 port**,而是經本機 named pipe 接上 GUI 已開啟的 serial session 來收發。AI 操作前該 port 必須已在 GUI 開啟(pipe 找不到對應 session 就回錯誤)。
|
||||
- ⚠️ VT 相容性以常見情境(VT100 / 常見 ANSI)為主,冷門 escape 後補,不阻塞 GUI 進度。
|
||||
- ⚠️ 本專案**無伺服端祕密 / 無 DB 密碼 / 無 EC2 / 無 VM**,因此不套用 AWS / VirtualBox 部署流程。
|
||||
- ⚠️ Group 同步指令(`waitall` / `sendlnall` / `sendlngroup`)**只能在 Run Group 模式**使用;`▶ Script` 和 `▶ Run All` 須拒絕含這些指令的腳本。
|
||||
@@ -65,6 +65,6 @@ kiro-cli mcp add --name serial --command dotnet --args "run --project src\ETTerm
|
||||
## 資料夾用途
|
||||
|
||||
- **`src/ETTerms/`** — 主應用程式(WinForms 視窗外殼 + 連線 / 終端機 / 腳本引擎)。
|
||||
- **`src/ETTerms.SerialMcp/`** — 🔜 獨立 stdio MCP server(給 AI agent 直接操作 serial),與 WinForms 主程式各自獨立行程;net8.0 console + `ModelContextProtocol` SDK。
|
||||
- **`src/ETTerms.SerialMcp/`** — 🔜 stdio MCP server(給 AI agent 收發 serial)。獨立行程,但**不直接開 COM port**:經本機 named pipe 連到 GUI 的 `SerialBridgeServer`,由 GUI 代為讀寫實體 port;net8.0 console + `ModelContextProtocol` SDK。
|
||||
- **`For_AI/`** — AI 協作素材與**參考專案**(`KKTerm-main` UI 參考、`MyTeraTerm` Script 參考)。整個資料夾 gitignored,僅供開發對照。
|
||||
- 本專案**無 `secret/` 資料夾**:沒有伺服端祕密 / DB 密碼 / compile-time secret,連線密碼一律走 Windows Credential Manager。
|
||||
|
||||
Reference in New Issue
Block a user