@mcp-b/react-components 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { McpServerCard, McpServerManualSetup, McpServerSetupAuth } from "../utils/mcp-server-catalog.js";
1
+ import { McpServerSetupAuth } from "../utils/mcp-server-catalog.js";
2
2
  import * as React from "react";
3
3
 
4
4
  //#region src/components/AgentConnection.d.ts
@@ -25,19 +25,14 @@ type NanitesAgentConnectionOptions = {
25
25
  type AgentConnectionPanelProps = {
26
26
  readonly className?: string;
27
27
  readonly commands?: readonly AgentConnectionCommand[];
28
- readonly dcrMcpServers?: readonly McpServerCard[];
29
28
  readonly defaultTarget?: AgentConnectionTarget;
30
29
  readonly headingLevel?: 2 | 3;
31
- readonly manualMcpServers?: readonly McpServerCard[];
32
30
  readonly origin?: string;
33
31
  readonly section?: boolean;
34
32
  };
35
33
  type AgentConnectionPopoverProps = Omit<AgentConnectionPanelProps, "section"> & {
36
34
  readonly className?: string;
37
35
  };
38
- type McpServerSetupProps = {
39
- readonly setup: McpServerManualSetup;
40
- };
41
36
  type McpConnectorFormValues = {
42
37
  readonly bearerToken?: string;
43
38
  readonly clientId?: string;
@@ -46,11 +41,10 @@ type McpConnectorFormValues = {
46
41
  readonly scope?: string;
47
42
  readonly url: string;
48
43
  };
49
- type McpConnectorFormDefaults = Partial<Pick<McpConnectorFormValues, "name" | "url">>;
50
44
  type McpConnectorFormProps = Omit<React.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "status"> & {
51
45
  /** Authentication metadata that decides which credential fields render. */readonly auth?: McpServerSetupAuth; /** Label for the OAuth authorization button. */
52
46
  readonly authorizeLabel?: string; /** Initial MCP name and URL values. */
53
- readonly defaults?: McpConnectorFormDefaults; /** Pattern used to validate the MCP name field. */
47
+ readonly defaults?: Partial<Pick<McpConnectorFormValues, "name" | "url">>; /** Pattern used to validate the MCP name field. */
54
48
  readonly namePattern?: string; /** OAuth URL waiting for the user to authorize, when available. */
55
49
  readonly pendingAuthUrl?: string | null; /** Read-only redirect URL shown for manual OAuth client setup. */
56
50
  readonly redirectUrl?: string; /** Inline connection status announced politely to assistive tech. */
@@ -81,16 +75,11 @@ declare function buildNanitesAgentConnectionCommands(origin: string, {
81
75
  declare function AgentConnectionPanel({
82
76
  className,
83
77
  commands: commandsProp,
84
- dcrMcpServers,
85
78
  defaultTarget,
86
79
  headingLevel,
87
- manualMcpServers,
88
80
  origin,
89
81
  section
90
82
  }: AgentConnectionPanelProps): React.JSX.Element | null;
91
- declare function McpServerSetup({
92
- setup
93
- }: McpServerSetupProps): React.JSX.Element;
94
83
  /** Collects MCP connector settings and optional credentials with native form validation. */
95
84
  declare function McpConnectorForm({
96
85
  auth,
@@ -118,4 +107,4 @@ declare function AgentConnectionPopover({
118
107
  ...props
119
108
  }: AgentConnectionPopoverProps): React.JSX.Element;
120
109
  //#endregion
121
- export { AgentConnectionCommand, AgentConnectionPanel, AgentConnectionPanelProps, AgentConnectionPopover, AgentConnectionPopoverProps, AgentConnectionTarget, Connection, ConnectionProps, McpConnectorForm, McpConnectorFormDefaults, McpConnectorFormProps, McpConnectorFormValues, McpServerSetup, McpServerSetupProps, NanitesAgentConnectionOptions, buildNanitesAgentConnectionCommands };
110
+ export { AgentConnectionCommand, AgentConnectionPanel, AgentConnectionPanelProps, AgentConnectionPopover, AgentConnectionPopoverProps, AgentConnectionTarget, Connection, ConnectionProps, McpConnectorForm, McpConnectorFormProps, McpConnectorFormValues, NanitesAgentConnectionOptions, buildNanitesAgentConnectionCommands };
@@ -5,7 +5,6 @@ import { Button } from "./Button.js";
5
5
  import { a as CodeBlockCopyButton, i as CodeBlockContent, n as CodeBlockActions, p as CodeBlockTitle, r as CodeBlockContainer, s as CodeBlockHeader, t as CodeBlock } from "../CodeBlock-XNQOupQ3.js";
6
6
  import { Field } from "./Field.js";
7
7
  import { Form } from "./Form.js";
8
- import { DCR_MCP_SERVER_CARDS, MANUAL_MCP_SERVER_CARDS, getMcpServerIconSrc } from "../utils/mcp-server-catalog.js";
9
8
  import * as React from "react";
10
9
  import { jsx, jsxs } from "react/jsx-runtime";
11
10
  //#region src/components/AgentConnection.tsx
@@ -104,7 +103,7 @@ function buildNanitesAgentConnectionCommands(origin, { mcpName = "nanites", plug
104
103
  * Use inside setup screens where users need Codex, Claude Code, skill-only,
105
104
  * or raw MCP JSON connection instructions.
106
105
  */
107
- function AgentConnectionPanel({ className, commands: commandsProp, dcrMcpServers = DCR_MCP_SERVER_CARDS, defaultTarget = "codex", headingLevel = 2, manualMcpServers = MANUAL_MCP_SERVER_CARDS, origin, section = true }) {
106
+ function AgentConnectionPanel({ className, commands: commandsProp, defaultTarget = "codex", headingLevel = 2, origin, section = true }) {
108
107
  const commands = React.useMemo(() => commandsProp ?? buildNanitesAgentConnectionCommands(origin ?? getBrowserOrigin()), [commandsProp, origin]);
109
108
  const [target, setTarget] = React.useState(defaultTarget);
110
109
  const selected = commands.find((command) => command.target === target) ?? commands[0];
@@ -150,72 +149,7 @@ function AgentConnectionPanel({ className, commands: commandsProp, dcrMcpServers
150
149
  code: selected.code,
151
150
  language: selected.language,
152
151
  children: [/* @__PURE__ */ jsxs(CodeBlockHeader, { children: [/* @__PURE__ */ jsx(CodeBlockTitle, { children: selected.label }), /* @__PURE__ */ jsx(CodeBlockActions, { children: /* @__PURE__ */ jsx(CodeBlockCopyButton, {}) })] }), /* @__PURE__ */ jsx(CodeBlockContainer, { children: /* @__PURE__ */ jsx(CodeBlockContent, {}) })]
153
- }),
154
- dcrMcpServers.length > 0 ? /* @__PURE__ */ jsx(McpServerList, {
155
- heading: "Auto",
156
- servers: dcrMcpServers
157
- }) : null,
158
- manualMcpServers.length > 0 ? /* @__PURE__ */ jsx(McpServerList, {
159
- heading: "Manual",
160
- servers: manualMcpServers
161
- }) : null
162
- ]
163
- });
164
- }
165
- function McpServerList({ heading, servers }) {
166
- return /* @__PURE__ */ jsxs("div", {
167
- className: "agent-connect__mcp",
168
- children: [/* @__PURE__ */ jsx("p", {
169
- className: "agent-connect__mcp-heading",
170
- children: heading
171
- }), /* @__PURE__ */ jsx("ul", {
172
- className: "agent-connect__mcp-list",
173
- role: "list",
174
- children: servers.map((server) => /* @__PURE__ */ jsxs("li", {
175
- className: "agent-connect__mcp-item",
176
- children: [/* @__PURE__ */ jsx("span", {
177
- className: "agent-connect__mcp-icon",
178
- children: renderMcpServerIcon(server)
179
- }), /* @__PURE__ */ jsxs("div", {
180
- className: "agent-connect__mcp-copy",
181
- children: [
182
- /* @__PURE__ */ jsx("a", {
183
- className: "agent-connect__mcp-name",
184
- href: server.url,
185
- target: "_blank",
186
- rel: "noreferrer",
187
- children: server.name
188
- }),
189
- server.description ? /* @__PURE__ */ jsx("span", {
190
- className: "agent-connect__mcp-description",
191
- children: server.description
192
- }) : null,
193
- server.manualSetup ? /* @__PURE__ */ jsx(McpServerSetup, { setup: server.manualSetup }) : null
194
- ]
195
- })]
196
- }, server.id))
197
- })]
198
- });
199
- }
200
- function McpServerSetup({ setup }) {
201
- return /* @__PURE__ */ jsxs("div", {
202
- className: "agent-connect__mcp-setup",
203
- children: [
204
- /* @__PURE__ */ jsx("p", { children: setup.description }),
205
- /* @__PURE__ */ jsxs("p", {
206
- className: "agent-connect__mcp-setup-auth",
207
- children: [/* @__PURE__ */ jsx("span", { children: setup.auth.label }), setup.auth.fields.length > 0 ? /* @__PURE__ */ jsx("span", { children: setup.auth.fields.map((field) => field.label).join(", ") }) : null]
208
- }),
209
- setup.links.length > 0 ? /* @__PURE__ */ jsx("ul", {
210
- className: "agent-connect__mcp-setup-links",
211
- role: "list",
212
- children: setup.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
213
- href: link.url,
214
- target: "_blank",
215
- rel: "noreferrer",
216
- children: link.label
217
- }) }, `${link.label}:${link.url}`))
218
- }) : null
152
+ })
219
153
  ]
220
154
  });
221
155
  }
