({
title,
description,
status,
busy,
entryMissing,
onInstall,
onUninstall,
onCopyConfigPath
}: {
title: string
description: string
status: McpClientStatus
busy: boolean
entryMissing: boolean
onInstall: () => void
onUninstall: () => void
onCopyConfigPath: () => void
})
| 5604 | } |
| 5605 | |
| 5606 | function McpClientRow({ |
| 5607 | title, |
| 5608 | description, |
| 5609 | status, |
| 5610 | busy, |
| 5611 | entryMissing, |
| 5612 | onInstall, |
| 5613 | onUninstall, |
| 5614 | onCopyConfigPath |
| 5615 | }: { |
| 5616 | title: string |
| 5617 | description: string |
| 5618 | status: McpClientStatus |
| 5619 | busy: boolean |
| 5620 | entryMissing: boolean |
| 5621 | onInstall: () => void |
| 5622 | onUninstall: () => void |
| 5623 | onCopyConfigPath: () => void |
| 5624 | }): JSX.Element { |
| 5625 | const chip = status.installed |
| 5626 | ? status.upToDate |
| 5627 | ? { label: 'Installed', tone: 'ok' as const } |
| 5628 | : { label: 'Needs update', tone: 'warn' as const } |
| 5629 | : { label: 'Not installed', tone: 'off' as const } |
| 5630 | |
| 5631 | return ( |
| 5632 | <div className="flex flex-col gap-3 px-5 py-4"> |
| 5633 | <div className="flex items-start justify-between gap-4"> |
| 5634 | <div className="min-w-0"> |
| 5635 | <div className="flex flex-wrap items-center gap-x-2 gap-y-1"> |
| 5636 | <span className="text-sm font-medium text-ink-900">{title}</span> |
| 5637 | <span |
| 5638 | className={[ |
| 5639 | 'rounded-full border px-2 py-0.5 text-2xs font-medium uppercase tracking-[0.14em]', |
| 5640 | statusChipClass(chip.tone) |
| 5641 | ].join(' ')} |
| 5642 | > |
| 5643 | {chip.label} |
| 5644 | </span> |
| 5645 | </div> |
| 5646 | <div className="mt-1 text-xs leading-5 text-ink-500">{description}</div> |
| 5647 | {status.note && <div className="mt-1.5 text-xs leading-5 text-ink-500">{status.note}</div>} |
| 5648 | </div> |
| 5649 | <div className="flex shrink-0 items-center gap-2"> |
| 5650 | {status.installed ? ( |
| 5651 | <> |
| 5652 | {!status.upToDate && ( |
| 5653 | <button |
| 5654 | type="button" |
| 5655 | onClick={onInstall} |
| 5656 | disabled={busy || entryMissing} |
| 5657 | className={[ |
| 5658 | 'rounded-xl border px-3 py-1.5 text-xs font-medium transition-colors', |
| 5659 | busy || entryMissing |
| 5660 | ? 'cursor-not-allowed border-paper-300/60 bg-paper-100/45 text-ink-400' |
| 5661 | : 'border-accent/30 bg-accent/15 text-accent hover:bg-accent/25' |
| 5662 | ].join(' ')} |
| 5663 | > |
nothing calls this directly
no test coverage detected