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 +2 -2
- package/dist/templates/apps-sdk/index.ts +38 -0
- package/dist/templates/{apps-sdk-demo → apps-sdk}/package.json +18 -17
- package/dist/templates/apps-sdk/resources/display-weather.tsx +89 -0
- package/dist/templates/apps-sdk/styles.css +12 -0
- package/dist/templates/{ui-resource → apps-sdk}/tsconfig.json +7 -2
- package/dist/templates/{ui-resource → mcp-ui}/README.md +3 -3
- package/dist/templates/{ui-resource/src/server.ts → mcp-ui/index.ts} +15 -42
- package/dist/templates/{ui-resource → mcp-ui}/package.json +7 -14
- package/dist/templates/{ui-resource → mcp-ui}/resources/kanban-board.tsx +1 -7
- package/dist/templates/{apps-sdk-demo → mcp-ui}/tsconfig.json +7 -2
- package/dist/templates/starter/index.ts +96 -7
- package/dist/templates/starter/package.json +7 -14
- package/dist/templates/starter/resources/display-weather.tsx +89 -0
- package/dist/templates/starter/resources/kanban-board.tsx +1 -7
- package/dist/templates/starter/styles.css +12 -0
- package/dist/templates/starter/tsconfig.json +6 -2
- package/package.json +3 -4
- package/dist/templates/apps-sdk-demo/README.md +0 -398
- package/dist/templates/apps-sdk-demo/index.ts +0 -11
- package/dist/templates/apps-sdk-demo/src/server.ts +0 -239
- package/dist/templates/apps-sdk-demo/src/widgets.ts +0 -153
- package/dist/templates/starter/src/remoteDom/index.ts +0 -93
- package/dist/templates/starter/src/server.ts +0 -195
- package/dist/templates/ui-resource/index.ts +0 -12
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
|
|
355
|
-
console.log('\u{1F4A1} Tip: Use "apps-sdk
|
|
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": "
|
|
2
|
+
"name": "Weather App",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"version": "1.0.0",
|
|
5
|
-
"description": "MCP server with
|
|
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
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
11
|
+
"starter",
|
|
12
|
+
"tools",
|
|
13
|
+
"resources",
|
|
14
|
+
"prompts",
|
|
15
|
+
"uiresource",
|
|
16
|
+
"ui",
|
|
17
|
+
"react",
|
|
14
18
|
"widgets",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
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
|
-
"
|
|
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/
|
|
36
|
-
"@types/
|
|
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**: `
|
|
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: `
|
|
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('
|
|
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
|
-
*
|
|
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 (
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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:
|
|
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:
|
|
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:
|
|
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('
|
|
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('
|
|
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/
|
|
35
|
-
"@types/
|
|
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
|
-
|
|
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
|
-
*
|
|
12
|
+
* Define UI Widgets
|
|
13
|
+
* All React components in the `resources/` folder
|
|
14
|
+
* are automatically registered as MCP tools and resources.
|
|
3
15
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
-
*
|
|
9
|
-
*
|
|
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
|
-
|
|
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/
|
|
38
|
-
"@types/
|
|
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
|
}
|