ncrypted-mcp
by Seidl-Family
README.md
# ncrypted
One-time, end-to-end encrypted secrets for AI agents.
An agent encrypts a password, API key or note **locally**, pays **0.005 USDC** over [x402](https://x402.org) on Base, and gets a link that opens **exactly once**. Share it with a person, email it, or hand it to another agent. Reading is free and destroys the secret.
```
https://ncrypted.ai/s/{id}#{key}
└─ decryption key, never sent to the server
```
## Install
You need a dedicated, low-balance Base wallet with some USDC (no ETH needed). Export its key as `NCRYPTED_WALLET_PRIVATE_KEY`.
**Claude Code**
```
/plugin marketplace add Seidl-Family/ncrypted
/plugin install ncrypted@ncrypted
```
**Any MCP client** (Claude Desktop, Cursor, Codex, …)
```json
{ "mcpServers": { "ncrypted": { "command": "npx", "args": ["-y", "@seidl-family/ncrypted-mcp"], "env": { "NCRYPTED_WALLET_PRIVATE_KEY": "0x..." } } } }
```
**Agent Skill**: `npx skills add Seidl-Family/ncrypted`
**CLI / SDK**
```sh
echo "hunter2" | npx ncrypted create --ttl 1h [--email ops@example.com] [--passphrase X]
npx ncrypted read "https://ncrypted.ai/s/abc#key"
```
```ts
import { Ncrypted } from "ncrypted";
const nc = new Ncrypted(); // reads NCRYPTED_WALLET_PRIVATE_KEY
const { link, receiptToken, id } = await nc.create("hunter2", { ttl: 3600 });
const value = await nc.read(link); // free, destroys it
```
## How it works
- **Zero-knowledge**: AES-256-GCM with a random 256-bit key, derived via HKDF (plus PBKDF2 if you set a passphrase). The server stores ciphertext only.
- **Exactly once**: reads use Redis `GETDEL`, so concurrent readers can't both get it. Unread secrets expire after their TTL (5 min to 7 days).
- **Preview-safe**: opening the web page doesn't consume the secret; the recipient has to click *Reveal*.
- **Pay per secret**: x402 `exact` scheme, USDC on Base, settled only after the secret is stored. The SDK refuses to pay more than $0.01 per request.
- **Email**: the creator can email the link once. It passes through the server for that request and isn't stored. Use a passphrase for very sensitive values.
## Payments and safety
ncrypted charges a fixed **0.005 USDC per secret created**, paid over [x402](https://x402.org) on Base. Everything else is free: reading, status checks, revoking.
- **Narrow scope:** the only payment the plugin can make is ncrypted's own fee for `ncrypted_create`. It has no tool to send arbitrary amounts, trade, swap, or pay anyone else.
- **Hard cap:** the SDK refuses to pay more than 0.01 USDC for a single request, whatever the server asks.
- **Dedicated wallet:** payments come from a low-balance wallet the user creates on purpose (`npx ncrypted wallet new`) and funds themselves. The plugin never asks for, reads or stores the user's main wallet, and the skill tells the agent never to ask for private keys in chat.
- **Visible and explicit:** every charge is an explicit `ncrypted_create` tool call. There are no background or recurring charges.
- **No charge on failure:** payment settles through Coinbase's x402 facilitator only after the secret is stored.
- **Zero-knowledge by default:** the local MCP server encrypts on the user's machine, so the service stores ciphertext only. The optional hosted endpoint (`https://ncrypted.ai/mcp`) is clearly labeled as server-side encryption.
## Data and services contacted
The plugin's MCP server, the CLI and the skill contact only these services:
| Service | What is sent | When |
|---|---|---|
| **ncrypted API** (`https://ncrypted.ai`, Vercel + Upstash Redis) | Ciphertext, IV, salt, passphrase flag and TTL. Never the key, passphrase or plaintext. | Creating, reading, checking status of or burning a secret |
| **Coinbase x402 facilitator / Base network** | A signed USDC payment authorization (payer address, amount, payee) | Creating a secret (0.005 USDC) |
| **Base public RPC** (`mainnet.base.org`) | The payer wallet address | `ncrypted_wallet` / `ncrypted wallet` balance checks |
| **Resend**, via the ncrypted API | Recipient email address, the share link (which includes the key) and an optional note. Relayed once and not stored by ncrypted. | Only when the user asks to email a link |
Retention: ciphertext is deleted on first read, when burned, or at expiry (at most 7 days). Receipt metadata is deleted 7 days after expiry. No analytics, no cookies. Details: [privacy policy](https://ncrypted.ai/privacy).
## Repo layout
| Path | What |
|---|---|
| `apps/web` | Next.js app on Vercel: API, viewer page, llms.txt, openapi.json |
| `packages/sdk` | `ncrypted` on npm: crypto, client, CLI |
| `packages/mcp` | `@seidl-family/ncrypted-mcp` on npm: stdio MCP server |
| `skills/ncrypted` | Agent Skill (`SKILL.md`) |
| `plugins/ncrypted` | Claude Code plugin; `.claude-plugin/marketplace.json` lists it |
| `server.json` | MCP Registry manifest (published by `.github/workflows/mcp-registry.yml`) |
## Development
```sh
npm install
npm test # crypto unit tests
cp apps/web/.env.example apps/web/.env.local # set NCRYPTED_PAY_TO
npm run dev # in-memory store when Redis isn't configured
npm run build && npm run e2e # needs .env.e2e with a funded Base Sepolia wallet
```
After editing `skills/ncrypted/SKILL.md`, run `npm run sync:skill`.
Tool-selection evals: `./scripts/run-evals.sh` runs `evals/` (14 cases, mocked MCP tools, ~$2.50) against a temporary copy of the plugin. Re-run after changing tool descriptions or the skill, and refresh `evals/mocks/ncrypted/_tools.json` from `tools/list` when tools change.
On each MCP release, bump the pinned version in `plugins/ncrypted/.mcp.json`, `plugins/ncrypted/package.json` (then `npm install --package-lock-only` there) and `gemini-extension.json` (the Claude directory rejects `@latest`), then run the "Publish to MCP Registry" workflow.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues