> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leanmcp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# UI Hooks

> React hooks for MCP tool calls, resources, and host communication

# MCP Hooks

React hooks for interacting with MCP servers from within your App components. All hooks work within an `AppProvider` or `GPTAppProvider` context.

## useTool

The primary hook for calling MCP tools with full state management, retries, and result transformation.

### Basic Usage

```tsx theme={null}
function RefreshButton() {
  const { call, loading, result, error } = useTool('refresh-data');

  return (
    <button onClick={() => call()} disabled={loading}>
      {loading ? 'Refreshing...' : 'Refresh'}
    </button>
  );
}
```

### With Arguments

```tsx theme={null}
function WeatherWidget({ city }: { city: string }) {
  const { call, result, loading } = useTool('get-weather');

  useEffect(() => {
    call({ city });
  }, [city]);

  if (loading) return <Skeleton />;
  return <div>{result?.temperature}°C</div>;
}
```

### With Options

```tsx theme={null}
const { call, result, error, retry, reset } = useTool('create-item', {
  defaultArgs: { type: 'note' },
  transform: (result) => result.structuredContent?.item,
  retry: { count: 3, delay: 1000 },
  onStart: () => console.log('Starting...'),
  onSuccess: (item) => toast.success(`Created: ${item.name}`),
  onError: (error) => toast.error(error.message),
  onComplete: () => console.log('Done'),
});
```

### Return Value

| Property  | Type                                          | Description               |
| --------- | --------------------------------------------- | ------------------------- |
| `call`    | `(args?) => Promise<T>`                       | Execute the tool          |
| `mutate`  | `(args) => Promise<T>`                        | Alias for call (semantic) |
| `loading` | `boolean`                                     | Whether tool is executing |
| `state`   | `'idle' \| 'loading' \| 'success' \| 'error'` | Current state             |
| `result`  | `T \| null`                                   | Last successful result    |
| `error`   | `Error \| null`                               | Last error                |
| `reset`   | `() => void`                                  | Reset to initial state    |
| `retry`   | `() => Promise<T>`                            | Retry last call           |
| `abort`   | `() => void`                                  | Abort current call        |

### Options

| Option        | Type                         | Description                             |
| ------------- | ---------------------------- | --------------------------------------- |
| `defaultArgs` | `Record<string, unknown>`    | Default arguments merged with call args |
| `transform`   | `(result) => T`              | Transform the raw tool result           |
| `retry`       | `number \| { count, delay }` | Retry configuration                     |
| `onStart`     | `() => void`                 | Called when tool starts                 |
| `onSuccess`   | `(result) => void`           | Called on success                       |
| `onError`     | `(error) => void`            | Called on error                         |
| `onComplete`  | `() => void`                 | Called after success or error           |

***

## useResource

Read MCP server resources with auto-refresh and subscription support.

### Basic Usage

```tsx theme={null}
function UserProfile() {
  const { data, loading, error, refresh } = useResource<User>('user://profile');

  if (loading) return <Skeleton />;
  if (error) return <Alert>{error.message}</Alert>;

  return (
    <Card>
      <h2>{data?.name}</h2>
      <Button onClick={refresh}>Refresh</Button>
    </Card>
  );
}
```

### With Auto-Refresh

```tsx theme={null}
const { data } = useResource('metrics://dashboard', {
  refreshInterval: 5000,  // Refresh every 5 seconds
  transform: (raw) => raw.metrics,
});
```

### Return Value

| Property      | Type               | Description           |
| ------------- | ------------------ | --------------------- |
| `data`        | `T \| null`        | Resource data         |
| `loading`     | `boolean`          | Whether loading       |
| `error`       | `Error \| null`    | Error if any          |
| `refresh`     | `() => Promise<T>` | Manual refresh        |
| `lastUpdated` | `Date \| null`     | Last update timestamp |

### Options

| Option            | Type          | Description                          |
| ----------------- | ------------- | ------------------------------------ |
| `refreshInterval` | `number`      | Auto-refresh interval in ms          |
| `subscribe`       | `boolean`     | Enable subscription (when supported) |
| `transform`       | `(data) => T` | Transform resource data              |
| `skip`            | `boolean`     | Skip initial fetch                   |

***

## useMessage

Send messages to the host chat interface.

```tsx theme={null}
function FeedbackButton() {
  const { sendMessage } = useMessage();

  const handleClick = async () => {
    await sendMessage('User requested help with the dashboard');
  };

  return <Button onClick={handleClick}>Ask for Help</Button>;
}
```

### Return Value

| Property      | Type                              | Description          |
| ------------- | --------------------------------- | -------------------- |
| `sendMessage` | `(text: string) => Promise<void>` | Send message to host |

***

## useHostContext

Access host environment information like theme, viewport, and display mode.

```tsx theme={null}
function ThemedComponent() {
  const { theme, displayMode, viewport } = useHostContext();

  return (
    <div className={theme === 'dark' ? 'dark-mode' : 'light-mode'}>
      <p>Display mode: {displayMode}</p>
      <p>Viewport: {viewport?.width}x{viewport?.height}</p>
    </div>
  );
}
```

### Return Value

| Property      | Type                | Description          |
| ------------- | ------------------- | -------------------- |
| `theme`       | `'light' \| 'dark'` | Current theme        |
| `displayMode` | `string`            | Current display mode |
| `viewport`    | `{ width, height }` | Viewport dimensions  |
| `styles`      | `object`            | Host style variables |

***

## useToolResult

Access the tool result passed from the host when rendering a tool-linked UI.

```tsx theme={null}
function WeatherCard() {
  const { result, loading, error } = useToolResult<WeatherData>();

  if (loading) return <Skeleton />;
  if (error) return <Alert>{error.message}</Alert>;
  if (!result) return null;

  return (
    <Card>
      <h2>{result.city}</h2>
      <p>{result.temperature}°C - {result.condition}</p>
    </Card>
  );
}
```

***

## useToolInput

Access the tool input arguments when the host is streaming input to your app.

```tsx theme={null}
function LivePreview() {
  const { input } = useToolInput<{ query: string }>();

  return (
    <div>
      <p>Current query: {input?.query ?? 'None'}</p>
    </div>
  );
}
```

***

## useToolStream

Handle streaming tool responses with partial updates.

```tsx theme={null}
function StreamingResponse() {
  const { partial, isStreaming } = useToolStream<{ text: string }>();

  return (
    <div>
      {isStreaming && <Spinner />}
      <ReactMarkdown>{partial?.text ?? ''}</ReactMarkdown>
    </div>
  );
}
```

***

## useMcpApp

Low-level hook to access the full MCP App context. Most use cases are covered by the specialized hooks above.

```tsx theme={null}
function AdvancedComponent() {
  const { 
    app,           // Raw ext-apps App instance
    isConnected,   // Connection state
    error,         // Connection error
    callTool,      // Call any tool
    sendMessage,   // Send chat message
    sendLog,       // Send log to host
    openLink,      // Open URL in host
    requestDisplayMode,  // Request display mode change
  } = useMcpApp();

  const handleFullscreen = async () => {
    await requestDisplayMode('fullscreen');
  };

  return (
    <Button onClick={handleFullscreen}>
      Go Fullscreen
    </Button>
  );
}
```
