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

draftshelf-mcp

v1.2.3

Published

MCP server giving an AI assistant direct read/write access to a DraftShelf account's resume Library and Versions.

Readme

DraftShelf MCP server

Lets an AI assistant (Claude Code, Claude Desktop, Codex, or any other MCP-compatible client) read and write your DraftShelf account's Library and Versions directly - add bullets, tailor a version for a specific job, export a PDF/DOCX, all through normal conversation instead of clicking through the web app.

Setup

draftshelf-mcp is published on npm - your MCP client fetches it automatically the first time it launches.

  1. Add it to your AI tool.

    Claude Code - one command, no config file to edit by hand:

    claude mcp add draftshelf -s user -- npx -y draftshelf-mcp

    (-s user makes it available in every project, not just the current one; drop it to scope it to the current project instead.)

    Codex CLI - also one command (per OpenAI's own docs):

    codex mcp add draftshelf -- npx -y draftshelf-mcp

    Claude Desktop, or any other MCP client with no CLI - paste this into the client's own MCP config file (check its docs for exactly where that file lives):

    {
      "mcpServers": {
        "draftshelf": {
          "command": "npx",
          "args": ["-y", "draftshelf-mcp"]
        }
      }
    }

    Claude Desktop has no CLI at all today, so manual config is genuinely the only path for it - Anthropic's newer "Desktop Extensions" (.dxt) format (double-click install, no JSON) exists but is a separate packaging effort this project hasn't built, not something skipped by accident.

  2. Restart your AI tool, then use it. The first time it actually launches the server, your browser opens on its own to a real DraftShelf sign-in + consent screen (the same one claude.ai/ ChatGPT use for their own connectors) - sign in there once. The server stores a token at ~/.draftshelf/credentials.json (owner-read-only) and every launch after that is instant, no browser involved. npx -y draftshelf-mcp login/logout also exist as manual commands, for signing in ahead of time or switching accounts, but neither is required.

    npx is also fetching the package itself and, the first time, a real Chromium browser for export_pdf (a few hundred MB - the direct cost of PDF export actually measuring real page layout instead of guessing), so the very first launch takes noticeably longer than every one after it. If your AI tool gives up waiting before you finish signing in in the browser, finish signing in anyway (the server keeps waiting up to 5 minutes) and just ask it to try again - your tool sees the stored credentials immediately on the next attempt.

    The sign-in link itself stays valid for 10 minutes - reopening an old one past that (say, from browser history days later) shows a plain "Connection request expired" screen instead of letting you click through, since it can't complete either way. Just start the connection again (re-run the command above, or ask your AI tool to try again) for a fresh one.

  3. Verify it's working. Ask it "what DraftShelf tools do you have access to?" - it should list things like get_library, add_entry, export_pdf. Then ask it to add one real bullet to a real experience entry, and confirm in the DraftShelf web app (reload the page) that the bullet is actually there. That round trip - a change made in conversation showing up in the real app - is the actual point of this whole setup.

What it can do

37 tools, covering the same ground the web app itself does for tailoring a resume:

  • Read: get_library, get_header, list_tags, list_skill_groups, list_versions, get_version
  • Entries: add_entry, edit_entry, remove_entry, add_bullet, edit_bullet, remove_bullet, update_header (kinds now include publications/certifications, real citation-style entries alongside experience/projects/etc.)
  • Positions (multiple roles under one Experience entry, or multiple sub-entries under one Custom Section heading): add_position, edit_position, remove_position, move_position, convert_entry_to_positions
  • Versions: create_version, duplicate_version, delete_version, restore_version, purge_version, update_version_selection (now also takes excluded_position_ids), fill_version_by_tag, update_version, set_override, clear_override (both now also take an optional position_id to freeze one position's own field)
  • Export: export_docx, export_pdf, get_page_layout (see exactly which section/entry landed on which page, and how full each page is, without exporting a PDF), get_full_export
  • Preferences: get_preferences, update_preferences
  • GitHub backup: get_github_backup_status (read-only), configure_github_backup (always refuses - see below)
  • Cover Letter: generate_cover_letter (drafting inputs only, nothing saved)

What it deliberately can't do

  • Set up GitHub backup. configure_github_backup always refuses and returns the manual setup steps instead. A GitHub personal access token is the single most sensitive secret this app ever handles - it's never allowed to touch an AI tool, only the browser → a locked-down server function → Supabase Vault. If you want backup, do it yourself in Settings → GitHub Manage.
  • Change your password, or manage sign-in. Not exposed at all.
  • Import a JSON file wholesale. There's no import tool - but you don't need one: hand your AI assistant a resume/PDF's text directly and ask it to add specific content via add_entry/add_bullet, or ask it to tailor a specific version. get_full_export covers the export/backup half of what import used to be for.

Using it well

  • Always ask it to check current state first (get_library/get_version) before editing - someone may have changed the same account from the browser since your last message.
  • A "version" is a tailored resume for one real job application. Prefer asking for a duplicate of an existing version over editing one in place, unless you're still drafting it.
  • Deletions require confirmation. remove_entry/remove_bullet/delete_version/ purge_version all need an explicit confirm:true - there's no undo dialog the way the web app has, so your assistant should always check with you in plain language first.
  • export_pdf and get_page_layout can take 10-30 seconds. Both drive a real browser through the live app to guarantee correct pagination - a long pause there is normal, not a hang.
  • Ask it to check get_page_layout before and after trimming content for length, rather than guessing from bullet count alone - it reports the real, measured page each section/entry landed on and how full each page actually is.
  • If a write fails with a conflict error, someone else changed that data since your last read. Ask your assistant to re-fetch and re-apply, not retry blindly.

Every write reports a githubBackup status (not-configured / paused / pushed / failed) if you have GitHub backup connected - your assistant should mention it if it ever comes back failed, the same way the web app's own topbar status dot would.

Disconnecting

Revoke access any time from Settings → Connected Apps in DraftShelf itself - takes effect immediately, no need to remove the config from your AI tool first. The access token this server uses expires within the hour and silently renews itself while you're actively using it; revoking just stops that renewal, so the very next request fails cleanly instead of quietly working forever. npx draftshelf-mcp logout also clears the credentials stored locally at ~/.draftshelf/credentials.json, useful for switching accounts on the same machine.

Architecture notes (for anyone extending this)

  • Every tool except export_pdf and get_page_layout is a straight HTTPS passthrough to the mcp-api Supabase Edge Function, authenticated with the token from your browser sign-in. This process never sees your Supabase session or any secret beyond that token.
  • export_pdf and get_page_layout are the two exceptions: both mint a real, narrowly-scoped session for your account (via mcp-api's internal _mint_session tool, itself gated by that same token) and drive real headless Chromium through the actual live DraftShelf app - the same technique scripts/download_pdf.js already uses in this repo, generalized in export-pdf.js/get-page-layout.js. This is deliberate, not incidental: a server-side "render the resume ourselves" approach can't measure real CSS layout (jsdom, for instance, has no layout engine at all), so it would silently report the wrong page count for every resume. get_page_layout is the lighter of the two - it reads the same window.PAGE_UNIT_MAP/ window.PAGE_FILL_RATIOS the live app's own pagination engine already computes after a normal render, without ever calling window.downloadPdf() or touching pdf-service at all.