Smoothen the process of getting started (#103)

* Restructure threejs-server README to match marketing examples

- Update title format to "Example: Three.js App"
- Constrain screenshot width using table layout
- Add Features section with key capabilities
- Reorganize Running section with Tool Input subsection
- Add Architecture section describing server and app components
- Remove implementation-focused sections (WidgetProps, Creating a New Widget)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add bun as devDependency to example packages

npm install now automatically installs bun, eliminating the need for
separate installation instructions. Removed manual bun install step
from customer-segmentation-server README.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add start:http and start:stdio npm scripts to examples

For the 6 examples supporting --stdio transport, add explicit scripts:
- serve:http / serve:stdio for running the server
- start:http / start:stdio for build + serve
- start now aliases to start:http for backward compatibility

Update READMEs to document both transport options.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Default basic-host SERVERS to localhost:3001/mcp

- Change threejs-server default port from 3109 to 3001 for consistency
- Add default SERVERS value in basic-host serve.ts
- Document SERVERS env var in basic-host README

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Improve Examples section in README

Frame the three basic examples as foundational starting points and
add a link to the examples directory for additional demo apps.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2025-12-09 09:15:32 -06:00 • committed by GitHub
commit 4ca20f21c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 149 additions and 132 deletions

View file

@ -54,18 +54,22 @@ Your `package.json` will then look like:
## Examples
- [`examples/basic-server-react`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) — Example MCP server with tools that return UI Apps (React)
Start with these foundational examples to learn the SDK:
- [`examples/basic-server-vanillajs`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vanillajs) — Example MCP server with tools that return UI Apps (vanilla JS)
- [`examples/basic-server-react`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) — Example MCP server with tools that return UI Apps (React)
- [`examples/basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) — Bare-bones example of hosting MCP Apps
To run the examples end-to-end:
The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples) directory contains additional demo apps showcasing real-world use cases.
To run all examples together:
```
npm i
npm install
npm run examples:start
```
Then open http://localhost:8080/
Then open http://localhost:8080/.
## Resources

View file

@ -1,6 +1,6 @@
# Example: Basic Host
A reference implementation showing how to build an MCP Host application that connects to MCP servers and renders tool UIs in a secure sandbox.
A reference implementation showing how to build an MCP host application that connects to MCP servers and renders tool UIs in a secure sandbox.
This basic host can also be used to test MCP Apps during local development.
@ -14,10 +14,16 @@ This basic host can also be used to test MCP Apps during local development.
```bash
npm install
npm run dev
npm run start
# Open http://localhost:8080
```
By default, the host application will try to connect to an MCP server at `http://localhost:3001/mcp`. You can configure this behavior by setting the `SERVERS` environment variable with a JSON array of server URLs:
```bash
SERVERS='["http://localhost:1234/mcp", "http://localhost:5678/mcp"]' npm run start
```
## Architecture
This example uses a double-iframe sandbox pattern for secure UI isolation:

View file

@ -18,7 +18,9 @@ const __dirname = dirname(__filename);
const HOST_PORT = parseInt(process.env.HOST_PORT || "8080", 10);
const SANDBOX_PORT = parseInt(process.env.SANDBOX_PORT || "8081", 10);
const DIRECTORY = join(__dirname, "dist");
const SERVERS: string[] = process.env.SERVERS ? JSON.parse(process.env.SERVERS) : [];
const SERVERS: string[] = process.env.SERVERS
? JSON.parse(process.env.SERVERS)
: ["http://localhost:3001/mcp"];
// ============ Host Server (port 8080) ============
const hostApp = express();

View file

@ -24,6 +24,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -19,6 +19,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -30,11 +30,11 @@ An interactive budget allocation tool demonstrating real-time data visualization
2. Build and start the server:
```bash
npm start
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
The server will listen on `http://localhost:3001/mcp`.
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Architecture

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -20,6 +23,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -30,11 +30,11 @@ A demo MCP App that displays cohort retention data as an interactive heatmap, sh
2. Build and start the server:
```bash
npm start
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
The server will listen on `http://localhost:3001/mcp`.
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Architecture

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -24,6 +27,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -22,27 +22,21 @@ A demo MCP App that displays customer data as an interactive scatter/bubble char
## Running
1. Install [Bun](https://github.com/oven-sh/bun) (if not already installed):
```bash
curl -fsSL https://bun.com/install | bash
```
2. Install dependencies:
1. Install dependencies:
```bash
npm install
```
3. Build and start the server:
2. Build and start the server:
```bash
npm start
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
The server will listen on `http://localhost:3001/mcp`.
4. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Architecture

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -20,6 +23,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -30,11 +30,11 @@ A React-based demo MCP App that lets users adjust SaaS business parameters and s
2. Build and start the server:
```bash
npm start
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
The server will listen on `http://localhost:3001/mcp`.
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Architecture

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -25,6 +28,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -29,11 +29,11 @@ A demo MCP App that displays real-time OS metrics with a stacked area chart for
2. Build and start the server:
```bash
npm start
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
The server will listen on `http://localhost:3001/mcp`.
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Architecture

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -21,6 +24,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -1,93 +1,43 @@
# Three.js MCP Server
# Example: Three.js App
Interactive 3D scene renderer using Three.js. Demonstrates streaming code preview and full MCP App integration.
![Screenshot](https://modelcontextprotocol.github.io/ext-apps/screenshots/threejs-server/screenshot.png)
<table>
<tr>
<td><a href="https://modelcontextprotocol.github.io/ext-apps/screenshots/threejs-server/screenshot.png"><img src="https://modelcontextprotocol.github.io/ext-apps/screenshots/threejs-server/screenshot.png" alt="Three.js scene" width="400"></a></td>
</tr>
</table>
## Tools
## Features
| Tool | Description |
| -------------------- | ------------------------------------ |
| `show_threejs_scene` | Render 3D scene from JavaScript code |
| `learn_threejs` | Get documentation and examples |
- **Interactive 3D Rendering**: Execute JavaScript code to create and animate Three.js scenes
- **Streaming Preview**: See the scene build in real-time as code is being written
- **Built-in Helpers**: Pre-configured `OrbitControls`, post-processing effects (bloom), and render passes
- **Documentation Tool**: `learn_threejs` provides API docs and code examples on demand
## Quick Start
## Running
```bash
# Build
npm run build
1. Install dependencies:
# Run (stdio mode for Claude Desktop)
bun server.ts --stdio
```bash
npm install
```
# Run (HTTP mode for basic-host)
bun server.ts
```
2. Build and start the server:
## Code Structure
```bash
npm run start:http # for Streamable HTTP transport
# OR
npm run start:stdio # for stdio transport
```
```
threejs-server/
├── server.ts # MCP server with tools
├── mcp-app.html # Entry HTML
└── src/
├── mcp-app-wrapper.tsx # Generic MCP App wrapper (reusable)
├── threejs-app.tsx # Three.js widget component
└── global.css # Styles
```
3. View using the [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example or another MCP Apps-compatible host.
## Key Files
### Tool Input
### `src/mcp-app-wrapper.tsx`
To test the example, copy the contents of [`test-input.json`](test-input.json) into the tool input field in `basic-host`.
Generic wrapper handling MCP connection. Provides `WidgetProps` interface:
```tsx
interface WidgetProps<TToolInput> {
toolInputs: TToolInput | null; // Complete tool input
toolInputsPartial: TToolInput | null; // Streaming partial input
toolResult: CallToolResult | null; // Tool execution result
hostContext: McpUiHostContext | null; // Theme, viewport, locale
callServerTool: App["callServerTool"]; // Call MCP server tools
sendMessage: App["sendMessage"]; // Send chat messages
sendOpenLink: App["sendOpenLink"]; // Open URLs in browser
sendLog: App["sendLog"]; // Debug logging
}
```
### `src/threejs-app.tsx`
Widget component receiving all props. Uses:
- `toolInputs.code` - JavaScript to execute
- `toolInputsPartial.code` - Streaming preview
- `toolInputs.height` - Canvas height
### `server.ts`
MCP server with:
- `show_threejs_scene` tool linked to UI resource
- `learn_threejs` documentation tool
- stdio + HTTP transport support
## Available Three.js Globals
```javascript
THREE; // Three.js library
canvas; // Pre-created canvas
(width, height); // Canvas dimensions
OrbitControls; // Camera controls
EffectComposer; // Post-processing
RenderPass; // Render pass
UnrealBloomPass; // Bloom effect
```
## Test Input
Copy contents of `test-input.json` to test in basic-host (`http://localhost:8080`).
## Example Code
The test input creates a simple scene with a rotating cube:
```javascript
const scene = new THREE.Scene();
@ -128,10 +78,37 @@ function animate() {
animate();
```
## Creating a New Widget
#### Available Three.js Globals
1. Copy this example
2. Rename `threejs-app.tsx` to your widget name
3. Define your `ToolInput` interface
4. Implement your widget using the `WidgetProps`
5. Update `server.ts` with your tools
When writing custom code, these globals are available:
```javascript
THREE; // Three.js library
canvas; // Pre-created canvas element
width; // Canvas width
height; // Canvas height
OrbitControls; // Camera controls
EffectComposer; // Post-processing composer
RenderPass; // Render pass
UnrealBloomPass; // Bloom effect
```
## Architecture
### Server (`server.ts`)
Exposes two tools:
- `show_threejs_scene` - Renders a 3D scene from JavaScript code
- `learn_threejs` - Returns documentation and code examples for Three.js APIs
Supports Streamable HTTP and stdio transports.
### App (`src/threejs-app.tsx`)
React component that:
- Receives tool inputs via the MCP App SDK
- Displays streaming preview from `toolInputsPartial.code` as code arrives
- Executes final code from `toolInputs.code` when complete
- Renders to a pre-created canvas with configurable height

View file

@ -6,9 +6,12 @@
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
@ -26,6 +29,7 @@
"@types/react-dom": "^19.2.2",
"@types/three": "^0.181.0",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",

View file

@ -14,7 +14,7 @@ import path from "node:path";
import { z } from "zod";
import { RESOURCE_URI_META_KEY } from "../../dist/src/app";
const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3109;
const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3001;
const DIST_DIR = path.join(import.meta.dirname, "dist");
const THREEJS_DOCUMENTATION = `# Three.js Widget Documentation

8
package-lock.json generated
View file

@ -92,6 +92,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -120,6 +121,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -149,6 +151,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -182,6 +185,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -211,6 +215,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -245,6 +250,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -275,6 +281,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
@ -310,6 +317,7 @@
"@types/react-dom": "^19.2.2",
"@types/three": "^0.181.0",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",