A local MCP server & CLI that pushes your repos and project files to cheap object storage โ with end-to-end encryption rooted in your Solana wallet. The hosted backend only ever sees ciphertext. Solana handles auth, billing, and tamper-evidence; never your keys.
AES-256-GCM ยท HKDF-SHA256 ยท ed25519 ยท content-addressed chunks ยท Merkle-verified restore
$ vault init my-repo
Created vault "my-repo"
vaultId: feaa0db244e9d07b4f401c92a329e1f9
wallet: BJc5hVBMxFFuqdzmwUEeTtWnGURq2UXB6wD8EV2bHVDR
$ vault push <vaultId> ./my-repo -m "first snapshot"
Pushed snapshot snap-0001-f4e5e181107c
merkleRoot: f4e5e181107c26a4d6ac990306f9595aโฆ
files: 6 chunks: 6 (new: 6) uploaded: 4.1 KB ciphertext
$ vault pull <vaultId> ./restore
โ Restored snap-0001 โ every chunk hash & Merkle root verified
โ byte-identical
No invented crypto โ just established primitives composed correctly. Your wallet signature derives the key; a random per-vault key encrypts the data; the server gets nothing it can open.
Your wallet signs a fixed canonical message. KEK = HKDF-SHA256(signature, salt=vaultId, info="kek") โ recomputable on any device that holds the wallet, on no device that doesn't.
A random per-vault DEK encrypts your files. It's stored only as wrappedDEK = AES-256-GCM(KEK, DEK). The server may hold the wrapped DEK โ it's useless without the wallet.
Files are split into chunks, content-addressed by SHA-256(plaintext) for per-vault dedup, then each chunk is encrypted with the DEK and a fresh nonce. Only ciphertext is uploaded.
The file tree โ chunk-hash map is itself encrypted with the DEK. The backend never learns your filenames, sizes, or directory structure.
pull recomputes the snapshot's Merkle root and re-checks every chunk's SHA-256 before writing a single byte. GCM auth tags catch any tampering. Phase 2 anchors that 32-byte root on-chain.
A complete backend compromise yields ciphertext and a wrapped key that opens nothing. Here's exactly what stays on your device โ and what the storage backend can and can't see.
S3-compatible storage pointed at Cloudflare R2 by default. Pull from anywhere without surprise bandwidth bills.
Your Solana keypair is the root of trust. Open any vault on a new machine just by signing โ no password vault to lose.
Content-addressed chunks + a Merkle root over the whole tree. A flipped byte in storage is caught before it ever touches disk.
Identical chunks upload once โ but never across users. We refuse convergent dedup that would leak who holds the same file.
Drive it from your editor's agent over the Model Context Protocol, or straight from the terminal. Same five operations.
Each push writes its 32-byte Merkle root on-chain, making snapshots independently auditable and rollback-evident.
With no R2 credentials set, storage falls back to a local filesystem mock โ so the full encrypted round trip works with zero cloud setup. Point it at R2 when you're ready.
# clone & install
$ git clone https://github.com/yksanjo/vaultmcp && cd vaultmcp
$ npm install && npm run build
# sign in, create a vault, push, pull
$ vault login
$ vault init my-repo
$ vault push <vaultId> ./my-repo -m "first snapshot"
$ vault pull <vaultId> ./restore # byte-identical, verified
# point at Cloudflare R2 (optional โ no egress fees)
$ export VAULTMCP_R2_ENDPOINT=https://<acct>.r2.cloudflarestorage.com
$ export VAULTMCP_R2_BUCKET=my-vault VAULTMCP_R2_ACCESS_KEY=โฆ VAULTMCP_R2_SECRET_KEY=โฆ