diff --git a/apps/web/src/components/settings/EnvironmentRoutesList.browser.test.tsx b/apps/web/src/components/settings/EnvironmentRoutesList.browser.test.tsx index 78a96ba4ebab4..6f3ad0a0b4a0f 100644 --- a/apps/web/src/components/settings/EnvironmentRoutesList.browser.test.tsx +++ b/apps/web/src/components/settings/EnvironmentRoutesList.browser.test.tsx @@ -65,7 +65,14 @@ function routesList(routes: ReadonlyArray) { connection: { phase: "available", error: null, traceId: null }, serverConfig: null, }; - return undefined} />; + return ( + undefined} + onCopyMcpUrl={() => undefined} + /> + ); } it("shows a route added after a reorder was saved, once another route is removed", async () => { diff --git a/apps/web/src/components/settings/EnvironmentRoutesList.tsx b/apps/web/src/components/settings/EnvironmentRoutesList.tsx index 6603f380120d6..85e9b24cee37c 100644 --- a/apps/web/src/components/settings/EnvironmentRoutesList.tsx +++ b/apps/web/src/components/settings/EnvironmentRoutesList.tsx @@ -21,11 +21,12 @@ import { connectionRouteAddress, connectionRouteId, connectionRouteLabel, + connectionRouteMcpUrl, connectionRoutes, isLearned, pendingRouteOrder, } from "@t3tools/client-runtime/connection"; -import { GripVerticalIcon, PlusIcon, XIcon } from "lucide-react"; +import { CopyIcon, GripVerticalIcon, PlusIcon, XIcon } from "lucide-react"; import { useState } from "react"; import { requestConfirmDialog } from "~/confirmDialog"; @@ -39,10 +40,14 @@ import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; export function EnvironmentRoutesList({ environment, + relayHttpBaseUrl, onAddRoute, + onCopyMcpUrl, }: { readonly environment: EnvironmentPresentation; + readonly relayHttpBaseUrl: string | undefined; readonly onAddRoute: () => void; + readonly onCopyMcpUrl: (url: string) => void; }) { const saved = connectionRoutes(environment.entry); const savedIds = saved.map((route) => connectionRouteId(route.target)); @@ -108,7 +113,9 @@ export function EnvironmentRoutesList({ route={route} position={index + 1} inUse={connectionRouteId(route.target) === activeRouteId} + mcpUrl={connectionRouteMcpUrl(route, relayHttpBaseUrl)} removable={routes.length > 1 && !isLearned(route)} + onCopyMcpUrl={onCopyMcpUrl} onRemove={() => void confirmRemove(route)} /> ))} @@ -129,13 +136,17 @@ function SortableRouteRow({ route, position, inUse, + mcpUrl, removable, + onCopyMcpUrl, onRemove, }: { readonly route: ConnectionRoute; readonly position: number; readonly inUse: boolean; + readonly mcpUrl: string | null; readonly removable: boolean; + readonly onCopyMcpUrl: (url: string) => void; readonly onRemove: () => void; }) { const id = connectionRouteId(route.target); @@ -176,6 +187,24 @@ function SortableRouteRow({

) : null} + {mcpUrl !== null ? ( + + onCopyMcpUrl(mcpUrl)} + /> + } + > + + + Copy MCP URL + + ) : null}