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

# Use React hooks

> Start with one result hook and add interactive calls only when you need them.

The [first widget](https://toolgrain.mintlify.site/mcp-apps/quickstart.md) uses one provider and one hook. Add the other hooks as the widget gains features.

| You want to… | Use |
| - | - |
| Connect the widget to its host | `AppProvider` around the component tree |
| Display the tool's initial result | `useToolResult()` |
| Refresh or filter by calling a tool | `useToolCall("tool_name")` |
| Read locale, current display mode, or other host hints | `useHostContext()` |
| Open a link, send a message, share context, or change display mode | [`useHostActions()`](https://toolgrain.mintlify.site/mcp-apps/host-actions) |

Create the bindings once in `src/mcp.ts`. Components import the hooks from that file. Every hook runs inside that factory's `AppProvider`.

## Display the first result

```tsx theme={null}
const { result, error, status } = useToolResult();
```

`result` is the complete initiating tool result. Its `structuredContent` contains the typed data you returned on the server. It can be absent while waiting, after cancellation, or when a tool fails.

Handle `error`, `result?.isError`, and missing data before rendering the result, as shown in the quickstart. With several tools in the map, use `useToolResult("weather")` to select the expected tool's type. An unnamed result is a union you can narrow by `state.toolName`.

## Add a refresh button

First, export `useToolCall` alongside your existing bindings:

```ts src/mcp.ts theme={null}
import { createApp } from "@toolgrain/react";
import type { tools } from "../server/tools.ts";

export const { AppProvider, useToolResult, useToolCall } = createApp<typeof tools>();
```

In `src/App.tsx`, import `useToolCall` from `./mcp.ts`. Replace the `Weather` component with this version; keep it inside the provider:

```tsx theme={null}
function Weather() {
  const initial = useToolResult("weather");
  const refresh = useToolCall("weather");
  const result = refresh.result ?? initial.result;

  if (initial.error) return <p role="alert">{initial.error.message}</p>;
  if (result?.isError) return <p role="alert">The tool reported a weather error.</p>;
  const weather = result?.structuredContent;
  if (!weather) return <p>Waiting for weather…</p>;

  return (
    <section>
      <h1>{weather.city}</h1>
      <p>{weather.temperature}°C</p>
      <button
        type="button"
        disabled={refresh.pending}
        onClick={() => {
          void refresh.call({
            city: weather.city === "Dubai" ? "London" : "Dubai",
          }).catch(() => {});
        }}
      >
        {refresh.pending ? "Refreshing…" : "Switch city"}
      </button>
      {refresh.error ? <p role="alert">Refresh failed. Try again.</p> : null}
    </section>
  );
}
```

`useToolCall` returns `call`, `pending`, `result`, and `error`. The catch prevents an unhandled rejection; the hook stores the failure in `refresh.error`, which the component displays. The host must advertise server tool-call support.

The initial result and refresh result are separate. `refresh.result ?? initial.result` displays the latest successful call or the original data. The hook does not overwrite `useToolResult()` or start calls automatically.

## Interactive calls

`call(input, options?)` returns the full result. Explicit `isError: true` tool results resolve normally; transport and JSON-RPC failures reject. Concurrent calls each settle their promises, while the latest invocation owns the hook's displayed state.

Options are optional:

```ts theme={null}
const controller = new AbortController();
await refresh.call({ city: "London" }, {
  timeoutMs: 10_000,
  signal: controller.signal,
});
```

The default deadline is 30 seconds. An abort or timeout rejects locally and suppresses late replies. Host cancellation remains cooperative.

## Read host context when needed

The provider already applies host fonts and theme variables. CSS such as `var(--color-text-primary, #1f2937)` is enough for the basic widget.

Export `useHostContext` from `src/mcp.ts` when you need host information in React logic:

```tsx theme={null}
const { locale, timeZone, displayMode } = useHostContext();
```

These hints are optional. Supply application defaults, such as `locale ?? "en"`. Use [host actions](https://toolgrain.mintlify.site/mcp-apps/host-actions.md) to request a display-mode change or another explicit host operation.

## Inferred types

Tool names come from registration keys. Arguments use the input schema's input type, before defaults/transforms. Structured results use the parsed output schema type. Result `_meta` retains the type inferred from `mcpResult()`.

`structuredContent` and `_meta` remain optional. Toolgrain validates the wire envelopes; application payload types are inferred rather than schema-validated in the browser. See [metadata](https://toolgrain.mintlify.site/mcp-apps/security.md#extra-widget-data) for an example.

## Provider lifecycle

Use one provider per widget window. Pass `appInfo` and either `tool` for a separate entry or `resolveTool` for a [shared entry](https://toolgrain.mintlify.site/mcp-apps/shared-entries.md). Identity, routing, and declared display modes are fixed for that mount.

The factory is safe to import during server rendering. Mounting connects to the host; React Strict Mode reuses the connection during effect replay. Unmount/host teardown removes owned listeners, observers, and timers and rejects pending requests. Remount to reconnect.

Host styling and automatic size reporting default to on. Disable them with `applyHostStyles={false}` or `autoResize={false}` when your application needs to manage them. See the [API reference](https://toolgrain.mintlify.site/mcp-apps/reference.md) for the complete provider options and state contracts.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.