flowbite-mcp 1.0.0

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.
Files changed (77) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +324 -0
  3. package/build/index.js +975 -0
  4. package/build/server-runner.js +228 -0
  5. package/data/components/accordion.md +860 -0
  6. package/data/components/alerts.md +739 -0
  7. package/data/components/avatar.md +178 -0
  8. package/data/components/badge.md +420 -0
  9. package/data/components/banner.md +145 -0
  10. package/data/components/bottom-navigation.md +513 -0
  11. package/data/components/breadcrumb.md +273 -0
  12. package/data/components/button-group.md +410 -0
  13. package/data/components/buttons.md +405 -0
  14. package/data/components/card.md +711 -0
  15. package/data/components/carousel.md +858 -0
  16. package/data/components/chat-bubble.md +1063 -0
  17. package/data/components/clipboard.md +1029 -0
  18. package/data/components/datepicker.md +673 -0
  19. package/data/components/device-mockups.md +152 -0
  20. package/data/components/drawer.md +1353 -0
  21. package/data/components/dropdowns.md +1925 -0
  22. package/data/components/footer.md +299 -0
  23. package/data/components/forms.md +371 -0
  24. package/data/components/gallery.md +322 -0
  25. package/data/components/indicators.md +262 -0
  26. package/data/components/jumbotron.md +213 -0
  27. package/data/components/kbd.md +217 -0
  28. package/data/components/list-group.md +365 -0
  29. package/data/components/mega-menu.md +558 -0
  30. package/data/components/modal.md +1309 -0
  31. package/data/components/navbar.md +1053 -0
  32. package/data/components/pagination.md +472 -0
  33. package/data/components/popover.md +826 -0
  34. package/data/components/progress.md +95 -0
  35. package/data/components/qr-code.md +280 -0
  36. package/data/components/rating.md +323 -0
  37. package/data/components/sidebar.md +1067 -0
  38. package/data/components/skeleton.md +221 -0
  39. package/data/components/speed-dial.md +1270 -0
  40. package/data/components/spinner.md +222 -0
  41. package/data/components/stepper.md +271 -0
  42. package/data/components/tables.md +3127 -0
  43. package/data/components/tabs.md +808 -0
  44. package/data/components/timeline.md +304 -0
  45. package/data/components/toast.md +341 -0
  46. package/data/components/tooltips.md +524 -0
  47. package/data/components/typography.md +269 -0
  48. package/data/components/video.md +95 -0
  49. package/data/forms/checkbox.md +375 -0
  50. package/data/forms/file-input.md +98 -0
  51. package/data/forms/floating-label.md +185 -0
  52. package/data/forms/input-field.md +222 -0
  53. package/data/forms/number-input.md +1099 -0
  54. package/data/forms/phone-input.md +577 -0
  55. package/data/forms/radio.md +315 -0
  56. package/data/forms/range.md +83 -0
  57. package/data/forms/search-input.md +280 -0
  58. package/data/forms/select.md +259 -0
  59. package/data/forms/textarea.md +155 -0
  60. package/data/forms/timepicker.md +732 -0
  61. package/data/forms/toggle.md +176 -0
  62. package/data/plugins/charts.md +2683 -0
  63. package/data/plugins/datatables.md +1922 -0
  64. package/data/plugins/datepicker.md +5 -0
  65. package/data/plugins/wysiwyg.md +2377 -0
  66. package/data/quickstart.md +169 -0
  67. package/data/theme.md +231 -0
  68. package/data/toc.md +79 -0
  69. package/data/typography/blockquote.md +182 -0
  70. package/data/typography/headings.md +174 -0
  71. package/data/typography/hr.md +74 -0
  72. package/data/typography/images.md +168 -0
  73. package/data/typography/links.md +118 -0
  74. package/data/typography/lists.md +387 -0
  75. package/data/typography/paragraphs.md +186 -0
  76. package/data/typography/text.md +249 -0
  77. package/package.json +71 -0
