MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

C
Component Library MCP

MCP server that scans React/Vue projects and exposes component library metadata to AI coding agents

Created 4/28/2026
Updated about 4 hours ago
Repository documentation and setup instructions

Component Library MCP

An MCP (Model Context Protocol) server that scans React and Vue projects, extracts component metadata (props, slots, events, imports, usage), and exposes it to AI coding agents via structured tools.

What it solves: When an AI coding agent writes UI code without context, it produces three recurring problems:

  1. Duplicate components — creates <UserCard> when <UserProfile> already exists.
  2. Wrong prop APIs — passes label when the component expects title, or misses a required prop.
  3. Inconsistent patterns — builds a one-off dialog instead of using the project's <BaseDialog>.

This MCP gives the agent full visibility into your component library before it writes any UI code.


Requirements

  • Node.js ≥ 20
  • pnpm (other package managers also work — install deps however you like, the server is a plain Node script at runtime)

Install & build

git clone <this-repo>
cd component-library-mcp
pnpm install
pnpm build

pnpm build emits a runnable server at dist/index.js.

Configure in Claude Code

The server scans whatever directory it is launched from (process.cwd()). Pick one of the two setups below — no PROJECT_ROOT needed.

Option A — Per-project .mcp.json (recommended)

Drop a .mcp.json file at the root of every React/Vue project you want to use the MCP with:

{
  "mcpServers": {
    "component-library": {
      "command": "node",
      "args": ["/absolute/path/to/component-library-mcp/dist/index.js"]
    }
  }
}

Claude Code auto-loads .mcp.json from the open workspace. Each project can have its own env overrides (see below) without polluting other projects.

Option B — Global ~/.claude.json

If you usually work in one project at a time and always launch Claude Code from that project's directory:

{
  "mcpServers": {
    "component-library": {
      "command": "node",
      "args": ["/absolute/path/to/component-library-mcp/dist/index.js"]
    }
  }
}

With no env vars set, the server scans process.cwd() — which is the directory Claude Code is opened in. Switch projects by opening a different folder in your editor / re-launching Claude Code from a different directory.

Restart Claude Code after changing either config. The server runs on stdio — there's no port, no daemon.

Environment variables (optional)

All env vars are optional. Set them under env: { ... } in the MCP config only when you need to override defaults.

