@safekb/mcp 0.7.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.
- package/README.md +62 -9
- package/dist/safekb-mcp.js +19527 -18760
- package/package.json +1 -1
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,6 +107,7 @@ 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
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). |
|
|
@@ -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,
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
@@ -323,7 +371,10 @@ npx -y @safekb/mcp --import all.safekb --keys pc-a.keys --keys pc-b.keys # key
|
|
|
323
371
|
```
|
|
324
372
|
|
|
325
373
|
Both need a terminal: the passphrase of the file is typed there (twice for an export) and is never an
|
|
326
|
-
argument. The
|
|
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,
|
|
327
378
|
in parts that cannot be dropped, swapped or cut off unnoticed; `--compress` gzips before encrypting.
|
|
328
379
|
Attachments are streamed, so the file may be large. **The file holds every secret in plaintext under
|
|
329
380
|
that one passphrase**: passwords, TOTP seeds and the content of sealed documents.
|
|
@@ -369,6 +420,8 @@ What an import does:
|
|
|
369
420
|
or the one named by `--store`; a passphrase root therefore becomes a key root. A seal root whose
|
|
370
421
|
name is taken on this machine gets ` (imported)` appended. **Back the new keys up**
|
|
371
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.
|
|
372
425
|
- A project whose slug is taken gets a numbered one. A task keeps its assignee only in the account
|
|
373
426
|
the export came from.
|
|
374
427
|
- When a step fails the import stops, says at which record, and leaves what it had created; nothing
|