import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { TabsContent } from "@/components/ui/tabs"; import { ListResourcesResult, Resource, ResourceTemplate, ListResourceTemplatesResult, } from "@modelcontextprotocol/sdk/types.js"; import { AlertCircle, ChevronRight, FileText, RefreshCw } from "lucide-react"; import ListPane from "./ListPane"; import { useState } from "react"; const ResourcesTab = ({ resources, resourceTemplates, listResources, listResourceTemplates, readResource, selectedResource, setSelectedResource, resourceContent, nextCursor, nextTemplateCursor, error, }: { resources: Resource[]; resourceTemplates: ResourceTemplate[]; listResources: () => void; listResourceTemplates: () => void; readResource: (uri: string) => void; selectedResource: Resource | null; setSelectedResource: (resource: Resource | null) => void; resourceContent: string; nextCursor: ListResourcesResult["nextCursor"]; nextTemplateCursor: ListResourceTemplatesResult["nextCursor"]; error: string | null; }) => { const [selectedTemplate, setSelectedTemplate] = useState(null); const [templateValues, setTemplateValues] = useState>( {}, ); const fillTemplate = ( template: string, values: Record, ): string => { return template.replace( /{([^}]+)}/g, (_, key) => values[key] || `{${key}}`, ); }; const handleReadTemplateResource = () => { if (selectedTemplate) { const uri = fillTemplate(selectedTemplate.uriTemplate, templateValues); readResource(uri); setSelectedTemplate(null); // We don't have the full Resource object here, so we create a partial one setSelectedResource({ uri, name: uri } as Resource); } }; return ( { setSelectedResource(resource); readResource(resource.uri); setSelectedTemplate(null); }} renderItem={(resource) => (
{resource.name}
)} title="Resources" buttonText={nextCursor ? "List More Resources" : "List Resources"} isButtonDisabled={!nextCursor && resources.length > 0} /> { setSelectedTemplate(template); setSelectedResource(null); setTemplateValues({}); }} renderItem={(template) => (
{template.name}
)} title="Resource Templates" buttonText={ nextTemplateCursor ? "List More Templates" : "List Templates" } isButtonDisabled={!nextTemplateCursor && resourceTemplates.length > 0} />

{selectedResource ? selectedResource.name : selectedTemplate ? selectedTemplate.name : "Select a resource or template"}

{selectedResource && ( )}
{error ? ( Error {error} ) : selectedResource ? (
              {resourceContent}
            
) : selectedTemplate ? (

{selectedTemplate.description}

{selectedTemplate.uriTemplate .match(/{([^}]+)}/g) ?.map((param) => { const key = param.slice(1, -1); return (
setTemplateValues({ ...templateValues, [key]: e.target.value, }) } className="mt-1" />
); })}
) : ( Select a resource or template from the list to view its contents )}
); }; export default ResourcesTab;