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.3.5

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). Requi

Readme

@bicharts/chart-mcp (experimental)

An MCP (Model Context Protocol) stdio server that lets any MCP-capable AI client (Claude Code, Claude Desktop, Copilot Studio, Cursor, …) use the BIC chart engine:

  • 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; zero-credit, no LLM). 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 optional (a license only unlocks draft types).
  • 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) | | 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 | | requiredD3Plugins | packages the code calls, e.g. ["d3-sankey"] — install and Object.assign them onto the same d3 you pass the host, or the chart throws mid-render | | geo / geoPoint | region/basemap wiring, and how many points actually placed | | 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 |

data carries the appended __geoIso__ / __geoLat__ / __geoLon__ columns, 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 } ]
  }
}

Build

cd mcp
npm install
npm run build     # bundles to dist/index.mjs (single file)

Credentials (generate_chart only)

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

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) |

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).
  • (Planned) retrieve an already-generated result by correlationId so a dropped connection recovers the billed code instead of re-generating.

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. The MCP/SDK surface has its own dial (LLMSdkByoOperatingCost, default 3 credits), separate from the visual's fee, so it can be priced independently.

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

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:

mkdir -Force .claude\skills
Copy-Item -Recurse (npm root)\@bicharts\chart-mcp\skills\bic-charts .claude\skills\

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.

Developing on the server itself? Point at your build instead, so you are not running whatever npx last cached:

claude mcp add --scope user bic-chart-dev -- node c:/Source/PowerBI_Controls/llmchart/mcp/dist/index.mjs

The ready banner prints the build stamp, which is how you tell the two apart.

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

Wire notes

Wire-compatible with the visual/harness envelope (see testharness/harness/client.py, the reference implementation): gzip→base64→. body, FNV X-Signature, clientVersion >= 2.0.0.0, plus host: "SDK" so prompts resolve to the generic host profile once server rev 144 + tokenized config are live (older servers ignore the field — deployment-order safe).

Publishing (when the experiment proves out — NOT yet)

  1. Keep "private": true until the conscious decision to release.
  2. Publish built artifacts only (files: ["dist"] already enforces this — the tarball carries the bundled dist/index.mjs, no source, no history).
  3. npm publish --access public under the org scope; users then configure "command": "npx", "args": ["-y", "@bicharts/chart-mcp"] — zero-install.
  4. List in MCP registries/directories for discoverability.
  5. shape-core rides inside the bundle minified (shared, not shown); the open-source decision for readable source is separate and deferred.