@safekb/mcp 0.1.0 → 0.2.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 +61 -8
  2. package/dist/safekb-mcp.js +1317 -118
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -15,6 +15,12 @@ This opens the browser and prints a **pairing code**. Sign in on the page, choos
15
15
  pairing code, and the client saves a service-account token to `~/.config/safekb/mcp.json` (mode 0600).
16
16
  It then prints the account it was authorized as; check that it is yours. There is no default URL.
17
17
 
18
+ Last, it chooses where this machine keeps the keys of new seal roots (see [Where secrets are kept](#where-secrets-are-kept)).
19
+ With a system keyring that is the choice. Without one, as on most servers, it warns and asks before it
20
+ uses key files. `npx -y @safekb/mcp --configure` makes the same choice again without re-authorizing.
21
+ A client authorized before this choice existed makes it by itself on its next start when the system
22
+ keyring works; only key files need `--configure`, because they need your agreement.
23
+
18
24
  How the token gets to the client: the page never sees it. The page hands the client a single-use code
19
25
  (valid for two minutes), and the client redeems that code itself, proving with a secret it never wrote
20
26
  anywhere that it is the process that started the flow. The URL in the browser launcher's arguments is
@@ -41,10 +47,13 @@ Claude Desktop and Cursor (`mcpServers` in their MCP config file):
41
47
  | --- | --- | --- |
42
48
  | `--url <api url>` | `KB_API_URL` | API base URL. Otherwise the URL saved by `--authorize`. When serving, it must have the origin the token was issued for: the token is never sent anywhere else. |
43
49
  | `--config <path>` | `SAFEKB_MCP_CONFIG` | Token file. Default `~/.config/safekb/mcp.json`. Use one per project for per-project access. |
44
- | `--keyring <dir>` | `SAFEKB_SEALED_KEYRING` | Directory of sealed key files (`*.json`). No default. |
50
+ | `--keyring <dir>` | `SAFEKB_SEALED_KEYRING` | Directory of sealed key files (`*.json`). Otherwise the one `--configure` chose, if any. |
45
51
  | `--sealed-only` | | Expose only the sealed tools; the hosted tools are not proxied. |
46
- | `--authorize` | | Authorize in the browser and write the token file. |
47
- | | `SAFEKB_SEALED_IDLE_TTL` | Seconds an unlocked seal root may stay idle. Default 900. |
52
+ | `--authorize` | | Authorize in the browser and write the token file, then choose the key store. |
53
+ | `--configure` | | Choose where new sealed keys are kept. Writes `stores.json` next to the token file. |
54
+ | `--sidecar` | | Run the sidecar in this terminal. With `--confirm` it asks before every release of a secret. |
55
+ | `--sidecar-socket <path>` | `SAFEKB_SIDECAR_SOCKET` | The sidecar's socket. Default `sidecar.sock` next to the token file. |
56
+ | | `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). |
48
57
  | | `SAFEKB_HOSTED_TIMEOUT` | Seconds a hosted tool call may take. Default 300. |
49
58
 
50
59
  The client refuses to start when the token file or a keyring file is readable by group or others,
@@ -57,16 +66,58 @@ confirmed*: it may have run, and it is not sent again. Check the state before re
57
66
  ## Sealed documents
58
67
 
59
68
  A **seal root** is a sealed folder (one secret opens everything in it) or a standalone sealed document.
60
- Its secret is a generated key (default) or a passphrase.
69
+ Its secret is a generated key or a passphrase.
61
70
 
62
- - `create_sealed_folder` / `insert_sealed_document` with `key_out_path` write a key file (mode 0600).
63
- The key is never returned to the model. **Back the file up: a lost secret cannot be recovered.**
64
- - `unlock_sealed` with `secret_file`, or with only `root_id` when the key file is in the keyring.
71
+ - `create_sealed_folder` / `insert_sealed_document` with `store` or `key_out_path` make a new seal root
72
+ and keep its secret on this machine. The secret is never returned to the model.
73
+ **Back it up: a lost secret cannot be recovered.**
74
+ - `unlock_sealed` with only `root_id` takes the secret from the store that has it; `secret_file` reads
75
+ it from a file.
65
76
  - Then `search_sealed`, `list_sealed`, `read_sealed_document`, `get_sealed_section`,
66
77
  `update_sealed_document`, `replace_in_sealed_document`, and the move, archive, delete, export,
67
78
  attachment and deposit tools.
68
79
  - `lock_sealed`, the idle timeout, or the end of the process forget the keys.
69
80
 
81
+ ## Where secrets are kept
82
+
83
+ Every seal root has its own secret, and each can be kept in a different place. All three work side by
84
+ side: `unlock_sealed` with only `root_id` asks each store and uses the one that has the secret. If two
85
+ have it, it stops and asks for `store`.
86
+
87
+ | `store` | What is kept | Where | At rest |
88
+ | --- | --- | --- | --- |
89
+ | `system` | a generated key | the operating system's keyring: Keychain (macOS), Credential Manager (Windows), Secret Service (Linux) | encrypted by the system |
90
+ | `file` | a generated key | a file (mode 0600) in the keyring directory | not encrypted |
91
+ | `sidecar` | a passphrase you type | the memory of a separate process, for a time you choose | nowhere |
92
+ | `default` | | whichever of `system` and `file` `--configure` chose | |
93
+
94
+ `key_out_path` still writes a key file to a path of your choice, and `passphrase` still takes one as
95
+ text (which then is in the conversation transcript).
96
+
97
+ The system keyring is used only where `--configure` found it working. On Linux that means a running
98
+ Secret Service (GNOME Keyring, KWallet, KeePassXC); the kernel keyring is never used, because it
99
+ forgets its content at logout. Keys are kept there with [`@napi-rs/keyring`](https://github.com/Brooooooklyn/keyring-node).
100
+
101
+ ### The sidecar
102
+
103
+ The sidecar keeps passphrases out of files, out of the keyring and out of the conversation. Run it in
104
+ a terminal of its own:
105
+
106
+ ```sh
107
+ npx -y @safekb/mcp --sidecar
108
+ ```
109
+
110
+ - `add <root id> [minutes]` asks for the root's secret without showing it and holds it for that long
111
+ (default 15 minutes). The time is fixed when you type the secret: use does not extend it.
112
+ - `list`, `drop <root id>`, `drop all`, `quit`.
113
+ - A new seal root with `store: "sidecar"` makes the sidecar ask you for a new passphrase, twice, while
114
+ the tool call waits.
115
+ - With `--confirm` it asks for your approval before every release of a secret.
116
+
117
+ Several roots can be held at once, each with its own passphrase and time. The sidecar listens on a Unix
118
+ socket only your user can open; it is not available on Windows. Any program running as you can still
119
+ ask it for a held secret, which is what `--confirm` is for.
120
+
70
121
  ## Sealed credentials
71
122
 
72
123
  A sealed credential belongs to a seal root. Its password, TOTP seed, `sealed_notes` and the values of
@@ -104,7 +155,9 @@ Old database and storage backups keep the server-encrypted copies until they age
104
155
  ## What sealing does not protect
105
156
 
106
157
  - Whatever a tool returns enters the local conversation transcript and is sent to the model provider.
107
- The same holds for a secret passed as text; use `secret_file` or the keyring.
158
+ The same holds for a secret passed as text; use a store or `secret_file`.
159
+ - A program running as your user can read a key file, ask the system keyring or the sidecar for a
160
+ secret, and read the memory of this client while a root is unlocked.
108
161
  - A session that has unlocked a root can be tricked by content it reads into copying it elsewhere.
109
162
  - A compromised local machine, or a malicious server serving stale data.
110
163
  - Metadata: existence, sizes, timestamps, tree position.