ngx-com-mcp
v0.1.20
Published
MCP server for the ngx-com Angular component library — provides AI tools for component lookup, search, and setup guidance
Maintainers
Readme
ngx-com-mcp
MCP (Model Context Protocol) server for the ngx-com Angular component library.
Provides AI tools for looking up components, searching by UI need, and getting setup instructions. Works with any MCP-compatible client: Claude Code, Cursor, Windsurf, VS Code Copilot, etc.
Table of Contents
- How It Works
- Consumer Setup
- Available Tools
- Tool Details & Examples
- Keeping the Inventory in Sync
- Development
- Architecture
- Publishing
How It Works
The MCP server runs as a local child process on the consumer's machine. No cloud, no API keys, no hosting required.
AI Tool (Claude Code, Cursor, etc.)
|
| spawns child process via .mcp.json config
v
ngx-com-mcp server (runs locally via stdio)
|
| reads bundled data
v
COMPONENT_INVENTORY.md (33 components, full API reference)- The AI tool reads
.mcp.jsonat startup - It spawns
npx ngx-com-mcpas a child process - The server starts and reports its 5 tools over the MCP protocol (JSON-RPC via stdio)
- When the user asks about ngx-com components, the AI tool automatically calls the relevant tool
- The server parses the bundled
COMPONENT_INVENTORY.mdand returns structured data - The AI tool uses the data to write correct code
Consumer Setup
Prerequisites
- Node.js >= 22
- An MCP-compatible AI tool (Claude Code, Cursor, Windsurf, VS Code Copilot, etc.)
Step 1 — Install (optional)
The server runs via npx, so no install is required. If you prefer a local install:
npm install -D ngx-com-mcpStep 2 — Configure .mcp.json
Create or edit .mcp.json in your project root:
{
"mcpServers": {
"ngx-com": {
"type": "stdio",
"command": "npx",
"args": ["-y", "ngx-com-mcp"]
}
}
}If you installed locally, you can point directly to the binary:
{
"mcpServers": {
"ngx-com": {
"type": "stdio",
"command": "node",
"args": ["node_modules/.bin/ngx-com-mcp"]
}
}
}Step 3 — Restart your AI tool
The MCP server is loaded at session start. After adding the config, restart Claude Code (or your AI tool) so it picks up the new server.
Step 4 — Use it
Just ask your AI tool about ngx-com components. The tools are called automatically:
"Add a date picker to my form"
"What button variants are available?"
"How do I set up ngx-com in my project?"
"Show me all form components"
Available Tools
| Tool | Description |
|------|-------------|
| lookup_component | Full API reference for a specific component (imports, inputs, outputs, usage examples) |
| list_components | List all 33 components, optionally filtered by category |
| find_component | Describe a UI need and get matching component suggestions |
| get_setup | Installation and configuration instructions |
| get_patterns | Cross-cutting patterns: form integration, overlays, two-way binding, template customization |
| get_testing_guide | Comprehensive guide for testing ngx-com components using CDK test harnesses |
Tool Details & Examples
lookup_component
Get the complete API reference for a specific component.
Parameters:
| Name | Type | Required | Description |
|------|------|----------|-------------|
| name | string | Yes | Component name or id (e.g. "button", "datepicker", "form-field") |
What it returns:
- Import statement
- Selector and exportAs
- Full inputs table (type, default, notes)
- Outputs table
- Sub-directives / sub-components
- Usage examples (HTML snippets)
Example call:
{ "name": "lookup_component", "arguments": { "name": "button" } }Example response (truncated):
### 4. Button
import { ComButton } from 'ngx-com/components/button';
Selector: button[comButton], a[comButton]
| Input | Type | Default |
|----------|-----------------------------------------|-----------|
| variant | 'solid' | 'outline' | 'ghost' | 'link' | 'solid' |
| color | 'primary' | 'accent' | 'warn' | 'muted' | 'primary' |
| size | 'sm' | 'md' | 'lg' | 'icon' | 'md' |
...Name matching is flexible — all of these work:
"button"(exact id)"Button"(case-insensitive name)"date"(partial match — returns Datepicker)
list_components
List all available components, optionally filtered by category.
Parameters:
| Name | Type | Required | Description |
|------|------|----------|-------------|
| category | enum | No | One of: all, form, overlay, display, layout, navigation |
Categories:
| Category | Components |
|----------|------------|
| form | Checkbox, Radio, Switch, Dropdown, Datepicker, Timepicker, Form Field, Native Control |
| overlay | Dialog, Menu, Popover, Tooltip, Toast, Confirm, Dropdown |
| display | Alert, Avatar, Badge, Card, Carousel, Code Block, Empty State, Icon, Item, Spinner, Table |
| layout | Separator, Collapsible, Paginator |
| navigation | Tabs, Segmented Control |
Example call:
{ "name": "list_components", "arguments": { "category": "form" } }Example response:
# ngx-com Components (form)
6 components available.
| Component | Selector | Import Path |
|----------------|-----------------------|------------------------------------|
| Checkbox | com-checkbox | ngx-com/components/checkbox |
| Dropdown | com-dropdown | ngx-com/components/dropdown |
| Form Field | com-form-field | ngx-com/components/form-field |
| Native Control | input[comNativeControl]| ngx-com/components/native-control |
| Radio | com-radio-group | ngx-com/components/radio |
| Switch | com-switch | ngx-com/components/switch |find_component
Describe a UI need in natural language and get matching component suggestions.
Parameters:
| Name | Type | Required | Description |
|------|------|----------|-------------|
| description | string | Yes | Describe the UI you need (e.g. "date picker with range selection") |
What it returns:
- Top 5 matching components ranked by relevance
- For each: import statement, selector, and key inputs
- Guidance to use
lookup_componentfor full details
Example call:
{ "name": "find_component", "arguments": { "description": "confirmation dialog before delete" } }Example response (truncated):
Found 3 matching component(s) for "confirmation dialog before delete":
## Confirm
import { ComConfirm, ... } from 'ngx-com/components/confirm';
Selector: [comConfirm]
...
## Dialog
import { ComDialog, ... } from 'ngx-com/components/dialog';
...
Use lookup_component with a specific name to get the full API reference.get_setup
Get complete installation and configuration instructions.
Parameters: None
What it returns:
- Install command and peer dependencies (required + optional)
- Theme CSS import instructions (individual files and bundle)
- CDK overlay stylesheet import
- Icon registration with
provideComIcons() - Date adapter setup with
provideNativeDateAdapter() - Import pattern explanation
- Utility functions overview
get_patterns
Get cross-cutting patterns that apply across multiple components.
Parameters: None
What it returns:
- Form integration — which components support
formControlName,[formControl],[(ngModel)] - Overlay components — list of all overlay-based components and their CDK usage
- Two-way signal binding — all
model()bindings with[()]syntax examples - Template customization — all
ng-templatedirectives with context variables - Required providers — which providers each component needs
- Theme tokens — semantic token pairing rules
get_testing_guide
Get a comprehensive guide for testing ngx-com components using CDK test harnesses.
Parameters: None
What it returns:
- Setup — TestBed configuration with
TestbedHarnessEnvironmentand zoneless change detection - Available harnesses — table of all 23 component harnesses with class names, import paths, and overlay status
- Basic usage — querying, filtering, and interacting with harnesses
- Overlay testing —
documentRootLoaderpattern for dialog, toast, menu, popover, confirm, tooltip, datepicker - Keyboard interaction —
TestKeyconstants for navigation testing - Nested harnesses — parent/child harness patterns (table rows, menu items, calendar cells)
- Complete example — full test file with TestBed, harness setup, and assertions
Keeping the Inventory in Sync
The MCP server's data comes from COMPONENT_INVENTORY.md — an LLM-optimized
reference generated from library source code. Three scripts keep it in sync.
Overview
Component source code (projects/com/components/)
|
| lib:sync-inventory — Claude reads source, writes docs
| lib:check-inventory — validates, catches drift in CI
| lib:generate-inventory — scaffolds from source (no AI)
v
COMPONENT_INVENTORY.md (repo root — source of truth)
|
| mcp:build — copies to mcp/data/ and compiles
v
mcp/data/COMPONENT_INVENTORY.md (bundled in published package)Script 1: lib:check-inventory — Validate (CI)
Fast, deterministic validation with no AI. Compares source code against the inventory and reports drift. Run this in CI.
npm run lib:check-inventoryWhat it checks:
| Check | Level | What it catches |
|-------|-------|-----------------|
| Missing sections | Error | New component directory with no inventory entry |
| Stale sections | Error | Inventory section for a deleted component |
| Selector mismatch | Error | Selector changed in source but not in docs |
| Undocumented signals | Warning | New input()/output()/model() not in inventory |
| Stale signals | Warning | Documented signal removed from source |
| Table row count | Warning | Quick reference table out of sync with sections |
How it works:
- Scans every directory under
projects/com/components/that has anindex.ts - For each, reads ALL
.tssource files (not just the main one) - Extracts
input(),output(),model()declarations via regex - Extracts selectors from
@Component/@Directivedecorators - Compares against the corresponding
### N. Namesection in the inventory - Reports errors (hard failures) and warnings (potential issues)
Handles edge cases:
- Aliased directories (
datepickerandtimepickerdocumented undercalendar) - Trigger directives (
popovermain file is the trigger, not the arrow) - Internal signals (skips
sf*,_*,userClass,touched) - Multi-file components (scans sub-directive files too)
Flags:
npm run lib:check-inventory -- --fix # print fix suggestionsExample output:
✗ Errors (1):
────────────────────────────────────────────────────────────
✗ Missing inventory section: "new-component" exists in source but has no ### section
Fix: Run "node scripts/generate-inventory-section.mjs new-component" to scaffold it
⚠ Warnings (2):
────────────────────────────────────────────────────────────
⚠ Undocumented input in "button": "loading" (boolean) exists in source but not in inventory
⚠ Potentially stale input in "card" inventory: "elevation" not found in any source fileScript 2: lib:generate-inventory — Scaffold (No AI)
Generates an inventory section by extracting metadata directly from source
files. Fast, no AI required — but produces a TODO placeholder for usage
examples.
npm run lib:generate-inventory <component-name>What it extracts automatically:
| Data | Source |
|------|--------|
| Import statement | index.ts exports |
| Selector, exportAs | @Component/@Directive decorator |
| Inputs table | input() declarations (name, type, default, alias) |
| Models | model() declarations (with two-way binding note) |
| Outputs table | output() declarations |
| Sub-directives | Other exported classes with selectors |
| @tokens JSDoc | Component class JSDoc comment |
| ControlValueAccessor | implements clause detection |
What you add manually:
- Usage examples (HTML snippets)
- Behavioral descriptions
- Complex provider documentation
How it works:
- Reads
index.tsto discover all exported classes - Reads the main component/directive
.tsfile - Extracts signals via regex (
readonly name = input<Type>(default)) - Reads sub-directive files for their selectors
- Outputs formatted markdown to stdout
- Outputs a summary to stderr (always visible)
Usage patterns:
# Preview on screen
npm run lib:generate-inventory button
# Append to inventory file
node scripts/generate-inventory-section.mjs new-component >> COMPONENT_INVENTORY.md
# Redirect to temp file for review
node scripts/generate-inventory-section.mjs new-component > /tmp/section.mdExample output:
### N. Badge
\`\`\`typescript
import { ComBadge } from 'ngx-com/components/badge';
\`\`\`
**Selector:** `[comBadge]` | **exportAs:** `comBadge`
#### Inputs
| Input | Type | Default | Notes |
|-------|------|---------|-------|
| `variant` | `BadgeVariant` | `'primary'` | |
| `size` | `BadgeSize` | `'default'` | |
| `pill` | `unknown` | `false` | |
#### Usage
\`\`\`html
<!-- TODO: Add usage examples -->
<span [comBadge]>Label</span>
\`\`\`
---Summary printed to stderr:
✓ Generated section for "Badge"
- 3 inputs, 0 models, 0 outputs
- 0 sub-directives
- Selector: [comBadge]
⚠ Add usage examples manually (HTML snippets)Script 3: lib:sync-inventory — AI-Powered Sync
The most powerful option. Uses claude -p (Claude Code CLI in non-interactive
mode) to read component source files and generate complete inventory sections
including usage examples.
npm run lib:sync-inventory [components...] [--all] [--dry-run]How it works:
sync-inventory.mjs
|
| 1. Detects which components are out of sync
| (compares source file timestamps vs COMPONENT_INVENTORY.md)
|
| 2. For each stale component, builds a prompt:
| "Read these files: projects/com/components/badge/*.ts
| Generate a complete inventory section with usage examples"
|
| 3. Spawns Claude Code CLI:
| claude -p --model sonnet --allowedTools "Read,Grep,Glob"
| |
| | Claude reads the source files using Read/Grep tools
| | Claude understands the component API
| | Claude writes practical HTML usage examples
| |
| v
| Returns complete markdown section
|
| 4. Replaces the section in COMPONENT_INVENTORY.md
|
| 5. Copies updated file to mcp/data/
v
Done — review changes and commitWhat Claude does that scripts can't:
- Writes practical, idiomatic usage examples
- Understands when to show reactive forms examples (CVA components)
- Composes with other library components (
com-icon,com-avatar,com-spinner) - Describes scenarios in HTML comments
- Preserves good existing examples while updating stale API docs
Flags:
| Flag | Behavior |
|------|----------|
| (no args) | Auto-detect stale components (source newer than inventory) |
| button checkbox | Sync only the named components |
| --all | Regenerate every section from scratch |
| --dry-run | Show what would be synced without modifying files |
Usage examples:
# Auto-detect and sync everything that's stale
npm run lib:sync-inventory
# Sync specific components after modifying them
npm run lib:sync-inventory button checkbox dropdown
# Regenerate the entire inventory from scratch
npm run lib:sync-inventory -- --all
# Preview what would change
npm run lib:sync-inventory -- --dry-run
# Combine: preview specific components
npm run lib:sync-inventory -- --dry-run badge alertExample output:
Syncing 3 component(s): badge, button, checkbox
~ badge...
✓ Generated (1242 chars)
~ button...
✓ Generated (1580 chars)
~ checkbox...
✓ Generated (2105 chars)
✓ Updated COMPONENT_INVENTORY.md
✓ Synced to mcp/data/COMPONENT_INVENTORY.md
Done. 3 section(s) processed.
Review the changes, then commit.Requirements:
claudeCLI must be in PATH (Claude Code installed globally)- Uses
sonnetmodel by default (configurable in script) - Each component takes ~10-30 seconds depending on size
Recommended Workflows
Adding a new component
# 1. Build the component
# ... write code in projects/com/components/new-component/ ...
# 2. Generate the inventory section with AI
npm run lib:sync-inventory new-component
# 3. Verify
npm run lib:check-inventory
# 4. Rebuild MCP server data
npm run mcp:build
# 5. Review and commit
git diff COMPONENT_INVENTORY.mdModifying an existing component (added/removed inputs)
# 1. Make your changes
# ... edit projects/com/components/button/button.directive.ts ...
# 2. Check what's out of sync
npm run lib:check-inventory
# 3. Auto-sync stale sections
npm run lib:sync-inventory
# 4. Rebuild MCP
npm run mcp:buildCI pipeline
# In your CI config (GitHub Actions, etc.)
npm run lib:check-inventory # fails if inventory is out of sync
npm run mcp:build # ensures MCP data is fresh
npm run mcp:test # smoke test the MCP serverFull regeneration (e.g. after major refactor)
npm run lib:sync-inventory -- --all
npm run lib:check-inventory
npm run mcp:build
npm run mcp:testDevelopment
Project structure
mcp/
├── package.json # "ngx-com-mcp" — separate npm package
├── tsconfig.json
├── test-server.mjs # End-to-end smoke test
├── data/
│ └── COMPONENT_INVENTORY.md # Bundled data (copied from repo root)
├── src/
│ ├── index.ts # Bin entry point (starts stdio transport)
│ ├── server.ts # MCP server with 5 tool definitions
│ ├── parser.ts # Markdown → structured ComponentEntry[]
│ └── setup-info.ts # Static setup instructions
└── dist/ # Compiled JS outputRelated scripts at repo root:
scripts/
├── check-inventory.mjs # Validate inventory vs source (CI)
├── generate-inventory-section.mjs # Scaffold section from source (no AI)
└── sync-inventory.mjs # AI-powered sync with claude -pPrerequisites
cd mcp
npm installBuild
From the mcp/ directory:
npm run buildOr from the repo root:
npm run mcp:buildThe build does two things:
prepare-data— copiesCOMPONENT_INVENTORY.mdfrom the repo root intomcp/data/tsc— compiles TypeScript tomcp/dist/
Test
From the mcp/ directory:
npm testOr from the repo root:
npm run mcp:testThe smoke test (test-server.mjs) spawns the server, sends MCP protocol messages, and
verifies all 5 tools return correct data.
Local development with .mcp.json
The repo root .mcp.json is already configured to use the local build:
{
"mcpServers": {
"ngx-com": {
"type": "stdio",
"command": "node",
"args": ["mcp/dist/index.js"]
}
}
}After running npm run mcp:build, restart your AI tool to pick up the server.
All npm scripts
| Script | Where | What it does |
|--------|-------|--------------|
| npm run mcp:build | root | Build MCP server (copy data + compile TS) |
| npm run mcp:test | root | Run MCP smoke test |
| npm run lib:check-inventory | root | Validate inventory vs source code |
| npm run lib:generate-inventory <name> | root | Scaffold a section from source (no AI) |
| npm run lib:sync-inventory | root | AI-powered sync with claude -p |
Architecture
Data flow
Component source code
projects/com/components/*/
|
| lib:sync-inventory (claude -p) or lib:generate-inventory
v
COMPONENT_INVENTORY.md (repo root — source of truth, 2400+ lines)
|
| mcp:build → prepare-data step (cp)
v
mcp/data/COMPONENT_INVENTORY.md (bundled copy for published package)
|
| parser.ts reads at first tool call (lazy, cached in memory)
v
InventoryData { overview, components[], crossCutting }
|
| server.ts tool handlers query the parsed data
v
MCP tool responses (JSON-RPC over stdio) → AI tool → correct codeParser
parser.ts splits COMPONENT_INVENTORY.md by ### N. Name headers and extracts:
name— display name (e.g. "Button")id— kebab-case id derived from import path (e.g. "button")importStatement— first TypeScript code blockselector— extracted from**Selector:**lineraw— full markdown section for the component
The inventory is parsed once on first tool call and cached in memory for the lifetime of the server process.
File resolution
The parser looks for the inventory file in two locations:
mcp/data/COMPONENT_INVENTORY.md— bundled in the published npm package../../COMPONENT_INVENTORY.md— repo root (development fallback)
This means it works both when published to npm and during local development.
Protocol
- Transport: stdio (stdin/stdout)
- Protocol: JSON-RPC 2.0 (MCP specification)
- SDK:
@modelcontextprotocol/sdkv1.x - Schema validation: Zod
Publishing
The MCP server is published independently from the main library using its own
tag prefix (mcp-v*) and GitHub Actions workflow.
Prerequisites
- Sync inventory and build:
npm run lib:sync-inventory # ensure docs are up to date
npm run lib:check-inventory # validate
npm run mcp:build # build server + copy data
npm run mcp:test # smoke test- Verify package contents:
cd mcp
npm pack --dry-runExpected files:
dist/index.js
dist/server.js
dist/parser.js
dist/setup-info.js
data/COMPONENT_INVENTORY.md
package.json
README.mdRelease with the script
The release script bumps the version, commits, tags, pushes, and creates a
GitHub Release — which triggers the release-mcp.yml workflow to publish to npm.
# Bump patch (0.1.0 → 0.1.1)
npm run release:mcp:patch
# Bump minor (0.1.0 → 0.2.0)
npm run release:mcp:minor
# Bump major (0.1.0 → 1.0.0)
npm run release:mcp:majorFor more control, run the script directly:
# Preview what would happen
node scripts/release-mcp.mjs patch --dry-run
# Create commit and tag locally without pushing
node scripts/release-mcp.mjs minor --no-push
# Explicit version
node scripts/release-mcp.mjs 1.0.0
# Prerelease
node scripts/release-mcp.mjs premajor --preid=betaRelease flow:
- Bumps version in
mcp/package.json - Commits:
chore(release): mcp-v<version> - Creates tag:
mcp-v<version> - Pushes commit and tag to origin
- Creates GitHub Release titled "MCP Server v<version>"
- GitHub Actions (
release-mcp.yml) builds and publishes to npm
Manual release
If you need to release without the script:
# 1. Bump version in mcp/package.json
# 2. Commit and tag
git add mcp/package.json
git commit -m "chore(release): mcp-v0.2.0"
git tag mcp-v0.2.0
git push origin HEAD --follow-tags
# 3. Create GitHub Release
gh release create mcp-v0.2.0 --title "MCP Server v0.2.0"Consumer verification
After publishing, consumers can verify the server works:
npx ngx-com-mcp # should start and wait for MCP messages on stdinPress Ctrl+C to stop. If it starts without errors, the server is working correctly.
