astro-component-kit 0.4.0 → 0.5.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 (208) hide show
  1. package/README.md +139 -27
  2. package/bin/cli.js +67 -0
  3. package/bin/installer.js +179 -0
  4. package/package.json +35 -5
  5. package/src/components/index.ts +2 -0
  6. package/src/components/lib/Galaxy3D.astro +249 -137
  7. package/src/components/lib/app/AppSidebar.astro +249 -0
  8. package/src/components/lib/app/AppTopbar.astro +284 -0
  9. package/src/components/lib/app/ArrivalsBoard.astro +176 -0
  10. package/src/components/lib/app/AuthCard.astro +213 -0
  11. package/src/components/lib/app/DataTable.astro +346 -0
  12. package/src/components/lib/app/GuestProfileCard.astro +133 -0
  13. package/src/components/lib/app/HousekeepingBoard.astro +189 -0
  14. package/src/components/lib/app/PageHeader.astro +157 -0
  15. package/src/components/lib/app/PlanUsageCard.astro +112 -0
  16. package/src/components/lib/app/RoomRack.astro +207 -0
  17. package/src/components/lib/app/SettingsSection.astro +96 -0
  18. package/src/components/lib/app/SwitchRow.astro +71 -0
  19. package/src/components/lib/app/TeamMembers.astro +190 -0
  20. package/src/components/lib/app/app-icons.ts +52 -0
  21. package/src/components/lib/app/index.ts +19 -0
  22. package/src/components/lib/charts/AreaChart.astro +4 -4
  23. package/src/components/lib/charts/BarChart.astro +3 -3
  24. package/src/components/lib/charts/ChartFrame.astro +10 -10
  25. package/src/components/lib/charts/DonutChart.astro +2 -2
  26. package/src/components/lib/charts/DumbbellChart.astro +1 -1
  27. package/src/components/lib/charts/ForecastLineChart.astro +1 -1
  28. package/src/components/lib/charts/GaugeChart.astro +1 -1
  29. package/src/components/lib/charts/HeatmapChart.astro +1 -1
  30. package/src/components/lib/charts/HorizontalBarChart.astro +2 -2
  31. package/src/components/lib/charts/KpiStatTile.astro +4 -4
  32. package/src/components/lib/charts/LinearProgressGauge.astro +4 -4
  33. package/src/components/lib/charts/MetricDeltaTable.astro +3 -3
  34. package/src/components/lib/charts/RadarMetricChart.astro +4 -4
  35. package/src/components/lib/charts/RadialBarChart.astro +1 -1
  36. package/src/components/lib/charts/RetentionCohortTable.astro +2 -2
  37. package/src/components/lib/charts/TreemapChart.astro +1 -1
  38. package/src/components/lib/ecommerce/CartDrawer.astro +483 -0
  39. package/src/components/lib/ecommerce/CartPageList.astro +290 -0
  40. package/src/components/lib/ecommerce/CartToast.astro +276 -0
  41. package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
  42. package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
  43. package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
  44. package/src/components/lib/ecommerce/FilterBar.astro +278 -0
  45. package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
  46. package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
  47. package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
  48. package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
  49. package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
  50. package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
  51. package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
  52. package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
  53. package/src/components/lib/ecommerce/ProductRating.astro +78 -0
  54. package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
  55. package/src/components/lib/ecommerce/PromoBar.astro +145 -0
  56. package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
  57. package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
  58. package/src/components/lib/ecommerce/StoreHero.astro +260 -0
  59. package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
  60. package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
  61. package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
  62. package/src/components/lib/ecommerce/cart-store.ts +151 -0
  63. package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
  64. package/src/components/lib/ecommerce/index.ts +34 -0
  65. package/src/components/lib/ecommerce/product-icons.ts +28 -0
  66. package/src/components/lib/ecommerce/types.ts +70 -0
  67. package/src/components/lib/forms/AnimatedInput.astro +4 -2
  68. package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
  69. package/src/components/lib/index.ts +2 -0
  70. package/src/components/lib/layout/BentoGrid3.astro +6 -4
  71. package/src/components/lib/layout/CenterFixedBox.astro +2 -2
  72. package/src/components/lib/layout/CenteredContainer.astro +4 -2
  73. package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
  74. package/src/components/lib/layout/FeatureHero.astro +4 -2
  75. package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
  76. package/src/components/lib/layout/FullBleedSection.astro +2 -2
  77. package/src/components/lib/layout/GalleryGrid4.astro +2 -2
  78. package/src/components/lib/layout/HolyGrailGrid.astro +11 -9
  79. package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
  80. package/src/components/lib/layout/MasonryGrid.astro +2 -2
  81. package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
  82. package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
  83. package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
  84. package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
  85. package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
  86. package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
  87. package/src/components/lib/sections/AgencyContactBrief.astro +194 -0
  88. package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
  89. package/src/components/lib/sections/AgencyHeader.astro +161 -0
  90. package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
  91. package/src/components/lib/sections/AgencyServicesList.astro +113 -0
  92. package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
  93. package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
  94. package/src/components/lib/sections/BlogGridSection.astro +9 -7
  95. package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
  96. package/src/components/lib/sections/CardsShowcase.astro +28 -26
  97. package/src/components/lib/sections/CareersOpenings.astro +10 -8
  98. package/src/components/lib/sections/ChangelogSection.astro +20 -7
  99. package/src/components/lib/sections/ContactGlassForm.astro +10 -8
  100. package/src/components/lib/sections/ContactSplitMap.astro +11 -9
  101. package/src/components/lib/sections/CtaAppDownload.astro +13 -11
  102. package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
  103. package/src/components/lib/sections/CtaNewsletterSection.astro +13 -11
  104. package/src/components/lib/sections/CtaSplitImage.astro +13 -11
  105. package/src/components/lib/sections/DataShowcase.astro +23 -21
  106. package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
  107. package/src/components/lib/sections/FaqTwoColumn.astro +9 -7
  108. package/src/components/lib/sections/FeatureAlternatingRows.astro +10 -8
  109. package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
  110. package/src/components/lib/sections/FeatureIconGrid.astro +6 -6
  111. package/src/components/lib/sections/FeatureTabsShowcase.astro +13 -11
  112. package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
  113. package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
  114. package/src/components/lib/sections/FooterMegaSection.astro +13 -11
  115. package/src/components/lib/sections/FormsShowcase.astro +22 -20
  116. package/src/components/lib/sections/HeroDashboardPreview.astro +11 -9
  117. package/src/components/lib/sections/HeroGlass.astro +22 -20
  118. package/src/components/lib/sections/HeroGradient.astro +15 -13
  119. package/src/components/lib/sections/HeroMinimalCentered.astro +10 -10
  120. package/src/components/lib/sections/HeroShowcaseSplit.astro +18 -16
  121. package/src/components/lib/sections/HeroSplit.astro +13 -11
  122. package/src/components/lib/sections/HeroTerminal.astro +14 -12
  123. package/src/components/lib/sections/HeroWaitlist.astro +10 -8
  124. package/src/components/lib/sections/HowItWorksSteps.astro +12 -10
  125. package/src/components/lib/sections/IntegrationsGrid.astro +7 -7
  126. package/src/components/lib/sections/LayoutShowcase.astro +21 -19
  127. package/src/components/lib/sections/LogoCloudSection.astro +4 -4
  128. package/src/components/lib/sections/LogoWallGrid.astro +6 -4
  129. package/src/components/lib/sections/NavigationShowcase.astro +15 -13
  130. package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
  131. package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
  132. package/src/components/lib/sections/PricingSinglePlan.astro +13 -11
  133. package/src/components/lib/sections/PricingTierCards.astro +11 -9
  134. package/src/components/lib/sections/PricingToggleCards.astro +13 -13
  135. package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
  136. package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
  137. package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
  138. package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
  139. package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
  140. package/src/components/lib/sections/ShopLookbook.astro +250 -0
  141. package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
  142. package/src/components/lib/sections/ShopProductRail.astro +150 -0
  143. package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
  144. package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
  145. package/src/components/lib/sections/StatsCounterBand.astro +9 -7
  146. package/src/components/lib/sections/StatsDashboardSection.astro +4 -2
  147. package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
  148. package/src/components/lib/sections/TeamGridSection.astro +12 -10
  149. package/src/components/lib/sections/TestimonialCarousel.astro +10 -8
  150. package/src/components/lib/sections/TestimonialFeatured.astro +7 -5
  151. package/src/components/lib/sections/TestimonialGridSection.astro +7 -7
  152. package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
  153. package/src/components/lib/sections/TypographyShowcase.astro +10 -8
  154. package/src/components/lib/sections/index.ts +10 -0
  155. package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
  156. package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
  157. package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
  158. package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
  159. package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
  160. package/src/components/lib/templates/ecommerce/data.ts +187 -0
  161. package/src/components/lib/templates/ecommerce/index.ts +14 -0
  162. package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
  163. package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
  164. package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
  165. package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
  166. package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
  167. package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
  168. package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
  169. package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
  170. package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
  171. package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
  172. package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
  173. package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
  174. package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
  175. package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
  176. package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
  177. package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
  178. package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
  179. package/src/components/lib/templates/saas-hotel/data.ts +229 -0
  180. package/src/components/lib/templates/saas-hotel/index.ts +19 -0
  181. package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -0
  182. package/src/data/registry/app.ts +93 -0
  183. package/src/data/registry/buttons.ts +3279 -0
  184. package/src/data/registry/cards.ts +1753 -0
  185. package/src/data/registry/charts-svg.ts +557 -0
  186. package/src/data/registry/charts.ts +500 -0
  187. package/src/data/registry/data.ts +986 -0
  188. package/src/data/registry/ecommerce.ts +269 -0
  189. package/src/data/registry/feedback.ts +1824 -0
  190. package/src/data/registry/forms.ts +2513 -0
  191. package/src/data/registry/index.ts +64 -0
  192. package/src/data/registry/layout.ts +206 -0
  193. package/src/data/registry/navigation.ts +936 -0
  194. package/src/data/registry/overlays.ts +1133 -0
  195. package/src/data/registry/sections-extra.ts +397 -0
  196. package/src/data/registry/sections.ts +361 -0
  197. package/src/data/registry/sources.ts +41 -0
  198. package/src/data/registry/templates.ts +414 -0
  199. package/src/data/registry/types.ts +30 -0
  200. package/src/data/registry/typography.ts +777 -0
  201. package/src/mcp/http-server.ts +324 -0
  202. package/src/mcp/index.ts +67 -0
  203. package/src/mcp/installer.ts +178 -0
  204. package/src/mcp/registry-adapter.ts +278 -0
  205. package/src/mcp/stdio-server.ts +11 -0
  206. package/src/mcp/tools.ts +247 -0
  207. package/src/mcp/types.ts +53 -0
  208. package/src/styles/global.css +95 -0
