feat(desktop): surface effective-merged buzz-agent MCP servers in read-only panel

Wires the buzzAgentSlot prop that McpServersSection has exposed since
#1780 with the RuntimeConfigSurface.buzzAgentMcpServers field added in
P0. AgentConfigPanel now renders the effective merged (global <
definition < agent) enabled-server list via a new BuzzAgentMcpServerRow,
giving Will's WYSIWYG requirement (Q2) its read-only half. Also fixes
McpServersSection's fallback text, which previously rendered unreachable
for buzz-agent (the extensions-based branch never executes there since
buzz-agent always reports empty extensions).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
2026-07-14 17:34:04 -04:00
co-authored by Will Pfleger
parent c7bfd0d80a
commit 95afd5996c
2 changed files with 84 additions and 7 deletions
@@ -17,7 +17,7 @@ import { useAgentConfigSurface } from "../hooks";
import { cn } from "@/shared/lib/cn";
import { copyTextToClipboard } from "@/shared/lib/clipboard";
import { Spinner } from "@/shared/ui/spinner";
import { McpServersSection } from "./McpServersSection";
import { McpServersSection, BuzzAgentMcpServerRow } from "./McpServersSection";
import type {
ConfigField,
ConfigOrigin,
@@ -366,8 +366,15 @@ export function AgentConfigPanel({
);
}
const { normalized, advanced, extensions, runtimeId, sources, isPreSpawn } =
data;
const {
normalized,
advanced,
extensions,
runtimeId,
sources,
isPreSpawn,
buzzAgentMcpServers,
} = data;
const configFilePath = sources.configFilePath;
const normalizedEntries = (
@@ -419,6 +426,19 @@ export function AgentConfigPanel({
</div>
<McpServersSection
buzzAgentSlot={
buzzAgentMcpServers.length > 0 ? (
<div className="divide-y divide-border/50">
{buzzAgentMcpServers.map((server) => (
<BuzzAgentMcpServerRow
key={server.name}
server={server}
variant={advancedMode === "flat" ? "profile" : "compact"}
/>
))}
</div>
) : undefined
}
extensions={extensions}
runtimeId={runtimeId}
variant={advancedMode === "flat" ? "profile" : "compact"}
@@ -1,6 +1,6 @@
import type * as React from "react";
import { CheckCircle2, CircleSlash } from "lucide-react";
import type { ExtensionEntry } from "@/shared/api/types";
import type { ExtensionEntry, McpServerConfig } from "@/shared/api/types";
import { cn } from "@/shared/lib/cn";
type McpServersSectionProps = {
@@ -38,9 +38,18 @@ export function McpServersSection({
MCP Servers
</p>
{isBuzzAgent && buzzAgentSlot ? buzzAgentSlot : null}
{extensions.length > 0 ? (
{isBuzzAgent ? (
(buzzAgentSlot ?? (
<p
className={cn(
"text-sm text-muted-foreground",
variant === "compact" ? "py-2" : "px-4 py-3",
)}
>
No custom servers configured
</p>
))
) : extensions.length > 0 ? (
<div className="divide-y divide-border/50">
{extensions.map((extension) => (
<McpServerRow
@@ -100,3 +109,51 @@ function McpServerRow({
</div>
);
}
/**
* Read-only row for an *effective merged* buzz-agent MCP server — "what
* runs." Shows the resolved command line rather than `kind`/enabled state
* (unlike `McpServerRow`), since every entry here is already enabled by
* contract (`RuntimeConfigSurface.buzzAgentMcpServers` is enabled-only).
*/
export function BuzzAgentMcpServerRow({
server,
variant,
}: {
server: McpServerConfig;
variant: "compact" | "profile";
}) {
const StatusIcon = server.enabled ? CheckCircle2 : CircleSlash;
const commandLine = [server.command, ...server.args]
.filter(Boolean)
.join(" ");
return (
<div
className={cn(
"flex min-w-0 items-center gap-3",
variant === "compact" ? "py-2" : "px-4 py-3",
)}
>
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted/50">
<StatusIcon
className={cn(
"h-4 w-4",
server.enabled ? "text-emerald-600" : "text-muted-foreground",
)}
/>
</span>
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-medium text-foreground">
{server.name}
</span>
<span
className="mt-0.5 block truncate text-2xs text-muted-foreground/70"
title={commandLine || undefined}
>
{commandLine || "stdio"}
</span>
</span>
</div>
);
}