Skip to main content
Glama
Jpisnice

@jpisnice/shadcn-ui-mcp-server

by Jpisnice

list_components

Read-only

Retrieve a list of all available shadcn/ui v4 components to understand component structure and installation.

Instructions

Get all available shadcn/ui v4 components

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main handler function 'handleListComponents' that executes the tool logic. It fetches available components via axios (which calls GitHub API), sorts them, and returns the list as JSON text.
    import { getAxiosImplementation } from '../../utils/framework.js';
    import { logError } from '../../utils/logger.js';
    
    export async function handleListComponents() {
      try {
        const axios = await getAxiosImplementation();
        const components = await axios.getAvailableComponents();
        return {
          content: [{ 
            type: "text", 
            text: JSON.stringify({ 
              components: components.sort(),
              total: components.length 
            }, null, 2) 
          }]
        };
      } catch (error) {
        logError('Failed to list components', error);
        throw new Error(`Failed to list components: ${error instanceof Error ? error.message : String(error)}`);
      }
    }
    
    export const schema = {}; 
  • The schema for list_components is an empty object (no input parameters required).
    export const schema = {}; 
  • src/tools/index.ts:3-3 (registration)
    Import of the handleListComponents function into the central tools registry.
    import { handleListComponents } from './components/list-components.js';
  • Import of the listComponentsSchema (empty object) into the central tools registry.
    import { schema as listComponentsSchema } from './components/list-components.js';
  • Registration of list_components tool handler in the toolHandlers map.
    list_components: handleListComponents,
  • Registration of listComponentsSchema in the toolSchemas map.
    list_components: listComponentsSchema,
  • Full tool definition for 'list_components' including name, description, and inputSchema (no required params).
    'list_components': {
      name: 'list_components',
      description: 'Get all available shadcn/ui v4 components',
      inputSchema: {
        type: 'object',
        properties: {}
      }
    },
  • The getAxiosImplementation helper that selects the right axios module based on the configured framework (react, svelte, vue, or react-native). Used by the handler to get the correct axios instance.
    export async function getAxiosImplementation() {
      const framework = getFramework();
    
      if (framework === "svelte") {
        // Dynamic import for Svelte implementation
        return import("./axios-svelte.js").then((module) => module.axios);
      } else if (framework === "vue") {
        // Dynamic import for Vue implementation
        return import("./axios-vue.js").then((module) => module.axios);
      } else if (framework === "react-native") {
        // Dynamic import for React Native implementation
        return import("./axios-react-native.js").then((module) => module.axios);
      } else {
        // Dynamic import for React implementation (default)
        return import("./axios.js").then((module) => module.axios);
      }
    }
  • The getAvailableComponents function that actually fetches the component list from the GitHub API (or falls back to a hardcoded list of known shadcn/ui v4 components).
    async function getAvailableComponents(): Promise<string[]> {
        const basePath = getRegistryBasePath();
        try {
            // First try the GitHub API
            const response = await githubApi.get(`/repos/${REPO_OWNER}/${REPO_NAME}/contents/${basePath}/ui`);
            
            if (!response.data || !Array.isArray(response.data)) {
                throw new Error('Invalid response from GitHub API');
            }
            
            const components = response.data
                .filter((item: any) => item.type === 'file' && item.name.endsWith('.tsx'))
                .map((item: any) => item.name.replace('.tsx', ''));
                
            if (components.length === 0) {
                throw new Error('No components found in the registry');
            }
            
            return components;
        } catch (error: any) {
            logError('Error fetching components from GitHub API', error);
            
            // Check for specific error types
            if (error.response) {
                const status = error.response.status;
                const message = error.response.data?.message || 'Unknown error';
                
                if (status === 403 && message.includes('rate limit')) {
                    throw new Error(`GitHub API rate limit exceeded. Please set GITHUB_PERSONAL_ACCESS_TOKEN environment variable for higher limits. Error: ${message}`);
                } else if (status === 404) {
                    throw new Error(`Components directory not found. The path ${basePath}/ui may not exist in the repository.`);
                } else if (status === 401) {
                    throw new Error(`Authentication failed. Please check your GITHUB_PERSONAL_ACCESS_TOKEN if provided.`);
                } else {
                    throw new Error(`GitHub API error (${status}): ${message}`);
                }
            }
            
            // If it's a network error or other issue, provide a fallback
            if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT') {
                throw new Error(`Network error: ${error.message}. Please check your internet connection.`);
            }
            
            // If all else fails, provide a fallback list of known components
            logWarning('Using fallback component list due to API issues');
            return getUiLibrary() === 'base' ? getFallbackComponentsBase() : getFallbackComponents();
        }
    }
  • Tool definition in capabilities.ts, declaring list_components with description and inputSchema.
    list_components: {
      description: "Get all available shadcn/ui v4 components",
      inputSchema: {
        type: "object",
        properties: {},
      },
    },
  • Tool definition in the ListToolsRequestSchema handler in server/handler.ts, registering list_components with name, description, inputSchema, and annotations.
      name: 'list_components',
      description: 'Get all available shadcn/ui v4 components',
      inputSchema: {
        type: 'object',
        properties: {},
      },
      annotations: {
        title: "List Components",
        readOnlyHint: true,
      },
    },

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv1.0.0

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint: true, so the description isn't required to restate that. It adds no additional context (e.g., return format, scope, rate limits), but it doesn't contradict the annotation. The description is adequate but adds no extra behavioral disclosure beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence: 'Get all available shadcn/ui v4 components.' It is front-loaded and contains no fluff, making it easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is minimal and adequate for a simple listing tool, but since there is no output schema, it could benefit from specifying what information is returned (e.g., component names, IDs, or metadata) and how it relates to sibling tools like get_component. Without these details, an agent might not know what to expect from the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so schema coverage is trivially 100%. The baseline for zero-parameter tools is 4, and the description doesn't need to explain any parameters. This score is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists all available shadcn/ui v4 components. It uses a specific verb and resource, and the 'all available' phrasing implies a listing function, which distinguishes it from sibling tools like get_component that retrieve individual components. However, it doesn't explicitly contrast with siblings, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. While 'all available' hints at an overview purpose, the description doesn't explicitly mention using it over get_component or other siblings, nor does it state when not to use it. This is a notable gap given the rich sibling list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.