#
tokens: 5286/50000 10/10 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── LICENSE.md
├── package-lock.json
├── package.json
├── public
│   └── mcp.png
├── README.md
├── src
│   ├── server.ts
│   └── utils
│       ├── api.ts
│       ├── formatters.ts
│       ├── index.ts
│       └── schemas.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
node_modules/
.DS_Store
dist/
tsconfig.tsbuildinfo
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# @magicuidesign/mcp

[![npm version](https://badge.fury.io/js/@magicuidesign%2Fmcp.svg?icon=si%3Anpm)](https://badge.fury.io/js/@magicuidesign%2Fmcp)

Official ModelContextProtocol (MCP) server for [Magic UI](https://magicui.design/).

<div align="center">
  <img src="https://github.com/magicuidesign/mcp/blob/main/public/mcp.png" alt="MCP" />
</div>

## Install MCP configuration

```bash
npx @magicuidesign/cli@latest install <client>
```

### Supported Clients

- [x] cursor
- [x] windsurf
- [x] claude
- [x] cline
- [x] roo-cline

## Manual Installation

Add to your IDE's MCP config:

```json
{
  "mcpServers": {
    "@magicuidesign/mcp": {
      "command": "npx",
      "args": ["-y", "@magicuidesign/mcp@latest"]
    }
  }
}
```

## Example Usage

Once configured, you can questions like:

> "Make a marquee of logos"

> "Add a blur fade text animation"

> "Add a grid background"

## Available Tools

The server provides the following tools callable via MCP:

| Tool Name       | Description                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `getUIComponents` | Provides a comprehensive list of all Magic UI components.                                                                                                                                                                                                                                                                                                                                                     |
| `getLayout`       | Provides implementation details for [bento-grid](https://magicui.design/docs/components/bento-grid), [dock](https://magicui.design/docs/components/dock), [file-tree](https://magicui.design/docs/components/file-tree), [grid-pattern](https://magicui.design/docs/components/grid-pattern), [interactive-grid-pattern](https://magicui.design/docs/components/interactive-grid-pattern), [dot-pattern](https://magicui.design/docs/components/dot-pattern) components.         |
| `getMedia`        | Provides implementation details for [hero-video-dialog](https://magicui.design/docs/components/hero-video-dialog), [terminal](https://magicui.design/docs/components/terminal), [marquee](https://magicui.design/docs/components/marquee), [script-copy-btn](https://magicui.design/docs/components/script-copy-btn), [code-comparison](https://magicui.design/docs/components/code-comparison) components.                                                               |
| `getMotion`       | Provides implementation details for [blur-fade](https://magicui.design/docs/components/blur-fade), [scroll-progress](https://magicui.design/docs/components/scroll-progress), [scroll-based-velocity](https://magicui.design/docs/components/scroll-based-velocity), [orbiting-circles](https://magicui.design/docs/components/orbiting-circles), [animated-circular-progress-bar](https://magicui.design/docs/components/animated-circular-progress-bar) components. |
| `getTextReveal`   | Provides implementation details for [text-animate](https://magicui.design/docs/components/text-animate), [line-shadow-text](https://magicui.design/docs/components/line-shadow-text), [aurora-text](https://magicui.design/docs/components/aurora-text), [animated-shiny-text](https://magicui.design/docs/components/animated-shiny-text), [animated-gradient-text](https://magicui.design/docs/components/animated-gradient-text), [text-reveal](https://magicui.design/docs/components/text-reveal), [typing-animation](https://magicui.design/docs/components/typing-animation), [box-reveal](https://magicui.design/docs/components/box-reveal), [number-ticker](https://magicui.design/docs/components/number-ticker) components. |
| `getTextEffects`  | Provides implementation details for [word-rotate](https://magicui.design/docs/components/word-rotate), [flip-text](https://magicui.design/docs/components/flip-text), [hyper-text](https://magicui.design/docs/components/hyper-text), [morphing-text](https://magicui.design/docs/components/morphing-text), [spinning-text](https://magicui.design/docs/components/spinning-text), [sparkles-text](https://magicui.design/docs/components/sparkles-text) components.       |
| `getButtons`      | Provides implementation details for [rainbow-button](https://magicui.design/docs/components/rainbow-button), [shimmer-button](https://magicui.design/docs/components/shimmer-button), [shiny-button](https://magicui.design/docs/components/shiny-button), [interactive-hover-button](https://magicui.design/docs/components/interactive-hover-button), [animated-subscribe-button](https://magicui.design/docs/components/animated-subscribe-button), [pulsating-button](https://magicui.design/docs/components/pulsating-button), [ripple-button](https://magicui.design/docs/components/ripple-button) components. |
| `getEffects`      | Provides implementation details for [animated-beam](https://magicui.design/docs/components/animated-beam), [border-beam](https://magicui.design/docs/components/border-beam), [shine-border](https://magicui.design/docs/components/shine-border), [magic-card](https://magicui.design/docs/components/magic-card), [meteors](https://magicui.design/docs/components/meteors), [neon-gradient-card](https://magicui.design/docs/components/neon-gradient-card), [confetti](https://magicui.design/docs/components/confetti), [particles](https://magicui.design/docs/components/particles), [cool-mode](https://magicui.design/docs/components/cool-mode), [scratch-to-reveal](https://magicui.design/docs/components/scratch-to-reveal) components. |
| `getWidgets`      | Provides implementation details for [animated-list](https://magicui.design/docs/components/animated-list), [tweet-card](https://magicui.design/docs/components/tweet-card), [client-tweet-card](https://magicui.design/docs/components/client-tweet-card), [lens](https://magicui.design/docs/components/lens), [pointer](https://magicui.design/docs/components/pointer), [avatar-circles](https://magicui.design/docs/components/avatar-circles), [icon-cloud](https://magicui.design/docs/components/icon-cloud), [globe](https://magicui.design/docs/components/globe) components.                                |
| `getBackgrounds`  | Provides implementation details for [warp-background](https://magicui.design/docs/components/warp-background), [flickering-grid](https://magicui.design/docs/components/flickering-grid), [animated-grid-pattern](https://magicui.design/docs/components/animated-grid-pattern), [retro-grid](https://magicui.design/docs/components/retro-grid), [ripple](https://magicui.design/docs/components/ripple) components.                                                               |
| `getDevices`      | Provides implementation details for [safari](https://magicui.design/docs/components/safari), [iphone-15-pro](https://magicui.design/docs/components/iphone-15-pro), [android](https://magicui.design/docs/components/android) components.                                                                                                                                                            |

## MCP Limitations

Some clients have a [limit](https://docs.cursor.com/context/model-context-protocol#limitations) on the number of tools they can call. This is why we opted to group the tools into categories. Note: For more specific context on each component, run the MCP locally and modify the logic that groups the components.

## Credits

Big thanks to [@beaubhp](https://github.com/beaubhp) for creating the MCP server 🙏

[MIT](https://github.com/magicuidesign/mcp/blob/main/LICENSE.md)
```

--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------

```markdown
MIT License

Copyright (c) Magic UI

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

```

--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------

```typescript
export * from "./api.js";
export * from "./formatters.js";
export * from "./schemas.js";

```

--------------------------------------------------------------------------------
/src/utils/formatters.ts:
--------------------------------------------------------------------------------

```typescript
// Helper function to format component names
export function formatComponentName(name: string): string {
  return name
    .split("-")
    .map((part) => {
      return part.charAt(0).toUpperCase() + part.slice(1);
    })
    .join("");
}

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "baseUrl": ".",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "ES2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitAny": true, 
    "module": "esnext",
    "moduleResolution": "bundler",
    "outDir": "dist",
    "rootDir": "src",
    "sourceMap": true,
    "declaration": true,
    "incremental": true,
  },
  "include": ["**/*.ts"],
  "exclude": ["node_modules", "dist"]
} 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "@magicuidesign/mcp",
  "version": "1.0.6",
  "description": "Official MCP server for Magic UI.",
  "homepage": "https://magicui.design",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/magicuidesign/mcp.git"
  },
  "scripts": {
    "build": "tsc && shx chmod +x dist/*.js",
    "start": "node dist/server.js",
    "dev": "nodemon --watch src --ext ts,json --exec \"npm run build\""
  },
  "type": "module",
  "main": "./dist/server.js",
  "module": "./dist/server.js",
  "types": "./dist/server.d.ts",
  "bin": {
    "mcp": "./dist/server.js"
  },
  "files": [
    "dist"
  ],
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.9.0",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@types/node": "^22.14.1",
    "nodemon": "^3.1.0",
    "shx": "^0.4.0",
    "typescript": "^5.8.3"
  },
  "author": "Beau Hayes-Pollard <[email protected]>",
  "license": "ISC"
}

```

--------------------------------------------------------------------------------
/src/utils/schemas.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from "zod";

// Define schema for general component
export const ComponentSchema = z.object({
  name: z.string(),
  type: z.string(),
  description: z.string().optional(), // Only optional because of interactive-hover-button
});

// Define schema for an individual example
const ExampleSchema = z.object({
  name: z.string(),
  type: z.string(),
  description: z.string(),
  content: z.string(),
});

// Define schema for individual component with content and examples
export const IndividualComponentSchema = ComponentSchema.extend({
  install: z.string(),
  content: z.string(),
  examples: z.array(ExampleSchema),
});

// Define schema for component detail response
export const ComponentDetailSchema = z.object({
  name: z.string(),
  type: z.string(),
  files: z.array(
    z.object({
      content: z.string(),
    }),
  ),
});

// Define schema for example component
export const ExampleComponentSchema = z.object({
  name: z.string(),
  type: z.string(),
  description: z.string(),
  registryDependencies: z.array(z.string()),
});

// Define schema for example detail response
export const ExampleDetailSchema = z.object({
  name: z.string(),
  type: z.string(),
  description: z.string(),
  files: z.array(
    z.object({
      content: z.string(),
    }),
  ),
});

```

--------------------------------------------------------------------------------
/src/utils/api.ts:
--------------------------------------------------------------------------------

```typescript
import {
  ComponentDetailSchema,
  ComponentSchema,
  ExampleComponentSchema,
  ExampleDetailSchema,
} from "./schemas.js";

// Function to fetch UI components
export async function fetchUIComponents() {
  try {
    const response = await fetch("https://magicui.design/registry.json");
    if (!response.ok) {
      throw new Error(
        `Failed to fetch registry.json: ${response.statusText} (Status: ${response.status})`,
      );
    }
    const data = await response.json();

    return data.items
      .filter((item: any) => item.type === "registry:ui")
      .map((item: any) => {
        try {
          return ComponentSchema.parse({
            name: item.name,
            type: item.type,
            description: item.description,
          });
        } catch (parseError) {
          return null;
        }
      });
  } catch (error) {
    return [];
  }
}

// Function to fetch individual component details
export async function fetchComponentDetails(name: string) {
  try {
    const response = await fetch(`https://magicui.design/r/${name}`);
    if (!response.ok) {
      throw new Error(
        `Failed to fetch component ${name}: ${response.statusText}`,
      );
    }
    const data = await response.json();
    return ComponentDetailSchema.parse(data);
  } catch (error) {
    console.error(`Error fetching component ${name}:`, error);
    throw error;
  }
}

// Function to fetch example components
export async function fetchExampleComponents() {
  try {
    const response = await fetch("https://magicui.design/registry.json");
    const data = await response.json();

    return data.items
      .filter((item: any) => item.type === "registry:example")
      .map((item: any) => {
        return ExampleComponentSchema.parse({
          name: item.name,
          type: item.type,
          description: item.description,
          registryDependencies: item.registryDependencies,
        });
      });
  } catch (error) {
    console.error("Error fetching MagicUI example components:", error);
    return [];
  }
}

// Function to fetch details for a specific example
export async function fetchExampleDetails(exampleName: string) {
  try {
    const response = await fetch(`https://magicui.design/r/${exampleName}`);
    if (!response.ok) {
      throw new Error(
        `Failed to fetch example details for ${exampleName}: ${response.statusText}`,
      );
    }
    const data = await response.json();
    return ExampleDetailSchema.parse(data);
  } catch (error) {
    console.error(`Error fetching example details for ${exampleName}:`, error);
    throw error;
  }
}

```

--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  IndividualComponentSchema,
  fetchComponentDetails,
  fetchExampleComponents,
  fetchExampleDetails,
  fetchUIComponents,
} from "./utils/index.js";
import { formatComponentName } from "./utils/formatters.js";

// Initialize the MCP Server
const server = new McpServer({
  name: "Magic UI MCP",
  version: "1.0.4",
});

// Register the main tool for getting all components
server.tool(
  "getUIComponents",
  "Provides a comprehensive list of all Magic UI components.",
  {},
  async () => {
    try {
      const uiComponents = await fetchUIComponents();

      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(uiComponents, null, 2),
          },
        ],
      };
    } catch (error) {
      return {
        content: [
          {
            type: "text",
            text: "Failed to fetch MagicUI components",
          },
        ],
        isError: true,
      };
    }
  },
);

// Maps component names to their example implementations
function buildExampleComponentMap(
  allExampleComponents: Array<{
    name: string;
    registryDependencies?: string[];
  }>,
): Map<string, string[]> {
  const exampleMap = new Map<string, string[]>();

  for (const example of allExampleComponents) {
    if (
      example.registryDependencies &&
      Array.isArray(example.registryDependencies)
    ) {
      for (const depUrl of example.registryDependencies) {
        if (typeof depUrl === "string" && depUrl.includes("magicui.design")) {
          const componentNameMatch = depUrl.match(/\/r\/([^\/]+)$/);
          if (componentNameMatch && componentNameMatch[1]) {
            const componentName = componentNameMatch[1];
            if (!exampleMap.has(componentName)) {
              exampleMap.set(componentName, []);
            }
            if (!exampleMap.get(componentName)?.includes(example.name)) {
              exampleMap.get(componentName)?.push(example.name);
            }
          }
        }
      }
    }
  }
  return exampleMap;
}

// Component category definitions
const componentCategories = {
  Layout: [
    "bento-grid",
    "dock",
    "file-tree",
    "grid-pattern",
    "interactive-grid-pattern",
    "dot-pattern",
  ],
  Media: [
    "hero-video-dialog",
    "terminal",
    "marquee",
    "script-copy-btn",
    "code-comparison",
  ],
  Motion: [
    "blur-fade",
    "scroll-progress",
    "scroll-based-velocity",
    "orbiting-circles",
    "animated-circular-progress-bar",
  ],
  TextReveal: [
    "text-animate",
    "line-shadow-text",
    "aurora-text",
    "animated-shiny-text",
    "animated-gradient-text",
    "text-reveal",
    "typing-animation",
    "box-reveal",
    "number-ticker",
  ],
  TextEffects: [
    "word-rotate",
    "flip-text",
    "hyper-text",
    "morphing-text",
    "spinning-text",
    "sparkles-text",
  ],
  Buttons: [
    "rainbow-button",
    "shimmer-button",
    "shiny-button",
    "interactive-hover-button",
    "animated-subscribe-button",
    "pulsating-button",
    "ripple-button",
  ],
  Effects: [
    "animated-beam",
    "border-beam",
    "shine-border",
    "magic-card",
    "meteors",
    "neon-gradient-card",
    "confetti",
    "particles",
    "cool-mode",
    "scratch-to-reveal",
  ],
  Widgets: [
    "animated-list",
    "tweet-card",
    "client-tweet-card",
    "lens",
    "pointer",
    "avatar-circles",
    "icon-cloud",
    "globe",
  ],
  Backgrounds: [
    "warp-background",
    "flickering-grid",
    "animated-grid-pattern",
    "retro-grid",
    "ripple",
  ],
  Devices: [
    "safari",
    "iphone-15-pro",
    "android",
  ],
};

// Fetches detailed information about components in a specific category
async function fetchComponentsByCategory(
  categoryComponents: string[],
  allComponents: any[],
  exampleNamesByComponent: Map<string, string[]>,
) {
  const componentResults = [];

  for (const componentName of categoryComponents) {
    const component = allComponents.find((c) => c.name === componentName);
    if (!component) continue;

    try {
      const componentDetails = await fetchComponentDetails(componentName);
      const componentContent = componentDetails.files[0]?.content;

      const relevantExampleNames =
        exampleNamesByComponent.get(componentName) || [];

      // Generate installation instructions
      const installInstructions = `Install the component using the same process as \
      shadcn/ui. If you run into linter or dependency errors, make sure to install the \
      component using these instructions. For example, with npm/npx: npx shadcn@latest add \
      "https://magicui.design/r/${componentName}.json" (Rules: make sure the URL is wrapped in \
      double quotes and use shadcn not shadcn-ui, or the command will fail). After installation, \ 
      you can import the component like this: import { ${formatComponentName(component.name)} } from \
      "@/components/ui/${componentName}";`;
      
      const disclaimerText = `The code below is for context only. It helps you understand \
      the component's props, types, and behavior. To actually install and use the \
      component, refer to the install instructions above. After installing, the component \
      will be available for import via: import { ${formatComponentName(component.name)} } \
      from "@/components/ui/${componentName}";`;

      const exampleDetailsList = await Promise.all(
        relevantExampleNames.map((name) => fetchExampleDetails(name)),
      );

      const formattedExamples = exampleDetailsList
        .filter((details) => details !== null)
        .map((details) => ({
          name: details.name,
          type: details.type,
          description: details.description,
          content: details.files[0]?.content,
        }));

      const validatedComponent = IndividualComponentSchema.parse({
        name: component.name,
        type: component.type,
        description: component.description,
        install: installInstructions,
        content: componentContent && disclaimerText + componentContent,
        examples: formattedExamples,
      });

      componentResults.push(validatedComponent);
    } catch (error) {
      console.error(`Error processing component ${componentName}:`, error);
    }
  }

  return componentResults;
}

// Registers tools for each component category
async function registerCategoryTools() {
  const [components, allExampleComponents] = await Promise.all([
    fetchUIComponents(),
    fetchExampleComponents(),
  ]);

  const exampleNamesByComponent =
    buildExampleComponentMap(allExampleComponents);

  for (const [category, categoryComponents] of Object.entries(
    componentCategories,
  )) {
    const componentNamesString = categoryComponents.join(", ");

    server.tool(
      `get${category}`,
      `Provides implementation details for ${componentNamesString} components.`,
      {},
      async () => {
        try {
          const categoryResults = await fetchComponentsByCategory(
            categoryComponents,
            components,
            exampleNamesByComponent,
          );

          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(categoryResults, null, 2),
              },
            ],
          };
        } catch (error) {
          let errorMessage = `Error processing ${category} components`;
          if (error instanceof Error) {
            errorMessage += `: ${error.message}`;
          }
          return {
            content: [{ type: "text", text: errorMessage }],
            isError: true,
          };
        }
      },
    );
  }
}

// Initialize category tools before starting the server
registerCategoryTools()
  .then(() => {
    const transport = new StdioServerTransport();
    server.connect(transport);
  })
  .catch((error) => {
    console.error("Error registering category tools:", error);
    const transport = new StdioServerTransport();
    server.connect(transport);
  });
```