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

@thoute/mcp

v0.7.1

Published

Local MCP server for a Thoute vault — pulls ciphertext over the Thoute API and decrypts client-side.

Readme

@thoute/mcp

A local Model Context Protocol server for your Thoute vault. It lets an MCP-aware client (Claude Desktop, Cursor, …) read and write your notes through natural tools: search, fetch, append to today's journal, and summarize recent activity.

How it works (and why it runs locally)

Your Thoute vault is end-to-end encrypted. The cloud only ever stores ciphertext. So this server runs on your machine: it authenticates to the Thoute API with an API key, pulls the encrypted vault, and decrypts it locally with your passphrase. Nothing but the one-time embedding-model download ever leaves your machine. Search (keyword and semantic) runs on-device over the decrypted content, using the same embedding model as the Thoute app.

Prerequisites

  • Node.js 20 or newer.
  • A Thoute API key (thoute_pk_…) created in the app under Settings → Integrations. Give it read:vault (and write:vault if you want the write tools). You can bind it to a single vault.
  • Your vault passphrase.

Install

Nothing to install — your MCP client runs it on demand with npx @thoute/mcp (see below). First run downloads the package and caches it.

Configure your MCP client

Add an entry to your client's MCP config. For Claude Desktop that is claude_desktop_config.json:

{
  "mcpServers": {
    "thoute": {
      "command": "npx",
      "args": ["-y", "@thoute/mcp"],
      "env": {
        "THOUTE_API_KEY": "thoute_pk_xxxxxxxxxxxxxxxx",
        "THOUTE_PASSPHRASE": "your vault passphrase",
        "THOUTE_VAULT_ID": "vault-... (optional if you have one vault)",
        "THOUTE_SERVER_URL": "https://app.thoute.com",
        "THOUTE_MCP_ALLOW_WRITE": "0"
      }
    }
  }
}

Fill in the env values, then restart the client. (To pin a version, use @thoute/[email protected].)

Environment variables

| Variable | Required | Default | Notes | | --- | --- | --- | --- | | THOUTE_API_KEY | yes | | Your thoute_pk_… key. | | THOUTE_PASSPHRASE | yes | | Your vault passphrase (used locally to decrypt). | | THOUTE_VAULT_ID | no | the only vault | Required if the key can reach more than one vault. | | THOUTE_SERVER_URL | no | https://app.thoute.com | Point at a local server for development. | | THOUTE_MCP_ALLOW_WRITE | no | 0 | Set to 1 to enable the write tools — create_block, update_block, append_to_journal, append_to_library, upload_attachment (also needs a write:vault key). |

Tools

Read (always available):

  • search_vault(query, limit?) — hybrid keyword + on-device semantic search.
  • get_block(id) — a block with its page, parent, children, and tags.
  • get_page(id) — a page rendered as a Markdown outline.
  • list_today_journal() — today's daily journal page.
  • summarize_recent(days?) — blocks created or updated recently, grouped by page.
  • due_tasks(asOf?, withinDays?) — open tasks that are overdue or due/scheduled today, grouped (Overdue / Today) and sorted by priority. asOf (ISO YYYY-MM-DD) overrides "today"; withinDays widens the today window for future look-ahead (default 0 = today only).
  • refresh_vault() — re-pull and decrypt from the server.

Write (only when THOUTE_MCP_ALLOW_WRITE=1 and the key has write:vault):

  • append_to_journal(content, type?, date?, status?, priority?, dueDate?, scheduledDate?, scheduledTime?) — append a top-level block to a daily journal page (defaults to today). Creates the journal page if it doesn't exist yet.
  • append_to_library(content, type?, status?, priority?, dueDate?, scheduledDate?, scheduledTime?) — append a top-level block to the Library (the Home outline). Creates the Library page if it doesn't exist yet.
  • create_block(content, parentId? | pageId?, type?, status?, priority?, dueDate?, scheduledDate?, scheduledTime?) — append a block under an existing block or page.
  • update_block(id, content?, status?, priority?, dueDate?, scheduledDate?, scheduledTime?) — update a block's content and/or its scheduling fields (at least one is required).
  • upload_attachment(filePath, parentId? | pageId?, content?) — encrypt and upload a local binary file (PDF, image, Office doc, audio, video, …) and create the typed attachment block that references it. filePath is an absolute path on the machine running the MCP server. Defaults to today's journal when no placement is given; pageId: "home" targets the Library, pageId: "journal-YYYY-MM-DD" a daily page. The file is end-to-end encrypted before upload; searchable text is extracted by the web app the first time the attachment is opened.

