Create: aipa-plans/docs/ssh-tui-mcp-interface-contract.md

This commit is contained in:
Atlas
2026-04-14 22:37:59 -07:00
parent 6ffd844bdb
commit 8af10ee356
@@ -0,0 +1,304 @@
---
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.