@safekb/mcp 0.6.0 → 0.8.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 +80 -15
  2. package/dist/safekb-mcp.js +19619 -18462
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -94,7 +94,7 @@ every tool that keeps a key this way; see [Where secrets are kept](#where-secret
94
94
  | `--url <api url>` | `KB_API_URL` | API base URL. Otherwise the URL in the token file, or `https://api.safekb.com` when authorizing. When serving, it must have the origin the token was issued for: the token is never sent anywhere else. |
95
95
  | `--config <path>` | `SAFEKB_MCP_CONFIG` | Token file. Default `~/.config/safekb/mcp.json`. Use one per project for per-project access. |
96
96
  | `--keyring <dir>` | `SAFEKB_SEALED_KEYRING` | Directory of sealed key files (`*.json`). Otherwise the one in the store settings, if any. |
97
- | `--sealed-only` | | Expose only the sealed tools; the hosted tools are not proxied. |
97
+ | `--sealed-only` | | Expose only the sealed and key tools; the hosted tools are not proxied, and `export_backup` and `import_backup` are not offered. |
98
98
  | `--authorize` | | Authorize again in the browser and replace the token file. |
99
99
  | `--configure` | | Choose again where new sealed keys are kept. Writes `stores.json` next to the token file. |
100
100
  | `--sidecar` | | Run the sidecar in this terminal. With `--confirm` it asks before every release of a secret. |
@@ -107,8 +107,9 @@ 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). |
110
111
  | `--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). |
111
- | `--import <file>` | | Create what such a file holds in this token's account, as new things. Takes `--into-space`, `--store`. |
112
+ | `--import <file>` | | Create what such a file holds in this token's account, as new things. Takes `--into-space`, `--store`, `--keys`. |
112
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). |
113
114
  | | `SAFEKB_HOSTED_TIMEOUT` | Seconds a hosted tool call may take. Default 300. |
114
115
  | | `SAFEKB_MCP_NO_BROWSER` | Set to anything: never start a browser, only show the authorize link. |
@@ -136,14 +137,16 @@ Its secret is a generated key or a passphrase.
136
137
  - `unlock_sealed` with only `root_id` takes the secret from the store that has it; `secret_file` reads
137
138
  it from a file.
138
139
  - Then `search_sealed`, `list_sealed`, `read_sealed_document`, `get_sealed_section`,
139
- `update_sealed_document`, `replace_in_sealed_document`, and the move, archive, delete, export,
140
+ `update_sealed_document`, `replace_in_sealed_document`, and the move, archive, delete,
140
141
  attachment and deposit tools.
142
+ - `unseal_document` turns a sealed document into a plain, unencrypted one (a new document the server
143
+ can read) and deletes the sealed original. It is not a backup: see [Export and import](#export-and-import).
141
144
  - `lock_sealed`, the idle timeout, or the end of the process forget the keys.
142
145
  - `change_seal_password` replaces the root's secret. Once the server has taken the new one, the
143
146
  superseded key is removed from the store that kept it (the system keyring, or any key file in the
144
147
  key file directory). A superseded passphrase, or a key file you had written elsewhere with
145
148
  `key_out_path`, is yours to remove.
146
- - Deleting a seal root (`delete_sealed_document`, or `export_sealed_document` of a standalone sealed
149
+ - Deleting a seal root (`delete_sealed_document`, or `unseal_document` of a standalone sealed
147
150
  document) also removes its keys and its name from this machine.
148
151
  - A tool parameter that names a seal root (`root_id`, `new_root_id`) takes its id or its
149
152
  [name](#names-of-seal-roots). Documents and folders inside a root are named by id.
@@ -187,6 +190,10 @@ npx -y @safekb/mcp --sidecar
187
190
  - A new seal root with `store: "sidecar"` makes the sidecar ask you for a new passphrase, twice, while
188
191
  the tool call waits.
189
192
  - With `--confirm` it asks for your approval before every release of a secret.
193
+ - The [key tools](#the-key-tools) and the backup tools ask here for the passphrase of a file, for
194
+ the name or id that confirms a deletion, and for the confirmation that turns auto-unlock on. Such a
195
+ passphrase is used for that one call and not held. An empty entry declines.
196
+ - The sidecar and the MCP client must be the same version of `@safekb/mcp`.
190
197
 
191
198
  Several roots can be held at once, each with its own passphrase and time. The sidecar listens on a Unix
192
199
  socket only your user can open; it is not available on Windows. Any program running as you can still
@@ -256,6 +263,44 @@ A seal root is given by its [name](#names-of-seal-roots) or its id.
256
263
  When a step after the point of no return fails (the superseded key cannot be removed after a rotation,
257
264
  the old copy cannot be removed after a move), the command fails and says where the key now is.
258
265
 
266
+ ### Unlocking automatically
267
+
268
+ ```sh
269
+ npx -y @safekb/mcp --auto-unlock "Bank" --set on # or a root id
270
+ npx -y @safekb/mcp --auto-unlock all --set on # every root without a setting of its own
271
+ npx -y @safekb/mcp --auto-unlock "Bank" --set off
272
+ ```
273
+
274
+ A sealed tool that needs a locked root it is allowed to open unlocks it by itself, as `unlock_sealed`
275
+ with only `root_id` would, with the same idle timeout, and goes on. **The trade-off: any session that
276
+ uses this token on this machine can then read such a root without unlocking it first.**
277
+
278
+ - Only a key kept in the system keyring or the key file directory is used. A root opened by a
279
+ passphrase never unlocks by itself: turning it on for one is refused, and with `all` such a root
280
+ stays locked and says so.
281
+ - A root's own setting wins over `all`. The settings are in `auto-unlock.json` next to the token file
282
+ (mode 0600), read on every use: a change applies to a running client at once.
283
+ - A failed automatic unlock (no key, a key in both stores) is the tool's error; nothing is guessed.
284
+ Without the setting a locked root stays the usual "call unlock_sealed first" error.
285
+ - `--list-keys` adds `unlocks automatically` to a current key whose root does; `list_sealed`,
286
+ `list_seal_keys` and `get_auto_unlock` show `auto_unlock`.
287
+ - `set_auto_unlock` turns it on only after you type the root's name or id (or `all`) at the sidecar:
288
+ the model cannot widen access on its own. Turning it off needs no confirmation.
289
+
290
+ ### The key tools
291
+
292
+ Everything above is also an MCP tool, and none of them takes or returns a secret: `list_seal_keys`,
293
+ `rename_seal_key`, `rotate_seal_key`, `move_seal_key`, `delete_seal_key`, `export_seal_keys`,
294
+ `import_seal_keys`, `get_auto_unlock` and `set_auto_unlock`, and for backups `export_backup` and
295
+ `import_backup` (see [Export and import](#export-and-import)).
296
+
297
+ What you type at the terminal for the command line, you type at the [sidecar](#the-sidecar) for a
298
+ tool, while the call waits: the passphrase of an export file or a key export (twice for a new one),
299
+ the name or id that confirms `delete_seal_key`, and the confirmation that turns auto-unlock on. It
300
+ reaches this client only, never the conversation. Without a running sidecar such a tool fails and says
301
+ to start one (`safekb-mcp --sidecar`); on Windows, which has no sidecar, it names the command to run
302
+ instead. File paths given to the tools must be absolute.
303
+
259
304
  ### Moving keys to another machine
260
305
 
261
306
  A generated key lives only where it was made: in the system keyring or in a key file. To carry all of
@@ -273,20 +318,22 @@ npx -y @safekb/mcp --import-keys keys.safekb # on the other machine, after --s
273
318
  Without the passphrase the file opens for nobody.
274
319
  - Import asks for that passphrase and keeps the keys in the default store of that
275
320
  machine. A key the machine already keeps is left as it is, so an import can be repeated.
276
- - Both need a terminal: the passphrase is never an argument, so it is in no shell history, no process
277
- list and no conversation.
321
+ - Both need a terminal, or the sidecar for `export_seal_keys` and `import_seal_keys`: the passphrase
322
+ is never an argument, so it is in no shell history, no process list and no conversation.
278
323
  - A root that is opened by a passphrase has no key on any machine. There is nothing to export: type
279
324
  the passphrase at the other machine's sidecar.
280
325
 
281
326
  ## Sealed credentials
282
327
 
283
- A sealed credential belongs to a seal root. Its password, TOTP seed, `sealed_notes` and the values of
328
+ A sealed credential belongs to a seal root and is kept in that root's space. Its password, TOTP seed, `sealed_notes` and the values of
284
329
  sealed custom fields are encrypted on your machine; its title, username, url, tags, `notes`, visible
285
330
  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
286
331
  `find_credential_duplicates` keep working. Never put a secret into `notes`.
287
332
 
288
333
  - `insert_sealed_credential`, `update_sealed_credential`, `delete_sealed_credential`: signed by the unlocked root.
289
- - `move_sealed_credential` hands a credential to another seal root; both roots must be unlocked.
334
+ - `move_sealed_credential` hands a credential to another seal root of its space; both roots must be
335
+ unlocked. A sealed credential changes space only with its root: moving the root's folder to another
336
+ space takes its credentials along (a credential's group in the old space is left behind).
290
337
  - `reveal_sealed_credential` and `get_sealed_totp` decrypt locally. The hosted `reveal_credential` and
291
338
  `get_credential_totp` cannot open a sealed credential.
292
339
  - Visible fields can be edited without the secret. Such an edit is flagged (`visible_tampered`) with the
@@ -294,7 +341,8 @@ custom fields and the key name of every custom field (sealed ones too) stay read
294
341
 
295
342
  ### Migrating server-encrypted credentials
296
343
 
297
- `migrate_credentials_to_sealed` turns every credential the token can see into a sealed one. It is
344
+ `migrate_credentials_to_sealed` turns every credential the token can see in the root's space into a
345
+ sealed one; `in_other_spaces` counts those that need a seal root of their own space. It is
298
346
  irreversible per credential: the server drops its own encrypted secrets and that credential's history.
299
347
 
300
348
  1. Unlock the target root, then run it with `dry_run: true` (the default). Nothing changes. It lists the
@@ -319,10 +367,14 @@ npx -y @safekb/mcp --export all.safekb --compress # everything this token
319
367
  npx -y @safekb/mcp --export work.safekb --space <space id> --doc <document id>
320
368
  npx -y @safekb/mcp --import all.safekb # into the account of this token
321
369
  npx -y @safekb/mcp --import work.safekb --into-space <space id>
370
+ npx -y @safekb/mcp --import all.safekb --keys pc-a.keys --keys pc-b.keys # keys of locked roots
322
371
  ```
