feat(pdu): add PDU MCP server for AI-driven SNMP power control
New ETTerms.PduMcp stdio MCP server lets AI agents (Kiro/Claude CLI) control SNMP PDU outlets directly. Unlike serial, SNMP is non-exclusive so it talks to the PDU directly without bridging through the GUI. Tools: pdu_connect / pdu_list / pdu_set_port / pdu_get_port / pdu_status / pdu_power_cycle / pdu_disconnect. - McpRegistrar now registers both etterms-serial and etterms-pdu in one click - Settings -> AI MCP shows both server paths - publish target (PublishMcpServers) bundles both MCP servers - bump version to 0.3.0, update About changelog, ARCHITECTURE.md, CLAUDE.md
This commit is contained in:
+49
-10
@@ -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`) | 獨立行程,但不自己開 port——經本機 named pipe 橋接到 GUI 持有的 serial session,把收發暴露成 AI 可呼叫工具(Kiro CLI / Claude CLI),見 [AI / MCP Integration](#ai--mcp-integrationserial-mcp-server) |
|
||||
| AI / MCP 整合(選用) | **stdio MCP server**(官方 C# SDK `ModelContextProtocol`) | 兩個獨立 server:`ETTerms.SerialMcp`(不自己開 port,經本機 named pipe 橋接 GUI 持有的 serial session)與 `ETTerms.PduMcp`(直接打 SNMP 控制 PDU 插座,不需 GUI);把收發 / 電源控制暴露成 AI 可呼叫工具(Kiro CLI / Claude CLI),見 [AI / MCP Integration](#ai--mcp-integrationserial-mcp--pdu-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`」。
|
||||
@@ -356,7 +356,16 @@ ScriptRunner.RunAsync(scriptText, activeChannel)
|
||||
|
||||
---
|
||||
|
||||
## AI / MCP Integration(Serial MCP Server)
|
||||
## AI / MCP Integration(Serial MCP + PDU MCP Server)
|
||||
|
||||
ETTerms 提供**兩個獨立的 stdio MCP server**給 AI agent(Kiro CLI / Claude CLI):
|
||||
|
||||
- **`ETTerms.SerialMcp`** — 收發 serial。COM port 獨佔,故由 GUI 唯一持有、MCP 經本機 named pipe 橋接(見下方)。
|
||||
- **`ETTerms.PduMcp`** — 控制 SNMP PDU 電源插座。SNMP(UDP) 非獨佔,故 MCP **直接打 SNMP**,不需 GUI 在跑、也不經 pipe。
|
||||
|
||||
兩者都能用 GUI **Settings → AI MCP** 一鍵 Setup(`McpRegistrar` 會同時註冊 `etterms-serial` 與 `etterms-pdu`)。
|
||||
|
||||
### Serial MCP Server
|
||||
|
||||
> 讓 **Kiro CLI / Claude CLI** 等 AI agent 收發 serial,**且使用者能在 ETTerms GUI 即時看到 AI 的每筆收發**。
|
||||
>
|
||||
@@ -425,6 +434,33 @@ kiro-cli mcp add --name serial --command dotnet `
|
||||
|
||||
或寫進 agent.json 的 `mcpServers`;Claude CLI 則用其對應的 `mcpServers` 設定。**使用前提:先在 ETTerms GUI 開好要操作的 serial 連線**,AI 才能 `serial_attach` 上去。註冊後即可對 AI 說「列出目前 serial session → 接上 COM3 → 送指令看回應」。
|
||||
|
||||
### PDU MCP Server(v0.3.0)
|
||||
|
||||
> 讓 AI agent 直接控制 SNMP PDU 的電源插座,**典型用途:測試中自動 power-cycle DUT**。
|
||||
|
||||
**關鍵設計:直接打 SNMP,不經 GUI 橋接。** 與 serial 不同,PDU 走 SNMP(UDP)**非獨佔**——多個行程可同時對同一台 PDU 下命令。因此 `ETTerms.PduMcp` 不需要像 serial 那樣繞 GUI 的 named pipe,而是內含一份精簡版 `PduController`(OID 邏輯複製自 GUI 的 `Scripting/Pdu/PduController`,診斷改走 stderr 以免污染 stdio JSON-RPC)直接與 PDU 對話。**好處:GUI 不必開著,AI 也能控制 PDU;最少程式碼、最穩。**
|
||||
|
||||
```
|
||||
Kiro/Claude CLI ── 啟動子行程 ETTerms.PduMcp(stdio / JSON-RPC)
|
||||
└─ SnmpSharpNet ──(SNMP/UDP 161)──► PDU(iPoMan II/III)
|
||||
```
|
||||
|
||||
連線狀態(device IP → controller)以行程內單例 `PduRegistry` 保存,跨工具呼叫保留,直到 `pdu_disconnect` 或行程結束。
|
||||
|
||||
**暴露的工具:**
|
||||
|
||||
| 工具 | 參數 | 說明 |
|
||||
|------|------|------|
|
||||
| `pdu_connect` | ip | 以 SNMP 連線並驗證 PDU 回應,成功回傳 model name;控制前必須先呼叫 |
|
||||
| `pdu_list` | — | 列出本 session 已連線的 PDU(依 IP) |
|
||||
| `pdu_set_port` | ip, port, on | 將某插座開(on=true)/關(off=false) |
|
||||
| `pdu_get_port` | ip, port | 讀單一插座的狀態 / 電流(mA) / 功率(W) |
|
||||
| `pdu_status` | ip | 讀全部 12 個插座的狀態 / 電流 / 功率 |
|
||||
| `pdu_power_cycle` | ip, port, offSeconds? | 關 → 等 offSeconds → 開(重啟 DUT) |
|
||||
| `pdu_disconnect` | ip | 解除本 session 的 PDU 連線(不改變插座狀態) |
|
||||
|
||||
> 所有工具回傳統一的 `{ "ok": bool, "result"/"error": ... }` JSON。SNMP community 目前沿用 GUI 版的 `"private"`。
|
||||
|
||||
---
|
||||
|
||||
## Key Constraints & Business Rules
|
||||
@@ -504,17 +540,20 @@ dotnet publish src\ETTerms\ETTerms.csproj -c Release -r win-x64 --self-contained
|
||||
|
||||
**內容結構:**
|
||||
```
|
||||
ETTerms_v0.2.0\
|
||||
├── ETTerms v0.2.0.exe # 主程式 apphost,改名為「ETTerms v{Version}.exe」
|
||||
ETTerms_v0.3.0\
|
||||
├── ETTerms v0.3.0.exe # 主程式 apphost,改名為「ETTerms v{Version}.exe」
|
||||
├── ETTerms.dll + 各相依 dll # SSH.NET / SQLite / SnmpSharpNet / System.IO.Ports …
|
||||
└── ETTerms.SerialMcp\ # Serial MCP server,獨立發佈到子資料夾(相依 dll 與 GUI 隔離)
|
||||
├── ETTerms.SerialMcp.exe
|
||||
└── ETTerms.SerialMcp.dll + 相依
|
||||
├── ETTerms.SerialMcp\ # Serial MCP server,獨立發佈到子資料夾(相依 dll 與 GUI 隔離)
|
||||
│ ├── ETTerms.SerialMcp.exe
|
||||
│ └── ETTerms.SerialMcp.dll + 相依
|
||||
└── ETTerms.PduMcp\ # PDU MCP server(v0.3.0),同樣獨立發佈到子資料夾
|
||||
├── ETTerms.PduMcp.exe
|
||||
└── ETTerms.PduMcp.dll + 相依(含 SnmpSharpNet)
|
||||
```
|
||||
|
||||
**規則:**
|
||||
1. **GUI publish 會自動帶上 MCP**:`ETTerms.csproj` 有 `PublishSerialMcp` target(`AfterTargets="Publish"`),會把 `ETTerms.SerialMcp` 一併發佈到 `<publish>\ETTerms.SerialMcp\` **子資料夾**(與 GUI 相依 dll 隔離)。因此**只要發佈 GUI 一個指令**即可,不必再單獨發 MCP。
|
||||
- 對齊 `McpRegistrar.ResolveServerExe()`:它解析的 `<ETTerms.exe>\ETTerms.SerialMcp\ETTerms.SerialMcp.exe` 因此**必定存在**,AI MCP 一鍵設定寫進去的路徑才不會落空。
|
||||
1. **GUI publish 會自動帶上兩個 MCP server**:`ETTerms.csproj` 有 `PublishMcpServers` target(`AfterTargets="Publish"`),會把 `ETTerms.SerialMcp` 與 `ETTerms.PduMcp` 一併發佈到各自的 `<publish>\<server>\` **子資料夾**(與 GUI 相依 dll 隔離)。因此**只要發佈 GUI 一個指令**即可,不必再單獨發 MCP。
|
||||
- 對齊 `McpRegistrar.ResolveServerExe()`:它解析的 `<ETTerms.exe>\<server>\<server>.exe` 因此**必定存在**,AI MCP 一鍵設定寫進去的路徑才不會落空。
|
||||
- MCP 子發佈會**跟隨 GUI 的 `SelfContained` 設定**(target 內以 `$(SelfContained)` 傳入):框架相依版的 MCP 也框架相依;portable 版的 MCP 也免 runtime。
|
||||
2. **主 exe 改名**:`dotnet publish` 產生的 `ETTerms.exe` 重新命名為 **`ETTerms v{Version}.exe`**。
|
||||
- 可安全改名:.NET apphost 內部記錄要載入的 `ETTerms.dll`,**不靠自身檔名**,改名後仍正常啟動。
|
||||
@@ -545,7 +584,7 @@ dotnet publish src\ETTerms\ETTerms.csproj -c Release -r win-x64 --self-contained
|
||||
Rename-Item (Join-Path $proot "ETTerms.exe") "ETTerms v$ver.exe"
|
||||
```
|
||||
|
||||
> 兩版的 `ETTerms.SerialMcp\` 子資料夾都由 `PublishSerialMcp` target 自動產生;portable 版的 MCP 也是 self-contained,故 AI MCP 功能在無 runtime 環境同樣可用。
|
||||
> 兩版的 `ETTerms.SerialMcp\` 與 `ETTerms.PduMcp\` 子資料夾都由 `PublishMcpServers` target 自動產生;portable 版的 MCP 也是 self-contained,故 AI MCP 功能在無 runtime 環境同樣可用。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user