@slickfast/mcp 0.7.2 → 0.7.3
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 +58 -33
- package/dist/index.js +23 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,37 +1,54 @@
|
|
|
1
|
-
# SlickFast
|
|
1
|
+
# SlickFast — charts & dashboards for AI agents
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Run / test
|
|
10
|
-
```bash
|
|
11
|
-
npm install
|
|
12
|
-
node test-client.mjs # spawns the server, calls render_chart, checks the SVG
|
|
9
|
+
```txt
|
|
10
|
+
render_chart({ type: "bar", data: { labels: ["Q1","Q2","Q3"], series: [{ values: [12,19,8] }] } })
|
|
11
|
+
→ a retina PNG, rendered on your machine
|
|
13
12
|
```
|
|
14
13
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
## Why it's built for agents
|
|
15
|
+
|
|
16
|
+
- **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.
|
|
28
|
+
- **100% local & private.** Rendered and rasterized on your machine. Nothing is sent anywhere.
|
|
29
|
+
|
|
30
|
+
## Tools
|
|
31
|
+
|
|
32
|
+
- **`render_chart(spec)`** → the chart as a PNG image (default) or SVG (`format: "svg"`). For a
|
|
33
|
+
dashboard, pass `type: "dashboard"` with `tiles: [{ chart, span }]` — each tile is a full spec
|
|
34
|
+
of any other type, composited into one image in a single render.
|
|
35
|
+
- **`describe_type(type)`** → the exact data shape, a minimal working spec, and per-type
|
|
36
|
+
gotchas. Call it first when you're unsure how to structure a type.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
Add to your MCP config and restart — it runs locally via `npx`, no clone or build needed:
|
|
28
41
|
|
|
29
|
-
## Use it in Claude Code
|
|
30
|
-
Project-scoped config (`.mcp.json` at the workspace root):
|
|
31
42
|
```json
|
|
32
|
-
{ "mcpServers": { "slickfast": { "command": "
|
|
43
|
+
{ "mcpServers": { "slickfast": { "command": "npx", "args": ["-y", "@slickfast/mcp"] } } }
|
|
33
44
|
```
|
|
34
|
-
|
|
45
|
+
|
|
46
|
+
- **Claude Desktop** — `claude_desktop_config.json` (Settings → Developer → Edit Config)
|
|
47
|
+
- **Claude Code** — project `.mcp.json` at the workspace root
|
|
48
|
+
- **claude.ai** — connector settings
|
|
49
|
+
|
|
50
|
+
Then ask it to *"render a bar chart of last quarter's revenue"* or *"build a dashboard with an
|
|
51
|
+
MRR tile, a signups funnel, and a usage heatmap."*
|
|
35
52
|
|
|
36
53
|
## Seeing your charts (why an image might not show inline)
|
|
37
54
|
|
|
@@ -64,14 +81,22 @@ embedding, posting to Slack/X/email, or getting a chart into a surface that can'
|
|
|
64
81
|
local image (see the table above). The agent should **offer this only when you ask to share
|
|
65
82
|
or post** — it never auto-inserts links. (The endpoint stays unadvertised during soft-launch.)
|
|
66
83
|
|
|
67
|
-
## Install via npm (published)
|
|
68
|
-
```json
|
|
69
|
-
{ "mcpServers": { "slickfast": { "command": "npx", "args": ["-y", "@slickfast/mcp"] } } }
|
|
70
|
-
```
|
|
71
|
-
Restart Claude; everything runs locally on your machine — nothing leaves.
|
|
72
|
-
|
|
73
84
|
## License
|
|
85
|
+
|
|
74
86
|
**AGPL-3.0-only.** Free to use, self-host, and embed under the AGPL's terms (your friends
|
|
75
87
|
running it locally are completely unaffected). Building it into a **closed-source product
|
|
76
88
|
or a hosted service**? That needs the AGPL'd source opened — or a **commercial license**
|
|
77
89
|
from us instead. Reach out for commercial terms.
|
|
90
|
+
|
|
91
|
+
## Developing locally
|
|
92
|
+
|
|
93
|
+
Clone the repo, then from the package directory:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cd apps/mcp
|
|
97
|
+
npm install
|
|
98
|
+
node test-client.mjs # spawns the server, calls render_chart, checks the output
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To point an MCP client at a local checkout instead of the published package, use
|
|
102
|
+
`"command": "node", "args": ["<path-to-clone>/apps/mcp/server.mjs"]`.
|
package/dist/index.js
CHANGED
|
@@ -786,7 +786,7 @@ function renderKpi(spec) {
|
|
|
786
786
|
const fs = spec.fontSize ? Number(spec.fontSize) : Math.max(13, Math.round(13 * Math.sqrt(W * H) / 600));
|
|
787
787
|
const font = resolveFont(spec);
|
|
788
788
|
const watermark = spec.watermark !== false;
|
|
789
|
-
const accent = resolveFlatPalette(spec.palette || "Clean Corporate", 1)[0];
|
|
789
|
+
const accent = spec.color || resolveFlatPalette(spec.palette || "Clean Corporate", 1)[0];
|
|
790
790
|
const labelCol = txt(spec, isDark ? "#94a3b8" : "#64748b");
|
|
791
791
|
const valueCol = txt(spec, isDark ? "#f1f5f9" : "#0f172a");
|
|
792
792
|
const faint = isDark ? "#475569" : "#94a3b8";
|
|
@@ -2002,7 +2002,9 @@ function renderTable(spec) {
|
|
|
2002
2002
|
const v = cells[ci];
|
|
2003
2003
|
if (v === void 0 || v === null || v === "") continue;
|
|
2004
2004
|
const num = ci > 0 && isNum(v);
|
|
2005
|
-
const
|
|
2005
|
+
const nv = Number(v);
|
|
2006
|
+
const yearLike = num && Number.isInteger(nv) && nv >= 1900 && nv <= 2100;
|
|
2007
|
+
const out = num ? yearLike ? String(nv) : fmt(nv) : String(v);
|
|
2006
2008
|
p.push(`<text x="${r(cellX(ci, num))}" y="${r(y + ROWH / 2 + 4)}" ${num ? 'text-anchor="end" ' : ""}font-size="${fs}"${wOpt(spec)} fill="${cellCol}">${esc(out)}</text>`);
|
|
2007
2009
|
}
|
|
2008
2010
|
});
|
|
@@ -3055,7 +3057,23 @@ var inputSchema = {
|
|
|
3055
3057
|
scale: z.number().optional().describe("png pixel-density multiplier (default 2 = retina)"),
|
|
3056
3058
|
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.')
|
|
3057
3059
|
};
|
|
3058
|
-
var server = new McpServer({ name: "slickfast", version: "0.7.
|
|
3060
|
+
var server = new McpServer({ name: "slickfast", version: "0.7.3" });
|
|
3061
|
+
var GOTCHAS = {
|
|
3062
|
+
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."],
|
|
3063
|
+
diverging: ["needs 2 series \u2014 series A is forced positive (up), series B negative (down), regardless of stored sign."],
|
|
3064
|
+
difference: ["needs 2 series; the gap between them is shaded."],
|
|
3065
|
+
kpi: ["sparkline is landscape-only (omit it in portrait).", "the accent bar follows the palette \u2014 pass `color` to fix it."],
|
|
3066
|
+
waffle: ["values are cell counts out of a 10\xD710 grid (100 total); a single part renders as one % gauge."],
|
|
3067
|
+
heatmap: ["`values` is a 2D matrix values[row][col]; `rows` and `columns` are the axis labels."],
|
|
3068
|
+
stacked: ["each ROW is a stack segment shared across every bar; segment color comes from the row, not the series."],
|
|
3069
|
+
stacked100: ["each bar sums to 100%; each row is a shared segment."],
|
|
3070
|
+
pieofpie: ['uses `pies:[\u2026]`, not `data`; each pie\u2019s first slice ("bridge") drills into the next.'],
|
|
3071
|
+
gauge: ["`value` is clamped to [min,max]; set min/max to your scale (default 0\u2013100)."],
|
|
3072
|
+
bullet: ["`bands` are qualitative thresholds on the measure scale; `target` draws the comparison marker."],
|
|
3073
|
+
calendar: ['`days` maps "YYYY-MM-DD" \u2192 value; weekday is computed deterministically (no clock/Date).'],
|
|
3074
|
+
dashboard: ["each tile.chart is a full spec of any other type; tiles keep their OWN scale \u2014 for a shared-scale comparison use one grouped/multi-series chart, not side-by-side tiles."],
|
|
3075
|
+
table: ["year-like integers (1900\u20132100) are shown without thousands separators; other numbers get them."]
|
|
3076
|
+
};
|
|
3059
3077
|
function typeContract(t) {
|
|
3060
3078
|
const meta = TYPES.find((x) => x.type === t);
|
|
3061
3079
|
if (!meta) return null;
|
|
@@ -3067,6 +3085,8 @@ function typeContract(t) {
|
|
|
3067
3085
|
needsData: meta.needsData,
|
|
3068
3086
|
honorsToggles: TYPE_TOGGLES[t] || [],
|
|
3069
3087
|
// which of showValues/showTotal/showPoints this type uses (others are ignored)
|
|
3088
|
+
gotchas: GOTCHAS[t] || [],
|
|
3089
|
+
// non-obvious per-type rules (else discovered by rendering twice)
|
|
3070
3090
|
example: EXAMPLES[t] || null
|
|
3071
3091
|
};
|
|
3072
3092
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slickfast/mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"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
|
+
"keywords": ["mcp", "model-context-protocol", "chart", "charts", "dashboard", "data-visualization", "svg", "png", "ai", "agent", "claude", "llm", "deterministic"],
|
|
5
6
|
"license": "AGPL-3.0-only",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"bin": { "slickfast-mcp": "dist/index.js" },
|