323
372
 
324
373
  Both need a terminal: the passphrase of the file is typed there (twice for an export) and is never an
325
- argument. The file is encrypted with AES-256-GCM under a key derived from the passphrase with Argon2id,
374
+ argument. The tools `export_backup` and `import_backup` do the same, with every passphrase typed at the
375
+ [sidecar](#the-sidecar); their result holds counts and names, never content or a secret. A large export
376
+ runs for minutes; the tool reports progress to an MCP client that asks for it. With `--sealed-only`
377
+ these two tools are not offered, since they reach unsealed content too. The file is encrypted with AES-256-GCM under a key derived from the passphrase with Argon2id,
326
378
  in parts that cannot be dropped, swapped or cut off unnoticed; `--compress` gzips before encrypting.
327
379
  Attachments are streamed, so the file may be large. **The file holds every secret in plaintext under
328
380
  that one passphrase**: passwords, TOTP seeds and the content of sealed documents.
@@ -334,10 +386,12 @@ What an export holds:
334
386
  - Databases with columns, indexes, views, rows, row pages and the rows' files.
335
387
  - Credentials with every secret field. Each secret of a server-encrypted credential is one audited
336
388
  reveal on the server.
337
- - Sealed folders, documents, attachments and credentials, decrypted on this machine. Every seal root
338
- in the selection must open with a secret this machine keeps or its sidecar holds
339
- (`safekb-mcp --sidecar`, then `add <name or id>` for a passphrase root); otherwise the export
340
- stops before it writes anything. `--skip-locked` exports without those roots and says so.
389
+ - Sealed folders, documents, attachments and credentials of every seal root that opens with a secret
390
+ this machine keeps or its sidecar holds (`safekb-mcp --sidecar`, then `add <name or id>` for a
391
+ passphrase root), decrypted on this machine.
392
+ - Every other seal root as the server stores it, still sealed: the machine that makes the backup needs
393
+ none of their keys. The export names these roots before it writes. Pending deposits in them are left
394
+ out. `--skip-locked` leaves such roots out entirely instead.
341
395
  - Projects, tasks, decisions, and the links between exported things.
342
396
 
343
397
  What is selected:
@@ -356,15 +410,25 @@ What an import does:
356
410
  - Every exported space becomes a new space, also where one of that name exists. `--into-space` puts
357
411
  everything into one existing space instead. A token limited to some spaces is given the spaces it
358
412
  creates (this needs a SafeKB server of October 2026 or newer).
413
+ - A seal root the file holds still sealed is opened with its key: from a key export given with
414
+ `--keys <file>` (repeatable; made with `--export-keys` on any machine that keeps the key; its
415
+ passphrase is asked and its keys are used for this import only), or from a store of this machine.
416
+ A key of another account, or one replaced since by a key or passphrase change, does not open it.
417
+ Without a key everything in that root is left out, and the root is named with the reason; import
418
+ the file again with its key to restore it (that creates everything else again too).
359
419
  - Every seal root becomes a new seal root with a newly generated key, kept in the default key store
360
420
  or the one named by `--store`; a passphrase root therefore becomes a key root. A seal root whose
361
421
  name is taken on this machine gets ` (imported)` appended. **Back the new keys up**
362
422
  (`--export-keys`).
423
+ - A sealed credential is created in the space of its new seal root. One exported from another space
424
+ than its root's is placed there, and the report says so.
363
425
  - A project whose slug is taken gets a numbered one. A task keeps its assignee only in the account
364
426
  the export came from.
365
427
  - When a step fails the import stops, says at which record, and leaves what it had created; nothing
366
428
  is rolled back.
367
429
 
430
+ A file written by 0.7.0 or newer is not read by 0.6.0; 0.7.0 reads files of 0.6.0.
431
+
368
432
  Not in an export: version history, creation and change times and authors, shares, public links, space
369
433
  members, and the account's settings. A vault document (encrypted in the browser to its owner's vault)
370
434
  is exported as ciphertext and can only go back into the account it came from, while its id is free
@@ -377,7 +441,8 @@ there. Merged tasks are left out.
377
441
  - A program running as your user can read a key file, ask the system keyring or the sidecar for a
378
442
  secret, and read the memory of this client while a root is unlocked.
379
443
  - A session that has unlocked a root can be tricked by content it reads into copying it elsewhere.
380
- - An export file: it holds sealed content under the passphrase of the file, not under its seal roots.
444
+ - An export file: it holds the sealed content of every root that opened under the passphrase of the
445
+ file, not under its seal roots.
381
446
  - A compromised local machine, or a malicious server serving stale data.
382
447
  - Metadata: existence, sizes, timestamps, tree position.
383
448