Skip to main content
useCallTool is a React hook for calling MCP tools from inside a widget. It manages the call with a discriminated union state machine (idle, pending, success, error) similar to TanStack Query, and exposes two ways to invoke the tool: callTool (fire-and-forget with optional side effect callbacks) and callToolAsync (returns a Promise). Types are inferred automatically from the tool name when running mcp-use dev, which generates ToolRegistry augmentations in .mcp-use/tool-registry.d.ts. For setups without the dev server, use generateHelpers() to bind the hook to an explicit tool map.
useCallTool runs only in a browser environment. Calling it outside the browser (for example, during server-side rendering) throws Error("useCallTool can only be used in browser environment").

useCallTool

Call an MCP tool and track its lifecycle with idle, pending, success, and error states.
import { useCallTool } from "mcp-use/react";
Hook for calling MCP tools with TanStack Query-like state management. The hook is declared with two overloads. The first is type-safe and resolves input and output types from the augmented ToolRegistry based on the tool name. The second is a fallback that lets you supply explicit generics when a tool is not in the registry. The runtime detects the protocol automatically: in MCP Apps clients it uses JSON-RPC over postMessage, and in the ChatGPT Apps SDK it uses window.openai.callTool(). Your code is identical in both cases. When name is a key of ToolRegistry, input arguments and the response structuredContent are fully typed from your server’s tool definition. The hook tracks the latest call with an internal counter, so if you fire a new call before a previous one resolves, only the most recent call updates state (responses from stale calls are ignored).
import { useCallTool } from "mcp-use/react";
Type Parameters (overload 1)
TName
keyof ToolRegistry
required
The tool name. Constrained to the keys of the augmented ToolRegistry, which gives autocomplete for available tool names.
Type Parameters (overload 2)
TArgs
UnknownObject | null
default:"null"
The shape of the tool input arguments. Use null when the tool takes no arguments.
TResponse
Partial<CallToolResponse>
default:"CallToolResponse"
The shape of the tool response.
Parameters
name
TName | string
required
The name of the tool to call. Auto-typed from ToolRegistry in the first overload, or a plain string in the fallback overload.
Returns
returns
UseCallToolReturn<TArgs, TResponse>
The current call state spread with the callTool and callToolAsync methods. See UseCallToolReturn.
Signature
// Overload 1: type-safe with ToolRegistry
export function useCallTool<TName extends keyof ToolRegistry>(name: TName): UseCallToolReturn<ResolveInput<TName>, ResolveOutput<TName>>;
// Overload 2: fallback with explicit generics
export function useCallTool<TArgs extends UnknownObject | null = null, TResponse extends Partial<CallToolResponse> = CallToolResponse>(name: string): UseCallToolReturn<TArgs, TResponse>;

Returns

The hook returns the current CallToolState spread together with two methods. Every field below is present on the returned object.

status

The current lifecycle state of the tool call. Returns
status
"idle" | "pending" | "success" | "error"
"idle" before any call, "pending" while a call is in flight, "success" after the latest call resolves, and "error" after the latest call rejects.

isIdle

Convenience boolean flag for the idle state. Returns
isIdle
boolean
true when status === "idle" (no call has been made yet).

isPending

Convenience boolean flag for the pending state. Returns
isPending
boolean
true when status === "pending" (a call is currently executing).

isSuccess

Convenience boolean flag for the success state. Returns
isSuccess
boolean
true when status === "success". When true, data is defined and error is undefined.

isError

Convenience boolean flag for the error state. Returns
isError
boolean
true when status === "error". When true, error is defined and data is undefined.

data

The tool result, available only after a successful call. Returns
data
TResponse | undefined
The normalized response. undefined in every state except success. For registry-typed tools this is CallToolResponse with a typed structuredContent. See CallToolResponse.

error

The error thrown by the tool call, available only after a failed call. Returns
error
unknown | undefined
The thrown error. undefined in every state except error. Typed as unknown because any value can be thrown.

callTool

Fire-and-forget invocation with optional side effect callbacks. callTool starts the tool call and returns void immediately. State (isPending, data, error, and so on) updates as the call progresses. You can pass a SideEffects object to react to the result. When the tool input is optional (for example null input or all-optional fields), you may omit args entirely or pass only the side effects object as the first argument; the hook detects a side effects object by the presence of an onSuccess, onError, or onSettled key. Type
callTool: CallToolFn<TArgs, TResponse>
See CallToolFn for the full set of call signatures.

callToolAsync

