metricui
MCP server for MetricUI — a React dashboard component library. Provides AI coding tools with full API references, working examples, format suggestions, prop validation, and complete dashboard scaffolding for building analytics UIs.
README
<p align="center"> <img src="https://metricui.com/og.png" alt="MetricUI" width="600" /> </p>
<h1 align="center">MetricUI</h1>
<p align="center"> <strong>The missing UI layer for React dashboards.</strong> <br /> KPI cards, charts, tables, and layout — with built-in formatting, theming, data states, and zero config. </p>
<p align="center"> <a href="https://metricui.com">Homepage</a> · <a href="https://metricui.com/docs">Docs</a> · <a href="https://metricui.com/demos/saas">SaaS Demo</a> · <a href="https://metricui.com/demos/github">GitHub Demo</a> · <a href="#mcp-server">MCP Server</a> · <a href="https://metricui.com/roadmap">Roadmap</a> </p>
<p align="center"> <img src="https://metricui.com/screenshots/full-dark.png" alt="MetricUI SaaS Dashboard — dark mode" width="800" /> </p>
<p align="center"> <em><a href="https://metricui.com/demos/saas">Live SaaS demo</a> — DashboardHeader, filters, KpiCards with conditions, Callout alerts, Waterfall chart. <a href="https://metricui.com/demos/github">GitHub demo</a> also available.</em> </p>
Install
npm install metricui
That's it. All chart dependencies are included.
Why MetricUI?
You're building a dashboard. You need KPI cards, charts, tables. You reach for Recharts + shadcn + custom CSS and spend days wiring up formatting, dark mode, loading states, and responsive layouts.
MetricUI does all of that in one import.
import {
MetricProvider, FilterProvider, DashboardHeader, PeriodSelector,
MetricGrid, KpiCard, AreaChart, DonutChart, DataTable, Callout,
} from "metricui";
import "metricui/styles.css";
export default function Dashboard() {
return (
<MetricProvider theme="emerald">
<FilterProvider defaultPreset="30d">
<DashboardHeader title="Revenue" lastUpdated={new Date()} actions={<PeriodSelector comparison />} />
<MetricGrid>
<MetricGrid.Section title="Key Metrics" />
<KpiCard title="Revenue" value={127450} format="currency"
comparison={{ value: 113500 }} comparisonLabel="vs last month"
sparkline={{ data: [89, 94, 99, 103, 109, 114, 127], previousPeriod: [78, 82, 85, 88, 91, 95, 98] }}
conditions={[
{ when: "above", value: 120000, color: "emerald" },
{ when: "below", value: 90000, color: "red" },
]}
/>
<KpiCard title="Users" value={8420} format="compact"
comparison={[{ value: 7680, label: "vs last month" }, { value: 6200, label: "vs last year" }]}
highlight
/>
<KpiCard title="Churn" value={3.2} format="percent"
comparison={{ value: 3.7, invertTrend: true }}
goal={{ value: 2.5, showTarget: true, showRemaining: true }}
/>
<Callout value={12.3} rules={[
{ min: 10, variant: "success", title: "Strong Growth", message: "Revenue grew {value}% this month." },
{ max: 0, variant: "error", title: "Revenue Declined", message: "Revenue dropped {value}%." },
]} />
<MetricGrid.Section title="Trends" border />
<AreaChart data={revenueData} comparisonData={prevPeriod} format="currency" title="Revenue Trend"
referenceLines={[{ axis: "y", value: 50000, label: "Target", style: "dashed" }]}
thresholds={[{ from: 0, to: 30000, color: "#EF4444", opacity: 0.05 }]}
/>
<DonutChart data={planBreakdown} format="currency" title="By Plan" centerValue="$127K" centerLabel="Total" />
<MetricGrid.Section title="Details" border />
<DataTable data={customers} title="Top Customers" columns={columns} searchable pageSize={10} />
</MetricGrid>
</FilterProvider>
</MetricProvider>
);
}
Zero layout code. MetricGrid auto-detects component types — KPIs row up, charts pair, tables go full width. DashboardHeader shows live status with auto-ticking "Updated Xm ago". FilterProvider + PeriodSelector wire time filtering across the page. Responsive out of the box.
Features
KPI Cards — Not Just Numbers
<p> <img src="https://metricui.com/screenshots/kpi-dark.png" alt="KpiCard with goal progress" width="280" /> </p>
Sparkline with previous-period overlay. Goal progress bars. Conditional red/amber/green coloring. Multiple comparison badges. Copyable values. Drill-down links. Docs →
Charts with Reference Lines & Threshold Bands
<p> <img src="https://metricui.com/screenshots/area-dark.png" alt="AreaChart with threshold bands" width="500" /> </p>
Mark targets, benchmarks, and danger zones directly on charts. Comparison overlays show period-over-period trends as dashed lines. Works on AreaChart, LineChart, and BarChart.
<AreaChart
data={revenueData}
comparisonData={previousPeriod}
referenceLines={[{ axis: "y", value: 50000, label: "Target", style: "dashed" }]}
thresholds={[{ from: 0, to: 30000, color: "#EF4444", opacity: 0.05 }]}
format="currency"
/>
Data-Driven Alerts
<p> <img src="https://metricui.com/screenshots/callout-light.png" alt="Callout alert with embedded metric" width="500" /> </p>
Pass a value and rules — Callout auto-selects the right variant, title, and message. Supports embedded formatted metrics, action buttons, collapsible detail, and auto-dismiss.
Expandable Data Tables
<p> <img src="https://metricui.com/screenshots/table-dark.png" alt="DataTable with expanded row showing sparkline, gauge, and status indicators" width="700" /> </p>
Click a row and a mini-dashboard slides open — sparklines, gauges, status indicators, badges. Plus search, multi-sort, pagination, pinned columns, 12 column types, and row conditions. Docs →
Conversion Funnels
<p> <img src="https://metricui.com/screenshots/funnel-light.png" alt="Funnel chart with conversion rates" width="500" /> </p>
Auto-computed stage-to-stage conversion rates. Vertical or horizontal. Smooth or linear interpolation. Docs →
Light & Dark Mode
<p> <img src="https://metricui.com/screenshots/full-light.png" alt="MetricUI Wikipedia dashboard — light mode" width="700" /> </p>
<em><a href="https://metricui.com/demos/world">Wikipedia live demo</a> in light mode.</em>
CSS variables. Zero config. Every component adapts automatically. Theming guide →
Smart Format Engine
One prop formats any value. Currency, percentages, durations, compact notation — with locale support. Docs →
<KpiCard value={127450} format="currency" /> // → $127.5K
<KpiCard value={4.2} format="percent" /> // → 4.2%
<KpiCard value={3725} format="duration" /> // → 1h 2m 5s
<KpiCard value={2400000} format="number" /> // → 2.4M
Theme Presets
One prop. Entire dashboard changes color. 8 built-in presets. Custom presets via ThemePreset type. Theming guide →
<MetricProvider theme="emerald"> // Green accent + green-first chart palette
<MetricProvider theme="rose"> // Pink accent + pink-first chart palette
<MetricProvider theme="amber"> // Warm amber everything
MetricGrid — Zero Layout Code
Drop components in. It figures out the layout. Docs →
<MetricGrid>
<MetricGrid.Section title="Overview" />
<KpiCard ... /> <KpiCard ... /> <KpiCard ... />
<AreaChart ... /> {/* Auto 2/3 width */}
<DonutChart ... /> {/* Auto 1/3 width */}
<DataTable ... /> {/* Auto full width */}
</MetricGrid>
Filter System
Complete filter context — wire PeriodSelector, DropdownFilter, SegmentToggle, and FilterTags together with zero boilerplate. Filtering guide →
<FilterProvider defaultPreset="30d">
<DashboardHeader title="Dashboard" actions={<PeriodSelector comparison />} />
<SegmentToggle options={["All", "Enterprise", "SMB"]} field="segment" />
<DropdownFilter label="Region" options={regions} field="region" multiple />
<FilterTags /> {/* Auto-renders active filters as dismissible chips */}
</FilterProvider>
Data States
Every component handles loading, empty, error, and stale states out of the box. Docs →
Error Boundaries
One chart crashes? The rest keep running. Dev mode shows component name + actionable hints. Prod mode shows clean retry UI.
Accessibility
prefers-reduced-motion, focus-visible rings, ARIA attributes on charts, keyboard-accessible drill-downs. Docs →
Components
Cards & Metrics
| Component | What it does | Docs |
|---|---|---|
| KpiCard | Comparison badges, sparkline overlays, goal progress, conditional coloring, copyable, drill-down | Docs |
| StatGroup | Multiple metrics in a dense responsive grid row with per-stat comparisons | Docs |
Charts
| Component | What it does | Docs |
|---|---|---|
| AreaChart | Gradient fills, stacking, dual Y-axis, comparison overlays, reference lines, threshold bands | Docs |
| LineChart | Clean lines — same props as AreaChart without fill | Docs |
| BarChart | 6 presets, comparison/target bars, sorting, negative values, reference lines | Docs |
| BarLineChart | Dual-axis combo: bars + lines — unified data format | Docs |
| DonutChart | Center KPI content, arc labels, percentage mode | Docs |
| Gauge | Arc gauge with threshold zones, target markers, comparison badges | Docs |
| HeatMap | 2D matrix, cross-hair hover, sequential + diverging color scales | Docs |
| Funnel | Conversion pipeline with auto-computed rates | Docs |
| Waterfall | Sequential +/- changes with auto running totals, connectors | Docs |
| BulletChart | Actual vs target with qualitative range bands | Docs |
| Sparkline | Inline micro-chart with reference lines, bands, trend coloring | Docs |
Data
| Component | What it does | Docs |
|---|---|---|
| DataTable | Sort, search, pagination, expandable rows, 12 column types, pinned columns, row conditions | Docs |
Layout
| Component | What it does | Docs |
|---|---|---|
| DashboardHeader | Live/stale status, auto-ticking "Updated Xm ago", breadcrumbs, action slots | Docs |
| MetricGrid | Smart auto-layout grid with staggered reveal animations | Docs |
| SectionHeader | Labeled divider with description popover, badge, action slot | Docs |
| Divider | Horizontal/vertical separator with label, icon, accent | Docs |
Filters
| Component | What it does | Docs |
|---|---|---|
| FilterProvider | Context that wires all filter components. useMetricFilters() hook |
Guide |
| PeriodSelector | Date range presets, custom ranges, comparison toggle | Docs |
| DropdownFilter | Multi-select dimension filter with search, grouped options | Docs |
| SegmentToggle | Pill toggle with icons, badges, multi-select | Docs |
| FilterTags | Auto-renders active filters as dismissible chips | Docs |
Status & Alerts
| Component | What it does | Docs |
|---|---|---|
| Callout | Data-driven alerts with rules, {value} templates, embedded metrics |
Docs |
| StatusIndicator | Rule-based health with 5 sizes, pulse animation, trend arrows | Docs |
| Badge | 6 variants, 3 sizes, custom colors, icons, dismiss | Docs |
AI-First: MCP Server + llms.txt
Most component libraries give you docs and hope the AI figures it out. MetricUI gives the AI structured knowledge of every component, every prop, and every pattern — so it generates production-quality dashboards on the first try.
# One command. That's it.
claude mcp add --transport stdio metricui -- npx -y @metricui/mcp-server
The difference is real
Here's what happens when you prompt an AI with "Build me a SaaS dashboard with MRR, churn, users, and revenue breakdown":
<details> <summary><strong>Without MetricUI MCP</strong> — what the AI generates with Recharts / generic components</summary>
// The AI guesses at library APIs, builds everything from scratch
import { LineChart, Line, XAxis, YAxis, PieChart, Pie } from "recharts";
export default function Dashboard() {
return (
<div className="p-8">
<h1 className="text-2xl font-bold mb-6">SaaS Dashboard</h1>
<div className="grid grid-cols-4 gap-4 mb-8">
<div className="border rounded-lg p-4">
<p className="text-sm text-gray-500">MRR</p>
<p className="text-2xl font-bold">${(127450).toLocaleString()}</p>
<p className="text-sm text-green-600">+12.3%</p>
</div>
<div className="border rounded-lg p-4">
<p className="text-sm text-gray-500">Churn Rate</p>
<p className="text-2xl font-bold">3.2%</p>
<p className="text-sm text-green-600">-13.5%</p>
</div>
{/* ...more hand-built cards with no formatting engine, no sparklines,
no conditional coloring, no goal tracking... */}
</div>
<LineChart width={800} height={300} data={data}>
<XAxis dataKey="month" />
<YAxis />
<Line dataKey="revenue" stroke="#8884d8" />
{/* No reference lines. No threshold bands. No comparison overlay.
No dark mode. No loading states. No error boundaries. */}
</LineChart>
</div>
);
}
Raw div cards. Manual number formatting. No sparklines, no conditions, no goals, no filters, no dark mode, no data states, no error boundaries. Every dashboard looks the same.
</details>
<details open> <summary><strong>With MetricUI MCP</strong> — what the AI generates (real output, unedited)</summary>
import {
MetricProvider, FilterProvider, DashboardHeader, PeriodSelector,
MetricGrid, KpiCard, Callout, AreaChart, DonutChart, BarChart,
DataTable, Badge,
} from "metricui";
import "metricui/styles.css";
export default function Dashboard() {
return (
<MetricProvider theme="emerald">
<FilterProvider defaultPreset="30d">
<DashboardHeader
title="SaaS Metrics"
subtitle="Real-time metrics overview"
lastUpdated={new Date()}
actions={<PeriodSelector comparison />}
/>
<MetricGrid>
<MetricGrid.Section title="Key Metrics" />
<KpiCard title="Monthly Revenue" value={127450} format="currency"
comparison={{ value: 113500 }} comparisonLabel="vs last month"
sparkline={{ data: [89, 94, 99, 103, 109, 114, 127],
previousPeriod: [78, 82, 85, 88, 91, 95, 98], interactive: true }}
conditions={[
{ when: "above", value: 115000, color: "emerald" },
{ when: "below", value: 90000, color: "red" },
]} />
<KpiCard title="Churn Rate" value={3.2} format="percent"
comparison={{ value: 3.7, invertTrend: true }}
goal={{ value: 2.5, showTarget: true, showRemaining: true }}
conditions={[
{ when: "below", value: 2.5, color: "emerald" },
{ when: "above", value: 4, color: "red" },
]} />
<KpiCard title="Active Users" value={8420} format="number"
comparison={{ value: 7680 }} copyable
drillDown={{ label: "View breakdown", onClick: () => {} }} />
<KpiCard title="Conversion" value={4.8} format="percent"
comparison={{ value: 4.2 }}
sparkline={{ data: [3.1, 3.4, 3.8, 4.0, 4.1, 4.2, 4.8] }} />
<Callout value={12.3} rules={[
{ min: 15, variant: "success", title: "Exceptional Growth",
message: "Revenue grew {value}% — exceeding target by 50%." },
{ min: 5, max: 15, variant: "info", title: "Healthy Growth",
message: "Revenue grew {value}% month-over-month." },
{ max: 0, variant: "error", title: "Revenue Declined",
message: "Revenue dropped {value}%." },
]} action={{ label: "View growth report", onClick: () => {} }} />
<MetricGrid.Section title="Trends" subtitle="Last 30 days" border />
<AreaChart data={revenueData} comparisonData={comparisonData}
format="currency" title="Revenue Trend"
referenceLines={[{ axis: "y", value: 50000, label: "Target",
color: "#10B981", style: "dashed" }]}
thresholds={[{ from: 0, to: 40000, color: "#EF4444", opacity: 0.05 }]}
xAxisLabel="Month" yAxisLabel="Revenue ($)"
height={360} legend />
<DonutChart data={breakdownData} format="currency"
title="Revenue by Plan" centerValue="$99.4K" centerLabel="Total MRR" />
<MetricGrid.Item span="full">
<BarChart preset="grouped" data={channelData}
keys={["revenue", "conversions"]} indexBy="channel"
sort="desc" format="currency" title="Channel Performance" legend />
</MetricGrid.Item>
<MetricGrid.Section title="Details" border />
<DataTable data={tableData} title="Top Customers" searchable
columns={[
{ key: "name", header: "Customer", sortable: true },
{ key: "plan", header: "Plan",
render: (v) => <Badge variant={v === "Enterprise" ? "info" : "default"}>{String(v)}</Badge> },
{ key: "mrr", header: "MRR", format: "currency", sortable: true },
{ key: "status", header: "Status",
render: (v) => <Badge variant={v === "active" ? "success" : v === "at-risk" ? "warning" : "danger"}>{String(v)}</Badge> },
]} />
</MetricGrid>
</FilterProvider>
</MetricProvider>
);
}
</details>
Same prompt. The AI with MetricUI MCP generates:
- DashboardHeader with live status + auto-ticking "Updated Xm ago"
- FilterProvider + PeriodSelector with comparison toggle
- MetricGrid auto-layout (zero CSS)
- KpiCards with conditional coloring, goal progress bars, sparkline overlays, drill-down links
- AreaChart with dashed target reference line, danger zone threshold band, and previous-period comparison overlay
- Data-driven Callout that auto-picks severity from a growth number
- Sorted grouped BarChart, DonutChart with center KPI
- Searchable DataTable with Badge status columns
- Theme preset, dark mode, animations, error boundaries — all automatic
The AI doesn't guess. It knows. 13 tools, 26 components, every prop, every pattern. Full MCP Server docs →
llms.txt
Machine-readable documentation for AI models at /llms.txt. Every component, every prop, every type, every pattern — so even AI tools without MCP support can generate correct MetricUI code.
Roadmap
MetricUI is building toward 1.0 — cross-filtering, zero-config charts, anomaly detection, data stories, and a stable API you can build on with confidence. See what's shipped, what's next, and where we're headed:
Built With
- Nivo — chart rendering (line, bar, pie, heatmap)
- Tailwind CSS — styling (ships pre-built, Tailwind not required in your project)
- Lucide — icons
- React 18/19
License
MIT
<p align="center"> <strong>Built for developers who care about design.</strong> </p>
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.