@@ -0,0 +1,324 @@
1
+ // src/mcp/http-server.ts
2
+ // Production-ready SSE HTTP server for Astro Components Kit MCP on Coolify.
3
+ import express, { type Request, type Response, type NextFunction } from 'express';
4
+ import cors from 'cors';
5
+ import rateLimit from 'express-rate-limit';
6
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
7
+ import { createMcpServer } from './tools.js';
8
+ import { getLibraryStats } from './registry-adapter.js';
9
+
10
+ export interface HttpServerOptions {
11
+ port?: number;
12
+ host?: string;
13
+ rateLimitMax?: number;
14
+ rateLimitWindowMs?: number;
15
+ }
16
+
17
+ export function startHttpServer(options: HttpServerOptions = {}) {
18
+ const port = options.port || Number(process.env.PORT) || 3000;
19
+ const host = options.host || process.env.HOST || '0.0.0.0';
20
+ const rateLimitMax = options.rateLimitMax || Number(process.env.RATE_LIMIT_MAX) || 120;
21
+ const rateLimitWindowMs = options.rateLimitWindowMs || Number(process.env.RATE_LIMIT_WINDOW_MS) || 60 * 1000;
22
+
23
+ const app = express();
24
+
25
+ // Trust reverse proxies (Coolify / Traefik / Caddy / Nginx) for proper IP rate limiting
26
+ app.set('trust proxy', 1);
27
+
28
+ // Disable identifying header
29
+ app.disable('x-powered-by');
30
+
31
+ // Security headers middleware
32
+ app.use((_req: Request, res: Response, next: NextFunction) => {
33
+ res.setHeader('X-Content-Type-Options', 'nosniff');
34
+ res.setHeader('X-Frame-Options', 'DENY');
35
+ res.setHeader('Referrer-Policy', 'no-referrer');
36
+ next();
37
+ });
38
+
39
+ // CORS for public MCP client access
40
+ app.use(
41
+ cors({
42
+ origin: '*',
43
+ methods: ['GET', 'POST', 'OPTIONS'],
44
+ allowedHeaders: ['Content-Type', 'Authorization', 'Accept'],
45
+ })
46
+ );
47
+
48
+ // Rate Limiting — protects Coolify container from abuse
49
+ const limiter = rateLimit({
50
+ windowMs: rateLimitWindowMs,
51
+ max: rateLimitMax,
52
+ standardHeaders: true,
53
+ legacyHeaders: false,
54
+ message: {
55
+ error: 'Too Many Requests',
56
+ message: `Rate limit of ${rateLimitMax} requests per minute exceeded. Please try again later.`,
57
+ },
58
+ });
59
+
60
+ app.use(limiter);
61
+
62
+ // Track active SSE transports by sessionId
63
+ const transports = new Map<string, SSEServerTransport>();
64
+
65
+ // 1. Healthcheck Endpoint (for Coolify / Docker health checks)
66
+ app.get('/health', (_req: Request, res: Response) => {
67
+ const stats = getLibraryStats();
68
+ res.json({
69
+ status: 'ok',
70
+ service: 'astro-components-kit-mcp',
71
+ version: stats.version,
72
+ componentsCount: stats.totalComponents,
73
+ templatesCount: stats.totalTemplates,
74
+ uptimeSeconds: Math.floor(process.uptime()),
75
+ timestamp: new Date().toISOString(),
76
+ });
77
+ });
78
+
79
+ // 2. Human-friendly landing page
80
+ app.get('/', (_req: Request, res: Response) => {
81
+ const stats = getLibraryStats();
82
+ const serverUrl = `https://${_req.get('host') || 'mcp.astrocomponents.dev'}`;
83
+
84
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
85
+ res.send(`<!DOCTYPE html>
86
+ <html lang="en">
87
+ <head>
88
+ <meta charset="utf-8">
89
+ <meta name="viewport" content="width=device-width, initial-scale=1">
90
+ <title>Astro Components Kit — MCP Server</title>
91
+ <style>
92
+ :root {
93
+ --bg: #090d16;
94
+ --card-bg: rgba(255, 255, 255, 0.04);
95
+ --border: rgba(255, 255, 255, 0.1);
96
+ --primary: #f59e0b;
97
+ --primary-glow: rgba(245, 158, 11, 0.25);
98
+ --text: #f1f5f9;
99
+ --text-muted: #94a3b8;
100
+ --code-bg: #030712;
101
+ }
102
+ * { box-sizing: border-box; margin: 0; padding: 0; }
103
+ body {
104
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
105
+ background: var(--bg);
106
+ color: var(--text);
107
+ line-height: 1.6;
108
+ padding: 2.5rem 1.25rem;
109
+ min-height: 100vh;
110
+ display: flex;
111
+ justify-content: center;
112
+ align-items: center;
113
+ }
114
+ .container {
115
+ max-width: 760px;
116
+ width: 100%;
117
+ background: var(--card-bg);
118
+ border: 1px solid var(--border);
119
+ border-radius: 20px;
120
+ padding: 2.5rem;
121
+ box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
122
+ backdrop-filter: blur(16px);
123
+ }
124
+ .badge {
125
+ display: inline-flex;
126
+ align-items: center;
127
+ gap: 0.4rem;
128
+ font-size: 0.8rem;
129
+ font-weight: 700;
130
+ color: var(--primary);
131
+ background: var(--primary-glow);
132
+ border: 1px solid rgba(245, 158, 11, 0.4);
133
+ padding: 0.25rem 0.75rem;
134
+ border-radius: 999px;
135
+ margin-bottom: 1rem;
136
+ }
137
+ .dot { width: 8px; height: 8px; border-radius: 50%; background: #10b981; }
138
+ h1 { font-size: 2rem; font-weight: 800; margin-bottom: 0.5rem; letter-spacing: -0.02em; }
139
+ p.lead { color: var(--text-muted); font-size: 1.05rem; margin-bottom: 2rem; }
140
+ .stats {
141
+ display: grid;
142
+ grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
143
+ gap: 1rem;
144
+ margin-bottom: 2rem;
145
+ }
146
+ .stat-box {
147
+ background: rgba(0, 0, 0, 0.3);
148
+ border: 1px solid var(--border);
149
+ padding: 1rem;
150
+ border-radius: 12px;
151
+ text-align: center;
152
+ }
153
+ .stat-val { font-size: 1.6rem; font-weight: 800; color: var(--primary); }
154
+ .stat-label { font-size: 0.8rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
155
+ h2 { font-size: 1.25rem; margin-bottom: 0.8rem; }
156
+ pre {
157
+ background: var(--code-bg);
158
+ border: 1px solid var(--border);
159
+ border-radius: 12px;
160
+ padding: 1.25rem;
161
+ overflow-x: auto;
162
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
163
+ font-size: 0.9rem;
164
+ color: #e2e8f0;
165
+ margin-bottom: 1.5rem;
166
+ }
167
+ .endpoint {
168
+ display: flex;
169
+ align-items: center;
170
+ gap: 0.5rem;
171
+ padding: 0.75rem 1rem;
172
+ background: rgba(16, 185, 129, 0.1);
173
+ border: 1px solid rgba(16, 185, 129, 0.3);
174
+ border-radius: 10px;
175
+ color: #34d399;
176
+ font-family: monospace;
177
+ font-size: 0.95rem;
178
+ margin-bottom: 2rem;
179
+ }
180
+ footer {
181
+ display: flex;
182
+ justify-content: space-between;
183
+ align-items: center;
184
+ padding-top: 1.5rem;
185
+ border-top: 1px solid var(--border);
186
+ font-size: 0.85rem;
187
+ color: var(--text-muted);
188
+ }
189
+ footer a { color: var(--primary); text-decoration: none; }
190
+ footer a:hover { text-decoration: underline; }
191
+ </style>
192
+ </head>
193
+ <body>
194
+ <div class="container">
195
+ <div class="badge"><span class="dot"></span> Online & Ready Ā· v${stats.version}</div>
196
+ <h1>Astro Components Kit MCP</h1>
197
+ <p class="lead">Model Context Protocol server for Astro 5.x. Connect this endpoint to Cursor, Claude Desktop, Windsurf, or Antigravity to let your AI build directly with the library.</p>
198
+
199
+ <div class="stats">
200
+ <div class="stat-box">
201
+ <div class="stat-val">${stats.totalComponents}+</div>
202
+ <div class="stat-label">Components</div>
203
+ </div>
204
+ <div class="stat-box">
205
+ <div class="stat-val">${stats.totalCategories}</div>
206
+ <div class="stat-label">Categories</div>
207
+ </div>
208
+ <div class="stat-box">
209
+ <div class="stat-val">${stats.totalTemplates}</div>
210
+ <div class="stat-label">Templates</div>
211
+ </div>
212
+ <div class="stat-box">
213
+ <div class="stat-val">WCAG AA</div>
214
+ <div class="stat-label">Accessible</div>
215
+ </div>
216
+ </div>
217
+
218
+ <h2>Connect via SSE URL</h2>
219
+ <div class="endpoint">
220
+ <strong>SSE Endpoint:</strong> ${serverUrl}/sse
221
+ </div>
222
+
223
+ <h2>Configuration (Cursor / Claude / Windsurf)</h2>
224
+ <pre>{
225
+ "mcpServers": {
226
+ "astro-components": {
227
+ "url": "${serverUrl}/sse"
228
+ }
229
+ }
230
+ }</pre>
231
+
232
+ <footer>
233
+ <span>Astro Components Kit v${stats.version}</span>
234
+ <div>
235
+ <a href="https://astrocomponents.dev" target="_blank">Docs</a> Ā·
236
+ <a href="https://github.com/konstantinwdk/astro-components" target="_blank">GitHub</a> Ā·
237
+ <a href="https://www.npmjs.com/package/astro-component-kit" target="_blank">npm</a>
238
+ </div>
239
+ </footer>
240
+ </div>
241
+ </body>
242
+ </html>`);
243
+ });
244
+
245
+ // 3. SSE Transport Endpoint (Client establishes SSE connection)
246
+ app.get('/sse', async (req: Request, res: Response) => {
247
+ try {
248
+ const server = createMcpServer();
249
+ const transport = new SSEServerTransport('/message', res);
250
+ const sessionId = transport.sessionId;
251
+
252
+ transports.set(sessionId, transport);
253
+
254
+ req.on('close', () => {
255
+ transports.delete(sessionId);
256
+ });
257
+
258
+ await server.connect(transport);
259
+ } catch (err: any) {
260
+ console.error('[mcp] Error establishing SSE session:', err?.message || err);
261
+ if (!res.headersSent) {
262
+ res.status(500).json({ error: 'Failed to establish SSE session' });
263
+ }
264
+ }
265
+ });
266
+
267
+ // 4. Message Endpoint (Client posts JSON-RPC calls)
268
+ app.post('/message', express.json({ limit: '256kb' }), async (req: Request, res: Response) => {
269
+ const sessionId = (req.query.sessionId as string) || '';
270
+ if (!sessionId) {
271
+ res.status(400).json({ error: 'Missing sessionId query parameter' });
272
+ return;
273
+ }
274
+
275
+ const transport = transports.get(sessionId);
276
+ if (!transport) {
277
+ res.status(404).json({ error: 'Session not found or expired' });
278
+ return;
279
+ }
280
+
281
+ try {
282
+ await transport.handlePostMessage(req, res);
283
+ } catch (err: any) {
284
+ console.error(`[mcp] Error handling message for session ${sessionId}:`, err?.message || err);
285
+ if (!res.headersSent) {
286
+ res.status(500).json({ error: 'Internal server error processing message' });
287
+ }
288
+ }
289
+ });
290
+
291
+ // Start HTTP listener
292
+ const serverInstance = app.listen(port, host, () => {
293
+ const stats = getLibraryStats();
294
+ console.log(`\nšŸš€ [Astro Components Kit MCP Server]`);
295
+ console.log(` Version: v${stats.version}`);
296
+ console.log(` Components: ${stats.totalComponents}`);
297
+ console.log(` Templates: ${stats.totalTemplates}`);
298
+ console.log(` HTTP/SSE: http://${host}:${port}/sse`);
299
+ console.log(` Health: http://${host}:${port}/health`);
300
+ console.log(` Rate limit: ${rateLimitMax} req/${rateLimitWindowMs / 1000}s\n`);
301
+ });
302
+
303
+ // Graceful shutdown
304
+ const shutdown = () => {
305
+ console.log('\n[mcp] Shutting down gracefully...');
306
+ for (const [, t] of transports) {
307
+ try {
308
+ t.close();
309
+ } catch {
310
+ // ignore
311
+ }
312
+ }
313
+ transports.clear();
314
+ serverInstance.close(() => {
315
+ console.log('[mcp] Server closed.');
316
+ process.exit(0);
317
+ });
318
+ };
319
+
320
+ process.on('SIGINT', shutdown);
321
+ process.on('SIGTERM', shutdown);
322
+
323
+ return serverInstance;
324
+ }
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ // src/mcp/index.ts
3
+ // CLI and entry point for Astro Components Kit MCP Server.
4
+ import { startHttpServer } from './http-server.js';
5
+ import { startStdioServer } from './stdio-server.js';
6
+ import { installMcpForClient } from './installer.js';
7
+
8
+ const args = process.argv.slice(2);
9
+ const firstArg = args[0]?.toLowerCase();
10
+
11
+ async function main() {
12
+ // 1. Install command: npx astro-component-kit mcp install <client>
13
+ if (firstArg === 'install' || (firstArg === 'mcp' && args[1]?.toLowerCase() === 'install')) {
14
+ const client = firstArg === 'install' ? args[1] : args[2];
15
+ if (!client) {
16
+ console.log(`\nUsage: npx astro-component-kit mcp install <cursor|claude|codex|lovable|mcp>`);
17
+ console.log(`Example: npx astro-component-kit mcp install cursor\n`);
18
+ process.exit(1);
19
+ }
20
+ const success = await installMcpForClient(client);
21
+ process.exit(success ? 0 : 1);
22
+ }
23
+
24
+ // 2. HTTP Server command: npx astro-component-kit mcp serve
25
+ if (firstArg === 'serve' || (firstArg === 'mcp' && args[1]?.toLowerCase() === 'serve')) {
26
+ startHttpServer();
27
+ return;
28
+ }
29
+
30
+ // 3. Stdio mode: if invoked with --stdio or piped
31
+ if (args.includes('--stdio') || firstArg === 'stdio' || (firstArg === 'mcp' && args[1]?.toLowerCase() === 'stdio')) {
32
+ startStdioServer().catch((err) => {
33
+ console.error('[mcp-stdio] Fatal error:', err);
34
+ process.exit(1);
35
+ });
36
+ return;
37
+ }
38
+
39
+ // 4. Default in production / Docker (PORT set): start HTTP server
40
+ if (process.env.PORT || process.env.COOLIFY_APP_ID || process.env.NODE_ENV === 'production') {
41
+ startHttpServer();
42
+ return;
43
+ }
44
+
45
+ // 5. Help output when invoked in terminal
46
+ console.log(`
47
+ šŸš€ Astro Components Kit — MCP Server (Model Context Protocol)
48
+
49
+ Usage:
50
+ npx astro-component-kit mcp install <cursor|claude|codex|lovable|mcp>
51
+ → Automatically configure your AI editor/agent to use Astro Components MCP
52
+
53
+ npx astro-component-kit mcp serve
54
+ → Start the remote SSE HTTP server locally (default port 3000)
55
+
56
+ npx astro-component-kit mcp --stdio
57
+ → Run in stdio mode for direct local MCP integration
58
+
59
+ Online Endpoint:
60
+ https://mcp.astrocomponents.dev/sse
61
+ `);
62
+ }
63
+
64
+ main().catch((err) => {
65
+ console.error('[mcp] Error:', err);
66
+ process.exit(1);
67
+ });
@@ -0,0 +1,178 @@
1
+ // src/mcp/installer.ts
2
+ // Automated 1-click CLI installer for Cursor, Claude, Codex, Lovable, Windsurf, Cline, and Universal MCP.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import os from 'node:os';
6
+
7
+ export type SupportedClient = 'cursor' | 'claude' | 'codex' | 'lovable' | 'mcp' | 'windsurf' | 'cline';
8
+
9
+ const MCP_SERVER_URL = 'https://mcp.astrocomponents.dev/sse';
10
+
11
+ const SERVER_CONFIG = {
12
+ url: MCP_SERVER_URL,
13
+ };
14
+
15
+ function getHomeDir(): string {
16
+ return os.homedir();
17
+ }
18
+
19
+ export function normalizeClient(input: string): SupportedClient | null {
20
+ const c = input.toLowerCase().trim();
21
+ if (c === 'cursor' || c === 'cursos') return 'cursor';
22
+ if (c === 'claude' || c === 'claude-desktop' || c === 'claude-code') return 'claude';
23
+ if (c === 'codex' || c === 'openai-codex' || c === 'copilot') return 'codex';
24
+ if (c === 'lovable' || c === 'lovable-dev') return 'lovable';
25
+ if (c === 'mcp' || c === 'universal' || c === 'generic') return 'mcp';
26
+ if (c === 'windsurf') return 'windsurf';
27
+ if (c === 'cline') return 'cline';
28
+ return null;
29
+ }
30
+
31
+ /**
32
+ * Returns the candidate configuration paths for each supported client.
33
+ */
34
+ function getClientConfigPaths(client: SupportedClient): { primary: string; fallback?: string } {
35
+ const home = getHomeDir();
36
+ const platform = os.platform();
37
+
38
+ switch (client) {
39
+ case 'cursor': {
40
+ const localCursor = path.resolve(process.cwd(), '.cursor/mcp.json');
41
+ const globalCursor = path.resolve(home, '.cursor/mcp.json');
42
+ return { primary: localCursor, fallback: globalCursor };
43
+ }
44
+ case 'claude': {
45
+ if (platform === 'darwin') {
46
+ return { primary: path.resolve(home, 'Library/Application Support/Claude/claude_desktop_config.json') };
47
+ }
48
+ if (platform === 'win32') {
49
+ const appData = process.env.APPDATA || path.resolve(home, 'AppData/Roaming');
50
+ return { primary: path.resolve(appData, 'Claude/claude_desktop_config.json') };
51
+ }
52
+ return { primary: path.resolve(home, '.config/Claude/claude_desktop_config.json') };
53
+ }
54
+ case 'codex': {
55
+ const localCodex = path.resolve(process.cwd(), '.codex/mcp.json');
56
+ const globalCodex = path.resolve(home, '.codex/config.json');
57
+ return { primary: localCodex, fallback: globalCodex };
58
+ }
59
+ case 'lovable': {
60
+ const localLovable = path.resolve(process.cwd(), '.lovable/mcp.json');
61
+ const globalLovable = path.resolve(home, '.lovable/config.json');
62
+ return { primary: localLovable, fallback: globalLovable };
63
+ }
64
+ case 'mcp': {
65
+ const localMcp = path.resolve(process.cwd(), 'mcp.json');
66
+ const globalMcp = path.resolve(home, '.mcp/config.json');
67
+ return { primary: localMcp, fallback: globalMcp };
68
+ }
69
+ case 'windsurf': {
70
+ return { primary: path.resolve(home, '.codeium/windsurf/mcp_config.json') };
71
+ }
72
+ case 'cline': {
73
+ if (platform === 'darwin') {
74
+ return {
75
+ primary: path.resolve(
76
+ home,
77
+ 'Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json'
78
+ ),
79
+ };
80
+ }
81
+ if (platform === 'win32') {
82
+ const appData = process.env.APPDATA || path.resolve(home, 'AppData/Roaming');
83
+ return {
84
+ primary: path.resolve(
85
+ appData,
86
+ 'Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json'
87
+ ),
88
+ };
89
+ }
90
+ return {
91
+ primary: path.resolve(
92
+ home,
93
+ '.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json'
94
+ ),
95
+ };
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Installs or updates the astro-components MCP server in the target client's configuration.
102
+ */
103
+ export async function installMcpForClient(targetClient: string): Promise<boolean> {
104
+ const client = normalizeClient(targetClient);
105
+ const validClients: SupportedClient[] = ['cursor', 'claude', 'codex', 'lovable', 'mcp', 'windsurf', 'cline'];
106
+
107
+ if (!client) {
108
+ console.error(`\nāŒ Unknown client "${targetClient}".`);
109
+ console.log(` Supported clients: ${validClients.join(', ')}`);
110
+ console.log(`\nExamples:`);
111
+ console.log(` npx astro-component-kit mcp install cursor`);
112
+ console.log(` npx astro-component-kit mcp install claude`);
113
+ console.log(` npx astro-component-kit mcp install codex`);
114
+ console.log(` npx astro-component-kit mcp install lovable`);
115
+ console.log(` npx astro-component-kit mcp install mcp\n`);
116
+ return false;
117
+ }
118
+
119
+ const { primary } = getClientConfigPaths(client);
120
+ const targetDir = path.dirname(primary);
121
+
122
+ console.log(`\nšŸ“¦ Configuring Astro Components Kit MCP for [${client}]...`);
123
+ console.log(` Target config: ${primary}`);
124
+
125
+ try {
126
+ if (!fs.existsSync(targetDir)) {
127
+ fs.mkdirSync(targetDir, { recursive: true });
128
+ }
129
+
130
+ let config: any = {};
131
+ if (fs.existsSync(primary)) {
132
+ try {
133
+ const raw = fs.readFileSync(primary, 'utf8');
134
+ config = JSON.parse(raw);
135
+ } catch {
136
+ config = {};
137
+ }
138
+ }
139
+
140
+ if (!config || typeof config !== 'object') {
141
+ config = {};
142
+ }
143
+
144
+ if (!config.mcpServers || typeof config.mcpServers !== 'object') {
145
+ config.mcpServers = {};
146
+ }
147
+
148
+ // Add or update astro-components server
149
+ config.mcpServers['astro-components'] = SERVER_CONFIG;
150
+
151
+ fs.writeFileSync(primary, JSON.stringify(config, null, 2) + '\n', 'utf8');
152
+
153
+ console.log(`\nāœ… Successfully installed!`);
154
+ console.log(` Server name: "astro-components"`);
155
+ console.log(` Endpoint: ${MCP_SERVER_URL}`);
156
+ console.log(`\nšŸ’” What to do next:`);
157
+ console.log(` Restart ${client.toUpperCase()} (or reload MCP servers), then prompt your AI:`);
158
+ console.log(` > "Search astro-components for ecommerce cards and buy box"`);
159
+ console.log(` > "Insert a KPI stat tile chart from astro-components"\n`);
160
+ return true;
161
+ } catch (err: any) {
162
+ console.error(`\nāŒ Failed to write configuration: ${err?.message || err}`);
163
+ console.log(`\nYou can configure it manually by adding this JSON:`);
164
+ console.log(
165
+ JSON.stringify(
166
+ {
167
+ mcpServers: {
168
+ 'astro-components': SERVER_CONFIG,
169
+ },
170
+ },
171
+ null,
172
+ 2
173
+ )
174
+ );
175
+ return false;
176
+ }
177
+ }
178
+