{
  "markdown": "<p align=\"center\">\n  <a href=\"https://blueprintchart.com\" align=\"center\">\n    <img src=\"https://raw.githubusercontent.com/blueprint-chart/blueprint-chart/main/packages/editor/src/assets/images/blueprint-chart-logo.svg\" width=\"120\" alt=\"blueprint-chart\">\n  </a>\n</p>\n<p align=\"center\"><strong>Model Context Protocol server for authoring Blueprint Chart <code>.bpc</code> files with LLMs, grounded in real dataviz pedagogy with a tight parse + render feedback loop. An open, plain-text chart format an AI can write and any browser can render. Self-contained, no backend, no account required.</strong></p>\n\n<div align=\"center\">\n\n|      | Status |\n| ---: | :--- |\n| **CI checks** | [![Github Actions](https://img.shields.io/github/actions/workflow/status/blueprint-chart/mcp/ci.yml?style=flat-square)](https://github.com/blueprint-chart/mcp/actions/workflows/ci.yml) |\n| **Latest version** | [![Latest version](https://img.shields.io/npm/v/@blueprint-chart/mcp?style=flat-square&color=success)](https://www.npmjs.com/package/@blueprint-chart/mcp) |\n|   **Release date** | [![Release date](https://img.shields.io/github/release-date/blueprint-chart/mcp?style=flat-square&color=success)](https://github.com/blueprint-chart/mcp/releases/latest) |\n|    **Open issues** | [![Open issues](https://img.shields.io/github/issues/blueprint-chart/mcp?style=flat-square&color=success)](https://github.com/blueprint-chart/mcp/issues/) |\n|  **Websites** | [![Editor](https://img.shields.io/badge/Editor-2563A0?style=flat-square)](https://blueprintchart.com) [![Docs](https://img.shields.io/badge/Docs-2563A0?style=flat-square)](https://docs.blueprintchart.com) |\n|    **Smithery** | [![smithery badge](https://smithery.ai/badge/blueprint-chart/remote)](https://smithery.ai/servers/blueprint-chart/remote) |\n\n</div>\n\nThe MCP exposes Blueprint Chart's dataviz handbook, DSL grammar reference, chart-type docs, and canonical samples as MCP resources, plus eleven deterministic tools: `validate_dsl`, `inspect_dsl`, `recommend_chart_type`, `render`, `list_chart_types`, `describe_chart_type`, `get_example`, `get_grammar`, `export_chart`, `search_examples`, and `list_palettes`. Your LLM writes the `.bpc`; the MCP grounds it in real dataviz pedagogy and gives it a tight feedback loop.\n\n## Install\n\n```bash\nnpx @blueprint-chart/mcp           # stdio (for Claude Desktop, Claude Code, Cursor)\nnpx @blueprint-chart/mcp --http    # HTTP/SSE on 127.0.0.1:4321\n```\n\n## Use with Claude Desktop\n\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"blueprint-chart\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@blueprint-chart/mcp\"]\n    }\n  }\n}\n```\n\n## Use with Claude Code\n\n```bash\nclaude mcp add blueprint-chart \\\n  -e BLUEPRINT_CHART_EDITOR_URL=https://blueprintchart.com \\\n  -e BLUEPRINT_CHART_DOCS_URL=https://docs.blueprintchart.com \\\n  -- npx -y @blueprint-chart/mcp\n```\n\n## Tools\n\n| Tool | Purpose |\n| --- | --- |\n| `validate_dsl` | Parse `.bpc`; returns `{ valid, errors[], warnings[] }` — each error has `code`, `message`, `suggestion` |\n| `inspect_dsl` | Parse and summarize: `chartType`, `scenes`, `seriesCount`, `rowCount`, `hasHighlights`, `hasColorizes`, etc. |\n| `recommend_chart_type` | Rank chart types for a given column shape and row count |\n| `render` | Render to SVG (default), PNG, or HTML; with `format:\"png\"` returns an inline image both you and the user can see. Always returns structured frame metadata. When `MCP_PUBLIC_URL` is set, includes `urls` (`{png,svg,bpc}`) — stateless links where the chart data travels inside the URL. Set `modelVisible:false` to drop the inline image from the response entirely, spending no image tokens. Pass `save:<path>` to write the output to disk (requires `MCP_FS_WRITE_DIR`; writes are confined to that directory). Width/height capped at 1600; PNG is 2× retina. |\n| `list_chart_types` | List all renderable chart types (tool equivalent of `bpc://handbook/choosing`) |\n| `describe_chart_type` | Properties, when-to-use, when-NOT-to-use, and data-shape for one chart type (tool equivalent of `bpc://chart-types/{slug}`) |\n| `get_example` | Fetch a canonical `.bpc` sample by chart type or sample name (tool equivalent of `bpc://samples/{id}`) |\n| `search_examples` | Find canonical examples by topic keywords and/or chart type (returns pointers; fetch full DSL with `get_example`) |\n| `get_grammar` | Full DSL syntax reference (tool equivalent of `bpc://grammar`) |\n| `list_palettes` | List named colour palettes with hex colours for `colorPalette` |\n| `export_chart` | Validate a `.bpc` and return shareable URLs plus an inline preview. Returns `{ copyUrl, embedUrl, urls?, frame }` — `copyUrl` is editable in the editor, `embedUrl` is a read-only iframe target, `urls.{png,svg,bpc}` are stateless rendered/source links (when `MCP_PUBLIC_URL` is set). Set `modelVisible:false` to drop the inline preview from the response entirely, spending no image tokens. Requires `BLUEPRINT_CHART_EDITOR_URL`; preview failures never block the export. |\n\nThe discovery tools (`list_chart_types`, `describe_chart_type`, `get_example`, `search_examples`, `get_grammar`, `list_palettes`) let clients without MCP resource support access the same reference material that the `bpc://` URIs expose.\n\n### Saving rendered output\n\nThe `render` tool can write its output to disk via `save: <path>`. This is disabled by default. Set `MCP_FS_WRITE_DIR` to a directory to enable it — ideally an absolute path; a relative value is resolved from the server's working directory at startup. Every write lands inside that directory (a sandbox), so you never have to worry about where a client puts files: relative `save` paths are joined to it, an absolute path already inside it is used as-is, and any other absolute path is re-anchored under it (the leading slash is stripped and the rest joined on, so `save: \"/tmp/foo.png\"` becomes `<dir>/tmp/foo.png`). Only paths that still escape via `../` traversal are rejected. Missing subdirectories are created automatically. Containment is checked lexically (no `realpath`), so a symlink whose lexical path is inside the sandbox still passes the check and is then resolved by the OS at write time — if its target is outside the sandbox, the write reaches it. Avoid placing symlinks in the sandbox if isolation matters to you.\n\nAdd the `-e` flag to your `claude mcp add` command:\n\n```bash\nclaude mcp add blueprint-chart \\\n  -e MCP_FS_WRITE_DIR=/path/to/output \\\n  -- npx -y @blueprint-chart/mcp\n```\n\n## Resources\n\n- `bpc://grammar` — full DSL syntax reference\n- `bpc://handbook/<slug>` — dataviz pedagogy (choosing, design-principles, color, typography, annotations, accessibility, ...)\n- `bpc://guide/<slug>` — usage guides (scenes, palettes, data-transforms, ...)\n- `bpc://chart-types/<slug>` — per-chart-type docs\n- `bpc://samples/<id>` — canonical `.bpc` examples\n- `bpc://reference/dsl/<slug>`, `bpc://reference/api/<slug>` — full reference\n\n## Prompts\n\n- `author_chart` — primes the LLM end-to-end (read → write → validate → render → iterate)\n\n## Examples\n\n### Quickstart with Claude\n\nOnce the MCP is connected, ask Claude to make a chart:\n\n> **You:** Make a horizontal bar chart of English letter frequencies — top 10, highlight E.\n>\n> **Claude:** *(calls `list_chart_types`, `get_example({ chartType: \"bar-horizontal\" })`, writes the `.bpc`, calls `validate_dsl` to confirm it parses, calls `render` with `format: 'png'` and shows you the image and the source)*\n>\n> Here's the chart:\n>\n> ![image]\n>\n> ```\n> chart bar-horizontal {\n>   title = \"E is the most frequent letter in English\"\n>   sort = descending\n>   valueLabels = true\n>   highlight \"E\"\n>   data { \"E\" = 12.70; \"T\" = 9.06; \"A\" = 8.17; ... }\n> }\n> ```\n\nThe MCP grounds Claude in real dataviz pedagogy (the handbook) before it writes a single line of DSL, then closes the loop with deterministic parse + render feedback.\n\n### What `.bpc` looks like\n\n```text\nchart bar-vertical {\n  title = \"E is the most frequent letter in English\"\n  description = \"How often each letter appears in typical English text\"\n  source = \"Lewand, Cryptological Mathematics\"\n  colorPalette = \"London\"\n  sort = descending\n  valueLabels = true\n  highlight \"E\"\n\n  data {\n    \"E\" = 12.70\n    \"T\" = 9.06\n    \"A\" = 8.17\n    \"O\" = 7.51\n    ...\n  }\n}\n```\n\nFull grammar at `bpc://grammar`; 17 canonical samples at `bpc://samples/<id>` (`letter-frequency`, `co2-emissions`, `quarterly-revenue`, `browser-market`, `temperature-anomaly`, `population-stacked-bar`, ...).\n\n### `validate_dsl` — parse with structured diagnostics\n\nRequest:\n\n```json\n{\n  \"name\": \"validate_dsl\",\n  \"arguments\": { \"source\": \"chart bar-vertical {\\n  title = \\\"oops\\n}\" }\n}\n```\n\nResponse — `valid` is false; each entry in `errors[]` carries a `code`, human-readable `message`, and an actionable `suggestion`:\n\n```json\n{\n  \"valid\": false,\n  \"errors\": [\n    {\n      \"code\": \"E_PARSE\",\n      \"message\": \"Expected \\\"\\\\\\\"\\\" but end of input found.\",\n      \"suggestion\": \"Close the string literal on line 2.\"\n    }\n  ],\n  \"warnings\": []\n}\n```\n\n### `inspect_dsl` — structured summary\n\nRequest:\n\n```json\n{ \"name\": \"inspect_dsl\", \"arguments\": { \"source\": \"<.bpc source>\" } }\n```\n\nResponse:\n\n```json\n{\n  \"ok\": true,\n  \"data\": {\n    \"chartType\": \"bar-vertical\",\n    \"scenes\": [{ \"index\": 1, \"hasTransition\": false }],\n    \"hasAnnotations\": false,\n    \"hasColorizes\": false,\n    \"hasHighlights\": true,\n    \"hasAreaFills\": false,\n    \"seriesCount\": 0,\n    \"rowCount\": 26\n  }\n}\n```\n\n### `recommend_chart_type` — ranked suggestions\n\nRequest:\n\n```json\n{\n  \"name\": \"recommend_chart_type\",\n  \"arguments\": { \"columnTypes\": [\"date\", \"number\", \"number\", \"number\"], \"rowCount\": 24 }\n}\n```\n\nResponse:\n\n```json\n{\n  \"ok\": true,\n  \"data\": {\n    \"recommendations\": [\n      { \"chartType\": \"line-multi\", \"label\": \"Multi-Line Chart\", \"fitness\": \"best\",\n        \"reason\": \"1 date + 3 numeric columns — compare trends\" },\n      { \"chartType\": \"bar-multi\",  \"label\": \"Grouped Bar Chart\", \"fitness\": \"alternative\",\n        \"reason\": \"Can also show as grouped bars\" }\n    ]\n  }\n}\n```\n\n### `render` — SVG (default), PNG, or HTML\n\nRequest:\n\n```json\n{\n  \"name\": \"render\",\n  \"arguments\": { \"source\": \"<.bpc source>\", \"format\": \"png\", \"width\": 800, \"height\": 500 }\n}\n```\n\nResponse:\n\n```json\n{\n  \"ok\": true,\n  \"data\": {\n    \"svg\": \"<svg ...>...</svg>\",\n    \"png\": \"<base64-encoded image>\",\n    \"mimeType\": \"image/png\",\n    \"urls\": {\n      \"png\": \"https://mcp.blueprintchart.com/render.png?bpc64=…\",\n      \"svg\": \"https://mcp.blueprintchart.com/render.svg?bpc64=…\",\n      \"bpc\": \"https://mcp.blueprintchart.com/render.bpc?bpc64=…\"\n    }\n  }\n}\n```\n\nThe `urls` field is only present when `MCP_PUBLIC_URL` is configured; every `render` and `export_chart` response then includes these stateless links, with the chart data travelling inside the URL (as `bpc64`, a URL-safe base64 encoding of the `.bpc` source) — no session, no server state required. Set `modelVisible:false` in the request to drop the inline image from the response entirely, spending no image tokens.\n\nIf rasterization fails (rare), `errors[]` is non-empty — each entry has a `code` (`\"E_RENDER\"`) and a `suggestion` — **and the response still includes** the SVG that was successfully produced, so partial success is preserved.\n\n#### Hosted render URLs\n\nEmbed a chart directly in a page:\n\n```html\n<img src=\"https://<your-mcp-host>/render.png?bpc64=<bpc64value>&width=800&height=500\" alt=\"My chart\" width=\"800\" height=\"500\">\n```\n\n`/render.bpc` serves the raw `.bpc` source — it's \"view source\" for any chart URL, handy for sharing or reproducing a chart from its link alone.\n\nSources whose encoding exceeds 8 KB return `413` from the endpoints (and the tool omits `urls`, returning `urlsOmitted: \"source-too-large\"` instead) — use the inline PNG for very large charts.\n\n### Reading a resource\n\n```json\n{ \"uri\": \"bpc://handbook/choosing\" }\n```\n\nReturns the full Markdown of the \"Choosing the Right Chart\" handbook page (same content as `docs.blueprintchart.com`).\n\n```json\n{ \"uri\": \"bpc://samples/letter-frequency\" }\n```\n\nReturns the raw `.bpc` source for the letter-frequency sample as `text/plain` — exactly what the LLM should imitate.\n\n## License\n\nMIT\n",
  "bytes": 12151,
  "sha": "47c793b877da0c77bae4a1966489edc369e3b38d58f61bfebcf24a247b08fb85",
  "repo_slug": "blueprint-chart/mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_blueprint_chart_mcp_2a1e551f/readme"
}