@svgrid/mcp 3.0.17 → 3.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,19 +22,20 @@
22
22
 
23
23
  Point any MCP-capable client - Claude Desktop, Claude Code, Cursor, Zed - at this server and the model answers with **accurate, version-pinned** facts about SvGrid: real prop, method, and event names, plus every demo's source as grounding. No hallucinated APIs, no stale blog posts.
24
24
 
25
- **Why this beats pasting docs into the chat.** A model working from memory invents plausible SvGrid APIs, because it learned from a mix of other grids and older versions. Pasting docs helps for one question and then falls out of the context window. This server puts the current API surface and 370+ working demo sources one tool call away, for every question, pinned to the version you installed.
25
+ **Why this beats pasting docs into the chat.** A model working from memory invents plausible SvGrid APIs, because it learned from a mix of other grids and older versions. Pasting docs helps for one question and then falls out of the context window. This server puts the current API surface and every working demo source one tool call away, for every question, pinned to the version you installed.
26
26
 
27
27
  ## Tools exposed
28
28
 
29
- Four. `tools/list` is sent on **every** request, so the tool surface is pure
29
+ Five. `tools/list` is sent on **every** request, so the tool surface is pure
30
30
  overhead on every turn - this server used to spend ~4,710 tokens of it on 36
31
31
  tools, 79% of them Studio tools most sessions never call once.
32
32
 
33
33
  | Tool | Purpose |
34
34
  | --- | --- |
35
- | `svgrid_search` | Search the docs, all 400+ demos and the API surface **in one call**. No arguments returns an index. |
35
+ | `svgrid_search` | Search the docs, every demo and the API surface **in one call**. No arguments returns an index. |
36
36
  | `svgrid_get` | Read one thing in full: a doc slug, a demo id, or `api`. |
37
37
  | `svgrid_check_code` | **Verify** a file against the real API surface + the Svelte compiler. |
38
+ | `svgrid_preview` | Render a live, interactive grid in the conversation from columns + rows (MCP Apps). |
38
39
  | `svgrid_scaffold` | Studio: turn a Drizzle schema, sample rows or an `EntitySchema` into runnable SvelteKit files. |
39
40
 
40
41
  The docs and demos are also served as **MCP resources**
@@ -89,8 +90,8 @@ What it checks:
89
90
  too. The result says which of the two ran in its `compiler` field, so
90
91
  "no errors" is never mistaken for "this compiles".
91
92
 
92
- It is tuned to shut up when the code is right: it reports **nothing** across all
93
- 400+ demos in this repo, which is what a CI test asserts. A verifier that cries
93
+ It is tuned to shut up when the code is right: it reports **nothing** across
94
+ every demo in this repo, which is what a CI test asserts. A verifier that cries
94
95
  wolf is worse than none, because a model will happily "fix" working code.
95
96
 
96
97
  ### Studio: drive the app model (agent co-designer)
@@ -122,8 +123,8 @@ failure reports which op failed and what already applied.
122
123
  | --- | --- | --- |
123
124
  | Install | `npx @svgrid/mcp` | `https://mcp.svgrid.com/mcp` |
124
125
  | Needs Node | yes | no |
125
- | `check_svgrid_code` compiles | yes | static checks only |
126
- | Studio `studio_*` tools | yes (27) | no |
126
+ | `svgrid_check_code` compiles | yes | static checks only |
127
+ | Studio `studio_*` tools | yes (opt-in) | no |
127
128
  | Works offline | yes | no |
128
129
 
129
130
  ```bash
@@ -136,8 +137,8 @@ claude mcp add --transport http svgrid https://mcp.svgrid.com/mcp
136
137
  <a href="https://insiders.vscode.dev/redirect/mcp/install?name=svgrid&config=%7B%22name%22%3A%22svgrid%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.svgrid.com%2Fmcp%22%7D"><img src="https://img.shields.io/badge/Add%20to-VS%20Code-0098FF?logo=visualstudiocode&logoColor=white" alt="Add to VS Code" /></a>
137
138
  </p>
138
139
 
139
- The remote server is live at **https://mcp.svgrid.com/mcp** and carries the six
140
- docs + verification tools ([source](../../workers/svgrid-mcp)). Use stdio when
140
+ The remote server is live at **https://mcp.svgrid.com/mcp** and carries the docs,
141
+ verification and preview tools ([source](../../workers/svgrid-mcp)). Use stdio when
141
142
  you want the compiler pass, the Studio tools, or no third-party endpoint in the
142
143
  loop.
143
144
 
@@ -206,6 +207,17 @@ node dist/index.js
206
207
  `examples/src/demos/*.svelte` and `docs/**/*.md` from the workspace and inlines
207
208
  them into `src/data.ts`, so the published package is fully self-contained.
208
209
 
210
+ ## Enterprise features
211
+
212
+ Export to Excel and PDF, pivot tables, the Kanban board, the scheduler, the
213
+ spreadsheet and the server-side row model live in `@svgrid/enterprise`, which
214
+ is commercial. Answers say so: a paid doc or demo in `svgrid_search` results
215
+ carries `"enterprise": true`, a question about a paid feature gets one line
216
+ with the trial link, and `svgrid_check_code` adds it when the fix is to install
217
+ the package. The package runs without a license key and shows a watermark
218
+ until one is set. The [30-day trial](https://svgrid.com/pricing/?trial=mcp-docs)
219
+ adds a download of every demo and 30 days of email support.
220
+
209
221
  ## Licensing
210
222
 
211
223
  MIT - free to run, no license key. Some tools generate SvGrid Studio projects, and Studio itself is
@@ -15,7 +15,8 @@
15
15
  */
16
16
  import { apiReference, apiSurface, docs, examples, schemas } from './data.js';
17
17
  import { meaningfulTerms, rankDocs } from './search.js';
18
- const DOCS_FOOTER = '\n\nSvGrid reference: full docs & 375 live demos at https://svgrid.com/docs';
18
+ import { ENTERPRISE_LINE, ENTERPRISE_NOTE, importsEnterprise, isEnterpriseDoc, isPaidQuestion } from './enterprise.js';
19
+ const DOCS_FOOTER = `\n\nSvGrid reference: full docs & ${examples.length} live demos at https://svgrid.com/docs`;
19
20
  const text = (body) => ({ content: [{ type: 'text', text: body }] });
