create-mcp-use-app 0.4.5 → 0.4.6-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -351,8 +351,8 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
351
351
  console.log("No templates directory found");
352
352
  }
353
353
  console.log('\u{1F4A1} Tip: Use "starter" template for a comprehensive MCP server with all features');
354
- console.log('\u{1F4A1} Tip: Use "ui-resource" template for a MCP server with mcp-ui resources');
355
- console.log('\u{1F4A1} Tip: Use "apps-sdk-demo" template for a MCP server with OpenAI Apps SDK integration');
354
+ console.log('\u{1F4A1} Tip: Use "mcp-ui" template for a MCP server with mcp-ui resources');
355
+ console.log('\u{1F4A1} Tip: Use "apps-sdk" template for a MCP server with OpenAI Apps SDK integration');
356
356
  process.exit(1);
357
357
  }
358
358
  copyDirectoryWithProcessing(templatePath, projectPath, versions, isDevelopment, useCanary);
@@ -0,0 +1,38 @@
1
+ import { createMCPServer } from 'mcp-use/server'
2
+
3
+ const server = createMCPServer('test-app', {
4
+ version: '1.0.0',
5
+ description: 'Test MCP server with automatic UI widget registration',
6
+ host: process.env.HOST || 'localhost',
7
+ baseUrl: process.env.MCP_URL, // Full base URL (e.g., https://myserver.com)
8
+ })
9
+
10
+ /**
11
+ * AUTOMATIC UI WIDGET REGISTRATION
12
+ * All React components in the `resources/` folder are automatically registered as MCP tools and resources.
13
+ * Just export widgetMetadata with description and Zod schema, and mcp-use handles the rest!
14
+ *
15
+ * It will automatically add to your MCP server:
16
+ * - server.tool('display-weather')
17
+ * - server.resource('ui://widget/display-weather')
18
+ *
19
+ * See docs: https://docs.mcp-use.com/typescript/server/ui-widgets
20
+ */
21
+
22
+
23
+ /**
24
+ * Add here yourtandard MCP tools, resources and prompts
25
+ */
26
+ server.tool({
27
+ name: 'get-my-city',
28
+ description: 'Get my city',
29
+ cb: async () => {
30
+ return { content: [{ type: 'text', text: `My city is San Francisco` }] }
31
+ },
32
+ })
33
+
34
+
35
+ const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000
36
+ const HOST = process.env.HOST || 'localhost'
37
+ server.listen(PORT)
38
+ console.log(`Server running at http://${HOST}:${PORT}`)
@@ -1,20 +1,23 @@
1
1
  {
2
- "name": "mcp-apps-sdk-server",
2
+ "name": "Weather App",
3
3
  "type": "module",
4
4
  "version": "1.0.0",
5
- "description": "MCP server with OpenAI Apps SDK integration using mcp-use",
5
+ "description": "MCP server with apps sdk integration",
6
6
  "author": "",
7
7
  "license": "MIT",
8
8
  "keywords": [
9
9
  "mcp",
10
10
  "server",
11
- "apps-sdk",
12
- "openai",
13
- "chatgpt",
11
+ "starter",
12
+ "tools",
13
+ "resources",
14
+ "prompts",
15
+ "uiresource",
16
+ "ui",
17
+ "react",
14
18
  "widgets",
15
- "pizzaz",
16
- "ai",
17
- "tools"
19
+ "mcp-ui",
20
+ "apps-sdk"
18
21
  ],
19
22
  "main": "dist/index.js",
20
23
  "scripts": {
@@ -23,20 +26,18 @@
23
26
  "start": "mcp-use start"
24
27
  },
25
28
  "dependencies": {
26
- "@mcp-ui/server": "^5.11.0",
27
29
  "cors": "^2.8.5",
28
30
  "express": "^4.18.0",
29
31
  "mcp-use": "workspace:*",
30
- "zod": "^3.23.0"
32
+ "react": "^19.2.0",
33
+ "react-dom": "^19.2.0",
34
+ "tailwindcss": "^4.0.0",
35
+ "zod": "^4.1.12"
31
36
  },
32
37
  "devDependencies": {
33
38
  "@mcp-use/cli": "workspace:*",
34
39
  "@mcp-use/inspector": "workspace:*",
35
- "@types/cors": "^2.8.0",
36
- "@types/express": "^4.17.0",
37
- "@types/node": "^20.0.0",
38
- "tsx": "^4.0.0",
39
- "typescript": "^5.0.0"
40
+ "@types/react": "^19.2.2",
41
+ "@types/react-dom": "^19.2.2"
40
42
  }
41
- }
42
-
43
+ }
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import { z } from 'zod';
3
+ import { useWidget } from 'mcp-use/react';
4
+ import '../styles.css';
5
+
6
+ /*
7
+ * Apps SDK widget
8
+ * Just export widgetMetadata with description and Zod schema, and mcp-use handles the rest!
9
+ * See docs: https://docs.mcp-use.com/typescript/server/ui-widgets
10
+ */
11
+
12
+ const propSchema = z.object({
13
+ city: z.string().describe('The city to display weather for'),
14
+ weather: z.enum(['sunny', 'rain', 'snow', 'cloudy']).describe('The weather condition'),
15
+ temperature: z.number().min(-20).max(50).describe('The temperature in Celsius'),
16
+ });
17
+
18
+ export const widgetMetadata = {
19
+ description: 'Display weather for a city',
20
+ inputs: propSchema,
21
+ }
22
+
23
+ type WeatherProps = z.infer<typeof propSchema>;
24
+
25
+ const WeatherWidget: React.FC = () => {
26
+ // Use the useWidget hook to get props from OpenAI Apps SDK
27
+ const { props, theme } = useWidget<WeatherProps>();
28
+
29
+ console.log(props)
30
+
31
+ const { city, weather, temperature } = props;
32
+ const getWeatherIcon = (weatherType: string) => {
33
+ switch (weatherType?.toLowerCase()) {
34
+ case 'sunny':
35
+ return '☀️';
36
+ case 'rain':
37
+ return '🌧️';
38
+ case 'snow':
39
+ return '❄️';
40
+ case 'cloudy':
41
+ return '☁️';
42
+ default:
43
+ return '🌤️';
44
+ }
45
+ };
46
+
47
+ const getWeatherColor = (weatherType: string) => {
48
+ switch (weatherType?.toLowerCase()) {
49
+ case 'sunny':
50
+ return 'from-yellow-400 to-orange-500';
51
+ case 'rain':
52
+ return 'from-blue-400 to-blue-600';
53
+ case 'snow':
54
+ return 'from-blue-100 to-blue-300';
55
+ case 'cloudy':
56
+ return 'from-gray-400 to-gray-600';
57
+ default:
58
+ return 'from-gray-300 to-gray-500';
59
+ }
60
+ };
61
+
62
+ // Theme-aware styling
63
+ const bgColor = theme === 'dark' ? 'bg-gray-900' : 'bg-white';
64
+ const textColor = theme === 'dark' ? 'text-gray-100' : 'text-gray-800';
65
+ const subtextColor = theme === 'dark' ? 'text-gray-400' : 'text-gray-600';
66
+
67
+ return (
68
+ <div className={`max-w-sm mx-auto ${bgColor} rounded-xl shadow-lg overflow-hidden`}>
69
+ <div className={`h-32 bg-gradient-to-br ${getWeatherColor(weather)} flex items-center justify-center`}>
70
+ <div className="text-6xl">{getWeatherIcon(weather)}</div>
71
+ </div>
72
+
73
+ <div className="p-6">
74
+ <div className="text-center">
75
+ <h2 className={`text-2xl font-bold ${textColor} mb-2`}>{city}</h2>
76
+ <div className="flex items-center justify-center space-x-4">
77
+ <span className={`text-4xl font-light ${textColor}`}>{temperature}°</span>
78
+ <div className="text-right">
79
+ <p className={`text-lg font-medium ${subtextColor} capitalize`}>{weather}</p>
80
+ <p className={`text-sm ${subtextColor}`}>Current</p>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ };
88
+
89
+ export default WeatherWidget;
@@ -0,0 +1,12 @@
1
+ @import "tailwindcss";
2
+
3
+ /* Custom styles */
4
+ body {
5
+ margin: 0;
6
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
7
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
8
+ sans-serif;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ }
12
+
@@ -13,8 +13,13 @@
13
13
  "allowSyntheticDefaultImports": true,
14
14
  "esModuleInterop": true,
15
15
  "forceConsistentCasingInFileNames": true,
16
- "skipLibCheck": true
16
+ "skipLibCheck": true,
17
+ "baseUrl": ".",
18
+ "paths": {
19
+ "@/*": ["src/*"]
20
+ }
17
21
  },