@@ -362,28 +296,6 @@ function readFormString(data, name) {
362
296
  function isCredentialAuthField(field) {
363
297
  return field.name !== "redirectUrl";
364
298
  }
365
- function renderMcpServerIcon(server) {
366
- const src = getMcpServerIconSrc(server);
367
- if (src) return /* @__PURE__ */ jsx(McpServerIconImage, {
368
- src,
369
- name: server.name
370
- });
371
- return server.name.slice(0, 1);
372
- }
373
- function McpServerIconImage({ src, name }) {
374
- const [failed, setFailed] = React.useState(false);
375
- if (failed) return name.slice(0, 1);
376
- return /* @__PURE__ */ jsx("img", {
377
- src,
378
- alt: "",
379
- width: 16,
380
- height: 16,
381
- loading: "lazy",
382
- decoding: "async",
383
- referrerPolicy: "no-referrer",
384
- onError: () => setFailed(true)
385
- });
386
- }
387
299
  /**
388
300
  * Compact popover trigger for showing AgentConnectionPanel inline.
389
301
  */
@@ -412,4 +324,4 @@ function AgentConnectionPopover({ className, ...props }) {
412
324
  }) })] });
413
325
  }
414
326
  //#endregion
415
- export { AgentConnectionPanel, AgentConnectionPopover, Connection, McpConnectorForm, McpServerSetup, buildNanitesAgentConnectionCommands };
327
+ export { AgentConnectionPanel, AgentConnectionPopover, Connection, McpConnectorForm, buildNanitesAgentConnectionCommands };
@@ -0,0 +1,46 @@
1
+ import * as React from "react";
2
+ import { BrowserLiveView } from "agents/browser";
3
+
4
+ //#region src/components/BrowserRunPanel.d.ts
5
+ interface BrowserRunPanelProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
6
+ /** Host-side Browser Run Live View data from `connector.liveView()`. */
7
+ liveView?: BrowserLiveView;
8
+ /** Refreshes the Live View URL before it expires. */
9
+ onRefresh?: () => void | Promise<void>;
10
+ /** Closes the app-owned shared browser session. */
11
+ onCloseSession?: () => void | Promise<void>;
12
+ /** True while the app is fetching Live View data. */
13
+ loading?: boolean;
14
+ /** Error from the app-owned browser session fetch/refresh path. */
15
+ error?: React.ReactNode;
16
+ /** Panel heading. */
17
+ label?: React.ReactNode;
18
+ /** Empty state shown when there is no shared browser session. */
19
+ empty?: React.ReactNode;
20
+ /** Fallback passed through to `BrowserLiveView` after URL expiry/failure. */
21
+ fallback?: React.ReactNode;
22
+ }
23
+ /**
24
+ * Right-side Browser Run panel for `ThinkFullApp.workbenchPanels`.
25
+ *
26
+ * The app owns `createBrowserRuntime()`, `connector.liveView()`, polling, and
27
+ * session cleanup. This component only renders upstream `BrowserLiveView`
28
+ * data and calls app-provided refresh/close callbacks.
29
+ */
30
+ declare function BrowserRunPanel({
31
+ liveView,
32
+ onRefresh,
33
+ onCloseSession,
34
+ loading,
35
+ error,
36
+ label,
37
+ empty,
38
+ fallback,
39
+ className,
40
+ ref,
41
+ ...props
42
+ }: BrowserRunPanelProps & {
43
+ ref?: React.Ref<HTMLDivElement>;
44
+ }): React.JSX.Element;
45
+ //#endregion
46
+ export { BrowserRunPanel, BrowserRunPanelProps };
@@ -0,0 +1,123 @@
1
+ import { t as cx } from "../class-names-9UtZwb0J.js";
2
+ import { C as MonitorIcon, L as XIcon, M as SpinnerIcon, k as RefreshIcon } from "../icons-D2Q5n5C1.js";
3
+ import { Button } from "./Button.js";
4
+ import { BrowserLiveView } from "./BrowserLiveView.js";
5
+ import * as React from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/BrowserRunPanel.tsx
8
+ function isInspectablePage(target) {
9
+ const pageUrl = target.pageUrl;
10
+ return Boolean(pageUrl && !pageUrl.startsWith("about:") && !pageUrl.startsWith("chrome:") && !pageUrl.startsWith("devtools:"));
11
+ }
12
+ function targetLabel(target) {
13
+ return target.title || target.pageUrl || target.targetId;
14
+ }
15
+ function pickTarget(targets, targetId) {
16
+ return (targetId ? targets.find((target) => target.targetId === targetId) : void 0) ?? targets.find(isInspectablePage) ?? targets[0];
17
+ }
18
+ function BrowserRunPanelState({ children, role, tone = "neutral" }) {
19
+ return /* @__PURE__ */ jsx("div", {
20
+ className: "browser-run-panel__state",
21
+ "data-tone": tone,
22
+ role: role ?? (tone === "danger" ? "alert" : void 0),
23
+ children
24
+ });
25
+ }
26
+ /**
27
+ * Right-side Browser Run panel for `ThinkFullApp.workbenchPanels`.
28
+ *
29
+ * The app owns `createBrowserRuntime()`, `connector.liveView()`, polling, and
30
+ * session cleanup. This component only renders upstream `BrowserLiveView`
31
+ * data and calls app-provided refresh/close callbacks.
32
+ */
33
+ function BrowserRunPanel({ liveView, onRefresh, onCloseSession, loading, error, label = "Browser", empty = "No live browser session", fallback, className, ref, ...props }) {
34
+ const [selectedTargetId, setSelectedTargetId] = React.useState();
35
+ const [receivedAt, setReceivedAt] = React.useState(() => Date.now());
36
+ React.useEffect(() => {
37
+ if (liveView) setReceivedAt(Date.now());
38
+ }, [liveView]);
39
+ const targets = liveView?.targets ?? [];
40
+ const target = pickTarget(targets, selectedTargetId);
41
+ const pageLabel = target ? targetLabel(target) : "Waiting for a shared browser session";
42
+ return /* @__PURE__ */ jsxs("section", {
43
+ ref,
44
+ className: cx("browser-run-panel", className),
45
+ "aria-label": typeof label === "string" ? label : "Browser",
46
+ ...props,
47
+ children: [
48
+ /* @__PURE__ */ jsxs("header", {
49
+ className: "browser-run-panel__header",
50
+ children: [/* @__PURE__ */ jsxs("div", {
51
+ className: "browser-run-panel__identity",
52
+ children: [/* @__PURE__ */ jsx(MonitorIcon, { className: "browser-run-panel__icon" }), /* @__PURE__ */ jsxs("div", {
53
+ className: "browser-run-panel__title-block",
54
+ children: [/* @__PURE__ */ jsx("span", {
55
+ className: "browser-run-panel__title",
56
+ children: label
57
+ }), /* @__PURE__ */ jsx("span", {
58
+ className: "browser-run-panel__url",
59
+ title: pageLabel,
60
+ children: pageLabel
61
+ })]
62
+ })]
63
+ }), /* @__PURE__ */ jsxs("div", {
64
+ className: "browser-run-panel__actions",
65
+ children: [onRefresh ? /* @__PURE__ */ jsx(Button, {
66
+ type: "button",
67
+ variant: "ghost",
68
+ color: "neutral",
69
+ size: "icon-sm",
70
+ "aria-label": "Refresh browser view",
71
+ disabled: loading,
72
+ onClick: () => void onRefresh(),
73
+ children: /* @__PURE__ */ jsx(RefreshIcon, {})
74
+ }) : null, onCloseSession ? /* @__PURE__ */ jsx(Button, {
75
+ type: "button",
76
+ variant: "ghost",
77
+ color: "neutral",
78
+ size: "icon-sm",
79
+ "aria-label": "Close browser session",
80
+ onClick: () => void onCloseSession(),
81
+ children: /* @__PURE__ */ jsx(XIcon, {})
82
+ }) : null]
83
+ })]
84
+ }),
85
+ targets.length > 1 ? /* @__PURE__ */ jsx("div", {
86
+ className: "browser-run-panel__targets",
87
+ "aria-label": "Browser tabs",
88
+ children: targets.map((candidate) => /* @__PURE__ */ jsxs("button", {
89
+ type: "button",
90
+ className: "browser-run-panel__target",
91
+ "aria-pressed": candidate.targetId === target?.targetId,
92
+ onClick: () => setSelectedTargetId(candidate.targetId),
93
+ children: [/* @__PURE__ */ jsx("span", {
94
+ className: "browser-run-panel__target-title",
95
+ children: targetLabel(candidate)
96
+ }), candidate.pageUrl ? /* @__PURE__ */ jsx("span", {
97
+ className: "browser-run-panel__target-url",
98
+ children: candidate.pageUrl
99
+ }) : null]
100
+ }, candidate.targetId))
101
+ }) : null,
102
+ error ? /* @__PURE__ */ jsx(BrowserRunPanelState, {
103
+ tone: "danger",
104
+ children: error
105
+ }) : null,
106
+ /* @__PURE__ */ jsx("div", {
107
+ className: "browser-run-panel__body",
108
+ "aria-busy": loading || void 0,
109
+ children: target && liveView ? /* @__PURE__ */ jsx(BrowserLiveView, {
110
+ url: target.url,
111
+ expiresAt: receivedAt + liveView.expiresInMs,
112
+ pageTitle: target.title ?? target.pageUrl,
113
+ fallback
114
+ }) : loading ? /* @__PURE__ */ jsxs(BrowserRunPanelState, {
115
+ role: "status",
116
+ children: [/* @__PURE__ */ jsx(SpinnerIcon, { className: "browser-run-panel__spinner" }), "Loading browser session"]
117
+ }) : /* @__PURE__ */ jsx(BrowserRunPanelState, { children: empty })
118
+ })
119
+ ]
120
+ });
121
+ }
122
+ //#endregion
123
+ export { BrowserRunPanel };
@@ -0,0 +1,41 @@
1
+ import * as React from "react";
2
+ import { MCPServer, MCPServersState } from "agents";
3
+
4
+ //#region src/components/McpServerConnections.d.ts
5
+ type McpServerConnectionAction = (serverId: string, server: MCPServer) => void | Promise<void>;
6
+ interface McpServerConnectionsProps extends React.HTMLAttributes<HTMLElement> {
7
+ /** Upstream Agents SDK MCP state from `getMcpServers()` or `useAgent({ onMcpUpdate })`. */
8
+ mcp: MCPServersState;
9
+ /** Optional heading for the connected-server list. */
10
+ heading?: React.ReactNode;
11
+ /** Called when an OAuth server needs user authorization. */
12
+ onAuthorize?: McpServerConnectionAction;
13
+ /** Called when a failed server should retry through an app-owned Agent RPC. */
14
+ onRetry?: McpServerConnectionAction;
15
+ /** Called when a ready/connected server should refresh discovery through an app-owned Agent RPC. */
16
+ onRefresh?: McpServerConnectionAction;
17
+ /** Called when a server transport should close but the stored config should remain. */
18
+ onDisconnect?: McpServerConnectionAction;
19
+ /** Should call `removeMcpServer(serverId)`; Agents SDK disconnects and removes storage. */
20
+ onRemove?: McpServerConnectionAction;
21
+ }
22
+ /**
23
+ * Runtime MCP server list. Add servers with `McpServerPicker`; render connected
24
+ * state here from the upstream Agents SDK `MCPServersState`.
25
+ */
26
+ declare function McpServerConnections({
27
+ className,
28
+ heading,
29
+ mcp,
30
+ onAuthorize,
31
+ onDisconnect,
32
+ onRefresh,
33
+ onRemove,
34
+ onRetry,
35
+ ref,
36
+ ...props
37
+ }: McpServerConnectionsProps & {
38
+ ref?: React.Ref<HTMLElement>;
39
+ }): React.JSX.Element;
40
+ //#endregion
41
+ export { McpServerConnections, McpServerConnectionsProps };
@@ -0,0 +1,188 @@
1
+ import { t as cx } from "../class-names-9UtZwb0J.js";
2
+ import { F as WarningIcon, L as XIcon, M as SpinnerIcon, a as CheckIcon, k as RefreshIcon } from "../icons-D2Q5n5C1.js";
3
+ import { Button } from "./Button.js";
4
+ import { Badge } from "./Badge.js";
5
+ import * as React from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/McpServerConnections.tsx
8
+ /**
9
+ * Runtime MCP server list. Add servers with `McpServerPicker`; render connected
10
+ * state here from the upstream Agents SDK `MCPServersState`.
11
+ */
12
+ function McpServerConnections({ className, heading = "Connected MCP servers", mcp, onAuthorize, onDisconnect, onRefresh, onRemove, onRetry, ref, ...props }) {
13
+ const [pendingAction, setPendingAction] = React.useState(null);
14
+ const entries = Object.entries(mcp.servers);
15
+ async function runAction(action, serverId, server, handler) {
16
+ if (!handler) return;
17
+ setPendingAction(`${action}:${serverId}`);
18
+ try {
19
+ await handler(serverId, server);
20
+ } finally {
21
+ setPendingAction(null);
22
+ }
23
+ }
24
+ return /* @__PURE__ */ jsxs("section", {
25
+ ref,
26
+ className: cx("mcp-server-connections", className),
27
+ ...props,
28
+ children: [/* @__PURE__ */ jsxs("div", {
29
+ className: "mcp-server-connections__header",
30
+ children: [/* @__PURE__ */ jsx("h2", { children: heading }), /* @__PURE__ */ jsxs("span", {
31
+ className: "mcp-server-connections__summary",
32
+ children: [
33
+ entries.length,
34
+ " ",
35
+ entries.length === 1 ? "server" : "servers"
36
+ ]
37
+ })]
38
+ }), entries.length === 0 ? /* @__PURE__ */ jsx("p", {
39
+ className: "mcp-server-connections__empty",
40
+ children: "No MCP servers connected."
41
+ }) : /* @__PURE__ */ jsx("ul", {
42
+ className: "mcp-server-connections__list",
43
+ role: "list",
44
+ children: entries.map(([serverId, server]) => {
45
+ const counts = getServerCapabilityCounts(mcp, serverId);
46
+ const status = getServerStatus(server);
47
+ const state = server.state;
48
+ const pending = (action) => pendingAction === `${action}:${serverId}`;
49
+ return /* @__PURE__ */ jsxs("li", {
50
+ className: "mcp-server-connections__item",
51
+ children: [/* @__PURE__ */ jsxs("div", {
52
+ className: "mcp-server-connections__main",
53
+ children: [
54
+ /* @__PURE__ */ jsxs("div", {
55
+ className: "mcp-server-connections__title-row",
56
+ children: [/* @__PURE__ */ jsx("span", {
57
+ className: "mcp-server-connections__name",
58
+ children: server.name
59
+ }), /* @__PURE__ */ jsxs(Badge, {
60
+ color: status.color,
61
+ size: "sm",
62
+ className: "mcp-server-connections__status",
63
+ children: [status.icon, status.label]
64
+ })]
65
+ }),
66
+ /* @__PURE__ */ jsx("span", {
67
+ className: "mcp-server-connections__url",
68
+ children: server.server_url
69
+ }),
70
+ server.error ? /* @__PURE__ */ jsx("p", {
71
+ className: "mcp-server-connections__error",
72
+ children: server.error
73
+ }) : null,
74
+ server.instructions ? /* @__PURE__ */ jsx("p", {
75
+ className: "mcp-server-connections__instructions",
76
+ children: server.instructions
77
+ }) : null,
78
+ /* @__PURE__ */ jsxs("p", {
79
+ className: "mcp-server-connections__capabilities",
80
+ children: [
81
+ counts.tools,
82
+ " tools, ",
83
+ counts.prompts,
84
+ " prompts, ",
85
+ counts.resources,
86
+ " resources"
87
+ ]
88
+ })
89
+ ]
90
+ }), /* @__PURE__ */ jsxs("div", {
91
+ className: "mcp-server-connections__actions",
92
+ children: [
93
+ state === "authenticating" && onAuthorize ? /* @__PURE__ */ jsx(Button, {
94
+ type: "button",
95
+ size: "xs",
96
+ variant: "outline",
97
+ color: "primary",
98
+ disabled: pending("authorize"),
99
+ onClick: () => void runAction("authorize", serverId, server, onAuthorize),
100
+ children: pending("authorize") ? "Opening" : "Authorize"
101
+ }) : null,
102
+ state === "failed" && onRetry ? /* @__PURE__ */ jsxs(Button, {
103
+ type: "button",
104
+ size: "xs",
105
+ variant: "outline",
106
+ color: "neutral",
107
+ disabled: pending("retry"),
108
+ onClick: () => void runAction("retry", serverId, server, onRetry),
109
+ children: [/* @__PURE__ */ jsx(RefreshIcon, {}), pending("retry") ? "Retrying" : "Retry"]
110
+ }) : null,
111
+ (state === "ready" || state === "connected") && onRefresh ? /* @__PURE__ */ jsx(Button, {
112
+ type: "button",
113
+ size: "icon-xs",
114
+ variant: "ghost",
115
+ color: "neutral",
116
+ "aria-label": `Refresh ${server.name} capabilities`,
117
+ disabled: pending("refresh"),
118
+ onClick: () => void runAction("refresh", serverId, server, onRefresh),
119
+ children: /* @__PURE__ */ jsx(RefreshIcon, {})
120
+ }) : null,
121
+ state !== "failed" && onDisconnect ? /* @__PURE__ */ jsx(Button, {
122
+ type: "button",
123
+ size: "xs",
124
+ variant: "outline",
125
+ color: "neutral",
126
+ disabled: pending("disconnect"),
127
+ onClick: () => void runAction("disconnect", serverId, server, onDisconnect),
128
+ children: pending("disconnect") ? "Disconnecting" : "Disconnect"
129
+ }) : null,
130
+ onRemove ? /* @__PURE__ */ jsx(Button, {
131
+ type: "button",
132
+ size: "icon-xs",
133
+ variant: "ghost",
134
+ color: "destructive",
135
+ "aria-label": `Remove ${server.name}`,
136
+ disabled: pending("remove"),
137
+ onClick: () => void runAction("remove", serverId, server, onRemove),
138
+ children: /* @__PURE__ */ jsx(XIcon, {})
139
+ }) : null
140
+ ]
141
+ })]
142
+ }, serverId);
143
+ })
144
+ })]
145
+ });
146
+ }
147
+ function getServerCapabilityCounts(mcp, serverId) {
148
+ return {
149
+ tools: mcp.tools.filter((tool) => tool.serverId === serverId).length,
150
+ prompts: mcp.prompts.filter((prompt) => prompt.serverId === serverId).length,
151
+ resources: mcp.resources.filter((resource) => resource.serverId === serverId).length
152
+ };
153
+ }
154
+ function getServerStatus(server) {
155
+ const state = server.state;
156
+ if (state === "ready") return {
157
+ color: "success",
158
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
159
+ label: "Ready"
160
+ };
161
+ if (state === "failed") return {
162
+ color: "destructive",
163
+ icon: /* @__PURE__ */ jsx(WarningIcon, {}),
164
+ label: "Failed"
165
+ };
166
+ if (state === "authenticating") return {
167
+ color: "warning",
168
+ icon: /* @__PURE__ */ jsx(WarningIcon, {}),
169
+ label: "Authorize"
170
+ };
171
+ if (state === "connecting") return {
172
+ color: "neutral",
173
+ icon: /* @__PURE__ */ jsx(SpinnerIcon, { className: "mcp-server-connections__spinner" }),
174
+ label: "Connecting"
175
+ };
176
+ if (state === "discovering") return {
177
+ color: "neutral",
178
+ icon: /* @__PURE__ */ jsx(SpinnerIcon, { className: "mcp-server-connections__spinner" }),
179
+ label: "Discovering"
180
+ };
181
+ return {
182
+ color: "neutral",
183
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
184
+ label: "Connected"
185
+ };
186
+ }
187
+ //#endregion
188
+ export { McpServerConnections };
@@ -141,180 +141,18 @@
141
141
  line-height: 1.5;
