diff --git a/.automaker/context/agent-push-protocol.md b/.automaker/context/agent-push-protocol.md new file mode 100644 index 0000000..e45fce4 --- /dev/null +++ b/.automaker/context/agent-push-protocol.md @@ -0,0 +1,152 @@ +# Agent Push Protocol — ZERO TOLERANCE + +Every agent push MUST follow this exact sequence. No shortcuts. No exceptions. +Pushing code that fails CI is a wasted cycle and an unacceptable failure. + +**CODE DOES NOT LEAVE THIS MACHINE UNTIL IT PASSES ALL QUALITY GATES.** + +--- + +## The Push Sequence + +### Step 1: Format + +```bash +pnpm run format +git add -u +``` + +### Step 2: Commit + +```bash +git commit -m "type(scope): lowercase message" +``` + +Do NOT use `HUSKY=0`. The pre-commit hook runs gitleaks (secret scanning) +and lint-staged. These are safety checks, not obstacles. + +### Step 3: Push + +```bash +git push origin +``` + +The pre-push hook runs `pnpm run preflight` automatically. This executes: +1. Lint (ESLint) +2. Format check (Prettier) +3. Type check (TypeScript strict) +4. Build (tsc compilation) +5. Test (Vitest) +6. Changeset check (if source changed) +7. Docker CI (act-ci, if Docker is available) +8. Full test suite (all tests, not just changed files) + +If ANY gate fails, the push is blocked. Fix the errors and push again. + +**Do NOT use `--no-verify` to bypass the pre-push hook.** +**Do NOT use `HUSKY=0` to skip hooks.** + +### Step 4: Create PR + Auto-Merge + +```bash +PR_URL=$(gh pr create \ + --repo bookedsolidtech/helixir \ + --base dev \ + --title "type(scope): lowercase description" \ + --body "Description of changes") + +PR_NUMBER=$(echo $PR_URL | grep -oE '[0-9]+$') + +gh pr merge $PR_NUMBER --auto --merge --repo bookedsolidtech/helixir +``` + +--- + +## Enforcement Layers + +| Layer | What | Bypassable? | +|-------|------|-------------| +| pre-commit | gitleaks + lint-staged | Only with `--no-verify` | +| commit-msg | commitlint | Only with `--no-verify` | +| **pre-push** | **`pnpm run preflight` (8 gates including changeset, Docker CI, and full test suite)** | **Only with `--no-verify`** | + +The pre-push hook calls `pnpm run preflight` which runs all 8 gates. +Gate 7 (Docker CI) is the act-ci gate — runs if Docker is available, hard fail if it fails. +Gate 8 (Full test suite) runs all tests when source files changed. +Skip Docker only: `SKIP_ACT=1 git push` +Skip full tests only: `SKIP_FULL_TESTS=1 git push` + +--- + +## What Happens If You Skip Steps + +- **Skip format** → pre-push format check fails → push blocked +- **Skip lint** → pre-push lint fails → push blocked +- **Type errors** → pre-push type-check fails → push blocked +- **Build broken** → pre-push build fails → push blocked +- **Tests fail** → pre-push test fails → push blocked +- **Use --no-verify** → EMERGENCY ONLY — document why in the commit message + +--- + +## Changeset Requirement + +If your changes modify published source code, create a changeset: + +```bash +pnpm exec changeset +``` + +Select the package, bump type, and write a description. +Commit the `.changeset/*.md` file WITH your code changes (same commit). + +--- + +## CI Matrix Parity — Node 20/22/24 + +helixir must pass tests on Node 20, 22, and 24. This mirrors the CI matrix +defined in `.github/workflows/ci-matrix.yml`. + +### When to run `--matrix` + +Run `./scripts/act-ci.sh --matrix` when: +- Modifying `package.json` engines or dependencies +- Adding/changing Node.js-version-specific code paths +- Preparing a release to main +- CI matrix failures are reported on a PR + +### How it works + +The `--matrix` flag sets `ACT_MATRIX_TESTS=true` and `ACT_FULL_TESTS=true`, +which activates the `test-full` job in `act-ci.yml`. That job uses nvm to +install and test against Node 20, 22, and 24 in parallel (fail-fast: false). + +```bash +# Run full matrix locally +./scripts/act-ci.sh --matrix + +# Matrix on ARM64 (no Rosetta emulation, faster on Apple Silicon) +./scripts/act-ci.sh --native --matrix + +# Run full suite on current Node only (no matrix) +./scripts/act-ci.sh --full +``` + +### Enforcement + +Gate 7 of preflight runs `act-ci.sh --native` (standard quality gates). +For matrix parity verification before a release, run manually: + +```bash +./scripts/act-ci.sh --native --matrix +``` + +This is required before merging any PR that touches `src/`, `package.json`, +or Node version configuration. + +--- + +## The One Rule + +If `git push` fails due to the pre-push hook, you do NOT bypass it. Period. +Fix the errors first. Then push. This is non-negotiable. diff --git a/.github/workflows/act-ci.yml b/.github/workflows/act-ci.yml new file mode 100644 index 0000000..a82d612 --- /dev/null +++ b/.github/workflows/act-ci.yml @@ -0,0 +1,132 @@ +# ============================================================================ +# Local CI — Quality gates for nektos/act +# ============================================================================ +# Mirrors the core quality gates from ci.yml but avoids GitHub-specific actions +# (pnpm/action-setup, actions/setup-node) that break in act due to PATH issues +# and missing API context. +# +# Single-job design: helixir is a single-package Node project. Running all +# gates in one job avoids bind-mount contention (parallel jobs sharing +# node_modules via --bind corrupt each other's pnpm install). +# +# Usage: ./scripts/act-ci.sh [--job ] [--list] [--full] [--matrix] +# Jobs: quality-gates (default), test-full (activated by --full or --matrix) +# ============================================================================ + +name: Local CI + +on: + pull_request: + +jobs: + quality-gates: + name: Quality Gates + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - name: Setup pnpm + run: | + corepack enable + corepack prepare pnpm@9.15.9 --activate + pnpm install --frozen-lockfile + - name: Lint + run: pnpm run lint + - name: Format check + run: pnpm run format:check + - name: Type check + run: pnpm run type-check + - name: Build + run: pnpm run build + - name: Test + run: pnpm run test + + # ── Full suite test with Node version matrix (mirrors ci-matrix.yml) ─── + test-full: + name: Test Full (Node ${{ matrix.node-version }}) + runs-on: ubuntu-latest + timeout-minutes: 30 + if: ${{ env.ACT_MATRIX_TESTS == 'true' || env.ACT_FULL_TESTS == 'true' }} + strategy: + fail-fast: false + matrix: + node-version: [20, 22, 24] + steps: + - uses: actions/checkout@v4 + - name: Setup Node ${{ matrix.node-version }} via nvm + run: | + if [ "${{ matrix.node-version }}" != "" ]; then + export NVM_DIR="$HOME/.nvm" + if [ ! -d "$NVM_DIR" ]; then + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash + fi + . "$NVM_DIR/nvm.sh" + nvm install ${{ matrix.node-version }} + nvm use ${{ matrix.node-version }} + echo "Node version: $(node --version)" + fi + - name: Setup pnpm + run: | + corepack enable + corepack prepare pnpm@9.15.9 --activate + pnpm install --frozen-lockfile + - name: Build + run: pnpm run build + - name: Run full test suite with hang watchdog + run: | + # Vitest hang watchdog — kills stale processes after 15s of no output + LOGFILE=$(mktemp /tmp/helixir-test-full.XXXXXX) + STALE_TIMEOUT=15 + POLL_INTERVAL=3 + START_TIME=$(date +%s) + + pnpm exec vitest run --reporter=verbose > "$LOGFILE" 2>&1 & + VITEST_PID=$! + + echo "[test-full] vitest PID=$VITEST_PID, Node ${{ matrix.node-version }}" + + LAST_SIZE=0 + STALE_SECONDS=0 + FORCE_KILLED=false + + while kill -0 "$VITEST_PID" 2>/dev/null; do + sleep "$POLL_INTERVAL" + CURRENT_SIZE=$(stat -c "%s" "$LOGFILE" 2>/dev/null || stat -f "%z" "$LOGFILE" 2>/dev/null || echo 0) + ELAPSED=$(( $(date +%s) - START_TIME )) + + if [ "$CURRENT_SIZE" -eq "$LAST_SIZE" ] && [ "$CURRENT_SIZE" -gt 0 ]; then + STALE_SECONDS=$((STALE_SECONDS + POLL_INTERVAL)) + if [ "$STALE_SECONDS" -ge "$STALE_TIMEOUT" ] && [ "$ELAPSED" -ge 30 ]; then + echo "[test-full] Output stale for ${STALE_SECONDS}s at ${ELAPSED}s — force killing vitest" + kill "$VITEST_PID" 2>/dev/null || true + sleep 1 + kill -9 "$VITEST_PID" 2>/dev/null || true + FORCE_KILLED=true + break + fi + else + STALE_SECONDS=0 + fi + LAST_SIZE=$CURRENT_SIZE + done + + wait "$VITEST_PID" 2>/dev/null || true + + # Determine pass/fail from output + FAILED_TESTS=$(grep -c "^[[:space:]]*[×x]" "$LOGFILE" 2>/dev/null || echo 0) + PASSED_TESTS=$(grep -c "^[[:space:]]*[✓✔]" "$LOGFILE" 2>/dev/null || echo 0) + + echo "" + cat "$LOGFILE" | tail -30 + echo "" + echo "[test-full] Node ${{ matrix.node-version }}: ${PASSED_TESTS} passed, ${FAILED_TESTS} failed" + + if [ "$FORCE_KILLED" = true ]; then + echo "[test-full] vitest was force-killed after teardown hang" + fi + + rm -f "$LOGFILE" + + if [ "$FAILED_TESTS" -gt 0 ]; then + exit 1 + fi diff --git a/.github/workflows/ci-matrix.yml b/.github/workflows/ci-matrix.yml new file mode 100644 index 0000000..2885551 --- /dev/null +++ b/.github/workflows/ci-matrix.yml @@ -0,0 +1,106 @@ +# ============================================================================ +# Matrix CI Pipeline — HELiXiR MCP Server +# ============================================================================ +# Tests across Node.js 20, 22, and 24 to ensure forward-compatibility +# and catch version-specific ESM / native module regressions. +# ============================================================================ + +name: CI Matrix + +on: + push: + branches: [main, dev, staging, 'changeset-release/**'] + paths-ignore: + - '**/*.md' + - '.automaker/**' + - '.claude/**' + - 'LICENSE' + - '.editorconfig' + pull_request: + branches: [main, dev] + paths-ignore: + - '**/*.md' + - '.automaker/**' + - '.claude/**' + - 'LICENSE' + - '.editorconfig' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + matrix-test: + name: Test (Node ${{ matrix.node-version }} on ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 15 + + strategy: + fail-fast: false + matrix: + node-version: [20, 22, 24] + os: [ubuntu-latest] + + steps: + # ---- Setup ---- + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + # ---- Quality Checks ---- + + - name: Type check + run: pnpm run type-check + + - name: Lint + run: pnpm run lint + + - name: Format check + run: pnpm run format:check + + # ---- Build ---- + + - name: Build + run: pnpm run build + + # ---- Tests ---- + + - name: Test + run: | + # Promotion PRs (staging→main): tests already verified on staging — skip + if [[ "${{ github.head_ref }}" == "staging" && "${{ github.base_ref }}" == "main" ]]; then + echo "Promotion PR (staging → main) — skipping matrix tests" + exit 0 + fi + pnpm run test + + matrix-summary: + name: Matrix Test Summary + runs-on: ubuntu-latest + needs: matrix-test + if: always() + + steps: + - name: Check matrix results + run: | + if [ "${{ needs.matrix-test.result }}" == "failure" ]; then + echo "❌ Matrix tests failed" + exit 1 + else + echo "✅ All matrix tests passed" + fi diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5d39eff..c8e3a29 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -63,6 +63,16 @@ jobs: - name: Scan build artifacts for secrets run: gitleaks detect --config .gitleaks.toml --source ./build --no-git --verbose --redact + - name: Generate SBOM + run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json --output-format json + + - name: Upload SBOM as release artifact + uses: actions/upload-artifact@v4 + with: + name: sbom + path: sbom.json + if-no-files-found: error + - name: Version and Publish uses: changesets/action@v1 with: diff --git a/.gitignore b/.gitignore index e7356d0..61670d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -node_modules/ -build/ +node_modules +build dist/ coverage/ @@ -29,6 +29,9 @@ coverage/ .automaker/authority/ .automaker/settings.json +# SBOM (generated artifact) +sbom.json + # Reports (generated artifacts) protoLabs.report.html *.report.html diff --git a/CODEOWNERS b/CODEOWNERS index 546e94b..0b44135 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -7,3 +7,12 @@ .github/workflows/ @himerus package.json @himerus CODEOWNERS @himerus + +# Security-sensitive tool handlers (user input, external URLs, filesystem access) +packages/core/src/handlers/cdn.ts @himerus +packages/core/src/tools/library.ts @himerus +packages/core/src/shared/error-handling.ts @himerus +packages/core/src/shared/git.ts @himerus + +# Configuration that affects security boundaries +packages/core/src/config.ts @himerus diff --git a/README.md b/README.md index de39877..e96e616 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@
+HELiXiR — MCP Server for Web Component Libraries + # HELiXiR **Give AI agents full situational awareness of any web component library.** @@ -13,6 +15,9 @@ Stop AI hallucinations. Ground every component suggestion in your actual Custom [![Node 20+](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org) [![Build](https://img.shields.io/github/actions/workflow/status/bookedsolidtech/helixir/build.yml?branch=main&label=build)](https://github.com/bookedsolidtech/helixir/actions/workflows/build.yml) [![Tests](https://img.shields.io/github/actions/workflow/status/bookedsolidtech/helixir/test.yml?branch=main&label=tests)](https://github.com/bookedsolidtech/helixir/actions/workflows/test.yml) +[![MCP Protocol](https://img.shields.io/badge/MCP-protocol-purple)](https://modelcontextprotocol.io) +[![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue?logo=typescript)](https://www.typescriptlang.org) +[![Tools](https://img.shields.io/badge/tools-73-purple)](https://www.npmjs.com/package/helixir) [Quick Start](#quick-start) · [Why HELiXiR](#why-helixir) · [Tools Reference](#tools-reference) · [Configuration](#configuration) · [AI Tool Configs](#ai-tool-configs) @@ -23,7 +28,7 @@ Stop AI hallucinations. Ground every component suggestion in your actual Custom ## Why HELiXiR - **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. +- **87+ MCP tools out of the box** — Component discovery, health scoring, design token lookup, TypeScript diagnostics, breaking-change detection, Storybook story generation, Shadow DOM styling validators, theme scaffolding, and scaffold/extend tools — 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.json` CEM file. - **Any AI editor, zero lock-in** — Claude Code, Claude Desktop, Cursor, VS Code (Cline/Continue), Zed — one config, any tool. @@ -281,14 +286,15 @@ All tools are exposed over the [Model Context Protocol](https://modelcontextprot ### Health -| 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 | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| `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)_ | +| `audit_library` | Generates a JSONL audit report scoring every component across 11 dimensions; returns file path (if outputPath given) and summary stats | — | ### Library @@ -368,6 +374,67 @@ _(Requires `tokensPath` to be configured)_ | `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` | +### TypeGenerate + +| Tool | Description | Required Args | +| ---------------- | ---------------------------------------------------------------------------------------- | ------------- | +| `generate_types` | Generates TypeScript type definitions (.d.ts content) for all custom elements in the CEM | — | + +### Theme + +| Tool | Description | Required Args | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | +| `create_theme` | Scaffold a complete enterprise CSS theme from the component library's design tokens with light/dark mode variables and color-scheme support | — | +| `apply_theme_tokens` | Map a theme token definition to specific components, generating per-component CSS blocks and a global `:root` block | `themeTokens` | + +### Scaffold + +| Tool | Description | Required Args | +| -------------------- | ------------------------------------------------------------------------------------------------- | ------------- | +| `scaffold_component` | Scaffold a new web component with boilerplate code based on an existing component's CEM structure | `tagName` | + +### Extend + +| Tool | Description | Required Args | +| ------------------ | ---------------------------------------------------------------------------------------------------------------- | ------------- | +| `extend_component` | Generate extension boilerplate for a web component, providing a subclass with overridable methods and properties | `tagName` | + +### Styling + +29 anti-hallucination validators that ground every component styling decision in real CEM data. Run `validate_component_code` as the all-in-one final check, or use individual tools for targeted validation. + +| Tool | Description | Required Args | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `diagnose_styling` | Generates a Shadow DOM styling guide for a component — token prefix, theming approach, dark mode support, anti-pattern warnings, and correct CSS usage snippets | `tagName` | +| `get_component_quick_ref` | Complete quick reference for a component — attributes, methods, events, slots, CSS custom properties, CSS parts, Shadow DOM warnings, and anti-patterns. Use as the FIRST call when working with any component | `tagName` | +| `validate_component_code` | ALL-IN-ONE validator — runs 19 anti-hallucination sub-validators (HTML, CSS, JS, a11y, events, methods, composition) in a single call. Use as the FINAL check before submitting any code | `html`, `tagName` | +| `styling_preflight` | Single-call styling validation combining API discovery, CSS reference resolution, and anti-pattern detection with inline fix suggestions. Call ONCE before finalizing component CSS | `cssText`, `tagName` | +| `validate_css_file` | Validates an entire CSS file targeting multiple components — auto-detects component tags, runs per-component and global validation with inline fixes | `cssText` | +| `check_shadow_dom_usage` | Scans CSS for Shadow DOM anti-patterns: descendant selectors piercing shadow boundaries, `::slotted()` misuse, invalid `::part()` chaining, `!important` on tokens, unknown part names | `cssText` | +| `check_html_usage` | Validates consumer HTML against a component CEM — catches invalid slot names, wrong enum values, boolean attribute misuse, and unknown attributes with typo suggestions | `htmlText`, `tagName` | +| `check_event_usage` | Validates event listener patterns against a component CEM — catches React `onXxx` props for custom events, unknown event names, and framework-specific binding mistakes | `codeText`, `tagName` | +| `check_component_imports` | Scans HTML/JSX/template code for all custom element tags and verifies they exist in the loaded CEM; catches non-existent components with fuzzy suggestions | `codeText` | +| `check_slot_children` | Validates that children placed inside slots match expected element types from the CEM — catches wrong child elements in constrained slots (e.g. `
` inside ``) | `htmlText`, `tagName` | +| `check_attribute_conflicts` | Detects conditional attributes used without their guard conditions — catches `target` without `href`, `min`/`max` on non-number inputs, and other attribute interaction mistakes | `htmlText`, `tagName` | +| `check_a11y_usage` | Validates consumer HTML for accessibility mistakes — catches missing accessible labels on icon buttons/dialogs/selects, and manual role overrides on components that self-assign ARIA roles | `htmlText`, `tagName` | +| `check_css_vars` | Validates CSS for custom property usage against a component CEM — catches unknown CSS custom properties with typo suggestions and `!important` on design tokens | `cssText`, `tagName` | +| `check_token_fallbacks` | Validates CSS for proper `var()` fallback chains and detects hardcoded colors that break theme switching | `cssText`, `tagName` | +| `check_composition` | Validates cross-component composition patterns — catches tab/panel count mismatches, unlinked cross-references, and empty containers | `htmlText` | +| `check_method_calls` | Validates JS/TS code for correct method and property usage — catches hallucinated API calls, properties called as methods, and methods assigned as properties | `codeText`, `tagName` | +| `check_theme_compatibility` | Validates CSS for dark mode and theme compatibility — catches hardcoded colors on background/color/border properties and potential contrast issues | `cssText` | +| `check_css_specificity` | Detects CSS specificity anti-patterns — catches `!important` usage, ID selectors, deeply nested selectors (4+ levels), and inline style attributes | `code` | +| `check_layout_patterns` | Detects layout anti-patterns when styling web component host elements — catches display overrides, fixed dimensions, absolute/fixed positioning, and `overflow: hidden` | `cssText` | +| `check_css_scope` | Detects component-scoped CSS custom properties set at the wrong scope (e.g. on `:root` instead of the component host) | `cssText`, `tagName` | +| `check_css_shorthand` | Detects risky CSS shorthand + `var()` combinations that can fail silently when any token is undefined | `cssText` | +| `check_color_contrast` | Detects color contrast issues: low-contrast hardcoded color pairs, mixed color sources (token + hardcoded), and low opacity on text | `cssText` | +| `check_transition_animation` | Detects CSS transitions and animations on component hosts targeting properties that cannot cross Shadow DOM boundaries | `cssText`, `tagName` | +| `check_shadow_dom_js` | Detects JavaScript anti-patterns that violate Shadow DOM encapsulation — catches `.shadowRoot.querySelector()`, `attachShadow()` on existing components, and `innerHTML` overwriting slot content | `codeText` | +| `check_dark_mode_patterns` | Detects dark mode styling anti-patterns — catches theme-scoped selectors setting standard CSS properties that won't reach shadow DOM internals | `cssText` | +| `resolve_css_api` | Resolves every `::part()`, CSS custom property, and slot reference in agent-generated code against actual CEM data — reports valid/hallucinated references with closest valid alternatives | `cssText`, `tagName` | +| `detect_theme_support` | Analyzes a component library for theming capabilities — token categories, semantic naming patterns, dark mode readiness, and coverage score | — | +| `recommend_checks` | Analyzes code to determine which validation tools are most relevant — returns a prioritized list of tool names without running them all | `codeText` | +| `suggest_fix` | Generates concrete, copy-pasteable code fixes for validation issues by type (shadow-dom, token-fallback, theme-compat, method-call, event-usage, specificity, layout) | `type`, `issue`, `original` | + --- ## Configuration @@ -388,6 +455,7 @@ Place this file at the root of your component library project (or wherever `MCP_ | `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 `