package/build/index.js ADDED
@@ -0,0 +1,975 @@
1
+ #!/usr/bin/env node
2
+ import { z } from 'zod';
3
+ import { ExpressHttpStreamableMcpServer } from "./server-runner.js";
4
+ import { readFileSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ // Get __dirname equivalent in ES modules
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ // Get transport mode from environment or command-line args
13
+ const args = process.argv.slice(2);
14
+ // Handle --version flag
15
+ if (args.includes('--version') || args.includes('-v')) {
16
+ try {
17
+ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
18
+ console.log(`Flowbite MCP Server v${packageJson.version}`);
19
+ process.exit(0);
20
+ }
21
+ catch (error) {
22
+ console.log('Flowbite MCP Server (version unknown)');
23
+ process.exit(0);
24
+ }
25
+ }
26
+ // Handle --help flag
27
+ if (args.includes('--help') || args.includes('-h')) {
28
+ console.log(`
29
+ Flowbite MCP Server - AI-powered Flowbite component and theme generation
30
+
31
+ Usage:
32
+ flowbite-mcp [options]
33
+ npx flowbite-mcp [options]
34
+
35
+ Options:
36
+ --mode <stdio|http> Transport mode (default: stdio)
37
+ --port <number> Port for HTTP mode (default: 3000)
38
+ --version, -v Show version number
39
+ --help, -h Show this help message
40
+
41
+ Examples:
42
+ # Run in stdio mode (for Claude Desktop, Cursor)
43
+ npx flowbite-mcp
44
+
45
+ # Run in HTTP server mode on port 3000
46
+ npx flowbite-mcp --mode http --port 3000
47
+
48
+ # Show version
49
+ npx flowbite-mcp --version
50
+
51
+ Documentation:
52
+ https://github.com/themesberg/flowbite-mcp#readme
53
+ `);
54
+ process.exit(0);
55
+ }
56
+ const modeIndex = args.indexOf('--mode');
57
+ const portIndex = args.indexOf('--port');
58
+ const TRANSPORT_MODE = modeIndex !== -1 ? args[modeIndex + 1] : process.env.MCP_TRANSPORT_MODE || 'stdio';
59
+ const PORT = portIndex !== -1 ? parseInt(args[portIndex + 1]) : parseInt(process.env.MCP_PORT || '3000');
60
+ console.log(`Initializing Flowbite MCP Server in ${TRANSPORT_MODE} mode${TRANSPORT_MODE === 'http' ? ` on port ${PORT}` : ''}`);
61
+ const COMPONENT_FILES = [
62
+ {
63
+ name: 'flowbite_accordion',
64
+ uri: 'flowbite://components/accordion',
65
+ title: 'Accordion',
66
+ path: 'data/components/accordion.md',
67
+ description: 'Use the accordion component to show hidden information based on the collapse and expand state of the child elements using data attribute options'
68
+ },
69
+ {
70
+ name: 'flowbite_alert',
71
+ uri: 'flowbite://components/alert',
72
+ title: 'Alert',
73
+ path: 'data/components/alerts.md',
74
+ description: 'Show contextual information to your users using alert elements based on Tailwind CSS'
75
+ },
76
+ {
77
+ name: 'flowbite_avatar',
78
+ uri: 'flowbite://components/avatar',
79
+ title: 'Avatar',
80
+ path: 'data/components/avatar.md',
81
+ description: 'Use the avatar component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
82
+ },
83
+ {
84
+ name: 'flowbite_badge',
85
+ uri: 'flowbite://components/badge',
86
+ title: 'Badge',
87
+ path: 'data/components/badge.md',
88
+ description: 'Use the badge component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
89
+ },
90
+ {
91
+ name: 'flowbite_banner',
92
+ uri: 'flowbite://components/banner',
93
+ title: 'Banner',
94
+ path: 'data/components/banner.md',
95
+ description: 'Use the banner component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
96
+ },
97
+ {
98
+ name: 'flowbite_bottom_navigation',
99
+ uri: 'flowbite://components/bottom-navigation',
100
+ title: 'Bottom Navigation',
101
+ path: 'data/components/bottom-navigation.md',
102
+ description: 'Use the bottom navigation component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
103
+ },
104
+ {
105
+ name: 'flowbite_breadcrumb',
106
+ uri: 'flowbite://components/breadcrumb',
107
+ title: 'Breadcrumb',
108
+ path: 'data/components/breadcrumb.md',
109
+ description: 'Use the breadcrumb component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
110
+ },
111
+ {
112
+ name: 'flowbite_buttons',
113
+ uri: 'flowbite://components/buttons',
114
+ title: 'Buttons',
115
+ path: 'data/components/buttons.md',
116
+ description: 'Use the buttons component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
117
+ },
118
+ {
119
+ name: 'flowbite_button_group',
120
+ uri: 'flowbite://components/button-group',
121
+ title: 'Button Group',
122
+ path: 'data/components/button-group.md',
123
+ description: 'Use the button group component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
124
+ },
125
+ {
126
+ name: 'flowbite_cards',
127
+ uri: 'flowbite://components/cards',
128
+ title: 'Cards',
129
+ path: 'data/components/card.md',
130
+ description: 'Use the cards component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
131
+ },
132
+ {
133
+ name: 'flowbite_carousel',
134
+ uri: 'flowbite://components/carousel',
135
+ title: 'Carousel',
136
+ path: 'data/components/carousel.md',
137
+ description: 'Use the carousel component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
138
+ },
139
+ {
140
+ name: 'flowbite_chat_bubble',
141
+ uri: 'flowbite://components/chat-bubble',
142
+ title: 'Chat Bubble',
143
+ path: 'data/components/chat-bubble.md',
144
+ description: 'Use the chat bubble component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
145
+ },
146
+ {
147
+ name: 'flowbite_clipboard',
148
+ uri: 'flowbite://components/clipboard',
149
+ title: 'Clipboard',
150
+ path: 'data/components/clipboard.md',
151
+ description: 'Use the clipboard component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
152
+ },
153
+ {
154
+ name: 'flowbite_datepicker',
155
+ uri: 'flowbite://components/datepicker',
156
+ title: 'Datepicker',
157
+ path: 'data/components/datepicker.md',
158
+ description: 'Use the datepicker component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
159
+ },
160
+ {
161
+ name: 'flowbite_device_mockups',
162
+ uri: 'flowbite://components/device-mockups',
163
+ title: 'Device Mockups',
164
+ path: 'data/components/device-mockups.md',
165
+ description: 'Use the device mockups component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
166
+ },
167
+ {
168
+ name: 'flowbite_drawer',
169
+ uri: 'flowbite://components/drawer',
170
+ title: 'Drawer',
171
+ path: 'data/components/drawer.md',
172
+ description: 'Use the drawer component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
173
+ },
174
+ {
175
+ name: 'flowbite_dropdowns',
176
+ uri: 'flowbite://components/dropdowns',
177
+ title: 'Dropdowns',
178
+ path: 'data/components/dropdowns.md',
179
+ description: 'Use the dropdowns component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
180
+ },
181
+ {
182
+ name: 'flowbite_footer',
183
+ uri: 'flowbite://components/footer',
184
+ title: 'Footer',
185
+ path: 'data/components/footer.md',
186
+ description: 'Use the footer component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
187
+ },
188
+ {
189
+ name: 'flowbite_forms',
190
+ uri: 'flowbite://components/forms',
191
+ title: 'Forms',
192
+ path: 'data/components/forms.md',
193
+ description: 'Use the forms component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
194
+ },
195
+ {
196
+ name: 'flowbite_gallery',
197
+ uri: 'flowbite://components/gallery',
198
+ title: 'Gallery',
199
+ path: 'data/components/gallery.md',
200
+ description: 'Use the gallery component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
201
+ },
202
+ {
203
+ name: 'flowbite_indicators',
204
+ uri: 'flowbite://components/indicators',
205
+ title: 'Indicators',
206
+ path: 'data/components/indicators.md',
207
+ description: 'Use the indicators component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
208
+ },
209
+ {
210
+ name: 'flowbite_jumbotron',
211
+ uri: 'flowbite://components/jumbotron',
212
+ title: 'Jumbotron',
213
+ path: 'data/components/jumbotron.md',
214
+ description: 'Use the jumbotron component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
215
+ },
216
+ {
217
+ name: 'flowbite_kbd',
218
+ uri: 'flowbite://components/kbd',
219
+ title: 'KBD',
220
+ path: 'data/components/kbd.md',
221
+ description: 'Use the kbd component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
222
+ },
223
+ {
224
+ name: 'flowbite_list_group',
225
+ uri: 'flowbite://components/list-group',
226
+ title: 'List Group',
227
+ path: 'data/components/list-group.md',
228
+ description: 'Use the list group component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
229
+ },
230
+ {
231
+ name: 'flowbite_mega_menu',
232
+ uri: 'flowbite://components/mega-menu',
233
+ title: 'Mega Menu',
234
+ path: 'data/components/mega-menu.md',
235
+ description: 'Use the mega menu component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
236
+ },
237
+ {
238
+ name: 'flowbite_modal',
239
+ uri: 'flowbite://components/modal',
240
+ title: 'Modal',
241
+ path: 'data/components/modal.md',
242
+ description: 'Use the modal component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
243
+ },
244
+ {
245
+ name: 'flowbite_navbar',
246
+ uri: 'flowbite://components/navbar',
247
+ title: 'Navbar',
248
+ path: 'data/components/navbar.md',
249
+ description: 'Use the navbar component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
250
+ },
251
+ {
252
+ name: 'flowbite_pagination',
253
+ uri: 'flowbite://components/pagination',
254
+ title: 'Pagination',
255
+ path: 'data/components/pagination.md',
256
+ description: 'Use the pagination component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
257
+ },
258
+ {
259
+ name: 'flowbite_popover',
260
+ uri: 'flowbite://components/popover',
261
+ title: 'Popover',
262
+ path: 'data/components/popover.md',
263
+ description: 'Use the popover component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
264
+ },
265
+ {
266
+ name: 'flowbite_progress',
267
+ uri: 'flowbite://components/progress',
268
+ title: 'Progress',
269
+ path: 'data/components/progress.md',
270
+ description: 'Use the progress component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
271
+ },
272
+ {
273
+ name: 'flowbite_qr_code',
274
+ uri: 'flowbite://components/qr-code',
275
+ title: 'QR Code',
276
+ path: 'data/components/qr-code.md',
277
+ description: 'Use this component to generate and show QR codes based on text or URL that can be scanned with device phone cameras and other devices using the Flowbite library based on Tailwind CSS'
278
+ },
279
+ {
280
+ name: 'flowbite_rating',
281
+ uri: 'flowbite://components/rating',
282
+ title: 'Rating',
283
+ path: 'data/components/rating.md',
284
+ description: 'Use the rating component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
285
+ },
286
+ {
287
+ name: 'flowbite_sidebar',
288
+ uri: 'flowbite://components/sidebar',
289
+ title: 'Sidebar',
290
+ path: 'data/components/sidebar.md',
291
+ description: 'Use the sidebar component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
292
+ },
293
+ {
294
+ name: 'flowbite_skeleton',
295
+ uri: 'flowbite://components/skeleton',
296
+ title: 'Skeleton',
297
+ path: 'data/components/skeleton.md',
298
+ description: 'Use the skeleton component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
299
+ },
300
+ {
301
+ name: 'flowbite_speed_dial',
302
+ uri: 'flowbite://components/speed-dial',
303
+ title: 'Speed Dial',
304
+ path: 'data/components/speed-dial.md',
305
+ description: 'Use the speed dial component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
306
+ },
307
+ {
308
+ name: 'flowbite_spinner',
309
+ uri: 'flowbite://components/spinner',
310
+ title: 'Spinner',
311
+ path: 'data/components/spinner.md',
312
+ description: 'Use the spinner component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
313
+ },
314
+ {
315
+ name: 'flowbite_stepper',
316
+ uri: 'flowbite://components/stepper',
317
+ title: 'Stepper',
318
+ path: 'data/components/stepper.md',
319
+ description: 'Use the stepper component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
320
+ },
321
+ {
322
+ name: 'flowbite_tables',
323
+ uri: 'flowbite://components/tables',
324
+ title: 'Tables',
325
+ path: 'data/components/tables.md',
326
+ description: 'Use the tables component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
327
+ },
328
+ {
329
+ name: 'flowbite_tabs',
330
+ uri: 'flowbite://components/tabs',
331
+ title: 'Tabs',
332
+ path: 'data/components/tabs.md',
333
+ description: 'Use the tabs component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
334
+ },
335
+ {
336
+ name: 'flowbite_timeline',
337
+ uri: 'flowbite://components/timeline',
338
+ title: 'Timeline',
339
+ path: 'data/components/timeline.md',
340
+ description: 'Use the timeline component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
341
+ },
342
+ {
343
+ name: 'flowbite_toast',
344
+ uri: 'flowbite://components/toast',
345
+ title: 'Toast',
346
+ path: 'data/components/toast.md',
347
+ description: 'Use the toast component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
348
+ },
349
+ {
350
+ name: 'flowbite_tooltips',
351
+ uri: 'flowbite://components/tooltips',
352
+ title: 'Tooltips',
353
+ path: 'data/components/tooltips.md',
354
+ description: 'Use the following Tailwind CSS powered tooltips to show extra content when hovering or focusing on an element'
355
+ },
356
+ {
357
+ name: 'flowbite_typography',
358
+ uri: 'flowbite://components/typography',
359
+ title: 'Typography',
360
+ path: 'data/components/typography.md',
361
+ description: 'Use the typography component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
362
+ },
363
+ {
364
+ name: 'flowbite_video',
365
+ uri: 'flowbite://components/video',
366
+ title: 'Video',
367
+ path: 'data/components/video.md',
368
+ description: 'Use the video component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes'
369
+ },
370
+ {
371
+ name: 'flowbite_checkbox',
372
+ uri: 'flowbite://forms/checkbox',
373
+ title: 'Checkbox',
374
+ path: 'data/forms/checkbox.md',
375
+ description: 'Get started with the checkbox component to allow the user to select one or more options in the form of a square box available in multiple sizes and colors'
376
+ },
377
+ {
378
+ name: 'flowbite_file_input',
379
+ uri: 'flowbite://forms/file-input',
380
+ title: 'File Input',
381
+ path: 'data/forms/file-input.md',
382
+ description: 'Get started with the file input component to allow the user to upload a file to the server'
383
+ },
384
+ {
385
+ name: 'flowbite_floating_label',
386
+ uri: 'flowbite://forms/floating-label',
387
+ title: 'Floating Label',
388
+ path: 'data/forms/floating-label.md',
389
+ description: 'Get started with the floating label component to allow the user to input a value into a text field by clicking on the label and typing the value'
390
+ },
391
+ {
392
+ name: 'flowbite_input_field',
393
+ uri: 'flowbite://forms/input-field',
394
+ title: 'Input Field',
395
+ path: 'data/forms/input-field.md',
396
+ description: 'Get started with the input field component to allow the user to input a value into a text field'
397
+ },
398
+ {
399
+ name: 'flowbite_number_input',
400
+ uri: 'flowbite://forms/number-input',
401
+ title: 'Number Input',
402
+ path: 'data/forms/number-input.md',
403
+ description: 'Get started with the number input component to allow the user to input a number into a text field'
404
+ },
405
+ {
406
+ name: 'flowbite_phone_input',
407
+ uri: 'flowbite://forms/phone-input',
408
+ title: 'Phone Input',
409
+ path: 'data/forms/phone-input.md',
410
+ description: 'Get started with the phone input component to allow the user to input a phone number into a text field'
411
+ },
412
+ {
413
+ name: 'flowbite_radio',
414
+ uri: 'flowbite://forms/radio',
415
+ title: 'Radio',
416
+ path: 'data/forms/radio.md',
417
+ description: 'Get started with the radio component to allow the user to select one option from a list of options'
418
+ },
419
+ {
420
+ name: 'flowbite_range_input',
421
+ uri: 'flowbite://forms/range-input',
422
+ title: 'Range Input',
423
+ path: 'data/forms/range.md',
424
+ description: 'Get started with the range input component to allow the user to input a range of values into a text field'
425
+ },
426
+ {
427
+ name: 'flowbite_search_input',
428
+ uri: 'flowbite://forms/search-input',
429
+ title: 'Search Input',
430
+ path: 'data/forms/search-input.md',
431
+ description: 'Get started with the search input component to allow the user to input a search query into a text field'
432
+ },
433
+ {
434
+ name: 'flowbite_select',
435
+ uri: 'flowbite://forms/select',
436
+ title: 'Select',
437
+ path: 'data/forms/select.md',
438
+ description: 'Get started with the select component to allow the user to select one option from a list of options'
439
+ },
440
+ {
441
+ name: 'flowbite_textarea',
442
+ uri: 'flowbite://forms/textarea',
443
+ title: 'Textarea',
444
+ path: 'data/forms/textarea.md',
445
+ description: 'Get started with the textarea component to allow the user to input a value into a text field'
446
+ },
447
+ {
448
+ name: 'flowbite_timepicker',
449
+ uri: 'flowbite://forms/timepicker',
450
+ title: 'Timepicker',
451
+ path: 'data/forms/timepicker.md',
452
+ description: 'Get started with the timepicker component to allow the user to input a time into a text field'
453
+ },
454
+ {
455
+ name: 'flowbite_toggle',
456
+ uri: 'flowbite://forms/toggle',
457
+ title: 'Toggle',
458
+ path: 'data/forms/toggle.md',
459
+ description: 'Get started with the toggle component to allow the user to toggle a value on and off'
460
+ },
461
+ {
462
+ name: 'flowbite_charts',
463
+ uri: 'flowbite://plugins/charts',
464
+ title: 'Charts',
465
+ path: 'data/plugins/charts.md',
466
+ description: 'Get started with the charts plugin to allow the user to create charts using the Chart.js library'
467
+ },
468
+ {
469
+ name: 'flowbite_datatables',
470
+ uri: 'flowbite://plugins/datatables',
471
+ title: 'Datatables',
472
+ path: 'data/plugins/datatables.md',
473
+ description: 'Get started with the datatables plugin to allow the user to create tables using the DataTables library'
474
+ },
475
+ {
476
+ name: 'flowbite_wysiwyg',
477
+ uri: 'flowbite://plugins/wysiwyg',
478
+ title: 'WYSIWYG',
479
+ path: 'data/plugins/wysiwyg.md',
480
+ description: 'Get started with the wysiwyg plugin to allow the user to create a rich text editor using the Quill library'
481
+ },
482
+ {
483
+ name: 'flowbite_blockquote',
484
+ uri: 'flowbite://typography/blockquote',
485
+ title: 'Blockquote',
486
+ path: 'data/typography/blockquote.md',
487
+ description: 'Get started with the blockquote component to allow the user to create a blockquote using theblockquote element'
488
+ },
489
+ {
490
+ name: 'flowbite_headings',
491
+ uri: 'flowbite://typography/headings',
492
+ title: 'Headings',
493
+ path: 'data/typography/headings.md',
494
+ description: 'Get started with the headings component to allow the user to create headings using the heading elements'
495
+ },
496
+ {
497
+ name: 'flowbite_hr',
498
+ uri: 'flowbite://typography/hr',
499
+ title: 'HR',
500
+ path: 'data/typography/hr.md',
501
+ description: 'Get started with the hr component to allow the user to create a horizontal rule using the hr element'
502
+ },
503
+ {
504
+ name: 'flowbite_images',
505
+ uri: 'flowbite://typography/images',
506
+ title: 'Images',
507
+ path: 'data/typography/images.md',
508
+ description: 'Get started with the images component to allow the user to create images using the img element'
509
+ },
510
+ {
511
+ name: 'flowbite_links',
512
+ uri: 'flowbite://typography/links',
513
+ title: 'Links',
514
+ path: 'data/typography/links.md',
515
+ description: 'Get started with the links component to allow the user to create links using the a element'
516
+ },
517
+ {
518
+ name: 'flowbite_lists',
519
+ uri: 'flowbite://typography/lists',
520
+ title: 'Lists',
521
+ path: 'data/typography/lists.md',
522
+ description: 'Get started with the lists component to allow the user to create lists using the ul and ol elements'
523
+ },
524
+ {
525
+ name: 'flowbite_paragraphs',
526
+ uri: 'flowbite://typography/paragraphs',
527
+ title: 'Paragraphs',
528
+ path: 'data/typography/paragraphs.md',
529
+ description: 'Get started with the paragraphs component to allow the user to create paragraphs using the p element'
530
+ },
531
+ {
532
+ name: 'flowbite_text',
533
+ uri: 'flowbite://typography/text',
534
+ title: 'Text',
535
+ path: 'data/typography/text.md',
536
+ description: 'Get started with the text component to allow the user to create text using the text element'
537
+ }
538
+ ];
539
+ // Helper function to get data directory path
540
+ const getDataPath = (relativePath) => {
541
+ // Try relative to current working directory first (for development)
542
+ const cwdPath = join(process.cwd(), 'data', relativePath);
543
+ try {
544
+ readFileSync(cwdPath, 'utf-8');
545
+ return cwdPath;
546
+ }
547
+ catch {
548
+ // Fall back to package directory (for npm installation)
549
+ return join(__dirname, '..', 'data', relativePath);
550
+ }
551
+ };
552
+ // Function to setup all resources and tools
553
+ const setupServer = (server) => {
554
+ server.resource("flowbite_theme", "flowbite://theme/file", {
555
+ description: "The theme file that sets the Tailwind CSS variables to make UI look unique for every website.",
556
+ title: "Flowbite Theme",
557
+ mimeType: "text/markdown",
558
+ }, async (uri) => {
559
+ const themeContent = readFileSync(getDataPath("theme.md"), "utf-8");
560
+ return {
561
+ contents: [
562
+ {
563
+ uri: uri.href,
564
+ text: themeContent,
565
+ mimeType: "text/markdown",
566
+ },
567
+ ],
568
+ };
569
+ });
570
+ server.resource("flowbite_quickstart", "flowbite://quickstart/file", {
571
+ description: "The quickstart file that sets the Tailwind CSS variables to make UI look unique for every website.",
572
+ title: "Flowbite Quickstart",
573
+ mimeType: "text/markdown",
574
+ }, async (uri) => {
575
+ const quickstartContent = readFileSync(getDataPath("quickstart.md"), "utf-8");
576
+ return {
577
+ contents: [
578
+ {
579
+ uri: uri.href,
580
+ text: quickstartContent,
581
+ mimeType: "text/markdown",
582
+ },
583
+ ],
584
+ };
585
+ });
586
+ server.resource("flowbite_components", "flowbite://components/all", {
587
+ description: "A list of all Flowbite UI components with links to documentation",
588
+ title: "Flowbite Components",
589
+ mimeType: "text/markdown",
590
+ }, async (uri) => {
591
+ const componentsContent = readFileSync(getDataPath("toc.md"), "utf-8");
592
+ return {
593
+ contents: [
594
+ {
595
+ uri: uri.href,
596
+ text: componentsContent,
597
+ mimeType: "text/markdown",
598
+ },
599
+ ],
600
+ };
601
+ });
602
+ COMPONENT_FILES.forEach((component) => {
603
+ server.resource(component.name, component.uri, async (uri) => {
604
+ // Extract filename from path (e.g., 'data/components/accordion.md' -> 'components/accordion.md')
605
+ const relativePath = component.path.replace('data/', '');
606
+ const componentContent = readFileSync(getDataPath(relativePath), "utf-8");
607
+ return {
608
+ contents: [
609
+ {
610
+ uri: uri.href,
611
+ text: componentContent,
612
+ mimeType: "text/markdown",
613
+ },
614
+ ],
615
+ };
616
+ });
617
+ });
618
+ server.tool('convert-figma-to-code', 'Converts a Figma layer to a code block', {
619
+ figmaNodeUrl: z.string().describe('The URL of the Figma node to convert'),
620
+ }, async ({ figmaNodeUrl }) => {
621
+ try {
622
+ return {
623
+ content: [
624
+ {
625
+ type: 'text',
626
+ text: `Code block converted`,
627
+ },
628
+ ],
629
+ };
630
+ }
631
+ catch (error) {
632
+ console.error(`Error converting Figma node to code: ${error}`);
633
+ return {
634
+ content: [
635
+ {
636
+ type: 'text',
637
+ text: `Error converting Figma node to code: ${error}`,
638
+ },
639
+ ],
640
+ };
641
+ }
642
+ });
643
+ server.tool('get_session', 'gets the session id and context', {}, async ({}) => {
644
+ return {
645
+ content: [
646
+ {
647
+ type: 'text',
648
+ text: `session`,
649
+ },
650
+ ],
651
+ };
652
+ });
653
+ server.tool('generate-theme', 'Generates a custom Flowbite theme CSS file based on a brand color (hex format) and user instructions. The AI will intelligently analyze the instructions and customize ALL theme variables (border radius, spacing, colors, typography, etc.) to match the desired aesthetic. This tool creates color shades and variations, adapting the entire theme system to match your brand identity.', {
654
+ brandColor: z.string().describe('The primary brand color in hex format (e.g., #3B82F6, #FF5733). This will be used as the base for generating all brand color variations.'),
655
+ instructions: z.string().describe('Natural language instructions describing the desired theme aesthetic and customizations. The AI will interpret these instructions to modify all relevant theme variables. Examples: "Make it modern and minimalist with soft rounded corners", "Create a luxury feel with gold accents and elegant spacing", "Design for a playful children\'s app with bright colors", "Professional corporate style with subtle borders", etc.'),
656
+ fileName: z.string().optional().describe('Optional filename for the generated theme (e.g., "my-brand-theme.css"). Defaults to "custom-theme.css"'),
657
+ }, async ({ brandColor, instructions, fileName }) => {
658
+ try {
659
+ // Helper function to convert hex to RGB
660
+ const hexToRgb = (hex) => {
661
+ const cleanHex = hex.replace('#', '');
662
+ const r = parseInt(cleanHex.substring(0, 2), 16);
663
+ const g = parseInt(cleanHex.substring(2, 4), 16);
664
+ const b = parseInt(cleanHex.substring(4, 6), 16);
665
+ return { r, g, b };
666
+ };
667
+ // Helper function to convert RGB to HSL
668
+ const rgbToHsl = (r, g, b) => {
669
+ r /= 255;
670
+ g /= 255;
671
+ b /= 255;
672
+ const max = Math.max(r, g, b);
673
+ const min = Math.min(r, g, b);
674
+ let h = 0, s = 0, l = (max + min) / 2;
675
+ if (max !== min) {
676
+ const d = max - min;
677
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
678
+ switch (max) {
679
+ case r:
680
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
681
+ break;
682
+ case g:
683
+ h = ((b - r) / d + 2) / 6;
684
+ break;
685
+ case b:
686
+ h = ((r - g) / d + 4) / 6;
687
+ break;
688
+ }
689
+ }
690
+ return { h: h * 360, s: s * 100, l: l * 100 };
691
+ };
692
+ // Helper function to convert HSL to RGB
693
+ const hslToRgb = (h, s, l) => {
694
+ h /= 360;
695
+ s /= 100;
696
+ l /= 100;
697
+ let r, g, b;
698
+ if (s === 0) {
699
+ r = g = b = l;
700
+ }
701
+ else {
702
+ const hue2rgb = (p, q, t) => {
703
+ if (t < 0)
704
+ t += 1;
705
+ if (t > 1)
706
+ t -= 1;
707
+ if (t < 1 / 6)
708
+ return p + (q - p) * 6 * t;
709
+ if (t < 1 / 2)
710
+ return q;
711
+ if (t < 2 / 3)
712
+ return p + (q - p) * (2 / 3 - t) * 6;
713
+ return p;
714
+ };
715
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
716
+ const p = 2 * l - q;
717
+ r = hue2rgb(p, q, h + 1 / 3);
718
+ g = hue2rgb(p, q, h);
719
+ b = hue2rgb(p, q, h - 1 / 3);
720
+ }
721
+ return {
722
+ r: Math.round(r * 255),
723
+ g: Math.round(g * 255),
724
+ b: Math.round(b * 255)
725
+ };
726
+ };
727
+ // Helper function to convert RGB to hex
728
+ const rgbToHex = (r, g, b) => {
729
+ const toHex = (n) => {
730
+ const hex = Math.round(n).toString(16);
731
+ return hex.length === 1 ? '0' + hex : hex;
732
+ };
733
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
734
+ };
735
+ // Generate color shades from base color (50, 100, 200, ..., 900, 950)
736
+ const generateColorShades = (baseHex) => {
737
+ const rgb = hexToRgb(baseHex);
738
+ const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
739
+ const shades = {};
740
+ // Lightness values for each shade based on Tailwind's color system
741
+ const lightnessMap = {
742
+ 50: 97,
743
+ 100: 93,
744
+ 200: 86,
745
+ 300: 77,
746
+ 400: 66,
747
+ 500: 55, // Base color around here
748
+ 600: 45,
749
+ 700: 37,
750
+ 800: 28,
751
+ 900: 20,
752
+ 950: 13
753
+ };
754
+ // Adjust saturation slightly for different shades
755
+ Object.entries(lightnessMap).forEach(([shade, lightness]) => {
756
+ let adjustedSaturation = hsl.s;
757
+ // Reduce saturation for very light and very dark shades
758
+ if (lightness > 90) {
759
+ adjustedSaturation = hsl.s * 0.3;
760
+ }
761
+ else if (lightness > 80) {
762
+ adjustedSaturation = hsl.s * 0.5;
763
+ }
764
+ else if (lightness < 20) {
765
+ adjustedSaturation = hsl.s * 0.8;
766
+ }
767
+ const adjustedRgb = hslToRgb(hsl.h, adjustedSaturation, lightness);
768
+ shades[parseInt(shade)] = rgbToHex(adjustedRgb.r, adjustedRgb.g, adjustedRgb.b);
769
+ });
770
+ return shades;
771
+ };
772
+ // Read the base theme file
773
+ const themeContent = readFileSync(getDataPath("theme.md"), "utf-8");
774
+ // Generate color shades for the brand color
775
+ const brandShades = generateColorShades(brandColor);
776
+ // Extract the CSS content from the markdown
777
+ const cssMatch = themeContent.match(/```css\n([\s\S]*?)\n```/);
778
+ if (!cssMatch) {
779
+ throw new Error('Could not parse theme CSS content');
780
+ }
781
+ let customTheme = cssMatch[1];
782
+ // Replace all blue color references with the new brand color shades
783
+ const blueReplacements = {
784
+ '--color-blue-50': brandShades[50],
785
+ '--color-blue-100': brandShades[100],
786
+ '--color-blue-200': brandShades[200],
787
+ '--color-blue-300': brandShades[300],
788
+ '--color-blue-400': brandShades[400],
789
+ '--color-blue-500': brandShades[500],
790
+ '--color-blue-600': brandShades[600],
791
+ '--color-blue-700': brandShades[700],
792
+ '--color-blue-800': brandShades[800],
793
+ '--color-blue-900': brandShades[900],
794
+ '--color-blue-950': brandShades[950],
795
+ };
796
+ // Apply brand color replacements
797
+ Object.entries(blueReplacements).forEach(([cssVar, hexValue]) => {
798
+ const regex = new RegExp(`var\\(${cssVar}\\)`, 'g');
799
+ customTheme = customTheme.replace(regex, hexValue);
800
+ });
801
+ // Generate output
802
+ const themeFileName = fileName || 'custom-theme.css';
803
+ // Create a detailed explanation with all customizable variables
804
+ const explanation = `
805
+ # Theme Generator - Base Theme with Brand Colors Applied
806
+
807
+ ## Configuration
808
+ - **File Name**: \`${themeFileName}\`
809
+ - **Brand Color**: ${brandColor}
810
+ - **User Instructions**: "${instructions}"
811
+
812
+ ## Generated Brand Color Palette
813
+ Your brand color has been expanded into a complete color system:
814
+ - **50** (Lightest): ${brandShades[50]}
815
+ - **100**: ${brandShades[100]}
816
+ - **200**: ${brandShades[200]}
817
+ - **300**: ${brandShades[300]}
818
+ - **400**: ${brandShades[400]}
819
+ - **500** (Base): ${brandShades[500]}
820
+ - **600**: ${brandShades[600]}
821
+ - **700**: ${brandShades[700]}
822
+ - **800**: ${brandShades[800]}
823
+ - **900**: ${brandShades[900]}
824
+ - **950** (Darkest): ${brandShades[950]}
825
+
826
+ ## Base Theme with Brand Colors Applied
827
+
828
+ Here is the theme with brand colors integrated. Based on the instructions "${instructions}", you should now customize the following variables to achieve the desired aesthetic:
829
+
830
+ ### Customizable Variable Categories:
831
+
832
+ #### 1. **Typography Variables**
833
+ - \`--font-sans\`: Main sans-serif font stack
834
+ - \`--font-body\`: Body text font
835
+ - \`--font-mono\`: Monospace font for code
836
+ - \`--text-2xs\`: Extra small text size
837
+ - \`--leading-*\`: Line height variables (4, 5, 6, 7, 8, 9, none, heading-none)
838
+ - \`--tracking-*\`: Letter spacing (tighter, tight)
839
+
840
+ #### 2. **Border Radius Variables** (Control roundness/sharpness)
841
+ - \`--radius-0\`: No radius (default: 0px)
842
+ - \`--radius-xxs\`: Extra extra small (default: 2px)
843
+ - \`--radius-xs\`: Extra small (default: 4px)
844
+ - \`--radius-sm\`: Small (default: 6px)
845
+ - \`--radius\`: Base radius (default: 8px)
846
+ - \`--radius-base\`: Base radius alternative (default: 12px)
847
+ - \`--radius-lg\`: Large radius (default: 16px)
848
+
849
+ #### 3. **Border Width Variables**
850
+ - \`--default-border-width\`: Global border thickness (default: 1px)
851
+
852
+ #### 4. **Spacing Variables**
853
+ - \`--spacing-8xl\`: Extra large spacing (default: 90rem)
854
+
855
+ ### Current Theme CSS:
856
+
857
+ \`\`\`css
858
+ @theme {
859
+ ${customTheme}
860
+ }
861
+ \`\`\`
862
+
863
+ ## How to Customize
864
+
865
+ Based on the instructions "${instructions}", analyze what changes should be made to the variables above. Consider:
866
+
867
+ **For aesthetics like "modern", "minimalist", "clean":**
868
+ - Reduce border radius for sharper look
869
+ - Adjust spacing for breathing room
870
+ - Consider modern font stacks
871
+
872
+ **For "playful", "friendly", "soft":**
873
+ - Increase border radius significantly
874
+ - Use more spacing
875
+ - Consider rounded, friendly typography
876
+
877
+ **For "luxury", "elegant", "sophisticated":**
878
+ - Moderate border radius
879
+ - Refined spacing
880
+ - Elegant font choices
881
+
882
+ **For "bold", "strong", "impactful":**
883
+ - Increase border widths
884
+ - Adjust typography weights
885
+ - Consider spacing adjustments
886
+
887
+ **For "corporate", "professional", "formal":**
888
+ - Conservative border radius
889
+ - Standard spacing
890
+ - Professional font stacks
891
+
892
+ **For "children", "kid-friendly", "fun":**
893
+ - Maximum border radius
894
+ - Bright, cheerful spacing
895
+ - Playful font choices
896
+
897
+ ## Next Steps
898
+
899
+ 1. Analyze the instructions and determine which variables need modification
900
+ 2. Update the CSS variables in the theme above
901
+ 3. Generate the final \`${themeFileName}\` file with your customizations
902
+ 4. Provide usage instructions for integration
903
+
904
+ The brand colors have been applied. Now intelligently modify the other variables based on the design intent in the instructions.
905
+ `;
906
+ return {
907
+ content: [
908
+ {
909
+ type: 'text',
910
+ text: explanation,
911
+ },
912
+ ],
913
+ };
914
+ }
915
+ catch (error) {
916
+ console.error(`Error generating theme: ${error}`);
917
+ return {
918
+ content: [
919
+ {
920
+ type: 'text',
921
+ text: `Error generating theme: ${error instanceof Error ? error.message : String(error)}
922
+
923
+ Please make sure:
924
+ 1. The brand color is in valid hex format (e.g., #3B82F6)
925
+ 2. Instructions are clear and specific
926
+ 3. The theme.md file is accessible
927
+
928
+ Example usage:
929
+ - brandColor: "#FF5733"
930
+ - instructions: "Make it modern and minimalist with rounded corners"
931
+ - fileName: "my-brand-theme.css"`,
932
+ },
933
+ ],
934
+ };
935
+ }
936
+ });
937
+ };
938
+ // Start server based on transport mode
939
+ if (TRANSPORT_MODE === 'stdio') {
940
+ // Standard I/O mode for local development and CLI integrations
941
+ console.log('Starting Flowbite MCP Server in stdio mode...');
942
+ const server = new McpServer({
943
+ name: "flowbite-mcp",
944
+ version: "1.0.0",
945
+ }, {
946
+ capabilities: {
947
+ resources: {},
948
+ tools: {},
949
+ }
950
+ });
951
+ setupServer(server);
952
+ const transport = new StdioServerTransport();
953
+ server.connect(transport).catch((error) => {
954
+ console.error('Failed to connect stdio transport:', error);
955
+ process.exit(1);
956
+ });
957
+ console.log('Flowbite MCP Server running in stdio mode');
958
+ console.log('Ready to accept requests via standard I/O');
959
+ }
960
+ else if (TRANSPORT_MODE === 'http') {
961
+ // HTTP Streamable mode for server/production deployments
962
+ console.log(`Starting Flowbite MCP Server in HTTP mode on port ${PORT}...`);
963
+ ExpressHttpStreamableMcpServer({
964
+ name: "flowbite-mcp",
965
+ }, setupServer);
966
+ console.log(`Flowbite MCP Server running in HTTP mode`);
967
+ console.log(`Server listening on http://localhost:${PORT}`);
968
+ console.log(`Health check: http://localhost:${PORT}/health`);
969
+ console.log(`MCP endpoint: http://localhost:${PORT}/mcp`);
970
+ }
971
+ else {
972
+ console.error(`Invalid transport mode: ${TRANSPORT_MODE}`);
973
+ console.error('Valid modes: stdio, http');
974
+ process.exit(1);
975
+ }