Ask a coding model to wire up a Svelte 5 data grid and you usually get code that looks right and does not run. The prop names drift in from a React grid, the reactivity is Svelte 4 stores, and the version it learned from shipped a year and a half ago. You paste the error back, it apologises, it invents a slightly different API.
That failure mode is the thing SvGrid is built around. It is a Svelte 5 native data grid: a headless core plus a <SvGrid> renderer, virtualization, grouping, editing, server-side data, keyboard and screen-reader support. The core package @svgrid/grid is MIT.
The part worth writing about is what sits on top of that. AI shows up twice in this product: once at build time, so your editor writes correct grid code, and once at runtime, so your users can talk to their data. Here are the five pieces that matter.
1. An MCP server, so the model reads the API instead of remembering it
Model Context Protocol is the open standard for exposing tools to LLM clients. SvGrid ships one: @svgrid/mcp, MIT licensed, listed in the official MCP registry as com.svgrid/svgrid.
One command in Claude Code:
claude mcp add svgrid -- npx -y @svgrid/mcp
Or the same server in Cursor, Zed, Claude Desktop, or anything else that speaks MCP over stdio:
{
"mcpServers": {
"svgrid": { "command": "npx", "args": ["-y", "@svgrid/mcp"] }
}
}
Eight of the tools cover docs and examples:
| Tool | What it returns |
|---|---|
list_examples |
Every demo: id, title, one-line blurb |
get_example_source |
The full .svelte source of one demo, verbatim |
list_docs / get_doc
|
Doc slugs, then the markdown of a page |
search_docs |
Substring search across the docs with excerpts |
get_api_reference |
The curated public API surface, grouped by category |
introspect_source |
A draft entity schema from a Drizzle file or sample rows |
scaffold_entity |
Runnable SvelteKit files for one entity |
Two details do most of the work here. First, the corpus is inlined into the package at build time, so answers are pinned to the version you installed rather than to whatever the model absorbed during training. Second, get_example_source returns real working files, all 360+ of them, so "build me a grid that groups by department and shows a sparkline per row" starts from code that already compiles.
It runs locally over stdio. No API key, no telemetry, no outbound call. stdout is JSON-RPC, logs go to stderr.
If you do not want to run a server, the same grounding ships as static files you can paste into a custom GPT, a Claude project, or your own agent's system prompt:
const topicMap = await fetch('https://svgrid.com/llms.txt').then((r) => r.text())
const schemas = await fetch('https://svgrid.com/schemas/index.json').then((r) => r.json())
llms.txt is the ~10 kB topic map, llms-full.txt is every doc page concatenated, and schemas/index.json gives you JSON Schema for ColumnDef and the <SvGrid> props so a generated config can be machine-validated before you ever run it.
2. Natural-language filtering that cannot invent a column
Now the runtime side. The AI helpers live in @svgrid/grid itself, MIT, no license key and no separate package.
import { aiFilter } from '@svgrid/grid'
const plan = await aiFilter(api, 'accounts losing momentum in EMEA, by NPS')
// {
// filters: [
// { field: 'region', operator: 'equals', value: 'EMEA' },
// { field: 'nps', operator: 'lessThan', value: '30' },
// ],
// sort: [{ field: 'nps', desc: false }],
// rationale: 'EMEA region, low NPS, sorted ascending.',
// }
Three things keep this from becoming a party trick:
- The prompt is grounded in your columns. Before the call, the grid embeds the live column schema (names, types, sampled values) so the model picks real field names.
-
A hallucination guard on the way back. If the model still returns a column that does not exist, that clause is dropped rather than handed to
setFilter, which would throw. You would rather lose a clause than crash the page. -
It returns a plan and does not apply it. That gives you the "here is what I would do, accept?" preview for free. Pass
{ apply: true }when you want it committed directly.
For an analyst-facing table this replaces a dozen per-column filter operators with one text box.
3. Smart fill, and paste from wherever the data actually came from
Smart fill is the spreadsheet feature. The user types one or two worked examples in a column, and the model proposes the rest:
const result = await aiSmartFill(api, {
field: 'tier',
examples: [
{ input: { company: 'Northwind' }, output: 'enterprise' },
{ input: { company: 'Helios' }, output: 'growth' },
],
})
// result.predictions: [{ rowIndex, value, confidence }, ...]
You decide what happens next: accept all, accept per cell, or write the prediction to a shadow field and render a confidence pill in the cell.
Smart paste is the one that RevOps users react to. Drop in CSV, TSV, JSON, a vCard, a Markdown table copied out of Slack, an email signature block, or a paragraph of prose, and the parser detects the format and maps it to typed rows. Every parsed row then goes through three normalization passes before the preview renders: email typo correction (gmial.com), phone rewriting to a consistent +CC AAA BBB CCCC shape, and name cleaning that strips Dr. / Jr. and rewrites "Last, First". Duplicate emails collapse into one row with missing fields merged in.
4. One adapter, no bundled model
Every AI call in the grid routes through a single async function you register once at boot:
import { setAIProvider, type AIProvider } from '@svgrid/grid'
const provider: AIProvider = async ({ prompt, responseFormat, signal, task }) => {
const r = await fetch('/api/ai', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ prompt, responseFormat, task }),
signal,
})
if (!r.ok) throw new Error(`AI provider returned ${r.status}`)
return r.text()
}
setAIProvider(provider)
The grid ships no model client at all. Model choice, routing, key handling, and what leaves the browser stay yours. signal is forwarded so you can cancel in flight, and task is tagged ('filter' | 'smart-fill' | 'summarize' | 'classify') so you can route cheap tasks to a small model and summaries to a stronger one.
That one provider powers the whole set:
aiFilter(api, query, opts?) // NL query -> filter + sort plan
aiSmartFill(api, opts) // examples -> proposed column values
aiSummarize(api, opts) // row / selection / group / all -> text + bullets
aiClassify(api, opts) // free-text cells -> bucketed labels
aiExport(api, query, opts?) // NL query -> filter + group + format, then export
aiFindAnomalies(api, opts?) // scan a slice for outliers and bad values
enableAiCharting(api) // adds an AI button to the chart panel
With enableAiCharting, "revenue by country, stacked by product" becomes a chart config (type, group-by, split-by, measure, aggregate) applied live.
Helpers request responseFormat: 'json' and the grid parses the reply, stripping a single markdown fence first so models that wrap output in a code block still parse. Malformed output gives you a typed error rather than a silent wrong answer.
Nothing is imported until you import it, so if you do not want natural language anywhere, these tree-shake away and cost nothing. A bundled mockAIProvider returns deterministic canned shapes per task, which is how every AI demo on the site runs with no key.
5. The grid is a tool surface
The imperative SvGridApi maps cleanly onto function calling, so an agent can drive the UI rather than just describe it. Each method becomes one tool:
const tools = [
{ type: 'function', function: { name: 'setFilter', /* columnId, operator, value */ } },
{ type: 'function', function: { name: 'setSort', /* columnId, direction */ } },
{ type: 'function', function: { name: 'setGroupBy', /* columnIds */ } },
{ type: 'function', function: { name: 'clearAllFilters', parameters: { type: 'object' } } },
]
Point getDisplayedRows() at a read-only summariser and the model sees exactly what the user sees, filters and sorting and grouping already applied, instead of the raw dataset.
The same idea runs one level up. Alongside the docs tools, the MCP server exposes 27 studio_* tools that drive the same validated project model the visual designer uses: add entities, screens, blocks and components, bind a data source, set auth, RBAC, theme, the typed data layer, and the deploy target, then emit a full runnable SvelteKit app. Every edit goes through the model's own functions and validateProject, so an agent that guesses wrong gets a validation error instead of a broken app. Those generators are part of the commercial Studio tier; the docs and example tools are free.
Worth a look if
You are building tables in Svelte 5 and you are tired of correcting your assistant's grid code, or you want natural-language filtering in an app without shipping a model client and a vendor lock-in with it.
npm create @svgrid@latest
claude mcp add svgrid -- npx -y @svgrid/mcp

Top comments (2)
The integration of the Model Context Protocol (MCP) with SvGrid is a clever approach to ensure that the AI models interact with up-to-date APIs, which can significantly reduce errors stemming from version mismatches. By inlining the corpus at build time, you not only maintain consistency but also enhance the development experience for users. I'm especially intrigued by the potential of the natural-language filtering capability; it seems like a powerful way to bridge the gap between user intent and data querying. If you're considering expanding the features or improving the AI interactions, I’d love to explore a paid collaboration to help enhance this aspect further! What other functionalities are you envisioning for the AI helpers in the future?
We will extend it in this direction: AI building a full SvelteKit app with Svelte Data Grid - SvGrid and the other Svelte UI Components part of it. See: https://svgrid.com/studio/