---
title: Hooks Reference
slug: react/hooks
icon: hook
description: Complete API reference for all @frontmcp/react hooks
keywords: ['frontmcp', 'mcp', 'model context protocol', 'react', 'ui', 'frontend', 'client', 'hooks', 'typescript']
---

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.

```tsx
const [callTool, state, reset] = useCallTool<InputType, OutputType>(toolName, options?);
```

### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `toolName` | `string` | Name of the MCP tool |
| `options.server` | `string` | Target a named server |
| `options.onSuccess` | `(data) => void` | Success callback |
| `options.onError` | `(error) => void` | Error callback |
| `options.resetOnToolChange` | `boolean` | Reset state when `toolName` changes (default: `true`) |

### Return Value

| Index | Type | Description |
|-------|------|-------------|
| `[0]` | `(args: TInput) => Promise<TOutput \| null>` | Call function |
| `[1]` | `ToolState<TOutput>` | `{ data, loading, error, called }` |
| `[2]` | `() => void` | Reset state |

### Example

```tsx
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

```tsx
const [readFn, state] = useReadResource(options?);
```

Returns a `[read, state]` tuple. Call `read(uri)` on demand.

```tsx
function LazyReader() {
  const [read, { data, loading }] = useReadResource();

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

### Auto-Fetch Mode

```tsx
const { data, loading, error, refetch } = useReadResource(uri, options?);
```

Fetches automatically when connected. Call `refetch()` to re-read.

```tsx
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.

```tsx
const [getPrompt, state] = useGetPrompt(promptName, options?);
```

### Example

```tsx
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.

```tsx
const tools: ToolInfo[] = useListTools(options?);
```

```tsx
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.

```tsx
const { resources, resourceTemplates } = useListResources(options?);
```

---

## useListPrompts

Reactive prompt list.

```tsx
const prompts: PromptInfo[] = useListPrompts(options?);
```

---

## useStoreResource

Subscribe to a `state://` URI with live updates via MCP resource subscriptions.

```tsx
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

```tsx
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.

```tsx
const entry: ServerEntry | undefined = useServer(name?);
```

Uses `useSyncExternalStore` for tear-free reads.

---

## useResolvedServer

Internal hook that resolves a server entry with context fallback.

```tsx
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](/frontmcp/react/dynamic-tools) for full details.

Supports both **zod schemas** (recommended) and raw **JSON Schema** (backward compat).

### With Zod Schema (Recommended)

```tsx
import { useDynamicTool } from '@frontmcp/react';
import { z } from '@frontmcp/sdk';

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)

```tsx
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

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `name` | `string` | — | **Required.** Tool name |
| `description` | `string` | — | **Required.** Description for agents |
| `schema` | `z.ZodObject` | — | Zod schema (mutually exclusive with `inputSchema`) |
| `inputSchema` | `Record<string, unknown>` | — | JSON Schema (mutually exclusive with `schema`) |
| `execute` | `(args) => Promise<CallToolResult>` | — | **Required.** Handler |
| `enabled` | `boolean` | `true` | Conditionally enable/disable |
| `server` | `string` | — | Target a named server |

---

## useDynamicResource

Register an MCP resource on mount, unregister on unmount. See [Dynamic Tools](/frontmcp/react/dynamic-tools) for full details.

```tsx
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

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `uri` | `string` | — | **Required.** Resource URI |
| `name` | `string` | — | **Required.** Human-readable name |
| `description` | `string` | — | Description for agents |
| `mimeType` | `string` | — | Content MIME type |
| `read` | `() => Promise<ReadResourceResult>` | — | **Required.** Handler |
| `enabled` | `boolean` | `true` | Conditionally enable/disable |
| `server` | `string` | — | Target a named server |

---

## useComponentTree

Expose the DOM subtree under a ref as a JSON MCP resource. See [Dynamic Tools](/frontmcp/react/dynamic-tools) for full details.

```tsx
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

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `rootRef` | `RefObject<HTMLElement \| null>` | — | **Required.** Root element ref |
| `uri` | `string` | `'react://component-tree'` | Resource URI |
| `maxDepth` | `number` | `10` | Max traversal depth |
| `includeProps` | `boolean` | `false` | Include `data-*` attributes |
| `server` | `string` | — | Target a named server |

---

## Multi-Server Pattern

All hooks accept `{ server: 'name' }` to target a specific server:

```tsx
// 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' });
```
