diff --git a/client/src/App.tsx b/client/src/App.tsx index 4395dcc..f64276a 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -19,10 +19,11 @@ import { Request, Resource, ResourceTemplate, - Result, Root, ServerNotification, Tool, + ServerCapabilitiesSchema, + Result, } from "@modelcontextprotocol/sdk/types.js"; import { useCallback, useEffect, useRef, useState } from "react"; @@ -43,7 +44,7 @@ import { } from "lucide-react"; import { toast } from "react-toastify"; -import { ZodType } from "zod"; +import { z, type ZodType } from "zod"; import "./App.css"; import ConsoleTab from "./components/ConsoleTab"; import HistoryAndNotifications from "./components/History"; @@ -55,6 +56,8 @@ import SamplingTab, { PendingRequest } from "./components/SamplingTab"; import Sidebar from "./components/Sidebar"; import ToolsTab from "./components/ToolsTab"; +type ServerCapabilities = z.infer; + const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000; const params = new URLSearchParams(window.location.search); @@ -67,6 +70,7 @@ const App = () => { const [connectionStatus, setConnectionStatus] = useState< "disconnected" | "connected" | "error" >("disconnected"); + const [serverCapabilities, setServerCapabilities] = useState(null); const [resources, setResources] = useState([]); const [resourceTemplates, setResourceTemplates] = useState< ResourceTemplate[] @@ -455,6 +459,9 @@ const App = () => { await client.connect(clientTransport); + const capabilities = client.getServerCapabilities(); + setServerCapabilities(capabilities ?? null); + client.setRequestHandler(CreateMessageRequestSchema, (request) => { return new Promise((resolve, reject) => { setPendingSampleRequests((prev) => [ @@ -497,20 +504,27 @@ const App = () => {
{mcpClient ? ( (window.location.hash = value)} > - + Resources - + Prompts - + Tools @@ -534,107 +548,117 @@ const App = () => {
- { - clearError("resources"); - listResources(); - }} - clearResources={() => { - setResources([]); - setNextResourceCursor(undefined); - }} - listResourceTemplates={() => { - clearError("resources"); - listResourceTemplates(); - }} - clearResourceTemplates={() => { - setResourceTemplates([]); - setNextResourceTemplateCursor(undefined); - }} - readResource={(uri) => { - clearError("resources"); - readResource(uri); - }} - selectedResource={selectedResource} - setSelectedResource={(resource) => { - clearError("resources"); - setSelectedResource(resource); - }} - resourceContent={resourceContent} - nextCursor={nextResourceCursor} - nextTemplateCursor={nextResourceTemplateCursor} - error={errors.resources} - /> - { - clearError("prompts"); - listPrompts(); - }} - clearPrompts={() => { - setPrompts([]); - setNextPromptCursor(undefined); - }} - getPrompt={(name, args) => { - clearError("prompts"); - getPrompt(name, args); - }} - selectedPrompt={selectedPrompt} - setSelectedPrompt={(prompt) => { - clearError("prompts"); - setSelectedPrompt(prompt); - }} - promptContent={promptContent} - nextCursor={nextPromptCursor} - error={errors.prompts} - /> - { - clearError("tools"); - listTools(); - }} - clearTools={() => { - setTools([]); - setNextToolCursor(undefined); - }} - callTool={(name, params) => { - clearError("tools"); - callTool(name, params); - }} - selectedTool={selectedTool} - setSelectedTool={(tool) => { - clearError("tools"); - setSelectedTool(tool); - setToolResult(null); - }} - toolResult={toolResult} - nextCursor={nextToolCursor} - error={errors.tools} - /> - - { - void makeRequest( - { - method: "ping" as const, - }, - EmptyResultSchema, - ); - }} - /> - - + {!serverCapabilities?.resources && !serverCapabilities?.prompts && !serverCapabilities?.tools ? ( +
+

+ The connected server does not support any MCP capabilities +

+
+ ) : ( + <> + { + clearError("resources"); + listResources(); + }} + clearResources={() => { + setResources([]); + setNextResourceCursor(undefined); + }} + listResourceTemplates={() => { + clearError("resources"); + listResourceTemplates(); + }} + clearResourceTemplates={() => { + setResourceTemplates([]); + setNextResourceTemplateCursor(undefined); + }} + readResource={(uri) => { + clearError("resources"); + readResource(uri); + }} + selectedResource={selectedResource} + setSelectedResource={(resource) => { + clearError("resources"); + setSelectedResource(resource); + }} + resourceContent={resourceContent} + nextCursor={nextResourceCursor} + nextTemplateCursor={nextResourceTemplateCursor} + error={errors.resources} + /> + { + clearError("prompts"); + listPrompts(); + }} + clearPrompts={() => { + setPrompts([]); + setNextPromptCursor(undefined); + }} + getPrompt={(name, args) => { + clearError("prompts"); + getPrompt(name, args); + }} + selectedPrompt={selectedPrompt} + setSelectedPrompt={(prompt) => { + clearError("prompts"); + setSelectedPrompt(prompt); + }} + promptContent={promptContent} + nextCursor={nextPromptCursor} + error={errors.prompts} + /> + { + clearError("tools"); + listTools(); + }} + clearTools={() => { + setTools([]); + setNextToolCursor(undefined); + }} + callTool={(name, params) => { + clearError("tools"); + callTool(name, params); + }} + selectedTool={selectedTool} + setSelectedTool={(tool) => { + clearError("tools"); + setSelectedTool(tool); + setToolResult(null); + }} + toolResult={toolResult} + nextCursor={nextToolCursor} + error={errors.tools} + /> + + { + void makeRequest( + { + method: "ping" as const, + }, + EmptyResultSchema, + ); + }} + /> + + + + )}
) : (