11#!/usr/bin/env node
2- /**
3- * Shadcn UI v4 MCP Server
4- *
5- * A Model Context Protocol server for shadcn/ui v4 components.
6- * Provides AI assistants with access to component source code, demos, blocks, and metadata.
7- *
8- * Usage:
9- * npx shadcn-ui-mcp-server
10- * npx shadcn-ui-mcp-server --github-api-key YOUR_TOKEN
11- * npx shadcn-ui-mcp-server -g YOUR_TOKEN
12- */
13- import { Server } from "@modelcontextprotocol/sdk/server/index.js"
14- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
15- import { setupHandlers } from "./handler.js"
16- import {
17- validateFrameworkSelection ,
18- getAxiosImplementation ,
19- } from "./utils/framework.js"
20- import { z } from "zod"
21- import { toolHandlers , toolSchemas } from "./tools/index.js"
22- import { logError , logInfo , logWarning } from "./utils/logger.js"
2+ import { start } from "./server/index.js"
3+ import { logError } from "./utils/logger.js"
234
24- /**
25- * Parse command line arguments
26- */
27- async function parseArgs ( ) {
28- const args = process . argv . slice ( 2 )
29-
30- // Help flag
31- if ( args . includes ( "--help" ) || args . includes ( "-h" ) ) {
32- console . log ( `
33- Shadcn UI v4 MCP Server
34-
35- Usage:
36- npx shadcn-ui-mcp-server [options]
37-
38- Options:
39- --github-api-key, -g <token> GitHub Personal Access Token for API access
40- --framework, -f <framework> Framework to use: 'react' or 'svelte' (default: react)
41- --help, -h Show this help message
42- --version, -v Show version information
43-
44- Examples:
45- npx shadcn-ui-mcp-server
46- npx shadcn-ui-mcp-server --github-api-key ghp_your_token_here
47- npx shadcn-ui-mcp-server -g ghp_your_token_here
48- npx shadcn-ui-mcp-server --framework svelte
49- npx shadcn-ui-mcp-server -f react
50-
51- Environment Variables:
52- GITHUB_PERSONAL_ACCESS_TOKEN Alternative way to provide GitHub token
53- FRAMEWORK Framework to use: 'react' or 'svelte' or 'vue' (default: react)
54- LOG_LEVEL Log level (debug, info, warn, error) - default: info
55-
56- For more information, visit: https://github.com/Jpisnice/shadcn-ui-mcp-server
57- ` )
58- process . exit ( 0 )
59- }
60-
61- // Version flag
62- if ( args . includes ( "--version" ) || args . includes ( "-v" ) ) {
63- // Read version from package.json
64- try {
65- const fs = await import ( "fs" )
66- const path = await import ( "path" )
67- const { fileURLToPath} = await import ( "url" )
68-
69- const __filename = fileURLToPath ( import . meta. url )
70- const __dirname = path . dirname ( __filename )
71- const packagePath = path . join ( __dirname , ".." , "package.json" )
72-
73- const packageContent = fs . readFileSync ( packagePath , "utf8" )
74- const packageJson = JSON . parse ( packageContent )
75- console . log ( `shadcn-ui-mcp-server v${ packageJson . version } ` )
76- } catch ( error ) {
77- console . log ( "shadcn-ui-mcp-server v1.0.2" )
78- }
79- process . exit ( 0 )
80- }
81-
82- // GitHub API key
83- const githubApiKeyIndex = args . findIndex (
84- ( arg ) => arg === "--github-api-key" || arg === "-g"
85- )
86- let githubApiKey = null
87-
88- if ( githubApiKeyIndex !== - 1 && args [ githubApiKeyIndex + 1 ] ) {
89- githubApiKey = args [ githubApiKeyIndex + 1 ]
90- } else if ( process . env . GITHUB_PERSONAL_ACCESS_TOKEN ) {
91- githubApiKey = process . env . GITHUB_PERSONAL_ACCESS_TOKEN
92- }
93-
94- return { githubApiKey}
95- }
96-
97- /**
98- * Main function to start the MCP server
99- */
100- async function main ( ) {
101- try {
102- logInfo ( "Starting Shadcn UI v4 MCP Server..." )
103-
104- const { githubApiKey} = await parseArgs ( )
105-
106- // Validate and log framework selection
107- validateFrameworkSelection ( )
108-
109- // Get the appropriate axios implementation based on framework
110- const axios = await getAxiosImplementation ( )
111-
112- // Configure GitHub API key if provided
113- if ( githubApiKey ) {
114- axios . setGitHubApiKey ( githubApiKey )
115- logInfo ( "GitHub API configured with token" )
116- } else {
117- logWarning (
118- "No GitHub API key provided. Rate limited to 60 requests/hour."
119- )
120- }
121-
122- // Initialize the MCP server with metadata and capabilities
123- // Following MCP SDK 1.16.0 best practices
124- const server = new Server (
125- {
126- name :"shadcn-ui-mcp-server" ,
127- version :"1.0.2" ,
128- } ,
129- {
130- capabilities :{
131- resources :{
132- get_components :{
133- description :
134- "List of available shadcn/ui components that can be used in the project" ,
135- uri :"resource:get_components" ,
136- contentType :"text/plain" ,
137- } ,
138- get_install_script_for_component :{
139- description :
140- "Generate installation script for a specific shadcn/ui component based on package manager" ,
141- uriTemplate :
142- "resource-template:get_install_script_for_component?packageManager={packageManager}&component={component}" ,
143- contentType :"text/plain" ,
144- } ,
145- get_installation_guide :{
146- description :
147- "Get the installation guide for shadcn/ui based on build tool and package manager" ,
148- uriTemplate :
149- "resource-template:get_installation_guide?buildTool={buildTool}&packageManager={packageManager}" ,
150- contentType :"text/plain" ,
151- } ,
152- } ,
153- prompts :{
154- component_usage :{
155- description :"Get usage examples for a specific component" ,
156- arguments :{
157- componentName :{
158- type :"string" ,
159- description :"Name of the component to get usage for" ,
160- } ,
161- } ,
162- } ,
163- component_search :{
164- description :"Search for components by name or description" ,
165- arguments :{
166- query :{
167- type :"string" ,
168- description :"Search query" ,
169- } ,
170- } ,
171- } ,
172- component_comparison :{
173- description :"Compare two components side by side" ,
174- arguments :{
175- component1 :{
176- type :"string" ,
177- description :"First component name" ,
178- } ,
179- component2 :{
180- type :"string" ,
181- description :"Second component name" ,
182- } ,
183- } ,
184- } ,
185- component_recommendation :{
186- description :"Get component recommendations based on use case" ,
187- arguments :{
188- useCase :{
189- type :"string" ,
190- description :"Use case description" ,
191- } ,
192- } ,
193- } ,
194- component_tutorial :{
195- description :"Get a step-by-step tutorial for using a component" ,
196- arguments :{
197- componentName :{
198- type :"string" ,
199- description :"Name of the component for tutorial" ,
200- } ,
201- } ,
202- } ,
203- } ,
204- tools :{
205- get_component :{
206- description :
207- "Get the source code for a specific shadcn/ui v4 component" ,
208- inputSchema :{
209- type :"object" ,
210- properties :{
211- componentName :{
212- type :"string" ,
213- description :
214- 'Name of the shadcn/ui component (e.g., "accordion", "button")' ,
215- } ,
216- } ,
217- required :[ "componentName" ] ,
218- } ,
219- } ,
220- get_component_demo :{
221- description :
222- "Get demo code illustrating how a shadcn/ui v4 component should be used" ,
223- inputSchema :{
224- type :"object" ,
225- properties :{
226- componentName :{
227- type :"string" ,
228- description :
229- 'Name of the shadcn/ui component (e.g., "accordion", "button")' ,
230- } ,
231- } ,
232- required :[ "componentName" ] ,
233- } ,
234- } ,
235- list_components :{
236- description :"Get all available shadcn/ui v4 components" ,
237- inputSchema :{
238- type :"object" ,
239- properties :{ } ,
240- } ,
241- } ,
242- get_component_metadata :{
243- description :"Get metadata for a specific shadcn/ui v4 component" ,
244- inputSchema :{
245- type :"object" ,
246- properties :{
247- componentName :{
248- type :"string" ,
249- description :
250- 'Name of the shadcn/ui component (e.g., "accordion", "button")' ,
251- } ,
252- } ,
253- required :[ "componentName" ] ,
254- } ,
255- } ,
256- get_directory_structure :{
257- description :
258- "Get the directory structure of the shadcn-ui v4 repository" ,
259- inputSchema :{
260- type :"object" ,
261- properties :{
262- path :{
263- type :"string" ,
264- description :
265- "Path within the repository (default: v4 registry)" ,
266- } ,
267- owner :{
268- type :"string" ,
269- description :'Repository owner (default: "shadcn-ui")' ,
270- } ,
271- repo :{
272- type :"string" ,
273- description :'Repository name (default: "ui")' ,
274- } ,
275- branch :{
276- type :"string" ,
277- description :'Branch name (default: "main")' ,
278- } ,
279- } ,
280- } ,
281- } ,
282- get_block :{
283- description :
284- "Get source code for a specific shadcn/ui v4 block (e.g., calendar-01, dashboard-01)" ,
285- inputSchema :{
286- type :"object" ,
287- properties :{
288- blockName :{
289- type :"string" ,
290- description :
291- 'Name of the block (e.g., "calendar-01", "dashboard-01", "login-02")' ,
292- } ,
293- includeComponents :{
294- type :"boolean" ,
295- description :
296- "Whether to include component files for complex blocks (default: true)" ,
297- } ,
298- } ,
299- required :[ "blockName" ] ,
300- } ,
301- } ,
302- list_blocks :{
303- description :
304- "Get all available shadcn/ui v4 blocks with categorization" ,
305- inputSchema :{
306- type :"object" ,
307- properties :{
308- category :{
309- type :"string" ,
310- description :
311- "Filter by category (calendar, dashboard, login, sidebar, products)" ,
312- } ,
313- } ,
314- } ,
315- } ,
316- } ,
317- } ,
318- }
319- )
320-
321- // Set up request handlers and register components (tools, resources, etc.)
322- setupHandlers ( server )
323-
324- // Start server using stdio transport
325- const transport = new StdioServerTransport ( )
326-
327- logInfo ( "Transport initialized: stdio" )
328-
329- await server . connect ( transport )
330-
331- logInfo ( "Server started successfully" )
332- } catch ( error ) {
333- logError ( "Failed to start server" , error )
334- process . exit ( 1 )
335- }
336- }
337-
338- // Start the server
339- main ( ) . catch ( ( error ) => {
5+ start ( ) . catch ( ( error :Error ) => {
3406logError ( "Unhandled startup error" , error )
3417process . exit ( 1 )
342- } )
8+ } )