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
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, exportuseToolCall alongside your existing bindings:
src/mcp.ts
src/App.tsx, import useToolCall from ./mcp.ts. Replace the Weather component with this version; keep it inside the provider:
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:
Read host context when needed
The provider already applies host fonts and theme variables. CSS such asvar(--color-text-primary, #1f2937) is enough for the basic widget.
Export useHostContext from src/mcp.ts when you need host information in React logic:
locale ?? "en". Use host actions 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 for an example.
Provider lifecycle
Use one provider per widget window. PassappInfo and either tool for a separate entry or resolveTool for a shared entry. 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 for the complete provider options and state contracts.