npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bicharts/chart-mcp

v0.6.56

Published

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). An ac

Readme

@bicharts/chart-mcp

Make Generative AI for Charts Better.

Docs and examples: RegiaBI for developers · live demos in React and Blazor · the React walkthrough · the Blazor recipe · how a fresh agent built a Blazor app through this server · all articles · terms

Listed in the official MCP Registry as com.regiabi/chart-mcp, so any MCP host that reads the registry can find it; or run it with npx -y @bicharts/chart-mcp (setup below).

An MCP (Model Context Protocol) stdio server that puts RegiaBI behind any MCP-capable AI client (Claude Code, Claude Desktop, Copilot Studio, Cursor, …).

What that buys you: a working, interactive chart that fits your data on the first try — real source you commit, with no D3, Vega or charting-API expertise in the loop, and a solid starting point to adjust rather than a blank page. Because the engine knows what ~90 chart types can honestly say, it will sometimes propose a view — or a measure — you had not thought to ask for.

What it costs: authoring, and nothing else. The calls that write a chart (and the eligibility lists beyond a free hourly allowance) are metered on your account. What they write is yours: the chart code needs no licence, no account, no credits and no connection to us to run, view, deploy, ship or keep, for any number of viewers, forever. The host that draws it, @bicharts/chart-host, is open source (Apache-2.0), and the generated code makes no calls home. See section 1(d) of the RegiaBI terms and LICENSE.txt section 2.

The main tools:

  • assess_data_shape — profiles a CSV locally with the same measurement engine the Power BI visual uses (@bicharts/shape-core). No backend call, no credentials, no data leaves the machine. The free-teaser tool.
  • list_eligible_charts — the authoritative list of chart types that can render this data (server-side policy, not a local guess; no LLM, but a network call to the engine and therefore metered — see Credentials). By default it auto-detects the project's language (JS/TS vs Python from the working dir) and returns the charts for THAT language — scoped to its renderers and ranked by the picker's chart-type×renderer weights (best first), each tagged with its source language (JavaScript for D3/Vega, Python for Plotly/matplotlib), its renderer, and a 0–100 score. Pass language: "javascript"|"python" to force it, renderer: "D3"/"PLOTLY"/… to rank one specific renderer, or renderer: "" for the full renderer-agnostic eligibility across all renderers (unranked — the wide "what can render" net). top: N trims to the best N. If the language can't be auto-detected and none is given, the tool asks you to specify one. Credentials required — no LLM is not the same as no cost, because eligibility is the engine's own answer. Free within a generous hourly allowance; beyond it a call may draw usage credits. A live licence additionally unlocks draft types.
  • suggest_charts — "which charts suit this model?" in one call, for a semantic model in a Microsoft Fabric App on Rayfin's data app template: reads the model's tables, measures and relationships through the project's own fabric-app-data CLI, finds its natural views (by place, flows between places, over time, by category), queries each at its grain and asks the eligibility engine what fits each, replying with the real counts. Each view saves its rows for generate_chart. One list_eligible_charts-style metered call per view.
  • generate_chart — profiles locally, then calls the BIC backend, which picks an eligible chart type for the measured shape (or honors chart_type) and returns code that has passed the backend's gates/QC. Renderer selection is the same language-aware intersection: with no explicit renderer, the detected/language narrows the backend's auto renderer pick to that language (JS → D3/Vega, Python → Plotly/matplotlib); an explicit renderer always wins. For D3 output, passing preview_html: true alongside out_dir also writes a standalone preview.html you can open with no build step. It is off by default — the code is meant to be merged into your app, not run as an index.html.

generate_chart's machine-readable result

generate_chart answers on two channels. The text block is for a human (and for hosts that only render text); structuredContent is for code, so nothing has to string-parse --- code --- out of prose:

| field | | | --- | --- | | code | the render() source (omitted when include_code: false, which is the default when out_dir is given - the code is then on disk) | | chartName, language, version, creditCost | what was produced, and what it cost | | correlationId | the handle into the server-side log — quote it in any support request | | outputHash | the server's identity for this exact code (the same code always carries the same hash) — keep it with the chart | | requiredD3Plugins | packages the code calls, e.g. ["d3-sankey"] — install them and pass the host one d3 that carries them, built with assembleD3(d3, { ...plugins }) from @bicharts/chart-host (assigning onto an ES-module d3 namespace throws), or the chart throws mid-render | | geo / geoPoint | region/basemap wiring, and how many points actually placed | | geoPointDest | present only for a route (an origin-destination flow map): the same count for each row's destination, which is geocoded apart from the origin | | data or files | the render payload inline, or the paths written — never both | | hostContract, build | the contract the code targets, and the bundle that served the call | | recoveredAfterMs | present only when the response stream was cut and the chart was fetched back by its correlation: milliseconds from the start of the call to delivery. creditCost is null then |

