MCP App for secure, self-destructing secret sharing with client-side encryption
OneTime Secret MCP App
A privacy-focused secret sharing application built with the Model Context Protocol (MCP). Share encrypted secrets that self-destruct after viewing.
Version: 1.1.0 | Status: Production Ready
Features
- Zero-Knowledge Encryption - Secrets are encrypted client-side using AES-256-GCM. Server never sees plaintext.
- Self-Destructing - Secrets automatically expire after time limit or view count.
- Link-Based Sharing - Generate shareable URLs for easy distribution.
- MCP Integration - Use directly from Claude Desktop or other MCP clients.
- Standalone UI - Non-Claude users can view secrets via simple web interface.
- Cloudflare Backend - Serverless storage with global edge network.
Architecture
┌─────────────────┐
│ Claude Desktop │
│ (MCP Client) │
└────────┬────────┘
│
│ MCP Protocol
│
┌────────▼────────┐
│ MCP Server │
│ (main.ts) │
└────────┬────────┘
│
│ REST API
│
┌────────▼────────────────┐
│ Cloudflare Worker │
│ - REST API │
│ - Serves reveal.html │
│ - KV Storage │
└─────────────────────────┘
The server never sees the plaintext secret or the passphrase - all encryption/decryption happens client-side.
Quick Start
Installation
npm install
Development
- Start Worker (local):
npm run worker:dev
- Start MCP server with MCP app:
npm start
- Add to Claude Desktop config:
{
"mcpServers": {
"onetimesecret": {
"command": "node",
"args": ["/path/to/onetimesecret-mcp/dist/main.js"],
"env": {
"CLOUDFLARE_WORKER_URL": "http://localhost:8787"
}
}
}
}
Usage
From Claude Desktop
- Open MCP App from Claude
- Create secret with passphrase
- Share the generated link
From MCP Tools
Ask Claude to create a secret:
Create a secret with the message "Hello World" using passphrase "test123"
Revealing Secrets
Recipients can:
- Open the shareable link (e.g.,
https://worker.dev/s/{id}) - Enter the passphrase
- View the secret (one-time or limited views)
Deployment
See DEPLOYMENT.md for full deployment guide.
Quick deploy:
# Create KV namespace
npm run worker:create-kv
# Build all components
npm run build
# Deploy Worker
npm run worker:deploy
# Update .env with deployed URL
echo "CLOUDFLARE_WORKER_URL=https://your-worker.workers.dev" > .env
API Endpoints
POST /secrets
Create a new secret.
Request:
{
"encryptedData": "base64...",
"iv": "base64...",
"ttlMinutes": 60,
"maxViews": 1
}
Response:
{
"success": true,
"secretId": "uuid",
"expiresAt": "2024-01-01T00:00:00.000Z",
"maxViews": 1
}
GET /secrets/:id
Retrieve and optionally destroy secret.
Response:
{
"success": true,
"encryptedData": "base64...",
"iv": "base64...",
"destroyed": true,
"viewsRemaining": 0
}
GET /secrets/:id/status
Check if secret exists without revealing.
Response:
{
"exists": true,
"expiresAt": "2024-01-01T00:00:00.000Z",
"viewsRemaining": 1
}
GET /s/:id
Serve reveal page for secret.
GET /health
Health check endpoint.
MCP Tools
create-secret
Create a new encrypted secret.
Arguments:
encryptedData(string): Base64-encoded encrypted dataiv(string): Base64-encoded initialization vectorttlMinutes(number, optional): Time to live in minutes (default: 60, max: 10080)maxViews(number, optional): Maximum views before destruction (default: 1)
reveal-secret
Retrieve an encrypted secret.
Arguments:
secretId(string): UUID of the secret
check-secret-status
Check if a secret exists without revealing it.
Arguments:
secretId(string): UUID of the secret
Security
Encryption Flow
-
Client-side encryption:
- Generate random 16-byte salt
- Derive key from passphrase using PBKDF2 (100k iterations, SHA-256)
- Encrypt with AES-256-GCM
- Send encrypted blob + IV to server
-
Server storage:
- Store encrypted data with metadata
- Never sees passphrase or plaintext
- Automatic expiration via KV TTL
-
Client-side decryption:
- Retrieve encrypted blob + IV
- Derive key from user-provided passphrase
- Decrypt locally in browser
Sharing Options
| Method | Security Level | Description | |--------|---------------|-------------| | ID + separate passphrase | High | Share ID and passphrase through different channels | | URL with ID only | Medium-High | Share URL, passphrase separately | | URL with fragment (#key) | Medium | Single-link sharing (passphrase in URL fragment) |
Development
Project Structure
onetimesecret-mcp/
├── src/
│ ├── mcp-app.ts # MCP app UI logic
│ └── reveal.ts # Standalone reveal page logic
├── worker/
│ └── index.ts # Cloudflare Worker
├── mcp-app.html # MCP app UI (full features)
├── reveal.html # Standalone reveal page
├── main.ts # MCP server
├── wrangler.toml # Cloudflare Worker config
└── package.json
Build Commands
npm run build- Build all componentsnpm run build:reveal- Build only reveal pagenpm run start- Development mode (watch + server)npm run worker:dev- Run Worker locallynpm run worker:deploy- Deploy Worker to Cloudflare
Roadmap
See TODO.md for detailed roadmap.
Phase 1: Cloudflare Backend (Completed)
- REST API with KV storage
- Automatic expiration
- View count tracking
Phase 2: Link-based Sharing (Completed)
- Shareable URLs
- Standalone reveal page
- Fragment-based one-click links
Phase 3: Enhancements
- Password-protected secrets
- File attachment support
- Burn notifications
- Rate limiting
- Admin dashboard
License
MIT