Skip to content

tracking: align MCP CLI UX with TUI design doc #105

@esengine

Description

@esengine

Why

An audit against docs/design/agent-tui-terminal.html (sections 24 · MCP browser, 32 · slow-server toast, 37 · MCP lifecycle) shows the runtime UX has drifted from the documented design.

design says runtime does gap
Interactive /mcp browser modal — ↑↓ pick, ⏎ inspect, r reconnect, d disable /mcp is a text dump into scrollback no modal
Six lifecycle one-liners on state changes: ↻ handshake… / ✓ connected / ◌ slow / ↻ reconnect 2/5 / ✖ failed / ○ disabled Two startup-only lines: ▸ MCP[label]: N tool(s)… and ▸ MCP setup SKIPPED… wrong vocab + 4 missing states
/mcp disable / enable / reconnect slash subcommands none missing
p95 slow-call detection + toast (⚠ MCP \notion` slow · 8.4s p95 over the last 5 calls`) one-shot elapsedMs at startup only no runtime tracking

Stages

Stage A — Lifecycle vocabulary alignment

Reshape the existing startup-time strings to match design §37 byte-for-byte. No new lifecycle states wired this stage — just the three that already fire (handshake… pre-bridge, connected post-bridge, failed in the catch).

Touch:

  • src/cli/commands/chat.tsx:206-277 (the for (const raw of requestedSpecs) loop)
  • src/cli/commands/run.ts:90-115 (same pattern)
  • New src/cli/ui/mcp-lifecycle.ts exporting formatMcpLifecycleEvent({ name, state, detail }) so chat / run / future code share the formatter

Acceptance:

  • Output matches design §37 layout (⌘ MCP · <name> ✓ connected 12 tools · 8 resources · 142ms)
  • Three states emit now: handshake… (before bridge), connected (after bridge with counts + ms), failed (catch path with reason)
  • Snapshot test in tests/mcp-lifecycle.test.ts pinning the formatter

Estimate: 2-3 hours.

Stage B — /mcp interactive browser

Replace the text-dump /mcp with a keyboard-driven modal matching design §24. Layout per the mockup; r and d are visible-but-stub keybinds in this stage (active in Stage C).

Touch:

  • New src/cli/ui/McpBrowser.tsx wrapping the existing Select.tsx for picker behavior
  • src/cli/ui/App.tsx — add modal slot + mcpBrowserOpen state
  • src/cli/ui/slash/handlers/mcp.ts — flip /mcp from returning { info: ... } to setting modal state
  • Keep the rich text dump as a non-TTY / replay fallback

Acceptance:

  • /mcp opens the modal; Esc closes it
  • ↑↓ navigates rows; is a no-op stub (Stage D will do tool inspection)
  • All four health badges render: healthy, slow, failed, disabled
  • Layout traces back to design §24 line-for-line

Depends on: Stage A (the lifecycle formatter is reused for row health text).

Estimate: 1 day.

Stage C — /mcp disable / enable / reconnect + slow-toast

Three slash subcommands and the p95 latency tracker that drives the warn toast.

Subcommands:

  • /mcp disable <name> — write disabled: true to the server's config entry; emit ○ disabled lifecycle card; bridge skips it on next session and the r key in the browser flips it back
  • /mcp enable <name> — inverse
  • /mcp reconnect <name> — tear down the live McpClient, re-handshake, re-bridge; emits ↻ reconnect N/5 then either ✓ connected or ✖ failed

Slow detection:

  • Wrap dispatch in src/mcp/registry.ts to record per-tool elapsed_ms in a per-server ring buffer (size 5)
  • After 5 calls, compute p95; if > mcpSlowThresholdMs (default 4000), emit toast ⚠ MCP \` slow · 8.4s p95 over the last 5 calls`
  • Idempotent within a turn (don't re-emit on every call)

Touch:

  • src/config.tsdisabled?: boolean per MCP entry, mcpSlowThresholdMs?: number global
  • src/mcp/registry.ts — latency ring buffer + p95 helper
  • New src/cli/ui/slash/handlers/mcp-control.ts for the three subcommands
  • New src/cli/ui/mcp-toast.ts for the warn emission

Acceptance:

  • All three subcommands work in current session (dynamic teardown matters for reconnect)
  • Slow toast fires after p95 threshold and is idempotent per turn
  • /mcp browse reflects updated state without restart

Depends on: A (lifecycle vocab), B (browser surface for live state).

Estimate: 1.5-2 days.

Stage D — (defer) tools sub-pane on browser ⏎

Inside the browser, on a server opens its tools / resources / prompts list. Deferred because reasonix mcp inspect <spec> already covers this from the CLI; in-browser inspection is polish, not core. Pull in 0.21.1 if there's demand.

Constraints

  • One stage per PR. Stage A unblocks the consistent lifecycle vocabulary that B and C reuse.
  • All PRs in this stack reference this issue with Closes part of #<this>.
  • Every visual element must trace back to a section number in docs/design/agent-tui-terminal.html. No design-token improvisation.

Versioning

Stages A + B + C target 0.21.0. Stage D may slip to 0.21.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttrackingTracking issue / umbrella for a multi-PR effort

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions