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

@markpin/mcp

v0.9.0

Published

MCP server over a Markpin folder: search and read your saved pages, optionally edit them with confirmation

Downloads

2,129

Readme

@markpin/mcp

MCP server for a Markpin folder. Markpin is a Chrome extension that saves web pages and clips as Markdown files in a folder you own — this server lets an AI client (Claude Code, Claude Desktop, Cursor, …) search and read those files, and optionally edit them with your confirmation.

  • Read-only by default. Writes need --allow-write and a confirmation dialog for every change.
  • Runs locally over stdio. Nothing leaves your computer.
  • Watches the folder, so pages you save in the browser show up in the next query without a restart.

Requirements

  • Node.js 20.1 or newer (node -v).
  • The Markpin Chrome extension with storage set to Local folder or Google Drive. With Google Drive you also need Google Drive for Desktop so the folder exists on disk.

Run

npx -y @markpin/mcp --dir "<your Markpin folder>"

Options:

| Flag | Meaning | |---|---| | --dir <path> | Required. The Markpin folder (the one that contains pages/). ~ is expanded. | | --allow-write | Registers the ten write tools. Without it the server is read-only. | | --lang ko\|en\|ja\|es\|pt-BR\|de\|fr | Language of the confirmation dialog. Default: taken from your system locale (pt* → pt-BR), otherwise en. The Markpin extension's setup guide fills this in from your Chrome language. |

On success the server logs serving N pages from <dir> to stderr. stdout carries the MCP protocol, so all logs go to stderr — that line is the quickest way to check the path.

Find your Markpin folder

The folder must contain a pages/ directory. If it doesn't, the extension hasn't uploaded anything there yet — save a page in Chrome first.

Local folder — the folder you picked in Markpin settings.

  • macOS: in Finder, right-click the folder, hold ⌥ Option, choose Copy "…" as Pathname.
  • Windows: Shift + right-click the folder, choose Copy as path (remove the surrounding quotes).

Google Drive — Drive for Desktop mirrors your Drive to disk. The Markpin folder sits at the top of My Drive, whose name follows your Google account language — My Drive (en), 내 드라이브 (ko), マイドライブ (ja), Mi unidad (es), Meu Drive (pt-BR), Meine Ablage (de), Mon Drive (fr):

  • macOS: ~/Library/CloudStorage/GoogleDrive-<your email>/My Drive/Markpin
  • Windows: G:\My Drive\Markpin (the drive letter can differ — check File Explorer)

The Markpin settings page in Chrome has an MCP setup guide button that fills these paths (and --lang) in for you.

Register the server

Replace <dir> with your folder path. Add --allow-write at the end of the arguments if you want the write tools.

Claude Code

claude mcp add -s user markpin -- npx -y @markpin/mcp --dir "<dir>"

-s user registers it for every project; drop the flag to keep it to the current directory only.

Then claude mcp list should show markpin: … - ✓ Connected.

Claude Desktop

Edit the config file (Claude → Settings → Developer → Edit Config):

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

macOS:

{
  "mcpServers": {
    "markpin": {
      "command": "npx",
      "args": ["-y", "@markpin/mcp", "--dir", "<dir>"]
    }
  }
}

Windows (Claude Desktop spawns without a shell, so npx needs cmd /c; escape backslashes in the path):

{
  "mcpServers": {
    "markpin": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@markpin/mcp", "--dir", "G:\\My Drive\\Markpin"]
    }
  }
}

Restart Claude Desktop. The hammer/plug icon in the chat box lists the Markpin tools.

Cursor

Add the same JSON to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project), then enable the server in Cursor Settings → MCP.

File format

Each page is one Markdown file. The frontmatter holds only the human-facing keys (title, url, savedAt, tags, summary, readAt, deletedAt) so note apps such as Obsidian show a clean Properties panel. Everything Markpin needs internally (id, rev, updatedAt, clips with their anchors, bookmark) lives in a one-line JSON block at the very end of the file:

<!-- markpin
{"v":2,"id":"…","rev":3,"updatedAt":"…","domain":"…","clips":[…]}
-->

Do not edit that block by hand. Files written before 0.7.0 (markpin: 1 in the frontmatter) are still read; they are rewritten in the new shape the next time anything changes them.

markpin.json (Markdown template)

The extension writes markpin.json at the folder root when you pick a Markdown template or turn on .trash/ in its options. This server reads it on start and on every rescan, and renders the files it writes with the same template (default or obsidian, or a custom template string), so pages saved through MCP look like the ones saved from the browser. Only the body below the frontmatter changes; the frontmatter is always Markpin's own. Moving deleted files to .trash/ is done by the extension, not by this server.

Read-only vs. --allow-write

Without --allow-write the server exposes four read tools and cannot change any file. With it, ten write tools are added. Every write passes three gates:

  1. The flag. You decided at registration time that writes are allowed at all.
  2. Client permission. The tools are marked non-read-only (delete_pages as destructive), so clients such as Claude Code ask before each call.
  3. Your confirmation. If the client supports MCP elicitation (Claude Code does), the server shows a dialog describing the exact change — for example "Add tag frontend to 'React Docs'?" — and writes only when you accept. If the client cannot show that dialog, the result carries "gate": "client" so the assistant can tell you that the client's own prompt was the only confirmation.

The confirmation waits up to 10 minutes. A save_page fetch happens only after you accept, so a declined URL is never requested.

Tools

Read (always):

| Tool | What it does | |---|---| | search | Full-text search over titles, content, clipped text, notes and tags. Empty query = most recent, optionally filtered by tags. bookmarked: true = only pages with a reading bookmark. | | get_page | One page in full by id or URL: metadata, tags, summary, content, clips with notes and colors, bookmark, file path, image paths. | | list_recent | Most recently updated pages. bookmarked: true = pages with a reading bookmark, newest bookmark first. | | list_tags | Every tag with its page count. |

Write (--allow-write):

| Tool | What it does | |---|---| | save_page | Saves a URL as a new page (fetches and extracts the article unless you pass content). Takes an optional summary (one or two sentences) and tags — the assistant is asked to supply both whenever it has read the page, since Markpin's built-in AI only runs for pages saved from the browser. One page per URL — an existing page is returned unchanged. | | update_tags | Adds and/or removes tags on one or more pages. | | add_clip | Adds a quoted text clip, with an optional note, highlight color (amber, green, blue, pink) and reaction mark kind (question, insight, disagree, star), to a page. | | set_clip_note | Replaces the note on a clip (empty clears it). | | set_summary | Replaces a page's summary (empty clears it). Handy for pages saved without one. | | set_note | Sets the reader's own one-line note on a page (frontmatter note; empty clears it). | | mark_skimmed | Marks a page as skimmed (skimmedAt); removes its bookmark and read mark. | | delete_pages | Marks pages deleted. The Markpin extension keeps them for 30 days and can restore them; this server never deletes files. | | restore_pages | Brings back pages deleted within the last 30 days. | | set_bookmark | Puts the reading bookmark on a page — from the start, or at a quote from the content to resume there. Replaces any existing bookmark and clears the read mark. | | clear_bookmark | Removes the bookmark without marking the page read. | | mark_read | Marks a page as read and removes its bookmark. |

Every write returns a note and a gate field ("elicitation" when you confirmed in the dialog, "client" when only the client's prompt stood between the assistant and the write). update_tags, set_clip_note, set_summary and set_note also return before/after; the others return the affected page(s).

Limits

  • Google Drive + new pages. With Google Drive storage the extension can only read files it created itself (drive.file scope), so save_page writes new pages to inbox.jsonl in your Markpin folder and the extension turns them into page files on its next sync. The extension creates and manages that file — do not delete it. Edits to existing pages are written in place. With a local folder there is normally no inbox and everything is written directly; if an inbox.jsonl exists in the folder (for example a former Drive mirror), the server uses it the same way.
  • No region clips. Image/area clips need the page DOM; the server adds text clips only.
  • Side panel delay. While the side panel is open it polls every 15 seconds, so changes show up within about 30 seconds; when it is closed they show up the moment you open it. A full sync also runs every 5 minutes. With Google Drive, add the time Drive for Desktop needs to upload.
  • Concurrent edits. If the extension wrote the same page after the server read it, the write is refused with Page changed on disk since it was read; re-read it and try again. Ask again.
  • Tombstones. Deleted pages are only purged by the extension. A folder used by this server alone keeps them.

Troubleshooting

| Symptom | Cause / fix | |---|---| | Not a directory: … | Typo in --dir, or Drive for Desktop is not running / the folder is not mirrored. Open the path in Finder or Explorer first. | | serving 0 pages | The folder has no pages/ yet or it is empty. Save a page in Chrome; with Drive wait for the upload. | | Client says the server failed to start | Run node -v (needs 20.1+). On Windows use the cmd /c npx form. Run the npx line in a terminal to see the error. | | Pages saved just now don't appear | The server rescans about 300 ms after a file change. With Drive, the file appears when Drive for Desktop finishes syncing. | | A page saved by the assistant is missing in the side panel | Keep the side panel open for about 30 seconds. With Google Drive, Drive for Desktop must be running so inbox.jsonl reaches Drive. | | Pages are missing after updating the Chrome extension | Files are now written in format v2 (see File format). Servers before 0.7.0 skip them — run npx -y @markpin/mcp@latest or re-register with the current version. | | Write tools missing | You registered without --allow-write. Re-register, then restart the client so it spawns the server again. | | A page saved by the assistant has no summary or tags | The assistant saved it without reading the page. Ask it to write the summary and tags (set_summary, update_tags). | | Not an HTML page / the server cannot fetch a URL | The site blocks bots or needs a login. Ask the assistant to read the page itself and pass content to save_page. | | User declined / No response to the confirmation | You declined the dialog, or it timed out after 10 minutes. Nothing was written. |

Development

yarn build:mcp                 # bundles to mcp-server/dist/index.js
node mcp-server/dist/index.js --dir "<dir>"

License MIT.