@shieldfive/mcp 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -5,6 +5,41 @@ All notable changes to `@shieldfive/mcp` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 0.3.0 — unreleased
9
+
10
+ Vault tools. The server can now work on a ShieldFive vault through an **agent
11
+ grant**: a connection the user creates in ShieldFive → Settings → AI
12
+ assistants, limited to chosen folders and permissions, expiring (at most 90
13
+ days), revocable, audited, and enforced by the server on every request.
14
+
15
+ ### Added
16
+
17
+ - `vault_list_files`, `vault_search_files`, `vault_storage_stats`,
18
+ `vault_find_duplicates` and `vault_read_file` (read), and `vault_rename`,
19
+ `vault_move`, `vault_create_folder` and `vault_trash` (organize). They are
20
+ registered only when a connection is configured.
21
+ - `npx @shieldfive/mcp login | logout | status`. The connection string is
22
+ stored in the OS keychain through `@napi-rs/keyring`, with `SHIELDFIVE_GRANT`
23
+ as the fallback for headless use.
24
+ - Decryption of all three vault formats (post-quantum hybrid, AES-GCM v1 and
25
+ legacy v0) in memory, through `@shieldfive/crypto`. Names are decrypted on a
26
+ worker pool and cached in memory.
27
+ - Progress notifications for name decryption and duplicate hashing.
28
+ - Every vault result is marked as data rather than instructions. File contents
29
+ are fenced with a random marker the file cannot close.
30
+
31
+ ### Changed
32
+
33
+ - **The security boundary is restated, not removed.** 0.2.0 held no credential
34
+ and made no network request. That still holds for the local tools, which
35
+ import nothing from the vault half, so a server with no connection behaves as
36
+ before. The vault half talks to one https origin with one scoped credential.
37
+ `test/boundary.test.mjs` asserts the new lines: network access only in
38
+ `vault/api.mjs`, no filesystem access in any vault module, no cipher outside
39
+ `@shieldfive/crypto`, no account credential anywhere.
40
+ - A server started with a connection and no roots registers only the vault
41
+ tools.
42
+
8
43
  ## Unreleased
9
44
 
10
45
  ## 0.2.0 - 2026-09-16
package/README.md CHANGED
@@ -1,28 +1,156 @@
1
1
  # @shieldfive/mcp
2
2
 
