Skip to main content
Most data hooks support multi-server targeting via an options.server parameter. When omitted, they use the provider’s default server. Low-level hooks like useServer and useResolvedServer accept a server name directly as an argument instead.

useCallTool

Call an MCP tool with typed input/output.
const [callTool, state, reset] = useCallTool<InputType, OutputType>(toolName, options?);

Parameters

ParameterTypeDescription
toolNamestringName of the MCP tool
options.serverstringTarget a named server
options.onSuccess(data) => voidSuccess callback
options.onError(error) => voidError callback
options.resetOnToolChangebooleanReset state when toolName changes (default: true)

Return Value

IndexTypeDescription
[0](args: TInput) => Promise<TOutput | null>Call function
[1]ToolState<TOutput>{ data, loading, error, called }
[2]() => voidReset state

Example

function SearchTool() {
  const [search, { data, loading, error, called }, reset] = useCallTool('search');

  return (
    <div>
      <button onClick={() => search({ query: 'react' })}>Search</button>
      <button onClick={reset}>Reset</button>
      {loading && <p>Searching...</p>}
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  );
}

useReadResource

Dual-mode resource reading — lazy or auto-fetch.

Lazy Mode

const [readFn, state] = useReadResource(options?);
Returns a [read, state] tuple. Call read(uri) on demand.
function LazyReader() {
  const [read, { data, loading }] = useReadResource();

  return <button onClick={() => read('app://config')}>Load Config</button>;
}

Auto-Fetch Mode

const { data, loading, error, refetch } = useReadResource(uri, options?);
Fetches automatically when connected. Call refetch() to re-read.
function AutoReader() {
  const { data, loading, refetch } = useReadResource('app://status');

  return (
    <div>
      {loading ? 'Loading...' : JSON.stringify(data)}
      <button onClick={refetch}>Refresh</button>
    </div>
  );
}

useGetPrompt

Fetch an MCP prompt by name.
const [getPrompt, state] = useGetPrompt(promptName, options?);

Example

function PromptFetcher() {
  const [getPrompt, { data, loading }] = useGetPrompt('summarize');

  return (
    <button onClick={() => getPrompt({ topic: 'AI safety' })}>
      {loading ? 'Loading...' : 'Get Prompt'}
    </button>
  );
}

useListTools

Reactive tool list from the registry.
const tools: ToolInfo[] = useListTools(options?);
function ToolList() {
  const tools = useListTools();
  return (
    <ul>
      {tools.map((t) => <li key={t.name}>{t.name}{t.description}</li>)}
    </ul>
  );
}

useListResources

Reactive resource and resource template lists.
const { resources, resourceTemplates } = useListResources(options?);

useListPrompts

Reactive prompt list.
const prompts: PromptInfo[] = useListPrompts(options?);

useStoreResource

Subscribe to a state:// URI with live updates via MCP resource subscriptions.
const { data, loading, error, refetch } = useStoreResource(uri, options?);
When the server sends notifications/resources/updated, the hook automatically re-fetches the resource. Content is JSON-parsed when possible.

Example

function LiveCounter() {
  const { data, loading } = useStoreResource('state://counter');

  if (loading) return <p>Loading...</p>;
  return <p>Count: {String(data)}</p>;
}

useServer

Low-level hook to access a raw ServerEntry from the registry.
const entry: ServerEntry | undefined = useServer(name?);
Uses useSyncExternalStore for tear-free reads.

useResolvedServer

Internal hook that resolves a server entry with context fallback.
const { entry, name, registry, connect } = useResolvedServer(serverName?);
This is the shared foundation for all other hooks. You typically don’t need to use it directly.

useDynamicTool

Register an MCP tool on mount, unregister on unmount. See Dynamic Tools for full details. Supports both zod schemas (recommended) and raw JSON Schema (backward compat).
import { useDynamicTool } from '@frontmcp/react';
import { z } from 'zod';

useDynamicTool({
  name: 'add_to_cart',
  description: 'Add item to cart',
  schema: z.object({
    itemId: z.string(),
    quantity: z.number().optional(),
  }),
  execute: async (args) => {
    // args is typed as { itemId: string; quantity?: number }
    addToCart(args.itemId, args.quantity ?? 1);
    return { content: [{ type: 'text', text: 'Added' }] };
  },
  enabled: isLoggedIn,
});
When using a zod schema, input is automatically validated via safeParse before reaching your execute callback. Invalid input returns an error CallToolResult with validation details.

With JSON Schema (Backward Compat)

useDynamicTool({
  name: 'add_to_cart',
  description: 'Add item to cart',
  inputSchema: { type: 'object', properties: { itemId: { type: 'string' } } },
  execute: async (args) => {
    addToCart(args.itemId as string);
    return { content: [{ type: 'text', text: 'Added' }] };
  },
});

Options

OptionTypeDefaultDescription
namestringRequired. Tool name
descriptionstringRequired. Description for agents
schemaz.ZodObjectZod schema (mutually exclusive with inputSchema)
inputSchemaRecord<string, unknown>JSON Schema (mutually exclusive with schema)
execute(args) => Promise<CallToolResult>Required. Handler
enabledbooleantrueConditionally enable/disable
serverstringTarget a named server

useDynamicResource

Register an MCP resource on mount, unregister on unmount. See Dynamic Tools for full details.
import { useDynamicResource } from '@frontmcp/react';

useDynamicResource({
  uri: 'app://user-prefs',
  name: 'user-prefs',
  description: 'Current user preferences',
  mimeType: 'application/json',
  read: async () => ({
    contents: [{ uri: 'app://user-prefs', text: JSON.stringify(prefs) }],
  }),
});

Options

OptionTypeDefaultDescription
uristringRequired. Resource URI
namestringRequired. Human-readable name
descriptionstringDescription for agents
mimeTypestringContent MIME type
read() => Promise<ReadResourceResult>Required. Handler
enabledbooleantrueConditionally enable/disable
serverstringTarget a named server

useComponentTree

Expose the DOM subtree under a ref as a JSON MCP resource. See Dynamic Tools for full details.
import { useRef } from 'react';
import { useComponentTree } from '@frontmcp/react';

const rootRef = useRef<HTMLDivElement>(null);

useComponentTree({
  rootRef,
  uri: 'react://component-tree',
  maxDepth: 10,
  includeProps: true,
});

Options

OptionTypeDefaultDescription
rootRefRefObject<HTMLElement | null>Required. Root element ref
uristring'react://component-tree'Resource URI
maxDepthnumber10Max traversal depth
includePropsbooleanfalseInclude data-* attributes
serverstringTarget a named server

Multi-Server Pattern

All hooks accept { server: 'name' } to target a specific server:
// Call a tool on the analytics server
const [track, state] = useCallTool('track_event', { server: 'analytics' });

// Read a resource from the config server
const { data } = useReadResource('app://settings', { server: 'config' });

// List tools from a specific server
const tools = useListTools({ server: 'analytics' });

// Subscribe to state on a specific server
const { data } = useStoreResource('state://counter', { server: 'state-server' });