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

@vijayst/invoice-studio

v1.0.0

Published

Invoice Studio — Markdown invoice templates with MCP tools for interactive editing and headless PDF generation

Readme

Invoice Studio

Markdown invoice templates with an MCP server for interactive editing (Claude Desktop / Cursor / Windsurf) and a headless generate pipeline for monthly PDF runs.

Agents: see AGENTS.md for the edit → generate → preview workflow. Registry → PDF → fork: USER-JOURNEY.md.

How it works

Phase 1 — Interactive studio: an AI client connects to the MCP server over stdio. You ask it to tweak the template or styles, regenerate, and inspect the preview PNG until the layout looks right.

Phase 2 — Monthly execution: update src/data/invoice-input.json (or inject it from CI), then run npm run generate to produce output/invoice.pdf and output/preview.png.

src/templates/invoice.md   ← Markdown template ({{placeholders}} for data)
src/styles/invoice.css     ← Print styles
src/data/invoice-input.json
        │
        ▼  npm run generate
output/invoice.md          ← rendered markdown
output/invoice.html
output/invoice.pdf
output/preview.png         ← used by get_invoice_preview

Setup

npm install
npm run build:mcp

Chrome or Chromium is required for PDF/PNG rendering. The generate script finds common install paths (macOS / Linux / Windows). If needed:

export CHROME_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

Generate an invoice (headless)

  1. Edit monthly fields in src/data/invoice-input.json (amounts, dates, line items, etc.).
  2. Optionally adjust layout in src/templates/invoice.md or src/styles/invoice.css.
  3. Run:
npm run generate

Artifacts land in output/.

Use the MCP to edit and generate

1. Build and point your client at the server

npm install
npm run build:mcp   # required — creates dist/index.js

Cursor (recommended): this repo includes .cursor/mcp.json. Open the project folder in Cursor, then reload MCP / the window. It uses ${workspaceFolder}/dist/index.js so the path is always the repo root.

If you configure MCP manually in Cursor Settings, use the absolute path to dist/index.js (relative dist/index.js alone resolves under your home directory and fails):

{
  "mcpServers": {
    "invoice-studio": {
      "command": "node",
      "args": ["/Users/YOU/Documents/invoice/dist/index.js"]
    }
  }
}

Claude Desktop — in claude_desktop_config.json (absolute paths required):

{
  "mcpServers": {
    "invoice-studio": {
      "command": "node",
      "args": ["/Users/YOU/Documents/invoice/dist/index.js"]
    }
  }
}

The server locates the repo from its own script path, so tools always read/write this project even if the client’s cwd is wrong.

Public MCP Registry

Registry name: io.github.vijayst/invoice-studio (npm: @vijayst/invoice-studio). After publish, search the official MCP Registry.

Clients that install from the registry typically run:

{
  "mcpServers": {
    "invoice-studio": {
      "command": "npx",
      "args": ["-y", "@vijayst/invoice-studio"]
    }
  }
}

npx runs a copy of this repo (sample data included). You can generate output/invoice.pdf in that copy, then fork this repo and export the template into the clone.

Full walkthrough: USER-JOURNEY.md.

2. Interactive edit loop

Ask the model something like:

Read src/templates/invoice.md and tighten the payment section. Regenerate and show me the preview.

Typical tool sequence:

| Tool | Purpose | |------|---------| | read_template_file | Read src/templates/invoice.md or src/styles/invoice.css | | write_template_file | Write updated template/CSS | | run_generate_build | Runs npm run generate → PDF + output/preview.png | | get_invoice_preview | Returns the preview PNG for visual review | | get_git_status | Check what changed before committing | | get_workspace_root | Show the npx or clone directory this server is using | | export_studio_to_repo | Copy template/CSS/data from this workspace into a cloned fork |

Repeat edit → generate → preview until satisfied, then commit.

3. Scripts reference

| Script | Command | |--------|---------| | Build MCP | npm run build:mcp | | Start MCP (stdio) | npm run start:mcp | | Generate PDF/PNG | npm run generate |

Project layout

├── smithery.yaml
├── package.json
├── src/
│   ├── templates/invoice.md
│   ├── styles/invoice.css
│   ├── data/invoice-input.json
│   └── mcp/index.ts
├── scripts/generate-invoice.js
└── output/preview.png