3
- A [Model Context Protocol](https://modelcontextprotocol.io) server that lets an
4
- AI assistant manage files on your own machine: find duplicates by content, find
5
- what is large or stale, and move, rename or trash them.
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that lets
4
+ Claude, ChatGPT, Cursor or a local model tidy two things:
6
5
 
7
- It holds no ShieldFive credential, makes no network request, and does not import
8
- `@shieldfive/crypto`. Those are not gaps to be filled in a later version. They
9
- are the security boundary, and the section below explains what they cost you.
6
+ - **your ShieldFive vault**: find duplicates, see what takes the space, rename,
7
+ move, and move to the Bin. It works on the folders you grant, decrypts on your
8
+ machine, and every change can be undone;
9
+ - **folders on your own disk**: the same jobs, with no network access at all.
10
10
 
11
- ```sh
12
- npx @shieldfive/mcp ~/Documents ~/Downloads
13
- ```
11
+ ShieldFive's servers never see a file name or a byte of content in the clear,
12
+ and that holds with this server running too. Decryption happens inside this
13
+ process, on your computer. What the assistant then does with what it reads is a
14
+ separate question, answered under [Security model](#security-model).
14
15
 
15
- ## Install
16
+ <!-- DEMO: a 40-second screen recording of a duplicate-cleanup session in Claude
17
+ Desktop: "find duplicates in my Photos" → groups with sizes → "trash the copies"
18
+ → preview → confirm → the items appear in ShieldFive's Bin → one is undone from
19
+ Settings → AI assistants. Record against a demo vault, never a real one. -->
20
+
21
+ ## Connect your vault in 60 seconds
16
22
 
17
23
  Requires Node 20 or newer.
18
24
 
25
+ 1. In ShieldFive, open **Settings → AI assistants → Connect an assistant**.
26
+ Choose the folders, *Read only* or *Read and organize*, and an expiry (1 hour
27
+ to 90 days). Copy the connection string. It is shown once.
28
+ 2. Store it in your system keychain:
29
+
30
+ ```sh
31
+ npx -y @shieldfive/mcp login
32
+ ```
33
+
34
+ 3. Add the server to your assistant. For Claude Desktop, add this to
35
+ `claude_desktop_config.json` (Cursor uses the same block in `~/.cursor/mcp.json`):
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "shieldfive": { "command": "npx", "args": ["-y", "@shieldfive/mcp"] }
41
+ }
42
+ }
43
+ ```
44
+
45
+ For Claude Code: `claude mcp add shieldfive -- npx -y @shieldfive/mcp`
46
+
47
+ Restart the assistant and ask it to *find duplicates in my vault*.
48
+
49
+ `npx @shieldfive/mcp status` shows which connection is configured and whether
50
+ ShieldFive still accepts it. `npx @shieldfive/mcp logout` removes it from the
51
+ keychain. Revoking it in ShieldFive is what cuts off access everywhere.
52
+
53
+ For CI or a machine without a keychain, set `SHIELDFIVE_GRANT` to the connection
54
+ string instead. Anything that can read the server's environment can then read
55
+ the connection, so prefer the keychain wherever there is one.
56
+
57
+ ## Security model
58
+
59
+ In plain terms:
60
+
61
+ - **The connection string holds two things.** A *token* the server checks on
62
+ every request, and a *secret* that never leaves your machine. ShieldFive stores
63
+ only a hash of the token and has never seen the secret.
64
+ - **The secret opens only the folders you chose.** When you create a connection,
65
+ your browser wraps those folders' keys under a key derived from the secret. It
66
+ wraps nothing else: not your vault root key, not your password, not your
67
+ post-quantum secret key. Subfolders open through the vault's normal folder-key
68
+ chain. A folder you did not choose cannot be opened with anything this server
69
+ holds.
70
+ - **ShieldFive enforces scope, expiry and revocation on every request.** The
71
+ checks in this process only produce clearer errors; the server is the
72
+ boundary. Revoking a connection makes its next request fail. Nothing is
73
+ cached that would outlive a revocation.
74
+ - **Decryption happens here, in memory.** No plaintext, key or ciphertext is
75
+ written to disk. The vault modules do not import the filesystem, and a test
76
+ asserts that.
77
+ - **Nothing is deleted.** `vault_trash` moves items into a folder in your Bin
78
+ that belongs to the connection. There is no permanent-delete tool, and the
79
+ API a connection can reach has no delete route. Every rename, move and trash
80
+ appears in *Settings → AI assistants → Activity* with an Undo button.
81
+ - **Every change is previewed first.** Mutating tools report a plan, and the
82
+ confirmed call must carry that plan's token and is refused if the items
83
+ changed in between.
84
+
85
+ What this does not protect:
86
+
87
+ - **Your AI provider sees what the assistant reads.** File names, and the
88
+ contents of files the assistant opens, go to the assistant, and for a cloud
89
+ assistant that means to its provider, like the rest of your conversation. The
90
+ only way to avoid that is a local model.
91
+ - **Revoking cannot un-read.** Anything the assistant has already read stays
92
+ read. Nothing else survives it: file contents are streamed through
93
+ ShieldFive on each request, so there is no download link to outlive a
94
+ revocation.
95
+ - **A connection is built from what the server shows your browser when you
96
+ create it.** Every later extension is checked against your own keys, so a
97
+ compromised server cannot widen a connection afterwards. At the moment of
98
+ creation, though, a compromised server could mislabel which folder you
99
+ picked.
100
+ - **A copied connection string is a live key** to the folders it covers until
101
+ it expires or you revoke it. Keep it in the keychain.
102
+ - **Files can contain instructions aimed at the assistant.** This server marks
103
+ every name and file content as data, fences file contents in a block the file
104
+ cannot close, caps `vault_trash` at 50 items per call, requires a preview for
105
+ every change, and keeps every change undoable. A model can still be talked
106
+ into a reversible mistake inside the folders you granted.
107
+
108
+ The full design, including the threat model and the reasoning behind each
109
+ decision, is in
110
+ [`docs/mcp-grants-design.md`](https://github.com/shieldfive/web/blob/main/docs/mcp-grants-design.md).
111
+
112
+ ## Vault tools
113
+
114
+ Registered only when a connection is configured. Everything below names things
115
+ by id; paths are for people.
116
+
117
+ | Tool | Needs | What it does |
118
+ |---|---|---|
119
+ | `vault_list_files` | read | files and folders in scope, with decrypted names, paths, sizes, dates |
120
+ | `vault_search_files` | read | by name, path, extension, size or date, run locally over decrypted names |
121
+ | `vault_storage_stats` | read | totals, the biggest folders and files, a breakdown by type |
122
+ | `vault_find_duplicates` | read | same-size files decrypted in memory and compared by SHA-256; budgeted, and says when a result is a lower bound |
123
+ | `vault_read_file` | read | text files as fenced, untrusted content (up to 1 M characters); other types return details only |
124
+ | `vault_rename` | organize | rename a file or folder |
125
+ | `vault_move` | organize | move into another folder in scope |
126
+ | `vault_create_folder` | organize | create a folder in scope |
127
+ | `vault_trash` | organize | up to 50 items into the connection's folder in the Bin |
128
+
129
+ Limits a user may meet:
130
+
131
+ - **Post-quantum files uploaded from a phone or the CLI** show as
132
+ `readable: false` until you next open ShieldFive on the web, which adds the key
133
+ the connection needs. Files uploaded in the web app are ready straight away.
134
+ - **The first listing of a large vault takes a while.** Each name costs about
135
+ 70 ms of Argon2id, spread over your CPU cores (about 20 seconds for 2,000
136
+ names on 8 cores). Names are cached in memory for the rest of the session.
137
+ - **Items at the very top of a whole-vault connection** can be read and moved
138
+ into a folder, but not renamed in place, and nothing can be moved to the top.
139
+ Their names are sealed under your vault root key, which a connection never
140
+ holds.
141
+ - **Uploads are not available yet.** The design allows them, but they ship
142
+ after the read and organize tools have been in use for a while.
143
+
144
+ ## Local files
145
+
146
+ Every path after the package name is a **root**. The local tools can read and
147
+ write inside those directories and nowhere else, and make no network request.
148
+
19
149
  ```sh
