Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 54 additions & 46 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import {
import { z } from "zod";
import "./App.css";
import AuthDebugger from "./components/AuthDebugger";
import ConsoleTab from "./components/ConsoleTab";
// import ConsoleTab from "./components/ConsoleTab";
import HistoryAndNotifications from "./components/HistoryAndNotifications";
import PingTab from "./components/PingTab";
import PromptsTab, { Prompt } from "./components/PromptsTab";
Expand All @@ -61,6 +61,7 @@ import RootsTab from "./components/RootsTab";
import SamplingTab, { PendingRequest } from "./components/SamplingTab";
import Sidebar from "./components/Sidebar";
import ToolsTab from "./components/ToolsTab";
import OverviewTab from "./components/OverviewTab";
import { InspectorConfig } from "./lib/configurationTypes";
import {
getMCPProxyAddress,
Expand Down Expand Up @@ -228,7 +229,7 @@ const App = () => {

const [activeTab, setActiveTab] = useState<string>(() => {
const hash = window.location.hash.slice(1);
const initialTab = hash || "resources";
const initialTab = hash || "overview";
return initialTab;
});

Expand Down Expand Up @@ -311,6 +312,7 @@ const App = () => {
const hash = window.location.hash.slice(1);

const validTabs = [
"overview",
...(serverCapabilities?.resources ? ["resources"] : []),
...(serverCapabilities?.prompts ? ["prompts"] : []),
...(serverCapabilities?.tools ? ["tools"] : []),
Expand All @@ -324,14 +326,7 @@ const App = () => {
const isValidTab = validTabs.includes(hash);

if (!isValidTab) {
const defaultTab = serverCapabilities?.resources
? "resources"
: serverCapabilities?.prompts
? "prompts"
: serverCapabilities?.tools
? "tools"
: "ping";

const defaultTab = "overview";
setActiveTab(defaultTab);
window.location.hash = defaultTab;
}
Expand Down Expand Up @@ -551,13 +546,7 @@ const App = () => {

useEffect(() => {
if (mcpClient && !window.location.hash) {
const defaultTab = serverCapabilities?.resources
? "resources"
: serverCapabilities?.prompts
? "prompts"
: serverCapabilities?.tools
? "tools"
: "ping";
const defaultTab = "overview";
window.location.hash = defaultTab;
} else if (!mcpClient && window.location.hash) {
// Clear hash when disconnected - completely remove the fragment
Expand Down Expand Up @@ -949,6 +938,7 @@ const App = () => {
}}
>
<TabsList className="mb-4 py-0">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger
value="resources"
disabled={!serverCapabilities?.resources}
Expand Down Expand Up @@ -1002,30 +992,37 @@ const App = () => {
</TabsTrigger>
</TabsList>

<div className="w-full">
{!serverCapabilities?.resources &&
!serverCapabilities?.prompts &&
!serverCapabilities?.tools ? (
<>
<div className="flex items-center justify-center p-4">
<p className="text-lg text-gray-500 dark:text-gray-400">
The connected server does not support any MCP
capabilities
</p>
</div>
<PingTab
onPingClick={() => {
void sendMCPRequest(
{
method: "ping" as const,
},
EmptyResultSchema,
);
}}
/>
</>
) : (
<>
<OverviewTab
serverCapabilities={serverCapabilities}
transportType={transportType}
command={command}
args={args}
sseUrl={sseUrl}
/>

{!serverCapabilities?.resources &&
!serverCapabilities?.prompts &&
!serverCapabilities?.tools ? (
<TabsContent value="ping">
<div className="flex items-center justify-center p-4">
<p className="text-lg text-gray-500 dark:text-gray-400">
The connected server does not support any MCP capabilities
</p>
</div>
<PingTab
onPingClick={() => {
void sendMCPRequest(
{
method: "ping" as const,
},
EmptyResultSchema,
);
}}
/>
</TabsContent>
) : (
<>
<TabsContent value="resources">
<ResourcesTab
resources={resources}
resourceTemplates={resourceTemplates}
Expand Down Expand Up @@ -1073,6 +1070,8 @@ const App = () => {
nextTemplateCursor={nextResourceTemplateCursor}
error={errors.resources}
/>
</TabsContent>
<TabsContent value="prompts">
<PromptsTab
prompts={prompts}
listPrompts={() => {
Expand All @@ -1099,6 +1098,8 @@ const App = () => {
nextCursor={nextPromptCursor}
error={errors.prompts}
/>
</TabsContent>
<TabsContent value="tools">
<ToolsTab
tools={tools}
listTools={() => {
Expand Down Expand Up @@ -1130,7 +1131,8 @@ const App = () => {
readResource(uri);
}}
/>
<ConsoleTab />
</TabsContent>
<TabsContent value="ping">
<PingTab
onPingClick={() => {
void sendMCPRequest(
Expand All @@ -1141,24 +1143,30 @@ const App = () => {
);
}}
/>
</TabsContent>
<TabsContent value="sampling">
<SamplingTab
pendingRequests={pendingSampleRequests}
onApprove={handleApproveSampling}
onReject={handleRejectSampling}
/>
</TabsContent>
<TabsContent value="elicitations">
<ElicitationTab
pendingRequests={pendingElicitationRequests}
onResolve={handleResolveElicitation}
/>
</TabsContent>
<TabsContent value="roots">
<RootsTab
roots={roots}
setRoots={setRoots}
onRootsChange={handleRootsChange}
/>
<AuthDebuggerWrapper />
</>
)}
</div>
</TabsContent>
<AuthDebuggerWrapper />
</>
)}
</Tabs>
) : isAuthDebuggerVisible ? (
<Tabs
Expand Down
82 changes: 82 additions & 0 deletions client/src/components/OverviewTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { TabsContent } from "@/components/ui/tabs";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Files, Hammer, MessageSquare } from "lucide-react";

interface OverviewTabProps {
serverCapabilities: any;
transportType: "stdio" | "sse" | "streamable-http";
command: string;
args: string;
sseUrl: string;
}

const OverviewTab = ({
serverCapabilities,
transportType,
command,
args,
sseUrl,
}: OverviewTabProps) => {
return (
<TabsContent value="overview">
<Card>
<CardHeader>
<CardTitle>Server Overview</CardTitle>
<CardDescription>
Server capabilities and configuration information
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{/* Server Capabilities Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="flex items-center gap-2">
<Files className="h-4 w-4 text-muted-foreground" />
<span className="text-sm">
Resources:{" "}
{serverCapabilities?.resources ? "Supported" : "Not supported"}
</span>
</div>
<div className="flex items-center gap-2">
<MessageSquare className="h-4 w-4 text-muted-foreground" />
<span className="text-sm">
Prompts:{" "}
{serverCapabilities?.prompts ? "Supported" : "Not supported"}
</span>
</div>
<div className="flex items-center gap-2">
<Hammer className="h-4 w-4 text-muted-foreground" />
<span className="text-sm">
Tools:{" "}
{serverCapabilities?.tools ? "Supported" : "Not supported"}
</span>
</div>
</div>

{/* Server Configuration Section */}
<div className="pt-4 border-t">
<h4 className="font-medium mb-2">Server Configuration</h4>
<div className="space-y-2 text-sm text-muted-foreground">
<div>Transport: {transportType}</div>
{transportType === "stdio" && (
<>
<div>Command: {command}</div>
{args && <div>Arguments: {args}</div>}
</>
)}
{(transportType === "streamable-http" ||
transportType === "sse") && <div>URL: {sseUrl}</div>}
</div>
</div>
</CardContent>
</Card>
</TabsContent>
);
};

export default OverviewTab;
86 changes: 86 additions & 0 deletions client/src/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from "react";

import { cn } from "@/lib/utils";

const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className,
)}
{...props}
/>
));
Card.displayName = "Card";

const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
));
CardHeader.displayName = "CardHeader";

const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className,
)}
{...props}
/>
));
CardTitle.displayName = "CardTitle";

const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
CardDescription.displayName = "CardDescription";

const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
));
CardContent.displayName = "CardContent";

const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
));
CardFooter.displayName = "CardFooter";

export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};