Smart.UI MCP Server
A Model Context Protocol server that gives any AI coding assistant deep, accurate knowledge of the Smart.UI Web Components library — 110+ components, runnable examples for 5 frameworks, zero hallucinations.
01What this is and why you want it
smart-ui-mcp-server is a Model Context Protocol server that gives any MCP-aware coding assistant (Claude Code, Claude Desktop, Cursor, GitHub Copilot Chat in agent mode, Continue, Windsurf, Zed…) deep, accurate knowledge of the Smart.UI Web Components library.
It exposes:
- 110+ Smart.UI components with the full API surface - every property, method, event, CSS variable, and allowed-value enum, sourced from the official component metadata.
- The exact module import and theme stylesheet stack for any component - no more guessing whether the property is editing or editable, or which theme files to load and in what order.
- Demo browsing - the assistant can list and read every demo your repo ships, per framework (Web Components, React, Angular, Vue).
- Documentation browsing - the same for /documentation topics (overview.htm, api.htm, accessibility.htm, plus framework-specific guides for Angular, Blazor, React, Vue).
- A code generator that emits a complete runnable file for Web Components, React, Angular, Vue, and Blazor, with the right imports, theme stylesheet, attribute markup, and post-mount property assignments for complex options.
Why this beats freehand prompting
Without the MCP, an assistant has to guess Smart.UI API names from training data. With the MCP, the assistant queries the actual schema before writing code. Concretely:
- It writes editing (the real property name) instead of hallucinating editable.
- It emits the exact paths that exist in your node_modules - smart.default.css + fluent/light/smart.fluent.css for the theme stack, and a single smart.grid.js import that already bundles every sub-module - not a guess.
- It can crib a working pattern from demos/grid/grouping/ instead of inventing one.
0260-second quick start
1. Install Claude Code (skip if you already have it) npm install -g @anthropic-ai/claude-code 2. Register the Smart.UI MCP server claude mcp add smart-ui npx smart-ui-mcp-server 3. Open any project and ask: claude > Use the smart-ui MCP. Generate a Web Components page with a smart-grid > bound to a 10-row JSON array of employees (id, name, position, salary), > with sorting and paging enabled. Theme fluent.
You'll get a complete runnable index.html with the right tag, imports, and config.
03Installation
From npm (recommended)
global install npm install -g smart-ui-mcp-server or call directly with npx (no global install needed) npx smart-ui-mcp-server
The package bundles a snapshot of the Smart.UI API metadata (110 components, ~4 MB unpacked) so it works zero-config straight after install. No live Smart.UI checkout is required for the core tools.
From a tarball
If you received smart-ui-mcp-server-1.0.0.tgz directly:
npm install -g ./smart-ui-mcp-server-1.0.0.tgz
From source
git clone <repo-url> cd smart-ui-mcp-server npm install npm test 45 smoke tests should pass npm start run the server over stdio (for manual probing)
Requirements
- Node.js 18 or newer (uses ESM and the modern fs promises API).
- Any MCP-capable assistant. Each one has its own config format - see the next section.
04Connecting your assistant
The Smart.UI MCP server speaks MCP over stdio. Every assistant below uses the same underlying command (
npx smart-ui-mcp-server) - only the config file differs.
Claude Code (CLI)
The cleanest path. From any directory:
claude mcp add smart-ui npx smart-ui-mcp-serverTo verify: claude mcp list. To remove later: claude mcp remove smart-ui.
Add it project-locally instead by passing --scope project, which writes to .mcp.json in the project root and is auto-picked-up by anyone who clones the repo.
Claude Desktop
Edit claude_desktop_config.json:
- macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
- Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"smart-ui": {
"command": "npx",
"args": ["smart-ui-mcp-server"]
}
}
}
Restart Claude Desktop. The tools should appear under the 🔨 hammer icon in the message input.
VS Code - GitHub Copilot Chat (agent mode)
Create .vscode/mcp.json in your workspace root:
{
"servers": {
"smart-ui": {
"type": "stdio",
"command": "npx",
"args": ["smart-ui-mcp-server"]
}
}
}
Open Copilot Chat, switch to agent mode, and ask a Smart.UI question. The tools appear automatically.
Cursor
Cursor uses ~/.cursor/mcp.json (or <workspace>/.cursor/mcp.json for project scope):
{
"mcpServers": {
"smart-ui": {
"command": "npx",
"args": ["smart-ui-mcp-server"]
}
}
}
Continue
Edit ~/.continue/config.json:
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "npx",
"args": ["smart-ui-mcp-server"]
}
}
]
}
}
Windsurf
Edit ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"smart-ui": {
"command": "npx",
"args": ["smart-ui-mcp-server"]
}
}
}
Zed
Add to ~/.config/zed/settings.json:
{
"context_servers": {
"smart-ui": {
"command": {
"path": "npx",
"args": ["smart-ui-mcp-server"]
}
}
}
}
05Verifying the connection
After restarting your assistant, ask:
A working setup will respond with a list of 100+ smart-* tags. If it says “I don't have access to that information” or makes up tag names that don't start with smart-, the MCP isn't wired in - check your config file path and restart the assistant.
You can also test directly from a shell:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | npx smart-ui-mcp-server
(Press Ctrl+C after a second.) You should see a JSON response listing all 13 tools.
06The 13 tools at a glance
| Tool | When the assistant calls it |
|---|---|
| list_widgets | “What components are there?” / fuzzy lookup by keyword. |
| get_widget | First call for any new component - gets counts, tag, class, module file, features. |
| get_widget_properties | Before writing config - finds the exact property name and its allowed values. |
| get_widget_methods | When the prompt mentions an imperative action (export, addRow, refresh). |
| get_widget_events | When wiring event handlers (onChange, onClick, onCellEditEnd). |
| get_widget_css_variables | Custom theming / CSS variable overrides. |
| get_widget_types | When a property has an enum type and the assistant needs the legal values. |
| get_required_scripts | Always called before generating code - gives the exact module URLs and the theme link. |
| list_demos | “What demos do you ship for X?” - returns folder names. |
| get_demo_code | Read a specific demo folder (returns every source file in it). |
| list_documentation | Lists /documentation/<topic>/*.htm files for a component. |
| get_documentation | Read a specific doc file (overview.htm, api.htm, accessibility.htm). |
| generate_example | Emits the final runnable file for the chosen framework. |
07How to refer to a component
Every Smart.UI component has three equivalent identifiers; the MCP accepts any of them in every tool call:
- bare slug - button, dropdownlist, ganttchart
- custom-element tag - smart-button, smart-drop-down-list, smart-gantt-chart
- class name - Button, DropDownList, GanttChart
All three resolve to the same component record. The generator always emits the canonical Smart.UI form in the output code - <smart-grid> for HTML / Vue, <Grid> for React / Blazor, and empre class="prettyprint"><smart-grid> with GridComponent for Angular.
08Worked tutorial - Grid (Web Components)
What happens under the hood
- The assistant calls get_widget("grid"). It learns the tag is smart-grid, the class is Grid, the available feature modules include sort, filter, pager, edit, group, export, reorder, select, tree, and the shorthand attributes include sortable, filterable, pageable, editable, groupable, selectable, columnResize, columnReorder.
- Because the prompt only asks to switch features on, the assistant picks the shorthand attributes (cleaner config) over the configurable object properties.
- It calls get_required_scripts("grid", { theme: "fluent" }) and gets two stylesheet links - smart.default.css (base) plus fluent/light/smart.fluent.css (overlay) - and exactly one module URL: smart.grid.js. That single file already imports every sub-module (sort, filter, pager, edit, …); no extra script tags needed.
- It calls generate_example with the merged options.
What you get
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Grid example</title>
<!-- smart.default.css is the base; smart.fluent.css overlays it -->
<link rel="stylesheet" type="text/css" href="../../../source/styles/smart.default.css" />
<link rel="stylesheet" type="text/css" href="../../../source/styles/fluent/light/smart.fluent.css" />
<!-- smart.grid.js already bundles sort/filter/pager/edit/group/… -->
<script type="module" src="../../../source/modules/smart.grid.js"></script>
</head>
<body>
<div id="grid"></div>
<script type="module">
window.addEventListener('load', () => {
new Smart.Grid({
dataSource: new Smart.DataAdapter({
dataSource: [
{ id: 1, name: 'Nancy Davolio', position: 'Sales Rep', salary: 60000 },
{ id: 2, name: 'Andrew Fuller', position: 'VP Sales', salary: 95000 },
],
dataFields: [
'id: number',
'name: string',
'position: string',
'salary: number',
],
}),
sortable: true,
filterable: true,
pageable: true,
columns: [
{ label: 'ID', dataField: 'id' },
{ label: 'Name', dataField: 'name' },
{ label: 'Position', dataField: 'position' },
{ label: 'Salary', dataField: 'salary', cellsFormat: 'c0' },
],
appendTo: '#grid',
});
});
</script>
</body>
</html>
Theme application - always layer the overlay on the default base
<link rel="stylesheet" href="…/source/styles/smart.default.css" /> <!-- base --> <link rel="stylesheet" href="…/source/styles/fluent/light/smart.fluent.css" /> <!-- overlay -->
Theme paths in the source repo are nested. Each non-default theme has its own subfolder under
source/styles/<theme>/with separate
light/and
dark/variants:
| Stylesheet | Source-repo path |
|---|---|
| Base (required) | source/styles/smart.default.css |
| Fluent light | source/styles/fluent/light/smart.fluent.css |
| Fluent dark | source/styles/fluent/dark/smart.fluent-dark.css |
| Material light | source/styles/material/light/smart.material.css |
| Material dark | source/styles/material/dark/smart.material-dark.css |
| Bootstrap | source/styles/bootstrap/light/smart.bootstrap.css |
| Strata / Tabula | source/styles/<theme>/light/smart.<theme>.css |
get_required_scripts(..., { theme: 'fluent' }) returns both URLs already ordered correctly. For dark mode pass dark: trueand the overlay flips to the corresponding
*-dark.cssvariant.
The npm-packaged React and Angular distributions flatten the most common themes to the top level (so React's generated code uses
smart-webcomponents-react/source/styles/smart.fluent.cssdirectly), but the Vue (
smart-webcomponents) package and the source repo both keep the nested layout.
theme="fluent"as an attribute on the component - themes are applied via the CSS stack, not via element attributes. The
themeproperty on a component exists for runtime color-variant switching only.
One script tag per component - sub-modules are bundled
Smart.UI's top-level
smart.<component>.jsES module already imports every sub-module the component needs. For example,
smart.grid.jsimports
smart.grid.sort.js,
smart.grid.filter.js,
smart.grid.edit.js,
smart.grid.pager.js,
smart.grid.group.js, and 20+ others - you load the grid with a single
<script type="module">tag.
bundledSubmodulesfield on
get_required_scriptsand
featuresfield on
get_widgetshow what's included; they're for documentation, not for additional
<script>tags.
Shorthand attributes vs full configuration
Smart Grid (and many other components) accepts two parallel ways of toggling behaviour. Prefer the shorthand attributes whenever you only need to switch a feature on or off. They produce cleaner, more declarative HTML.
| Shorthand boolean attr | Full-config property |
|---|---|
| sortable | sorting = { enabled, mode, … } |
| filterable | filtering = { enabled, filterRow, … } |
| pageable | paging = { enabled, pageSize, … } |
| editable | editing = { enabled, mode, … } |
| groupable | grouping = { enabled, mode, … } |
| selectable | selection = { enabled, mode, … } |
| columnResize | per-column allowResize plus options |
| columnReorder | per-column allowReorder plus options |
Switch to the object-form property only when you need to configure how the feature behaves (filter mode, page size, batch-edit, multi-sort, etc.). The MCP surfaces the available shorthand attrs for each component via
get_widget(the
shorthandAttributesfield) - so a prompt like “add sorting and filtering to the grid” reliably produces
sortable filterablerather than the longer object form.
SMART_UI_SCRIPTS_PREFIX="/assets/smart-webcomponents/" npx smart-ui-mcp-serverOr pass
prefix: "/assets/..."directly in the
generate_examplecall when you're prompting.
09Worked tutorial - Scheduler (React)
<Scheduler>showing Day, Week, and Month views. Use the fluent theme.
Behind the scenes
- get_widget("scheduler") → tag smart-scheduler, class Scheduler.
- get_widget_properties("scheduler", { nameFilter: "view" }) → confirms view, viewType, views, plus an enum of allowed view-type strings.
- get_widget_types("scheduler") → returns the View enum (day, week, month, agenda, timelineDay…).
- generate_example with framework: "react".
Result
import React from 'react';
import { createRoot } from 'react-dom/client';
// Theme stack: base first, overlay second.
import 'smart-webcomponents-react/source/styles/smart.default.css';
import 'smart-webcomponents-react/source/styles/smart.fluent.css';
import { Scheduler } from 'smart-webcomponents-react/scheduler';
function App() {
return (
<Scheduler
view="week"
views={['day', 'week', 'month']}
/>
);
}
const root = createRoot(document.getElementById('root'));
root.render(<App />);
Grid-family components - use Smart.DataAdapter
For data-driven components (Grid, Chart, Scheduler, CardView, Kanban, GanttChart, PivotTable, QueryBuilder), the React import becomes
{ Smart, <Component> } and the data source is wrapped in new Smart.DataAdapter({ dataSource, dataFields }):
import { Smart, Grid } from 'smart-webcomponents-react/grid';
function App() {
const dataSource = new Smart.DataAdapter({
dataSource: [
{ id: 1, name: 'Alice', salary: 60000 },
{ id: 2, name: 'Bob', salary: 75000 },
],
dataFields: ['id: number', 'name: string', 'salary: number'],
});
return (
<Grid
dataSource={dataSource}
sortable
filterable
pageable
columns={[
{ label: 'ID', dataField: 'id' },
{ label: 'Name', dataField: 'name' },
{ label: 'Salary', dataField: 'salary', cellsFormat: 'c0' },
]}
/>
);
}
get_widget_properties("scheduler", { nameFilter: "data" }) to find dataSource, then
get_demo_code("scheduler", "recurring") to see the recurring-event shape your repo ships, and update the code accordingly.10Worked tutorial - Chart with annotations (Angular)
The MCP path
- get_widget("chart") → features include annotations.
- get_required_scripts("chart", { features: ["annotations"], theme: "fluent" }) adds smart.chart.annotations.js to the module list.
- get_widget_properties("chart", { nameFilter: "annotation" }) → confirms the annotations property and its shape.
- generate_example with framework: "angular".
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChartComponent, ChartModule } from '@smart-webcomponents-angular/chart';
// angular.json -> "styles": [
// "./node_modules/@smart-webcomponents-angular/chart/styles/smart.base.css",
// "./node_modules/@smart-webcomponents-angular/chart/styles/smart.chart.css",
// "./node_modules/@smart-webcomponents-angular/chart/styles/smart.common.css",
// "./node_modules/@smart-webcomponents-angular/chart/styles/smart.fluent.css" // theme overlay
// ]
@Component({
selector: 'app-root',
standalone: true,
imports: [ChartModule],
template: `<smart-chart #chart></smart-chart>`,
})
export class AppComponent implements AfterViewInit {
@ViewChild('chart', { read: ChartComponent, static: false })
chart!: ChartComponent;
ngAfterViewInit(): void {
this.chart.caption = 'Monthly Sales';
this.chart.seriesGroups = [{
type: 'line',
series: [{ dataField: 'sales', displayText: 'Sales' }],
}];
this.chart.annotations = [{
type: 'line',
xAxis: { value: 0 }, yAxis: { value: 5000 },
xAxisEnd: { value: 11 }, yAxisEnd: { value: 5000 },
lineColor: '#d33', lineWidth: 2,
}];
}
}
11Worked tutorial - Tree + context menu (composition)
This is the most ambitious type of prompt - the assistant composes two components.
smart-treeshowing folders. Wire a
smart-menuas a right-click context menu with Add / Rename / Delete actions.
The MCP path
- get_widget("tree") - confirms smart-tree with allowDrag, filterable, selectionMode.
- get_widget("menu") - confirms smart-menu with mode="dropDown" and a select event.
- get_widget_events("tree", { nameFilter: "context" }) - finds an event the assistant can use to position the menu, or falls back to the native contextmenu DOM event.
- list_demos("tree") - looks for any shipped right-click pattern; if one exists, get_demo_code reads it.
- generate_example is called twice - once for tree, once for menu - and the assistant manually composes them in one HTML file.
The output combines the two generated stubs with a
contextmenulistener on the tree that opens the menu at the click coordinates and dispatches the selected action.
12Prompt patterns - a cheat sheet
The MCP works best when your prompt includes:
- An explicit “Use the smart-ui MCP” - primes the assistant to call the tools instead of guessing.
- A target framework - webcomponents, react, angular, vue, or blazor.
- A theme name if you care - default, fluent, material, bootstrap, strata, tabula.
- The features you want by name - e.g. “sorting, paging, filtering, row grouping”. The assistant will resolve these to the right feature modules via get_required_scripts.
Templates
Generate from scratch
Adapt a shipped demo
API exploration
Migration / fix
13Configuration reference
All env vars are optional.
| Variable | Default | Purpose |
|---|---|---|
| SMART_UI_REPO_ROOT | unset | Path to a local Smart.UI checkout. Enables list_demos, get_demo_code, list_documentation, get_documentation, and live feature/theme discovery. |
| SMART_UI_SCRIPTS_PREFIX | ../../../source/ | Prefix injected into generated <script> / <link> URLs. |
| SMART_UI_REACT_PACKAGE | smart-webcomponents-react | npm package name used in React imports. |
| SMART_UI_ANGULAR_PACKAGE | smart-webcomponents-angular | npm package name used in Angular imports. |
| SMART_UI_VUE_PACKAGE | smart-webcomponents | npm package name used in Vue imports. |
Setting env vars per-client
Most MCP clients pass through env vars from your shell. To set them per-server (instead of globally), use the
envfield in the client config:
{
"mcpServers": {
"smart-ui": {
"command": "npx",
"args": ["smart-ui-mcp-server"],
"env": {
"SMART_UI_REPO_ROOT": "/Users/me/code/smart-ui-repo",
"SMART_UI_SCRIPTS_PREFIX": "/assets/smart/"
}
}
}
}
14Local development & contributing
git clone <repo> cd smart-ui-mcp-server npm install rebuild the bundled snapshot from a Smart.UI checkout SMART_UI_REPO_ROOT=/path/to/Team npm run build-data run the 45-test smoke suite SMART_UI_REPO_ROOT=/path/to/Team npm test run the server interactively (for hand-rolled JSON-RPC probing) npm start
Adding a new tool
- Implement the logic in src/<area>.js (or a new module).
- Register it in src/server.js with server.registerTool(...). Use Zod to declare the input schema.
- Add a smoke test in test/smoke.js.
- Update README.md and this tutorial's tools table.
Updating the bundled API metadata
Whenever Smart.UI ships new components or new properties:
SMART_UI_REPO_ROOT=/path/to/Team npm run build-data
This refreshes
data/api/*.json,
data/features.json,
data/themes.json,
data/widget-scripts.json, and
data/snapshot.json.
15Troubleshooting
“Tool not found” / the assistant doesn't see Smart.UI
- Restart the assistant after editing the MCP config.
- Confirm the config file path is the one your assistant actually reads (Claude Desktop on Windows is
%APPDATA%\Claude\
, not%LOCALAPPDATA%
). - Run
npx smart-ui-mcp-server
from a terminal - if it starts without errors, the binary is fine and the issue is in your client config.
“Smart.UI API metadata not found”
The bundled snapshot lives in
data/api/. If you installed via
npm installand still see this, your install was incomplete. Reinstall:
npm uninstall -g smart-ui-mcp-server npm install -g smart-ui-mcp-server
If you're running from source, run
npm run build-dataonce.
Generated examples reference modules that don't exist on disk
The default
SMART_UI_SCRIPTS_PREFIX(
../../../source/) assumes a folder layout like
<repo>/demos/<widget>/<example>/index.htmlwith Smart.UI sources at
<repo>/source/. If your project layout differs, override the prefix - see Configuration reference.
list_demos
returns an empty array
The demos browser only works against a local Smart.UI checkout. Set
SMART_UI_REPO_ROOTto a folder that contains a
demos/(and optionally
react/demos/,
smart-angular/demos/,
vue/vue-3/demos/) subfolder.
The assistant emits the wrong tag name
If the generated code uses an unfamiliar prefix or a tag that doesn't start with
smart-, the assistant is guessing instead of calling the MCP. Re-prompt with:
get_widgetfor each component you reference and use the exact
tagfield it returns.
“Unknown widget” errors
Smart.UI uses kebab-case multi-word tags. If you call
getWidget("dropdown-list") or "DropDownList"it resolves fine; if you misspell (
"dropdownllist") it returns an error. Run
list_widgets({ filter: "drop" }) to find the right id.
16FAQ
Does this require an Anthropic API key / Claude subscription?
No. The MCP server itself is plain Node.js with no API calls. It only provides knowledge to whatever assistant you've connected - that assistant provides its own model.
Does it work offline?
Yes. After
npm install, all metadata is on disk. No network calls at runtime.
Can I use it with my own private Smart.UI fork?
Yes. Set
SMART_UI_REPO_ROOTto your fork's root, and either run
npm run build-datato refresh the bundled snapshot, or leave it pointed at the live fork - the server reads JSON / source / demos / docs directly. You can also override the npm package names emitted in generated React / Angular / Vue code via
SMART_UI_REACT_PACKAGEetc.
Does it cover Smart.UI for Blazor too?
Yes -
generate_examplewith
framework: "blazor"emits Razor markup using
@using Smart.Blazorand PascalCased element tags (
<Button Value="…" />).
Can I add my own custom-component metadata?
Yes. Drop additional
<slug>.jsonfiles into the data folder your
SMART_UI_REPO_ROOTpoints at and rerun
npm run build-data. The server picks them up alongside the official components - they're available through every tool just like the built-ins.
How big is the bundled snapshot?
~4 MB unpacked, ~720 KB packed. The bulk is the per-component API JSON.
How do I report a bug?
Open an issue at github.com/HTMLElements/smart-webcomponents/issues with: the prompt you used, the tool call(s) the assistant made, the actual vs expected output, and your assistant + MCP server versions.