Skip to content

Commit 2755438

Browse files
antonpk1claude
andcommitted
Add Three.js marketing example server
New example demonstrating interactive 3D scene rendering with: - show_threejs_scene tool with streaming code preview - learn_threejs documentation tool - Full WidgetProps interface for MCP App integration - Reusable mcp-app-wrapper.tsx pattern Also adds bun.lockb to .gitignore. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 42265d8 commit 2755438

File tree

14 files changed

+913
-1
lines changed

14 files changed

+913
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
dist/
33
node_modules/
44
yarn.lock
5+
bun.lockb
56
.vscode/
67
docs/api/
78
tmp/

examples/basic-host/src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const SERVERS = [
1313
{ name: "Customer Segmentation", port: 3105 },
1414
{ name: "Scenario Modeler", port: 3106 },
1515
{ name: "System Monitor", port: 3107 },
16+
{ name: "Three.js", port: 3109 },
1617
] as const;
1718

1819
function serverUrl(port: number): string {

examples/threejs-server/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Three.js MCP Server
2+
3+
Interactive 3D scene renderer using Three.js. Demonstrates streaming code preview and full MCP App integration.
4+
5+
![Screenshot](https://modelcontextprotocol.github.io/ext-apps/screenshots/threejs-server/screenshot.png)
6+
7+
## Tools
8+
9+
| Tool | Description |
10+
| -------------------- | ------------------------------------ |
11+
| `show_threejs_scene` | Render 3D scene from JavaScript code |
12+
| `learn_threejs` | Get documentation and examples |
13+
14+
## Quick Start
15+
16+
```bash
17+
# Build
18+
npm run build
19+
20+
# Run (stdio mode for Claude Desktop)
21+
bun server.ts --stdio
22+
23+
# Run (HTTP mode for basic-host)
24+
bun server.ts
25+
```
26+
27+
## Code Structure
28+
29+
```
30+
threejs-server/
31+
├── server.ts # MCP server with tools
32+
├── mcp-app.html # Entry HTML
33+
└── src/
34+
├── mcp-app-wrapper.tsx # Generic MCP App wrapper (reusable)
35+
├── threejs-app.tsx # Three.js widget component
36+
└── global.css # Styles
37+
```
38+
39+
## Key Files
40+
41+
### `src/mcp-app-wrapper.tsx`
42+
43+
Generic wrapper handling MCP connection. Provides `WidgetProps` interface:
44+
45+
```tsx
46+
interface WidgetProps<TToolInput> {
47+
toolInputs: TToolInput | null; // Complete tool input
48+
toolInputsPartial: TToolInput | null; // Streaming partial input
49+
toolResult: CallToolResult | null; // Tool execution result
50+
hostContext: McpUiHostContext | null; // Theme, viewport, locale
51+
callServerTool: App["callServerTool"]; // Call MCP server tools
52+
sendMessage: App["sendMessage"]; // Send chat messages
53+
sendOpenLink: App["sendOpenLink"]; // Open URLs in browser
54+
sendLog: App["sendLog"]; // Debug logging
55+
}
56+
```
57+
58+
### `src/threejs-app.tsx`
59+
60+
Widget component receiving all props. Uses:
61+
62+
- `toolInputs.code` - JavaScript to execute
63+
- `toolInputsPartial.code` - Streaming preview
64+
- `toolInputs.height` - Canvas height
65+
66+
### `server.ts`
67+
68+
MCP server with:
69+
70+
- `show_threejs_scene` tool linked to UI resource
71+
- `learn_threejs` documentation tool
72+
- stdio + HTTP transport support
73+
74+
## Available Three.js Globals
75+
76+
```javascript
77+
THREE; // Three.js library
78+
canvas; // Pre-created canvas
79+
(width, height); // Canvas dimensions
80+
OrbitControls; // Camera controls
81+
EffectComposer; // Post-processing
82+
RenderPass; // Render pass
83+
UnrealBloomPass; // Bloom effect
84+
```
85+
86+
## Test Input
87+
88+
Copy contents of `test-input.json` to test in basic-host (`http://localhost:8080`).
89+
90+
## Example Code
91+
92+
```javascript
93+
const scene = new THREE.Scene();
94+
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 100);
95+
camera.position.set(2, 2, 2);
96+
97+
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
98+
renderer.setSize(width, height);
99+
renderer.shadowMap.enabled = true;
100+
101+
const cube = new THREE.Mesh(
102+
new THREE.BoxGeometry(),
103+
new THREE.MeshStandardMaterial({ color: 0x00ff88 }),
104+
);
105+
cube.castShadow = true;
106+
cube.position.y = 0.5;
107+
scene.add(cube);
108+
109+
const floor = new THREE.Mesh(
110+
new THREE.PlaneGeometry(5, 5),
111+
new THREE.MeshStandardMaterial({ color: 0x222233 }),
112+
);
113+
floor.rotation.x = -Math.PI / 2;
114+
floor.receiveShadow = true;
115+
scene.add(floor);
116+
117+
const light = new THREE.DirectionalLight(0xffffff, 2);
118+
light.position.set(3, 5, 3);
119+
light.castShadow = true;
120+
scene.add(light);
121+
scene.add(new THREE.AmbientLight(0x404040));
122+
123+
function animate() {
124+
requestAnimationFrame(animate);
125+
cube.rotation.y += 0.01;
126+
renderer.render(scene, camera);
127+
}
128+
animate();
129+
```
130+
131+
## Creating a New Widget
132+
133+
1. Copy this example
134+
2. Rename `threejs-app.tsx` to your widget name
135+
3. Define your `ToolInput` interface
136+
4. Implement your widget using the `WidgetProps`
137+
5. Update `server.ts` with your tools
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Three.js Widget</title>
7+
<link rel="stylesheet" href="/src/global.css">
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/mcp-app-wrapper.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "threejs-server",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"build": "INPUT=mcp-app.html vite build",
8+
"watch": "INPUT=mcp-app.html vite build --watch",
9+
"serve": "bun server.ts",
10+
"start": "NODE_ENV=development npm run build && npm run serve",
11+
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
12+
},
13+
"dependencies": {
14+
"@modelcontextprotocol/ext-apps": "../..",
15+
"@modelcontextprotocol/sdk": "^1.22.0",
16+
"react": "^19.2.0",
17+
"react-dom": "^19.2.0",
18+
"three": "^0.181.0",
19+
"zod": "^3.25.0"
20+
},
21+
"devDependencies": {
22+
"@types/cors": "^2.8.19",
23+
"@types/express": "^5.0.0",
24+
"@types/node": "^22.0.0",
25+
"@types/react": "^19.2.2",
26+
"@types/react-dom": "^19.2.2",
27+
"@types/three": "^0.181.0",
28+
"@vitejs/plugin-react": "^4.3.4",
29+
"concurrently": "^9.2.1",
30+
"cors": "^2.8.5",
31+
"express": "^5.1.0",
32+
"typescript": "^5.9.3",
33+
"vite": "^6.0.0",
34+
"vite-plugin-singlefile": "^2.3.0"
35+
}
36+
}

0 commit comments

Comments
 (0)