142
142
  }
143
143
 
144
- .agent-connect__mcp {
145
- display: grid;
146
- gap: 0.5rem;
147
- min-inline-size: 0;
148
- }
149
-
150
- .agent-connect__mcp-heading {
151
- margin: 0;
152
- color: var(--sigvelo-color-text-muted);
153
- font-size: 0.74rem;
154
- font-weight: var(--sigvelo-font-weight-semibold);
155
- line-height: 1.25;
156
- }
157
-
158
- .agent-connect__mcp-list {
159
- display: grid;
160
- grid-template-columns: repeat(2, minmax(0, 1fr));
161
- gap: 0.35rem;
162
- max-block-size: 24rem;
163
- margin: 0;
164
- padding: 0;
165
- overflow-y: auto;
166
- overscroll-behavior: contain;
167
- list-style: none;
168
- }
169
-
170
- .agent-connect__mcp-item {
171
- display: grid;
172
- grid-template-columns: 1.625rem minmax(0, 1fr);
173
- gap: 0.5rem;
174
- align-items: start;
175
- min-inline-size: 0;
176
- padding: 0.5rem;
177
- border: var(--sigvelo-border-style) var(--sigvelo-border-width)
178
- var(--sigvelo-color-neutral-border-subtle);
179
- border-radius: var(--sigvelo-radius-md);
180
- background: var(--sigvelo-color-surface);
181
- }
182
-
183
- .agent-connect__mcp-icon {
184
- display: grid;
185
- place-items: center;
186
- inline-size: 1.625rem;
187
- block-size: 1.625rem;
188
- border-radius: var(--sigvelo-radius-sm);
189
- background: var(--sigvelo-color-neutral-bg-subtle);
190
- color: var(--sigvelo-color-text-muted);
191
- font-size: 0.72rem;
192
- font-weight: var(--sigvelo-font-weight-bold);
193
- line-height: 1;
194
- }
195
-
196
- .agent-connect__mcp-icon img {
197
- display: block;
198
- max-inline-size: 1rem;
199
- max-block-size: 1rem;
200
- }
201
-
202
- .agent-connect__mcp-copy {
203
- display: grid;
204
- gap: 0.08rem;
205
- min-inline-size: 0;
206
- }
207
-
208
- .agent-connect__mcp-name {
209
- color: var(--sigvelo-color-text);
210
- font-size: 0.78rem;
211
- font-weight: var(--sigvelo-font-weight-semibold);
212
- line-height: 1.2;
213
- overflow-wrap: anywhere;
214
- text-decoration: none;
215
- }
216
-
217
- .agent-connect__mcp-name:hover {
218
- color: var(--sigvelo-color-primary-text);
219
- text-decoration: underline;
220
- text-underline-offset: 0.16em;
221
- }
222
-
223
- .agent-connect__mcp-name:focus-visible {
224
- outline: 2px solid var(--sigvelo-color-focus);
225
- outline-offset: 2px;
226
- }
227
-
228
- .agent-connect__mcp-description {
229
- color: var(--sigvelo-color-text-muted);
230
- font-size: 0.7rem;
231
- line-height: 1.25;
232
- overflow-wrap: anywhere;
233
- }
234
-
235
- .agent-connect__mcp-setup {
236
- display: grid;
237
- gap: 0.3rem;
238
- margin-block-start: 0.2rem;
239
- min-inline-size: 0;
240
- }
241
-
242
- .agent-connect__mcp-setup p {
243
- margin: 0;
244
- color: var(--sigvelo-color-text-muted);
245
- font-size: 0.68rem;
246
- line-height: 1.3;
247
- overflow-wrap: anywhere;
248
- }
249
-
250
- .agent-connect__mcp-setup-auth {
251
- display: flex;
252
- flex-wrap: wrap;
253
- gap: 0.25rem;
254
- }
255
-
256
- .agent-connect__mcp-setup-auth span:first-child {
257
- color: var(--sigvelo-color-text);
258
- font-weight: var(--sigvelo-font-weight-semibold);
259
- }
260
-
261
- .agent-connect__mcp-setup-links {
262
- display: flex;
263
- flex-wrap: wrap;
264
- gap: 0.25rem;
265
- margin: 0;
266
- padding: 0;
267
- list-style: none;
268
- }
269
-
270
- .agent-connect__mcp-setup-links a {
271
- display: inline-flex;
272
- align-items: center;
273
- min-block-size: 1.35rem;
274
- padding: 0 0.35rem;
275
- border: var(--sigvelo-border-style) var(--sigvelo-border-width)
276
- var(--sigvelo-color-neutral-border-subtle);
277
- border-radius: var(--sigvelo-radius-sm);
278
- color: var(--sigvelo-color-text-muted);
279
- font-size: 0.65rem;
280
- font-weight: var(--sigvelo-font-weight-semibold);
281
- line-height: 1.1;
282
- text-decoration: none;
283
- }
284
-
285
- .agent-connect__mcp-setup-links a:hover {
286
- border-color: var(--sigvelo-color-primary-border-muted);
287
- color: var(--sigvelo-color-primary-text);
288
- }
289
-
290
- .agent-connect__mcp-setup-links a:focus-visible {
291
- outline: 2px solid var(--sigvelo-color-focus);
292
- outline-offset: 2px;
293
- }
294
-
295
144
  .agent-connect__mcp-form {
296
145
  display: grid;
297
146
  gap: 0.75rem;
298
147
  min-inline-size: 0;
299
148
  }
