From d857e1462bbbb1b3cdbe877525f451184bda2bc2 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:11:03 +0000 Subject: [PATCH] refactor: simplify capability handling and remove context provider - Remove redundant useEffect for capability checking - Remove CapabilityContext provider pattern - Set default tab to first supported capability - Add fallback UI for unsupported capabilities - Delete unused contexts.ts file --- client/src/App.tsx | 325 ++++++++++++++++++++----------------- client/src/lib/contexts.ts | 12 -- 2 files changed, 178 insertions(+), 159 deletions(-) delete mode 100644 client/src/lib/contexts.ts diff --git a/client/src/App.tsx b/client/src/App.tsx index 2f36450..70f3175 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,7 +56,12 @@ import SamplingTab, { PendingRequest } from "./components/SamplingTab"; import Sidebar from "./components/Sidebar"; import ToolsTab from "./components/ToolsTab"; -import { CapabilityContext, ServerCapabilities } from "@/lib/contexts"; +type ServerCapabilities = z.infer; + +type ServerCapabilities = z.infer; + +type ServerCapabilities = z.infer; + const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000; @@ -220,12 +226,7 @@ const App = () => { rootsRef.current = roots; }, [roots]); - useEffect(() => { - if (mcpClient) { - const capabilities = mcpClient.getServerCapabilities(); - setServerCapabilities(capabilities ?? null); - } - }, [mcpClient]); + const pushHistory = (request: object, response?: object) => { setRequestHistory((prev) => [ @@ -498,145 +499,175 @@ const App = () => {
{mcpClient ? ( - - - - - - Resources - - - - Prompts - - - - Tools - - - - Ping - - - - Sampling - {pendingSampleRequests.length > 0 && ( - - {pendingSampleRequests.length} - - )} - - - - Roots - - + + + + + Resources + + + + Prompts + + + + Tools + + + + Ping + + + + Sampling + {pendingSampleRequests.length > 0 && ( + + {pendingSampleRequests.length} + + )} + + + + Roots + + -
- { - 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"); + if (serverCapabilities?.resources) { + listResources(); + } + }} + clearResources={() => { + setResources([]); + setNextResourceCursor(undefined); + }} + listResourceTemplates={() => { + clearError("resources"); + if (serverCapabilities?.resources) { + listResourceTemplates(); + } + }} + clearResourceTemplates={() => { + setResourceTemplates([]); + setNextResourceTemplateCursor(undefined); + }} + readResource={(uri) => { + clearError("resources"); + if (serverCapabilities?.resources) { + readResource(uri); + } + }} + selectedResource={selectedResource} + setSelectedResource={(resource) => { + clearError("resources"); + setSelectedResource(resource); + }} + resourceContent={resourceContent} + nextCursor={nextResourceCursor} + nextTemplateCursor={nextResourceTemplateCursor} + error={errors.resources} + /> + { + clearError("prompts"); + if (serverCapabilities?.prompts) { + listPrompts(); + } + }} + clearPrompts={() => { + setPrompts([]); + setNextPromptCursor(undefined); + }} + getPrompt={(name, args) => { + clearError("prompts"); + if (serverCapabilities?.prompts) { + getPrompt(name, args); + } + }} + selectedPrompt={selectedPrompt} + setSelectedPrompt={(prompt) => { + clearError("prompts"); + setSelectedPrompt(prompt); + }} + promptContent={promptContent} + nextCursor={nextPromptCursor} + error={errors.prompts} + /> + { + clearError("tools"); + if (serverCapabilities?.tools) { + listTools(); + } + }} + clearTools={() => { + setTools([]); + setNextToolCursor(undefined); + }} + callTool={(name, params) => { + clearError("tools"); + if (serverCapabilities?.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, + ); + }} + /> + + + + )} +
+ ) : (

diff --git a/client/src/lib/contexts.ts b/client/src/lib/contexts.ts deleted file mode 100644 index c953dd1..0000000 --- a/client/src/lib/contexts.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createContext, useContext } from "react"; -import { ServerCapabilitiesSchema } from "@modelcontextprotocol/sdk/types.js"; -import type { z } from "zod"; - -export type ServerCapabilities = z.infer; - -export const CapabilityContext = createContext(null); - -export function useServerCapability(capability: keyof ServerCapabilities): boolean { - const capabilities = useContext(CapabilityContext); - return !!capabilities?.[capability]; -}