18
- "include": ["index.ts", "src/**/*", "resources/**/*"],
22
+ "include": ["index.ts", "src/**/*", "resources/**/*", "server.ts"],
19
23
  "exclude": ["node_modules", "dist"]
20
24
  }
25
+
@@ -38,7 +38,7 @@ server.uiResource({
38
38
 
39
39
  This automatically creates:
40
40
 
41
- - **Tool**: `ui_kanban-board` - Accepts parameters and returns UIResource
41
+ - **Tool**: `kanban-board` - Accepts parameters and returns UIResource
42
42
  - **Resource**: `ui://widget/kanban-board` - Static access with defaults
43
43
 
44
44
  ## Getting Started
@@ -205,7 +205,7 @@ server.uiResource({
205
205
 
206
206
  When you call `uiResource`, it automatically creates a tool:
207
207
 
208
- - Name: `ui_[widget-name]`
208
+ - Name: `[widget-name]`
209
209
  - Accepts all props as parameters
210
210
  - Returns both text description and UIResource object
211
211
 
@@ -323,7 +323,7 @@ Visit: `http://localhost:3000/mcp-use/widgets/[widget-name]`
323
323
 
324
324
  ```typescript
325
325
  // Call as tool
326
- const result = await client.callTool('ui_kanban-board', {
326
+ const result = await client.callTool('kanban-board', {
327
327
  initialTasks: [...],
328
328
  theme: 'dark'
329
329
  })
@@ -1,11 +1,10 @@
1
1
  import { createMCPServer } from 'mcp-use/server'
2
2
  import type {
3
- ExternalUrlUIResource,
4
3
  RawHtmlUIResource,
5
4
  RemoteDomUIResource
6
5
  } from 'mcp-use/server'
7
6
 
8
- // Create an MCP server with UIResource support
7
+ // Create an MCP server with MCP-UI UIResource support
9
8
  const server = createMCPServer('uiresource-mcp-server', {
10
9
  version: '1.0.0',
11
10
  description: 'MCP server demonstrating all UIResource types',
@@ -15,42 +14,18 @@ const PORT = process.env.PORT || 3000
15
14
 
16
15
  /**
17
16
  * ════════════════════════════════════════════════════════════════════
18
- * Type 1: External URL (Iframe Widget)
17
+ * Type 1: External URL (Iframe Widget from `resources/`)
19
18
  * ════════════════════════════════════════════════════════════════════
20
19
  *
21
20
  * Serves a widget from your local filesystem via iframe.
22
- * Best for: Complex interactive widgets with their own assets
21
+ * All React components in the `resources/` folder are automatically registered as MCP tools and resources.
23
22
  *
24
23
  * This automatically:
25
- * 1. Creates a tool (ui_kanban-board) that accepts parameters
24
+ * 1. Creates a tool (kanban-board) that accepts parameters
26
25
  * 2. Creates a resource (ui://widget/kanban-board) for static access
27
26
  * 3. Serves the widget from dist/resources/mcp-use/widgets/kanban-board/
28
27
  */
29
- server.uiResource({
30
- type: 'externalUrl',
31
- name: 'kanban-board',
32
- widget: 'kanban-board',
33
- title: 'Kanban Board',
34
- description: 'Interactive task management board with drag-and-drop support',
35
- props: {
36
- initialTasks: {
37
- type: 'array',
38
- description: 'Initial tasks to display on the board',
39
- required: false,
40
- },
41
- theme: {
42
- type: 'string',
43
- description: 'Visual theme for the board (light/dark)',
44
- required: false,
45
- default: 'light'
46
- },
47
- columns: {
48
- type: 'array',
49
- description: 'Column configuration for the board',
50
- required: false,
51
- }
52
- }
53
- } satisfies ExternalUrlUIResource)
28
+
54
29
 
55
30
  /**
56
31
  * ════════════════════════════════════════════════════════════════════
@@ -58,10 +33,9 @@ server.uiResource({
58
33
  * ════════════════════════════════════════════════════════════════════
59
34
  *
60
35
  * Renders HTML content directly without an iframe.
61
- * Best for: Simple visualizations, status displays, formatted text
62
36
  *
63
37
  * This creates:
64
- * - Tool: ui_welcome-card
38
+ * - Tool: welcome-card
65
39
  * - Resource: ui://widget/welcome-card
66
40
  */
67
41
  server.uiResource({
@@ -157,10 +131,9 @@ server.uiResource({
157
131
  * ════════════════════════════════════════════════════════════════════
158
132
  *
159
133
  * Uses Remote DOM to render interactive components.
160
- * Best for: Lightweight interactive UIs using MCP-UI React components
161
134
  *
162
135
  * This creates:
163
- * - Tool: ui_quick-poll
136
+ * - Tool: quick-poll
164
137
  * - Resource: ui://widget/quick-poll
165
138
  */
166
139
  server.uiResource({
@@ -294,20 +267,20 @@ server.tool({
294
267
  {
295
268
  name: 'kanban-board',
296
269
  type: 'externalUrl',
297
- tool: 'ui_kanban-board',
270
+ tool: 'kanban-board',
298
271
  resource: 'ui://widget/kanban-board',
299
272
  url: `http://localhost:${PORT}/mcp-use/widgets/kanban-board`
300
273
  },
301
274
  {
302
275
  name: 'welcome-card',
303
276
  type: 'rawHtml',
304
- tool: 'ui_welcome-card',
277
+ tool: 'welcome-card',
305
278
  resource: 'ui://widget/welcome-card'
306
279
  },
307
280
  {
308
281
  name: 'quick-poll',
309
282
  type: 'remoteDom',
310
- tool: 'ui_quick-poll',
283
+ tool: 'quick-poll',
311
284
  resource: 'ui://widget/quick-poll'
312
285
  }
313
286
  ]
@@ -382,24 +355,24 @@ Server is running on port ${PORT}
382
355
 
383
356
  1️⃣ External URL Widget (Iframe)
384
357
  • kanban-board
385
- Tool: ui_kanban-board
358
+ Tool: kanban-board
386
359
  Resource: ui://widget/kanban-board
387
360
  Browser: http://localhost:${PORT}/mcp-use/widgets/kanban-board
388
361
 
389
362
  2️⃣ Raw HTML Widget (Direct Rendering)
390
363
  • welcome-card
391
- Tool: ui_welcome-card
364
+ Tool: welcome-card
392
365
  Resource: ui://widget/welcome-card
393
366
 
394
367
  3️⃣ Remote DOM Widget (React Components)
395
368
  • quick-poll
396
- Tool: ui_quick-poll
369
+ Tool: quick-poll
397
370
  Resource: ui://widget/quick-poll
398
371
 
399
372
  📝 Usage Examples:
400
373
 
401
374
  // External URL - Call with dynamic parameters
402
- await client.callTool('ui_kanban-board', {
375
+ await client.callTool('kanban-board', {
403
376
  initialTasks: [{id: 1, title: 'Task 1'}],
404
377
  theme: 'dark'
405
378
  })
@@ -408,7 +381,7 @@ Server is running on port ${PORT}
408
381
  await client.readResource('ui://widget/welcome-card')
409
382
 
410
383
  // Remote DOM - Interactive component
411
- await client.callTool('ui_quick-poll', {
384
+ await client.callTool('quick-poll', {
412
385
  question: 'Favorite color?',
413
386
  options: ['Red', 'Blue', 'Green']
414
387
  })
@@ -23,25 +23,18 @@
23
23
  "start": "mcp-use start"
24
24
  },
25
25
  "dependencies": {
26
- "@mcp-ui/server": "^5.11.0",
27
26
  "cors": "^2.8.5",
28
27
  "express": "^4.18.0",
29
- "mcp-use": "workspace:*"
28
+ "mcp-use": "workspace:*",
29
+ "react": "^19.2.0",
30
+ "react-dom": "^19.2.0",
31
+ "tailwindcss": "^4.0.0",
32
+ "zod": "^4.1.12"
30
33
  },
31
34
  "devDependencies": {
32
35
  "@mcp-use/cli": "workspace:*",
33
36
  "@mcp-use/inspector": "workspace:*",
34
- "@types/cors": "^2.8.0",
35
- "@types/express": "^4.17.0",
36
- "@types/node": "^20.0.0",
37
- "@types/react": "^18.0.0",
38
- "@types/react-dom": "^18.0.0",
39
- "concurrently": "^8.0.0",
40
- "esbuild": "^0.23.0",
41
- "globby": "^14.0.2",
42
- "react": "^18.0.0",
43
- "react-dom": "^18.0.0",
44
- "tsx": "^4.0.0",
45
- "typescript": "^5.0.0"
37
+ "@types/react": "^19.2.2",
38
+ "@types/react-dom": "^19.2.2"
46
39
  }
47
40
  }
@@ -1,5 +1,4 @@
1
1
  import React, { useEffect, useState } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
2
 
4
3
  interface Task {
5
4
  id: string
@@ -298,9 +297,4 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
298
297
  )
299
298
  }
300
299
 
301
- // Mount the component
302
- const container = document.getElementById('widget-root')
303
- if (container) {
304
- const root = createRoot(container)
305
- root.render(<KanbanBoard />)
306
- }
300
+ export default KanbanBoard
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2022",
4
+ "jsx": "react-jsx",
4
5
  "module": "ESNext",
5
6
  "moduleResolution": "bundler",
6
7
  "allowJs": true,
@@ -12,9 +13,13 @@
12
13
  "allowSyntheticDefaultImports": true,
13
14
  "esModuleInterop": true,
14
15
  "forceConsistentCasingInFileNames": true,
15
- "skipLibCheck": true
16
+ "skipLibCheck": true,
17
+ "baseUrl": ".",
18
+ "paths": {
19
+ "@/*": ["src/*"]
20
+ }
16
21
  },
17
- "include": ["index.ts", "src/**/*"],
22
+ "include": ["index.ts", "src/**/*", "resources/**/*", "server.ts"],
18
23
  "exclude": ["node_modules", "dist"]
19
24
  }
20
25
 
@@ -1,12 +1,101 @@
1
+ import { createMCPServer } from 'mcp-use/server'
2
+
3
+
4
+ // Create MCP server instance
5
+ const server = createMCPServer('my-mcp-server', {
6
+ version: '1.0.0',
7
+ description: 'My first MCP server with all features',
8
+ })
9
+
10
+
1
11
  /**
2
- * MCP Server Entry Point
12
+ * Define UI Widgets
13
+ * All React components in the `resources/` folder
14
+ * are automatically registered as MCP tools and resources.
3
15
  *
4
- * This file serves as the main entry point for the MCP server application.
5
- * It re-exports all functionality from the server implementation, allowing
6
- * the CLI and other tools to locate and start the server.
16
+ * Just export widgetMetadata with description and Zod schema,
17
+ * and mcp-use handles the rest!
7
18
  *
8
- * The server is automatically started when this module is imported, making
9
- * it suitable for both direct execution and programmatic usage.
19
+ * It will automatically add to your MCP server:
20
+ * - server.tool('kanban-board')
21
+ * - server.tool('display-weather')
22
+ * - server.resource('ui://widget/kanban-board')
23
+ * - server.resource('ui://widget/display-weather')
24
+ *
25
+ * Docs: https://docs.mcp-use.com/typescript/server/ui-widgets
26
+ */
27
+
28
+
29
+ /*
30
+ * Define MCP tools
31
+ * Docs: https://docs.mcp-use.com/typescript/server/tools
32
+ */
33
+ server.tool({
34
+ name: 'fetch-weather',
35
+ description: 'Fetch the weather for a city',
36
+ inputs: [
37
+ { name: 'city', type: 'string', required: true }
38
+ ],
39
+ cb: async (params: Record<string, any>) => {
40
+ const city = params.city as string
41
+ const response = await fetch(`https://wttr.in/${city}?format=j1`)
42
+ const data: any = await response.json()
43
+ const current = data.current_condition[0]
44
+ return {
45
+ content: [{
46
+ type: 'text',
47
+ text: `The weather in ${city} is ${current.weatherDesc[0].value}. Temperature: ${current.temp_C}°C, Humidity: ${current.humidity}%`
48
+ }]
49
+ }
50
+ }
51
+ })
52
+
53
+
54
+ /*
55
+ * Define MCP resources
56
+ * Docs: https://docs.mcp-use.com/typescript/server/resources
10
57
  */
11
- export * from './src/server.js'
58
+ server.resource({
59
+ name: 'config',
60
+ uri: 'config://settings',
61
+ mimeType: 'application/json',
62
+ description: 'Server configuration',
63
+ readCallback: async () => ({
64
+ contents: [{
65
+ uri: 'config://settings',
66
+ mimeType: 'application/json',
67
+ text: JSON.stringify({
68
+ theme: 'dark',
69
+ language: 'en'
70
+ })
71
+ }]
72
+ })
73
+ })
74
+
75
+
76
+ /*
77
+ * Define MCP prompts
78
+ * Docs: https://docs.mcp-use.com/typescript/server/prompts
79
+ */
80
+ server.prompt({
81
+ name: 'review-code',
82
+ description: 'Review code for best practices and potential issues',
83
+ args: [
84
+ { name: 'code', type: 'string', required: true }
85
+ ],
86
+ cb: async (params: Record<string, any>) => {
87
+ const { code } = params
88
+ return {
89
+ messages: [{
90
+ role: 'user',
91
+ content: {type: 'text', text: `Please review this code:\n\n${code}`}
92
+ }]
93
+ }
94
+ }
95
+ })
96
+
12
97
 
98
+ const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3000
99
+ console.log(`Server running on port ${PORT}`)
100
+ // Start the server
101
+ server.listen(PORT)
@@ -26,25 +26,18 @@
26
26
  "start": "mcp-use start"
27
27
  },
