@safekb/mcp 0.9.1 → 0.10.0

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 (3) hide show
  1. package/README.md +48 -45
  2. package/dist/safekb-mcp.js +305 -466
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -107,10 +107,8 @@ every tool that keeps a key this way; see [Where secrets are kept](#where-secret
107
107
  | `--rotate-key <ref>` | | Replace a seal root's secret with a new generated key; takes `--store`. |
108
108
  | `--move-key <ref>` | | Move a seal root's current key to `--store system\|file`. |
109
109
  | `--delete-key <ref>` | | Remove a seal root's keys from this machine, after a typed confirmation. |
110
- | `--auto-unlock <ref>\|all` | | With `--set on\|off`: let the sealed tools unlock this root (or every root) by themselves. See [Unlocking automatically](#unlocking-automatically). |
111
110
  | `--export <file>` | | Write what this token reaches to a new passphrase-protected file. Takes `--space`, `--doc`, `--compress`, `--skip-locked`. See [Export and import](#export-and-import). |
112
111
  | `--import <file>` | | Create what such a file holds in this token's account, as new things. Takes `--into-space`, `--store`, `--keys`. |
113
- | | `SAFEKB_SEALED_IDLE_TTL` | Seconds an unlocked seal root may stay idle. Default 900. `unlock_sealed` can set it per root with `idle_ttl_seconds` (60 to 3600). |
114
112
  | | `SAFEKB_HOSTED_TIMEOUT` | Seconds a hosted tool call may take. Default 300. |
115
113
  | | `SAFEKB_MCP_NO_BROWSER` | Set to anything: never start a browser, only show the authorize link. |
116
114
 
@@ -134,15 +132,17 @@ Its secret is a generated key or a passphrase.
134
132
  - `create_sealed_folder` / `insert_sealed_document` with `store` or `key_out_path` make a new seal root
135
133
  and keep its secret on this machine. The secret is never returned to the model.
136
134
  **Back it up: a lost secret cannot be recovered.**
137
- - `unlock_sealed` with only `root_id` takes the secret from the store that has it; `secret_file` reads
138
- it from a file.
139
- - Then `search_sealed`, `list_sealed`, `read_sealed_document`, `get_sealed_section`,
135
+ - There is no unlock step. Every sealed tool opens the seal root it needs by itself, with the secret
136
+ the one local store that has it keeps (system keyring, key file directory, or the sidecar), and the
137
+ root's keys stay in the client's memory until the process ends. **Any session on this machine that
138
+ uses these key stores can read every root whose secret is kept here.** See
139
+ [Opening seal roots](#opening-seal-roots).
140
+ - `search_sealed`, `list_sealed`, `read_sealed_document`, `get_sealed_section`,
140
141
  `update_sealed_document`, `replace_in_sealed_document`, and the move, archive, delete,
141
142
  attachment and deposit tools.
142
143
  - `seal_document` and `unseal_document` move a document between hosted and sealed form; see
143
144
  [Moving documents in and out of a seal root](#moving-documents-in-and-out-of-a-seal-root).
144
145
  `unseal_document` is not a backup: see [Export and import](#export-and-import).
145
- - `lock_sealed`, the idle timeout, or the end of the process forget the keys.
146
146
  - `change_seal_password` replaces the root's secret. Once the server has taken the new one, the
147
147
  superseded key is removed from the store that kept it (the system keyring, or any key file in the
148
148
  key file directory). A superseded passphrase, or a key file you had written elsewhere with
@@ -188,8 +188,9 @@ conversation.
188
188
  ## Where secrets are kept
189
189
 
190
190
  Every seal root has its own secret, and each can be kept in a different place. All three work side by
191
- side: `unlock_sealed` with only `root_id` asks each store and uses the one that has the secret. If two
192
- have it, it stops and asks for `store`.
191
+ side: a sealed tool asks each store and uses the one that has the secret. If two have it, the tool
192
+ fails and names them: `provide_seal_secret` with `store` says which one to use, `move_seal_key` leaves
193
+ one copy.
193
194
 
194
195
  | `store` | What is kept | Where | At rest |
195
196
  | --- | --- | --- | --- |
@@ -207,6 +208,14 @@ Secret Service (GNOME Keyring, KWallet, KeePassXC); the kernel keyring is never
207
208
  forgets its content at logout. Where it does not work, keys are kept as files in `keys/` next to the
208
209
  token file: readable only by your user, but not encrypted on disk. The client tells you when it does this. Keys are kept there with [`@napi-rs/keyring`](https://github.com/Brooooooklyn/keyring-node).
209
210
 
211
+ A locked keyring does not answer until it is unlocked. On Linux it waits for an unlock dialog on the
212
+ machine's own screen, which nobody sees over SSH or after an autologin that typed no password. Every
213
+ keyring call is therefore given up after 10 seconds. When the choice is being made, that counts as no
214
+ keyring: keys go to files, and you are told why. Later, the call that waited fails with "The system
215
+ keyring did not answer". Unlock the keyring at the machine (log in at the desktop, or unlock it in
216
+ your keyring manager) and try again; after unlocking, `--configure` can choose the system keyring
217
+ again.
218
+
210
219
  ### The sidecar
211
220
 
212
221
  The sidecar keeps passphrases out of files, out of the keyring and out of the conversation. Run it in
@@ -225,8 +234,7 @@ npx -y @safekb/mcp --sidecar
225
234
  the tool call waits.
226
235
  - With `--confirm` it asks for your approval before every release of a secret.
227
236
  - The [key tools](#the-key-tools) and the backup tools ask here for the passphrase of a file, for
228
- the name or id that confirms a deletion, and for the confirmation that turns auto-unlock on. Such a
229
- passphrase is used for that one call and not held. An empty entry declines.
237
+ the name or id that confirms a deletion. Such a passphrase is used for that one call and not held. An empty entry declines.
230
238
  - The sidecar and the MCP client must be the same version of `@safekb/mcp`.
231
239
 
232
240
  Several roots can be held at once, each with its own passphrase and time. The sidecar listens on a Unix
@@ -236,20 +244,20 @@ ask it for a held secret, which is what `--confirm` is for.
236
244
  ### Names of seal roots
237
245
 
238
246
  The server cannot read the name of a sealed folder, and an id like `6acdb031893533e0ae1f5456` is no
239
- name to type. So the client remembers the name of every seal root it creates or unlocks, in
247
+ name to type. So the client remembers the name of every seal root it creates or opens, in
240
248
  `roots.json` next to the token file (mode 0600), and follows a rename or a delete. The sidecar, the
241
249
  key export and the key modes show a root as `"Tax papers" (6acd…)`, and the name is taken wherever a
242
250
  seal root's id is: at the sidecar, in the key modes, and in the `root_id` of the MCP tools.
243
251
 
244
252
  - The names are in plaintext in that file: readable on this machine by programs running as you,
245
- never by the server. Delete the file to forget them; they come back as roots are unlocked.
246
- - The client never puts a name into a tool result, so unlocking a root does not tell the model what
253
+ never by the server. Delete the file to forget them; they come back as roots are opened.
254
+ - The client never puts a name into a tool result, so opening a root does not tell the model what
247
255
  it is called. An error repeats only the name the caller passed.
248
256
  - A name stays a usable handle: creating or renaming a seal root is refused when the name has the
249
257
  shape of an id (24 hex characters), or when another root known on this machine already has it.
250
258
  - Text with the shape of an id always means the root with that id. A root that got such a title
251
- elsewhere is not given a name here when it is unlocked or its key is imported: use its id.
252
- - Two roots can still share a name when both were named elsewhere and then unlocked or imported
259
+ elsewhere is not given a name here when it is opened or its key is imported: use its id.
260
+ - Two roots can still share a name when both were named elsewhere and then opened or imported
253
261
  here. Such a name stands for neither and is refused as ambiguous: use the id. Such a root can
254
262
  still be changed while its name stays the same.
255
263
 
@@ -297,41 +305,34 @@ A seal root is given by its [name](#names-of-seal-roots) or its id.
297
305
  When a step after the point of no return fails (the superseded key cannot be removed after a rotation,
298
306
  the old copy cannot be removed after a move), the command fails and says where the key now is.
299
307
 
300
- ### Unlocking automatically
308
+ ### Opening seal roots
301
309
 
302
- ```sh
303
- npx -y @safekb/mcp --auto-unlock "Bank" --set on # or a root id
304
- npx -y @safekb/mcp --auto-unlock all --set on # every root without a setting of its own
305
- npx -y @safekb/mcp --auto-unlock "Bank" --set off
306
- ```
310
+ A sealed tool that needs a seal root this process does not hold yet opens it from the local stores,
311
+ and keeps its keys in memory until the process ends. Nothing is asked and nothing has to be turned on.
307
312
 
308
- A sealed tool that needs a locked root it is allowed to open unlocks it by itself, as `unlock_sealed`
309
- with only `root_id` would, with the same idle timeout, and goes on. **The trade-off: any session that
310
- uses this token on this machine can then read such a root without unlocking it first.**
311
-
312
- - Only a key kept in the system keyring or the key file directory is used. A root opened by a
313
- passphrase never unlocks by itself: turning it on for one is refused, and with `all` such a root
314
- stays locked and says so.
315
- - A root's own setting wins over `all`. The settings are in `auto-unlock.json` next to the token file
316
- (mode 0600), read on every use: a change applies to a running client at once.
317
- - A failed automatic unlock (no key, a key in both stores) is the tool's error; nothing is guessed.
318
- Without the setting a locked root stays the usual "call unlock_sealed first" error.
319
- - `--list-keys` adds `unlocks automatically` to a current key whose root does; `list_sealed`,
320
- `list_seal_keys` and `get_auto_unlock` show `auto_unlock`.
321
- - `set_auto_unlock` turns it on only after you type the root's name or id (or `all`) at the sidecar:
322
- the model cannot widen access on its own. Turning it off needs no confirmation.
313
+ - Since 0.10.0 there is no `unlock_sealed`, `lock_sealed`, idle timeout (`SAFEKB_SEALED_IDLE_TTL`,
314
+ `idle_ttl_seconds`), `--auto-unlock`, `get_auto_unlock` or `set_auto_unlock`. An `auto-unlock.json`
315
+ left next to the token file is not read; delete it.
316
+ - A root opened by a passphrase opens once you have typed the passphrase at the
317
+ [sidecar](#the-sidecar) (`add <name or id>`). The secret leaves the sidecar when its time is up,
318
+ but a client that already opened the root keeps it open until it ends.
319
+ - A root whose secret no store holds fails with an error that says how to supply it: type it at the
320
+ sidecar and repeat the call, or give a key file or a file holding only the secret with
321
+ `provide_seal_secret` (`secret_file`). Nothing is guessed: a secret found in two stores is an
322
+ error too.
323
+ - To stop a session from reading a root, end the client, or remove the root's key from this machine
324
+ (`--move-key` it elsewhere, or `--delete-key`).
323
325
 
324
326
  ### The key tools
325
327
 
326
328
  Everything above is also an MCP tool, and none of them takes or returns a secret: `list_seal_keys`,
327
329
  `rename_seal_key`, `rotate_seal_key`, `move_seal_key`, `delete_seal_key`, `export_seal_keys`,
328
- `import_seal_keys`, `get_auto_unlock` and `set_auto_unlock`, and for backups `export_backup` and
330
+ and `import_seal_keys`, and for backups `export_backup` and
329
331
  `import_backup` (see [Export and import](#export-and-import)).
330
332
 
331
333
  What you type at the terminal for the command line, you type at the [sidecar](#the-sidecar) for a
332
334
  tool, while the call waits: the passphrase of an export file or a key export (twice for a new one),
333
- the name or id that confirms `delete_seal_key`, and the confirmation that turns auto-unlock on. It
334
- reaches this client only, never the conversation. Without a running sidecar such a tool fails and says
335
+ and the name or id that confirms `delete_seal_key`. It reaches this client only, never the conversation. Without a running sidecar such a tool fails and says
335
336
  to start one (`safekb-mcp --sidecar`); on Windows, which has no sidecar, it names the command to run
336
337
  instead. File paths given to the tools must be absolute.
337
338
 
@@ -364,9 +365,9 @@ sealed custom fields are encrypted on your machine; its title, username, url, ta
364
365
  custom fields and the key name of every custom field (sealed ones too) stay readable by the server, so the standard `search_credentials`, `list_credentials` and
365
366
  `find_credential_duplicates` keep working. Never put a secret into `notes`.
366
367
 
367
- - `insert_sealed_credential`, `update_sealed_credential`, `delete_sealed_credential`: signed by the unlocked root.
368
- - `move_sealed_credential` hands a credential to another seal root of its space; both roots must be
369
- unlocked. A sealed credential changes space only with its root: moving the root's folder to another
368
+ - `insert_sealed_credential`, `update_sealed_credential`, `delete_sealed_credential`: signed by the credential's seal root.
369
+ - `move_sealed_credential` hands a credential to another seal root of its space; both roots must
370
+ open here. A sealed credential changes space only with its root: moving the root's folder to another
370
371
  space takes its credentials along (a credential's group in the old space is left behind).
371
372
  - `reveal_sealed_credential` and `get_sealed_totp` decrypt locally. The hosted `reveal_credential` and
372
373
  `get_credential_totp` cannot open a sealed credential.
@@ -379,7 +380,7 @@ custom fields and the key name of every custom field (sealed ones too) stay read
379
380
  sealed one; `in_other_spaces` counts those that need a seal root of their own space. It is
380
381
  irreversible per credential: the server drops its own encrypted secrets and that credential's history.
381
382
 
382
- 1. Unlock the target root, then run it with `dry_run: true` (the default). Nothing changes. It lists the
383
+ 1. Run it with `dry_run: true` (the default). Nothing changes. It lists the
383
384
  credentials, says which have notes, and flags notes that match a few secret patterns. That scan is
384
385
  advisory and misses secrets.
385
386
  2. Decide every note, because today notes are encrypted and afterwards they are either sealed or
@@ -473,8 +474,10 @@ there. Merged tasks are left out.
473
474
  - Whatever a tool returns enters the local conversation transcript and is sent to the model provider.
474
475
  The same holds for a secret passed as text; use a store or `secret_file`.
475
476
  - A program running as your user can read a key file, ask the system keyring or the sidecar for a
476
- secret, and read the memory of this client while a root is unlocked.
477
- - A session that has unlocked a root can be tricked by content it reads into copying it elsewhere.
477
+ secret, and read the memory of this client while it holds a root open.
478
+ - Every session on this machine that uses these key stores can read every root whose secret is kept
479
+ here: there is no unlock step that would stop it.
480
+ - A session can be tricked by content it reads into copying sealed content elsewhere.
478
481
  - An export file: it holds the sealed content of every root that opened under the passphrase of the
479
482
  file, not under its seal roots.
480
483
  - A compromised local machine, or a malicious server serving stale data.