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

# <ModelContext />

> Keep the AI model aware of what the user is currently viewing in your widget

`ModelContext` and `modelContext` let your widget push contextual descriptions to the AI model so it can reason about what the user is currently seeing  -  without requiring an explicit tool call or storing it in developer-managed state.

<Info>
  Both APIs feed into a single hierarchical context string that is sent to the host via `ui/update-model-context` (MCP Apps) or `setWidgetState` (ChatGPT Apps SDK) whenever the node tree changes. Updates are batched automatically.
</Info>

## Import

```typescript theme={null}
import { ModelContext, modelContext } from "mcp-use/react";
```

***

## `<ModelContext>` component

Declarative React component that registers a context annotation for as long as it is mounted. Participates in a parent-child tree based on nesting in JSX.

### Props

| Prop       | Type        | Required | Description                                                                                                                            |
| ---------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `content`  | `string`    | Yes      | The description the model should see.                                                                                                  |
| `children` | `ReactNode` | No       | Optional. If provided, this component becomes a scope boundary  -  any nested `<ModelContext>` components become children in the tree. |

### Basic usage

```tsx theme={null}
import { ModelContext } from "mcp-use/react";

function WeatherCard({ city, temp }: Props) {
  return (
    <>
      {/* Leaf annotation  -  no children needed */}
      <ModelContext content={`Showing weather for ${city}: ${temp}°C`} />
      <div className="card">
        {city}: {temp}°C
      </div>
    </>
  );
}
```

### Nesting

`<ModelContext>` components nest hierarchically. A component wrapped in another's `children` becomes a child node in the serialized tree:

```tsx theme={null}
<ModelContext content="User is on the Dashboard">
  <ModelContext content="Revenue chart is visible" />
  <ModelContext content="5 notifications pending" />
</ModelContext>
```

The model receives:

```
- User is on the Dashboard
  - Revenue chart is visible
  - 5 notifications pending
```

### Siblings

Multiple `<ModelContext>` at the same level in the component tree are siblings  -  they produce a flat list at that depth:

```tsx theme={null}
function Dashboard() {
  return (
    <>
      <ModelContext content="Revenue section" />
      <ModelContext content="Users section" />
    </>
  );
}
// - Revenue section
// - Users section
```

### Dynamic content

The component re-registers automatically when `content` changes. Use this to reflect interactive state:

```tsx theme={null}
const [tab, setTab] = useState("overview");

<ModelContext content={`Active tab: ${tab}`}>
  <TabPanel tab={tab} />
</ModelContext>
```

### Empty children

Children are optional. A self-closing tag registers a leaf annotation:

```tsx theme={null}
<ModelContext content={`Selected: ${item.name}`} />
```

***

## `modelContext` API

Module-level imperative API. Works anywhere  -  event handlers, plain functions, outside React. Entries registered via this API are always root-level nodes (no parent in the tree).

### Methods

| Method                           | Description                                                                                                                                   |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `modelContext.set(key, content)` | Register or update a named context entry. The `key` is a stable identifier  -  calling `set` with the same key overwrites the previous value. |
| `modelContext.remove(key)`       | Remove a previously registered entry by key.                                                                                                  |
| `modelContext.clear()`           | Remove all entries (both component-based and imperative).                                                                                     |

### Usage

```ts theme={null}
import { modelContext } from "mcp-use/react";

function onItemSelect(item: Item) {
  // The model now knows which item the user selected
  modelContext.set("selected-item", `User selected: ${item.name} ($${item.price})`);
}

function onDrawerClose() {
  modelContext.remove("selected-item");
}
```

Use `modelContext.set` from a `useEffect` when you want lifecycle-aware imperative updates:

```tsx theme={null}
useEffect(() => {
  modelContext.set("scroll-position", `User scrolled to item ${visibleIndex}`);
  return () => modelContext.remove("scroll-position");
}, [visibleIndex]);
```

<Note>
  Unlike `<ModelContext>`, entries set via `modelContext.set()` are not automatically cleaned up when a component unmounts. Always call `modelContext.remove(key)` in cleanup logic, or use `<ModelContext>` when you need automatic lifecycle management.
</Note>

***

## How the tree is serialized

All mounted `<ModelContext>` nodes and `modelContext.set()` entries are collected in a global registry. On every change, the tree is serialized into an indented markdown-like string:

```
- Root description
  - Child description
    - Grandchild description
  - Another child
- Standalone imperative entry
```

This string is sent to the host as:

* **MCP Apps**: `ui/update-model-context` with `structuredContent.__model_context`
* **ChatGPT Apps SDK**: `setWidgetState` with `__model_context` merged into the state object

Updates are **batched via `queueMicrotask`**, so rapid mount/unmount cycles within a single render produce a single host notification.

***

## Integration with `useWidget` state

`<ModelContext>` and `setState` from `useWidget` are **independent**. Use them for different purposes:

| API                                     | Purpose                                                                                                                     |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `setState`                              | Explicit developer-managed state (cart items, form values, filters). The developer decides what to include.                 |
| `<ModelContext>` / `modelContext.set()` | Declarative annotations about what the user is *currently seeing*. Set it and forget it  -  the framework handles the rest. |

The `__model_context` key is automatically filtered from the `state` value returned by `useWidget`, so it never appears in your code.

<Tip>
  Use `<ModelContext>` for UI annotations that mirror your JSX structure (which tab is active, which section is visible). Use `modelContext.set()` for annotations triggered by user actions (item selected, modal opened) that don't map cleanly to a rendered component.
</Tip>

***

## Full example

```tsx theme={null}
import { McpUseProvider, ModelContext, modelContext, useWidget } from "mcp-use/react";
import { useState } from "react";

const TABS = ["Overview", "Reviews", "Specs"];

export default function ProductWidget() {
  const { props, isPending } = useWidget<{ name: string; price: number }>();
  const [tab, setTab] = useState("Overview");

  function onAddToCart() {
    modelContext.set("cart-action", `User added ${props.name} to cart`);
    // Clear after a short delay so it doesn't linger
    setTimeout(() => modelContext.remove("cart-action"), 3000);
  }

  if (isPending) return <div>Loading...</div>;

  return (
    <McpUseProvider autoSize>
      {/* Root annotation */}
      <ModelContext content={`Viewing product: ${props.name} ($${props.price})`}>
        {/* Updates when tab changes */}
        <ModelContext content={`Active tab: ${tab}`} />

        <div>
          <h1>{props.name}</h1>
          <p>${props.price}</p>

          <div>
            {TABS.map((t) => (
              <button key={t} onClick={() => setTab(t)}>{t}</button>
            ))}
          </div>

          <button onClick={onAddToCart}>Add to cart</button>
        </div>
      </ModelContext>
    </McpUseProvider>
  );
}
```

***

## Related

* [`useWidget()`](./usewidget)  -  Access widget props and state
* [`<McpUseProvider />`](./mcpuseprovider)  -  Widget root provider
