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

html-report-server

v1.4.0

Published

MCP server for generating styled HTML reports from structured JSON — stat cards, tables, SVG charts, timelines, and more

Readme

html-report-server

A local MCP server for generating styled HTML reports from structured JSON. Works with Claude Code, Cursor, and any MCP-compatible client.

4 tools to render publication-quality HTML reports — stat cards, tables, SVG charts, timelines, and more — with 80-90% fewer output tokens compared to raw HTML generation.

Why

When an LLM generates HTML reports, it outputs verbose inline styles, SVG paths, and layout markup. This server lets the LLM describe the report as compact JSON blocks, and the server expands them into fully-styled HTML with charts, cards, and professional layouts — all running locally via stdio with no file uploads.

Features

| Category | Tools | |---|---| | Render | render_report — JSON DSL → styled HTML file (one call for an entire report) | | Read | read_report — extract JSON structure from existing report for re-editing | | Edit | edit_report — patch operations (replace, insert, delete blocks) | | Reference | get_component_examples — example JSON for every block type |

Style presets

| Preset | Character | |---|---| | mckinsey | Executive: uppercase headers, thin borders, generous whitespace | | clean | Modern SaaS: subtle shadows, rounded corners, no borders | | minimal | Content-dense: tight spacing, 720px width, no decoration | | dashboard | Data-dense: 1200px width, dark header tables, compact layout |

Block types (25)

| Category | Blocks | |---|---| | Text | section, heading, paragraph, list, callout | | Data | stat_cards, hero_stats, metadata, table, before_after | | Charts | bar_chart, line_chart, pie_chart, progress_bars | | Layout | card_grid, comparison, timeline, steps, badges, divider | | Tables | comparison_matrix — multi-party comparison with badge/tag columns; sectioned_table — multi-section table with subtotals | | Diagrams | diagram — layered architecture diagrams; relationship_graph — node-and-edge graphs (hierarchical/radial/force layout, serif/mono/print modes) | | Escape hatch | html — raw HTML (sanitized) |

Document-level options

  • title — report title (required)
  • subtitle — subtitle below the title
  • badge — badge label next to the title (e.g. "PERFORMANCE REPORT")
  • style — preset name
  • style_overrides — selective overrides for card/table/chart/sectionTitle tokens

Token efficiency

| Component | Raw HTML tokens | JSON DSL tokens | Savings | |---|---|---|---| | Stat card grid (3 cards) | ~350 | ~60 | 83% | | Data table (5×10) | ~600 | ~150 | 75% | | Bar chart (8 bars) | ~800 | ~60 | 92% | | SVG line chart | ~1200 | ~80 | 93% | | Before/after comparison (3 items) | ~900 | ~120 | 87% | | Steps flow (5 steps) | ~500 | ~100 | 80% | | Architecture diagram (4 layers, 16 edges) | ~8000 | ~1500 | 81% | | Full report (30 blocks) | ~13000 | ~1700 | ~87% |

Installation

Claude Code

Add to ~/.claude.json:

{
  "mcpServers": {
    "html-report": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "html-report-server@latest"]
    }
  }
}

Cursor

Add to your MCP server configuration:

{
  "html-report": {
    "command": "npx",
    "args": ["-y", "html-report-server@latest"]
  }
}

Local development

git clone https://github.com/knorq-ai/html-report-server.git
cd html-report-server
npm install
npm run build
npm run dev  # or: node dist/index.js

Usage

render_report

The primary tool. Pass a complete report with title, style preset, and array of block objects:

{
  "file_path": "/tmp/report.html",
  "title": "Q4 Performance Report",
  "subtitle": "Google Sheets → Cloud SQL Migration",
  "badge": "PERFORMANCE REPORT",
  "style": "mckinsey",
  "blocks": [
    { "type": "section", "title": "Key Metrics" },
    {
      "type": "stat_cards",
      "cards": [
        { "label": "Revenue", "value": "$4.2M", "delta": "+15%", "trend": "up" },
        { "label": "Users", "value": "12,847", "delta": "+28%", "trend": "up" }
      ]
    },
    {
      "type": "bar_chart",
      "title": "Monthly Revenue",
      "data": [
        { "label": "Jan", "value": 280 },
        { "label": "Feb", "value": 310 },
        { "label": "Mar", "value": 350 }
      ],
      "unit": "K"
    }
  ]
}

Round-trip editing

1. render_report  → creates report.html
2. read_report    → returns JSON structure + block summary
3. edit_report    → patch operations (replace/insert/delete blocks)

The JSON source is embedded as an HTML comment in the output file, enabling seamless round-trip editing without a separate database.

get_component_examples

Call this tool (no parameters) to get example JSON snippets for every block type. Useful for learning the DSL.

Security

Since this server generates HTML from user input, all output is sanitized:

  • Text content: escaped via escapeHtml() (prevents XSS in all text fields)
  • Inline HTML (paragraph, callout): allowlist-based sanitizer permits only safe formatting tags (b, i, em, strong, a, code, br, span)
  • Raw HTML block: allowlist-based sanitizer permits layout + formatting tags, strips <script>, <iframe>, event handlers, javascript: / data: URIs
  • CSS values (user-supplied colors): sanitized to reject injection characters
  • HTML attributes: auto-escaped in all element builders
  • JSON embedding: --> escaped to prevent HTML comment breakout
  • Sanitizers run in a loop until stable to prevent nested-tag bypass attacks

Architecture

src/
├── index.ts           MCP server + 4 tool definitions
├── html-engine.ts     Public API barrel module
└── engine/
    ├── types.ts       TypeScript types (Block union, presets, DSL)
    ├── errors.ts      Structured error codes
    ├── file-lock.ts   Per-file write serialization
    ├── theme.ts       4 style presets + inline style builder
    ├── html-utils.ts  HTML escaping + sanitization
    ├── charts.ts      SVG bar/line/pie/donut charts
    ├── diagrams.ts    SVG layered architecture diagrams
    ├── graph.ts       SVG relationship graph renderer
    ├── color-utils.ts Shared color utilities for SVG renderers
    ├── components.ts  25 block type renderers
    ├── renderer.ts    Main render loop + block summarizer
    └── html-io.ts     File I/O + JSON comment round-trip

Limitations

  • No JavaScript in output: all <script> tags and event handlers are stripped
  • No external CSS: output uses inline styles only (CSS variables from host)
  • No image insertion: charts are inline SVG, no raster image support
  • No formula recalculation: chart data is static
  • CJK text width: SVG text sizing uses a codepoint-based width heuristic (CJK characters counted as ~1.8× Latin width)

License

MIT