Skip to content

feat: add ui/update-model-context - #125

Merged
ochafik merged 15 commits into
mainfrom
feat/update-context
Jan 12, 2026
Merged

feat: add ui/update-model-context#125
ochafik merged 15 commits into
mainfrom
feat/update-context

Conversation

@idosal

@idosalidosal commented Dec 10, 2025

Copy link
Copy Markdown
Contributor

This new message allows the UI to update the Host's model context without triggering a follow-up action.

`ui/update-model-context` - Update the Host's model context
// Request
{
jsonrpc: "2.0",
id: 3,
method: "ui/update-model-context",
params: {
role: "user",
content: ContentBlock[]
}
}
Guest UI MAY send this request to inform the agent about app state changes that should be added to the model's context for future reasoning. This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger followups).
Host behavior:
- SHOULD provide the context to the model in future turns
- SHOULD overwrite the previous model context with the new update
- MAY display context updates to the user

notifications/message remains another message type with MCP's original intent.

Addresses #61.

Note: the params's type (content: ContentBlock[]) may be problematic for the MVP. It's subject to the same decision as #119 (comment)

CopilotAI review requested due to automatic review settings December 10, 2025 17:49
@pkg-pr-new

pkg-pr-newBot commented Dec 10, 2025

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@125

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-react@125

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-vanillajs@125

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-budget-allocator@125

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-cohort-heatmap@125

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-customer-segmentation@125

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-scenario-modeler@125

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-system-monitor@125

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-threejs@125

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-wiki-explorer@125

commit: d8156f9

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the ui/update-context request to allow Guest UI applications to inform the host agent about app state changes that should be stored in the conversation context for future reasoning, without triggering follow-up actions. This addresses the need to distinguish between logging messages (notifications/message), interactive messages that expect follow-ups (ui/message), and context updates that inform the agent's reasoning.

Key changes:

  • Added ui/update-context request type with role and ContentBlock[] parameters
  • Extended host capabilities to include optional context capability for negotiation
  • Implemented sendContext() method in App class and oncontext handler in AppBridge class

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/types.tsRe-exports new McpUiUpdateContextRequest/Result types and schemas
src/spec.types.tsDefines TypeScript interfaces for update-context request/result and adds context capability to McpUiHostCapabilities
src/generated/schema.tsAdds Zod schemas for validating update-context requests and results
src/generated/schema.test.tsAdds type inference tests to verify schema/type compatibility
src/generated/schema.jsonContains JSON schema definitions for update-context with full ContentBlock support
src/app.tsImplements sendContext() method for Guest UI to send context updates to host
src/app-bridge.tsImplements oncontext handler for Host to receive context updates from Guest UI
src/app-bridge.test.tsAdds integration tests covering basic sendContext functionality with single and multiple content blocks
specification/draft/apps.mdxDocuments ui/update-context in the protocol specification with examples and host behavior guidelines

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/app-bridge.ts Outdated
Comment threadsrc/app-bridge.test.ts Outdated
Comment threadsrc/app-bridge.ts Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 9 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/spec.types.ts Outdated
Comment threadsrc/app.ts Outdated
Comment threadsrc/app.ts Outdated
Comment threadsrc/app-bridge.ts Outdated
Comment threadsrc/app.ts Outdated
Comment threadspecification/draft/apps.mdx Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/app-bridge.ts Outdated
liady
liady previously approved these changes Dec 11, 2025

@ochafikochafik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something to discuss: I wonder if we want to go full multimedia on this one.
Also, in OAI Apps SDK the updates are essentially structuredContent, and text might also often be the most useful kind of update, so both would place us in the territory of Pick<CallToolResult, 'content' | 'structuredContent' | 'isError'> more than a message content block array

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably also need to mention that the host MAY defer sending the context to the model, and it MAY dedupe identical ui/update-context calls.

Potentially we could add a boolean that says it replaces / purges any previously pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. How about SHOULD provide the context to the model in future turns?
  2. We always replace now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And should this be ui/update-semantic-state?

