Skip to content

Commit 412b39f

Browse files
cliffhallclaude
andcommitted
Phase 1: Refactor all 16 element component interfaces to use MCP SDK types
Replace ad-hoc local type definitions in element components with real MCP SDK types and Inspector wrapper types from core/mcp/types.ts: Schema-typed primitives: - LogLevelBadge: LogLevel → LoggingLevel (SDK) - TransportBadge: "stdio"|"http" → ServerType (core), add sse/streamable-http - TaskStatusBadge: local TaskStatus → SDK TaskStatus (working/input_required/...) - ServerStatusIndicator: inline union → ConnectionStatus (core), "failed"→"error" MCP wrapper consumers: - AnnotationBadge: label+variant → facet+value with SDK Role type - CapabilityItem: name:string → capability:keyof ServerCapabilities|ClientCapabilities - LogEntry: flat props → entry:{receivedAt:Date, params:LoggingMessageNotification["params"]} - MessageBubble: flat props → message:SamplingMessage|PromptMessage - ProgressDisplay: flat props → params:ProgressNotification["params"] Composite-input elements: - ContentViewer: type+content+mimeType → block:ContentBlock (SDK discriminated union) - InlineError: message+details → error:{message,data?} - ConnectionToggle: checked+loading+onChange → status:ConnectionStatus+onConnect/onDisconnect Also updates all group/screen/view consumers to keep the build green, and renames CSS variable --inspector-status-failed → --inspector-status-error. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0db9030 commit 412b39f

54 files changed

Lines changed: 905 additions & 648 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

clients/web/src/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
--inspector-status-connected: var(--mantine-color-green-6);
3535
--inspector-status-connecting: var(--mantine-color-yellow-6);
3636
--inspector-status-disconnected: var(--mantine-color-gray-5);
37-
--inspector-status-failed: var(--mantine-color-red-6);
37+
--inspector-status-error: var(--mantine-color-red-6);
3838

3939
/* ── Log levels (RFC 5424) ─────────────────────────────── */
4040
--inspector-log-debug: var(--mantine-color-gray-6);

clients/web/src/components/elements/AnnotationBadge/AnnotationBadge.stories.tsx

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,63 @@ type Story = StoryObj<typeof AnnotationBadge>;
1111

1212
export const Audience: Story = {
1313
args: {
14-
label: "user",
15-
variant: "audience",
14+
facet: "audience",
15+
value: ["user"],
16+
},
17+
};
18+
19+
export const AudienceMultiple: Story = {
20+
args: {
21+
facet: "audience",
22+
value: ["user", "assistant"],
1623
},
1724
};
1825

1926
export const ReadOnly: Story = {
2027
args: {
21-
label: "read-only",
22-
variant: "readOnly",
28+
facet: "readOnlyHint",
29+
value: true,
2330
},
2431
};
2532

2633
export const Destructive: Story = {
2734
args: {
28-
label: "destructive",
29-
variant: "destructive",
35+
facet: "destructiveHint",
36+
value: true,
37+
},
38+
};
39+
40+
export const Idempotent: Story = {
41+
args: {
42+
facet: "idempotentHint",
43+
value: true,
44+
},
45+
};
46+
47+
export const OpenWorld: Story = {
48+
args: {
49+
facet: "openWorldHint",
50+
value: true,
3051
},
3152
};
3253