20
- npm install -g @shieldfive/mcp
150
+ npx @shieldfive/mcp ~/Documents ~/Downloads
21
151
  ```
22
152
 
23
- ### Claude Desktop
24
-
25
- Add to `claude_desktop_config.json`:
153
+ In `claude_desktop_config.json`:
26
154
 
27
155
  ```json
28
156
  {
@@ -35,10 +163,9 @@ Add to `claude_desktop_config.json`:
35
163
  }
36
164
  ```
37
165
 
38
- Every path after the package name is a **root**. The server can read and write
39
- inside those directories and nowhere else. There is no default root and no
40
- override flag a server started with no roots will refuse every call and tell
41
- you so.
166
+ With a connection configured and no roots, only the vault tools are registered.
167
+ With roots and no connection, only the local tools are, and the server behaves
168
+ exactly as 0.2.0 did. With both, you get both.
42
169
 
43
170
  `SHIELDFIVE_MCP_ROOTS` adds roots as well — the two are combined, not
44
171
  alternatives — as a list separated by your platform's path separator (`:` on
@@ -51,7 +178,7 @@ SHIELDFIVE_MCP_ROOTS="/Users/you/Documents:/Volumes/Archive" npx @shieldfive/mcp
51
178
  Whitespace around a root is ignored. In a path given to a tool it is not: there,
52
179
  every character is part of the path.
53
180
 
54
- ## See it work first
181
+ ### See it work first
55
182
 
56
183
  ```bash