@idosalidosalDec 18, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think semantic-state isn't as self-documenting as model-context

@antonpk1antonpk1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the proposal! I think we should design the state that only the last 'context-update' is used, and all past context updates are disregarded.

Here's a specific example: imagine a text-editor app. The user can write and edit text and wants to be able to ask the agent to help/reflect/act on the current text state.

Problem with the current proposal: if we send a 'context-update' with full text on every character change, it will quickly pollute the entire context window and won't work well.

At the same time, if an app wants to share context with a chronological history of events like in current proposal, nothing prevents them from accumulating an array and passing that as a 'context-update'.

@idosal

idosal commented Dec 18, 2025

Copy link
Copy Markdown
ContributorAuthor

Thanks for the proposal! I think we should design the state that only the last 'context-update' is used, and all past context updates are disregarded.

Here's a specific example: imagine a text-editor app. The user can write and edit text and wants to be able to ask the agent to help/reflect/act on the current text state.

Problem with the current proposal: if we send a 'context-update' with full text on every character change, it will quickly pollute the entire context window and won't work well.

At the same time, if an app wants to share context with a chronological history of events like in current proposal, nothing prevents them from accumulating an array and passing that as a 'context-update'.

After further discussions, for the MVP, we propose clarifying that ui/update-model-context will overwrite the previous state. In the future, following community feedback and requirements, we can extend it to enable maintaining history and other enhancements.

@idosal
idosal requested a review from antonpk1December 18, 2025 22:49
@idosal
idosal requested a review from ochafikDecember 18, 2025 22:50
@idosal

Copy link
Copy Markdown
ContributorAuthor

Something to discuss: I wonder if we want to go full multimedia on this one. Also, in OAI Apps SDK the updates are essentially structuredContent, and text might also often be the most useful kind of update, so both would place us in the territory of Pick<CallToolResult, 'content' | 'structuredContent' | 'isError'> more than a message content block array

I think this is the last open item. I can see value in pushing non-textual information (like images) into context. Thoughts?

@idosalidosal changed the title feat: add ui/update-contextfeat: add ui/update-model-contextDec 18, 2025
@idosalidosal mentioned this pull request Dec 23, 2025
9 tasks
@antonpk1

Copy link
Copy Markdown
Contributor

Thanks for this, the overall design is great! The ui/update-model-context name and behavior (overwrite semantics, no follow-up trigger) looks solid.

Two suggestions:

  1. Method naming: Could we rename sendUpdateModelContext to just updateModelContext? This would be consistent with other API methods where we avoid using two verbs at the beginning (e.g., we have openLink()).

  2. Params type: The role: "user" field doesn't add much value here - it's always "user" and the concept of "role" doesn't quite fit this use case (we're updating context, not sending a message). As @ochafik suggested, we could use something like Pick<CallToolResult, 'content' | 'structuredContent' | 'isError'> instead for consistency with tool call results.

lmk what you think!

@idosal

Copy link
Copy Markdown
ContributorAuthor

Thanks for this, the overall design is great! The ui/update-model-context name and behavior (overwrite semantics, no follow-up trigger) looks solid.

Two suggestions:

  1. Method naming: Could we rename sendUpdateModelContext to just updateModelContext? This would be consistent with other API methods where we avoid using two verbs at the beginning (e.g., we have openLink()).
  2. Params type: The role: "user" field doesn't add much value here - it's always "user" and the concept of "role" doesn't quite fit this use case (we're updating context, not sending a message). As @ochafik suggested, we could use something like Pick<CallToolResult, 'content' | 'structuredContent' | 'isError'> instead for consistency with tool call results.

lmk what you think!

Thanks @antonpk1 ! Makes sense. I'll update the PR tomorrow so we can merge.

@antonpk1

Copy link
Copy Markdown
Contributor

Thanks @antonpk1 ! Makes sense. I'll update the PR tomorrow so we can merge.

thank you, Ido! looking forward to it

@ochafikochafik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @idosal, sorry for the delay!