300
149
 
301
- .agent-connect__mcp-form--row {
302
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
303
- align-items: end;
304
- padding: 0.75rem;
305
- background: var(--sigvelo-color-surface);
306
- }
307
-
308
150
  .agent-connect__mcp-form-actions {
309
151
  display: flex;
310
152
  flex-wrap: wrap;
311
153
  gap: 0.5rem;
312
154
  }
313
155
 
314
- .agent-connect__mcp-form--row .agent-connect__mcp-form-actions {
315
- align-self: end;
316
- }
317
-
318
156
  .agent-connect__mcp-form-status {
319
157
  align-self: end;
320
158
  min-inline-size: 0;
@@ -340,10 +178,6 @@
340
178
  grid-template-columns: repeat(2, minmax(0, 1fr));
341
179
  }
342
180
 
343
- .agent-connect__mcp-list {
344
- grid-template-columns: 1fr;
345
- }
346
-
347
181
  .agent-connect-popover {
348
182
  inline-size: min(24rem, calc(100dvi - 1.5rem));
349
183
  }
@@ -0,0 +1,178 @@
1
+ .browser-run-panel {
2
+ min-inline-size: 0;
3
+ min-block-size: 0;
4
+ display: flex;
5
+ flex-direction: column;
6
+ background: var(--sigvelo-color-canvas);
7
+ color: var(--sigvelo-color-text);
8
+ font-family: var(--sigvelo-font-sans);
9
+ }
10
+
11
+ .browser-run-panel__header {
12
+ min-block-size: 3rem;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: space-between;
16
+ gap: 0.75rem;
17
+ padding: 0.5rem 0.625rem;
18
+ border-block-end: var(--sigvelo-border-style) var(--sigvelo-border-width)
19
+ color-mix(in srgb, var(--sigvelo-color-neutral-border-subtle) 62%, transparent);
20
+ background: var(--sigvelo-color-surface);
21
+ }
22
+
23
+ .browser-run-panel__identity {
24
+ min-inline-size: 0;
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 0.625rem;
28
+ }
29
+
30
+ .browser-run-panel__icon {
31
+ flex: none;
32
+ color: var(--sigvelo-color-text-muted);
33
+ }
34
+
35
+ .browser-run-panel__title-block {
36
+ min-inline-size: 0;
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: 0.125rem;
40
+ }
41
+
42
+ .browser-run-panel__title {
43
+ font-size: 0.8125rem;
44
+ font-weight: var(--sigvelo-font-weight-semibold);
45
+ line-height: 1.2;
46
+ }
47
+
48
+ .browser-run-panel__url,
49
+ .browser-run-panel__target-url {
50
+ min-inline-size: 0;
51
+ overflow: hidden;
52
+ color: var(--sigvelo-color-text-muted);
53
+ font-size: 0.75rem;
54
+ line-height: 1.2;
55
+ text-overflow: ellipsis;
56
+ white-space: nowrap;
57
+ }
58
+
59
+ .browser-run-panel__actions {
60
+ flex: none;
61
+ display: flex;
62
+ align-items: center;
63
+ gap: 0.25rem;
64
+ }
65
+
66
+ .browser-run-panel__actions svg {
67
+ width: 1rem;
68
+ height: 1rem;
69
+ }
70
+
71
+ .browser-run-panel__targets {
72
+ display: flex;
73
+ gap: 0.375rem;
74
+ padding: 0.5rem 0.625rem;
75
+ overflow-x: auto;
76
+ border-block-end: var(--sigvelo-border-style) var(--sigvelo-border-width)
77
+ color-mix(in srgb, var(--sigvelo-color-neutral-border-subtle) 50%, transparent);
78
+ background: color-mix(in oklab, var(--sigvelo-color-canvas), var(--sigvelo-color-surface) 58%);
79
+ }
80
+
81
+ .browser-run-panel__target {
82
+ min-inline-size: 8rem;
83
+ max-inline-size: 13rem;
84
+ display: flex;
85
+ flex: 0 0 auto;
86
+ flex-direction: column;
87
+ gap: 0.125rem;
88
+ padding: 0.375rem 0.5rem;
89
+ border: var(--sigvelo-border-style) var(--sigvelo-border-width)
90
+ color-mix(in srgb, var(--sigvelo-color-neutral-border-subtle) 68%, transparent);
91
+ border-radius: var(--sigvelo-radius-md);
92
+ background: var(--sigvelo-color-surface);
93
+ color: inherit;
94
+ font: inherit;
95
+ text-align: start;
96
+ cursor: pointer;
97
+ }
98
+
99
+ .browser-run-panel__target:hover {
100
+ border-color: var(--sigvelo-color-neutral-border);
101
+ }
102
+
103
+ .browser-run-panel__target:focus-visible {
104
+ outline: 2px solid var(--sigvelo-color-focus);
105
+ outline-offset: 2px;
106
+ }
107
+
108
+ .browser-run-panel__target[aria-pressed="true"] {
109
+ border-color: color-mix(in srgb, var(--sigvelo-color-primary-border) 82%, transparent);
110
+ background: var(--sigvelo-color-primary-bg-subtle);
111
+ }
112
+
113
+ .browser-run-panel__target-title {
114
+ overflow: hidden;
115
+ font-size: 0.75rem;
116
+ font-weight: var(--sigvelo-font-weight-semibold);
117
+ line-height: 1.2;
118
+ text-overflow: ellipsis;
119
+ white-space: nowrap;
120
+ }
121
+
122
+ .browser-run-panel__body {
123
+ min-block-size: 0;
124
+ display: flex;
125
+ flex: 1;
126
+ padding: 0.625rem;
127
+ }
128
+
129
+ .browser-run-panel__body > .browser-live-view {
130
+ flex: 1;
131
+ min-block-size: 16rem;
132
+ aspect-ratio: auto;
133
+ border-radius: var(--sigvelo-radius-md);
134
+ }
135
+
136
+ .browser-run-panel__state {
137
+ min-block-size: 14rem;
138
+ display: flex;
139
+ flex: 1;
140
+ flex-direction: column;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 0.5rem;
144
+ padding: 1rem;
145
+ border: var(--sigvelo-border-style) var(--sigvelo-border-width)
146
+ var(--sigvelo-color-neutral-border-subtle);
147
+ border-radius: var(--sigvelo-radius-md);
148
+ background: var(--sigvelo-color-neutral-bg-subtle);
149
+ color: var(--sigvelo-color-text-muted);
150
+ font-size: 0.8125rem;
151
+ text-align: center;
152
+ }
153
+
154
+ .browser-run-panel__state[data-tone="danger"] {
155
+ min-block-size: auto;
156
+ flex: none;
157
+ margin: 0.625rem 0.625rem 0;
158
+ border-color: var(--sigvelo-color-danger-border-subtle);
159
+ background: var(--sigvelo-color-danger-bg-subtle);
160
+ color: var(--sigvelo-color-danger-text);
161
+ }
162
+
163
+ .browser-run-panel__spinner {
164
+ animation: browser-run-panel-spin 900ms linear infinite;
165
+ }
166
+
167
+ @keyframes browser-run-panel-spin {
168
+ to {
169
+ transform: rotate(360deg);
170
+ }
171
+ }
172
+
173
+ @media (prefers-reduced-motion: reduce) {
174
+ .browser-run-panel__spinner,
175
+ .browser-run-panel__actions .button svg {
176
+ animation: none;
177
+ }
178
+ }
@@ -39,6 +39,7 @@
39
39
  @import "./nanite-scene.css" layer(components);
