@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.
- package/dist/components/AgentConnection.d.ts +3 -14
- package/dist/components/AgentConnection.js +3 -91
- package/dist/components/BrowserRunPanel.d.ts +46 -0
- package/dist/components/BrowserRunPanel.js +123 -0
- package/dist/components/McpServerConnections.d.ts +41 -0
- package/dist/components/McpServerConnections.js +188 -0
- package/dist/styles/agent-connection.css +0 -166
- package/dist/styles/browser-run-panel.css +178 -0
- package/dist/styles/index.css +2 -0
- package/dist/styles/mcp-server-connections.css +145 -0
- package/dist/utils/mcp-server-catalog.d.ts +2 -3
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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?:
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
+
}
|
package/dist/styles/index.css
CHANGED
|
@@ -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 {
|
|
1
|
+
import { MCPServer } from "agents";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/mcp-server-catalog.d.ts
|
|
4
|
-
type
|
|
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.
|
|
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.
|
|
55
|
+
"@mcp-b/design-tokens": "0.11.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@ai-sdk/react": "^3.0.222",
|