Preserve MCP App UI metadata in tool-call events and history (#45805)

## Why

Clients need widget presentation details to render MCP Apps without waiting for the full MCP catalog, including when replaying saved history.

## What changed

- Add `mcpToolCall.mcpAppUi` with the invoked descriptor's `resourceUri` and `preferredModelDisplayMode`, and carry it through tool-call events and saved history.
- Support `fullscreen` and default to `inline` when the display preference is missing or unsupported.
- Keep existing resource URI fields for compatibility. Leave `mcpAppUi` null for older history and tools that declare widgets only in result metadata, where clients still use catalog discovery.
- Update protocol schemas, TypeScript and Python types, and app-server documentation.

## Testing

Add parameterized integration coverage for fullscreen, missing and unsupported preferences, legacy URI metadata, and result-only widgets, verifying consistent tool events and preservation across session resume.

GitOrigin-RevId: 2a9bed804dcea8c2b4903b8406fa6710681f7f5e
This commit is contained in:
victor-openai
2026-09-15 22:52:56 +00:00
committed by copyberry
parent 872fc22f9c
commit b71af39fe6
51 changed files with 1027 additions and 47 deletions
@@ -2461,6 +2461,21 @@ class MarketplaceUpgradeResponse(BaseModel):
upgraded_roots: Annotated[list[AbsolutePathBuf], Field(alias="upgradedRoots")]
class McpAppDisplayMode(Enum):
inline = "inline"
fullscreen = "fullscreen"
class McpAppUi(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
preferred_model_display_mode: Annotated[
McpAppDisplayMode, Field(alias="preferredModelDisplayMode")
]
resource_uri: Annotated[str, Field(alias="resourceUri")]
class McpAuthStatus(Enum):
unknown = "unknown"
unsupported = "unsupported"
@@ -5303,7 +5318,14 @@ class McpToolCallThreadItem(BaseModel):
str | None,
Field(
alias="mcpAppResourceUri",
description="Deprecated: use `appContext.resourceUri` instead.",
description="Legacy compatibility field; prefer `mcpAppUi.resourceUri` when available.",
),
] = None
mcp_app_ui: Annotated[
McpAppUi | None,
Field(
alias="mcpAppUi",
description="Presentation captured from the invoked descriptor; absent in older history.",
),
] = None
plugin_id: Annotated[str | None, Field(alias="pluginId")] = None