Promise-based invocation for sequential or try/catch flows. callToolAsync starts the tool call and returns a Promise that resolves with the response or rejects with the thrown error. State flags update the same way as callTool. When the tool input is optional, you may call it with no arguments. Use this method to chain tool calls or to handle the result with await inside a try/catch block. Type
callToolAsync: CallToolAsyncFn<TArgs, TResponse>
See CallToolAsyncFn for the full set of call signatures.

generateHelpers

Generate fully-typed hook helpers from an explicit tool map. This is an alternative to the automatic ToolRegistry approach. When using mcp-use dev, types are auto-generated in .mcp-use/tool-registry.d.ts and useCallTool is typed without this factory. Use generateHelpers for advanced cases: running without mcp-use dev (for example a custom build setup), scoping types to a subset of tools, or using different tool maps in different parts of your app. It returns an object containing a typed useCallTool and a typed useToolInfo hook, both bound to the supplied TMap.
import { generateHelpers } from "mcp-use/react";
Type Parameters
TMap
ToolMap
required
The tool map defining all tools and their input/output types. See ToolMap.
Returns
useCallTool
TypedUseCallTool<TMap>
A useCallTool hook whose name argument is constrained to the keys of TMap, with input and output inferred from the map. See TypedUseCallTool.
useToolInfo
TypedUseToolInfo<TMap>
A useToolInfo hook that returns the current widget state typed against TMap. See TypedUseToolInfo.
Signature
export function generateHelpers<TMap extends ToolMap>(): { useCallTool: TypedUseCallTool<TMap>; useToolInfo: <TName extends keyof TMap & string>() => UseWidgetResult<WidgetInputType<ToolInput<TMap, TName>>, UnknownObject, ToolOutput<TMap, TName>, UnknownObject, WidgetInputType<ToolInput<TMap, TName>>> };

Types

CallToolState

The discriminated union that models the four lifecycle states of a tool call. Each variant fixes the boolean flags and the presence of data and error, so narrowing on status (or on any flag) gives type-safe access to data and error. The success variant is the only one where data is present, and the error variant is the only one where error is present.
import type { CallToolState } from "mcp-use/react";
Type Parameters
TData
any
required
The type of data in the success variant.
Signature
export type CallToolState<TData> =
  | { status: "idle"; isIdle: true; isPending: false; isSuccess: false; isError: false; data: undefined; error: undefined }
  | { status: "pending"; isIdle: false; isPending: true; isSuccess: false; isError: false; data: undefined; error: undefined }
  | { status: "success"; isIdle: false; isPending: false; isSuccess: true; isError: false; data: TData; error: undefined }
  | { status: "error"; isIdle: false; isPending: false; isSuccess: false; isError: true; data: undefined; error: unknown };

SideEffects

Optional callbacks passed to callTool, modeled after TanStack Query mutation callbacks. All three callbacks are optional. onSuccess runs when the call resolves, onError runs when it rejects, and onSettled runs after either outcome. Each callback receives the original args that were passed to the call. In onSettled, exactly one of data or error is defined depending on the outcome.
import type { SideEffects } from "mcp-use/react";
Type Parameters
TArgs
TArgs
required
The type of the tool input arguments passed back to each callback.
TResponse
TResponse
required
The type of the successful response.
Signature
export type SideEffects<TArgs, TResponse> = {
  onSuccess?: (data: TResponse, args: TArgs) => void;
  onError?: (error: unknown, args: TArgs) => void;
  onSettled?: (data: TResponse | undefined, error: unknown | undefined, args: TArgs) => void;
};

CallToolFn

The call signature of callTool, the fire-and-forget method. Returns void. The signature adapts to whether the tool input is optional. When the input type is optional (it is null, or all of its keys are optional), you can call with no arguments, with only a SideEffects object, with only args, or with both. When the input is required, you must pass args, optionally followed by a SideEffects object.
import type { CallToolFn } from "mcp-use/react";
Type Parameters
TArgs
TArgs
required
The tool input type. Whether it is optional determines which overloads are available.
TResponse
TResponse
required
The successful response type passed to the callbacks.
Signature
export type CallToolFn<TArgs, TResponse> = IsArgsOptional<TArgs> extends true
  ? {
      (): void;
      (sideEffects: SideEffects<TArgs, TResponse>): void;
      (args: TArgs): void;
      (args: TArgs, sideEffects: SideEffects<TArgs, TResponse>): void;
    }
  : {
      (args: TArgs): void;
      (args: TArgs, sideEffects: SideEffects<TArgs, TResponse>): void;
    };

CallToolAsyncFn

