Skip to main content
Use model context to give the next model turn the information it needs without duplicating every value rendered by the view. Tool results establish the initial context; useViewState and ModelContext update it as the user interacts.

Choose the right channel

Keep structured choices in view state

Use useViewState for selections, filters, drafts, and progress that future model turns should understand.
The root state value must be a JSON-serializable object. All components in one mounted view share it. Separate view instances remain isolated. ChatGPT restores the state through window.openai.widgetState. Other MCP Apps hosts keep it for the current iframe lifetime until the protocol provides a restoration channel.

Describe visible UI

Use ModelContext for natural-language descriptions that follow the React component lifecycle.
Nested components serialize into an indented tree:
For annotations produced by event handlers or other callbacks, store the description in React state and render it declaratively:

Understand the merged snapshot

The runtime merges structured state and the serialized context tree into one complete object:
_uiContext is a reserved model-visible field. useViewState filters it from application state and rejects developer state containing the same key. Every write sends the complete snapshot. On MCP Apps hosts, mcp-use sends the object as structuredContent and a JSON text block as content through ui/update-model-context. On ChatGPT, mcp-use writes the object to modelContent with window.openai.setWidgetState.

Keep ephemeral values local

Use React useState for transient details that the model does not need, such as hover state, open tooltips, or animation progress.

Next steps