-
Notifications
You must be signed in to change notification settings - Fork 39
docs: add tool visibility and restructure _meta.ui #131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -241,21 +241,31 @@ Example: | |||||
|
|
||||||
| ### Resource Discovery | ||||||
|
|
||||||
| Tools are associated with UI resources through the `_meta` field: | ||||||
| Tools are associated with UI resources through the `_meta.ui` field: | ||||||
|
|
||||||
| ```typescript | ||||||
| interface McpUiToolMeta { | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add to spec.types.ts too? |
||||||
| /** URI of UI resource for rendering tool results */ | ||||||
| resourceUri?: string; | ||||||
| /** | ||||||
| * Who can access this tool. Default: ["model"] | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * - "model": Tool visible to and callable by the agent | ||||||
| * - "apps": Tool callable by ui apps from this server | ||||||
| */ | ||||||
| visibility?: Array<"model" | "apps">; | ||||||
| } | ||||||
|
|
||||||
| interface Tool { | ||||||
| name: string; | ||||||
| description: string; | ||||||
| inputSchema: object; | ||||||
| _meta?: { | ||||||
| // Required: URI of the UI resource to use for rendering | ||||||
| "ui/resourceUri"?: string; | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we keep this for now (don't need to break everyone) but deprecate it? |
||||||
| ui?: McpUiToolMeta; | ||||||
| }; | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| Example: | ||||||
| Example (tool visible to both model and apps): | ||||||
|
|
||||||
| ```json | ||||||
| { | ||||||
|
|
@@ -268,20 +278,48 @@ Example: | |||||
| } | ||||||
| }, | ||||||
| "_meta": { | ||||||
| "ui/resourceUri": "ui://weather-server/dashboard-template" | ||||||
| "ui": { | ||||||
| "resourceUri": "ui://weather-server/dashboard-template", | ||||||
| "visibility": ["model", "apps"] | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| Example (app-only tool, hidden from model): | ||||||
|
|
||||||
| ```json | ||||||
| { | ||||||
| "name": "refresh_dashboard", | ||||||
| "description": "Refresh dashboard data", | ||||||
| "inputSchema": { "type": "object" }, | ||||||
| "_meta": { | ||||||
| "ui": { | ||||||
| "resourceUri": "ui://weather-server/dashboard-template", | ||||||
| "visibility": ["apps"] | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| #### Behavior: | ||||||
|
|
||||||
| - If `ui/resourceUri` is present and host supports MCP Apps, host renders tool results using the specified UI resource | ||||||
| - If `ui.resourceUri` is present and host supports MCP Apps, host renders tool results using the specified UI resource | ||||||
| - If host does not support MCP Apps, tool behaves as standard tool (text-only fallback) | ||||||
| - Resource MUST exist on the server | ||||||
| - Host MUST use `resources/read` to fetch the referenced resource URI. | ||||||
| - Host MUST use `resources/read` to fetch the referenced resource URI | ||||||
| - Host MAY prefetch and cache UI resource content for performance optimization | ||||||
| - Since UI resources are primarily discovered through tool metadata, Servers MAY omit UI-only resources from `resources/list` and `notifications/resources/list_changed` | ||||||
|
|
||||||
| #### Visibility: | ||||||
|
|
||||||
| - `visibility` defaults to `["model"]` if omitted (standard MCP behavior) | ||||||
| - `"model"`: Tool is visible to and callable by the agent | ||||||
| - `"apps"`: Tool is callable by apps from the same server connection only | ||||||
| - Host MUST NOT include tools with `visibility: ["apps"]` in the agent's tool list | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| - Host MUST reject `tools/call` requests from apps for tools that don't include `"apps"` in visibility | ||||||
| - Cross-server tool calls are always blocked for app-only tools | ||||||
|
|
||||||
| #### Benefits: | ||||||
|
|
||||||
| - **Performance:** Host can preload templates before tool execution | ||||||
|
|
@@ -702,7 +740,7 @@ sequenceDiagram | |||||
|
|
||||||
| autonumber | ||||||
| S -->> H: resources/list (includes ui:// resources) | ||||||
| S -->> H: tools/list (includes tools with ui/resourceUri metadata) | ||||||
| S -->> H: tools/list (includes tools with _meta.ui metadata) | ||||||
| ``` | ||||||
|
|
||||||
| #### 2. UI Initialization (Desktop/Native Hosts) | ||||||
|
|
@@ -716,7 +754,7 @@ sequenceDiagram | |||||
|
|
||||||
| autonumber | ||||||
| par UI Tool call | ||||||
| H ->> S: tools/call to Tool with ui/resourceUri metadata | ||||||
| H ->> S: tools/call to Tool with _meta.ui metadata | ||||||
| and UI initialization | ||||||
| alt Desktop/Native hosts | ||||||
| H ->> H: Render Guest UI in an iframe (HTML from the ui:// resource) | ||||||
|
|
@@ -902,7 +940,7 @@ await client.callTool("get_weather", { location: "New York" }); | |||||
|
|
||||||
| This pattern enables interactive, self-updating widgets. | ||||||
|
|
||||||
| Note: The called tool may not appear in `tools/list` responses. MCP servers MAY expose private tools specifically designed for UI interaction that are not visible to the agent. UI implementations SHOULD attempt to call tools by name regardless of discoverability. The specification for Private Tools will be covered in a future SEP. | ||||||
| Note: Tools with `visibility: ["apps"]` are hidden from the agent but remain callable by apps via `tools/call`. This enables UI-only interactions (refresh buttons, form submissions) without exposing implementation details to the model. See the Visibility section under Resource Discovery for details. | ||||||
|
|
||||||
| ### Client\<\>Server Capability Negotiation | ||||||
|
|
||||||
|
|
@@ -955,7 +993,7 @@ if (hasUISupport) { | |||||
| description: "Get weather with interactive dashboard", | ||||||
| inputSchema: { /* ... */ }, | ||||||
| _meta: { | ||||||
| "ui/resourceUri": "ui://weather-server/dashboard" | ||||||
| ui: { resourceUri: "ui://weather-server/dashboard" } | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a breaking change. Let's deprecate it and give consumers some time to adapt. We should remove it before GA. |
||||||
| } | ||||||
| }); | ||||||
| } else { | ||||||
|
|
@@ -1046,6 +1084,24 @@ This proposal synthesizes feedback from the UI CWG and MCP-UI community, host im | |||||
| - **Include external URLs in MVP:** This is one of the easiest content types for servers to adopt, as it's possible to embed regular apps. However, it was deferred due to concerns around model visibility, inability to screenshot content, and review process. | ||||||
| - **Support multiple content types:** Deferred to maintain a lean MVP. | ||||||
|
|
||||||
| #### 4. Tool Visibility via Metadata | ||||||
|
|
||||||
| **Decision:** Use `_meta.ui.visibility` array to control tool accessibility between model and apps. | ||||||
|
|
||||||
| **Rationale:** | ||||||
|
|
||||||
| - Nested `_meta.ui` structure groups all UI-related metadata cleanly | ||||||
| - Array format (`["model", "apps"]`) allows flexible combinations | ||||||
| - Default `["model"]` preserves standard MCP behavior for existing tools | ||||||
| - `"apps"` scope is per-server, preventing cross-server tool calls | ||||||
| - Cleaner than OpenAI's two-field approach (`widgetAccessible` + `visibility`) | ||||||
|
|
||||||
| **Alternatives considered:** | ||||||
|
|
||||||
| - **Two separate fields:** OpenAI uses `widgetAccessible` and `visibility` separately. Rejected as redundant; single `visibility` array covers all cases. | ||||||
| - **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. | ||||||
|
|
||||||
| ### Backward Compatibility | ||||||
|
|
||||||
| The proposal builds on the existing core protocol. There are no incompatibilities. | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also add a blurb about tools/list and tools/call, to say the former will skip tools that don't have "apps", and the latter will error when attempting to call such a tool anyway.