@bicharts/chart-mcp 0.2.0 → 0.3.0
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 +15 -0
- package/dist/index.mjs +22 -22
- package/package.json +4 -3
- package/skills/bic-charts/SKILL.md +122 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP (Model Context Protocol) stdio server for BIC AI charts: profile a dataset locally, then generate chart code that has passed the BIC backend's render gates. Works with any MCP-capable client (Claude Code, Claude Desktop, Cursor, Copilot Studio). Requires a BIC trial or paid account.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"// files": "dist ONLY — this package ships the built server, not its source. LICENSE.txt and README.md are included automatically by npm, but listed so an audit does not have to know that.",
|
|
26
26
|
"files": [
|
|
27
27
|
"dist",
|
|
28
|
+
"skills",
|
|
28
29
|
"LICENSE.txt",
|
|
29
30
|
"README.md"
|
|
30
31
|
],
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
"zod": "^3.23.0"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@bicharts/chart-host": "^0.
|
|
48
|
-
"@bicharts/shape-core": "^0.
|
|
48
|
+
"@bicharts/chart-host": "^0.4.0",
|
|
49
|
+
"@bicharts/shape-core": "^0.4.0",
|
|
49
50
|
"@types/node": "^20.0.0",
|
|
50
51
|
"@types/papaparse": "^5.3.14",
|
|
51
52
|
"esbuild": "^0.28.1",
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bic-charts
|
|
3
|
+
description: Build a web app or dashboard containing BIC-generated charts — a bubble map, a table with in-cell bars, linked cross-filtering. Use whenever the bic-chart MCP tools are available and the task is "put a chart / dashboard in this app".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Building an app with BIC charts
|
|
7
|
+
|
|
8
|
+
The golden path, end to end. Following it costs a handful of tool calls; deriving it from
|
|
9
|
+
first principles costs about thirty, and the places people lose time are all called out
|
|
10
|
+
below because they were all measured.
|
|
11
|
+
|
|
12
|
+
**The mental model.** A BIC chart is *generated source you own* — a plain
|
|
13
|
+
`render(container, data, options)` function you commit to your repo. There is no API key at
|
|
14
|
+
run time, no per-render cost, and no network call. `@bicharts/chart-host` runs it; the MCP
|
|
15
|
+
generates it. Generation happens **once, at build time, by you** — never in your users'
|
|
16
|
+
browsers.
|
|
17
|
+
|
|
18
|
+
## 1. Scaffold (one command block)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm create vite@latest my-app -- --template react-ts
|
|
22
|
+
cd my-app
|
|
23
|
+
npm install d3@7 @bicharts/chart-host
|
|
24
|
+
npm install -D @types/d3
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`d3` is a peer requirement of the **chart**, not of chart-host. `@types/d3` only for
|
|
28
|
+
TypeScript. chart-host has no runtime dependencies.
|
|
29
|
+
|
|
30
|
+
## 2. Generate — say what the output must BE, not just what it should look like
|
|
31
|
+
|
|
32
|
+
Call `generate_chart` once per chart, with `out_dir` so the artifacts land on disk.
|
|
33
|
+
|
|
34
|
+
The single most important habit: **`prompt` is a suggestion lane.** It steers style and
|
|
35
|
+
emphasis, and it competes with the chart lane's own guidance about summarizing. When your
|
|
36
|
+
app *depends* on the shape of the output, use the contract parameters instead — they are
|
|
37
|
+
authoritative, and `required_columns` is verified in the generated code with an automatic
|
|
38
|
+
correction:
|
|
39
|
+
|
|
40
|
+
| Parameter | Use it when |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `rows_policy: "all"` | every source row must appear — a row-per-entity table, a point per location. Without it the engine may legitimately show a Top-N with an "Other" rollup. |
|
|
43
|
+
| `required_columns: [...]` | a field must be visible because your app's interactions depend on it (e.g. the column you colour or filter by). |
|
|
44
|
+
| `forbid_derived_columns: true` | your app owns the analytics; the chart is only the display. Stops per-capita / share-of-total / rank columns being added. |
|
|
45
|
+
|
|
46
|
+
Asking for these in `prompt` prose instead is the most expensive mistake available here: it
|
|
47
|
+
routinely costs two or three extra generations, and each one is minutes of wall-clock.
|
|
48
|
+
|
|
49
|
+
Other parameters worth knowing: `chart_type` (a preference, honored unless the data shape
|
|
50
|
+
disqualifies it), `renderer: "D3"` for a web app, `width`/`height`, and
|
|
51
|
+
`reasoning_mode: "1P"` when you want the cheapest, fastest pass.
|
|
52
|
+
|
|
53
|
+
**Generation takes minutes.** Fire the calls for independent charts **in parallel** rather
|
|
54
|
+
than in sequence — it is the difference between ~4 minutes and ~12.
|
|
55
|
+
|
|
56
|
+
## 3. Wire it up
|
|
57
|
+
|
|
58
|
+
Import the generated code as raw text and the sample payload as JSON:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import * as d3 from "d3";
|
|
62
|
+
import { BicChart, BicChartGroup } from "@bicharts/chart-host/react";
|
|
63
|
+
import mapCode from "./charts/map/chart.js?raw";
|
|
64
|
+
import tableCode from "./charts/table/chart.js?raw";
|
|
65
|
+
import payload from "./charts/map/data.sample.json";
|
|
66
|
+
|
|
67
|
+
// data.sample.json rows are POSITIONAL arrays; the group wants row OBJECTS.
|
|
68
|
+
const columns = payload.columns;
|
|
69
|
+
const rows = payload.rows.map(r =>
|
|
70
|
+
Object.fromEntries(columns.map((c, i) => [c.name, r[i]])));
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### The coordinated dashboard — the recipe, memorized
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<BicChartGroup columns={columns} rows={rows} point={{ city: "City", state: "StateOrProvince" }}>
|
|
77
|
+
<BicChart id="map" code={mapCode} d3={d3} geoKind="na" respondsWith="highlight" />
|
|
78
|
+
<BicChart id="table" code={tableCode} d3={d3} />
|
|
79
|
+
</BicChartGroup>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
That is all of it. The map **highlights** (keeps every bubble, dims the rest) and the table
|
|
83
|
+
**filters**. Cross-filtering is mutual by default, a chart never filters itself, and
|
|
84
|
+
`group.clear()` clears.
|
|
85
|
+
|
|
86
|
+
Do **not** hand-roll dimming out of the `lch-*` CSS classes. They are an implementation
|
|
87
|
+
detail, they are re-applied on every render (so a `classList` poke is lost at the next data
|
|
88
|
+
change), and translating row indices across a filtered payload is the hazard below.
|
|
89
|
+
|
|
90
|
+
> **The row-index hazard.** `__rowIdx__` is a position *within the payload a chart
|
|
91
|
+
> received*, not an id in your table. Re-render a chart with filtered rows and its payload
|
|
92
|
+
> renumbers from zero, so the same integer denotes a different record. `BicChartGroup` owns
|
|
93
|
+
> that mapping. Comparing indices across two charts by hand does not throw — it quietly
|
|
94
|
+
> filters to the wrong thing.
|
|
95
|
+
|
|
96
|
+
### Sizing
|
|
97
|
+
|
|
98
|
+
Sizing is yours. Give each `<BicChart>` a sized container and pass `width`/`height` in
|
|
99
|
+
`options` — a chart handed `undefined` dimensions draws nothing visible.
|
|
100
|
+
|
|
101
|
+
## 4. Things that will otherwise cost you time
|
|
102
|
+
|
|
103
|
+
- **Place names, not coordinates.** If your data has city/state/ZIP but no lat/lon, pass a
|
|
104
|
+
`point` binding and the host resolves coordinates. Never hardcode a city→coordinate table
|
|
105
|
+
from memory: it breaks silently off famous cities and reports nothing. The host reports
|
|
106
|
+
what it achieved in `options.geoPoint` — `precisionCounts` (rows per tier) and
|
|
107
|
+
`unplaced` — so a chart can annotate honestly instead of implying exact positions.
|
|
108
|
+
- **Both code forms work.** `wrap: "esm"` appends `export { render };` so the file can be
|
|
109
|
+
imported; chart-host strips the clause before compiling. Either form runs anywhere.
|
|
110
|
+
- **D3 plugins.** Some charts call `d3.sankey`, `d3.hexbin` etc., which live in separate
|
|
111
|
+
packages. `requiredD3Plugins(code)` tells you which to install **before** rendering;
|
|
112
|
+
`structuredContent.plugins` on the MCP result says the same thing.
|
|
113
|
+
- **Read `integration_contract`** in the MCP result if you need anything beyond this file —
|
|
114
|
+
it describes the exact payload and option shape for the chart you just generated.
|
|
115
|
+
|
|
116
|
+
## 5. Check it
|
|
117
|
+
|
|
118
|
+
Verify in a real browser, not jsdom — a chart can pass a DOM-shape assertion and paint
|
|
119
|
+
nothing. Assert marks carry `data-row-idx`, that clicking one changes the other chart, and
|
|
120
|
+
that `Clear` restores both. If a check fails, suspect the probe before the product: query
|
|
121
|
+
`fillOpacity` as well as `opacity` when testing dimming, and match buttons by role rather
|
|
122
|
+
than by text that also appears in hint copy.
|