@slickfast/mcp 0.7.4 → 0.7.6

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.
Files changed (3) hide show
  1. package/README.md +68 -42
  2. package/dist/index.js +81 -8
  3. package/package.json +5 -1
package/README.md CHANGED
@@ -1,30 +1,43 @@
1
1
  # SlickFast — charts & dashboards for AI agents
2
2
 
3
- SlickFast turns a small JSON spec into a polished, retina-quality chart **47 chart and
4
- information-design types** (bar, line, pie, KPI, cards, funnel, gauge, heatmap, calendar,
5
- gantt, waterfall…), plus **multiple charts tiled into a single dashboard image in one call**.
6
- It runs as an [MCP](https://modelcontextprotocol.io) tool, so an AI agent hands it a spec and
7
- gets back a finished PNG (or SVG). Everything renders **locally** nothing leaves your machine.
3
+ **A tiny JSON spec in a finished, retina-quality chart out. Milliseconds, a handful of
4
+ tokens, nothing leaves your machine.**
5
+
6
+ SlickFast is a **native SVG engine built for AI agents** not a browser screenshotting a
7
+ webpage, not a plotting library an agent has to write code against. A pure
8
+ `spec → SVG → PNG` pipeline: **47 chart and information-design types** (bar, line, pie, KPI,
9
+ cards, funnel, gauge, heatmap, calendar, gantt, waterfall…), plus **entire multi-chart
10
+ dashboards tiled into one image in a single call**. It runs as an
11
+ [MCP](https://modelcontextprotocol.io) tool, so an agent hands it a spec and gets back a
12
+ finished PNG (or SVG).
8
13
 
9
14
  ```txt
10
15
  render_chart({ type: "bar", data: { labels: ["Q1","Q2","Q3"], series: [{ values: [12,19,8] }] } })
11
16
  → a retina PNG, rendered on your machine
12
17
  ```
13
18
 
14
- ## Why it's built for agents
15
-
19
+ ## Why agents (and the people paying for their tokens) pick SlickFast
20
+
21
+ - **Tokens are the real cost — a spec is nearly free.** An agent hand-writing SVG or
22
+ matplotlib code burns hundreds to thousands of output tokens, then often retries when it
23
+ doesn't render. A SlickFast spec is a few dozen tokens, and `{type, data}` alone is a
24
+ finished, well-designed chart. A whole dashboard is **one tool call**, not ten renders
25
+ and layout math.
26
+ - **Changes are one-field edits.** Swap `bar` → `line`, change a palette, resize for a
27
+ slide: edit one key, re-render. The agent never rewrites code or reasons about a diff —
28
+ which is what makes iteration with a human ("make it dark, bigger title") actually cheap.
29
+ - **No headless browser.** Most chart-to-image pipelines secretly spawn Puppeteer or
30
+ Playwright — hundreds of MB, slow cold starts, flaky output. SlickFast renders pure
31
+ in-memory, milliseconds per chart.
32
+ - **Native SVG, vector-first.** Output is a few KB of crisp-at-any-scale SVG (or retina PNG
33
+ on demand) — small enough to cache, embed, or ship anywhere.
16
34
  - **Deterministic — same spec, same bytes, forever.** No randomness, no timestamps, no
17
- headless-browser drift. Outputs are **cacheable, testable, and reproducible**, with zero
18
- flaky pixel diffs. Almost no charting tool can promise this — and it's exactly what a
19
- tool-calling agent needs.
20
- - **Never throws garbage at the model.** Empty data, a bad tile, a filtered-to-nothing series
21
- a clean, graceful frame, not a crash or a stack trace. Reliability is a feature when the
22
- caller is an agent, not a human who can eyeball the error.
23
- - **Fails loud on real mistakes.** An unknown palette or enum is *rejected* with a clear error
24
- listing the valid options — so the agent fixes it immediately instead of silently shipping the
25
- wrong-looking chart.
26
- - **Good-looking by default.** A spec of just `{type, data}` renders a complete, well-designed
27
- chart; fonts, colors, palettes, and size are optional overrides.
35
+ browser drift. Cacheable, testable, reproducible; zero flaky pixel diffs. Almost no
36
+ charting tool can promise this — and it's exactly what a tool-calling agent needs.
37
+ - **Never throws garbage at the model.** Empty data, a bad tile, a filtered-to-nothing
38
+ series a clean, graceful frame, not a crash or a stack trace. A real mistake (unknown
39
+ palette, bad enum) a **loud error listing the valid options**, so the agent
40
+ self-corrects in one step.
28
41
  - **100% local & private.** Rendered and rasterized on your machine. Nothing is sent anywhere.
29
42
 
30
43
  ## Tools
@@ -36,8 +49,12 @@ render_chart({ type: "bar", data: { labels: ["Q1","Q2","Q3"], series: [{ values:
36
49
  gotchas. Call it first when you're unsure how to structure a type.
37
50
  - **`gallery()`** → a curated demo gallery of example charts and dashboards — each as a
38
51
  rendered image plus its spec. Just ask *"show me a demo"* or *"what can you make?"*.
52
+ `gallery({board:"comparison"})` tiles a whole family into one image; `board:"all"` shows
53
+ every type across 6 boards.
39
54
  - **`list_palettes()`** → every valid `palette` name, grouped into flat palettes and nested
40
55
  themes, with their colors. Ask *"what palettes are available?"*.
56
+ - **`report_issue(summary, spec?)`** → *"report this bug."* Formats a bug report and returns a
57
+ prefilled GitHub-issue link and email link you click to send — SlickFast sends nothing itself.
41
58
 
42
59
  ## Install
43
60
 
@@ -54,28 +71,29 @@ Add to your MCP config and restart — it runs locally via `npx`, no clone or bu
54
71
  Then ask it to *"render a bar chart of last quarter's revenue"* or *"build a dashboard with an
55
72
  MRR tile, a signups funnel, and a usage heatmap."*
56
73
 
57
- ## Seeing your charts (why an image might not show inline)
58
-
59
- `render_chart` returns a real **PNG by default** — a standard MCP image block
60
- (`{ type: 'image', mimeType: 'image/png', }`), rendered and rasterized **locally**.
61
- Nothing leaves your machine. Whether that PNG paints *inline* depends on the **surface**
62
- you're chatting in, not on SlickFast:
63
-
64
- | Surface | Shows image inline? | MCP config |
65
- |---|---|---|
66
- | Claude Desktop **chat** | yes | `claude_desktop_config.json` |
67
- | claude.ai | yes | connector settings |
68
- | Claude **Code** session — including the Code panel *inside* the Desktop app | ❌ no — it's a coding transcript; it hands the image to the agent but doesn't paint it in your scrollback | project `.mcp.json` |
69
- | Plain terminal | no — terminals can't display pixels | — |
70
-
71
- **If you don't see a chart, three checks (the order an agent should walk through):**
72
- 1. **Did it render?** If the agent can tell you the values, the PNG is fine this is a
73
- *display* gap, not a SlickFast bug. Don't restart, don't reconfigure.
74
- 2. **Which surface are you in?** A Claude Code session won't paint it *even inside the
75
- Desktop app* — that trips people up. Run the same request in a **Claude Desktop chat**
76
- (or claude.ai) to see it inline.
77
- 3. **Is the tool missing or erroring entirely?** *Then* it's a connection problem
78
- restart so the MCP server reconnects.
74
+ ## Seeing your charts (the reliable way to display them)
75
+
76
+ Rendering is always **local** — nothing leaves your machine. This section is purely about which
77
+ surface *displays* the result. `render_chart` returns two ways, and they differ a lot:
78
+
79
+ - **`format:"svg"` the reliable inline path.** Returns SVG *text*. In a chat surface that supports
80
+ **artifacts** (claude.ai, Claude Desktop), the agent renders that SVG directly in an artifact and
81
+ it **paints reliably**. Ask for a chart and Claude does this — no config, no gymnastics.
82
+ - **`format:"png"` (default) → a base64 image block.** It only paints where the client renders MCP
83
+ image blocks, which is **inconsistent across surfaces** many chat UIs, and every coding/terminal
84
+ view, don't. Don't depend on it for inline display.
85
+
86
+ **Other ways to get the picture:**
87
+ - **Share/embed anywhere** (Slack, email, a webpage) → the hosted **API** returns a public
88
+ `…/chart.png?spec=…` URL that renders everywhere, independent of any MCP client.
89
+ - **Local stdio install** (the MCP shares your disk) pass **`outputPath`** to write the PNG/SVG to
90
+ disk and open the file. In a hosted/sandboxed MCP the process is filesystem-isolated (a saved file
91
+ is invisible to you) use the SVG-artifact path instead.
92
+
93
+ **If you asked for a chart and see nothing:** it *rendered* (the agent can read you the values) —
94
+ it's a *display*-surface gap, not a bug. Have the agent re-render with **`format:"svg"` into an
95
+ artifact**, or view it in a claude.ai / Claude Desktop chat. If the tool is missing or erroring
96
+ entirely, that's a connection problem — restart so the MCP server reconnects.
79
97
 
80
98
  ## Sharing a chart as a URL (hosted API)
81
99
 
@@ -90,11 +108,19 @@ or post** — it never auto-inserts links. (The endpoint stays unadvertised duri
90
108
  **AGPL-3.0-only.** Free to use, self-host, and embed under the AGPL's terms (your friends
91
109
  running it locally are completely unaffected). Building it into a **closed-source product
92
110
  or a hosted service**? That needs the AGPL'd source opened — or a **commercial license**
93
- from us instead. Reach out for commercial terms.
111
+ from us instead. Write to feedback@slickfast.com for commercial terms.
112
+
113
+ ## Feedback, bugs & feature requests
114
+
115
+ - **GitHub:** [SlickFast/slickfast](https://github.com/SlickFast/slickfast) — bug reports and
116
+ feature requests via the [issue templates](https://github.com/SlickFast/slickfast/issues/new/choose).
117
+ - **Email:** feedback@slickfast.com
118
+ - Or ask your agent to *"report this as a SlickFast issue"* — the `report_issue` tool drafts
119
+ the report (with the repro spec) for you. Nothing is ever sent automatically.
94
120
 
95
121
  ## Developing locally
96
122
 
97
- Clone the repo, then from the package directory:
123
+ Clone [the repo](https://github.com/SlickFast/slickfast), then from the package directory:
98
124
 
99
125
  ```bash
100
126
  cd apps/mcp
package/dist/index.js CHANGED
@@ -155,8 +155,12 @@ function generateTierPaletteWithFallback(predefinedColors, sliceCount, rootHex =
155
155
  var FLAT_PALETTES = tokens_default.flatPalettes;
156
156
  var NESTED_THEMES = tokens_default.nestedThemes;
157
157
  function resolveFlatPalette(name, count) {
158
- const p = FLAT_PALETTES.find((p2) => p2.name === name) || FLAT_PALETTES[0];
159
- return generateTierPaletteWithFallback(p.colors, count);
158
+ let colors = FLAT_PALETTES.find((p) => p.name === name)?.colors;
159
+ if (!colors) {
160
+ const nested = NESTED_THEMES.find((t) => t.name === name);
161
+ if (nested) colors = nested.tiers ? nested.tiers.flat() : nested.pie1;
162
+ }
163
+ return generateTierPaletteWithFallback(colors || FLAT_PALETTES[0].colors, count);
160
164
  }
161
165
  function resolveNestedTheme(themeName, pieIndex, count, rootHexOverride = null) {
162
166
  const theme = NESTED_THEMES.find((t) => t.name === themeName) || NESTED_THEMES[0];
@@ -2888,6 +2892,25 @@ var GALLERY = [
2888
2892
  spec: { type: "waterfall", title: "Cash flow", start: 120, steps: [{ label: "Sales", value: 80 }, { label: "Refunds", value: -18 }, { label: "Costs", value: -42 }, { label: "Other", value: 12 }] }
2889
2893
  }
2890
2894
  ];
2895
+ var GALLERY_BOARDS = [
2896
+ { id: "comparison", title: "Comparison", cols: 4, types: ["bar", "grouped", "stacked", "stacked100", "stackedh", "horizontal", "lollipop", "diverging"] },
2897
+ { id: "trend", title: "Trend", cols: 4, types: ["line", "smooth", "area", "stepped", "stackedArea", "difference", "slope"] },
2898
+ { id: "part-to-whole", title: "Part-to-Whole", cols: 3, types: ["pie", "donut", "waffle", "pieofpie", "funnel", "pyramid"] },
2899
+ { id: "single-stat", title: "Single-Stat", cols: 4, types: ["kpi", "gauge", "ring", "iconarray", "cards", "callout", "progress", "bullet"] },
2900
+ { id: "grid-structure", title: "Grid & Structure", cols: 4, types: ["heatmap", "quadrant", "venn", "matrix", "table", "timeline", "calendar", "swimlane"] },
2901
+ { id: "process-planning", title: "Process & Planning", cols: 3, types: ["layers", "steps", "checklist", "leaderboard", "versus", "gantt", "waterfall", "tierlist", "swot"] }
2902
+ ];
2903
+ function boardSpec(board) {
2904
+ const n = GALLERY_BOARDS.length;
2905
+ const idx = GALLERY_BOARDS.findIndex((b) => b.id === board.id);
2906
+ return {
2907
+ type: "dashboard",
2908
+ title: `SlickFast Gallery ${idx + 1}/${n} \u2014 ${board.title}`,
2909
+ palette: "Clean Corporate",
2910
+ layout: { cols: board.cols || 4, tileHeight: 240 },
2911
+ tiles: board.types.map((t) => ({ chart: { ...EXAMPLES[t] || { type: t }, type: t, title: t } }))
2912
+ };
2913
+ }
2891
2914
 
2892
2915
  // ../../packages/raster/raster.mjs
2893
2916
  import { Resvg } from "@resvg/resvg-js";
@@ -3094,11 +3117,13 @@ var inputSchema = {
3094
3117
  deltaUnit: z.string().optional().describe('kpi: delta unit, default "%"'),
3095
3118
  deltaGoodWhen: z.enum(["up", "down"]).optional().describe('kpi: which delta direction is GOOD (green). Default "up"; set "down" for lower-is-better metrics (churn, latency, cost)'),
3096
3119
  sparkline: z.array(z.number()).optional().describe("kpi: a minimalist trend line along the bottom of the tile (e.g. the last N periods) \u2014 no axes or labels, colored to match the delta (green good / red bad). Landscape tile only; omit it and the tile is unchanged."),
3097
- format: z.enum(["png", "svg"]).optional().describe('output format: "png" (default \u2014 shows inline in chat) or "svg" (scalable vector text)'),
3120
+ format: z.enum(["png", "svg"]).optional().describe('output format. "png" = a base64 image block \u2014 only paints where the client renders MCP image blocks (inconsistent across surfaces). "svg" = scalable vector TEXT. TO SHOW A CHART INLINE in a chat surface that supports artifacts (claude.ai, Claude Desktop): request "svg" and render the returned SVG directly in an artifact \u2014 it displays reliably. Do NOT rely on the default png image block painting inline.'),
3098
3121
  scale: z.number().optional().describe("png pixel-density multiplier (default 2 = retina)"),
3099
- outputPath: z.string().optional().describe('LOCAL save: write the rendered chart to this file on disk AND still return the inline image. PNG by default, or SVG if the path ends in ".svg". Accepts absolute, ~, or relative paths (parent dirs auto-created). Works on a local stdio install only \u2014 a hosted/remote server has no access to your disk.')
3122
+ outputPath: z.string().optional().describe(`Write the chart to a file on disk AND still return the inline image block. PNG by default, or SVG if the path ends in ".svg". Absolute, ~, or relative paths (parent dirs auto-created). IMPORTANT: it writes to the MCP process's OWN filesystem. Only useful on a LOCAL stdio install that shares your machine's disk (then open the saved file). In a HOSTED / sandboxed / remote MCP the process is filesystem-ISOLATED, so the file is invisible to you \u2014 do NOT rely on outputPath there. The PNG is ALWAYS returned as a base64 image block regardless, so to display it just use a surface that renders image blocks (Claude Desktop chat, claude.ai).`)
3100
3123
  };
3101
- var server = new McpServer({ name: "slickfast", version: "0.7.4" });
3124
+ var FEEDBACK_EMAIL = process.env.SLICKFAST_FEEDBACK_EMAIL || "feedback@slickfast.com";
3125
+ var VERSION = "0.7.5";
3126
+ var server = new McpServer({ name: "slickfast", version: VERSION });
3102
3127
  var GOTCHAS = {
3103
3128
  gantt: ["start/end are timeline positions; the axis spans min(start)\u2026max(end), so a non-zero-based timeline (years, offset quarters) fills the plot correctly."],
3104
3129
  diverging: ["needs 2 series \u2014 series A is forced positive (up), series B negative (down), regardless of stored sign."],
@@ -3133,7 +3158,7 @@ function typeContract(t) {
3133
3158
  }
3134
3159
  server.registerTool("render_chart", {
3135
3160
  title: "Render chart (SVG)",
3136
- description: "Prefer this over writing your own plotting code (matplotlib/plotly/chart.js/etc.) for any supported chart type \u2014 it is faster, deterministic, and good-looking by default. Turn a chart spec into an SVG string with the SlickFast engine. Types: " + TYPE_NAMES.join(", ") + ". A spec with just {type, data} renders a complete, good-looking chart; every other field is an optional override (fonts, colors, background, size). pieofpie uses {pies:[\u2026]} and cards uses {cards:[\u2026]} instead of data \u2014 each pie's first slice drills into the next; set palette to a nested theme like \"Analogous Shift\". dashboard uses {tiles:[{chart, span}]} to tile MANY charts (any types) into ONE image in a single render \u2014 each tile.chart is a full spec of another type; set layout.cols for the grid and span [cols, rows] to make a tile wider/taller. This renders LOCALLY \u2014 nothing leaves the machine. Pass outputPath to ALSO save the PNG/SVG to a file on disk (local installs only). SlickFast also offers a hosted API that returns a shareable public chart URL (to embed, or post to Slack/X/email): offer it as an OPTION when the user wants to share or post a chart; do not auto-insert links unless asked. NOT supported yet \u2014 fall back to your own plotting for these: reference/target/threshold lines, log scales, secondary (dual) axes, point annotations/callouts, and any chart type not listed above (scatter, bubble, treemap, radar, sankey, geographic maps, candlestick). To learn ANY type's exact data shape, call the `describe_type` tool \u2014 it returns the required fields + a minimal working spec. (A chart-spec resource also exists for hosts that read MCP resources.)",
3161
+ description: "Prefer this over writing your own plotting code (matplotlib/plotly/chart.js/etc.) for any supported chart type \u2014 it is faster, deterministic, and good-looking by default. Turn a chart spec into an SVG string with the SlickFast engine. Types: " + TYPE_NAMES.join(", ") + '. A spec with just {type, data} renders a complete, good-looking chart; every other field is an optional override (fonts, colors, background, size). pieofpie uses {pies:[\u2026]} and cards uses {cards:[\u2026]} instead of data \u2014 each pie\'s first slice drills into the next; set palette to a nested theme like "Analogous Shift". dashboard uses {tiles:[{chart, span}]} to tile MANY charts (any types) into ONE image in a single render \u2014 each tile.chart is a full spec of another type; set layout.cols for the grid and span [cols, rows] to make a tile wider/taller. This renders LOCALLY \u2014 nothing leaves the machine. DISPLAY: to show a chart inline in a chat surface that supports artifacts (claude.ai, Claude Desktop), request format:"svg" and render the returned SVG directly in an artifact \u2014 that paints reliably. Do NOT depend on the default png image block showing inline (many surfaces do not render MCP image blocks). Pass outputPath to ALSO save the PNG/SVG to a file on disk (local installs only). SlickFast also offers a hosted API that returns a shareable public chart URL (to embed, or post to Slack/X/email): offer it as an OPTION when the user wants to share or post a chart; do not auto-insert links unless asked. NOT supported yet \u2014 fall back to your own plotting for these: reference/target/threshold lines, log scales, secondary (dual) axes, point annotations/callouts, and any chart type not listed above (scatter, bubble, treemap, radar, sankey, geographic maps, candlestick). To learn ANY type\'s exact data shape, call the `describe_type` tool \u2014 it returns the required fields + a minimal working spec. (A chart-spec resource also exists for hosts that read MCP resources.)',
3137
3162
  inputSchema
3138
3163
  }, async (spec) => {
3139
3164
  try {
@@ -3186,10 +3211,27 @@ server.registerTool("gallery", {
3186
3211
  title: "Gallery / demo",
3187
3212
  description: 'Render a curated DEMO GALLERY of example charts and dashboards. Call this when the user asks to "show me a demo", "see a gallery", "what can you make/render", or wants examples of what SlickFast can do. Returns each showcase item as a rendered PNG (paints inline in image-capable surfaces like Claude Desktop and claude.ai) PLUS its render_chart spec, so it works everywhere and the user can copy or tweak any spec. Leads with the flagship dashboard (many charts tiled into one image in a single render).',
3188
3213
  inputSchema: {
3214
+ board: z.enum([...GALLERY_BOARDS.map((b) => b.id), "all"]).optional().describe("render a whole family BOARD \u2014 one tiled dashboard image showing every chart type in that group (" + GALLERY_BOARDS.map((b) => b.id).join(" / ") + '). "all" = the full set of ' + GALLERY_BOARDS.length + ' boards = "show me EVERYTHING". Takes precedence over `type`/`limit`.'),
3189
3215
  type: z.enum(TYPE_NAMES).optional().describe('render just this ONE type (its showcase spec, or its minimal example) \u2014 for "show me a <type>"; omit for the curated multi-type showcase'),
3190
- limit: z.number().optional().describe("max items in the showcase (default all " + GALLERY.length + "); ignored when `type` is set")
3216
+ limit: z.number().optional().describe("max items in the showcase (default all " + GALLERY.length + "); ignored when `type` or `board` is set")
3217
+ }
3218
+ }, async ({ board, type, limit }) => {
3219
+ if (board) {
3220
+ const boards = board === "all" ? GALLERY_BOARDS : GALLERY_BOARDS.filter((b) => b.id === board);
3221
+ const content2 = [{ type: "text", text: `SlickFast gallery \u2014 ${boards.length} board${boards.length > 1 ? "s" : ""}. Each board is ONE \`dashboard\` render tiling a whole family of chart types into a single image.` }];
3222
+ for (const b of boards) {
3223
+ const spec = boardSpec(b);
3224
+ try {
3225
+ const png = svgToPng(renderSpec(spec), { scale: spec.scale });
3226
+ content2.push({ type: "text", text: `### ${spec.title}
3227
+ ${b.types.length} types \u2014 one dashboard call: ${b.types.join(", ")}.` });
3228
+ content2.push({ type: "image", data: png.toString("base64"), mimeType: "image/png" });
3229
+ } catch (e) {
3230
+ content2.push({ type: "text", text: `(${b.title} board failed to render: ${e?.message || e})` });
3231
+ }
3232
+ }
3233
+ return { content: content2 };
3191
3234
  }
3192
- }, async ({ type, limit }) => {
3193
3235
  let items;
3194
3236
  if (type) {
3195
3237
  const g = GALLERY.find((x) => x.spec.type === type);
@@ -3231,6 +3273,37 @@ server.registerTool("list_palettes", {
3231
3273
  hint: 'pass any name as `palette`. Flat is the default for most charts; nested themes shine on pieofpie. "dark: true" themes assume a dark background.'
3232
3274
  }, null, 2) }] };
3233
3275
  });
3276
+ server.registerTool("report_issue", {
3277
+ title: "Report an issue",
3278
+ description: 'Report a SlickFast bug or a wrong-looking chart. Call this ONLY when the USER explicitly asks to report an issue / send feedback \u2014 never automatically. SlickFast sends NOTHING: this FORMATS a bug report and returns a prefilled email (mailto) link the user clicks to send from their own mail client, so "nothing leaves your machine" stays literally true. ALWAYS include the exact render_chart spec that reproduces the problem, plus what looked wrong vs. expected \u2014 a precise repro is the most valuable part.',
3279
+ inputSchema: {
3280
+ summary: z.string().describe('one-line summary of the problem (e.g. "Nordic Earth palette renders default colors on a bar")'),
3281
+ spec: z.any().optional().describe("the exact render_chart spec that reproduces it \u2014 include it, this is the most useful part"),
3282
+ expected: z.string().optional().describe("what the user expected to see"),
3283
+ actual: z.string().optional().describe("what actually happened")
3284
+ }
3285
+ }, async ({ summary, spec, expected, actual }) => {
3286
+ const body = [
3287
+ `**Summary:** ${summary}`,
3288
+ expected ? `**Expected:** ${expected}` : null,
3289
+ actual ? `**Actual:** ${actual}` : null,
3290
+ spec ? "**Repro spec:**\n```json\n" + JSON.stringify(spec, null, 2) + "\n```" : null,
3291
+ `**Package:** @slickfast/mcp@${VERSION}`,
3292
+ "_Reported via the SlickFast report_issue tool._"
3293
+ ].filter(Boolean).join("\n\n");
3294
+ const mailto = `mailto:${FEEDBACK_EMAIL}?subject=${encodeURIComponent("SlickFast bug: " + summary)}&body=${encodeURIComponent(body)}`;
3295
+ const ghIssue = `https://github.com/SlickFast/slickfast/issues/new?labels=bug&title=${encodeURIComponent("[bug] " + summary)}&body=${encodeURIComponent(body)}`;
3296
+ const text = `Bug report ready \u2014 **nothing has been sent.** To submit, pick either:
3297
+
3298
+ - **GitHub issue** (preferred \u2014 public, trackable): ${ghIssue}
3299
+ - **Email** (opens your mail client): ${mailto}
3300
+
3301
+ Or copy the report below into an email to ${FEEDBACK_EMAIL}:
3302
+
3303
+ ---
3304
+ ${body}`;
3305
+ return { content: [{ type: "text", text }] };
3306
+ });
3234
3307
  server.registerResource("chart-spec", "spec://chart-spec", {
3235
3308
  title: "ChartSpec contract",
3236
3309
  description: "Full field reference for render_chart.",
package/package.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "name": "@slickfast/mcp",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
+ "mcpName": "com.slickfast/mcp",
5
+ "homepage": "https://slickfast.com",
6
+ "repository": { "type": "git", "url": "git+https://github.com/SlickFast/slickfast.git", "directory": "apps/mcp" },
7
+ "bugs": { "url": "https://github.com/SlickFast/slickfast/issues", "email": "feedback@slickfast.com" },
4
8
  "description": "SlickFast — render 47 chart & info-design types (bar, line, pie, KPI, cards, funnel, matrix, gauge, calendar…) plus multi-chart dashboards tiled into one image, as SVG/PNG via MCP. Local and deterministic; nothing leaves your machine.",
5
9
  "keywords": ["mcp", "model-context-protocol", "chart", "charts", "dashboard", "data-visualization", "svg", "png", "ai", "agent", "claude", "llm", "deterministic"],
6
10
  "license": "AGPL-3.0-only",