Skip to content

Commit bcb5b64

Browse files
cliffhallclaude
andauthored
docs(apps): specify the v2 Apps tab (#1265)
Adds the missing Apps tab to the v2 UX specification. Apps are the subset of tools whose `_meta.ui.resourceUri` advertises a UI resource (per `@modelcontextprotocol/ext-apps`). The screen mirrors the legacy v1 layout: a sidebar of apps and a right pane that toggles between an input form (before launch) and the embedded MCP App via `AppBridge`. - v2_ux.md: add `[Apps]` to the navigation tab list and a new "Apps Screen" subsection with both states (input form / running app). - v2_ux_features.md: full Apps Screen feature spec — ASCII diagrams, detection rule, presentational contract for `AppsScreen` / `AppRenderer` (imperative ref shape so the screen stays "dumb" and the wiring layer drives the bridge). - v2_screenshots.md: link the two reference PNGs from the legacy v1 client. - v2_ux_storybook.md: add `AppListItem` (2.3a), `AppDetailPanel` (2.5a), `AppRenderer` (2.5b), and `AppsScreen` (3.2a); update Build Order. Implementation work tracked on the v2 board: #1260#1264. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5a2d24b commit bcb5b64

6 files changed

Lines changed: 315 additions & 19 deletions

File tree

475 KB
Loading
235 KB
Loading

specification/v2_screenshots.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ Tool list with annotations (user, read-only, destructive, long-running), paramet
5151

5252
![Tools Screen](screenshots/shadcn-tools.png)
5353

54+
### Apps Screen
55+
56+
The subset of tools that are MCP Apps — tools with `_meta.ui.resourceUri`. Two-panel layout: list of apps on the left, input form (before launch) or embedded app iframe (after launch) on the right.
57+
58+
**Input form state** (from legacy v1 reference):
59+
60+
![Apps Screen — Input Form](screenshots/apps-tab-form.png)
61+
62+
**Running app state** (from legacy v1 reference):
63+
64+
![Apps Screen — Running App](screenshots/apps-tab-app.png)
65+
5466
### Resources Screen
5567
Accordion layout with Resources, Templates, and Subscriptions sections.
5668

specification/v2_ux.md

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* [Server Info (Connected)](#server-info-connected)
1414
* [Feature Screens](#feature-screens)
1515
* [Tools Screen](#tools-screen)
16+
* [Apps Screen](#apps-screen)
1617
* [Resources Screen](#resources-screen)
1718
* [Prompts Screen](#prompts-screen)
1819
* [Logging Screen](#logging-screen)
@@ -40,7 +41,7 @@
4041

4142
```
4243
┌─────────────────────────────────────────────────────────────────────────────────────────┐
43-
│ [Server Name ▼] ● Connected (23ms) [Tools] [Resources] [Prompts] [Logs] [Tasks] [History] [Disconnect] │
44+
│ [Server Name ▼] ● Connected (23ms) [Tools] [Apps] [Resources] [Prompts] [Logs] [Tasks] [History] [Disconnect] │
4445
├─────────────────────────────────────────────────────────────────────────────────────────┤
4546
│ │
4647
│ Full-width content │
@@ -49,7 +50,7 @@
4950
```
5051

5152
- **Menu bar** displays server name, connection status with latency, and disconnect button when connected
52-
- **Top navigation** links to Tools, Resources, Prompts, Logs, Tasks, and History sections
53+
- **Top navigation** links to Tools, Apps, Resources, Prompts, Logs, Tasks, and History sections
5354
- **Connection indicator** shows latency from periodic `ping` requests
5455
- **No sidebar** - content areas use full width
5556

@@ -399,6 +400,95 @@ When a tool execution triggers sampling or elicitation requests, they appear inl
399400
- Audio player for audio content (base64)
400401
- Resource links displayed as clickable references
401402

403+
#### Apps Screen
404+
405+
A two-panel layout showing the subset of tools that are **MCP Apps** — tools whose
406+
metadata advertises a UI resource via `_meta.ui.resourceUri` (or the deprecated
407+
flat `_meta["ui/resourceUri"]`). The right panel toggles between an input form
408+
(before launch) and the embedded app (after launch).
409+
410+
**Input Form State:**
411+
412+
```
413+
┌──────────────────────────┬──────────────────────────────────────────────┐
414+
│ MCP Apps (1) 🔍 │ get-cohort-data ✕ │
415+
│ [Refresh Apps] │ Returns cohort retention heatmap data... │
416+
├──────────────────────────┼──────────────────────────────────────────────┤
417+
│ │ │
418+
│ ▸ get-cohort-data │ ┌──────────────────────────────────────────┐ │
419+
│ Returns cohort │ │ App Input │ │
420+
│ retention heatmap... │ │ │ │
421+
│ │ │ metric │ │
422+
│ │ │ ┌──────────────────────────────────────┐ │ │
423+
│ │ │ │ retention ▾ │ │ │
424+
│ │ │ └──────────────────────────────────────┘ │ │
425+
│ │ │ │ │
426+
│ │ │ periodType │ │
427+
│ │ │ ┌──────────────────────────────────────┐ │ │
428+
│ │ │ │ monthly ▾ │ │ │
429+
│ │ │ └──────────────────────────────────────┘ │ │
430+
│ │ │ │ │
431+
│ │ │ cohortCount │ │
432+
│ │ │ ┌──────────────────────────────────────┐ │ │
433+
│ │ │ │ 12 │ │ │
434+
│ │ │ └──────────────────────────────────────┘ │ │
435+
│ │ │ │ │
436+
│ │ │ maxPeriods │ │
437+
│ │ │ ┌──────────────────────────────────────┐ │ │
438+
│ │ │ │ 12 │ │ │
439+
│ │ │ └──────────────────────────────────────┘ │ │
440+
│ │ │ │ │
441+
│ │ │ [▶ Open App] │ │
442+
│ │ └──────────────────────────────────────────┘ │
443+
└──────────────────────────┴──────────────────────────────────────────────┘
444+
```
445+
446+
**Running App State:**
447+
448+
After "Open App" the right panel swaps to the embedded MCP App. The input
449+
form is replaced by the app iframe; a "Back to Input" button (only when the
450+
selected app has input fields) returns to the form.
451+
452+
```
453+
┌──────────────────────────┬──────────────────────────────────────────────┐
454+
│ MCP Apps (1) 🔍 │ get-cohort-data ⛶ ✕ │
455+
│ [Refresh Apps] │ [Back to Input] │
456+
├──────────────────────────┼──────────────────────────────────────────────┤
457+
│ ▸ get-cohort-data │ ┌──────────────────────────────────────────┐ │
458+
│ Returns cohort │ │ │ │
459+
│ retention heatmap... │ │ [Embedded MCP App] │ │
460+
│ │ │ │ │
461+
│ │ │ Cohort Retention Analysis Metric: ▾ │ │
462+
│ │ │ │ │
463+
│ │ │ May 2025 100 85 72 ... │ │
464+
│ │ │ Jun 2025 100 85 78 ... │ │
465+
│ │ │ ... │ │
466+
│ │ │ │ │
467+
│ │ └──────────────────────────────────────────┘ │
468+
└──────────────────────────┴──────────────────────────────────────────────┘
469+
```
470+
471+
**Features:**
472+
- **App Detection** — A tool is treated as an App when `getToolUiResourceUri(tool)`
473+
returns a defined `ui://...` URI (helper from `@modelcontextprotocol/ext-apps`).
474+
Filtering happens upstream (wiring layer); the screen receives an already-filtered
475+
`tools: Tool[]` array of apps.
476+
- **List Changed Indicator** — Shows when `notifications/tools/list_changed` received.
477+
- **Refresh Apps** button re-runs `tools/list`.
478+
- Searchable list, mirroring the Tools screen sidebar.
479+
- **App icons** rendered from `tool.icons` when present.
480+
- **App Input form** generated from `tool.inputSchema` (same `SchemaForm` used by
481+
Tools screen).
482+
- **Open App** button:
483+
- If the tool has input fields, the form must be filled before launch.
484+
- If the tool has no input fields, "Open App" runs immediately on selection.
485+
- **Back to Input** returns to the form (only visible when the app has fields).
486+
- **Maximize / Minimize** toggle hides the sidebar to give the app the full viewport.
487+
- **App Renderer** embeds the UI resource in a sandboxed iframe and bridges
488+
it to the active MCP server via `AppBridge`. Tool input and result are sent
489+
to the app via `sendToolInput` / `sendToolResult`.
490+
- **Close (✕)** deselects the app and clears any in-flight launch.
491+
402492
#### Resources Screen
403493

404494
```

specification/v2_ux_features.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Each feature screen uses a **resizable panel layout** for flexibility.
99

1010
## Table of Contents
1111
* [Tools Screen](#tools-screen)
12+
* [Apps Screen](#apps-screen)
1213
* [Resources Screen](#resources-screen)
1314
* [Prompts Screen](#prompts-screen)
1415
* [Logging Screen](#logging-screen)
@@ -124,6 +125,111 @@ When a tool execution triggers sampling or elicitation requests, they appear inl
124125
- Audio player for audio content (base64)
125126
- Resource links displayed as clickable references
126127

128+
## Apps Screen
129+
130+
A two-panel layout showing the subset of tools that are **MCP Apps** — tools
131+
whose metadata advertises a UI resource via `_meta.ui.resourceUri` (or the
132+
deprecated flat `_meta["ui/resourceUri"]`). The right panel toggles between an
133+
input form (before launch) and the embedded app (after launch).
134+
135+
```
136+
+--------------------------+----------------------------------------------+
137+
| MCP Apps (1) [Q] | get-cohort-data [x] |
138+
| [Refresh Apps] | Returns cohort retention heatmap data |
139+
+--------------------------+----------------------------------------------+
140+
| | |
141+
| > get-cohort-data | +------------------------------------------+ |
142+
| Returns cohort | | App Input | |
143+
| retention heatmap... | | | |
144+
| | | metric | |
145+
| | | +--------------------------------------+ | |
146+
| | | | retention v | | |
147+
| | | +--------------------------------------+ | |
148+
| | | | |
149+
| | | periodType | |
150+
| | | +--------------------------------------+ | |
151+
| | | | monthly v | | |
152+
| | | +--------------------------------------+ | |
153+
| | | | |
154+
| | | cohortCount | |
155+
| | | +--------------------------------------+ | |
156+
| | | | 12 | | |
157+
| | | +--------------------------------------+ | |
158+
| | | | |
159+
| | | maxPeriods | |
160+
| | | +--------------------------------------+ | |
161+
| | | | 12 | | |
162+
| | | +--------------------------------------+ | |
163+
| | | | |
164+
| | | [> Open App] | |
165+
| | +------------------------------------------+ |
166+
+--------------------------+----------------------------------------------+
167+
```
168+
169+
**Running App State:**
170+
171+
After "Open App" the right panel swaps to the embedded MCP App. The input form
172+
is replaced by the app iframe. A "Back to Input" button is shown when the
173+
selected app has input fields; it returns to the form. A Maximize toggle hides
174+
the sidebar so the app takes the full viewport.
175+
176+
```
177+
+--------------------------+----------------------------------------------+
178+
| MCP Apps (1) [Q] | get-cohort-data [^] [x] |
179+
| [Refresh Apps] | [Back to Input] |
180+
+--------------------------+----------------------------------------------+
181+
| > get-cohort-data | +------------------------------------------+ |
182+
| Returns cohort | | | |
183+
| retention heatmap... | | [Embedded MCP App] | |
184+
| | | | |
185+
| | | Cohort Retention Analysis Metric: [v] | |
186+
| | | | |
187+
| | | May 2025 100 85 72 ... | |
188+
| | | Jun 2025 100 85 78 ... | |
189+
| | | ... | |
190+
| | | | |
191+
| | +------------------------------------------+ |
192+
+--------------------------+----------------------------------------------+
193+
```
194+
195+
**Features:**
196+
197+
- **App Detection** — A tool is treated as an App when `getToolUiResourceUri(tool)`
198+
returns a defined `ui://...` URI (helper from `@modelcontextprotocol/ext-apps`).
199+
The detection helper is wrapped in `core/mcp/apps.ts` (e.g. `isAppTool(tool)`)
200+
so all clients (web, CLI, TUI) share one definition. Filtering happens upstream
201+
(wiring layer); the screen receives an already-filtered `tools: Tool[]` array.
202+
- **List Changed Indicator** — shows when `notifications/tools/list_changed`
203+
received; same component as the Tools screen.
204+
- **Refresh Apps** re-runs `tools/list`.
205+
- **Searchable list**, mirroring the Tools screen sidebar.
206+
- **App icons** rendered from `tool.icons` (real MCP `Tool.icons`) when present.
207+
- **App Input form** generated from `tool.inputSchema` via the same `SchemaForm`
208+
used by the Tools screen.
209+
- **Open App** button:
210+
- If the tool has input fields, the form is filled before launch.
211+
- If the tool has no input fields, "Open App" runs immediately on selection.
212+
- **Back to Input** returns to the form (visible only when the app has fields).
213+
- **Maximize / Minimize** toggles full-viewport mode by hiding the sidebar.
214+
- **App Renderer** embeds the UI resource in a sandboxed iframe and bridges
215+
it to the active MCP server via the `AppBridge` from
216+
`@modelcontextprotocol/ext-apps`. The host pushes tool input and results to
217+
the app via `sendToolInput` / `sendToolResult` through an imperative ref.
218+
- **Close (x)** deselects the app and clears any in-flight launch.
219+
220+
**Component contract (presentational):**
221+
222+
The screen and its sub-components stay "dumb": they accept data + callbacks +
223+
imperative refs and contain only display logic.
224+
225+
- `AppsScreen` props: `tools: Tool[]` (already filtered to apps), `listChanged`,
226+
`onRefreshList`, `onSelectApp`, `onOpenApp(name, args)`, `onCloseApp`, plus a
227+
ref for the embedded `AppRenderer`.
228+
- `AppRenderer` exposes an imperative ref with `sendToolInput`,
229+
`sendToolResult`, `sendToolCancelled`, `teardown`. The wiring layer creates
230+
the `AppBridge` from the active MCP `Client` (real MCP type) and drives the
231+
ref; the renderer itself only owns the iframe and the bridge handle.
232+
127233
## Resources Screen
128234

129235
Uses an **accordion layout** for the left panel to organize Resources, Templates, and Subscriptions into collapsible sections.

0 commit comments

Comments
 (0)