import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { useMutation, useQuery, useSuspenseQuery, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, type UseSuspenseQueryResult, } from "@tanstack/react-query"; import type { CallToolRequest, CallToolResult, ListToolsResult, } from "@modelcontextprotocol/sdk/types.js"; import { KEYS } from "../lib/query-keys"; export interface UseMcpToolsListOptions extends Omit< UseSuspenseQueryOptions, "queryKey" | "queryFn" > { /** The MCP client from useMCPClient */ client: Client; } /** * Suspense hook to list tools from an MCP client. * Must be used within a Suspense boundary. */ export function useMCPToolsList({ client, ...queryOptions }: UseMcpToolsListOptions): UseSuspenseQueryResult { return useSuspenseQuery({ ...queryOptions, queryKey: KEYS.mcpToolsList(client), queryFn: async () => { return await client.listTools(); }, staleTime: queryOptions.staleTime ?? 30000, retry: false, }); } export interface UseMcpToolsListQueryOptions extends Omit< UseQueryOptions, "queryKey" | "queryFn" > { /** The MCP client from useMCPClient */ client: Client; } /** * Non-suspense hook to list tools from an MCP client. */ export function useMCPToolsListQuery({ client, ...queryOptions }: UseMcpToolsListQueryOptions): UseQueryResult { return useQuery({ ...queryOptions, queryKey: KEYS.mcpToolsList(client), queryFn: async () => { return await client.listTools(); }, staleTime: queryOptions.staleTime ?? 30000, retry: false, }); } export interface UseMcpToolCallOptions extends Omit< UseSuspenseQueryOptions, "queryKey" | "queryFn" > { /** The MCP client from useMCPClient */ client: Client; /** Tool name to call */ toolName: string; /** Tool arguments */ toolArguments?: Record; } /** * Suspense hook to call a tool on an MCP client. * Must be used within a Suspense boundary. * * @template TData - The type of data returned (after optional select transformation) */ export function useMCPToolCall({ client, toolName, toolArguments, ...queryOptions }: UseMcpToolCallOptions): UseSuspenseQueryResult { const argsKey = JSON.stringify(toolArguments ?? {}); return useSuspenseQuery({ ...queryOptions, queryKey: KEYS.mcpToolCall(client, toolName, argsKey), queryFn: async () => { const result = await client.callTool({ name: toolName, arguments: toolArguments, }); return result as CallToolResult; }, staleTime: queryOptions.staleTime ?? 30000, retry: false, }); } export interface UseMcpToolCallQueryOptions extends Omit< UseQueryOptions, "queryKey" | "queryFn" > { /** The MCP client from useMCPClient */ client: Client; /** Tool name to call */ toolName: string; /** Tool arguments */ toolArguments?: Record; } /** * Non-suspense hook to call a tool on an MCP client. * * @template TData - The type of data returned (after optional select transformation) */ export function useMCPToolCallQuery({ client, toolName, toolArguments, ...queryOptions }: UseMcpToolCallQueryOptions): UseQueryResult { const argsKey = JSON.stringify(toolArguments ?? {}); return useQuery({ ...queryOptions, queryKey: KEYS.mcpToolCall(client, toolName, argsKey), queryFn: async () => { const result = await client.callTool({ name: toolName, arguments: toolArguments, }); return result as CallToolResult; }, staleTime: queryOptions.staleTime ?? 30000, retry: false, }); } export interface UseMcpToolCallMutationOptions extends Omit< UseMutationOptions, "mutationFn" > { /** The MCP client from useMCPClient */ client: Client; } /** * Mutation hook to call a tool on an MCP client. */ export function useMCPToolCallMutation({ client, ...mutationOptions }: UseMcpToolCallMutationOptions): UseMutationResult< CallToolResult, Error, CallToolRequest["params"] > { return useMutation({ ...mutationOptions, mutationFn: async (params) => { return (await client.callTool(params)) as CallToolResult; }, }); }