create-mcp-use-app 0.2.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.
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "test-ui",
3
+ "type": "module",
4
+ "version": "1.0.0",
5
+ "description": "MCP server: test-ui",
6
+ "author": "",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "mcp",
10
+ "server",
11
+ "ui",
12
+ "react",
13
+ "widgets",
14
+ "ai",
15
+ "tools"
16
+ ],
17
+ "main": "dist/server.js",
18
+ "scripts": {
19
+ "build": "mcp-use build",
20
+ "dev": "mcp-use dev",
21
+ "start": "mcp-use start"
22
+ },
23
+ "dependencies": {
24
+ "@mcp-ui/server": "^5.11.0",
25
+ "@mcp-use/inspector": "workspace:*",
26
+ "cors": "^2.8.5",
27
+ "express": "^4.18.0",
28
+ "mcp-use": "workspace:*"
29
+ },
30
+ "devDependencies": {
31
+ "@mcp-use/cli": "workspace:*",
32
+ "@types/cors": "^2.8.0",
33
+ "@types/express": "^4.17.0",
34
+ "@types/node": "^20.0.0",
35
+ "@types/react": "^18.0.0",
36
+ "@types/react-dom": "^18.0.0",
37
+ "concurrently": "^8.0.0",
38
+ "esbuild": "^0.23.0",
39
+ "globby": "^14.0.2",
40
+ "react": "^18.0.0",
41
+ "react-dom": "^18.0.0",
42
+ "tsx": "^4.0.0",
43
+ "typescript": "^5.0.0"
44
+ }
45
+ }
@@ -0,0 +1,475 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+
4
+ interface DataPoint {
5
+ label: string
6
+ value: number
7
+ color?: string
8
+ }
9
+
10
+ interface DataVisualizationProps {
11
+ initialData?: DataPoint[]
12
+ chartType?: 'bar' | 'line' | 'pie'
13
+ }
14
+
15
+ const DataVisualization: React.FC<DataVisualizationProps> = ({
16
+ initialData = [],
17
+ chartType = 'bar',
18
+ }) => {
19
+ const [data, setData] = useState<DataPoint[]>(initialData)
20
+ const [currentChartType, setCurrentChartType] = useState<'bar' | 'line' | 'pie'>(chartType)
21
+ const [newDataPoint, setNewDataPoint] = useState({ label: '', value: 0 })
22
+
23
+ // Load data from URL parameters or use defaults
24
+ useEffect(() => {
25
+ const urlParams = new URLSearchParams(window.location.search)
26
+ const dataParam = urlParams.get('data')
27
+ const typeParam = urlParams.get('chartType')
28
+
29
+ if (dataParam) {
30
+ try {
31
+ const parsedData = JSON.parse(decodeURIComponent(dataParam))
32
+ setData(parsedData)
33
+ }
34
+ catch (error) {
35
+ console.error('Error parsing data from URL:', error)
36
+ }
37
+ }
38
+ else {
39
+ // Default data for demo
40
+ setData([
41
+ { label: 'January', value: 65, color: '#3498db' },
42
+ { label: 'February', value: 59, color: '#e74c3c' },
43
+ { label: 'March', value: 80, color: '#2ecc71' },
44
+ { label: 'April', value: 81, color: '#f39c12' },
45
+ { label: 'May', value: 56, color: '#9b59b6' },
46
+ { label: 'June', value: 55, color: '#1abc9c' },
47
+ ])
48
+ }
49
+
50
+ if (typeParam) {
51
+ setCurrentChartType(typeParam as 'bar' | 'line' | 'pie')
52
+ }
53
+ }, [])
54
+
55
+ const addDataPoint = () => {
56
+ if (newDataPoint.label.trim() && newDataPoint.value > 0) {
57
+ const colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#34495e', '#e67e22']
58
+ const newPoint: DataPoint = {
59
+ ...newDataPoint,
60
+ color: colors[data.length % colors.length],
61
+ }
62
+ setData([...data, newPoint])
63
+ setNewDataPoint({ label: '', value: 0 })
64
+ }
65
+ }
66
+
67
+ const removeDataPoint = (index: number) => {
68
+ setData(data.filter((_, i) => i !== index))
69
+ }
70
+
71
+ const getMaxValue = () => {
72
+ return Math.max(...data.map(d => d.value), 0)
73
+ }
74
+
75
+ const getTotalValue = () => {
76
+ return data.reduce((sum, d) => sum + d.value, 0)
77
+ }
78
+
79
+ const renderBarChart = () => {
80
+ const maxValue = getMaxValue()
81
+
82
+ return (
83
+ <div style={{ padding: '20px' }}>
84
+ <h3 style={{ marginBottom: '20px', color: '#2c3e50' }}>Bar Chart</h3>
85
+ <div style={{ display: 'flex', alignItems: 'end', gap: '10px', height: '300px' }}>
86
+ {data.map((point, index) => (
87
+ <div key={index} style={{ flex: '1', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
88
+ <div
89
+ style={{
90
+ background: point.color || '#3498db',
91
+ height: `${(point.value / maxValue) * 250}px`,
92
+ width: '100%',
93
+ borderRadius: '4px 4px 0 0',
94
+ transition: 'all 0.3s ease',
95
+ cursor: 'pointer',
96
+ position: 'relative',
97
+ }}
98
+ title={`${point.label}: ${point.value}`}
99
+ >
100
+ <div style={{
101
+ position: 'absolute',
102
+ top: '-25px',
103
+ left: '50%',
104
+ transform: 'translateX(-50%)',
105
+ background: 'rgba(0,0,0,0.8)',
106
+ color: 'white',
107
+ padding: '2px 6px',
108
+ borderRadius: '4px',
109
+ fontSize: '12px',
110
+ whiteSpace: 'nowrap',
111
+ }}
112
+ >
113
+ {point.value}
114
+ </div>
115
+ </div>
116
+ <div style={{
117
+ marginTop: '10px',
118
+ fontSize: '12px',
119
+ textAlign: 'center',
120
+ color: '#7f8c8d',
121
+ wordBreak: 'break-word',
122
+ }}
123
+ >
124
+ {point.label}
125
+ </div>
126
+ </div>
127
+ ))}
128
+ </div>
129
+ </div>
130
+ )
131
+ }
132
+
133
+ const renderLineChart = () => {
134
+ const maxValue = getMaxValue()
135
+ const width = 600
136
+ const height = 300
137
+ const padding = 40
138
+
139
+ const points = data.map((point, index) => ({
140
+ x: padding + (index * (width - 2 * padding)) / (data.length - 1),
141
+ y: padding + ((maxValue - point.value) / maxValue) * (height - 2 * padding),
142
+ }))
143
+
144
+ const pathData = points.map((point, index) =>
145
+ `${index === 0 ? 'M' : 'L'} ${point.x} ${point.y}`,
146
+ ).join(' ')
147
+
148
+ return (
149
+ <div style={{ padding: '20px' }}>
150
+ <h3 style={{ marginBottom: '20px', color: '#2c3e50' }}>Line Chart</h3>
151
+ <svg width={width} height={height} style={{ border: '1px solid #ecf0f1', borderRadius: '8px' }}>
152
+ {/* Grid lines */}
153
+ {[0, 0.25, 0.5, 0.75, 1].map(ratio => (
154
+ <line
155
+ key={ratio}
156
+ x1={padding}
157
+ y1={padding + ratio * (height - 2 * padding)}
158
+ x2={width - padding}
159
+ y2={padding + ratio * (height - 2 * padding)}
160
+ stroke="#ecf0f1"
161
+ strokeWidth="1"
162
+ />
163
+ ))}
164
+
165
+ {/* Line */}
166
+ <path
167
+ d={pathData}
168
+ fill="none"
169
+ stroke="#3498db"
170
+ strokeWidth="3"
171
+ />
172
+
173
+ {/* Data points */}
174
+ {points.map((point, index) => (
175
+ <circle
176
+ key={index}
177
+ cx={point.x}
178
+ cy={point.y}
179
+ r="6"
180
+ fill={data[index].color || '#3498db'}
181
+ stroke="white"
182
+ strokeWidth="2"
183
+ style={{ cursor: 'pointer' }}
184
+ title={`${data[index].label}: ${data[index].value}`}
185
+ />
186
+ ))}
187
+
188
+ {/* Labels */}
189
+ {data.map((point, index) => (
190
+ <text
191
+ key={index}
192
+ x={padding + (index * (width - 2 * padding)) / (data.length - 1)}
193
+ y={height - 10}
194
+ textAnchor="middle"
195
+ fontSize="12"
196
+ fill="#7f8c8d"
197
+ >
198
+ {point.label}
199
+ </text>
200
+ ))}
201
+ </svg>
202
+ </div>
203
+ )
204
+ }
205
+
206
+ const renderPieChart = () => {
207
+ const total = getTotalValue()
208
+ let currentAngle = 0
209
+
210
+ return (
211
+ <div style={{ padding: '20px' }}>
212
+ <h3 style={{ marginBottom: '20px', color: '#2c3e50' }}>Pie Chart</h3>
213
+ <div style={{ display: 'flex', gap: '40px', alignItems: 'center' }}>
214
+ <svg width="300" height="300" style={{ border: '1px solid #ecf0f1', borderRadius: '8px' }}>
215
+ {data.map((point, index) => {
216
+ const percentage = point.value / total
217
+ const angle = percentage * 360
218
+ const startAngle = currentAngle
219
+ const endAngle = currentAngle + angle
220
+ currentAngle += angle
221
+
222
+ const centerX = 150
223
+ const centerY = 150
224
+ const radius = 120
225
+
226
+ const startAngleRad = (startAngle - 90) * (Math.PI / 180)
227
+ const endAngleRad = (endAngle - 90) * (Math.PI / 180)
228
+
229
+ const x1 = centerX + radius * Math.cos(startAngleRad)
230
+ const y1 = centerY + radius * Math.sin(startAngleRad)
231
+ const x2 = centerX + radius * Math.cos(endAngleRad)
232
+ const y2 = centerY + radius * Math.sin(endAngleRad)
233
+
234
+ const largeArcFlag = angle > 180 ? 1 : 0
235
+
236
+ const pathData = [
237
+ `M ${centerX} ${centerY}`,
238
+ `L ${x1} ${y1}`,
239
+ `A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`,
240
+ 'Z',
241
+ ].join(' ')
242
+
243
+ return (
244
+ <path
245
+ key={index}
246
+ d={pathData}
247
+ fill={point.color || '#3498db'}
248
+ stroke="white"
249
+ strokeWidth="2"
250
+ style={{ cursor: 'pointer' }}
251
+ title={`${point.label}: ${point.value} (${(percentage * 100).toFixed(1)}%)`}
252
+ />
253
+ )
254
+ })}
255
+ </svg>
256
+
257
+ <div style={{ flex: '1' }}>
258
+ <h4 style={{ marginBottom: '15px', color: '#2c3e50' }}>Legend</h4>
259
+ {data.map((point, index) => (
260
+ <div
261
+ key={index}
262
+ style={{
263
+ display: 'flex',
264
+ alignItems: 'center',
265
+ marginBottom: '8px',
266
+ padding: '8px',
267
+ background: '#f8f9fa',
268
+ borderRadius: '4px',
269
+ }}
270
+ >
271
+ <div style={{
272
+ width: '16px',
273
+ height: '16px',
274
+ background: point.color || '#3498db',
275
+ borderRadius: '2px',
276
+ marginRight: '10px',
277
+ }}
278
+ />
279
+ <span style={{ flex: '1', fontSize: '14px' }}>{point.label}</span>
280
+ <span style={{
281
+ fontSize: '14px',
282
+ fontWeight: 'bold',
283
+ color: '#2c3e50',
284
+ }}
285
+ >
286
+ {point.value}
287
+ </span>
288
+ </div>
289
+ ))}
290
+ </div>
291
+ </div>
292
+ </div>
293
+ )
294
+ }
295
+
296
+ return (
297
+ <div style={{ padding: '20px' }}>
298
+ <div style={{ marginBottom: '30px' }}>
299
+ <h1 style={{ margin: '0 0 20px 0', color: '#2c3e50' }}>Data Visualization</h1>
300
+
301
+ {/* Controls */}
302
+ <div style={{
303
+ background: 'white',
304
+ padding: '20px',
305
+ borderRadius: '8px',
306
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
307
+ marginBottom: '20px',
308
+ }}
309
+ >
310
+ <div style={{ display: 'flex', gap: '20px', flexWrap: 'wrap', alignItems: 'center', marginBottom: '20px' }}>
311
+ <div>
312
+ <label style={{ marginRight: '10px', fontWeight: 'bold', color: '#2c3e50' }}>Chart Type:</label>
313
+ <select
314
+ value={currentChartType}
315
+ onChange={e => setCurrentChartType(e.target.value as typeof currentChartType)}
316
+ style={{
317
+ padding: '8px 12px',
318
+ border: '1px solid #ddd',
319
+ borderRadius: '4px',
320
+ }}
321
+ >
322
+ <option value="bar">Bar Chart</option>
323
+ <option value="line">Line Chart</option>
324
+ <option value="pie">Pie Chart</option>
325
+ </select>
326
+ </div>
327
+ </div>
328
+
329
+ <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap', alignItems: 'center' }}>
330
+ <input
331
+ type="text"
332
+ placeholder="Label"
333
+ value={newDataPoint.label}
334
+ onChange={e => setNewDataPoint({ ...newDataPoint, label: e.target.value })}
335
+ style={{
336
+ padding: '8px 12px',
337
+ border: '1px solid #ddd',
338
+ borderRadius: '4px',
339
+ minWidth: '120px',
340
+ }}
341
+ />
342
+ <input
343
+ type="number"
344
+ placeholder="Value"
345
+ value={newDataPoint.value}
346
+ onChange={e => setNewDataPoint({ ...newDataPoint, value: Number(e.target.value) })}
347
+ style={{
348
+ padding: '8px 12px',
349
+ border: '1px solid #ddd',
350
+ borderRadius: '4px',
351
+ minWidth: '100px',
352
+ }}
353
+ />
354
+ <button
355
+ onClick={addDataPoint}
356
+ style={{
357
+ padding: '8px 16px',
358
+ background: '#3498db',
359
+ color: 'white',
360
+ border: 'none',
361
+ borderRadius: '4px',
362
+ cursor: 'pointer',
363
+ }}
364
+ >
365
+ Add Data Point
366
+ </button>
367
+ </div>
368
+ </div>
369
+
370
+ {/* Chart */}
371
+ <div style={{
372
+ background: 'white',
373
+ borderRadius: '8px',
374
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
375
+ overflow: 'hidden',
376
+ }}
377
+ >
378
+ {data.length === 0
379
+ ? (
380
+ <div style={{
381
+ textAlign: 'center',
382
+ padding: '40px 20px',
383
+ color: '#7f8c8d',
384
+ fontStyle: 'italic',
385
+ }}
386
+ >
387
+ No data to visualize. Add some data points above!
388
+ </div>
389
+ )
390
+ : (
391
+ <>
392
+ {currentChartType === 'bar' && renderBarChart()}
393
+ {currentChartType === 'line' && renderLineChart()}
394
+ {currentChartType === 'pie' && renderPieChart()}
395
+ </>
396
+ )}
397
+ </div>
398
+
399
+ {/* Data table */}
400
+ {data.length > 0 && (
401
+ <div style={{
402
+ background: 'white',
403
+ borderRadius: '8px',
404
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
405
+ marginTop: '20px',
406
+ overflow: 'hidden',
407
+ }}
408
+ >
409
+ <div style={{ padding: '20px', borderBottom: '1px solid #ecf0f1' }}>
410
+ <h3 style={{ margin: '0', color: '#2c3e50' }}>Data Table</h3>
411
+ </div>
412
+ <div style={{ overflowX: 'auto' }}>
413
+ <table style={{ width: '100%', borderCollapse: 'collapse' }}>
414
+ <thead>
415
+ <tr style={{ background: '#f8f9fa' }}>
416
+ <th style={{ padding: '12px', textAlign: 'left', borderBottom: '1px solid #ecf0f1' }}>Label</th>
417
+ <th style={{ padding: '12px', textAlign: 'left', borderBottom: '1px solid #ecf0f1' }}>Value</th>
418
+ <th style={{ padding: '12px', textAlign: 'left', borderBottom: '1px solid #ecf0f1' }}>Percentage</th>
419
+ <th style={{ padding: '12px', textAlign: 'left', borderBottom: '1px solid #ecf0f1' }}>Color</th>
420
+ <th style={{ padding: '12px', textAlign: 'left', borderBottom: '1px solid #ecf0f1' }}>Actions</th>
421
+ </tr>
422
+ </thead>
423
+ <tbody>
424
+ {data.map((point, index) => (
425
+ <tr key={index} style={{ borderBottom: '1px solid #ecf0f1' }}>
426
+ <td style={{ padding: '12px' }}>{point.label}</td>
427
+ <td style={{ padding: '12px', fontWeight: 'bold' }}>{point.value}</td>
428
+ <td style={{ padding: '12px' }}>
429
+ {((point.value / getTotalValue()) * 100).toFixed(1)}
430
+ %
431
+ </td>
432
+ <td style={{ padding: '12px' }}>
433
+ <div style={{
434
+ width: '20px',
435
+ height: '20px',
436
+ background: point.color || '#3498db',
437
+ borderRadius: '2px',
438
+ display: 'inline-block',
439
+ }}
440
+ />
441
+ </td>
442
+ <td style={{ padding: '12px' }}>
443
+ <button
444
+ onClick={() => removeDataPoint(index)}
445
+ style={{
446
+ background: '#e74c3c',
447
+ color: 'white',
448
+ border: 'none',
449
+ borderRadius: '4px',
450
+ padding: '4px 8px',
451
+ cursor: 'pointer',
452
+ fontSize: '12px',
453
+ }}
454
+ >
455
+ Remove
456
+ </button>
457
+ </td>
458
+ </tr>
459
+ ))}
460
+ </tbody>
461
+ </table>
462
+ </div>
463
+ </div>
464
+ )}
465
+ </div>
466
+ </div>
467
+ )
468
+ }
469
+
470
+ // Mount the component
471
+ const container = document.getElementById('widget-root')
472
+ if (container) {
473
+ const root = createRoot(container)
474
+ root.render(<DataVisualization />)
475
+ }