Files
VuongKB/aipa-plans/docs/ssh-tui-mcp-interface-contract.md
T

304 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
created: '2026-04-15T05:37:59+00:00'
id: 556bb313-29a5-4cd8-bd83-3213268262bf
keywords:
- MCP
- SSH-TUI
- interface contract
- Linus
- Model Context Protocol
- TUI
- Textual
- AI copilot
- ssh-tui
- suggested commands
- intent checklist
- terminal context
links: []
modified: '2026-04-15T05:37:59+00:00'
summary: MCP interface contract defining the message types, data formats, and behavioral
contracts between the SSH-TUI application and the Linus AI agent.
tags:
- aipa-plans
- ssh-tui
- mcp
- interface-contract
- linus
- specification
title: SSH-TUI MCP Interface Contract
---
# SSH-TUI MCP Interface Contract
**Status:** Draft — Pending review
**Project:** AIPA SSH-TUI
**Last updated:** 2025-07-10
**Author:** Linus (Systems Architect)
## Overview
This document defines the MCP (Model Context Protocol) interface between the SSH-TUI application and the Linus AI agent. The SSH-TUI is a Textual-based terminal application that wraps SSH sessions and provides an AI copilot experience. The TUI acts as an MCP client; Linus is exposed via the MCP server.
## Design Principles
1. **TUI calls Linus, Linus responds with structured updates** — the TUI makes one call and receives everything it needs to render (chat response, intent, suggested commands).
2. **Linus never executes commands directly** — all commands must be explicitly sent by the user via the Send action.
3. **Intent is a living checklist** — not freeform text. Uses step status markers (✓ done, ▸ current, ○ pending).
4. **Commands are editable before sending** — the TUI must allow the user to modify any suggested command before execution.
5. **AI-sent commands are visually distinct** — in the SSH session panel, commands originating from suggested commands are dimmed or prefixed (e.g., `→`) so there is always a clear audit trail.
6. **Graceful degradation** — if the AI connection drops, SSH remains fully functional. Intent/Commands show "AI offline", Chat queues messages locally.
## Message Types
### TUI → Linus (via MCP)
#### 1. `chat` — User typed a message in the Chat panel
Sent when the user submits a message in the "Chat to Linus" panel. Includes the current terminal context so Linus has situational awareness.
```json
{
"type": "chat",
"session_id": "uuid-string",
"message": "hey linus, /var is full what's eating the space",
"context": {
"ssh_host": "root@10.250.50.70",
"ssh_user": "root",
"connected": true,
"terminal_tail": "last ~100 lines of terminal output as string",
"cwd": "/root",
"last_command": "df -h",
"last_exit_code": 0
}
}
```
#### 2. `terminal_update` — New output in the SSH session
Streamed to Linus on a debounced interval (~1 second) when new output appears in the SSH session while the session is active. Provides Linus with awareness of what's happening even when the user isn't chatting.
```json
{
"type": "terminal_update",
"session_id": "uuid-string",
"new_output": "only the new lines since last update",
"terminal_tail": "last ~100 lines including new output",
"context": {
"ssh_host": "root@10.250.50.70",
"ssh_user": "root",
"cwd": "/root"
}
}
```
#### 3. `command_executed` — A command was sent through the SSH session
Sent when any command is executed — whether it was a user-typed command, a sent suggested command (possibly user-edited), or a command Linus previously suggested. This gives Linus feedback on what happened.
```json
{
"type": "command_executed",
"session_id": "uuid-string",
"command": "du -ah /var | sort -rh | head -20",
"source": "suggested",
"suggestion_id": "cmd_001",
"was_edited": false,
"output": "4.2G /var/log/syslog\n2.1G /var/log/journal/...\n...",
"exit_code": 0,
"context": {
"ssh_host": "root@10.250.50.70",
"ssh_user": "root",
"cwd": "/root"
}
}
```
`source` values: `"suggested"` (from suggested commands panel), `"user_typed"` (typed directly into SSH session).
#### 4. `session_state` — Session lifecycle events
Sent on connection, disconnection, and error events.
```json
{
"type": "session_state",
"session_id": "uuid-string",
"event": "connected",
"context": {
"ssh_host": "root@10.250.50.70",
"ssh_user": "root"
}
}
```
`event` values: `"connected"`, `"disconnected"`, `"connection_error"`, `"authentication_failed"`.
### Linus → TUI (via MCP response)
All responses use a unified envelope. A single MCP response can contain any combination of the following blocks.
```json
{
"chat_response": { ... },
"intent_update": { ... },
"suggested_commands": { ... },
"clear_suggestions": { ... }
}
```
#### `chat_response` — Reply in the Chat panel
```json
{
"chat_response": {
"message": "Looks like /var/log is the culprit at 4.2G. I've queued up some commands to identify the largest files.",
"mentions": ["cmd_001", "cmd_003"]
}
}
```
`mentions` is optional — IDs of suggested commands that are particularly relevant to this response, which the TUI can highlight.
#### `intent_update` — Living checklist in the Intent panel
The intent is structured as a multi-step plan with status markers:
```json
{
"intent_update": {
"summary": "Investigating /var disk usage",
"confidence": 0.85,
"steps": [
{
"status": "done",
"text": "Check overall disk usage with df -h"
},
{
"status": "done",
"text": "Identify largest directories in /var"
},
{
"status": "current",
"text": "List largest individual files in /var/log"
},
{
"status": "pending",
"text": "Determine if logs can be rotated or cleaned"
},
{
"status": "pending",
"text": "Free disk space safely"
}
]
}
}
```
Status values: `"done"` (rendered as ✓), `"current"` (rendered as ▸), `"pending"` (rendered as ○).
`confidence` is a float 0.0–1.0 indicating how certain Linus is about the approach. The TUI renders this as a visual indicator.
#### `suggested_commands` — Commands in the Suggested Commands panel
```json
{
"suggested_commands": {
"commands": [
{
"id": "cmd_001",
"command": "ls -lhS /var/log/*.log | head -10",
"description": "List largest log files in /var/log",
"risk": "low"
},
{
"id": "cmd_002",
"command": "sudo journalctl --disk-usage",
"description": "Check journald disk usage",
"risk": "low"
},
{
"id": "cmd_003",
"command": "sudo apt-get clean && sudo apt-get autoremove -y",
"description": "Clean apt cache and remove unused packages (~500MB typical)",
"risk": "medium"
}
]
}
}
```
`risk` values: `"low"`, `"medium"`, `"high"`. The TUI renders risk indicators to help the user make informed decisions. The TUI MUST allow editing any command before sending.
#### `clear_suggestions` — Remove stale commands
```json
{
"clear_suggestions": {
"ids": ["cmd_001", "cmd_002"]
}
}
```
Optionally `"all": true` to clear all suggestions.
## MCP Tool Interface (Alternative Framing)
If the MCP server exposes Linus as tools rather than a streaming message channel, the TUI would call:
| Tool | Input | Output |
|---|---|---|
| `linus_chat` | `{ message, context }` | `{ chat_response, intent_update, suggested_commands }` |
| `linus_terminal_update` | `{ new_output, terminal_tail, context }` | `{ intent_update, suggested_commands }` (optional — Linus may choose not to update) |
| `linus_command_executed` | `{ command, output, source, exit_code, context }` | `{ chat_response, intent_update, suggested_commands, clear_suggestions }` |
| `linus_session_state` | `{ event, context }` | `{ chat_response, intent_update }` |
The response from `linus_chat` is always the full unified envelope — the TUI makes one call and gets everything it needs to render all panels.
## Terminal Context Format
The `terminal_tail` field is a plain string of the last ~100 lines of terminal output. Format conventions:
- Preserve ANSI escape codes if present (the TUI can strip them for context, but raw output is more useful for Linus to detect colors/formats)
- Include the prompt line so Linus can see the current working directory and user
- Trim trailing whitespace per line
- Include a `--- snip ---` marker if lines were omitted from the middle (should be rare at 100 lines)
```json
{
"terminal_tail": "root@prod-web-03:~# df -h\nFilesystem Size Used Avail Use% Mounted on\n/dev/sda1 45G 42G 1.2G 98% /\nroot@prod-web-03:~# _"
}
```
## Debouncing and Throttling
| Event | Debounce | Notes |
|---|---|---|
| `terminal_update` | 1 second | Only send if new output exists since last update. Buffer and send in batch. |
| `command_executed` | Immediate | Send as soon as the command produces output (or after a 5s timeout for long-running commands, send what's available). |
| `chat` | Immediate | User-initiated, no debounce. |
| `session_state` | Immediate | Lifecycle events are infrequent. |
## Error Handling
If Linus is unreachable or returns an error:
1. The TUI continues operating as a normal SSH client — no functionality is blocked.
2. The Intent panel shows: `AI offline — chat messages will be queued.`
3. The Suggested Commands panel shows its last state with a note: `(AI offline — commands may be stale)`.
4. Chat messages are queued locally and sent when connection is restored.
5. Terminal updates are discarded (not queued) — they're ephemeral context.
## Security Considerations
- **No direct command execution** — Linus never sends commands to the SSH session. The TUI always presents commands to the user for explicit approval via the Send action.
- **Risk labels** — every suggested command includes a risk level. The TUI should render high-risk commands with a warning.
- **Command editing** — the TUI MUST allow the user to modify any suggested command before sending. The user is the final safety net.
- **Audit trail** — commands sent from the suggested panel are visually distinct in the SSH session (dimmed or prefixed) so the user can always distinguish their own commands from AI-suggested ones.
- **No credential exposure** — the TUI should never include SSH passwords, keys, or authentication material in MCP messages. The `context` object includes host and user but never credentials.
## Future Considerations
- **Multiple concurrent sessions** — the `session_id` field is designed to support this. Not in scope for v1.
- **Command history** — Linus could suggest commands based on the user's bash history. Requires `history` file access or session command log.
- **File content inspection** — Linus may want to read specific files on the remote host. This would require a new tool (`linus_read_file`) that the TUI executes over SSH. Not in scope for v1.
- **Notifications** — Linus could proactively notify the user of conditions detected in terminal output (e.g., "I see a kernel OOM in the dmesg output"). This would be a push mechanism. Not in scope for v1.