diff --git a/client/src/App.tsx b/client/src/App.tsx index b255ab5..cd03714 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -74,6 +74,13 @@ const App = () => { ); const [selectedPrompt, setSelectedPrompt] = useState(null); const [selectedTool, setSelectedTool] = useState(null); + const [nextResourceCursor, setNextResourceCursor] = useState< + string | undefined + >(); + const [nextPromptCursor, setNextPromptCursor] = useState< + string | undefined + >(); + const [nextToolCursor, setNextToolCursor] = useState(); const progressTokenRef = useRef(0); const pushHistory = (request: object, response: object) => { @@ -105,12 +112,12 @@ const App = () => { const response = await makeRequest( { method: "resources/list" as const, + params: nextResourceCursor ? { cursor: nextResourceCursor } : {}, }, ListResourcesResultSchema, ); - if (response.resources) { - setResources(response.resources); - } + setResources(resources.concat(response.resources ?? [])); + setNextResourceCursor(response.nextCursor); }; const readResource = async (uri: URL) => { @@ -128,10 +135,12 @@ const App = () => { const response = await makeRequest( { method: "prompts/list" as const, + params: nextPromptCursor ? { cursor: nextPromptCursor } : {}, }, ListPromptsResultSchema, ); setPrompts(response.prompts); + setNextPromptCursor(response.nextCursor); }; const getPrompt = async (name: string, args: Record = {}) => { @@ -149,10 +158,12 @@ const App = () => { const response = await makeRequest( { method: "tools/list" as const, + params: nextToolCursor ? { cursor: nextToolCursor } : {}, }, ListToolsResultSchema, ); setTools(response.tools); + setNextToolCursor(response.nextCursor); }; const callTool = async (name: string, params: Record) => { @@ -293,6 +304,7 @@ const App = () => { selectedResource={selectedResource} setSelectedResource={setSelectedResource} resourceContent={resourceContent} + nextCursor={nextResourceCursor} error={error} /> { selectedPrompt={selectedPrompt} setSelectedPrompt={setSelectedPrompt} promptContent={promptContent} + nextCursor={nextPromptCursor} error={error} /> @@ -315,6 +328,7 @@ const App = () => { setToolResult(""); }} toolResult={toolResult} + nextCursor={nextToolCursor} error={error} /> diff --git a/client/src/components/ListPane.tsx b/client/src/components/ListPane.tsx index 0a0760b..fa703b5 100644 --- a/client/src/components/ListPane.tsx +++ b/client/src/components/ListPane.tsx @@ -7,6 +7,7 @@ type ListPaneProps = { renderItem: (item: T) => React.ReactNode; title: string; buttonText: string; + isButtonDisabled?: boolean; }; const ListPane = ({ @@ -16,16 +17,22 @@ const ListPane = ({ renderItem, title, buttonText, + isButtonDisabled, }: ListPaneProps) => (

{title}

- -
+
{items.map((item, index) => (
void; promptContent: string; + nextCursor: ListPromptsResult["nextCursor"]; error: string | null; }) => { const [promptArgs, setPromptArgs] = useState>({}); @@ -63,7 +66,8 @@ const PromptsTab = ({ )} title="Prompts" - buttonText="List Prompts" + buttonText={nextCursor ? "List More Prompts" : "List Prompts"} + isButtonDisabled={!nextCursor && prompts.length > 0} />
diff --git a/client/src/components/ResourcesTab.tsx b/client/src/components/ResourcesTab.tsx index f315933..7fe62cf 100644 --- a/client/src/components/ResourcesTab.tsx +++ b/client/src/components/ResourcesTab.tsx @@ -2,7 +2,7 @@ import { FileText, ChevronRight, AlertCircle, RefreshCw } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { TabsContent } from "@/components/ui/tabs"; -import { Resource } from "mcp-typescript/types.js"; +import { ListResourcesResult, Resource } from "mcp-typescript/types.js"; import ListPane from "./ListPane"; const ResourcesTab = ({ @@ -12,6 +12,7 @@ const ResourcesTab = ({ selectedResource, setSelectedResource, resourceContent, + nextCursor, error, }: { resources: Resource[]; @@ -20,6 +21,7 @@ const ResourcesTab = ({ selectedResource: Resource | null; setSelectedResource: (resource: Resource) => void; resourceContent: string; + nextCursor: ListResourcesResult["nextCursor"]; error: string | null; }) => ( @@ -40,7 +42,8 @@ const ResourcesTab = ({
)} title="Resources" - buttonText="List Resources" + buttonText={nextCursor ? "List More Resources" : "List Resources"} + isButtonDisabled={!nextCursor && resources.length > 0} />
diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index c7efa33..e0a3c84 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Send, AlertCircle } from "lucide-react"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { Tool } from "mcp-typescript/types.js"; +import { ListToolsResult, Tool } from "mcp-typescript/types.js"; import { useState } from "react"; import { Label } from "@/components/ui/label"; import ListPane from "./ListPane"; @@ -15,6 +15,7 @@ const ToolsTab = ({ selectedTool, setSelectedTool, toolResult, + nextCursor, error, }: { tools: Tool[]; @@ -23,6 +24,7 @@ const ToolsTab = ({ selectedTool: Tool | null; setSelectedTool: (tool: Tool) => void; toolResult: string; + nextCursor: ListToolsResult["nextCursor"]; error: string | null; }) => { const [params, setParams] = useState>({}); @@ -42,7 +44,8 @@ const ToolsTab = ({ )} title="Tools" - buttonText="List Tools" + buttonText={nextCursor ? "List More Tools" : "List Tools"} + isButtonDisabled={!nextCursor && tools.length > 0} />