@thoute/mcp
v0.4.0
Published
Local MCP server for a Thoute vault — pulls ciphertext over the Thoute API and decrypts client-side.
Downloads
58
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 itread:vault(andwrite:vaultif 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.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?)— 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?)— 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?)— append a block under an existing block or page.update_block(id, content?, status?, priority?, dueDate?, scheduledDate?)— update a block's content and/or its task fields (at least one is required).
The task fields make full task management possible over MCP: status (open, in-progress, done, archived, hold, blocked, delegated, dropped), priority (low, medium, high, urgent), and dueDate / scheduledDate (ISO YYYY-MM-DD; pass an empty string to clear). Setting any of them on create infers type: "task" when no type is given. Setting status to done stamps completion (and moving off done clears it), matching the app.
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.filePathis 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.
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_vaultto 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 bundlePublishing (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.