Comment threadsrc/app.ts Outdated
*
* @returns Promise that resolves when the context update is acknowledged
*/
sendUpdateModelContext(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateModelContext

the current pattern is to avoid double verbs (w/ exception of sendMessage as message is ambiguous)

Comment threadsrc/spec.types.ts Outdated
* @description Result from setting the agent's model context.
* @see {@link McpUiUpdateModelContextRequest}
*/
export interface McpUiUpdateModelContextResult {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably can just rely on the request erroring (i.e. use EmptyResult for this one)

Comment threadsrc/spec.types.ts Outdated
method: "ui/update-model-context";
params: {
/** @description Message role, currently only "user" is supported. */
role: "user";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the role? (In OAI land, their role would be tool anyway; the real role here is kinda app)

Comment threadsrc/spec.types.ts Outdated
/** @description Message role, currently only "user" is supported. */
role: "user";
/** @description Context content blocks (text, image, etc.). */
content: ContentBlock[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add structuredContent?

Comment threadsrc/spec.types.ts Outdated
/** @description Host accepts log messages. */
logging?: {};
/** @description Host accepts context updates to be included in the model's context for future turns. */
updateModelContext?: {};

@ochafikochafikJan 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
updateModelContext?: {};
updateModelContext?: {
text?: {};
image?: {};
audio?: {};
resource?: {};
resourceLink?: {};
structuredContent?: {};
};

- Rename sendUpdateModelContext → updateModelContext (avoid double verbs)
- Remove role field from params (always user, adds no value)
- Add structuredContent support for machine-readable context data
- Use EmptyResult instead of {isError?: boolean} for result type
- Errors now signaled via JSON-RPC error responses
- Update capability to specify supported content types:
text, image, audio, resource, resourceLink, structuredContent
- Add spec guidance for deferred delivery semantics:
- Host MAY defer until next user message
- Host MAY dedupe identical updates
- Only last update before user message is sent to model
- Create reusable McpUiSupportedContentBlockModalities interface
- Use it for both updateModelContext and message capabilities
- Add message capability to advertise ui/message content type support
Gives hosts flexibility to accumulate context history if desired,
rather than mandating replacement semantics.
@ochafik

Copy link
Copy Markdown
Contributor

@idosal I pushed some commits implementing the review feedback. Here's a suggested updated PR description:


This new message allows the UI to update the Host's model context without triggering a follow-up action.

// Request{jsonrpc: "2.0",id: 3,method: "ui/update-model-context",params: {content?: ContentBlock[],structuredContent?: Record<string,unknown>}}

Guest UI MAY send this request to inform the agent about app state changes that should be added to the model's context for future reasoning. Each request overwrites the previous context. This differs from notifications/message (logging) and ui/message (which triggers follow-ups).

Host behavior:

  • SHOULD provide the context to the model in future turns
  • MAY overwrite the previous model context with the new update
  • MAY defer sending until the next user message (including ui/message)
  • MAY dedupe identical calls; only last update before user message is sent
  • MAY display context updates to the user

notifications/message remains another message type with MCP's original intent.

Addresses #61.


Summary of changes from review feedback:

  • Removed role field (always "user", added no value)
  • Added structuredContent for machine-readable context data
  • Made both fields optional
  • Renamed method: sendUpdateModelContextupdateModelContext
  • Empty result {}; errors via JSON-RPC error responses
  • Extracted McpUiSupportedContentBlockModalities for capability negotiation
  • Added message capability to McpUiHostCapabilities for symmetry

antonpk1
antonpk1 previously approved these changes Jan 12, 2026

@antonpk1antonpk1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very cool!

# Conflicts:
#	src/generated/schema.json
#	src/generated/schema.test.ts
#	src/generated/schema.ts
#	src/spec.types.ts
@ochafik
ochafik merged commit b273279 into mainJan 12, 2026
18 checks passed
@ochafikochafik mentioned this pull request Jan 12, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@idosal@antonpk1@ochafik@liady