33-
export const LongRun: Story = {
54+
export const LongRunning: Story = {
3455
args: {
35-
label: "long-run",
36-
variant: "longRun",
56+
facet: "longRunHint",
57+
value: true,
3758
},
3859
};
3960

4061
export const PriorityHigh: Story = {
4162
args: {
42-
label: "priority: high",
43-
variant: "priority",
63+
facet: "priority",
64+
value: 0.9,
4465
},
4566
};
4667

47-
export const Default: Story = {
68+
export const PriorityLow: Story = {
4869
args: {
49-
label: "custom",
50-
variant: "default",
70+
facet: "priority",
71+
value: 0.2,
5172
},
5273
};
Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,59 @@
11
import { Badge, useComputedColorScheme } from "@mantine/core";
2+
import type { Role } from "@modelcontextprotocol/sdk/types.js";
23

3-
export type AnnotationVariant =
4+
export type AnnotationFacet =
45
| "audience"
5-
| "readOnly"
6-
| "destructive"
7-
| "longRun"
86
| "priority"
9-
| "default";
7+
| "readOnlyHint"
8+
| "destructiveHint"
9+
| "idempotentHint"
10+
| "openWorldHint"
11+
| "longRunHint";
1012

1113
export interface AnnotationBadgeProps {
12-
label: string;
13-
variant?: AnnotationVariant;
14+
facet: AnnotationFacet;
15+
value: Role[] | number | boolean;
1416
}
1517

16-
const colorMap: Record<AnnotationVariant, string> = {
18+
const colorMap: Record<AnnotationFacet, string> = {
1719
audience: "blue",
18-
readOnly: "green",
19-
destructive: "red",
20-
longRun: "yellow",
2120
priority: "orange",
22-
default: "gray",
21+
readOnlyHint: "green",
22+
destructiveHint: "red",
23+
idempotentHint: "teal",
24+
openWorldHint: "grape",
25+
longRunHint: "yellow",
2326
};
2427

25-
export function AnnotationBadge({
26-
label,
27-
variant = "default",
28-
}: AnnotationBadgeProps) {
28+
function formatLabel(
29+
facet: AnnotationFacet,
30+
value: Role[] | number | boolean,
31+
): string {
32+
switch (facet) {
33+
case "audience":
34+
return `audience: ${(value as Role[]).join(", ")}`;
35+
case "priority":
36+
return `priority: ${value}`;
37+
case "readOnlyHint":
38+
return "read-only";
39+
case "destructiveHint":
40+
return "destructive";
41+
case "idempotentHint":
42+
return "idempotent";
43+
case "openWorldHint":
44+
return "open-world";
45+
case "longRunHint":
46+
return "long-running";
47+
}
48+
}
49+
50+
export function AnnotationBadge({ facet, value }: AnnotationBadgeProps) {
2951
const colorScheme = useComputedColorScheme();
30-
const color = colorMap[variant];
52+
const color = colorMap[facet];
3153
const textColor = colorScheme === "dark" ? "black" : "white";
3254
return (
3355
<Badge color={color} variant="filled" fw={500} c={textColor}>
34-
{label}
56+
{formatLabel(facet, value)}
3557
</Badge>
3658
);
3759
}

clients/web/src/components/elements/CapabilityItem/CapabilityItem.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ type Story = StoryObj<typeof CapabilityItem>;
1111

1212
export const Supported: Story = {
1313
args: {
14-
name: "Tools",
14+
capability: "tools",
1515
supported: true,
1616
},
1717
};
1818

1919
export const SupportedWithCount: Story = {
2020
args: {
21-
name: "Tools",
21+
capability: "tools",
2222
supported: true,
2323
count: 4,
2424
},
2525
};
2626

2727
export const NotSupported: Story = {
2828
args: {
29-
name: "Completions",
29+
capability: "completions",
3030
supported: false,
3131
},
3232
};

clients/web/src/components/elements/CapabilityItem/CapabilityItem.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
11
import { Group, Text } from "@mantine/core";
2+
import type {
3+
ClientCapabilities,
4+
ServerCapabilities,
5+
} from "@modelcontextprotocol/sdk/types.js";
6+
7+
export type CapabilityKey = keyof ServerCapabilities | keyof ClientCapabilities;
28

39
export interface CapabilityItemProps {
4-
name: string;
10+
capability: CapabilityKey;
511
supported: boolean;
612
count?: number;
713
}
814

15+
const displayLabel: Record<string, string> = {
16+
tools: "Tools",
17+
resources: "Resources",
18+
prompts: "Prompts",
19+
logging: "Logging",
20+
completions: "Completions",
21+
tasks: "Tasks",
22+
experimental: "Experimental",
23+
roots: "Roots",
24+
sampling: "Sampling",
25+
elicitation: "Elicitation",
26+
};
27+
928
export function CapabilityItem({
10-
name,
29+
capability,
1130
supported,
1231
count,
1332
}: CapabilityItemProps) {
33+
const name = displayLabel[capability] ?? String(capability);
1434
const label = count != null ? `${name} (${count})` : name;
1535

1636
return (

clients/web/src/components/elements/ConnectionToggle/ConnectionToggle.stories.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const meta: Meta<typeof ConnectionToggle> = {
66
title: "Elements/ConnectionToggle",
77
component: ConnectionToggle,
88
args: {
9-
onChange: fn(),
9+
onConnect: fn(),
10+
onDisconnect: fn(),
1011
},
1112
};
1213

@@ -15,32 +16,31 @@ type Story = StoryObj<typeof ConnectionToggle>;
1516

1617
export const Connected: Story = {
1718
args: {
18-
checked: true,
19-
loading: false,
20-
disabled: false,
19+
status: "connected",
2120
},
2221
};
2322

2423
export const Disconnected: Story = {
2524
args: {
26-
checked: false,
27-
loading: false,
28-
disabled: false,
25+
status: "disconnected",
2926
},
3027
};
3128

32-
export const Loading: Story = {
29+
export const Connecting: Story = {
3330
args: {
34-
checked: false,
35-
loading: true,
36-
disabled: false,
31+
status: "connecting",
3732
},
3833
};
3934

4035
export const Disabled: Story = {
4136
args: {
42-
checked: false,
43-
loading: false,
37+
status: "disconnected",
4438
disabled: true,
4539
},
4640
};
41+
42+
export const Error: Story = {
43+
args: {
44+
status: "error",
45+
},
46+
};
Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
import { Switch } from "@mantine/core";
2+
import type { ConnectionStatus } from "@inspector/core/mcp/types.js";
23

34
export interface ConnectionToggleProps {
4-
checked: boolean;
5-
loading: boolean;
6-
disabled: boolean;
7-
onChange: (checked: boolean) => void;
5+
status: ConnectionStatus;
6+
disabled?: boolean;
7+
onConnect: () => void;
8+
onDisconnect: () => void;
89
}
910

1011
export function ConnectionToggle({
11-
checked,
12-
loading,
13-
disabled,
14-
onChange,
12+
status,
13+
disabled = false,
14+
onConnect,
15+
onDisconnect,
1516
}: ConnectionToggleProps) {
17+
const isConnected = status === "connected";
18+
const isConnecting = status === "connecting";
19+
1620
return (
1721
<Switch
1822
size="lg"
19-
checked={checked || loading}
20-
disabled={disabled || loading}
21-
onChange={(event) => onChange(event.currentTarget.checked)}
23+
checked={isConnected || isConnecting}
24+
disabled={disabled || isConnecting}
25+
onChange={(event) => {
26+
if (event.currentTarget.checked) {
27+
onConnect();
28+
} else {
29+
onDisconnect();
30+
}
31+
}}
2232
/>
2333
);
2434
}

0 commit comments

Comments
 (0)