Block references

((blockId)) in a block's content is a live link to another block. Reads render it as “label” ((blockId)) — the label is there so the text is readable, but the token is the data. When editing, copy it through unchanged.

This matters because update_block replaces content wholesale and re-derives the block's outbound references from the text it receives. Writing back only the label removes the link from both the content and the reference index, and nothing in the result records what the id was. get_block prints the exact stored text under Raw content; edit against that form.

References to blocks that aren't loaded render as the bare ((blockId)) rather than a placeholder, for the same reason — an unresolved reference is usually just an un-hydrated page, not a dead link.

Scheduling fields

The scheduling fields make full task and agenda management possible over MCP: status (open, in-progress, done, archived, hold, blocked, delegated, dropped), priority (low, medium, high, urgent), dueDate / scheduledDate (ISO YYYY-MM-DD), and scheduledTime (24h HH:mm). Pass an empty string to any date or time to clear it. Setting status to done stamps completion (and moving off done clears it), matching the app.

Despite the names, the dates and times are not task-only — they're valid on any block type, and setting one never changes the type of an existing block. On create, when no explicit type is given, status / priority / dueDate infer type: "task" and a bare scheduledTime infers type: "event".

scheduledTime is what makes a block an agenda item:

create_block(pageId="journal-2026-08-03", type="event", content="QSOS",
             scheduledDate="2026-08-03", scheduledTime="07:30")

renders in the app as 7:30a QSOS with a leading time chip. Two conveniences match the app's own behavior: a time given on a journal page with no scheduledDate takes that day, and a timed root event on a journal page is placed in the day's time order rather than appended, so agenda items stay sorted however they arrive. (Timed events order only against other timed events; notes and untimed blocks stay where they are. Blocks created under a parentId are never reordered.)

append_to_journal, append_to_library, and upload_attachment auto-create their target page (and register it in the vault catalog) when it's missing, so you can write to a fresh day or an empty vault without opening the app first.

Notes

  • The server loads a snapshot of the vault at startup and serves tools from memory. Call refresh_vault to pick up changes made elsewhere.
  • Semantic search downloads a ~22 MB model on first use and caches it (and your block vectors) under ~/.thoute/mcp/. If the model can't load (e.g. offline), search falls back to keyword-only.
  • v1 writes target existing pages only; creating pages (including today's journal) from the server is a planned follow-up.

Develop

npm run typecheck
npm test                                   # crypto unit tests
# integration harnesses (need a local sync-server + Postgres):
DATABASE_URL=… THOUTE_SERVER_URL=http://localhost:3002 npx tsx scripts/it.ts        # read path
DATABASE_URL=… THOUTE_SERVER_URL=http://localhost:3002 npx tsx scripts/it-tools.ts  # MCP tools
DATABASE_URL=… THOUTE_SERVER_URL=http://localhost:3002 npx tsx scripts/it-write.ts  # write tools
npx tsx scripts/it-embed.ts                # semantic ranking (downloads the model)

npm run build                              # tsup → self-contained dist/index.js
MCP_USE_DIST=1 DATABASE_URL=… THOUTE_SERVER_URL=… npx tsx scripts/it-tools.ts  # test the bundle

Publishing (maintainers)

npm run build (tsup) bundles the server and the shared repo files it imports into a single dist/index.js; only dist/ ships (see files in package.json).

Publishing uses Trusted Publishing (GitHub OIDC) — no stored npm token, and npm attaches provenance automatically. The package is live on npm as @thoute/mcp.

To cut a release: bump version in package.json, push a tag mcp-vX.Y.Z, and the mcp-publish workflow publishes via OIDC (the tag must match version). Add a "What's New" entry as needed.

The one-time bootstrap (already done): create the @thoute npm org/scope, do the first publish locally (npm login && npm run build && npm publish — trusted publishing requires the package to already exist), then on npmjs.com → @thoute/mcp → Settings → Trusted Publisher → GitHub Actions register repo jcromwell/thoute, workflow mcp-publish.yml.