Refactor ServerCard with active server logic, rename StatusIndicator, and polish UI panels

- Rename StatusIndicator to ServerStatusIndicator across all files
- ServerCard: add activeServer/onSetActiveServer props for coordinated
  connection flow — when a card's toggle is switched on, it sets itself
  as the active server, shows "Connecting" status, and dims all other
  cards (opacity + pointerEvents none + inert for full keyboard blocking)
- ServerListScreen: manage activeServer state internally, pass to cards;
  switch to full-width layout with 3-column grid and scrollable card area
- ServerCard: move "Test Client Features" dropdown above ContentViewer
  with min-height row for consistent card heights
- ToolResultPanel: move Clear button to top-right header row
- ToolDetailPanel: right-align Execute Tool button, size md, not full-width
- ListChangedIndicator: bump Refresh button to size sm
- ToolsActive story: expand to 30 tools with titles
- UnconnectedView stories: all servers disconnected, remove Connecting story

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-04-02 18:00:18 -04:00
commit 8e73bc6ffb
12 changed files with 295 additions and 117 deletions

View file

@ -16,7 +16,7 @@ export function ConnectionToggle({
return ( return (
<Switch <Switch
size="lg" size="lg"
checked={checked} checked={checked || loading}
disabled={disabled || loading} disabled={disabled || loading}
onChange={(event) => onChange(event.currentTarget.checked)} onChange={(event) => onChange(event.currentTarget.checked)}
/> />

View file

@ -18,7 +18,7 @@ const UpdateLabel = Text.withProps({
}); });
const RefreshButton = Button.withProps({ const RefreshButton = Button.withProps({
size: "xs", size: "sm",
variant: "light", variant: "light",
}); });

View file

@ -0,0 +1,42 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { ServerStatusIndicator } from "./ServerStatusIndicator";
const meta: Meta<typeof ServerStatusIndicator> = {
title: "Elements/ServerStatusIndicator",
component: ServerStatusIndicator,
};
export default meta;
type Story = StoryObj<typeof ServerStatusIndicator>;
export const Connected: Story = {
args: {
status: "connected",
latencyMs: 23,
},
};
export const Connecting: Story = {
args: {
status: "connecting",
},
};
export const Disconnected: Story = {
args: {
status: "disconnected",
},
};
export const Failed: Story = {
args: {
status: "failed",
},
};
export const FailedWithRetries: Story = {
args: {
status: "failed",
retryCount: 3,
},
};

View file

@ -0,0 +1,53 @@
import { Group, Paper, Text } from "@mantine/core";
export interface ServerStatusIndicatorProps {
status: "connected" | "connecting" | "disconnected" | "failed";
latencyMs?: number;
retryCount?: number;
}
const statusColorVar: Record<ServerStatusIndicatorProps["status"], string> = {
connected: "var(--inspector-status-connected)",
connecting: "var(--inspector-status-connecting)",
disconnected: "var(--inspector-status-disconnected)",
failed: "var(--inspector-status-failed)",
};
function getLabel(
status: ServerStatusIndicatorProps["status"],
latencyMs?: number,
retryCount?: number,
): string {
switch (status) {
case "connected":
return latencyMs != null ? `Connected (${latencyMs}ms)` : "Connected";
case "connecting":
return "Connecting...";
case "disconnected":
return "Disconnected";
case "failed":
return retryCount != null ? `Failed (${retryCount})` : "Failed";
}
}
const Dot = Paper.withProps({
w: 10,
h: 10,
radius: "xl",
});
export function ServerStatusIndicator({
status,
latencyMs,
retryCount,
}: ServerStatusIndicatorProps) {
return (
<Group gap="xs">
<Dot
bg={statusColorVar[status]}
className={status === "connecting" ? "inspector-pulse" : undefined}
/>
<Text size="sm">{getLabel(status, latencyMs, retryCount)}</Text>
</Group>
);
}

View file

@ -7,6 +7,7 @@ const meta: Meta<typeof ServerCard> = {
component: ServerCard, component: ServerCard,
args: { args: {
onToggleConnection: fn(), onToggleConnection: fn(),
onSetConnectingServer: fn(),
onServerInfo: fn(), onServerInfo: fn(),
onSettings: fn(), onSettings: fn(),
onEdit: fn(), onEdit: fn(),

View file

@ -1,5 +1,6 @@
import { useEffect } from "react";
import { Badge, Button, Card, Group, Menu, Stack, Text } from "@mantine/core"; import { Badge, Button, Card, Group, Menu, Stack, Text } from "@mantine/core";
import { StatusIndicator } from "../../elements/StatusIndicator/StatusIndicator"; import { ServerStatusIndicator } from "../../elements/ServerStatusIndicator/ServerStatusIndicator";
import { TransportBadge } from "../../elements/TransportBadge/TransportBadge"; import { TransportBadge } from "../../elements/TransportBadge/TransportBadge";
import { ConnectionToggle } from "../../elements/ConnectionToggle/ConnectionToggle"; import { ConnectionToggle } from "../../elements/ConnectionToggle/ConnectionToggle";
import { ContentViewer } from "../../elements/ContentViewer/ContentViewer"; import { ContentViewer } from "../../elements/ContentViewer/ContentViewer";
@ -15,6 +16,8 @@ export interface ServerCardProps {
retryCount?: number; retryCount?: number;
error?: { message: string; details?: string }; error?: { message: string; details?: string };
canTestClientFeatures: boolean; canTestClientFeatures: boolean;
activeServer?: string;
onSetActiveServer?: (name: string | undefined) => void;
onToggleConnection: (connect: boolean) => void; onToggleConnection: (connect: boolean) => void;
onServerInfo: () => void; onServerInfo: () => void;
onSettings: () => void; onSettings: () => void;
@ -71,6 +74,8 @@ export function ServerCard({
retryCount, retryCount,
error, error,
canTestClientFeatures, canTestClientFeatures,
activeServer,
onSetActiveServer,
onToggleConnection, onToggleConnection,
onServerInfo, onServerInfo,
onSettings, onSettings,
@ -83,11 +88,35 @@ export function ServerCard({
onConfigureRoots, onConfigureRoots,
compact = false, compact = false,
}: ServerCardProps) { }: ServerCardProps) {
const isThisConnecting = activeServer === name;
const isDimmed = activeServer !== undefined && activeServer !== name;
const isConnected = status === "connected"; const isConnected = status === "connected";
const isConnecting = status === "connecting"; const isConnecting = status === "connecting" || isThisConnecting;
const displayStatus = isThisConnecting ? "connecting" : status;
useEffect(() => {
if (isThisConnecting) {
onToggleConnection(true);
}
}, [isThisConnecting, onToggleConnection]);
function handleToggle(connect: boolean) {
if (connect && !activeServer) {
onSetActiveServer?.(name);
} else if (!connect && activeServer && activeServer === name) {
onSetActiveServer?.(undefined);
onToggleConnection(false);
}
}
return ( return (
<Card withBorder padding="lg"> <Card
withBorder
padding="lg"
opacity={isDimmed ? 0.4 : 1}
style={isDimmed ? { pointerEvents: "none" } : undefined}
{...(isDimmed ? { "aria-disabled": true, inert: "" } : {})}
>
<Stack gap="sm"> <Stack gap="sm">
<Group justify="space-between" wrap="wrap"> <Group justify="space-between" wrap="wrap">
<HeaderLeft> <HeaderLeft>
@ -95,21 +124,47 @@ export function ServerCard({
{version && <Badge variant="outline">{version}</Badge>} {version && <Badge variant="outline">{version}</Badge>}
</HeaderLeft> </HeaderLeft>
<HeaderRight> <HeaderRight>
<StatusIndicator status={status} retryCount={retryCount} /> <ServerStatusIndicator
status={displayStatus}
retryCount={retryCount}
/>
<ConnectionToggle <ConnectionToggle
checked={isConnected} checked={isConnected}
loading={isConnecting} loading={isConnecting}
disabled={false} disabled={isDimmed}
onChange={onToggleConnection} onChange={handleToggle}
/> />
</HeaderRight> </HeaderRight>
</Group> </Group>
{!compact && ( {!compact && (
<> <>
<Group gap="sm"> <Group justify="space-between" mih={30}>
<TransportBadge transport={transport} /> <Group gap="sm">
<ModeText>{connectionMode}</ModeText> <TransportBadge transport={transport} />
<ModeText>{connectionMode}</ModeText>
</Group>
{canTestClientFeatures && (
<Menu>
<Menu.Target>
<SubtleButton>Test Client Features &#x25BE;</SubtleButton>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item onClick={onTestSampling}>
Simulate Sampling Request
</Menu.Item>
<Menu.Item onClick={onTestElicitationForm}>
Simulate Elicitation (Form)
</Menu.Item>
<Menu.Item onClick={onTestElicitationUrl}>
Simulate Elicitation (URL)
</Menu.Item>
<Menu.Item onClick={onConfigureRoots}>
Configure Roots
</Menu.Item>
</Menu.Dropdown>
</Menu>
)}
</Group> </Group>
<ContentViewer type="text" content={command} copyable /> <ContentViewer type="text" content={command} copyable />
@ -131,27 +186,6 @@ export function ServerCard({
<ActionsRow> <ActionsRow>
<SubtleButton onClick={onServerInfo}>Server Info</SubtleButton> <SubtleButton onClick={onServerInfo}>Server Info</SubtleButton>
<SubtleButton onClick={onSettings}>Settings</SubtleButton> <SubtleButton onClick={onSettings}>Settings</SubtleButton>
{canTestClientFeatures && (
<Menu>
<Menu.Target>
<SubtleButton>Test Client Features &#x25BE;</SubtleButton>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item onClick={onTestSampling}>
Simulate Sampling Request
</Menu.Item>
<Menu.Item onClick={onTestElicitationForm}>
Simulate Elicitation (Form)
</Menu.Item>
<Menu.Item onClick={onTestElicitationUrl}>
Simulate Elicitation (URL)
</Menu.Item>
<Menu.Item onClick={onConfigureRoots}>
Configure Roots
</Menu.Item>
</Menu.Dropdown>
</Menu>
)}
</ActionsRow> </ActionsRow>
</Group> </Group>
</> </>

View file

@ -115,16 +115,16 @@ export function ToolDetailPanel({
/> />
)} )}
<Group> <Group justify="flex-end">
{isExecuting && <CancelButton onClick={onCancel}>Cancel</CancelButton>}
<Button <Button
fullWidth size="md"
onClick={onExecute} onClick={onExecute}
disabled={isExecuting} disabled={isExecuting}
loading={isExecuting} loading={isExecuting}
> >
Execute Tool Execute Tool
</Button> </Button>
{isExecuting && <CancelButton onClick={onCancel}>Cancel</CancelButton>}
</Group> </Group>
</Stack> </Stack>
); );

View file

@ -29,7 +29,10 @@ function resolveMediaType(mimeType?: string): "image" | "audio" {
export function ToolResultPanel({ content, onClear }: ToolResultPanelProps) { export function ToolResultPanel({ content, onClear }: ToolResultPanelProps) {
return ( return (
<Stack> <Stack>
<Title order={4}>Results</Title> <Group justify="space-between">
<Title order={4}>Results</Title>
<ClearButton onClick={onClear}>Clear</ClearButton>
</Group>
{content.length === 0 ? ( {content.length === 0 ? (
<Text c="dimmed">No results yet</Text> <Text c="dimmed">No results yet</Text>
) : ( ) : (
@ -59,9 +62,6 @@ export function ToolResultPanel({ content, onClear }: ToolResultPanelProps) {
})} })}
</> </>
)} )}
<Group>
<ClearButton onClick={onClear}>Clear</ClearButton>
</Group>
</Stack> </Stack>
); );
} }

View file

@ -10,7 +10,7 @@ import {
} from "@mantine/core"; } from "@mantine/core";
import { useComputedColorScheme } from "@mantine/core"; import { useComputedColorScheme } from "@mantine/core";
import { MdLightMode, MdDarkMode } from "react-icons/md"; import { MdLightMode, MdDarkMode } from "react-icons/md";
import { StatusIndicator } from "../../elements/StatusIndicator/StatusIndicator"; import { ServerStatusIndicator } from "../../elements/ServerStatusIndicator/ServerStatusIndicator";
import mcpLogo from "../../../theme/assets/MCP.svg"; import mcpLogo from "../../../theme/assets/MCP.svg";
import mcpLogoDark from "../../../theme/assets/MCP-dark.svg"; import mcpLogoDark from "../../../theme/assets/MCP-dark.svg";
@ -133,7 +133,7 @@ export function ViewHeader(props: ViewHeaderProps) {
</CenterSection> </CenterSection>
<RightSection> <RightSection>
<StatusIndicator status={props.status} latencyMs={props.latencyMs} /> <ServerStatusIndicator status={props.status} latencyMs={props.latencyMs} />
<DisconnectButton onClick={props.onDisconnect}> <DisconnectButton onClick={props.onDisconnect}>
Disconnect Disconnect
</DisconnectButton> </DisconnectButton>

View file

@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Container, SimpleGrid, Stack, Text } from "@mantine/core"; import { ScrollArea, SimpleGrid, Stack, Text } from "@mantine/core";
import { ServerCard } from "../../groups/ServerCard/ServerCard"; import { ServerCard } from "../../groups/ServerCard/ServerCard";
import { ServerListControls } from "../../groups/ServerListControls/ServerListControls"; import { ServerListControls } from "../../groups/ServerListControls/ServerListControls";
import type { ServerCardProps } from "../../groups/ServerCard/ServerCard"; import type { ServerCardProps } from "../../groups/ServerCard/ServerCard";
@ -11,9 +11,8 @@ export interface ServerListScreenProps {
onImportServerJson: () => void; onImportServerJson: () => void;
} }
const PageContainer = Container.withProps({ const PageContainer = Stack.withProps({
size: "xl", p: "xl",
py: "xl",
}); });
const EmptyState = Text.withProps({ const EmptyState = Text.withProps({
@ -29,6 +28,9 @@ export function ServerListScreen({
onImportServerJson, onImportServerJson,
}: ServerListScreenProps) { }: ServerListScreenProps) {
const [compact, setCompact] = useState<boolean>(false); const [compact, setCompact] = useState<boolean>(false);
const [activeServer, setActiveServer] = useState<
string | undefined
>();
function handleToggleList() { function handleToggleList() {
setCompact((prev) => (prev === true ? false : true)); setCompact((prev) => (prev === true ? false : true));
@ -36,32 +38,38 @@ export function ServerListScreen({
return ( return (
<PageContainer> <PageContainer>
<Stack gap="lg"> <ServerListControls
<ServerListControls serverCount={servers.length}
serverCount={servers.length} compact={compact}
compact={compact} onToggleList={handleToggleList}
onToggleList={handleToggleList} onAddManually={onAddManually}
onAddManually={onAddManually} onImportConfig={onImportConfig}
onImportConfig={onImportConfig} onImportServerJson={onImportServerJson}
onImportServerJson={onImportServerJson} />
/>
<ScrollArea.Autosize mah="calc(100vh - var(--app-shell-header-height, 60px) - var(--mantine-spacing-xl) * 2 - 60px)">
{servers.length === 0 ? ( {servers.length === 0 ? (
<EmptyState> <EmptyState>
No servers configured. Add a server to get started. No servers configured. Add a server to get started.
</EmptyState> </EmptyState>
) : ( ) : (
<SimpleGrid <SimpleGrid
cols={{ base: 1, md: 2 }} cols={{ base: 1, sm: 2, lg: 3 }}
spacing="lg" spacing="lg"
className="grid-align-start" className="grid-align-start"
> >
{servers.map((server) => ( {servers.map((server) => (
<ServerCard key={server.name} compact={compact} {...server} /> <ServerCard
key={server.name}
compact={compact}
activeServer={activeServer}
onSetActiveServer={setActiveServer}
{...server}
/>
))} ))}
</SimpleGrid> </SimpleGrid>
)} )}
</Stack> </ScrollArea.Autosize>
</PageContainer> </PageContainer>
); );
} }

View file

@ -184,9 +184,174 @@ export const ToolsActive: Story = {
selected: true, selected: true,
onClick: fn(), onClick: fn(),
}, },
{ name: "delete_records", selected: false, onClick: fn() }, {
{ name: "list_users", selected: false, onClick: fn() }, name: "delete_records",
{ name: "batch_process", selected: false, onClick: fn() }, title: "Delete Records",
selected: false,
onClick: fn(),
},
{
name: "list_users",
title: "List Users",
selected: false,
onClick: fn(),
},
{
name: "batch_process",
title: "Batch Process",
selected: false,
onClick: fn(),
},
{
name: "search_files",
title: "Search Files",
selected: false,
onClick: fn(),
},
{
name: "read_file",
title: "Read File",
selected: false,
onClick: fn(),
},
{
name: "write_file",
title: "Write File",
selected: false,
onClick: fn(),
},
{
name: "get_schema",
title: "Get Schema",
selected: false,
onClick: fn(),
},
{
name: "run_query",
title: "Run Query",
selected: false,
onClick: fn(),
},
{
name: "create_migration",
title: "Create Migration",
selected: false,
onClick: fn(),
},
{
name: "validate_config",
title: "Validate Config",
selected: false,
onClick: fn(),
},
{
name: "deploy_service",
title: "Deploy Service",
selected: false,
onClick: fn(),
},
{
name: "rollback_deploy",
title: "Rollback Deploy",
selected: false,
onClick: fn(),
},
{
name: "check_health",
title: "Check Health",
selected: false,
onClick: fn(),
},
{
name: "generate_report",
title: "Generate Report",
selected: false,
onClick: fn(),
},
{
name: "export_csv",
title: "Export CSV",
selected: false,
onClick: fn(),
},
{
name: "import_data",
title: "Import Data",
selected: false,
onClick: fn(),
},
{
name: "send_notification",
title: "Send Notification",
selected: false,
onClick: fn(),
},
{
name: "schedule_task",
title: "Schedule Task",
selected: false,
onClick: fn(),
},
{
name: "cancel_task",
title: "Cancel Task",
selected: false,
onClick: fn(),
},
{
name: "list_connections",
title: "List Connections",
selected: false,
onClick: fn(),
},
{
name: "refresh_cache",
title: "Refresh Cache",
selected: false,
onClick: fn(),
},
{
name: "purge_logs",
title: "Purge Logs",
selected: false,
onClick: fn(),
},
{
name: "encrypt_secret",
title: "Encrypt Secret",
selected: false,
onClick: fn(),
},
{
name: "rotate_keys",
title: "Rotate Keys",
selected: false,
onClick: fn(),
},
{
name: "sync_resources",
title: "Sync Resources",
selected: false,
onClick: fn(),
},
{
name: "compile_template",
title: "Compile Template",
selected: false,
onClick: fn(),
},
{
name: "analyze_performance",
title: "Analyze Performance",
selected: false,
onClick: fn(),
},
{
name: "resize_image",
title: "Resize Image",
selected: false,
onClick: fn(),
},
]} ]}
selectedTool={{ selectedTool={{
name: "create_record", name: "create_record",

View file

@ -59,8 +59,8 @@ export const WithServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-everything", command: "npx -y @modelcontextprotocol/server-everything",
status: "connected", status: "disconnected",
canTestClientFeatures: true, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
{ {
@ -80,9 +80,7 @@ export const WithServers: Story = {
transport: "http", transport: "http",
connectionMode: "Direct", connectionMode: "Direct",
command: "https://api.example.com/mcp", command: "https://api.example.com/mcp",
status: "failed", status: "disconnected",
retryCount: 3,
error: { message: "Connection timeout after 20s" },
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -106,8 +104,8 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-everything", command: "npx -y @modelcontextprotocol/server-everything",
status: "connected", status: "disconnected",
canTestClientFeatures: true, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
{ {
@ -127,8 +125,8 @@ export const ManyServers: Story = {
transport: "http", transport: "http",
connectionMode: "Direct", connectionMode: "Direct",
command: "https://api.example.com/mcp", command: "https://api.example.com/mcp",
status: "connected", status: "disconnected",
canTestClientFeatures: true, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
{ {
@ -137,7 +135,7 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-postgres", command: "npx -y @modelcontextprotocol/server-postgres",
status: "connecting", status: "disconnected",
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -147,8 +145,8 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-github", command: "npx -y @modelcontextprotocol/server-github",
status: "connected", status: "disconnected",
canTestClientFeatures: true, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
{ {
@ -157,9 +155,7 @@ export const ManyServers: Story = {
transport: "http", transport: "http",
connectionMode: "Direct", connectionMode: "Direct",
command: "https://slack-mcp.example.com/mcp", command: "https://slack-mcp.example.com/mcp",
status: "failed", status: "disconnected",
retryCount: 5,
error: { message: "Authentication failed" },
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -169,7 +165,7 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-memory", command: "npx -y @modelcontextprotocol/server-memory",
status: "connected", status: "disconnected",
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -189,8 +185,8 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-sqlite ./data.db", command: "npx -y @modelcontextprotocol/server-sqlite ./data.db",
status: "connected", status: "disconnected",
canTestClientFeatures: true, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
{ {
@ -199,9 +195,7 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-brave-search", command: "npx -y @modelcontextprotocol/server-brave-search",
status: "failed", status: "disconnected",
retryCount: 2,
error: { message: "API key expired" },
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -221,7 +215,7 @@ export const ManyServers: Story = {
transport: "stdio", transport: "stdio",
connectionMode: "Via Proxy", connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-sequential-thinking", command: "npx -y @modelcontextprotocol/server-sequential-thinking",
status: "connecting", status: "disconnected",
canTestClientFeatures: false, canTestClientFeatures: false,
...makeServerCallbacks(), ...makeServerCallbacks(),
}, },
@ -232,28 +226,4 @@ export const ManyServers: Story = {
/> />
), ),
}, },
}; };
export const Connecting: Story = {
args: {
children: (
<ServerListScreen
servers={[
{
name: "everything-server",
version: "1.0.0",
transport: "stdio",
connectionMode: "Via Proxy",
command: "npx -y @modelcontextprotocol/server-everything",
status: "connecting",
canTestClientFeatures: false,
...makeServerCallbacks(),
},
]}
onAddManually={fn()}
onImportConfig={fn()}
onImportServerJson={fn()}
/>
),
},
};