Give AI agents full situational awareness of any web component library.
Stop AI hallucinations. Ground every component suggestion in your actual Custom Elements Manifest.
Quick Start · Why HELiXiR · Tools Reference · Configuration · AI Tool Configs
- No more hallucinations — AI reads your real component API from the Custom Elements Manifest, not from training data. Every attribute, event, slot, and CSS part is sourced directly from your library.
- 30+ MCP tools out of the box — Component discovery, health scoring, design token lookup, TypeScript diagnostics, breaking-change detection, and Storybook story generation — all callable by any MCP-compatible AI agent.
- Works with any web component framework — Shoelace, Lit, Stencil, FAST, Spectrum, Vaadin, and any library that produces a
custom-elements.jsonCEM file. - Any AI editor, zero lock-in — Claude Code, Claude Desktop, Cursor, VS Code (Cline/Continue), Zed — one config, any tool.
Under 60 seconds from zero to a component-aware AI agent.
npm install helixirThen generate a starter config in your component library:
npx helixir init
# → writes mcpwc.config.json to the current directoryEdit mcpwc.config.json to point at your library:
{
"cemPath": "custom-elements.json",
"projectRoot": "/absolute/path/to/your/component-library",
"componentPrefix": "sl-",
"tokensPath": "dist/tokens/tokens.json"
}Add HELiXiR to your Claude Desktop config (see AI Tool Configs for other editors):
{
"mcpServers": {
"helixir": {
"command": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
}
}Restart Claude Desktop. Done — your AI agent now knows every property, event, slot, CSS part, and design token in your library.
You: How do I use sl-button?
Claude: You can use
<sl-button>like this:<sl-button type="primary" color="blue" rounded>Click me</sl-button>It supports
type,color,rounded,icon, andlabelattributes.
All of that is hallucinated. type, color, rounded, icon, and label are not real attributes on sl-button. The correct attribute for the visual style is variant, and rounded doesn't exist at all.
You: How do I use sl-button?
Claude: (calls
get_component→sl-button) Here's the accurate API for<sl-button>:Attributes:
variant—'default' | 'primary' | 'success' | 'neutral' | 'warning' | 'danger' | 'text'(default:'default')size—'small' | 'medium' | 'large'(default:'medium')disabled—boolean(default:false)loading—boolean— Draws the button in a loading stateoutline—boolean— Draws an outlined buttonpill—boolean— Draws a pill-style button with rounded edgeshref—string | undefined— Renders as<a>when setSlots: default (button label),
prefix(before label),suffix(after label)Events:
sl-blur,sl-focus,sl-invalidExample:
<sl-button variant="primary" size="medium">Save changes</sl-button>
Every property, event, slot, CSS part, and design token — sourced directly from your Custom Elements Manifest. No hallucinations.
HELiXiR works with any toolchain that produces a custom-elements.json (CEM). Below are quick-start setups for the most common frameworks.
Shoelace ships custom-elements.json inside its npm package. No build step needed.
npm install @shoelace-style/shoelace{
"cemPath": "node_modules/@shoelace-style/shoelace/dist/custom-elements.json",
"componentPrefix": "sl-"
}Use the official CEM analyzer with the Lit plugin:
npm install -D @custom-elements-manifest/analyzer// package.json scripts
"analyze": "cem analyze --litelement --globs 'src/**/*.ts'"{
"cemPath": "custom-elements.json",
"componentPrefix": "my-"
}Run npm run analyze after each build to keep the CEM current.
Enable CEM output in stencil.config.ts:
// stencil.config.ts
import { Config } from '@stencil/core';
export const config: Config = {
outputTargets: [{ type: 'docs-custom' }, { type: 'dist-custom-elements' }],
};Stencil emits custom-elements.json to your dist/ folder:
{
"cemPath": "dist/custom-elements/custom-elements.json",
"componentPrefix": "my-"
}FAST components ship with CEM support via the @custom-elements-manifest/analyzer:
npm install -D @custom-elements-manifest/analyzer// package.json scripts
"analyze": "cem analyze --globs 'src/**/*.ts'"{
"cemPath": "custom-elements.json",
"componentPrefix": "fluent-"
}Spectrum Web Components use Stencil under the hood and ship their CEM in the package:
npm install @spectrum-web-components/bundle{
"cemPath": "node_modules/@spectrum-web-components/bundle/custom-elements.json",
"componentPrefix": "sp-"
}Any project can add CEM generation with the analyzer:
npm install -D @custom-elements-manifest/analyzer// package.json scripts
"analyze": "cem analyze --globs 'src/**/*.js'"{
"cemPath": "custom-elements.json"
}All tools are exposed over the Model Context Protocol. Your AI agent can call any of these tools by name.
| Tool | Description | Required Args |
|---|---|---|
list_components |
List all custom elements registered in the CEM | — |
find_component |
Semantic search for components by name, description, or member names (top 3 matches) | query |
get_library_summary |
Overview of the library: component count, average health score, grade distribution | — |
list_events |
List all events across the library, optionally filtered by component | tagName (optional) |
list_slots |
List all slots across the library, optionally filtered by component | tagName (optional) |
list_css_parts |
List all CSS ::part() targets across the library, optionally filtered by component |
tagName (optional) |
list_components_by_category |
Group components by functional category (form, navigation, feedback, layout, etc.) | — |
| Tool | Description | Required Args |
|---|---|---|
get_component |
Full metadata for a component: members, events, slots, CSS parts, CSS properties | tagName |
validate_cem |
Validate CEM documentation completeness; returns score (0–100) and issues list | tagName |
suggest_usage |
Generate an HTML snippet showing key attributes with their defaults and variant options | tagName |
generate_import |
Generate side-effect and named import statements from CEM exports | tagName |
get_component_narrative |
3–5 paragraph markdown prose description of a component optimized for LLM comprehension | tagName |
get_prop_constraints |
Structured constraint table for an attribute: union values with descriptions, or simple type info | tagName, attributeName |
find_components_by_token |
Find all components that expose a given CSS custom property token | tokenName |
find_components_using_token |
Find all components referencing a token in their cssProperties (works without tokensPath) |
tokenName |
get_component_dependencies |
Dependency graph for a component: direct and transitive dependencies from CEM reference data | tagName |
validate_usage |
Validate a proposed HTML snippet against the CEM spec: unknown attrs, bad slot names, enum mismatches | tagName, html |
| Tool | Description | Required Args |
|---|---|---|
get_composition_example |
Realistic HTML snippet showing how to compose 1–4 components together using their slot structure | tagNames |
| Tool | Description | Required Args |
|---|---|---|
score_component |
Latest health score for a component: grade (A–F), dimension scores, and issues | tagName |
score_all_components |
Health scores for every component in the library | — |
get_health_trend |
Health trend for a component over the last N days with trend direction | tagName |
get_health_diff |
Before/after health comparison between current branch and a base branch | tagName |
get_health_summary |
Aggregate health stats for all components: average score, grade distribution | — |
analyze_accessibility |
Accessibility profile: ARIA roles, keyboard events, focus management, label support | tagName (optional) |
| Tool | Description | Required Args |
|---|---|---|
load_library |
Load an additional web component library by npm package name or CEM path | libraryId |
list_libraries |
List all currently loaded web component libraries | — |
unload_library |
Remove a loaded library from memory | libraryId |
| Tool | Description | Required Args |
|---|---|---|
diff_cem |
Per-component CEM diff between branches; highlights breaking changes and additions | tagName, baseBranch |
check_breaking_changes |
Breaking-change scan across all components vs. a base branch with summary report | baseBranch |
| Tool | Description | Required Args |
|---|---|---|
detect_framework |
Identifies the web component framework in use from package.json, CEM metadata, and config | — |
| Tool | Description | Required Args |
|---|---|---|
get_file_diagnostics |
TypeScript diagnostics for a single file | filePath |
get_project_diagnostics |
Full TypeScript diagnostic pass across the entire project | — |
| Tool | Description | Required Args |
|---|---|---|
generate_story |
Generates a Storybook CSF3 story file for a component based on its CEM declaration | tagName |
| Tool | Description | Required Args |
|---|---|---|
estimate_bundle_size |
Estimates minified + gzipped bundle size for a component's npm package via bundlephobia/npm | tagName |
package parameter derivation:
The estimate_bundle_size tool accepts an optional package argument — the npm package name to look up (e.g. "@shoelace-style/shoelace"). When omitted, the tool derives the package name from your componentPrefix config value using a built-in prefix-to-package map:
| Prefix | npm Package |
|---|---|
sl |
@shoelace-style/shoelace |
fluent- |
@fluentui/web-components |
mwc- |
@material/web |
ion- |
@ionic/core |
vaadin- |
@vaadin/components |
lion- |
@lion/ui |
pf- |
@patternfly/elements |
carbon- |
@carbon/web-components |
If your prefix is not in the list above and you omit package, the tool returns a VALIDATION error. In that case, pass the package argument explicitly.
| Tool | Description | Required Args |
|---|---|---|
benchmark_libraries |
Compare 2–10 web component libraries by health score, documentation quality, and API surface; returns a weighted score table | libraries |
| Tool | Description | Required Args |
|---|---|---|
resolve_cdn_cem |
Fetch and cache a library's CEM from jsDelivr or UNPKG by npm package name (for CDN-loaded libraries) | package |
(Requires tokensPath to be configured)
| Tool | Description | Required Args |
|---|---|---|
get_design_tokens |
List all design tokens, optionally filtered by category (e.g. "color", "spacing") |
— |
find_token |
Search for a design token by name or value (case-insensitive substring match) | query |
Configuration is resolved in priority order: environment variables > mcpwc.config.json > defaults.
Place this file at the root of your component library project (or wherever MCP_WC_PROJECT_ROOT points).
| Key | Type | Default | Description |
|---|---|---|---|
cemPath |
string |
"custom-elements.json" |
Path to the Custom Elements Manifest, relative to projectRoot. Auto-discovered if omitted. |
projectRoot |
string |
process.cwd() |
Absolute path to the component library project root. |
componentPrefix |
string |
"" |
Optional tag-name prefix (e.g. "sl-") to scope component discovery. |
healthHistoryDir |
string |
".mcp-wc/health" |
Directory where health snapshots are stored, relative to projectRoot. |
tsconfigPath |
string |
"tsconfig.json" |
Path to the project's tsconfig.json, relative to projectRoot. |
tokensPath |
string | null |
null |
Path to a design tokens JSON file. Set to null to disable token tools. |
cdnBase |
string | null |
null |
Base URL prepended to component paths when generating CDN <script> and <link> tags in suggest_usage output (e.g. "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2/cdn"). Does not affect resolve_cdn_cem. Set to null to disable CDN suggestions. |
watch |
boolean |
false |
When true, HELiXiR automatically reloads the CEM on file changes. |
Full example:
{
"cemPath": "dist/custom-elements.json",
"projectRoot": "/home/user/my-design-system",
"componentPrefix": "ds-",
"healthHistoryDir": ".mcp-wc/health",
"tsconfigPath": "tsconfig.build.json",
"tokensPath": "dist/tokens/tokens.json",
"cdnBase": "https://cdn.jsdelivr.net/npm"
}Environment variables override all config file values. Useful for CI or when pointing the same server at different libraries.
| Variable | Overrides |
|---|---|
MCP_WC_PROJECT_ROOT |
projectRoot |
MCP_WC_CEM_PATH |
cemPath |
MCP_WC_COMPONENT_PREFIX |
componentPrefix |
MCP_WC_HEALTH_HISTORY_DIR |
healthHistoryDir |
MCP_WC_TSCONFIG_PATH |
tsconfigPath |
MCP_WC_TOKENS_PATH |
tokensPath |
MCP_WC_CDN_BASE |
cdnBase |
Set MCP_WC_TOKENS_PATH=null (the string "null") to explicitly disable token tools via env var.
See mcpwc.config.json.example for a ready-to-copy template.
Add to .mcp.json in your project root (project-scoped) or ~/.claude.json (global):
Option 1 — Install from npm (recommended)
npx helixir init # generates mcpwc.config.json in your project rootThen add to .mcp.json:
{
"mcpServers": {
"helixir": {
"command": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
}
}Option 2 — Install from local clone (development)
git clone https://github.com/bookedsolidtech/helixir.git
cd helixir
pnpm install
pnpm buildThen add to .mcp.json:
{
"mcpServers": {
"helixir": {
"command": "node",
"args": ["/absolute/path/to/helixir/build/index.js"],
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
}
}Reload Claude Code after saving (:mcp to verify the server appears).
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"helixir": {
"command": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
}
}Restart Claude Desktop after saving.
Add to .cursor/mcp.json in your project root (or ~/.cursor/mcp.json for global):
{
"mcpServers": {
"helixir": {
"command": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "${workspaceFolder}"
}
}
}
}Cline — add to .vscode/cline_mcp_settings.json:
{
"mcpServers": {
"helixir": {
"command": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "${workspaceFolder}"
}
}
}
}Continue — add to ~/.continue/config.json under mcpServers:
{
"mcpServers": [
{
"name": "helixir",
"command": "npx helixir",
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
]
}Add to your Zed settings (~/.config/zed/settings.json):
{
"context_servers": {
"helixir": {
"command": {
"path": "npx",
"args": ["helixir"],
"env": {
"MCP_WC_PROJECT_ROOT": "/absolute/path/to/your/component-library"
}
}
}
}
}HELiXiR applies defense-in-depth on all inputs that touch the file system or network:
- Path containment — all file paths are resolved and verified to stay within
projectRoot;..traversals and absolute paths outside the root are rejected. - Input validation — every tool argument is validated with Zod schemas before reaching handler code; unknown properties are rejected via
additionalProperties: false. - CDN safety —
resolve_cdn_cemonly fetches from allowlisted CDN origins (jsDelivr, UNPKG); arbitrary URLs are not accepted. - No shell execution — the server never spawns subprocesses based on user input; TypeScript diagnostics use the TS compiler API in-process.
See SECURITY.md for the vulnerability disclosure policy.
Every pull request must pass all five CI checks before merge:
| Workflow | What it checks |
|---|---|
| build | TypeScript type-check + tsc compile on Node 20/22 |
| test | Full vitest suite with coverage on Node 20/22 |
| lint | ESLint (TypeScript + Prettier compatibility rules) |
| format | Prettier formatting check |
| security | pnpm audit --audit-level=high |
Pre-commit hooks (via husky + lint-staged):
- TypeScript/JavaScript files: ESLint auto-fix → Prettier format
- JSON/CSS/Markdown/YAML files: Prettier format
- Commit messages: validated by commitlint against conventional-commits format
Allowed commit types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert, audit
See CONTRIBUTING.md and LOCAL.md for full setup details.
See CONTRIBUTING.md for guidelines.
Quick steps:
- Fork the repo and create a feature branch.
- Run
pnpm installto install dependencies. - Make your changes in
src/. - Run
pnpm testto ensure all tests pass. - Run
pnpm run lint && pnpm run format:checkbefore submitting. - Open a pull request with a clear description of the change.
Issues and feature requests are welcome on GitHub.
MIT © 2025-2026 Clarity House LLC d/b/a Booked Solid Technology