diff --git a/client/package.json b/client/package.json index eb0091f..3a2f51c 100644 --- a/client/package.json +++ b/client/package.json @@ -32,6 +32,7 @@ "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.1", + "@radix-ui/react-tooltip": "^1.1.8", "@types/prismjs": "^1.26.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 23c508f..e652263 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -20,7 +20,6 @@ import { import React, { Suspense, useEffect, useRef, useState } from "react"; import { useConnection } from "./lib/hooks/useConnection"; import { useDraggablePane } from "./lib/hooks/useDraggablePane"; - import { StdErrNotification } from "./lib/notificationTypes"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; @@ -47,10 +46,12 @@ import Sidebar from "./components/Sidebar"; import ToolsTab from "./components/ToolsTab"; import { DEFAULT_INSPECTOR_CONFIG } from "./lib/constants"; import { InspectorConfig } from "./lib/configurationTypes"; +import { + getMCPProxyAddress, + getMCPServerRequestTimeout, +} from "./utils/configUtils"; const params = new URLSearchParams(window.location.search); -const PROXY_PORT = params.get("proxyPort") ?? "6277"; -const PROXY_SERVER_URL = `http://${window.location.hostname}:${PROXY_PORT}`; const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1"; const App = () => { @@ -95,7 +96,13 @@ const App = () => { const [config, setConfig] = useState(() => { const savedConfig = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY); - return savedConfig ? JSON.parse(savedConfig) : DEFAULT_INSPECTOR_CONFIG; + if (savedConfig) { + return { + ...DEFAULT_INSPECTOR_CONFIG, + ...JSON.parse(savedConfig), + } as InspectorConfig; + } + return DEFAULT_INSPECTOR_CONFIG; }); const [bearerToken, setBearerToken] = useState(() => { return localStorage.getItem("lastBearerToken") || ""; @@ -152,8 +159,8 @@ const App = () => { sseUrl, env, bearerToken, - proxyServerUrl: PROXY_SERVER_URL, - requestTimeout: config.MCP_SERVER_REQUEST_TIMEOUT.value as number, + proxyServerUrl: getMCPProxyAddress(config), + requestTimeout: getMCPServerRequestTimeout(config), onNotification: (notification) => { setNotifications((prev) => [...prev, notification as ServerNotification]); }, @@ -214,7 +221,7 @@ const App = () => { }, [connectMcpServer]); useEffect(() => { - fetch(`${PROXY_SERVER_URL}/config`) + fetch(`${getMCPProxyAddress(config)}/config`) .then((response) => response.json()) .then((data) => { setEnv(data.defaultEnvironment); @@ -228,6 +235,7 @@ const App = () => { .catch((error) => console.error("Error fetching default environment:", error), ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/client/src/components/Sidebar.tsx b/client/src/components/Sidebar.tsx index 33e88a7..69aec99 100644 --- a/client/src/components/Sidebar.tsx +++ b/client/src/components/Sidebar.tsx @@ -10,6 +10,7 @@ import { EyeOff, RotateCcw, Settings, + HelpCircle, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -26,12 +27,17 @@ import { LoggingLevelSchema, } from "@modelcontextprotocol/sdk/types.js"; import { InspectorConfig } from "@/lib/configurationTypes"; - +import { ConnectionStatus } from "@/lib/constants"; import useTheme from "../lib/useTheme"; import { version } from "../../../package.json"; +import { + Tooltip, + TooltipTrigger, + TooltipContent, +} from "@/components/ui/tooltip"; interface SidebarProps { - connectionStatus: "disconnected" | "connected" | "error"; + connectionStatus: ConnectionStatus; transportType: "stdio" | "sse"; setTransportType: (type: "stdio" | "sse") => void; command: string; @@ -177,6 +183,7 @@ const Sidebar = ({ variant="outline" onClick={() => setShowEnvVars(!showEnvVars)} className="flex items-center w-full" + data-testid="env-vars-button" > {showEnvVars ? ( @@ -298,6 +305,7 @@ const Sidebar = ({ variant="outline" onClick={() => setShowConfig(!showConfig)} className="flex items-center w-full" + data-testid="config-button" > {showConfig ? ( @@ -313,9 +321,19 @@ const Sidebar = ({ const configKey = key as keyof InspectorConfig; return (
- +
+ + + + + + + {configItem.description} + + +
{typeof configItem.value === "number" ? (
-