Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions specification/draft/apps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ interface McpUiToolMeta {
* - "app": Tool callable by the app from this server only
*/
visibility?: Array<"model" | "app">;
/**
* When the host should render the View in the conversation. Default: "inline"
* - "inline": Render the View as soon as the tool returns
* - "end-of-turn": Defer rendering until the agent's turn is complete
*/
renderTiming?: "inline" | "end-of-turn";
}

interface Tool {
Expand Down Expand Up @@ -419,6 +425,32 @@ Example (app-only tool, hidden from model):
- **tools/call behavior:** Host MUST reject `tools/call` requests from apps for tools that don't include `"app"` in visibility
- Cross-server tool calls are always blocked for app-only tools

#### Render Timing:

Some tools produce Views that should only be shown after the agent has finished its turn — for example, an "Apply to Site" action where the user should not interact with the View while the agent is still making additional tool calls. The `renderTiming` field controls this:

- `renderTiming` defaults to `"inline"` if omitted
- `"inline"`: Host SHOULD render the View as soon as the tool returns its result
- `"end-of-turn"`: Host SHOULD defer rendering the View until the agent's turn is complete (no more tool calls or model output expected)
- Host MAY ignore `renderTiming` and render immediately if it does not support deferred rendering
- This field is orthogonal to `displayMode` (inline/fullscreen/pip), which controls the visual layout of the View

Example (tool with deferred rendering):

```json
{
"name": "apply_changes",
"description": "Apply code changes to the user's site",
"inputSchema": { "type": "object" },
"_meta": {
"ui": {
"resourceUri": "ui://editor/apply-to-site",
"renderTiming": "end-of-turn"
}
}
}
```

#### Benefits:

- **Performance:** Host can preload templates before tool execution
Expand Down Expand Up @@ -1754,6 +1786,24 @@ This proposal synthesizes feedback from the UI CWG and MCP-UI community, host im
- **Boolean `private` flag:** Simpler but less flexible; doesn't express model-only tools.
- **Flat `ui/visibility` key:** Rejected in favor of nested structure for consistency with future `_meta.ui` fields.

#### 6. Render Timing via Tool Metadata

**Decision:** Use `_meta.ui.renderTiming` to let servers declare when a View should appear in the conversation.

**Rationale:**

- The server knows best whether its View requires user interaction during or after the agent's turn
- Orthogonal to the visual `displayMode` (inline/fullscreen/pip) — timing and layout are independent concerns
- Optional field with `"inline"` default preserves backward compatibility
- Addresses a real production need: tools like "Apply to Site" should not show interactive UI while the agent is still making additional tool calls
- Simple two-value enum (`"inline"` | `"end-of-turn"`) covers the observed use cases without over-engineering

**Alternatives considered:**

- **Host-side only:** Let hosts decide timing without server input. Rejected because the server has the domain knowledge about whether its View needs deferred rendering.
- **Boolean `deferRendering` flag:** Simpler but less extensible if future timing modes are needed (e.g., `"on-user-action"`).
- **Reuse `displayMode`:** Rejected because `displayMode` controls visual layout (inline/fullscreen/pip), not temporal presentation. Overloading it would create confusion.

### Backward Compatibility

The proposal builds on the existing core protocol. There are no incompatibilities.
Expand Down
27 changes: 27 additions & 0 deletions src/generated/schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/generated/schema.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions src/generated/schema.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions src/spec.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,11 @@ export interface McpUiRequestDisplayModeResult {
*/
export type McpUiToolVisibility = "model" | "app";

/**
* @description When the host should render the View relative to the agent's turn.
*/
export type McpUiRenderTiming = "inline" | "end-of-turn";

/**
* @description UI-related metadata for tools.
*/
Expand All @@ -762,6 +767,12 @@ export interface McpUiToolMeta {
* - "app": Tool callable by the app from this server only
*/
visibility?: McpUiToolVisibility[];
/**
* @description When the host should render the View in the conversation. Default: "inline"
* - "inline": Render the View as soon as the tool returns
* - "end-of-turn": Defer rendering until the agent's turn is complete (no more tool calls)
*/
renderTiming?: McpUiRenderTiming;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export {
type McpUiRequestDisplayModeRequest,
type McpUiRequestDisplayModeResult,
type McpUiToolVisibility,
type McpUiRenderTiming,
type McpUiToolMeta,
type McpUiClientCapabilities,
} from "./spec.types.js";
Expand Down Expand Up @@ -129,6 +130,7 @@ export {
McpUiRequestDisplayModeRequestSchema,
McpUiRequestDisplayModeResultSchema,
McpUiToolVisibilitySchema,
McpUiRenderTimingSchema,
McpUiToolMetaSchema,
} from "./generated/schema.js";

Expand Down