28
28
  "dependencies": {
29
- "@mcp-ui/server": "^5.11.0",
30
29
  "cors": "^2.8.5",
31
30
  "express": "^4.18.0",
32
- "mcp-use": "workspace:*"
31
+ "mcp-use": "workspace:*",
32
+ "react": "^19.2.0",
33
+ "react-dom": "^19.2.0",
34
+ "tailwindcss": "^4.0.0",
35
+ "zod": "^4.1.12"
33
36
  },
34
37
  "devDependencies": {
35
38
  "@mcp-use/cli": "workspace:*",
36
39
  "@mcp-use/inspector": "workspace:*",
37
- "@types/cors": "^2.8.0",
38
- "@types/express": "^4.17.0",
39
- "@types/node": "^20.0.0",
40
- "@types/react": "^18.0.0",
41
- "@types/react-dom": "^18.0.0",
42
- "concurrently": "^8.0.0",
43
- "esbuild": "^0.23.0",
44
- "globby": "^14.0.2",
45
- "react": "^18.0.0",
46
- "react-dom": "^18.0.0",
47
- "tsx": "^4.0.0",
48
- "typescript": "^5.0.0"
40
+ "@types/react": "^19.2.2",
41
+ "@types/react-dom": "^19.2.2"
49
42
  }
50
43
  }