The call signature of callToolAsync, the Promise-based method. Like CallToolFn, it adapts to whether the input is optional. When the input is optional, you can call with no arguments or with args; both return Promise<TResponse>. When the input is required, you must pass args.
import type { CallToolAsyncFn } from "mcp-use/react";
Type Parameters
TArgs
TArgs
required
The tool input type. Whether it is optional determines which overloads are available.
TResponse
TResponse
required
The type the returned Promise resolves with.
Signature
export type CallToolAsyncFn<TArgs, TResponse> = IsArgsOptional<TArgs> extends true
  ? {
      (): Promise<TResponse>;
      (args: TArgs): Promise<TResponse>;
    }
  : (args: TArgs) => Promise<TResponse>;

UseCallToolReturn

The full return type of useCallTool. Intersects the current CallToolState with the two call methods.
import type { UseCallToolReturn } from "mcp-use/react";
Type Parameters
TArgs
TArgs
required
The tool input type.
TResponse
TResponse
required
The successful response type.
Signature
export type UseCallToolReturn<TArgs, TResponse> = CallToolState<TResponse> & {
  callTool: CallToolFn<TArgs, TResponse>;
  callToolAsync: CallToolAsyncFn<TArgs, TResponse>;
};

ToolMap

The structure of a tool map passed to generateHelpers. Maps each tool name to its input and optional output types. Each entry has a required input (an object type, or null when the tool takes no arguments) and an optional output object type. When output is omitted, the tool’s response is the bare CallToolResponse without typed structuredContent.
import type { ToolMap } from "mcp-use/react";
Signature
export type ToolMap = Record<string, {
  input: UnknownObject | null;
  output?: UnknownObject;
}>;

ToolInput

Extracts the input type for a given tool name from a ToolMap.
import type { ToolInput } from "mcp-use/react";
Type Parameters
TMap
ToolMap
required
The tool map to read from.
TName
keyof TMap
required
The tool name whose input type to extract.
Signature
export type ToolInput<TMap extends ToolMap, TName extends keyof TMap> = TMap[TName]["input"];

ToolOutput

Extracts the output type for a given tool name from a ToolMap, combined with CallToolResponse. When the map entry declares an output object, the result is CallToolResponse intersected with { structuredContent: <output> }. When output is absent, it intersects with Record<string, never>, leaving structuredContent untyped.
import type { ToolOutput } from "mcp-use/react";
Type Parameters
TMap
ToolMap
required
The tool map to read from.
TName
keyof TMap
required
The tool name whose output type to extract.
Signature
export type ToolOutput<TMap extends ToolMap, TName extends keyof TMap> =
  CallToolResponse & (TMap[TName]["output"] extends UnknownObject
    ? { structuredContent: TMap[TName]["output"] }
    : Record<string, never>);

TypedUseCallTool

The type of the useCallTool hook returned by generateHelpers. A useCallTool bound to a specific ToolMap, so name is constrained to that map’s keys and input/output are inferred from it.
import type { TypedUseCallTool } from "mcp-use/react";
Type Parameters
TMap
ToolMap
required
The tool map the hook is bound to.
Signature
export type TypedUseCallTool<TMap extends ToolMap> = <TName extends keyof TMap & string>(name: TName) => UseCallToolReturn<ToolInput<TMap, TName>, ToolOutput<TMap, TName>>;

TypedUseToolInfo

The type of the useToolInfo hook returned by generateHelpers. A useToolInfo bound to a specific ToolMap that returns the current widget state (a UseWidgetResult) typed against the map. null input types are widened to UnknownObject for compatibility with useWidget.
import type { TypedUseToolInfo } from "mcp-use/react";
Type Parameters
TMap
ToolMap
required
The tool map the hook is bound to.
Signature
export type TypedUseToolInfo<TMap extends ToolMap> = <TName extends keyof TMap & string>() => UseWidgetResult<
  WidgetInputType<ToolInput<TMap, TName>>,
  UnknownObject,
  ToolOutput<TMap, TName>,
  UnknownObject,
  WidgetInputType<ToolInput<TMap, TName>>
>;

InferToolMapFromSchemas