57
184
  npm run demo
@@ -63,33 +190,19 @@ a two-year-old PDF — runs the read tools over them, previews a trash call, the
63
190
  confirms it and shows the manifest. It touches nothing outside that directory
64
191
  and removes it at the end (`--keep` leaves it in place).
65
192
 
66
- ## What this cannot do
67
-
68
- **It cannot see your ShieldFive vault.** Not the file list, not the names, not
69
- the sizes. It will not tell you whether a local file is already backed up,
70
- because it has no way to know and it is not permitted to guess.
71
-
72
- That is a deliberate trade. The alternative was to authenticate with a full
73
- ShieldFive account JWT the only credential the vault API accepts. That token
74
- also opens `/api/vault-key`, which returns your wrapped root key and an ML-KEM
75
- public key, and every content-download route, and **none of it can be scoped
76
- away**, because no scoped vault credential exists. A server holding that token
77
- would be *declining* to read your files rather than being *unable* to, with the
78
- difference resting on a client-side denylist and on nothing else on your machine
79
- reading the token file. A server holding no token cannot read them at all.
80
-
81
- When a scoped, metadata-only key exists, vault tools can be added behind it.
82
- Until then this is a local file manager that happens to be published by the
83
- people who make an encrypted vault.
84
-
85
- **It cannot stop the results from reaching your AI provider.** This server
86
- makes no network request, and that is worth exactly what it says and no more:
87
- everything it returns — paths, file names, sizes, dates, the digests it
88
- reports — goes back to the AI client that called it, and if that client is a
193
+ ## What the local tools cannot do
194
+
195
+ **They cannot tell you whether a local file is already in your vault.** Matching
196
+ a local name and size against a vault listing is how a tool deletes the only
197
+ copy of something, and this server will not guess.
198
+
199
+ **They cannot stop the results from reaching your AI provider.** The local
200
+ tools make no network request, and that is worth exactly what it says and no
201
+ more:
202
+ everything they return paths, file names, sizes, dates, the digests they
203
+ report goes back to the AI client that called it, and if that client is a
89
204
  cloud assistant, those names travel to the assistant's provider like the rest
90
- of your conversation. The server's silence is not the client's. Choose roots on
91
- that basis: point it at the folders you would be willing to describe out loud,
92
- and it will never see anything else.
205
+ of your conversation. Choose roots on that basis.
93
206
 
94
207
  **It will never infer that two files are the same from their names and sizes.**
95
208
  Duplicate detection reads both files and compares a full SHA-256 of their
@@ -143,7 +256,7 @@ naming what changed. A token performs one change and expires after ten minutes.
143
256
  So a directory that grew, a destination that appeared, or a path that now points
144
257
  at a different file stops the call instead of silently widening it.
145
258
 
146
- ## Tools
259
+ ## Local tools
147
260
 
148
261
  | Tool | Reads | Writes |
149
262
  |---|---|---|
@@ -290,7 +403,7 @@ renames, and a file created in that instant would be replaced.
290
403
 
291
404
  ## What the tests assert
292
405
 
293
- `npm test` runs 161 tests. The ones worth knowing about:
406
+ `npm test` runs 183 tests. The ones worth knowing about:
294
407
 
295
408
  - A symlink pointing out of a root is refused, on both the read and the write
296
409
  side, and so is a dangling symlink on a write path.
@@ -310,18 +423,33 @@ renames, and a file created in that instant would be replaced.
310
423
  replaced.
311
424
  - A cancelled request moves nothing, and a trash batch cancelled midway says
312
425
  exactly what it moved.
