useModelContext sends content blocks to the model through the MCP Apps ui/update-model-context request. Each update replaces what the hook sent before. On hosts other than ChatGPT, Skybridge sends it together with the useViewState state, so an update from one doesn’t drop the other.
ChatGPT goes further through the OpenAI MCP extensions: it shows each block as a composer attachment the user can remove, and reports the attached context back as context. Other hosts ignore that metadata and just pass the content to the model.
Example
A product view attaches the selected variant with a title and a thumbnail.Returns
supported
hostCapabilities.updateModelContext or the OpenAI experimental["openai/modelContext"]. false before the handshake.
context
null once the user removes it from the composer, and stays undefined when the host never reported one.
update
updateId ChatGPT assigns to it, to compare with context.updateId. Other hosts resolve with undefined. Rejects with a NotSupportedError on hosts that don’t advertise model context updates. On hosts other than ChatGPT, the view state is sent alongside: its JSON goes first in content, addressed to the model only, and its keys win over yours in structuredContent, with a console warning naming the shared keys. The host may reject block types it doesn’t list in hostCapabilities.updateModelContext, such as an image on a text-only host.
ChatGPT reads this presentation metadata on content blocks:
useViewState
Persist view state, also shared with the model
useHost
Check which extensions the host supports