@@ -19,10 +19,11 @@ import {
1919 Request ,
2020 Resource ,
2121 ResourceTemplate ,
22- Result ,
2322 Root ,
2423 ServerNotification ,
2524 Tool ,
25+ ServerCapabilitiesSchema ,
26+ Result ,
2627} from "@modelcontextprotocol/sdk/types.js" ;
2728import { useCallback , useEffect , useRef , useState } from "react" ;
2829
@@ -43,7 +44,7 @@ import {
4344} from "lucide-react" ;
4445
4546import { toast } from "react-toastify" ;
46- import { ZodType } from "zod" ;
47+ import { z , type ZodType } from "zod" ;
4748import "./App.css" ;
4849import ConsoleTab from "./components/ConsoleTab" ;
4950import HistoryAndNotifications from "./components/History" ;
@@ -55,6 +56,8 @@ import SamplingTab, { PendingRequest } from "./components/SamplingTab";
5556import Sidebar from "./components/Sidebar" ;
5657import ToolsTab from "./components/ToolsTab" ;
5758
59+ type ServerCapabilities = z . infer < typeof ServerCapabilitiesSchema > ;
60+
5861const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000 ;
5962
6063const params = new URLSearchParams ( window . location . search ) ;
@@ -67,6 +70,7 @@ const App = () => {
6770 const [ connectionStatus , setConnectionStatus ] = useState <
6871 "disconnected" | "connected" | "error"
6972 > ( "disconnected" ) ;
73+ const [ serverCapabilities , setServerCapabilities ] = useState < ServerCapabilities | null > ( null ) ;
7074 const [ resources , setResources ] = useState < Resource [ ] > ( [ ] ) ;
7175 const [ resourceTemplates , setResourceTemplates ] = useState <
7276 ResourceTemplate [ ]
@@ -455,6 +459,9 @@ const App = () => {
455459
456460 await client . connect ( clientTransport ) ;
457461
462+ const capabilities = client . getServerCapabilities ( ) ;
463+ setServerCapabilities ( capabilities ?? null ) ;
464+
458465 client . setRequestHandler ( CreateMessageRequestSchema , ( request ) => {
459466 return new Promise < CreateMessageResult > ( ( resolve , reject ) => {
460467 setPendingSampleRequests ( ( prev ) => [
@@ -497,20 +504,27 @@ const App = () => {
497504 < div className = "flex-1 overflow-auto" >
498505 { mcpClient ? (
499506 < Tabs
500- defaultValue = { window . location . hash . slice ( 1 ) || "resources" }
507+ defaultValue = {
508+ Object . keys ( serverCapabilities ?? { } ) . includes ( window . location . hash . slice ( 1 ) ) ?
509+ window . location . hash . slice ( 1 ) :
510+ serverCapabilities ?. resources ? "resources" :
511+ serverCapabilities ?. prompts ? "prompts" :
512+ serverCapabilities ?. tools ? "tools" :
513+ "ping"
514+ }
501515 className = "w-full p-4"
502516 onValueChange = { ( value ) => ( window . location . hash = value ) }
503517 >
504518 < TabsList className = "mb-4 p-0" >
505- < TabsTrigger value = "resources" >
519+ < TabsTrigger value = "resources" disabled = { ! serverCapabilities ?. resources } >
506520 < Files className = "w-4 h-4 mr-2" />
507521 Resources
508522 </ TabsTrigger >
509- < TabsTrigger value = "prompts" >
523+ < TabsTrigger value = "prompts" disabled = { ! serverCapabilities ?. prompts } >
510524 < MessageSquare className = "w-4 h-4 mr-2" />
511525 Prompts
512526 </ TabsTrigger >
513- < TabsTrigger value = "tools" >
527+ < TabsTrigger value = "tools" disabled = { ! serverCapabilities ?. tools } >
514528 < Hammer className = "w-4 h-4 mr-2" />
515529 Tools
516530 </ TabsTrigger >
@@ -534,107 +548,117 @@ const App = () => {
534548 </ TabsList >
535549
536550 < div className = "w-full" >
537- < ResourcesTab
538- resources = { resources }
539- resourceTemplates = { resourceTemplates }
540- listResources = { ( ) => {
541- clearError ( "resources" ) ;
542- listResources ( ) ;
543- } }
544- clearResources = { ( ) => {
545- setResources ( [ ] ) ;
546- setNextResourceCursor ( undefined ) ;
547- } }
548- listResourceTemplates = { ( ) => {
549- clearError ( "resources" ) ;
550- listResourceTemplates ( ) ;
551- } }
552- clearResourceTemplates = { ( ) => {
553- setResourceTemplates ( [ ] ) ;
554- setNextResourceTemplateCursor ( undefined ) ;
555- } }
556- readResource = { ( uri ) => {
557- clearError ( "resources" ) ;
558- readResource ( uri ) ;
559- } }
560- selectedResource = { selectedResource }
561- setSelectedResource = { ( resource ) => {
562- clearError ( "resources" ) ;
563- setSelectedResource ( resource ) ;
564- } }
565- resourceContent = { resourceContent }
566- nextCursor = { nextResourceCursor }
567- nextTemplateCursor = { nextResourceTemplateCursor }
568- error = { errors . resources }
569- />
570- < PromptsTab
571- prompts = { prompts }
572- listPrompts = { ( ) => {
573- clearError ( "prompts" ) ;
574- listPrompts ( ) ;
575- } }
576- clearPrompts = { ( ) => {
577- setPrompts ( [ ] ) ;
578- setNextPromptCursor ( undefined ) ;
579- } }
580- getPrompt = { ( name , args ) => {
581- clearError ( "prompts" ) ;
582- getPrompt ( name , args ) ;
583- } }
584- selectedPrompt = { selectedPrompt }
585- setSelectedPrompt = { ( prompt ) => {
586- clearError ( "prompts" ) ;
587- setSelectedPrompt ( prompt ) ;
588- } }
589- promptContent = { promptContent }
590- nextCursor = { nextPromptCursor }
591- error = { errors . prompts }
592- />
593- < ToolsTab
594- tools = { tools }
595- listTools = { ( ) => {
596- clearError ( "tools" ) ;
597- listTools ( ) ;
598- } }
599- clearTools = { ( ) => {
600- setTools ( [ ] ) ;
601- setNextToolCursor ( undefined ) ;
602- } }
603- callTool = { ( name , params ) => {
604- clearError ( "tools" ) ;
605- callTool ( name , params ) ;
606- } }
607- selectedTool = { selectedTool }
608- setSelectedTool = { ( tool ) => {
609- clearError ( "tools" ) ;
610- setSelectedTool ( tool ) ;
611- setToolResult ( null ) ;
612- } }
613- toolResult = { toolResult }
614- nextCursor = { nextToolCursor }
615- error = { errors . tools }
616- />
617- < ConsoleTab />
618- < PingTab
619- onPingClick = { ( ) => {
620- void makeRequest (
621- {
622- method : "ping" as const ,
623- } ,
624- EmptyResultSchema ,
625- ) ;
626- } }
627- />
628- < SamplingTab
629- pendingRequests = { pendingSampleRequests }
630- onApprove = { handleApproveSampling }
631- onReject = { handleRejectSampling }
632- />
633- < RootsTab
634- roots = { roots }
635- setRoots = { setRoots }
636- onRootsChange = { handleRootsChange }
637- />
551+ { ! serverCapabilities ?. resources && ! serverCapabilities ?. prompts && ! serverCapabilities ?. tools ? (
552+ < div className = "flex items-center justify-center p-4" >
553+ < p className = "text-lg text-gray-500" >
554+ The connected server does not support any MCP capabilities
555+ </ p >
556+ </ div >
557+ ) : (
558+ < >
559+ < ResourcesTab
560+ resources = { resources }
561+ resourceTemplates = { resourceTemplates }
562+ listResources = { ( ) => {
563+ clearError ( "resources" ) ;
564+ listResources ( ) ;
565+ } }
566+ clearResources = { ( ) => {
567+ setResources ( [ ] ) ;
568+ setNextResourceCursor ( undefined ) ;
569+ } }
570+ listResourceTemplates = { ( ) => {
571+ clearError ( "resources" ) ;
572+ listResourceTemplates ( ) ;
573+ } }
574+ clearResourceTemplates = { ( ) => {
575+ setResourceTemplates ( [ ] ) ;
576+ setNextResourceTemplateCursor ( undefined ) ;
577+ } }
578+ readResource = { ( uri ) => {
579+ clearError ( "resources" ) ;
580+ readResource ( uri ) ;
581+ } }
582+ selectedResource = { selectedResource }
583+ setSelectedResource = { ( resource ) => {
584+ clearError ( "resources" ) ;
585+ setSelectedResource ( resource ) ;
586+ } }
587+ resourceContent = { resourceContent }
588+ nextCursor = { nextResourceCursor }
589+ nextTemplateCursor = { nextResourceTemplateCursor }
590+ error = { errors . resources }
591+ />
592+ < PromptsTab
593+ prompts = { prompts }
594+ listPrompts = { ( ) => {
595+ clearError ( "prompts" ) ;
596+ listPrompts ( ) ;
597+ } }
598+ clearPrompts = { ( ) => {
599+ setPrompts ( [ ] ) ;
600+ setNextPromptCursor ( undefined ) ;
601+ } }
602+ getPrompt = { ( name , args ) => {
603+ clearError ( "prompts" ) ;
604+ getPrompt ( name , args ) ;
605+ } }
606+ selectedPrompt = { selectedPrompt }
607+ setSelectedPrompt = { ( prompt ) => {
608+ clearError ( "prompts" ) ;
609+ setSelectedPrompt ( prompt ) ;
610+ } }
611+ promptContent = { promptContent }
612+ nextCursor = { nextPromptCursor }
613+ error = { errors . prompts }
614+ />
615+ < ToolsTab
616+ tools = { tools }
617+ listTools = { ( ) => {
618+ clearError ( "tools" ) ;
619+ listTools ( ) ;
620+ } }
621+ clearTools = { ( ) => {
622+ setTools ( [ ] ) ;
623+ setNextToolCursor ( undefined ) ;
624+ } }
625+ callTool = { ( name , params ) => {
626+ clearError ( "tools" ) ;
627+ callTool ( name , params ) ;
628+ } }
629+ selectedTool = { selectedTool }
630+ setSelectedTool = { ( tool ) => {
631+ clearError ( "tools" ) ;
632+ setSelectedTool ( tool ) ;
633+ setToolResult ( null ) ;
634+ } }
635+ toolResult = { toolResult }
636+ nextCursor = { nextToolCursor }
637+ error = { errors . tools }
638+ />
639+ < ConsoleTab />
640+ < PingTab
641+ onPingClick = { ( ) => {
642+ void makeRequest (
643+ {
644+ method : "ping" as const ,
645+ } ,
646+ EmptyResultSchema ,
647+ ) ;
648+ } }
649+ />
650+ < SamplingTab
651+ pendingRequests = { pendingSampleRequests }
652+ onApprove = { handleApproveSampling }
653+ onReject = { handleRejectSampling }
654+ />
655+ < RootsTab
656+ roots = { roots }
657+ setRoots = { setRoots }
658+ onRootsChange = { handleRootsChange }
659+ />
660+ </ >
661+ ) }
638662 </ div >
639663 </ Tabs >
640664 ) : (
0 commit comments