313
- - No file under `src/` imports a networking module, calls `fetch`, spawns a
314
- subprocess, or reads any environment variable other than
315
- `SHIELDFIVE_MCP_ROOTS`.
316
- - A real MCP client over a real stdio transport sees nine tools and no vault
317
- tool, including when the server is started through a symlink the way npm
318
- installs it.
319
-
320
- The network assertion has a limit worth stating: it proves nothing in `src/`
321
- reaches the network. It does not prove the dependency tree is network-free —
322
- `@modelcontextprotocol/sdk` ships HTTP transports for other people's servers,
323
- and claiming otherwise would be false. What closes that gap is that `server.mjs`
324
- imports the stdio transport and no HTTP one, which is also asserted.
426
+ - Only `src/vault/api.mjs` calls `fetch`, and only to an https ShieldFive
427
+ origin. No local-tool module imports anything from the vault half, no file
428
+ under `src/` spawns a subprocess, and the only environment variables read are
429
+ `SHIELDFIVE_MCP_ROOTS`, `SHIELDFIVE_GRANT` and `SHIELDFIVE_API_URL`.
430
+ - The vault modules import no filesystem module, so decrypted data cannot be
431
+ written to disk. No module uses a cipher, HMAC or KDF of its own. All
432
+ cryptography comes from `@shieldfive/crypto`.
433
+ - Against an in-memory ShieldFive that serves real ciphertext in all three vault
434
+ formats, over a real MCP client:
435
+ - files decrypt through the grant's keys only, and nothing outside the scope
436
+ is listed, read or even requested;
437
+ - a revoked or expired connection fails the very next call;
438
+ - renames and moves re-seal names and keys so the owner's own keys still
439
+ open them;
440
+ - the grant secret and token never appear in any request body or path.
441
+ - A file whose contents tell the assistant to trash everything comes back
442
+ inside a fence it cannot close. Reading it issues only reads, and a 51-item
443
+ trash call is refused.
444
+ - A real MCP client over a real stdio transport sees exactly the nine local
445
+ tools when no connection is configured, including when the server is started
446
+ through a symlink the way npm installs it.
447
+
448
+ The network assertion has a limit worth stating: it proves what `src/` does,
449
+ not what the dependency tree could do. `@modelcontextprotocol/sdk` ships HTTP
450
+ transports for other people's servers. What closes that gap is that
451
+ `server.mjs` imports the stdio transport and no HTTP one, which is also
452
+ asserted.
325
453
 
326
454
  ## Limits
327
455
 
package/SECURITY.md CHANGED
@@ -40,17 +40,21 @@ shipped the fix.
40
40
  ## Scope
41
41
 
42
42
  In scope: this package's own source — path containment, the walk, the mutating
43
- tools, the trash, the MCP surface, and the claims its README makes.
43
+ tools, the trash, the vault tools and how they handle grant keys, names and
44
+ decrypted content, the MCP surface, and the claims its README makes.
44
45
 
45
46
  Out of scope for this repository, with the right destination:
46
47
 
47
48
  - The ShieldFive vault, web application and API — `security@shieldfive.com`,
48
49
  same address, different codebase.
49
- - `@shieldfive/crypto` its own repository. **This package does not depend on
50
- it**, and a test asserts no `@shieldfive/*` or `@supabase/*` package is a
51
- dependency.
52
- - `@modelcontextprotocol/sdk` and `zod`, this package's only two dependencies
53
- report upstream. A vulnerability in how *this* package uses them is in scope.
50
+ - The agent-grant API and its enforcement (scope, expiry, revocation, the
51
+ audit log) `shieldfive/web`, same address.
52
+ - `@shieldfive/crypto` — its own repository. The vault half depends on it for
53
+ every cryptographic operation; a test asserts no module here implements a
54
+ cipher, HMAC or KDF of its own.
55
+ - `@modelcontextprotocol/sdk`, `zod`, `libsodium-wrappers-sumo` and
56
+ `@napi-rs/keyring` — report upstream. A vulnerability in how *this* package
57
+ uses them is in scope.
54
58
 
