@bicharts/chart-mcp 0.6.101 → 0.6.104
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 +7 -1
- package/dist/check-chart.mjs +94 -91
- package/dist/index.mjs +173 -136
- package/package.json +7 -6
- package/skills/bic-charts/SKILL.md +48 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.104",
|
|
4
4
|
"description": "AI Data Components for Power BI, Excel, Fabric Apps and the web, over MCP: bivariate maps, what-if projections and about 90 everyday chart types, with selection and cross-filtering already wired. It profiles your table locally; the code it writes is yours and runs with no license.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
},
|
|
48
48
|
"// dependencies": "NONE, deliberately. dist/ bundles every module the server uses, so a runtime dependency installs nothing it needs - it only makes npx fetch that package (and its tree) before the first start. Everything the bundle carries is a devDependency; scripts/verify-package.mjs fails the release if a dependency appears or a shipped file imports anything but Node's built-ins.",
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@bicharts/chart-host": "^0.6.
|
|
51
|
-
"@bicharts/shape-core": "^0.6.
|
|
50
|
+
"@bicharts/chart-host": "^0.6.103",
|
|
51
|
+
"@bicharts/shape-core": "^0.6.103",
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
53
|
-
"@types/node": "^
|
|
53
|
+
"@types/node": "^26.6.5",
|
|
54
54
|
"@types/papaparse": "^5.3.14",
|
|
55
55
|
"d3": "^7.9.0",
|
|
56
56
|
"d3-hexbin": "^0.2.2",
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
"esbuild": "^0.28.1",
|
|
60
60
|
"happy-dom": "^20.14.5",
|
|
61
61
|
"papaparse": "^5.4.1",
|
|
62
|
-
"typescript": "^
|
|
63
|
-
"
|
|
62
|
+
"typescript": "^7.0.2",
|
|
63
|
+
"typescript5": "npm:typescript@^5.9.3",
|
|
64
|
+
"zod": "^4.6.7"
|
|
64
65
|
}
|
|
65
66
|
}
|
|
@@ -180,6 +180,12 @@ disqualifies it; leave it unset when they only asked for a chart, and the engine
|
|
|
180
180
|
`@bicharts/chart-host` draws), `width`/`height`, and
|
|
181
181
|
`reasoning_mode: "1P"` when you want the cheapest, fastest pass.
|
|
182
182
|
|
|
183
|
+
**Check a named request before generating it.** When the person's request names a chart type or something
|
|
184
|
+
specific (a date grain, a limit, an overlay, a column that must show), pass the same arguments to
|
|
185
|
+
`check_request` first. It says, in the service's own words, which asks this data can't honor and why,
|
|
186
|
+
with chart types that fit when the type itself is denied; tell the person what it denies and why rather
|
|
187
|
+
than generating around it. It spends no generation credits and is metered like `list_eligible_charts`.
|
|
188
|
+
|
|
183
189
|
**Settings are the user's to answer, not yours to guess.** Every `generate_chart` result carries a
|
|
184
190
|
`structuredContent.settings` block: `applied` lists each setting that took effect and whose choice it
|
|
185
191
|
was (`user`, `app`, `default`, `server-roll`, `from-prompt`), `askable` names the ones still open to
|
|
@@ -547,9 +553,21 @@ overwrites a file, and its reply ends with a worked example. Building notes on m
|
|
|
547
553
|
data service is on (the notes recipe below, step a), run it again with `features: ["notes", "scenarios"]`: it writes
|
|
548
554
|
those files finished.
|
|
549
555
|
|
|
556
|
+
**The model's name is the `connection`.** Connect the semantic model the way the template's AGENTS.md says - before or
|
|
557
|
+
after `setup_fabric_app`, whose reply names it either way. On the template's current layout the model is a Rayfin
|
|
558
|
+
connector: `npx rayfin connector search "<model name>" --all-workspaces --type fabric-semanticmodel --json`, then the
|
|
559
|
+
`npx rayfin connector add --type fabric-semanticmodel --name <name> --workspace-id <id> --item-id <id>` it prints (ids from
|
|
560
|
+
the search, never guessed); the connector's name in `rayfin/rayfin.yml` is what `useSemanticModelQuery({ connection })`
|
|
561
|
+
takes. On the template's older layout (a `fabric.yaml`, `@microsoft/fabric-app-data`) it is the model's alias in
|
|
562
|
+
`fabric.yaml`. `query_semantic_model` and `suggest_charts` read it from whichever file the project has; pass `alias` only
|
|
563
|
+
when the project declares more than one.
|
|
564
|
+
|
|
550
565
|
**1. Pull each chart's rows at the chart's GRAIN, with a query written for that chart.** One row per
|
|
551
|
-
country for a country map, one per route for a flow map, one per month for a trend. The template's
|
|
552
|
-
|
|
566
|
+
country for a country map, one per route for a flow map, one per month for a trend. The template's own
|
|
567
|
+
command runs a `.dax` file through the connector: `npx fabric-app-semantic-model-tools run-dax-query --dax <file.dax>
|
|
568
|
+
--alias <connector>` (on its older layout, `npx fabric-app-data query <alias> --query '<DAX>'`).
|
|
569
|
+
`query_semantic_model` runs the query through that same connector and the project's own sign-in, so a query it returned
|
|
570
|
+
has passed the template's check: don't run it again with `run-dax-query`. Don't pull a fact
|
|
553
571
|
table and aggregate it in the browser: the Execute Queries API refuses a response over 15 MB, and a
|
|
554
572
|
column repeated on every fact row (a country's population on each sale) sums to nonsense.
|
|
555
573
|
|
|
@@ -567,12 +585,14 @@ name. Pass the model's metadata as you rename: `isMeasure`, `format` and `descri
|
|
|
567
585
|
Power BI visual gets for free. In `INFO.VIEW.COLUMNS()` a column's name is `[Name]`, not `[Column]`.
|
|
568
586
|
|
|
569
587
|
**Steps 1-3 are one call: `query_semantic_model`.** Give it the chart's DAX (`dax`, or a `.dax` file) and a
|
|
570
|
-
`name`; it runs the query through the project's own
|
|
588
|
+
`name`; it runs the query through the project's own tooling - the model's Rayfin connector (through
|
|
589
|
+
`@microsoft/fabric-app-semantic-model-tools`, else the Rayfin CLI), or on the older layout the `fabric-app-data` CLI - so
|
|
590
|
+
it signs in and gets the reply the app will get. It renames the headers (dropping the
|
|
571
591
|
table and any symbols: `[Occupancy %]` becomes `Occupancy`), saves every row to `.bic/data/<name>.csv`,
|
|
572
592
|
reads each column's role, format and description from the model (`INFO.VIEW.MEASURES()` / `INFO.VIEW.COLUMNS()`),
|
|
573
593
|
and profiles the result. Its reply ends with the arguments for the next two calls - `csv_path`, `measures`,
|
|
574
594
|
`dimensions`, `formats`, `descriptions` - so pass them to `list_eligible_charts` and `generate_chart` as they
|
|
575
|
-
are.
|
|
595
|
+
are. It keeps at most 1,000 rows of a query; the tool says so when it cut a result, and the fix is a query at the
|
|
576
596
|
chart's grain.
|
|
577
597
|
|
|
578
598
|
**4. Ask before choosing, then choose what answers the question.** `list_eligible_charts` on that
|
|
@@ -590,13 +610,15 @@ without naming:
|
|
|
590
610
|
| every place drawn at the same size, because which are high or low matters more than where | World tile-grid cartogram (or US hex-tile cartogram for states) |
|
|
591
611
|
| actual against a budget, plan or target, with the gap shown for each period or unit | Variance chart (budget vs actual) |
|
|
592
612
|
| that same actual-against-target comparison across many accounts or nested groups, read as a table with subtotals | Variance grid (a preview type) - it needs a category to group by; a date series alone is the Variance chart |
|
|
593
|
-
| a table with one row per item and each value DRAWN (bars, dots or icons in the cells),
|
|
594
|
-
| a table a reader sorts, hides columns
|
|
613
|
+
| a table with one row per item and each value DRAWN (bars, dots or icons in the cells), compact, for scanning down a column and nothing more | Table with embedded |
|
|
614
|
+
| a table a reader WORKS with: sorts, drags column widths, copies cells out, hides columns, scrolls a wide table sideways with frozen columns or rows, opens a row's detail; plain values by default, and where the request asks, data bars, chips, icons, or one value compared with several others as bars (this week against its averages) | Interactive table (a preview type) - name the cells to draw in `prompt`; widths, sort and hidden columns are the reader's, kept through the host's view state |
|
|
595
615
|
| circling a group of points to see what sets them apart from the rest | Selection explainer (a preview type) - the lasso and the comparison are drawn inside the chart; put the other fields to compare in the same table (which ones: below); on a page, give it `selects` so a circled group filters the page (step 6) |
|
|
596
616
|
|
|
597
617
|
If the list doesn't offer what you expected, read its notes: it names a type refused on a count
|
|
598
618
|
when your table is small, and it says when `name_filter` hid description matches.
|
|
599
619
|
|
|
620
|
+
The Interactive table and the Variance grid are preview types too, so either may be missing from the list. When the person asked for one and it isn't listed, say so and ask how to go on; don't build a table by hand in its place.
|
|
621
|
+
|
|
600
622
|
The Selection explainer is a preview type: the server offers it only where it's switched on, so it may be missing from the
|
|
601
623
|
list even when the data fits. When `list_eligible_charts` doesn't list it for your data, tell the person it isn't available
|
|
602
624
|
for this data right now, and ask how they want to go on. Don't silently draw a plain scatter in its place, and don't write the
|
|
@@ -627,7 +649,8 @@ import { BicChartPanel } from "@/components/bic-chart-panel";
|
|
|
627
649
|
import { useBicChartOptions } from "@/lib/bic-chart-options";
|
|
628
650
|
import QUERY from "@/queries/overview/occupancy-map.dax?raw"; // the template's rule: DAX lives in .dax files
|
|
629
651
|
|
|
630
|
-
|
|
652
|
+
// connection: the model's connector name in rayfin/rayfin.yml (fabric.yaml's alias on the older layout)
|
|
653
|
+
const result = useSemanticModelQuery({ connection: "<connector name>", query: QUERY }); // the DAX it was generated on
|
|
631
654
|
const options = useBicChartOptions();
|
|
632
655
|
const country = useBicFilter("CountryIso3", { label: "Country", display: "CountryName" }); // step 6
|
|
633
656
|
<BicChartPanel result={result}>
|
|
@@ -637,6 +660,11 @@ const country = useBicFilter("CountryIso3", { label: "Country", display: "Countr
|
|
|
637
660
|
</BicChartPanel>
|
|
638
661
|
```
|
|
639
662
|
|
|
663
|
+
**A reader's view outlives the page only if you keep it.** What a reader sets inside a chart - an Interactive table's sort,
|
|
664
|
+
column widths and hidden columns, a 3D camera, an expanded row - lives while the chart is mounted and is gone on reload.
|
|
665
|
+
Pass `rememberAs="<a key per chart>"` to keep it in that browser, or `viewState={{ load, save }}` to keep it per signed-in
|
|
666
|
+
person on your server (a plain JSON bag). Hand-hosting `BicChart`, pass the same `viewState` prop.
|
|
667
|
+
|
|
640
668
|
It is rewritten with the chart on every generation, so keep app logic outside it. What it does, if you
|
|
641
669
|
host by hand instead - `generate_chart` returns `binding`; pass all three:
|
|
642
670
|
|
|
@@ -719,7 +747,7 @@ import FORECAST_DAX from "@/queries/overview/bookings-forecast.dax?raw";
|
|
|
719
747
|
const country = useBicFilter("CountryIso3", { label: "Country", display: "CountryName" });
|
|
720
748
|
const route = useBicFilter(["OriginCode", "DestinationCode"],
|
|
721
749
|
{ label: "Route", display: ["OriginName", "DestinationName"] });
|
|
722
|
-
const forecast = useSemanticModelQuery({ connection: "<
|
|
750
|
+
const forecast = useSemanticModelQuery({ connection: "<connector name>",
|
|
723
751
|
query: filterQuery(FORECAST_DAX, treatAs(country, "Geography[CountryIso3]")) });
|
|
724
752
|
|
|
725
753
|
<BicFilterChips /> {/* "Country: Japan ×" - what's filtered, and its clear */}
|
|
@@ -786,8 +814,10 @@ npx rayfin init --services auth,data --auth-methods fabric --dialect mssql --ove
|
|
|
786
814
|
Each flag is needed: without `--overwrite` it prints "Initialization cancelled" and exits 0 with no
|
|
787
815
|
reason; without `--project-name` (pass the `id:` already in `rayfin/rayfin.yml`, so nothing is renamed)
|
|
788
816
|
it stops with "--project-name is required in non-interactive mode". It rewrites `rayfin/rayfin.yml`
|
|
789
|
-
and `.gitignore`, so `git diff` both and put back what's yours
|
|
790
|
-
`
|
|
817
|
+
and `.gitignore`, so `git diff` both and put back what's yours: on the template's connector layout that is the
|
|
818
|
+
`connectors:` list in `rayfin/rayfin.yml` (put it back, or run the same `npx rayfin connector add` again - without it
|
|
819
|
+
the app and `query_semantic_model` have no model) and the template's `.gitignore` lines; on the older layout, on 1.36.1, it
|
|
820
|
+
dropped the `src/fabric.generated.ts` line. It writes `rayfin/tsconfig.json` - keep its
|
|
791
821
|
`outDir`, `.temp/compiled`, which is where the deploy reads the entities from - and no entities. On 1.36.2 it
|
|
792
822
|
writes no `rayfin/data/schema.ts` either: don't write one by hand - `setup_fabric_app` with `features` (step c) writes it
|
|
793
823
|
when `rayfin/rayfin.yml` shows the data service on.
|
|
@@ -796,9 +826,11 @@ when `rayfin/rayfin.yml` shows the data service on.
|
|
|
796
826
|
- `rayfin/tsconfig.json`, in `compilerOptions`: `"tsBuildInfoFile": ".temp/tsconfig.tsbuildinfo"` and
|
|
797
827
|
`"allowImportingTsExtensions": false` (it inherits both from the root: TS6377 and TS5096 otherwise).
|
|
798
828
|
- the root `tsconfig.json`: `"references": [{ "path": "./rayfin" }]`.
|
|
799
|
-
- type the client with your schema
|
|
800
|
-
|
|
801
|
-
`
|
|
829
|
+
- type the client with your schema (`import type { AppSchema } from "../../rayfin/data/schema";`): in
|
|
830
|
+
`src/lib/rayfin-client.ts`, on the connector layout, `AppSchema` in place of `EntitySchema` as the first type argument
|
|
831
|
+
of `ConnectorsRayfinClient<EntitySchema, FunctionsSchema, AppConnectorsSchema>` (the older layout's file has
|
|
832
|
+
`RayfinClient<AppSchema>`); and `RayfinClient<AppSchema>` in the constructor of `src/services/rayfin-auth.service.ts`
|
|
833
|
+
(TS2345 otherwise).
|
|
802
834
|
|
|
803
835
|
Check with `npx tsc -b`; a bare `tsc --noEmit` reports TS6305 until the `rayfin/` project is built. If a
|
|
804
836
|
TS2345 names two copies of `rayfin-auth`, something installed only some Rayfin packages: run
|
|
@@ -818,8 +850,9 @@ never rewrites them:
|
|
|
818
850
|
chart's card (a card has a fixed height and `overflow-hidden`, and clips it). The reader's text is cleared only once
|
|
819
851
|
the save succeeds; a failure is shown with the text kept.
|
|
820
852
|
|
|
821
|
-
*d. Badges on the marks: pass `annotations`, never measure the chart.* The host draws each badge on its key's mark
|
|
822
|
-
after
|
|
853
|
+
*d. Badges on the marks: pass `annotations`, never measure the chart.* The host draws each badge on its key's mark (on a
|
|
854
|
+
table row, just after the row's label; on a chart type that asks for it, such as a tile map, a small dot inside the
|
|
855
|
+
tile's top-right corner with the `label` and `title` in its tooltip) after every render and keeps it there through filters, re-queries and zooms; it never reads a row position. A route is
|
|
823
856
|
keyed by BOTH of its ends with `where` - no key column to add, no query to change and no chart to regenerate:
|
|
824
857
|
|
|
825
858
|
```tsx
|