Helper type that builds a ToolMap from Zod schemas, so you do not have to hand-write input and output object types. Pass a record mapping tool names to objects with an optional schema and outputSchema. The helper reads the inferred input from the schema (_input, falling back to _type) and the inferred output from the output schema (_output, falling back to _type). When a schema is missing, input resolves to null; when an output schema is missing, output resolves to undefined.
import type { InferToolMapFromSchemas } from "mcp-use/react";
Type Parameters
T
Record<string, { schema?: any; outputSchema?: any }>
required
A record mapping tool names to their Zod input and output schemas.
Signature
export type InferToolMapFromSchemas<T extends Record<string, { schema?: any; outputSchema?: any }>> = {
  [K in keyof T]: {
    input: T[K]["schema"] extends { _input: infer I } ? I : T[K]["schema"] extends { _type: infer I } ? I : null;
    output: T[K]["outputSchema"] extends { _output: infer O } ? O : T[K]["outputSchema"] extends { _type: infer O } ? O : undefined;
  };
};

Response Structure

Successful calls resolve with a normalized CallToolResponse. The hook’s data field (and the data argument of the success callbacks) has this shape. For registry-typed or tool-map-typed tools, structuredContent is narrowed to your tool’s output type.

CallToolResponse

The normalized response returned by a tool call. result is a convenience field containing the text content blocks joined into a single string. structuredContent holds the tool’s structured output when it returned any. isError is set by the protocol when the tool reported an error result. Signature
export type CallToolResponse = {
  content: Array<{ type: string; text?: string; [key: string]: any }>;
  structuredContent?: Record<string, unknown>;
  isError?: boolean;
  result: string; // text content joined as a convenience
  _meta?: Record<string, unknown>;
};

Examples

Basic usage

The tool name is type-checked, and input and output are typed from the registry when running mcp-use dev.
import { useCallTool } from "mcp-use/react";

const MyWidget = () => {
  const { callTool, data, isPending, isSuccess, isError, error } =
    useCallTool("search-flights");

  return (
    <div>
      <button onClick={() => callTool({ destination: "NYC" })}>
        Search Flights
      </button>
      {isPending && <p>Searching...</p>}
      {isSuccess && (
        <ul>
          {data.structuredContent.flights.map((flight) => (
            <li key={flight.id}>{flight.price}</li>
          ))}
        </ul>
      )}
      {isError && <p>Error: {String(error)}</p>}
    </div>
  );
};

Fire-and-forget with callbacks

Use callTool for non-blocking calls. The callbacks receive the original args, so you can read them back in any of the three handlers.
const { callTool } = useCallTool("create-booking");

callTool(
  { flightId: "123", passenger: "John Doe" },
  {
    onSuccess: (data, args) => {
      console.log("Booking confirmed:", data.structuredContent, args);
    },
    onError: (error, args) => {
      console.error("Booking failed:", error, args);
    },
    onSettled: (data, error, args) => {
      console.log("Request complete", { data, error, args });
    },
  }
);

Async/await

Use callToolAsync to chain calls or handle results in a try/catch block. The Promise resolves with the response or rejects with the thrown error.
const { callToolAsync } = useCallTool("search-flights");

const handleSearch = async () => {
  try {
    const result = await callToolAsync({
      destination: "Tokyo",
      date: "2024-12-01",
    });
    setFlights(result.structuredContent.flights);
  } catch (error) {
    console.error("Search failed:", error);
  }
};

Explicit generics (escape hatch)

When a tool is not in the registry, supply input and response types directly with the fallback overload.
const { callTool } = useCallTool<{ query: string }, { results: string[] }>(
  "custom-tool"
);

Manual typing with generateHelpers

For setups without mcp-use dev, bind the hooks to an explicit tool map.
import { generateHelpers } from "mcp-use/react";

type MyToolMap = {
  "search-flights": {
    input: { destination: string; date?: string };
    output: { flights: Array<{ id: string; price: number }> };
  };
  "book-flight": {
    input: { flightId: string };
    output: { confirmation: string };
  };
};

const { useCallTool } = generateHelpers<MyToolMap>();

// useCallTool is now typed against MyToolMap
const { callTool, data } = useCallTool("search-flights");

Server tool definition

The tool names and schemas registered on the server drive the generated types. Define tools with new MCPServer({ ... }) and a Zod schema.
import { MCPServer, widget } from "mcp-use/server";
import { z } from "zod";

const server = new MCPServer({
  name: "mcp-apps-example",
  version: "1.0.0",
});

server.tool(
  {
    name: "get-weather",
    description: "Get current weather for a city",
    schema: z.object({
      city: z.string().describe("City name"),
    }),
    widget: {
      name: "weather-display",
      invoking: "Fetching weather data...",
      invoked: "Weather data loaded",
    },
  },
  async ({ city }) =>
    widget({
      props: { city, temperature: 22, conditions: "Partly Cloudy" },
      message: `Current weather in ${city}`,
    })
);

await server.listen();

See Also