data carries the appended __geoIso__ / __geoLat__ / __geoLon__ columns (and a route's __geoLatD__ / __geoLonD__), which a caller cannot reconstruct from the source data — so a geo chart needs either it or files.data.

Language & renderer

Both list/generate tools speak language (what your project is written in) as well as renderer (a specific chart library). The server maps javascript/typescript → D3 + Vega and python → Plotly + matplotlib, and the picker's weights rank across that language's renderers. Precedence is explicit renderer > language > auto-detected language. The MCP sniffs the working directory (or project_dir) for language markers (package.json/tsconfig.json → JS, pyproject.toml/requirements.txt → Python) plus a bounded source-file count; when the signal is genuinely mixed or absent it asks you to pick rather than silently assuming one.

Data inputs — CSV or a pre-typed table

Both tools accept, as alternatives:

  • csv_path / csv_text — a CSV; column types and measure/dimension roles are inferred (numeric-non-identifier = measure), and you can steer them with the measures/dimensions/formats/descriptions levers.
  • data: { columns, rows } — a pre-typed table, the shape a Fabric DAX Execute-Queries result, a dataframe, or an arrow table already has. columns carry name and (optionally) dataType, isMeasure, format, description; rows are positional arrays or objects keyed by column name. When a caller supplies isMeasure + format + description from a semantic model, the shape matches Power BI fidelity with no heuristic guessing — the profiler engine is the same one the visual runs; CSV was only ever one adapter over it.

Example (a semantic-model query result):

{
  "data": {
    "columns": [
      { "name": "Region",  "dataType": "String",  "isMeasure": false },
      { "name": "Revenue", "dataType": "Decimal", "isMeasure": true,
        "format": "$#,##0", "description": "Net booked revenue" }
    ],
    "rows": [ { "Region": "West", "Revenue": 12000.5 }, { "Region": "East", "Revenue": 9000 } ]
  }
}

Credentials (generate_chart and list_eligible_charts)

A trial or paid BIC account is required — no freemium. Use the same License Key, Licensee, and Secret Key from your BIC account (the ones the Power BI visual's license settings use).

assess_data_shape needs no credentials at all — it runs entirely locally in @bicharts/shape-core and never calls the backend. list_eligible_charts does need them: it is the server's own eligibility verdict, not a local guess, which is the whole reason it is worth calling. It is free within a generous hourly allowance; beyond that, a call may draw usage credits from the account (both knobs are server-configured), so don't put it inside a tight loop. Use of the API and this MCP server is covered by the RegiaBI Programmatic Access Terms.

Two ways to supply them — env wins over the file:

1. Env vars (via the MCP server's env block — see registration below):

| Var | Meaning | | --- | --- | | BIC_LICENSE_KEY | required | | BIC_LICENSEE | required (account name) | | BIC_SECRET_KEY | optional | | BIC_URL | override backend (default https://bizintelligencechampions.com) | | BIC_MCP_REASONING | OPTIONAL override of the default reasoning mode (else "" = leave-to-visual, same as the PBI visual) | | BIC_MCP_MODEL | OPTIONAL override of the default model (else "" = the account's IsDefault model, same as the visual) | | BIC_MCP_TIMEOUT_MS | OPTIONAL: how long one generate_chart call waits, recovery included (default 900000, 15 minutes) |

Defaults match the Power BI visual. Unset, the MCP sends model="" (server resolves the IsDefault model), reasoning_mode="" (leave-to-visual heuristic), and privacy_level="20" (detailed stats, no sample rows — see below). The two env vars above are escape hatches only; leave them unset for visual parity.

Response timeouts (HTTP 499 / dropped connection)

The backend completes long multi-pass generations (the visual regularly runs several minutes on rich charts). A dropped connection is therefore a delivery timeout in the calling path — the MCP host's tool-call timeout or an intermediary proxy — not a server ceiling, and not a generation failure (the chart likely generated and may have been billed). The parity-preserving fix is to let the call take as long as it needs:

  • Built in: the server sends MCP progress notifications every 10s during a generation; spec-compliant hosts (including Claude Code) reset their per-call timeout on progress, so the call stays alive as long as the generation needs — no user configuration required.
  • Fallback for hosts that don't reset on progress: raise the host's per-tool timeout (Claude Code: MCP_TOOL_TIMEOUT in ms, set in the environment Claude Code itself runs in — e.g. the env block of settings.json).
  • Built in: when the response stream is cut after the server accepted the request, the MCP does not give up or re-generate. Inside the same tool call it checks for the finished chart by its correlationId (a fetch that can never call a model), backing off between checks, until the chart arrives or the recovery window or BIC_MCP_TIMEOUT_MS runs out, whichever is sooner. A recovered chart carries recoveredAfterMs; when nothing arrives, the error keeps the correlationId to quote to support.

BIC_MCP_REASONING=CP/1P would finish faster, but that trades away visual parity (no validator) — prefer raising the timeout.

2. A credentials file — so secrets never sit in a project-committed .mcp.json. Default ~/.bic/credentials.json (override with BIC_CREDENTIALS_FILE):

{ "licenseKey": "…", "licensee": "…" }

(secretKey optional.)

Prefer the file, or a user-scoped claude mcp add (stored in your user config), over putting secrets in a repo-committed .mcp.json.

Note: this package deliberately does NOT contain the freemium key-mint secret — consistent with trial/paid-only access, and safe if the folder is ever published.

Credit charges

Each generate_chart call spends credits on your account, exactly like the Power BI visual (the MCP hits the same billed endpoint):

  • Hosted (our models) → token-based — you pay for the tokens the generation actually used.
  • BYO (your own API key) → a flat operating fee per request, priced for this surface separately from the Power BI visual. Current rates are shown in your account.

The response header line shows credits: N so you can see what each call cost.

That's the whole bill: a chart you've generated costs nothing to keep, run or show to anyone.

Telemetry

The server tells the BIC service three things, and nothing else:

  • A usage counter for each call of list_eligible_charts and generate_chart that reaches the service: the tool's name, this server's client version and a random nonce. No data, no account, no machine identity.
  • One row when generate_chart returns code, joined to the generation the service already logged (by its output hash) and marked as delivered through the MCP: the call's duration, the row count, the requested language and this server's build. It records that the code was handed over, never that anyone drew it.
  • One row when a generation fails after the service answered, carrying the service's own message.

assess_data_shape never sends anything - it profiles your data locally, telemetry on or off.

Set BIC_MCP_TELEMETRY=0 in the server's environment to turn all of it off.

The agent skill (recommended)

This package ships skills/bic-charts/SKILL.md — the golden path from empty directory to a working cross-filtered dashboard: the scaffold command block, when to use the authoritative contract parameters instead of prompt prose, the coordinated-dashboard recipe, and the handful of places builds measurably lose time. Copy it where your agent looks for skills, in the folder you'll work in. npx keeps the package in its own cache, not under npm root, so unpack it from the registry instead:

$tgz = npm pack @bicharts/chart-mcp
tar -xzf $tgz
mkdir -Force .claude\skills
Copy-Item -Recurse package\skills\bic-charts .claude\skills\
Remove-Item -Recurse package, $tgz
tgz=$(npm pack @bicharts/chart-mcp 2>/dev/null)
tar -xzf "$tgz"
mkdir -p .claude/skills && cp -r package/skills/bic-charts .claude/skills/
rm -rf package "$tgz"

(PowerShell does not expand a * for tar, so tar -xzf bicharts-chart-mcp-*.tgz fails there; capturing the file name npm pack prints works in both shells.)

An agent that reads it first does in a few calls what otherwise takes thirty — most of the difference is not knowing the API, it is not knowing the shape of the answer.

Register with Claude Code

claude mcp add --scope user bic-chart -- npx -y @bicharts/chart-mcp

--scope user stores it in your user config so it works in every project. With credentials in ~/.bic/credentials.json you need no -e flags at all; add them only if you prefer env vars:

claude mcp add --scope user bic-chart -e BIC_LICENSE_KEY=... -e BIC_LICENSEE=... -- npx -y @bicharts/chart-mcp

or in a project .mcp.json:

{
  "mcpServers": {
    "bic-chart": {
      "command": "npx",
      "args": ["-y", "@bicharts/chart-mcp"]
    }
  }
}

Claude Desktop uses the same command/args/env block in claude_desktop_config.json under mcpServers.

Try: "Assess the shape of ./sales.csv, then generate a chart for it and write the preview to ./out."