virlow-mcp 3.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -0
  3. package/dist/cli.js +2030 -0
  4. package/package.json +46 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Typelets Secure Notes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # virlow-mcp
2
+
3
+ A local [MCP](https://modelcontextprotocol.io) server that gives any MCP-compatible AI
4
+ client (Claude Code, Claude Desktop, Cursor, Codex, and others) durable memory and note
5
+ access backed by [Virlow](https://virlow.com) — with your data end-to-end encrypted the
6
+ entire time.
7
+
8
+ ## What it is
9
+
10
+ virlow-mcp runs on your machine as a local process (`npx -y virlow-mcp`, launched by your
11
+ AI client over stdio). It exposes 19 tools for two things:
12
+
13
+ - **Memories** — short, durable facts ("the user prefers TypeScript", "this repo's CI
14
+ runs on self-hosted runners") that any AI tool can add, search semantically, and recall
15
+ across sessions and projects. Each memory is an ordinary encrypted note in your
16
+ **Memories** folder, so you can read, edit, reorganise, and trash them in the Virlow
17
+ app like anything else you have written.
18
+ - **Notes** — full read/write access to your existing Virlow notes: search, list, read,
19
+ create, update, move, star, archive, and trash, plus folder management.
20
+
21
+ Everything is **end-to-end encrypted, zero-knowledge**: the encryption key is derived
22
+ from your Virlow master password inside this local process and never leaves it. Every
23
+ memory and note is encrypted on your machine before it is sent to the Virlow API — the
24
+ server stores only ciphertext. Decryption happens only in this local process, in memory —
25
+ no decrypted text is ever written to disk.
26
+
27
+ Your account credentials and master password are just as protected from the AI: they are
28
+ entered exclusively into a local browser form served by this process, never passed
29
+ through a tool call, and never seen by the AI model.
30
+
31
+ ## Install / configure
32
+
33
+ virlow-mcp needs no separate install — `npx -y virlow-mcp` fetches and runs it directly.
34
+ Add it to your client's MCP config:
35
+
36
+ ### Claude Code
37
+
38
+ ```
39
+ claude mcp add virlow -- npx -y virlow-mcp
40
+ ```
41
+
42
+ ### Claude Desktop
43
+
44
+ Add to your `claude_desktop_config.json`
45
+ (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`,
46
+ Windows: `%APPDATA%\Claude\claude_desktop_config.json`):
47
+
48
+ ```json
49
+ {
50
+ "mcpServers": {
51
+ "virlow": {
52
+ "command": "npx",
53
+ "args": ["-y", "virlow-mcp"]
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### Cursor
60
+
61
+ Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project-local):
62
+
63
+ ```json
64
+ {
65
+ "mcpServers": {
66
+ "virlow": {
67
+ "command": "npx",
68
+ "args": ["-y", "virlow-mcp"]
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### Codex CLI
75
+
76
+ Codex's MCP config is TOML, not JSON. Add to `~/.codex/config.toml`:
77
+
78
+ ```toml
79
+ [mcp_servers.virlow]
80
+ command = "npx"
81
+ args = ["-y", "virlow-mcp"]
82
+ ```
83
+
84
+ ### Self-hosting Virlow
85
+
86
+ By default virlow-mcp talks to `https://api.virlow.com`. If you run your own Virlow API,
87
+ point it there with an `env` block (JSON clients) or `env` table (Codex's TOML), e.g. for
88
+ Claude Desktop / Cursor:
89
+
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "virlow": {
94
+ "command": "npx",
95
+ "args": ["-y", "virlow-mcp"],
96
+ "env": { "VIRLOW_API_URL": "https://api.your-domain.com" }
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ ## First use
103
+
104
+ 1. Ask your AI client to run the **`unlock`** tool. This opens a browser window pointed
105
+ at a page served by the local virlow-mcp process — sign in with your Virlow account
106
+ email/password (and 2FA code, if enabled) and enter your master password there.
107
+ 2. Once the form succeeds, ask the AI to run **`status`** to confirm the vault is
108
+ unlocked and which account it's unlocked as.
109
+ 3. From then on, `add_memory`, `search_memory`, `search_notes`, and the rest of the tools
110
+ work normally until the vault locks again (see Security notes).
111
+
112
+ ## How memories are stored
113
+
114
+ Memories live in a single folder marked as your memories root — shown with a brain icon
115
+ in the app, and created by this process the first time you add one. Its **subfolders are
116
+ namespaces**: `add_memory` with `namespace: "acme-api"` files the memory under
117
+ `Memories/acme-api`, creating that subfolder if needed. Memories with no namespace sit in
118
+ the root and are visible to every namespace's searches.
119
+
120
+ Each memory is a **code note** holding YAML frontmatter above the fact itself:
121
+
122
+ ```
123
+ ---
124
+ source: claude-code
125
+ tags: [ui, preferences]
126
+ confidence: high
127
+ created: 2026-09-01T00:12:04.000Z
128
+ ---
129
+ Prefers dark mode in every editor, including terminal themes.
130
+ ```
131
+
132
+ The note's title is the memory's label. Because it is a code note, the app opens it in a
133
+ plain text editor rather than the rich-text one, so nothing reformats it behind your back
134
+ and every field is yours to edit.
135
+
136
+ Everything about that is safe to change by hand:
137
+
138
+ - **Edit the fact** and the next search reflects it — the memory re-embeds automatically.
139
+ - **Edit the metadata** and the tools report your values.
140
+ - **Break the YAML** and nothing is lost: the memory is simply read as all fact and no
141
+ metadata, still searchable, and the next `update_memory` rewrites it cleanly.
142
+ - **Drag it to another subfolder** and its namespace follows.
143
+ - **Trash it** and it stops being recalled, recoverable from Trash like any note.
144
+
145
+ Deliberately *not* in the frontmatter: the memory's id, its label, and its namespace.
146
+ Those are the note's id, its title, and the folder it sits in — duplicating them would
147
+ just give you two versions to keep in sync.
148
+
149
+ ## Reaching your vault from a session that is not on this machine
150
+
151
+ By default `virlow-mcp` speaks stdio, so your AI client spawns it as a child
152
+ process and everything stays on one machine. `--http` serves the same 19 tools
153
+ over HTTP instead, so a client that cannot spawn a local process — a cloud
154
+ coding session, another laptop — can reach this vault:
155
+
156
+ ```bash
157
+ npx -y virlow-mcp --http # loopback, random port
158
+ npx -y virlow-mcp --http --port 8787 # pick the port
159
+ ```
160
+
161
+ It prints the URL and the path to a bearer token, generated on first run and
162
+ stored `0600` at `~/.virlow-mcp/http-token`. Every request must carry it:
163
+
164
+ ```
165
+ Authorization: Bearer <token>
166
+ ```
167
+
168
+ **Your vault does not move.** The master key is still derived and held in this
169
+ process on your machine; `unlock` still opens its form in your local browser.
170
+ Virlow's servers still see only ciphertext.
171
+
172
+ **What does change:** decrypted note and memory text now travels over that
173
+ connection to whatever client you point at it. So:
174
+
175
+ - The listener binds `127.0.0.1` by default. `--host` will bind elsewhere and
176
+ warns loudly, because anyone who can reach the port and holds the token can
177
+ read your decrypted notes.
178
+ - To reach it from outside, put your own tunnel in front of it
179
+ (`cloudflared`, `ssh -R`, Tailscale) rather than binding to `0.0.0.0`.
180
+ - Treat the token like a password. Delete the file to rotate it; the next start
181
+ mints a new one.
182
+
183
+ ## Which folders AI tools can see
184
+
185
+ Every folder in the Virlow app has an **"Expose to MCP"** switch — *"Let the
186
+ local AI assistant read & edit this folder and its subfolders. Off by
187
+ default."* This server now honours it. Until this version it did not, so the
188
+ app was telling you something untrue: the switch saved a value that nothing
189
+ ever read.
190
+
191
+ - A folder is visible when **it or any ancestor** is switched on, matching what
192
+ the label promises. Turning a parent on opens everything beneath it.
193
+ - `read_note` respects it too. Knowing a note's id is not consent.
194
+ - The **Memories** folder is exempt — this server creates it and it exists only
195
+ for AI tools.
196
+ - A note in **no folder** is not visible: exposure is granted per folder, and
197
+ nothing has granted it. File it into an exposed folder to include it.
198
+
199
+ **Filtering is never silent.** Any result that withheld something says so, with
200
+ the count and what to do about it:
201
+
202
+ ```
203
+ (4 notes hidden in folders that are not exposed to MCP. Turn on "Expose to MCP"
204
+ in a folder's settings in the Virlow app to include it.)
205
+ ```
206
+
207
+ A shortened list is otherwise indistinguishable from an empty vault, and you
208
+ would have no reason to suspect a setting. Since the switch is off by default,
209
+ expect to see this until you turn some folders on — that is the setting
210
+ working, not a fault.
211
+
212
+ ## Turning memories off
213
+
214
+ Memories are **opt-in**. The switch lives in the Virlow app under
215
+ **Settings → Security → AI memories**, and it is off until you turn it on. With
216
+ it off, every memory tool refuses:
217
+
218
+ ```
219
+ AI memories are switched off for this account. Turn on "AI memories" in
220
+ Settings → Security in the Virlow app to use this tool.
221
+ ```
222
+
223
+ The setting is re-read from your account on **every** memory tool call, never
224
+ cached for the session. Turning it *on* being slow would be an inconvenience;
225
+ turning it *off* being slow would be a privacy control that does not work — you
226
+ would switch it off, keep being recorded, and have no way to tell. If the
227
+ account cannot be reached, the tools refuse rather than assume consent.
228
+
229
+ `--no-memories` additionally starts the server with the five memory tools
230
+ unregistered, so they do not appear in `tools/list` at all:
231
+
232
+ ```bash
233
+ npx -y virlow-mcp --no-memories
234
+ ```
235
+
236
+ Use it when you want a connector that structurally cannot touch memories,
237
+ regardless of the account setting. Notes tools, `unlock`, `lock`, and `status`
238
+ are unaffected either way (14 tools instead of 19).
239
+
240
+ ## Suggested agent rules
241
+
242
+ Drop this into your client's persistent instructions (`.cursorrules`, `CLAUDE.md`,
243
+ Codex's `AGENTS.md`, etc.) so the AI uses memory proactively instead of only when asked:
244
+
245
+ ```
246
+ You have Virlow memory tools. At the start of a task, call search_memory
247
+ with the task topic to recall relevant facts. When you learn a durable
248
+ fact about the user, their preferences, or this project (a decision, a
249
+ convention, a gotcha), store it with add_memory — one concise fact per
250
+ call, a short label describing it, and namespace set to the project name
251
+ for project-specific facts. Do not store secrets, credentials, or
252
+ transient details.
253
+ ```
254
+
255
+ ## Security notes
256
+
257
+ - **What's stored where.** The Virlow API stores only ciphertext: encrypted note titles
258
+ and content, memories included. The plaintext-looking `title`/`content` columns for
259
+ encrypted notes hold a literal `[ENCRYPTED]` placeholder, not your data. No decrypted
260
+ text ever touches disk — decryption happens in this process's memory only, per tool
261
+ call, and is discarded when the vault locks. Folder names are the one exception, and
262
+ always have been: they are stored in the clear, so a namespace name is visible to the
263
+ server even though everything in it is not.
264
+ - **Embedding cache.** Search vectors are cached in `~/.virlow-mcp/cache` so a session
265
+ starts without re-embedding every memory. The file is a single AES-GCM blob under your
266
+ master key — note ids and timestamps included — and its name is a hash of your user id.
267
+ Without your master password it is unreadable, and if it cannot be decrypted (say after
268
+ a password change) it is silently discarded and rebuilt. It holds vectors only, never
269
+ the text they came from.
270
+ - **Credentials never reach the AI.** Login, master password, and any 2FA code are typed
271
+ into the local browser form (served on `127.0.0.1` with a random one-time nonce) and
272
+ go straight from your browser to this process and the Virlow API. No tool call ever
273
+ carries a password, and the AI model never sees one.
274
+ - **Auto-lock.** The vault locks automatically after 4 hours of inactivity, and
275
+ immediately on explicit `lock`. Locking discards the in-memory decryption key and all
276
+ cached memories/notes; any further tool call fails until you `unlock` again. An
277
+ operation still in flight when the vault locks cannot write its results back in
278
+ afterwards.
279
+ - **Model download.** Semantic search over memories runs a small, public embedding
280
+ model (`Xenova/all-MiniLM-L6-v2`, ~30MB of open ONNX weights, pinned to a fixed
281
+ revision) entirely locally via `@huggingface/transformers`. It downloads once, on the
282
+ first memory-tool call, into `~/.virlow-mcp/models`, and is reused after that. This
283
+ model only ever processes your already-decrypted plaintext locally to produce a
284
+ vector — it sends nothing anywhere.
285
+ - **Dedupe.** `add_memory` compares the new fact's embedding against existing memories
286
+ in the same scope (same namespace, or global). At cosine similarity ≥ 0.9 it updates
287
+ the closest match in place instead of creating a duplicate, carrying that memory's
288
+ existing metadata and creation date forward. Between 0.7 and 0.9 it stores the new
289
+ memory and tells the agent which existing ones it resembles. Only the label and the
290
+ fact are embedded — never the frontmatter, which is near-identical across every memory
291
+ and would otherwise distort these thresholds.
292
+ - **Hidden notes.** Hidden notes never appear in `list_notes`/`search_notes` results; they
293
+ can still be read by exact id with `read_note`.