40
40
  @import "./number-field.css" layer(components);
41
41
  @import "./popover.css" layer(components);
42
+ @import "./mcp-server-connections.css" layer(components);
42
43
  @import "./mcp-server-picker.css" layer(components);
43
44
  @import "./preview-card.css" layer(components);
44
45
  @import "./progress.css" layer(components);
@@ -62,6 +63,7 @@
62
63
  @import "./streamdown.css" layer(components);
63
64
  @import "./artifact.css" layer(components);
64
65
  @import "./browser-live-view.css" layer(components);
66
+ @import "./browser-run-panel.css" layer(components);
65
67
  @import "./browser-replay.css" layer(components);
66
68
  @import "./chain-of-thought.css" layer(components);
67
69
  @import "./code-block.css" layer(components);
@@ -0,0 +1,145 @@
1
+ .mcp-server-connections {
2
+ display: grid;
3
+ gap: 0.625rem;
4
+ min-inline-size: 0;
5
+ color: var(--sigvelo-color-text);
6
+ }
7
+
8
+ .mcp-server-connections__header {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: space-between;
12
+ gap: 0.75rem;
13
+ min-inline-size: 0;
14
+ }
15
+
16
+ .mcp-server-connections__header h2 {
17
+ margin: 0;
18
+ font-size: 0.95rem;
19
+ font-weight: var(--sigvelo-font-weight-bold);
20
+ line-height: 1.2;
21
+ letter-spacing: 0;
22
+ }
23
+
24
+ .mcp-server-connections__summary,
25
+ .mcp-server-connections__empty,
26
+ .mcp-server-connections__url,
27
+ .mcp-server-connections__capabilities,
28
+ .mcp-server-connections__instructions {
29
+ color: var(--sigvelo-color-text-muted);
30
+ font-size: 0.75rem;
31
+ line-height: 1.35;
32
+ }
33
+
34
+ .mcp-server-connections__summary {
35
+ flex: 0 0 auto;
36
+ white-space: nowrap;
37
+ }
38
+
39
+ .mcp-server-connections__empty {
40
+ margin: 0;
41
+ padding: 0.75rem;
42
+ border: var(--sigvelo-border-style) var(--sigvelo-border-width)
43
+ var(--sigvelo-color-neutral-border-subtle);
44
+ border-radius: var(--sigvelo-radius-md);
45
+ background: var(--sigvelo-color-surface);
46
+ }
47
+
48
+ .mcp-server-connections__list {
49
+ display: grid;
50
+ gap: 0.375rem;
51
+ margin: 0;
52
+ padding: 0;
53
+ list-style: none;
54
+ }
55
+
56
+ .mcp-server-connections__item {
57
+ display: grid;
58
+ grid-template-columns: minmax(0, 1fr) auto;
59
+ gap: 0.75rem;
60
+ align-items: start;
61
+ min-inline-size: 0;
62
+ padding: 0.625rem;
63
+ border: var(--sigvelo-border-style) var(--sigvelo-border-width)
64
+ var(--sigvelo-color-neutral-border-subtle);
65
+ border-radius: var(--sigvelo-radius-md);
66
+ background: var(--sigvelo-color-surface);
67
+ }
68
+
69
+ .mcp-server-connections__main {
70
+ display: grid;
71
+ gap: 0.25rem;
72
+ min-inline-size: 0;
73
+ }
74
+
75
+ .mcp-server-connections__title-row {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ align-items: center;
79
+ gap: 0.375rem;
80
+ min-inline-size: 0;
81
+ }
82
+
83
+ .mcp-server-connections__name {
84
+ min-inline-size: 0;
85
+ color: var(--sigvelo-color-text);
86
+ font-size: 0.85rem;
87
+ font-weight: var(--sigvelo-font-weight-semibold);
88
+ line-height: 1.25;
89
+ overflow-wrap: anywhere;
90
+ }
91
+
92
+ .mcp-server-connections__status .mcp-server-connections__spinner {
93
+ animation: mcp-server-connections-spin 900ms linear infinite;
94
+ }
95
+
96
+ .mcp-server-connections__url,
97
+ .mcp-server-connections__error,
98
+ .mcp-server-connections__instructions,
99
+ .mcp-server-connections__capabilities {
100
+ margin: 0;
101
+ overflow-wrap: anywhere;
102
+ }
103
+
104
+ .mcp-server-connections__error {
105
+ color: var(--sigvelo-color-danger-text);
106
+ font-size: 0.75rem;
107
+ line-height: 1.35;
108
+ }
109
+
110
+ .mcp-server-connections__actions {
111
+ display: flex;
112
+ flex-wrap: wrap;
113
+ justify-content: flex-end;
114
+ gap: 0.25rem;
115
+ }
116
+
117
+ .mcp-server-connections__actions .button > svg {
118
+ inline-size: 0.875rem;
119
+ block-size: 0.875rem;
120
+ }
121
+
122
+ @media (width < 34rem) {
123
+ .mcp-server-connections__item {
124
+ grid-template-columns: 1fr;
125
+ }
126
+
127
+ .mcp-server-connections__actions {
128
+ justify-content: flex-start;
129
+ }
130
+ }
131
+
132
+ @media (prefers-reduced-motion: reduce) {
133
+ .mcp-server-connections__status .mcp-server-connections__spinner {
134
+ animation: none;
135
+ }
136
+ }
137
+
138
+ @keyframes mcp-server-connections-spin {
139
+ from {
140
+ transform: rotate(0deg);
141
+ }
142
+ to {
143
+ transform: rotate(360deg);
144
+ }
145
+ }
@@ -1,8 +1,7 @@
1
- import { MCPServersState } from "agents";
1
+ import { MCPServer } from "agents";
2
2
 
3
3
  //#region src/utils/mcp-server-catalog.d.ts
4
- type McpServerConnectionState = MCPServersState["servers"][string]["state"];
5
- type McpServerPickerStatus = McpServerConnectionState | "needs-auth";
4
+ type McpServerPickerStatus = MCPServer["state"] | "needs-auth";
6
5
  interface McpServerCardIcon {
7
6
  src: string;
8
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/react-components",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "MCP-B React components built on Base UI and shared design tokens, including Cloudflare Think chat primitives.",
5
5
  "homepage": "https://design-system.sigvelo.com",
6
6
  "bugs": {
@@ -52,7 +52,7 @@
52
52
  "cloudflare": "^6.5.0",
53
53
  "shiki": "^3.23.0",
54
54
  "streamdown": "^2.5.0",
55
- "@mcp-b/design-tokens": "0.10.0"
55
+ "@mcp-b/design-tokens": "0.11.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@ai-sdk/react": "^3.0.222",