55
59
  ## Threat model
56
60
 
@@ -76,8 +80,13 @@ has.
76
80
  | An assistant acting without the user seeing the plan | Mutating tools are inert without `confirm: true` and report what they would displace as well as what they would move | yes |
77
81
  | An oversized argument | `limit`, `max_files`, `max_files_hashed`, `paths`, path length and `new_name` are capped at the MCP schema and again in the handler; values echoed in a refusal are cut short | yes |
78
82
  | A cancelled request still changing files | Nothing starts once a request is cancelled; a trash batch stops between items and says what moved; the outcome is logged, because the SDK sends no response to a cancelled request | yes |
79
- | Credential exposure in this code | No credential is read or stored. `SHIELDFIVE_MCP_ROOTS` is the only environment variable read | yes |
80
- | Exfiltration over the network | No networking module imported, `fetch` never called; the transport is stdio | yes, for this package's source |
83
+ | Credential exposure in this code | The only credential is an agent grant, read from `SHIELDFIVE_GRANT` or the OS keychain; never logged, never returned, never written to a file. The only environment variables read are `SHIELDFIVE_MCP_ROOTS`, `SHIELDFIVE_GRANT` and `SHIELDFIVE_API_URL`. No account password, service key or vault-key route is referenced anywhere | yes |
84
+ | Network access | Only `vault/api.mjs` calls `fetch`, only to an https ShieldFive origin (or localhost for development). Local tools import nothing from the vault half; the transport is stdio | yes, for this package's source |
85
+ | A grant opening more than its scope | Keys come only from the grant's own wraps (AAD-bound to grant, kind and object) and the folder chain below them. The server enforces scope on every request; local checks only produce clearer errors | yes, against an in-memory server with real ciphertext |
86
+ | Revocation not taking effect | Every tool call re-fetches the grant and its listing; file contents are streamed through the API per request (no storage URL is ever held); nothing that would outlive a revocation is cached | yes |
87
+ | Decrypted data reaching disk | Vault modules import no filesystem module; plaintext exists only in memory for the duration of a call; decrypted names are cached in memory only | yes |
88
+ | Prompt injection through names or file contents | Names are stripped of control and bidi characters; every result is marked as data; file contents are fenced with a random marker the file cannot close; every change needs a preview and its plan token; `vault_trash` is capped at 50 items; nothing is ever deleted and every change is undoable by the owner | yes, with an injection fixture |
89
+ | A write the owner cannot read back | Names are re-sealed as v6 envelopes under the destination folder key and content keys re-wrapped under it; a name that failed to decrypt is never re-sealed | yes, the owner's keys re-open every write |
81
90
  | Credential exposure via a subprocess | No subprocess is spawned at all. Spawning `sf` would inherit `SF_PASSWORD` from the environment whether or not this code named it | yes |
82
91
 
83
92
  ## Known limits
@@ -139,6 +148,16 @@ has.
139
148
  import would evade it.
140
149
  - **File paths reach the model.** If a path is itself sensitive, do not give
141
150
  this server the root it sits in.
151
+ - **Everything the vault tools return reaches the model, and so its provider.**
152
+ A grant limits which folders the assistant can open; it cannot limit what the
153
+ assistant's provider sees of what was opened. Revocation cannot un-read.
154
+ - **A connection string is a bearer credential plus its key.** Held by anyone,
155
+ it gives that connection's access until it expires or is revoked. In the
156
+ keychain it is protected like any other stored secret; in `SHIELDFIVE_GRANT`
157
+ it is readable by anything that can read the process environment.
158
+ - **Instruction-following is the model's, not this server's.** The fencing and
159
+ caps above bound the damage of an injected instruction to reversible changes
160
+ inside the granted folders; they do not make a model ignore text.
142
161
  - **Windows is untested.** No POSIX-only API is used and paths go through