20
21
  const withDocs = (body) => text(body + DOCS_FOOTER);
21
22
  const fail = (message) => ({
@@ -59,8 +60,20 @@ const apiNames = (() => {
59
60
  add(c.name, 'column option');
60
61
  for (const m of apiSurface.apiMethods)
61
62
  add(m, 'grid api method');
62
- return [...merged].map(([name, groups]) => ({ name, group: [...groups].join(', ') }));
63
+ // The methods installEnterprise(api) adds are searchable too, so "export"
64
+ // finds exportData and says where it comes from. Not every enterprise
65
+ // export: over a thousand names drowned the free API on ordinary queries
66
+ // (tools/mcp-tools.test.ts, "filler words"); the docs and demos cover them.
67
+ for (const m of apiSurface.enterpriseApiMethods)
68
+ add(m, 'enterprise api method (installEnterprise)');
69
+ return [...merged].map(([name, groups]) => {
70
+ const group = [...groups].join(', ');
71
+ return { name, group, ...(group.includes('enterprise') ? { enterprise: true } : {}) };
72
+ });
63
73
  })();
74
+ /** Docs and demos that use the paid package, found once from their source. */
75
+ const enterpriseDocs = new Set(docs.filter((d) => isEnterpriseDoc(d.slug, d.markdown)).map((d) => d.slug));
76
+ const enterpriseExamples = new Set(examples.filter((e) => importsEnterprise(e.source)).map((e) => e.id));
64
77
  export const CORE_TOOLS = [
65
78
  {
66
79
  name: 'svgrid_search',
@@ -240,7 +253,10 @@ function search(args) {
240
253
  body.docs = {
241
254
  total: ranked.total,
242
255
  partial: partial || undefined,
243
- hits: shown.map((h) => detail === 'full' ? h : { ...h, excerpt: trimBlurb(String(h.excerpt ?? ''), 200) }),
256
+ hits: shown.map((h) => {
257
+ const hit = detail === 'full' ? h : { ...h, excerpt: trimBlurb(String(h.excerpt ?? ''), 200) };
258
+ return enterpriseDocs.has(String(h.slug)) ? { ...hit, enterprise: true } : hit;
259
+ }),
244
260
  };
245
261
  if (partial) {
246
262
  body.hint = `No page matched all of "${query}". These matched some of it - treat them as leads, not answers.`;
@@ -258,6 +274,7 @@ function search(args) {
258
274
  title: e.title,
259
275
  category: e.category,
260
276
  blurb: detail === 'full' ? e.blurb : trimBlurb(e.blurb),
277
+ ...(enterpriseExamples.has(e.id) ? { enterprise: true } : {}),
261
278
  })),
262
279
  };
263
280
  }
@@ -268,6 +285,10 @@ function search(args) {
268
285
  const empty = !body.docs?.total &&
269
286
  !body.examples?.total &&
270
287
  !body.api?.total;
288
+ // Once per answer, and only when the question is about a paid feature.
289
+ const lists = [body.docs, body.examples, body.api].map((c) => c?.hits ?? []);
290
+ if (isPaidQuestion(lists))
291
+ body.enterprise = ENTERPRISE_NOTE;
271
292
  if (!empty) {
272
293
  // A partial-match warning outranks the generic next-step hint: it is the
273
294
  // one thing the caller must not miss, and it is set above.
@@ -352,15 +373,19 @@ function get(args) {
352
373
  }
353
374
  if (kind === 'doc' || kind === 'auto') {
354
375
  const doc = docs.find((d) => d.slug === ref);
355
- if (doc)
356
- return withDocs(clip(doc.markdown));
376
+ if (doc) {
377
+ // On top, where truncation cannot cut it off.
378
+ const paid = enterpriseDocs.has(doc.slug) ? `> ${ENTERPRISE_LINE}\n\n` : '';
379
+ return withDocs(clip(paid + doc.markdown));
380
+ }
357
381
  if (kind === 'doc') {
358
382
  return fail(`No doc with slug "${ref}". Use svgrid_search to find one.`);
359
383
  }
360
384
  }
361
385
  const example = examples.find((e) => e.id === ref);
362
386
  if (example) {
363
- return text(clip(`// ${example.path}\n// ${example.title} - ${example.blurb}\n\n${example.source}`));
387
+ const paid = enterpriseExamples.has(example.id) ? `// ${ENTERPRISE_LINE}\n` : '';
388
+ return text(clip(`// ${example.path}\n// ${example.title} - ${example.blurb}\n${paid}\n${example.source}`));
364
389
  }
365
390
  // A miss is a chance to point somewhere useful rather than just say no.
366
391
  const near = [