Skip to content

Commit e548370

Browse files
antonpk1claude
andcommitted
docs: add tool visibility and restructure _meta.ui
- Restructure tool metadata: `_meta["ui/resourceUri"]` → `_meta.ui.resourceUri` - Add `visibility` array field: ["model"], ["apps"], or ["model", "apps"] - Default ["model"] preserves standard MCP behavior - ["apps"] enables widget-only tools hidden from agent - Add McpUiToolMeta interface for type safety - Add Design Decision #4 explaining approach vs OpenAI's two-field model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6f14cf3 commit e548370

1 file changed

Lines changed: 67 additions & 11 deletions

File tree

specification/draft/apps.mdx

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,31 @@ Example:
244244

245245
### Resource Discovery
246246

247-
Tools are associated with UI resources through the `_meta` field:
247+
Tools are associated with UI resources through the `_meta.ui` field:
248248

249249
```typescript
250+
interface McpUiToolMeta {
251+
/** URI of UI resource for rendering tool results */
252+
resourceUri?: string;
253+
/**
254+
* Who can access this tool. Default: ["model"]
255+
* - "model": Tool visible to and callable by the agent
256+
* - "apps": Tool callable by ui apps from this server
257+
*/
258+
visibility?: Array<"model" | "apps">;
259+
}
260+
250261
interface Tool {
251262
name: string;
252263
description: string;
253264
inputSchema: object;
254265
_meta?: {
255-
// Required: URI of the UI resource to use for rendering
256-
"ui/resourceUri"?: string;
266+
ui?: McpUiToolMeta;
257267
};
258268
}
259269
```
260270

261-
Example:
271+
Example (tool visible to both model and apps):
262272

263273
```json
264274
{
@@ -271,20 +281,48 @@ Example:
271281
}
272282
},
273283
"_meta": {
274-
"ui/resourceUri": "ui://weather-server/dashboard-template"
284+
"ui": {
285+
"resourceUri": "ui://weather-server/dashboard-template",
286+
"visibility": ["model", "apps"]
287+
}
288+
}
289+
}
290+
```
291+
292+
Example (app-only tool, hidden from model):
293+
294+
```json
295+
{
296+
"name": "refresh_dashboard",
297+
"description": "Refresh dashboard data",
298+
"inputSchema": { "type": "object" },
299+
"_meta": {
300+
"ui": {
301+
"resourceUri": "ui://weather-server/dashboard-template",
302+
"visibility": ["apps"]
303+
}
275304
}
276305
}
277306
```
278307

279308
#### Behavior:
280309

281-
- If `ui/resourceUri` is present and host supports MCP Apps, host renders tool results using the specified UI resource
310+
- If `ui.resourceUri` is present and host supports MCP Apps, host renders tool results using the specified UI resource
282311
- If host does not support MCP Apps, tool behaves as standard tool (text-only fallback)
283312
- Resource MUST exist on the server
284-
- Host MUST use `resources/read` to fetch the referenced resource URI.
313+
- Host MUST use `resources/read` to fetch the referenced resource URI
285314
- Host MAY prefetch and cache UI resource content for performance optimization
286315
- Since UI resources are primarily discovered through tool metadata, Servers MAY omit UI-only resources from `resources/list` and `notifications/resources/list_changed`
287316

317+
#### Visibility:
318+
319+
- `visibility` defaults to `["model"]` if omitted (standard MCP behavior)
320+
- `"model"`: Tool is visible to and callable by the agent
321+
- `"apps"`: Tool is callable by apps from the same server connection only
322+
- Host MUST NOT include tools with `visibility: ["apps"]` in the agent's tool list
323+
- Host MUST reject `tools/call` requests from apps for tools that don't include `"apps"` in visibility
324+
- Cross-server tool calls are always blocked for app-only tools
325+
288326
#### Benefits:
289327

290328
- **Performance:** Host can preload templates before tool execution
@@ -706,7 +744,7 @@ sequenceDiagram
706744
707745
autonumber
708746
S -->> H: resources/list (includes ui:// resources)
709-
S -->> H: tools/list (includes tools with ui/resourceUri metadata)
747+
S -->> H: tools/list (includes tools with _meta.ui metadata)
710748
```
711749

712750
#### 2. UI Initialization (Desktop/Native Hosts)
@@ -720,7 +758,7 @@ sequenceDiagram
720758
721759
autonumber
722760
par UI Tool call
723-
H ->> S: tools/call to Tool with ui/resourceUri metadata
761+
H ->> S: tools/call to Tool with _meta.ui metadata
724762
and UI initialization
725763
alt Desktop/Native hosts
726764
H ->> H: Render Guest UI in an iframe (HTML from the ui:// resource)
@@ -906,7 +944,7 @@ await client.callTool("get_weather", { location: "New York" });
906944

907945
This pattern enables interactive, self-updating widgets.
908946

909-
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.
947+
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.
910948

911949
### Client\<\>Server Capability Negotiation
912950

@@ -959,7 +997,7 @@ if (hasUISupport) {
959997
description: "Get weather with interactive dashboard",
960998
inputSchema: { /* ... */ },
961999
_meta: {
962-
"ui/resourceUri": "ui://weather-server/dashboard"
1000+
ui: { resourceUri: "ui://weather-server/dashboard" }
9631001
}
9641002
});
9651003
} else {
@@ -1050,6 +1088,24 @@ This proposal synthesizes feedback from the UI CWG and MCP-UI community, host im
10501088
- **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.
10511089
- **Support multiple content types:** Deferred to maintain a lean MVP.
10521090

1091+
#### 4. Tool Visibility via Metadata
1092+
1093+
**Decision:** Use `_meta.ui.visibility` array to control tool accessibility between model and apps.
1094+
1095+
**Rationale:**
1096+
1097+
- Nested `_meta.ui` structure groups all UI-related metadata cleanly
1098+
- Array format (`["model", "apps"]`) allows flexible combinations
1099+
- Default `["model"]` preserves standard MCP behavior for existing tools
1100+
- `"apps"` scope is per-server, preventing cross-server tool calls
1101+
- Cleaner than OpenAI's two-field approach (`widgetAccessible` + `visibility`)
1102+
1103+
**Alternatives considered:**
1104+
1105+
- **Two separate fields:** OpenAI uses `widgetAccessible` and `visibility` separately. Rejected as redundant; single `visibility` array covers all cases.
1106+
- **Boolean `private` flag:** Simpler but less flexible; doesn't express model-only tools.
1107+
- **Flat `ui/visibility` key:** Rejected in favor of nested structure for consistency with future `_meta.ui` fields.
1108+
10531109
### Backward Compatibility
10541110

10551111
The proposal builds on the existing core protocol. There are no incompatibilities.

0 commit comments

Comments
 (0)