143
162
  `node:path`, but nobody has run it there, and the cross-device tests run only
144
163
  on macOS.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@shieldfive/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
- "description": "Model Context Protocol server for local file management. Finds duplicates, large files and stale files across the drives you allow it, and reorganises them. Holds no ShieldFive credential and makes no network calls.",
5
+ "description": "Model Context Protocol server for your ShieldFive vault and local files: find duplicates, reclaim space and reorganise, with decryption on your machine and scoped, revocable, audited access.",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Cho Garcia <security@shieldfive.com>",
8
8
  "homepage": "https://github.com/shieldfive/mcp",
@@ -14,13 +14,17 @@
14
14
  "url": "https://github.com/shieldfive/mcp/issues"
15
15
  },
16
16
  "keywords": [
17
- "shieldfive",
18
- "mcp",
19
- "model-context-protocol",
20
17
  "claude",
21
- "filesystem",
18
+ "disk-space",
22
19
  "duplicate-files",
23
- "disk-space"
20
+ "encryption",
21
+ "end-to-end-encryption",
22
+ "filesystem",
23
+ "mcp",
24
+ "model-context-protocol",
25
+ "post-quantum",
26
+ "shieldfive",
27
+ "vault"
24
28
  ],
25
29
  "bin": {
26
30
  "shieldfive-mcp": "src/server.mjs"
@@ -29,21 +33,27 @@
29
33
  "access": "public"
30
34
  },
31
35
  "files": [
32
- "src",
36
+ "CHANGELOG.md",
37
+ "LICENSE",
33
38
  "README.md",
34
39
  "SECURITY.md",
35
- "CHANGELOG.md",
36
- "LICENSE"
40
+ "server.json",
41
+ "src"
37
42
  ],
38
43
  "engines": {
39
44
  "node": ">=20"
40
45
  },
41
46
  "scripts": {
42
47
  "test": "node --test test/*.test.mjs",
43
- "demo": "node demo/run-demo.mjs"
48
+ "demo": "node demo/run-demo.mjs",
49
+ "build:mcpb": "node scripts/build-mcpb.mjs"
44
50
  },
45
51
  "dependencies": {
46
52
  "@modelcontextprotocol/sdk": "^1.30.0",
53
+ "@napi-rs/keyring": "^2.1.0",
54
+ "@shieldfive/crypto": "1.0.0-rc.5",
55
+ "libsodium-wrappers-sumo": "^0.8.4",
47
56
  "zod": "^3.25.0"
48
- }
57
+ },
58
+ "mcpName": "io.github.shieldfive/mcp"
49
59
  }
package/server.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.shieldfive/mcp",
4
+ "title": "ShieldFive",
5
+ "description": "Tidy your end-to-end encrypted ShieldFive vault and local folders: duplicates, space, reorganising. Decrypts on your machine; scoped, revocable access.",
6
+ "version": "0.3.0",
7
+ "repository": {
8
+ "url": "https://github.com/shieldfive/mcp",
9
+ "source": "github"
10
+ },
11
+ "websiteUrl": "https://shieldfive.com",
12
+ "packages": [
13
+ {
14
+ "registryType": "npm",
15
+ "identifier": "@shieldfive/mcp",
16
+ "version": "0.3.0",
17
+ "transport": { "type": "stdio" },
18
+ "environmentVariables": [
19
+ {
20
+ "name": "SHIELDFIVE_GRANT",
21
+ "description": "Connection string from ShieldFive → Settings → AI assistants. Optional: `npx @shieldfive/mcp login` stores it in the OS keychain instead.",
22
+ "isRequired": false,
23
+ "isSecret": true
24
+ },
25
+ {
26
+ "name": "SHIELDFIVE_MCP_ROOTS",
27
+ "description": "Local directories the local tools may use, separated by the platform path separator. Optional.",
28
+ "isRequired": false,
29
+ "isSecret": false
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }