feat(cli): add MCP health pill to footer (#3741)#213
Conversation
Cherry-picked from QwenLM/qwen-code: 9e8f826 Adds a small status pill to the footer showing MCP server health (connected / connecting / disconnected counts). Subscribes to the mcp-client module-level listener API and re-renders on transitions. Adaptations: - Skipped upstream's Footer left-column restructure (statusLineLines + leftBottomContent + BackgroundTasksPill) — those depend on the un-ported background-agents subsystem. Instead, render <MCPHealthPill /> alongside our existing leftContent in the same Box, preserving our simpler footer layout. - Skipped the BackgroundTasksPill import for the same reason. The hook (`useMCPHealth`) and component (`MCPHealthPill`) added verbatim from the cherry-pick — both new files, no fork-side divergence. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughThis PR introduces MCP (Model Context Protocol) health monitoring to the CLI footer. A new custom hook ( ChangesMCP Health Status Monitoring
Sequence DiagramsequenceDiagram
participant Footer as Footer Component
participant Pill as MCPHealthPill
participant Hook as useMCPHealth Hook
participant Registry as MCP Status Registry
participant Listener as Status Change Listener
Footer->>Pill: render
Pill->>Hook: useMCPHealth()
Hook->>Registry: getAllMCPServerStatuses()
Registry-->>Hook: Map<name, status>
Hook->>Listener: addMCPStatusChangeListener()
Listener->>Hook: (on status change)
Hook->>Hook: update Map with new status
Hook->>Hook: compute snapshot (totalCount, disconnectedCount, etc.)
Hook-->>Pill: MCPHealthSnapshot
Pill->>Pill: getPillLabel(snapshot)
Pill-->>Footer: render pill or null
Footer-->>Footer: render footer with/without pill
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 1/5 review remaining, refill in 45 minutes and 43 seconds. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/cli/src/ui/components/mcp/MCPHealthPill.tsx (1)
36-44: ⚡ Quick winAvoid rendering the inline separator when footer is stacked vertically.
When the footer switches to column layout, the hardcoded leading
·renders as a stray bullet on its own line. Make the separator optional and letFooterdecide based onisNarrow.♻️ Suggested change
-export const MCPHealthPill: React.FC = () => { +export const MCPHealthPill: React.FC<{ withSeparator?: boolean }> = ({ + withSeparator = true, +}) => { const snapshot = useMCPHealth(); const label = getPillLabel(snapshot); if (!label) return null; return ( <> - <Text color={theme.text.secondary}> · </Text> + {withSeparator && <Text color={theme.text.secondary}> · </Text>} <Text color={theme.status.warning}>{label}</Text> </> ); };// packages/cli/src/ui/components/Footer.tsx <MCPHealthPill withSeparator={!isNarrow} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/cli/src/ui/components/mcp/MCPHealthPill.tsx` around lines 36 - 44, The MCPHealthPill currently always renders the inline separator " · ", which becomes a stray bullet when the Footer stacks vertically; modify the MCPHealthPill component (function MCPHealthPill) to accept a prop like withSeparator?: boolean (default true) and render the separator only when withSeparator is true (keep usage of useMCPHealth and getPillLabel unchanged), and then update Footer to pass withSeparator={!isNarrow} when rendering <MCPHealthPill /> so the separator is omitted in narrow/column layouts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/cli/src/ui/components/mcp/MCPHealthPill.tsx`:
- Around line 36-44: The MCPHealthPill currently always renders the inline
separator " · ", which becomes a stray bullet when the Footer stacks vertically;
modify the MCPHealthPill component (function MCPHealthPill) to accept a prop
like withSeparator?: boolean (default true) and render the separator only when
withSeparator is true (keep usage of useMCPHealth and getPillLabel unchanged),
and then update Footer to pass withSeparator={!isNarrow} when rendering
<MCPHealthPill /> so the separator is omitted in narrow/column layouts.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b5b05df3-b863-46f1-8316-7e1525e48d57
📒 Files selected for processing (4)
packages/cli/src/ui/components/Footer.tsxpackages/cli/src/ui/components/mcp/MCPHealthPill.test.tsxpackages/cli/src/ui/components/mcp/MCPHealthPill.tsxpackages/cli/src/ui/hooks/useMCPHealth.ts
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
Summary
Backport of upstream QwenLM/qwen-code#3741. Adds a small status pill to the footer showing MCP server health (connected / connecting / disconnected counts), updated live as servers transition.
What changes for users
A new pill in the left side of the footer displays current MCP server status. Subscribes to
mcp-client's module-level listener API and re-renders on every transition.Adaptations
statusLineLines+leftBottomContent+BackgroundTasksPill— those depend on the un-ported background-agents subsystem. Render<MCPHealthPill />alongside our existingleftContentin the same Box, preserving our simpler footer layout.useMCPHealth.ts,MCPHealthPill.tsx, test) are taken verbatim — no fork-side divergence on those paths.Test plan
npm run typecheckcleanMCPHealthPill.test.tsx, 6 in existingFooter.test.tsx)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests