Thank you for your interest in contributing to the HeroUI MCP project! This monorepo hosts both @heroui/react-mcp and @heroui/native-mcp servers. This guide will help you get started with development.
- Node.js v22+ (see
.nvmrc) - pnpm package manager
# Clone the repository
git clone https://github.com/heroui-inc/heroui-mcp.git
cd heroui-mcp
# Install dependencies
pnpm install
# Set up environment variables
cp .env.example .env
# Edit .env with your credentials
# Extract component data to local development R2 bucket
pnpm extract:react # Extract React MCP data
pnpm extract:native # Extract Native MCP data
# Start development API server
pnpm dev:react # React MCP (http://localhost:8787)
pnpm dev:native # Native MCP (http://localhost:8788)Create a .env file with your credentials:
# R2 Configuration
CLOUDFLARE_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_r2_access_key
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_BUCKET_NAME=your_r2_bucket_name
# GitHub Token (optional but recommended to avoid rate limits)
GITHUB_TOKEN=your_github_personal_access_tokenNote: GitHub token doesn't need special permissions for public repos. Create one at GitHub Settings.
# Build all packages
pnpm build
# Build specific package
pnpm build:react
pnpm build:nativeTest using the build output directly. For example, in Cursor, add the following to your MCP settings:
"heroui-react": {
"command": "/path/to/repo/mcp/apps/react-mcp/dist/stdio.js",
"env": {
"HEROUI_API_URL": "http://localhost:8787"
}
}
Remember to start the API server with pnpm dev:react as well.
Deployment is automatic through GitHub Actions
The MCP Inspector provides a web UI to test and debug the MCP server functionality:
# Start the React MCP Inspector
pnpm inspect:react
# Start the Native MCP Inspector
pnpm inspect:nativeThis will:
- Start the MCP server with stdio transport
- Launch the Inspector UI in your browser (usually at http://localhost:6274)
- Provide a session token for authentication
- Allow interactive testing of all MCP tools
For development or testing with a local build in your IDE:
{
"mcpServers": {
"heroui-react-local": {
"command": "node",
"args": ["/path/to/heroui-mcp/apps/react-mcp/dist/stdio.js"]
},
"heroui-native-local": {
"command": "node",
"args": ["/path/to/heroui-mcp/apps/native-mcp/dist/stdio.js"]
}
}
}When installed via npx, the MCP servers connect to these default API endpoints:
- React MCP (
@heroui/react-mcp):https://mcp-api.heroui.com - Native MCP (
@heroui/native-mcp):https://native-mcp-api.heroui.com
You can override the API URL for local development:
{
"mcpServers": {
"heroui-react": {
"command": "npx",
"args": ["-y", "@heroui/react-mcp"],
"env": {
"HEROUI_API_URL": "http://localhost:8787"
}
},
"heroui-native": {
"command": "npx",
"args": ["-y", "@heroui/native-mcp"],
"env": {
"HEROUI_NATIVE_API_URL": "http://localhost:8788"
}
}
}
}# Type checking
pnpm typecheck
# Linting
pnpm lint
# Format code
pnpm format# Build all packages
pnpm build
# Build specific package
pnpm build:native # Build @heroui/native-mcp
pnpm build:react # Build @heroui/react-mcp# Start development server for all packages
pnpm dev
# Start development server for specific package
pnpm dev:native # Native MCP API server (http://localhost:8788)
pnpm dev:react # React MCP API server (http://localhost:8787)# Launch MCP Inspector web UI for testing tools
pnpm inspect:native # Native MCP Inspector
pnpm inspect:react # React MCP InspectorThe Inspector provides a web interface for testing MCP tools interactively.
pnpm extract:react # Extract React MCP data (components + theme)
pnpm extract:native # Extract Native MCP data (components + theme)For granular extraction (components or theme only), run from within the app directory. See apps/react-mcp/scripts/extract.sh or apps/native-mcp/scripts/extract.sh for usage.
# Type checking
pnpm typecheck # Check all packages
# Linting
pnpm lint # Lint all packages
# Formatting
pnpm format # Format all TypeScript/JSON files
# Code cleanup
pnpm clean # Clean build artifacts# Run all tests
pnpm test
# Pre-release checks
pnpm release:check # Run lint, typecheck, and buildThe HeroUI MCP uses a simple architecture:
- STDIO Client - Runs locally, handles MCP protocol
- REST API (Cloudflare Worker) - Serves component data
- R2 Storage - Stores component metadata
AI Assistant → STDIO Client → REST API → R2 Storage
The project supports multiple environments with different configurations:
NODE_ENV=developmentNODE_ENV=stagingNODE_ENV=productionEnvironment variables are configured in wrangler.toml for API servers.
The server extracts component data directly from heroui.com and stores it in Cloudflare R2:
- React MCP: Fetches component documentation from
https://heroui.com/docs/react/components/usingllms.txtmanifest - Native MCP: Fetches component documentation from
https://heroui.com/docs/native/components/usingllms.txtmanifest
Data is stored as ctx.json in R2, containing components list, documentation paths, version, and timestamp.
Set up environment variables in .env, then extract to development bucket:
pnpm extract:react # Extract React MCP data
pnpm extract:native # Extract Native MCP dataData is automatically extracted via GitHub Actions when:
- Code is pushed to
develop(staging) ormain(production) - Manually triggered via GitHub Actions UI
The extraction scripts fetch documentation directly from heroui.com:
- Documentation is fetched from public URLs (no authentication required)
- Rate limiting is handled by the documentation server
- GitHub token is optional and only used for version checking via GitHub API
To add a new tool to the MCP server (from apps/react-mcp or apps/native-mcp):
- Create a new tool file in
src/mcp/tools/:
// src/mcp/tools/my-tool.ts
import type { Tool } from "../types";
import { z } from "zod";
import { fetchApi } from "../lib/fetch";
export const myTool: Tool = {
name: "my_tool",
description: "Description of your tool",
async ctx(shared) {
// Optional: Initialize tool-specific context from shared context
return {
// Tool-specific context
};
},
exec(server, { config, name, description, ctx }) {
const inputSchema = z.object({
// Define your parameters
});
const handler = async (args: z.infer<typeof inputSchema>) => {
// Implementation
const data = await fetchApi("/endpoint", config.apiBaseUrl);
return {
content: [
{
type: "text" as const,
text: JSON.stringify(data),
},
],
};
};
server.registerTool(
name,
{ description, inputSchema: inputSchema.shape },
handler as any,
);
},
};- Register the tool in
src/mcp/tools/index.ts:
import { myTool } from "./my-tool";
const tools: Tool[] = [
// ... existing tools
myTool,
];- If needed, add a corresponding API route in
src/api/routes/:
// src/api/routes/my-route.ts
import { Hono } from "hono";
const myRoute = new Hono();
myRoute.get("/", async (c) => {
// Implementation
return c.json({ data: "..." });
});
export { myRoute };- Mount the route in
src/api/index.ts:
import { myRoute } from "./routes/my-route";
app.route("/my-route", myRoute);Each MCP package follows a unified architecture:
-
MCP Server - STDIO transport for NPM distribution
- Runs locally in AI assistants
- Communicates with REST API via HTTP
- Uses shared context for tool initialization
-
REST API - Cloudflare Worker
- Serves component data from R2 storage
- Fetches documentation directly from heroui.com when needed
- Provides analytics and authentication middleware
-
R2 Storage - Cloudflare R2 bucket
- Stores
ctx.jsonwith shared context (components, docs paths, version) - Single source of truth for component metadata
- Stores
-
Data Extraction - CLI scripts
- Fetches component data from heroui.com using
llms.txtmanifest - Extracts minimal metadata (name, links) from component documentation
- Uploads consolidated
ctx.jsonto R2
- Fetches component data from heroui.com using
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure:
- Code is formatted (
pnpm format) - All tests pass (
pnpm typecheck && pnpm lint && pnpm test) - Documentation is updated if needed
- Commit messages are clear and descriptive
- Use TypeScript for all new code
- Follow the existing code style (enforced by ESLint and Prettier)
- Add types for all function parameters and return values
- Document complex functions with JSDoc comments
- Keep functions small and focused
Please use the GitHub issue tracker to report bugs or request features. When reporting bugs, please include:
- Version of the MCP server
- IDE/editor you're using
- Steps to reproduce the issue
- Expected behavior
- Actual behavior
- Any error messages or logs
By contributing, you agree that your contributions will be licensed under the MIT License.