create-mcp-use-app 0.4.4-canary.0 → 0.4.4

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
@@ -303,8 +303,9 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
303
303
  } else {
304
304
  console.log("No templates directory found");
305
305
  }
306
- console.log('\u{1F4A1} Tip: Use "ui" template for React components and modern UI features');
307
- console.log('\u{1F4A1} Tip: Use "uiresource" template for UI resources and advanced server examples');
306
+ console.log('\u{1F4A1} Tip: Use "starter" template for a comprehensive MCP server with all features');
307
+ console.log('\u{1F4A1} Tip: Use "ui-resource" template for a MCP server with mcp-ui resources');
308
+ console.log('\u{1F4A1} Tip: Use "apps-sdk-demo" template for a MCP server with OpenAI Apps SDK integration');
308
309
  process.exit(1);
309
310
  }
310
311
  copyDirectoryWithProcessing(templatePath, projectPath, versions, isDevelopment, useCanary);
@@ -359,12 +360,21 @@ async function promptForProjectName() {
359
360
  }
360
361
  async function promptForTemplate() {
361
362
  const templatesDir = join(__dirname, "templates");
362
- const availableTemplates = existsSync(templatesDir) ? readdirSync(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort() : ["simple", "ui", "uiresource"];
363
- const templateDescriptions = {
364
- "simple": "Simple MCP server with a basic calculator tool (add numbers)",
365
- "ui": "MCP Server with mcp-ui resources returned from tools",
366
- "uiresource": "MCP Server with mcp-ui resources"
367
- };
363
+ const availableTemplates = readdirSync(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
364
+ const templateDescriptions = {};
365
+ for (const template2 of availableTemplates) {
366
+ const packageJsonPath = join(templatesDir, template2, "package.json");
367
+ if (existsSync(packageJsonPath)) {
368
+ try {
369
+ const packageJson2 = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
370
+ templateDescriptions[template2] = packageJson2.description || "MCP server template";
371
+ } catch (error) {
372
+ templateDescriptions[template2] = "MCP server template";
373
+ }
374
+ } else {
375
+ templateDescriptions[template2] = "MCP server template";
376
+ }
377
+ }
368
378
  const { template } = await inquirer.prompt([
369
379
  {
370
380
  type: "list",
@@ -363,7 +363,7 @@ console.log('Resource:', resource)
363
363
  ## 📂 Project Structure
364
364
 
365
365
  ```
366
- apps_sdk/
366
+ apps-sdk/
367
367
  ├── index.ts # Entry point
368
368
  ├── package.json # Dependencies
369
369
  ├── tsconfig.json # TypeScript config
@@ -151,30 +151,3 @@ export function getPizzazWidgetsSummary() {
151
151
  }))
152
152
  }
153
153
 
154
- /**
155
- * Create widget metadata for a specific widget
156
- */
157
- export function widgetMeta(widget: PizzazWidgetDefinition) {
158
- return {
159
- 'openai/outputTemplate': widget.templateUri,
160
- 'openai/toolInvocation/invoking': widget.invoking,
161
- 'openai/toolInvocation/invoked': widget.invoked,
162
- 'openai/widgetAccessible': true,
163
- 'openai/resultCanProduceWidget': true
164
- } as const
165
- }
166
-
167
- /**
168
- * Get widget by ID
169
- */
170
- export function getWidgetById(id: string): PizzazWidgetDefinition | undefined {
171
- return pizzazWidgets.find(w => w.id === id)
172
- }
173
-
174
- /**
175
- * Get widget by template URI
176
- */
177
- export function getWidgetByUri(uri: string): PizzazWidgetDefinition | undefined {
178
- return pizzazWidgets.find(w => w.templateUri === uri)
179
- }
180
-
@@ -0,0 +1,557 @@
1
+ # MCP Starter Server
2
+
3
+ A comprehensive MCP server template with examples of tools, resources, prompts, and all UIResource types.
4
+
5
+ > 📚 **[View Full Documentation](https://docs.mcp-use.com/typescript/getting-started/quickstart)** - Complete guides, API references, and tutorials
6
+
7
+ ## Features
8
+
9
+ - **🛠️ Tools**: Regular MCP tools and API integrations
10
+ - **📦 Resources**: Static and dynamic resources
11
+ - **📝 Prompts**: Reusable prompt templates
12
+ - **🎨 UIResources**: Three types of interactive widgets
13
+ - External URL (React iframe widgets)
14
+ - Remote DOM (MCP-UI components)
15
+ - Apps SDK (OpenAI ChatGPT compatible)
16
+ - **🔥 Hot Reload**: Development server with auto-reload
17
+ - **🔍 Inspector UI**: Built-in testing interface
18
+ - **✅ TypeScript**: Full type safety
19
+
20
+ ## What's Included
21
+
22
+ This starter template demonstrates all major MCP features:
23
+
24
+ ### 1. Traditional Tools
25
+
26
+ ```typescript
27
+ server.tool({
28
+ name: 'greet',
29
+ description: 'Greet someone by name',
30
+ inputs: [{ name: 'name', type: 'string', required: true }],
31
+ cb: async ({ name }) => {
32
+ return { content: [{ type: 'text', text: `Hello, ${name}!` }] }
33
+ },
34
+ })
35
+ ```
36
+
37
+ ### 2. Resources
38
+
39
+ ```typescript
40
+ server.resource({
41
+ name: 'config',
42
+ uri: 'config://settings',
43
+ mimeType: 'application/json',
44
+ readCallback: async () => ({
45
+ /* ... */
46
+ }),
47
+ })
48
+ ```
49
+
50
+ ### 3. Prompts
51
+
52
+ ```typescript
53
+ server.prompt({
54
+ name: 'review-code',
55
+ description: 'Review code for best practices',
56
+ args: [{ name: 'code', type: 'string', required: true }],
57
+ cb: async ({ code }) => {
58
+ /* ... */
59
+ },
60
+ })
61
+ ```
62
+
63
+ ### 4. UIResources (3 Types)
64
+
65
+ #### A. External URL (Iframe Widget)
66
+
67
+ React components served from your filesystem:
68
+
69
+ ```typescript
70
+ server.uiResource({
71
+ type: 'externalUrl',
72
+ name: 'kanban-board',
73
+ widget: 'kanban-board',
74
+ title: 'Kanban Board',
75
+ props: {
76
+ /* ... */
77
+ },
78
+ })
79
+ ```
80
+
81
+ #### B. Remote DOM (MCP-UI Components)
82
+
83
+ Lightweight widgets using MCP-UI React components:
84
+
85
+ ```typescript
86
+ server.uiResource({
87
+ type: 'remoteDom',
88
+ name: 'quick-poll',
89
+ script: `/* Remote DOM script */`,
90
+ framework: 'react',
91
+ props: {
92
+ /* ... */
93
+ },
94
+ })
95
+ ```
96
+
97
+ #### C. Apps SDK (ChatGPT Compatible)
98
+
99
+ OpenAI Apps SDK widgets for ChatGPT integration:
100
+
101
+ ```typescript
102
+ server.uiResource({
103
+ type: 'appsSdk',
104
+ name: 'pizzaz-map-apps-sdk',
105
+ htmlTemplate: `<div id="pizzaz-root"></div>`,
106
+ appsSdkMetadata: {
107
+ /* OpenAI metadata */
108
+ },
109
+ })
110
+ ```
111
+
112
+ ## Getting Started
113
+
114
+ ### Installation
115
+
116
+ ```bash
117
+ # Install dependencies
118
+ npm install
119
+ ```
120
+
121
+ ### Development
122
+
123
+ ```bash
124
+ # Start development server with hot reloading
125
+ npm run dev
126
+ ```
127
+
128
+ This starts:
129
+
130
+ - MCP server on port 3000
131
+ - Widget serving at `/mcp-use/widgets/*`
132
+ - Inspector UI at `/inspector`
133
+
134
+ ### Production
135
+
136
+ ```bash
137
+ # Build the server and widgets
138
+ npm run build
139
+
140
+ # Run the built server
141
+ npm start
142
+ ```
143
+
144
+ ## Project Structure
145
+
146
+ ```
147
+ starter/
148
+ ├── src/
149
+ │ ├── server.ts # Main server configuration
150
+ │ └── remoteDom/ # Remote DOM scripts
151
+ │ └── index.ts # Quick poll script
152
+ ├── resources/ # React widget components (root level!)
153
+ │ └── kanban-board.tsx
154
+ ├── index.ts # Entry point
155
+ ├── package.json
156
+ ├── tsconfig.json
157
+ └── README.md
158
+ ```
159
+
160
+ ## Available Tools
161
+
162
+ ### `greet`
163
+
164
+ Simple greeting tool demonstrating basic tool structure.
165
+
166
+ ```typescript
167
+ await client.callTool('greet', { name: 'Alice' })
168
+ // Returns: "Hello, Alice! Welcome to MCP."
169
+ ```
170
+
171
+ ### `fetch-weather`
172
+
173
+ Demonstrates async operations and external API calls.
174
+
175
+ ```typescript
176
+ await client.callTool('fetch-weather', { city: 'London' })
177
+ // Returns: Weather information from wttr.in
178
+ ```
179
+
180
+ ### `ui_kanban-board`
181
+
182
+ Interactive Kanban board widget (External URL).
183
+
184
+ ```typescript
185
+ await client.callTool('ui_kanban-board', {
186
+ initialTasks: [{ id: '1', title: 'Task 1' /* ... */ }],
187
+ theme: 'dark',
188
+ })
189
+ ```
190
+
191
+ ### `ui_quick-poll`
192
+
193
+ Quick polling widget (Remote DOM).
194
+
195
+ ```typescript
196
+ await client.callTool('ui_quick-poll', {
197
+ question: 'Favorite framework?',
198
+ options: ['React', 'Vue', 'Svelte'],
199
+ })
200
+ ```
201
+
202
+ ### `ui_pizzaz-map-apps-sdk`
203
+
204
+ Pizza location map (Apps SDK).
205
+
206
+ ```typescript
207
+ await client.callTool('ui_pizzaz-map-apps-sdk', {
208
+ pizzaTopping: 'pepperoni',
209
+ })
210
+ ```
211
+
212
+ ## Available Resources
213
+
214
+ ### `config://settings`
215
+
216
+ Server configuration resource.
217
+
218
+ ```typescript
219
+ await client.readResource('config://settings')
220
+ ```
221
+
222
+ ### `ui://widget/kanban-board`
223
+
224
+ Static Kanban board widget with defaults.
225
+
226
+ ```typescript
227
+ await client.readResource('ui://widget/kanban-board')
228
+ ```
229
+
230
+ ### `ui://widget/quick-poll`
231
+
232
+ Static quick poll widget with defaults.
233
+
234
+ ```typescript
235
+ await client.readResource('ui://widget/quick-poll')
236
+ ```
237
+
238
+ ### `ui://widget/pizzaz-map-apps-sdk`
239
+
240
+ Static pizza map widget.
241
+
242
+ ```typescript
243
+ await client.readResource('ui://widget/pizzaz-map-apps-sdk')
244
+ ```
245
+
246
+ ## Available Prompts
247
+
248
+ ### `review-code`
249
+
250
+ Code review prompt template.
251
+
252
+ ```typescript
253
+ await client.getPrompt('review-code', { code: 'const x = 1;' })
254
+ ```
255
+
256
+ ## Customization Guide
257
+
258
+ ### Adding New Tools
259
+
260
+ 1. Add to `src/server.ts`:
261
+
262
+ ```typescript
263
+ server.tool({
264
+ name: 'my-tool',
265
+ description: 'My custom tool',
266
+ inputs: [{ name: 'param', type: 'string', required: true }],
267
+ cb: async ({ param }) => {
268
+ // Your logic here
269
+ return {
270
+ content: [{ type: 'text', text: `Result: ${param}` }],
271
+ }
272
+ },
273
+ })
274
+ ```
275
+
276
+ ### Adding New React Widgets
277
+
278
+ 1. Create widget in `resources/my-widget.tsx` (at root level):
279
+
280
+ ```tsx
281
+ import React from 'react'
282
+ import { createRoot } from 'react-dom/client'
283
+
284
+ const MyWidget: React.FC = () => {
285
+ return <div>My Widget</div>
286
+ }
287
+
288
+ const container = document.getElementById('widget-root')
289
+ if (container) {
290
+ createRoot(container).render(<MyWidget />)
291
+ }
292
+ ```
293
+
294
+ 2. Register in `src/server.ts`:
295
+
296
+ ```typescript
297
+ server.uiResource({
298
+ type: 'externalUrl',
299
+ name: 'my-widget',
300
+ widget: 'my-widget',
301
+ title: 'My Widget',
302
+ description: 'My custom widget',
303
+ })
304
+ ```
305
+
306
+ ### Adding Remote DOM Widgets
307
+
308
+ 1. Create script in `src/remoteDom/my-script.ts`:
309
+
310
+ ```typescript
311
+ export const myScript = `
312
+ const container = document.createElement('ui-stack');
313
+ container.setAttribute('direction', 'column');
314
+
315
+ const text = document.createElement('ui-text');
316
+ text.textContent = 'Hello from Remote DOM!';
317
+ container.appendChild(text);
318
+
319
+ root.appendChild(container);
320
+ `
321
+ ```
322
+
323
+ 2. Register in `src/server.ts`:
324
+
325
+ ```typescript
326
+ import { myScript } from './remoteDom/my-script'
327
+
328
+ server.uiResource({
329
+ type: 'remoteDom',
330
+ name: 'my-remote-widget',
331
+ script: myScript,
332
+ framework: 'react',
333
+ encoding: 'text',
334
+ })
335
+ ```
336
+
337
+ ### Adding Resources
338
+
339
+ ```typescript
340
+ server.resource({
341
+ name: 'my-resource',
342
+ uri: 'custom://my-data',
343
+ mimeType: 'application/json',
344
+ description: 'My custom resource',
345
+ readCallback: async () => ({
346
+ contents: [
347
+ {
348
+ uri: 'custom://my-data',
349
+ mimeType: 'application/json',
350
+ text: JSON.stringify({ data: 'value' }),
351
+ },
352
+ ],
353
+ }),
354
+ })
355
+ ```
356
+
357
+ ### Adding Prompts
358
+
359
+ ```typescript
360
+ server.prompt({
361
+ name: 'my-prompt',
362
+ description: 'My custom prompt',
363
+ args: [{ name: 'input', type: 'string', required: true }],
364
+ cb: async ({ input }) => ({
365
+ content: [
366
+ {
367
+ type: 'text',
368
+ text: `Process this input: ${input}`,
369
+ },
370
+ ],
371
+ }),
372
+ })
373
+ ```
374
+
375
+ ## Testing Your Server
376
+
377
+ ### Using the Inspector UI
378
+
379
+ 1. Start the server: `npm run dev`
380
+ 2. Open: `http://localhost:3000/inspector`
381
+ 3. Test tools, resources, and prompts interactively
382
+
383
+ ### Direct Browser Access
384
+
385
+ For External URL widgets:
386
+
387
+ ```
388
+ http://localhost:3000/mcp-use/widgets/kanban-board
389
+ ```
390
+
391
+ ### Via MCP Client
392
+
393
+ ```typescript
394
+ import { createMCPClient } from 'mcp-use/client'
395
+
396
+ const client = createMCPClient({
397
+ serverUrl: 'http://localhost:3000/mcp',
398
+ })
399
+
400
+ await client.connect()
401
+
402
+ // Test tools
403
+ const result = await client.callTool('greet', { name: 'World' })
404
+
405
+ // Test resources
406
+ const config = await client.readResource('config://settings')
407
+
408
+ // Test prompts
409
+ const prompt = await client.getPrompt('review-code', { code: '...' })
410
+ ```
411
+
412
+ ## UIResource Types Comparison
413
+
414
+ | Type | Use Case | Complexity | Features |
415
+ | ---------------- | ------------------- | ---------- | --------------------------------- |
416
+ | **External URL** | Complex React apps | High | Full React, npm packages, routing |
417
+ | **Remote DOM** | Lightweight widgets | Low | MCP-UI components only |
418
+ | **Apps SDK** | ChatGPT integration | Medium | OpenAI ecosystem compatibility |
419
+
420
+ ### When to Use Each
421
+
422
+ - **External URL**: Complex interactive UIs (dashboards, forms, games)
423
+ - **Remote DOM**: Simple widgets (buttons, cards, polls)
424
+ - **Apps SDK**: ChatGPT-specific integrations
425
+
426
+ ## Environment Variables
427
+
428
+ ```bash
429
+ PORT=3000 # Server port (default: 3000)
430
+ ```
431
+
432
+ ## Build Output
433
+
434
+ After running `npm run build`:
435
+
436
+ ```
437
+ dist/
438
+ ├── index.js # Entry point
439
+ ├── src/
440
+ │ ├── server.js # Compiled server
441
+ │ └── remoteDom/
442
+ │ └── index.js
443
+ └── resources/
444
+ └── mcp-use/
445
+ └── widgets/
446
+ └── kanban-board/
447
+ └── index.html
448
+ ```
449
+
450
+ ## Troubleshooting
451
+
452
+ ### Widget Not Loading
453
+
454
+ - Ensure `tsconfig.json` has `"jsx": "react-jsx"`
455
+ - Check `src/resources/` contains your widget file
456
+ - Verify widget is built in `dist/resources/mcp-use/widgets/`
457
+ - Check browser console for errors
458
+
459
+ ### Props Not Passed to Widget
460
+
461
+ - Widgets receive props as URL query parameters
462
+ - Parse them in `useEffect` with `URLSearchParams`
463
+ - Complex objects are JSON-stringified
464
+
465
+ ### Build Errors
466
+
467
+ ```bash
468
+ # Clean build
469
+ rm -rf dist node_modules
470
+ npm install
471
+ npm run build
472
+ ```
473
+
474
+ ### Port Already in Use
475
+
476
+ ```bash
477
+ # Change port
478
+ PORT=3001 npm run dev
479
+ ```
480
+
481
+ ## Examples
482
+
483
+ ### Complete Weather Widget
484
+
485
+ 1. **Create widget** (`resources/weather.tsx`):
486
+
487
+ ```tsx
488
+ import React, { useEffect, useState } from 'react'
489
+ import { createRoot } from 'react-dom/client'
490
+
491
+ const Weather: React.FC = () => {
492
+ const [city, setCity] = useState('London')
493
+ const [weather, setWeather] = useState(null)
494
+
495
+ useEffect(() => {
496
+ const params = new URLSearchParams(window.location.search)
497
+ const cityParam = params.get('city')
498
+ if (cityParam) setCity(cityParam)
499
+ }, [])
500
+
501
+ useEffect(() => {
502
+ fetch(`https://wttr.in/${city}?format=j1`)
503
+ .then((r) => r.json())
504
+ .then(setWeather)
505
+ }, [city])
506
+
507
+ if (!weather) return <div>Loading...</div>
508
+
509
+ return (
510
+ <div style={{ padding: 20 }}>
511
+ <h1>Weather in {city}</h1>
512
+ <p>{weather.current_condition[0].temp_C}°C</p>
513
+ </div>
514
+ )
515
+ }
516
+
517
+ const container = document.getElementById('widget-root')
518
+ if (container) createRoot(container).render(<Weather />)
519
+ ```
520
+
521
+ 2. **Register** (`src/server.ts`):
522
+
523
+ ```typescript
524
+ server.uiResource({
525
+ type: 'externalUrl',
526
+ name: 'weather-widget',
527
+ widget: 'weather',
528
+ title: 'Weather Widget',
529
+ props: {
530
+ city: { type: 'string', default: 'London' },
531
+ },
532
+ })
533
+ ```
534
+
535
+ 3. **Use**:
536
+
537
+ ```typescript
538
+ await client.callTool('ui_weather-widget', { city: 'Paris' })
539
+ ```
540
+
541
+ ## Learn More
542
+
543
+ - [MCP Documentation](https://modelcontextprotocol.io)
544
+ - [MCP-UI Documentation](https://github.com/idosal/mcp-ui)
545
+ - [mcp-use Documentation](https://github.com/pyroprompt/mcp-use)
546
+ - [React Documentation](https://react.dev/)
547
+ - [OpenAI Apps SDK](https://platform.openai.com/docs/apps)
548
+
549
+ ## License
550
+
551
+ MIT
552
+
553
+ ---
554
+
555
+ > 📚 **[View Full Documentation](https://docs.mcp-use.com/typescript/getting-started/quickstart)** - For more guides and advanced features
556
+
557
+ Happy building! 🚀
@@ -1,18 +1,23 @@
1
1
  {
2
- "name": "mcp-use-server-with-mcp-ui",
2
+ "name": "mcp-use-starter-server",
3
3
  "type": "module",
4
4
  "version": "1.0.0",
5
- "description": "MCP server: mcp-use-server-with-mcp-ui",
5
+ "description": "MCP server with starter tools and resources",
6
6
  "author": "",
7
7
  "license": "MIT",
8
8
  "keywords": [
9
9
  "mcp",
10
10
  "server",
11
+ "starter",
12
+ "tools",
13
+ "resources",
14
+ "prompts",
15
+ "uiresource",
11
16
  "ui",
12
17
  "react",
13
18
  "widgets",
14
- "ai",
15
- "tools"
19
+ "mcp-ui",
20
+ "apps-sdk"
16
21
  ],
17
22
  "main": "dist/index.js",
18
23
  "scripts": {