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

11 KiB
Raw Blame History

created, id, keywords, links, modified, summary, tags, title
created id keywords links modified summary tags title
2026-04-15T05:37:59+00:00 556bb313-29a5-4cd8-bd83-3213268262bf
MCP
SSH-TUI
interface contract
Linus
Model Context Protocol
TUI
Textual
AI copilot
ssh-tui
suggested commands
intent checklist
terminal context
2026-04-15T05:37:59+00:00 MCP interface contract defining the message types, data formats, and behavioral contracts between the SSH-TUI application and the Linus AI agent.
aipa-plans
ssh-tui
mcp
interface-contract
linus
specification
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.

{
  "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.

{
  "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.

{
  "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.

{
  "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.

{
  "chat_response": { ... },
  "intent_update": { ... },
  "suggested_commands": { ... },
  "clear_suggestions": { ... }
}

chat_response — Reply in the Chat panel

{
  "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:

{
  "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

{
  "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

{
  "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)
{
  "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.