| Variable | Default | Description | |---|---|---| | PROJECT_ROOT | process.cwd() | Absolute path to scan. Usually you don't need to set this — the server uses the directory it was launched from. Only set it when that isn't what you want. | | COMPONENT_DIRS | auto | Comma-separated dirs to scan. auto probes src/components, src/ui, src/shared, components, lib/components, app/components and falls back to src/ or the project root. | | FRAMEWORK | auto | react | vue | auto. Auto detects from package.json deps. | | EXCLUDE_PATTERNS | node_modules,dist,.next,.nuxt | Comma-separated dir names or globs. Bare names become **/<name>/**. | | MAX_DEPTH | 10 | Max recursion depth for fast-glob. | | INCLUDE_STORIES | true | Parse .stories.(ts\|tsx\|js\|jsx) and attach story examples to components. | | LOG_LEVEL | silent | silent | info | debug. All logs go to stderr. |

Example .mcp.json with overrides:

{
  "mcpServers": {
    "component-library": {
      "command": "node",
      "args": ["/absolute/path/to/component-library-mcp/dist/index.js"],
      "env": {
        "COMPONENT_DIRS": "src/components,src/ui",
        "FRAMEWORK": "react",
        "EXCLUDE_PATTERNS": "node_modules,dist,__tests__,stories",
        "INCLUDE_STORIES": "false",
        "LOG_LEVEL": "info"
      }
    }
  }
}

Available tools

All 7 tools accept Zod-validated JSON input and return both content (text) and structuredContent (same data as structured output).

1. list_components

Summary of every component in the project. Agents typically call this first.

{ "framework": "react", "min_usage": 1, "include_props": false }

Returns an alphabetically sorted array: { name, file_path, framework, prop_count, usage_count, has_stories, description?, tags? }.

2. get_component_details

Full metadata for one component — props, slots, events, description, story examples.

{ "name": "Button" }
// or
{ "file_path": "src/components/Button.tsx" }

Fuzzy fallback: if name has no exact match, suggestions within Levenshtein distance ≤ 3 are returned.

3. search_components

Natural-language + structured search.

{
  "query": "dialog modal",
  "prop_type": "boolean",
  "has_slot": "footer",
  "limit": 10
}

Returns ranked { name, score, reasons[] } hits. Weights: name 1.0, description 0.5, tags 0.6, prop names 0.35, path 0.2.

4. get_import_graph

Who imports what.

{ "component_name": "Button", "direction": "both", "depth": 2 }

Returns dependencies[] (what this component imports) and dependents[] (who imports it, with is_page: true for pages/routes). Barrel files are followed through but not counted as dependents.

5. check_duplicatehighest-value tool

Call this before creating a new component.

{
  "proposed_name": "UserCard",
  "proposed_props": ["user", "size", "avatarUrl"],
  "purpose": "display user profile card"
}

Returns { has_duplicates, existing_matches[], recommendation } where recommendation is use_existing | extend_existing | create_new. Score combines name similarity (0.45), prop overlap (0.35), and purpose/description overlap (0.2), with a short-circuit to use_existing when proposed props are a full subset of an existing component.

6. get_component_usage_example

Real usage snippets from the codebase.

{ "component_name": "Button", "limit": 3 }

Returns up to limit { file_path, code_snippet, props_used[] } examples (5–15 lines around the import line), plus story_examples[] from any matching .stories.(t|j)sx files.

7. refresh_cache

Force re-scan. Incremental by default.

{ "full_scan": true }

Returns { components_found, scan_duration_ms, new_components[], removed_components[], reparsed_files[] }.

How it works

  • First tool call triggers a full scan. Subsequent calls do an mtime-based incremental scan — only re-parses files that changed.
  • React parsing handles function/arrow/FC components, HOC unwrapping (memo, forwardRef, observer, nested), legacy propTypes, JSDoc, and cross-file type expansion via the TypeScript compiler API.
  • Vue parsing handles <script setup> typed + runtime defineProps / defineEmits, Options API, defineComponent, named + scoped slots.
  • Import graph includes page/route directories as consumers (so usage_count reflects imports from src/pages/**), follows barrel re-exports to source files, and resolves tsconfig paths aliases.
  • Performance — 200-component project scans in ~150ms; 2-file incremental scans in ~30ms.

Development

pnpm dev          # tsx watch mode
pnpm test         # vitest, all tests
pnpm test:perf    # perf tests only
pnpm test:watch   # vitest watch mode
pnpm build        # tsc → dist/

Troubleshooting

The server returns { components: [], total: 0 } for my project.

  • Make sure Claude Code was launched from (or has opened) the project root — where package.json lives. The server scans process.cwd() by default.
  • If the project root is somewhere else, set PROJECT_ROOT in the MCP config's env block as a last resort.
  • Run with LOG_LEVEL=info. stderr will show which dirs the scanner tried and how many files it found.
  • If you have a non-standard layout, set COMPONENT_DIRS explicitly (e.g., "lib/ui,packages/core/components").

Framework is wrong.

  • Set FRAMEWORK=react or FRAMEWORK=vue explicitly. Auto-detection reads package.json deps (react, next, vue, nuxt).

Cross-file types show up as "Props" instead of "a" | "b".

  • The TS type resolver runs automatically. If it fails, the parser falls back to the alias name. Check LOG_LEVEL=debug for resolver errors — usually a missing tsconfig.json path alias.

usage_count is 0 for a component that's clearly used.

  • Your importing files must live inside the scanned directories, or inside one of the auto-detected page dirs (src/pages, src/routes, src/app, pages, routes, app). If imports come from a non-standard dir, add it to COMPONENT_DIRS.

JSON-RPC protocol errors from the client.

  • The server writes only JSON-RPC to stdout. If you see garbage there, a dependency is using console.log — open an issue. All of our logging goes to stderr via src/logger.ts.

Project layout

src/
  index.ts                  # stdio entry point
  server.ts                 # MCP server + tool registration
  config.ts                 # env var parsing
  logger.ts                 # stderr-only logger
  lib/
    types.ts                # ComponentInfo, PropInfo, etc.
    schemas.ts              # Zod schemas for tool inputs
  scanner/
    file-scanner.ts         # component dir discovery
    page-scanner.ts         # page/route dir discovery (for graph only)
    framework-detector.ts   # react vs vue
    import-resolver.ts      # relative + tsconfig paths
    import-extractor.ts     # AST → import statements
    import-graph.ts         # dependencies / dependents / usages
  parsers/
    react-parser.ts         # TSX + HOC unwrap
    vue-sfc-parser.ts       # <script setup> / Options API / template slots
    vue-tsx-parser.ts       # Vue TSX (thin wrapper over react parser)
    story-parser.ts         # .stories.tsx
    jsdoc-parser.ts         # @tag, @param, description
    ts-type-resolver.ts     # cross-file type expansion via ts.Program
    shared.ts
  search/
    fuzzy-match.ts          # Levenshtein + token overlap
    text-search.ts          # ranked + structured filters
    duplicate-detector.ts   # name + prop + purpose scoring
  cache/
    component-cache.ts      # in-memory file_path → entry
    incremental-scan.ts     # mtime diff + graph rebuild + story join
  tools/
    list-components.ts
    get-component-details.ts
    search-components.ts
    get-import-graph.ts
    check-duplicate.ts
    get-usage-example.ts
    refresh-cache.ts
tests/
  fixtures/                 # react-project, vue-project, mixed, nonstandard
  parsers/ scanner/ search/ cache/ tools/ perf/

License

ISC.

Quick Setup
Installation guide for this server

Install Package (if required)

npx @modelcontextprotocol/server-component-library-mcp

Cursor configuration (mcp.json)

{ "mcpServers": { "vasyl-bilous-component-library-mcp": { "command": "npx", "args": [ "vasyl-bilous-component-library-mcp" ] } } }