Skip to content
Draft
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
2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"devDependencies": {},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.5",
"@modelcontextprotocol/sdk": "file:../../typescript-sdk",
"commander": "^13.1.0",
"spawn-rx": "^5.1.2"
}
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"cleanup:e2e": "node e2e/global-teardown.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.5",
"@modelcontextprotocol/sdk": "file:../../typescript-sdk",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-icons": "^1.3.0",
Expand Down
2 changes: 2 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ const App = () => {
const {
connectionStatus,
serverCapabilities,
serverImplementation,
mcpClient,
requestHistory,
makeRequest,
Expand Down Expand Up @@ -818,6 +819,7 @@ const App = () => {
logLevel={logLevel}
sendLogLevelRequest={sendLogLevelRequest}
loggingSupported={!!serverCapabilities?.logging || false}
serverImplementation={serverImplementation}
/>
<div
onMouseDown={handleSidebarDragStart}
Expand Down
1 change: 1 addition & 0 deletions client/src/__tests__/App.routing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jest.mock("../utils/configUtils", () => ({
const disconnectedConnectionState = {
connectionStatus: "disconnected" as const,
serverCapabilities: null,
serverImplementation: null,
mcpClient: null,
requestHistory: [],
makeRequest: jest.fn(),
Expand Down
57 changes: 57 additions & 0 deletions client/src/components/IconDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Define Icon type locally since it might not be exported yet
interface Icon {
src: string;
mimeType?: string;
sizes?: string;
}

// Helper type for objects that may have icons
export interface WithIcons {
icons?: Icon[];
}

interface IconDisplayProps {
icons?: Icon[];
className?: string;
size?: "sm" | "md" | "lg";
}

const IconDisplay = ({
icons,
className = "",
size = "md",
}: IconDisplayProps) => {
if (!icons || icons.length === 0) {
return null;
}

const sizeClasses = {
sm: "w-4 h-4",
md: "w-6 h-6",
lg: "w-8 h-8",
};

const sizeClass = sizeClasses[size];

return (
<div className={`flex gap-1 ${className}`}>
{icons.map((icon, index) => (
<img
key={index}
src={icon.src}
alt=""
className={`${sizeClass} object-contain flex-shrink-0`}
style={{
imageRendering: "auto",
}}
onError={(e) => {
// Hide broken images
e.currentTarget.style.display = "none";
}}
/>
))}
</div>
);
};

export default IconDisplay;
18 changes: 14 additions & 4 deletions client/src/components/PromptsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useEffect, useState } from "react";
import ListPane from "./ListPane";
import { useCompletionState } from "@/lib/hooks/useCompletionState";
import JsonView from "./JsonView";
import IconDisplay from "./IconDisplay";

export type Prompt = {
name: string;
Expand All @@ -23,6 +24,7 @@ export type Prompt = {
description?: string;
required?: boolean;
}[];
icons?: { src: string; mimeType?: string; sizes?: string }[];
};

const PromptsTab = ({
Expand Down Expand Up @@ -101,7 +103,10 @@ const PromptsTab = ({
}}
renderItem={(prompt) => (
<div className="flex flex-col items-start">
<span className="flex-1">{prompt.name}</span>
<div className="flex items-center gap-2 w-full">
<IconDisplay icons={prompt.icons} size="sm" />
<span className="flex-1">{prompt.name}</span>
</div>
<span className="text-sm text-gray-500 text-left">
{prompt.description}
</span>
Expand All @@ -114,9 +119,14 @@ const PromptsTab = ({

<div className="bg-card border border-border rounded-lg shadow">
<div className="p-4 border-b border-gray-200 dark:border-border">
<h3 className="font-semibold">
{selectedPrompt ? selectedPrompt.name : "Select a prompt"}
</h3>
<div className="flex items-center gap-2">
{selectedPrompt && (
<IconDisplay icons={selectedPrompt.icons} size="md" />
)}
<h3 className="font-semibold">
{selectedPrompt ? selectedPrompt.name : "Select a prompt"}
</h3>
</div>
</div>
<div className="p-4">
{error ? (
Expand Down
57 changes: 45 additions & 12 deletions client/src/components/ResourcesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useEffect, useState } from "react";
import { useCompletionState } from "@/lib/hooks/useCompletionState";
import JsonView from "./JsonView";
import { UriTemplate } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
import IconDisplay, { WithIcons } from "./IconDisplay";

const ResourcesTab = ({
resources,
Expand Down Expand Up @@ -129,7 +130,16 @@ const ResourcesTab = ({
}}
renderItem={(resource) => (
<div className="flex items-center w-full">
<FileText className="w-4 h-4 mr-2 flex-shrink-0 text-gray-500" />
{(resource as WithIcons).icons &&
(resource as WithIcons).icons!.length > 0 ? (
<IconDisplay
icons={(resource as WithIcons).icons}
size="sm"
className="mr-2"
/>
) : (
<FileText className="w-4 h-4 mr-2 flex-shrink-0 text-gray-500" />
)}
<span className="flex-1 truncate" title={resource.uri.toString()}>
{resource.name}
</span>
Expand Down Expand Up @@ -159,7 +169,16 @@ const ResourcesTab = ({
}}
renderItem={(template) => (
<div className="flex items-center w-full">
<FileText className="w-4 h-4 mr-2 flex-shrink-0 text-gray-500" />
{(template as WithIcons).icons &&
(template as WithIcons).icons!.length > 0 ? (
<IconDisplay
icons={(template as WithIcons).icons}
size="sm"
className="mr-2"
/>
) : (
<FileText className="w-4 h-4 mr-2 flex-shrink-0 text-gray-500" />
)}
<span className="flex-1 truncate" title={template.uriTemplate}>
{template.name}
</span>
Expand All @@ -175,16 +194,30 @@ const ResourcesTab = ({

<div className="bg-card border border-border rounded-lg shadow">
<div className="p-4 border-b border-gray-200 dark:border-border flex justify-between items-center">
<h3
className="font-semibold truncate"
title={selectedResource?.name || selectedTemplate?.name}
>
{selectedResource
? selectedResource.name
: selectedTemplate
? selectedTemplate.name
: "Select a resource or template"}
</h3>
<div className="flex items-center gap-2 min-w-0">
{selectedResource && (selectedResource as WithIcons).icons && (
<IconDisplay
icons={(selectedResource as WithIcons).icons}
size="md"
/>
)}
{selectedTemplate && (selectedTemplate as WithIcons).icons && (
<IconDisplay
icons={(selectedTemplate as WithIcons).icons}
size="md"
/>
)}
<h3
className="font-semibold truncate"
title={selectedResource?.name || selectedTemplate?.name}
>
{selectedResource
? selectedResource.name
: selectedTemplate
? selectedTemplate.name
: "Select a resource or template"}
</h3>
</div>
{selectedResource && (
<div className="flex row-auto gap-1 justify-end w-2/5">
{resourceSubscriptionsSupported &&
Expand Down
45 changes: 45 additions & 0 deletions client/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
RefreshCwOff,
Copy,
CheckCheck,
Server,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
Expand All @@ -38,6 +39,7 @@ import {
TooltipContent,
} from "@/components/ui/tooltip";
import { useToast } from "../lib/hooks/useToast";
import IconDisplay, { WithIcons } from "./IconDisplay";

interface SidebarProps {
connectionStatus: ConnectionStatus;
Expand Down Expand Up @@ -66,6 +68,9 @@ interface SidebarProps {
loggingSupported: boolean;
config: InspectorConfig;
setConfig: (config: InspectorConfig) => void;
serverImplementation?:
| (WithIcons & { name?: string; version?: string; websiteUrl?: string })
| null;
}

const Sidebar = ({
Expand Down Expand Up @@ -95,6 +100,7 @@ const Sidebar = ({
loggingSupported,
config,
setConfig,
serverImplementation,
}: SidebarProps) => {
const [theme, setTheme] = useTheme();
const [showEnvVars, setShowEnvVars] = useState(false);
Expand Down Expand Up @@ -729,6 +735,45 @@ const Sidebar = ({
</span>
</div>

{connectionStatus === "connected" && serverImplementation && (
<div className="bg-gray-50 dark:bg-gray-900 p-3 rounded-lg mb-4">
<div className="flex items-center gap-2 mb-1">
{(serverImplementation as WithIcons).icons &&
(serverImplementation as WithIcons).icons!.length > 0 ? (
<IconDisplay
icons={(serverImplementation as WithIcons).icons}
size="sm"
/>
) : (
<Server className="w-4 h-4 text-gray-500" />
)}
{(serverImplementation as { websiteUrl?: string })
.websiteUrl ? (
<a
href={
(serverImplementation as { websiteUrl?: string })
.websiteUrl
}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:underline transition-colors"
>
{serverImplementation.name || "MCP Server"}
</a>
) : (
<span className="text-sm font-medium text-gray-800 dark:text-gray-200">
{serverImplementation.name || "MCP Server"}
</span>
)}
</div>
{serverImplementation.version && (
<div className="text-xs text-gray-500 dark:text-gray-400">
Version: {serverImplementation.version}
</div>
)}
</div>
)}

{loggingSupported && connectionStatus === "connected" && (
<div className="space-y-2">
<label
Expand Down
20 changes: 16 additions & 4 deletions client/src/components/ToolsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { useEffect, useState } from "react";
import ListPane from "./ListPane";
import JsonView from "./JsonView";
import ToolResults from "./ToolResults";
import IconDisplay, { WithIcons } from "./IconDisplay";

// Type guard to safely detect the optional _meta field without using `any`
const hasMeta = (tool: Tool): tool is Tool & { _meta: unknown } =>
Expand Down Expand Up @@ -83,7 +84,10 @@ const ToolsTab = ({
setSelectedItem={setSelectedTool}
renderItem={(tool) => (
<div className="flex flex-col items-start">
<span className="flex-1">{tool.name}</span>
<div className="flex items-center gap-2 w-full">
<IconDisplay icons={(tool as WithIcons).icons} size="sm" />
<span className="flex-1">{tool.name}</span>
</div>
<span className="text-sm text-gray-500 text-left">
{tool.description}
</span>
Expand All @@ -96,9 +100,17 @@ const ToolsTab = ({

<div className="bg-card border border-border rounded-lg shadow">
<div className="p-4 border-b border-gray-200 dark:border-border">
<h3 className="font-semibold">
{selectedTool ? selectedTool.name : "Select a tool"}
</h3>
<div className="flex items-center gap-2">
{selectedTool && (
<IconDisplay
icons={(selectedTool as WithIcons).icons}
size="md"
/>
)}
<h3 className="font-semibold">
{selectedTool ? selectedTool.name : "Select a tool"}
</h3>
</div>
</div>
<div className="p-4">
{selectedTool ? (
Expand Down
10 changes: 10 additions & 0 deletions client/src/lib/hooks/useConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ export function useConnection({
{ request: string; response?: string }[]
>([]);
const [completionsSupported, setCompletionsSupported] = useState(false);
const [serverImplementation, setServerImplementation] = useState<{
name?: string;
version?: string;
websiteUrl?: string;
icons?: { src: string; mimeType?: string; sizes?: string }[];
} | null>(null);

useEffect(() => {
if (!oauthClientId) {
Expand Down Expand Up @@ -542,6 +548,8 @@ export function useConnection({
setClientTransport(transport);

capabilities = client.getServerCapabilities();
const serverInfo = client.getServerVersion();
setServerImplementation(serverInfo || null);
const initializeRequest = {
method: "initialize",
};
Expand Down Expand Up @@ -651,11 +659,13 @@ export function useConnection({
setConnectionStatus("disconnected");
setCompletionsSupported(false);
setServerCapabilities(null);
setServerImplementation(null);
};

return {
connectionStatus,
serverCapabilities,
serverImplementation,
mcpClient,
requestHistory,
makeRequest,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@modelcontextprotocol/inspector-cli": "^0.16.6",
"@modelcontextprotocol/inspector-client": "^0.16.6",
"@modelcontextprotocol/inspector-server": "^0.16.6",
"@modelcontextprotocol/sdk": "^1.17.5",
"@modelcontextprotocol/sdk": "file:../typescript-sdk",
"concurrently": "^9.2.0",
"open": "^10.2.0",
"shell-quote": "^1.8.3",
Expand Down