Skip to content

Commit 13e599c

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/virtual-desktop-server
2 parents 4bc85b6 + 978d8e6 commit 13e599c

40 files changed

Lines changed: 1208 additions & 51 deletions

File tree

README.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,28 @@ Or edit your `package.json` manually:
5656

5757
## Examples
5858

59-
Start with these foundational examples to learn the SDK:
60-
61-
- [`examples/basic-server-vanillajs`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vanillajs) — MCP server + MCP App using vanilla JS
62-
- [`examples/basic-server-react`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) — MCP server + MCP App using [React](https://github.com/facebook/react)
63-
- [`examples/basic-server-vue`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vue) — MCP server + MCP App using [Vue](https://github.com/vuejs/vue)
64-
- [`examples/basic-server-svelte`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-svelte) — MCP server + MCP App using [Svelte](https://github.com/sveltejs/svelte)
65-
- [`examples/basic-server-preact`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-preact) — MCP server + MCP App using [Preact](https://github.com/preactjs/preact)
66-
- [`examples/basic-server-solid`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-solid) — MCP server + MCP App using [Solid](https://github.com/solidjs/solid)
67-
- [`examples/basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) — MCP host application supporting MCP Apps
59+
<!-- prettier-ignore-start -->
60+
| | | |
61+
|:---:|:---:|:---:|
62+
| [![Map](examples/map-server/grid-cell.png "Interactive 3D globe viewer using CesiumJS")](examples/map-server) | [![Three.js](examples/threejs-server/grid-cell.png "Interactive 3D scene renderer")](examples/threejs-server) | [![ShaderToy](examples/shadertoy-server/grid-cell.png "Real-time GLSL shader renderer")](examples/shadertoy-server) |
63+
| [**Map**](examples/map-server) | [**Three.js**](examples/threejs-server) | [**ShaderToy**](examples/shadertoy-server) |
64+
| [![Sheet Music](examples/sheet-music-server/grid-cell.png "ABC notation to sheet music")](examples/sheet-music-server) | [![Wiki Explorer](examples/wiki-explorer-server/grid-cell.png "Wikipedia link graph visualization")](examples/wiki-explorer-server) | [![Cohort Heatmap](examples/cohort-heatmap-server/grid-cell.png "Customer retention heatmap")](examples/cohort-heatmap-server) |
65+
| [**Sheet Music**](examples/sheet-music-server) | [**Wiki Explorer**](examples/wiki-explorer-server) | [**Cohort Heatmap**](examples/cohort-heatmap-server) |
66+
| [![Scenario Modeler](examples/scenario-modeler-server/grid-cell.png "SaaS business projections")](examples/scenario-modeler-server) | [![Budget Allocator](examples/budget-allocator-server/grid-cell.png "Interactive budget allocation")](examples/budget-allocator-server) | [![Customer Segmentation](examples/customer-segmentation-server/grid-cell.png "Scatter chart with clustering")](examples/customer-segmentation-server) |
67+
| [**Scenario Modeler**](examples/scenario-modeler-server) | [**Budget Allocator**](examples/budget-allocator-server) | [**Customer Segmentation**](examples/customer-segmentation-server) |
68+
| [![System Monitor](examples/system-monitor-server/grid-cell.png "Real-time OS metrics")](examples/system-monitor-server) | [![Transcript](examples/transcript-server/grid-cell.png "Live speech transcription")](examples/transcript-server) | [![Video Resource](examples/video-resource-server/grid-cell.png "Binary video via MCP resources")](examples/video-resource-server) |
69+
| [**System Monitor**](examples/system-monitor-server) | [**Transcript**](examples/transcript-server) | [**Video Resource**](examples/video-resource-server) |
70+
71+
### Starter Templates
72+
73+
| | |
74+
|:---:|:---|
75+
| [![Basic](examples/basic-server-react/grid-cell.png "Starter template")](examples/basic-server-react) | The same app built with different frameworks — pick your favorite!<br><br>[React](examples/basic-server-react) · [Vue](examples/basic-server-vue) · [Svelte](examples/basic-server-svelte) · [Preact](examples/basic-server-preact) · [Solid](examples/basic-server-solid) · [Vanilla JS](examples/basic-server-vanillajs) |
76+
<!-- prettier-ignore-end -->
6877

6978
The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples) directory contains additional demo apps showcasing real-world use cases.
7079

71-
To run all examples together:
80+
To run all examples:
7281

7382
```bash
7483
npm install

docs/migrate_from_openai_apps.md

Lines changed: 351 additions & 0 deletions
Large diffs are not rendered by default.

examples/basic-host/src/index.tsx

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
1+
import { getToolUiResourceUri, McpUiToolMetaSchema } from "@modelcontextprotocol/ext-apps/app-bridge";
12
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
23
import { Component, type ErrorInfo, type ReactNode, StrictMode, Suspense, use, useEffect, useMemo, useRef, useState } from "react";
34
import { createRoot } from "react-dom/client";
45
import { callTool, connectToServer, hasAppHtml, initializeApp, loadSandboxProxy, log, newAppBridge, type ServerInfo, type ToolCallInfo, type ModelContext, type AppMessage } from "./implementation";
56
import styles from "./index.module.css";
67

8+
/**
9+
* Check if a tool is visible to the model (not app-only).
10+
* Tools with `visibility: ["app"]` should not be shown in tool lists.
11+
*/
12+
function isToolVisibleToModel(tool: { _meta?: Record<string, unknown> }): boolean {
13+
const result = McpUiToolMetaSchema.safeParse(tool._meta?.ui);
14+
if (!result.success) return true; // default: visible to model
15+
const visibility = result.data.visibility;
16+
if (!visibility) return true; // default: visible to model
17+
return visibility.includes("model");
18+
}
19+
20+
/** Compare tools: UI-enabled first, then alphabetically by name. */
21+
function compareTools(a: Tool, b: Tool): number {
22+
const aHasUi = !!getToolUiResourceUri(a);
23+
const bHasUi = !!getToolUiResourceUri(b);
24+
if (aHasUi && !bHasUi) return -1;
25+
if (!aHasUi && bHasUi) return 1;
26+
return a.name.localeCompare(b.name);
27+
}
728

829
/**
930
* Extract default values from a tool's JSON Schema inputSchema.
@@ -80,7 +101,13 @@ function CallToolPanel({ serversPromise, addToolCall }: CallToolPanelProps) {
80101
const [selectedTool, setSelectedTool] = useState("");
81102
const [inputJson, setInputJson] = useState("{}");
82103

83-
const toolNames = selectedServer ? Array.from(selectedServer.tools.keys()) : [];
104+
// Filter out app-only tools, prioritize tools with UIs
105+
const toolNames = selectedServer
106+
? Array.from(selectedServer.tools.values())
107+
.filter((tool) => isToolVisibleToModel(tool))
108+
.sort(compareTools)
109+
.map((tool) => tool.name)
110+
: [];
84111

85112
const isValidJson = useMemo(() => {
86113
try {
@@ -93,10 +120,14 @@ function CallToolPanel({ serversPromise, addToolCall }: CallToolPanelProps) {
93120

94121
const handleServerSelect = (server: ServerInfo) => {
95122
setSelectedServer(server);
96-
const [firstTool] = server.tools.keys();
97-
setSelectedTool(firstTool ?? "");
123+
// Filter out app-only tools, prioritize tools with UIs
124+
const visibleTools = Array.from(server.tools.values())
125+
.filter((tool) => isToolVisibleToModel(tool))
126+
.sort(compareTools);
127+
const firstTool = visibleTools[0]?.name ?? "";
128+
setSelectedTool(firstTool);
98129
// Set input JSON to tool defaults (if any)
99-
setInputJson(getToolDefaults(server.tools.get(firstTool ?? "")));
130+
setInputJson(getToolDefaults(server.tools.get(firstTool)));
100131
};
101132

102133
const handleToolSelect = (toolName: string) => {

examples/basic-server-react/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Example: Basic Server (React)
22

3+
![Screenshot](screenshot.png)
4+
35
An MCP App example with a React UI.
46

57
> [!TIP]
24.9 KB
Loading
20.8 KB
Loading
32.5 KB
Loading
39.5 KB
Loading
49 KB
Loading
63.9 KB
Loading

0 commit comments

Comments
 (0)