Version: 0.3.1 Date: 2025-11-11 Maintainer: Olivier Vitrac — Adservio Innovation Lab
- Overview
- Architecture
- Data Storage
- Server Modes
- Configuration
- Security Model
- API Reference
- Deployment
- Monitoring
- Troubleshooting
CloakMCP can operate in two modes:
- CLI Mode (default) — Direct command-line usage, no network involved
- Server Mode (optional) — FastAPI REST API for IDE integration
Important: CloakMCP is designed as a local-first tool. The server mode is for localhost-only integration with IDEs and tools, not for remote deployment.
┌─────────────────────────────────────────────────────────────┐
│ YOUR LOCAL MACHINE │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ VS Code │────────▶│ MCP Server │ │
│ │ │ HTTP │ 127.0.0.1: │ │
│ │ (or IDE) │ Request │ 8765 │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Policy Engine │ │
│ │ + Scanner │ │
│ └────────┬───────┘ │
│ │ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌──────────────┐ │
│ │ Encrypted Vault│ │ Audit Logs │ │
│ │ ~/.cloakmcp/ │ │ ./audit/ │ │
│ └─────────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
│
│ Sanitized output
│ (secrets replaced by tags)
▼
┌───────────────┐
│ LLM (Claude, │
│ Codex, etc) │
└───────────────┘
Key principle: Secrets never leave your machine. Only sanitized data (with tags) goes to LLMs.
Location: ~/.cloakmcp/vaults/
~/.cloakmcp/
├── keys/
│ └── <project-slug>.key # Fernet encryption key (600 perms)
└── vaults/
└── <project-slug>.vault # Encrypted JSON: {TAG → secret}
Details:
- Project slug: 16-character SHA-256 hash of project's absolute path
- Encryption: AES-128 via Python's
cryptography.Fernet - Permissions:
chmod 600(owner read/write only) - Storage format: Encrypted JSON
- Backup: Use
cloak vault-exportto create encrypted backups
Example:
# Project: /home/user/myproject
# Slug: 9f8e7d6c5b4a3210
# Vault: ~/.cloakmcp/vaults/9f8e7d6c5b4a3210.vault
# Key: ~/.cloakmcp/keys/9f8e7d6c5b4a3210.keyLocation: ./audit/audit.jsonl (inside project directory)
Format: JSON Lines (one JSON object per line)
{"ts": "2025-11-11T10:30:00+00:00", "rule_id": "aws_key", "action": "pseudonymize", "blocked": false, "start": 42, "end": 62, "value_hash": "sha256:abc123..."}Contents:
- Timestamp of detection
- Rule that matched
- Action taken (redact/pseudonymize/block)
- Whether action was blocked
- Position in file (start/end)
- SHA-256 hash of original value (for traceability)
Security:
- Original secrets are never logged
- Only hashes are stored for audit trail
Location: ./keys/mcp_hmac_key (inside project directory)
Purpose: Generate deterministic pseudonyms via HMAC-SHA256
Generation:
mkdir -p keys
openssl rand -hex 32 > keys/mcp_hmac_key
chmod 600 keys/mcp_hmac_keyImportant: Add keys/ to .gitignore to prevent committing
Location: ./examples/mcp_policy.yaml (or custom path)
Purpose: Define detection rules and actions
Storage: Plain text YAML (no secrets)
Usage: Direct command execution, no network involved
cloak scan --policy examples/mcp_policy.yaml --input file.py
cloak sanitize --policy examples/mcp_policy.yaml --input file.py --output -
cloak pack --policy examples/mcp_policy.yaml --dir /path/to/project
cloak unpack --dir /path/to/projectData flow:
File → Policy Engine → Action Engine → Output
↓ ↓
Scanner Vault (if pack/unpack)
Usage: FastAPI server for IDE/tool integration
# Install server dependencies (if not already)
pip install -e .
# Generate API token (one-time)
mkdir -p keys
openssl rand -hex 32 > keys/mcp_api_token
chmod 600 keys/mcp_api_token
# Start server (localhost only - DEFAULT - RECOMMENDED)
uvicorn cloak.server:app --host 127.0.0.1 --port 8765
# ⚠️ SECURITY WARNING: LAN/network access
# Only use --host 0.0.0.0 on fully trusted networks with proper firewall rules
# Exposing this server publicly transmits secrets over the network and defeats
# the entire security model of CloakMCP. Use TLS, authentication, and VPN.
# YOU HAVE BEEN WARNED.
uvicorn cloak.server:app --host 0.0.0.0 --port 8765 # NOT RECOMMENDED- Rate limiting: 10 requests/minute per IP (requires
slowapi) - Token authentication: Bearer token from
keys/mcp_api_token - Endpoints:
/health,/sanitize,/scan - API docs: http://127.0.0.1:8765/docs (OpenAPI/Swagger)
| Variable | Description | Default |
|---|---|---|
MCP_POLICY |
Path to policy YAML file | examples/mcp_policy.yaml |
MCP_VAULT_DIR |
Override vault storage location | ~/.cloakmcp |
MCP_AUDIT_DIR |
Override audit log location | ./audit |
File: mcp/server.py (modify if needed)
# Default policy
DEFAULT_POLICY = os.getenv("MCP_POLICY", "examples/mcp_policy.yaml")
# Rate limiting (if slowapi installed)
limiter = Limiter(
key_func=get_remote_address,
default_limits=["10/minute"] # Adjust as needed
)File: ~/.config/systemd/user/mcp-local.service
[Unit]
Description=CloakMCP Local Server
After=network-online.target
[Service]
WorkingDirectory=/path/to/CloakMCP
ExecStart=/usr/bin/env uvicorn cloak.server:app --host 127.0.0.1 --port 8765
Restart=on-failure
Environment=MCP_POLICY=examples/mcp_policy.yaml
[Install]
WantedBy=default.targetEnable:
systemctl --user daemon-reload
systemctl --user enable --now cloak-local.service
systemctl --user status cloak-local.serviceAssumptions:
- Local machine is trusted (filesystem, processes)
- Vault encryption key remains local and secure
- Network between IDE and localhost server is secure (loopback)
- LLM provider is untrusted (may log all data sent to it)
Protections:
- Secrets never leave local machine — Only tags are sent to LLM
- Vault is encrypted — AES-128 Fernet with per-project keys
- Deterministic tags — Same secret → same tag (enables stable diffs)
- Audit trail — All operations logged with hashes (not plaintext)
- Rate limiting — Protects server from brute-force attacks
- Token authentication — Prevents unauthorized API access
Mitigation: Secrets are replaced with tags like TAG-2f1a8e3c9b12. LLM only sees tags, never original secrets.
Mitigation: Server binds to 127.0.0.1 (localhost only). No network traffic leaves machine.
Mitigation: Vault is encrypted. Attacker needs both .vault file AND .key file to decrypt.
Mitigation: Vaults are stored in ~/.cloakmcp/, NOT in project directory. .gitignore excludes keys/ and audit/.
1. cloak pack --dir /project # Secrets → tags, vault updated
2. git commit -am "Add feature" # Only tags committed
3. Share code with LLM # LLM sees tags, not secrets
4. cloak unpack --dir /project # Tags → secrets restored locally
Description: Health check endpoint
Authentication: Bearer token required
Response:
{
"status": "ok",
"policy_path": "examples/mcp_policy.yaml",
"policy_sha256": "abc123..."
}Description: Sanitize text (replace secrets with tags)
Authentication: Bearer token required
Request:
{
"text": "Email: alice@secret.com\nAPI Key: AKIAIOSFODNN7EXAMPLE",
"policy_path": "examples/mcp_policy.yaml",
"dry_run": false
}Response:
{
"sanitized": "Email: <EMAIL:a1b2c3d4>\nAPI Key: <REDACTED:aws_key>",
"blocked": false,
"policy_sha256": "abc123..."
}Description: Scan text (detect secrets without modification)
Authentication: Bearer token required
Request:
{
"text": "Email: alice@secret.com",
"policy_path": "examples/mcp_policy.yaml",
"dry_run": true
}Response: Same as /sanitize but sanitized field is unchanged
All endpoints require a Bearer token:
TOKEN=$(cat keys/mcp_api_token)
curl -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"text":"test@example.com","dry_run":false}' \
http://127.0.0.1:8765/sanitize# 1. Install dependencies
pip install -e .
# 2. Generate keys
mkdir -p keys
openssl rand -hex 32 > keys/mcp_hmac_key
openssl rand -hex 32 > keys/mcp_api_token
# 3. Start server
uvicorn cloak.server:app --host 127.0.0.1 --port 8765 --reload🚨 CRITICAL SECURITY WARNING 🚨:
DO NOT expose CloakMCP server to the public internet or untrusted networks.
When you use --host 0.0.0.0, you are transmitting secrets over the network, which defeats the core security model of CloakMCP (local-only secret storage).
Only proceed if:
- You have a fully trusted, firewalled local network
- You use TLS termination with valid certificates
- You have strong authentication (rotate tokens regularly)
- You understand the risks of network-based secret transmission
RECOMMENDED: Use --host 127.0.0.1 (localhost only) and never expose beyond your machine.
# 1. Install with security dependencies
pip install -e . slowapi
# 2. Generate strong tokens
openssl rand -hex 64 > keys/mcp_api_token
# 3. Configure firewall (restrict to LAN subnet)
sudo ufw allow from 192.168.1.0/24 to any port 8765
# 4. Start with host binding
uvicorn cloak.server:app --host 0.0.0.0 --port 8765 --workers 2
# 5. Use systemd for persistence (see Configuration section)🚨 STRONGLY NOT RECOMMENDED 🚨:
Docker containers inherently expose services over network interfaces. Using CloakMCP in Docker:
- Requires
--host 0.0.0.0which transmits secrets over network - Adds container orchestration as attack surface
- Defeats the "local-first" security model
ONLY use Docker if:
- You bind to localhost only (
-p 127.0.0.1:8765:8765) - Container runs on the same machine as the user
- You fully understand the security implications
If you must use Docker (for testing/development only):
FROM python:3.10-slim
WORKDIR /app
COPY . .
RUN pip install -e .
# Mount volumes for persistent data
VOLUME ["/root/.cloakmcp", "/app/keys", "/app/audit"]
CMD ["uvicorn", "cloak.server:app", "--host", "0.0.0.0", "--port", "8765"]docker run -it --rm \
-v ~/.cloakmcp:/root/.cloakmcp \
-v $(pwd)/keys:/app/keys \
-v $(pwd)/audit:/app/audit \
-p 127.0.0.1:8765:8765 \
cloakmcp# Check server status
curl -H "Authorization: Bearer $(cat keys/mcp_api_token)" \
http://127.0.0.1:8765/health
# Check rate limiting
for i in {1..15}; do
curl -H "Authorization: Bearer $(cat keys/mcp_api_token)" \
http://127.0.0.1:8765/health
echo "Request $i"
done# View recent operations
tail -f audit/audit.jsonl | jq .
# Count operations by rule
cat audit/audit.jsonl | jq -r .rule_id | sort | uniq -c
# Find blocked operations
cat audit/audit.jsonl | jq 'select(.blocked == true)'# Check vault contents (encrypted, safe to inspect)
cloak vault-stats --dir /path/to/project
# Output:
# Vault statistics for: /path/to/project
# Project slug: 9f8e7d6c5b4a3210
# Total secrets: 42
# Unique tags: 42
# Vault location: ~/.cloakmcp/vaults/9f8e7d6c5b4a3210.vaultError: Address already in use
Solution:
# Find process using port 8765
lsof -i :8765
kill <PID>
# Or use different port
uvicorn cloak.server:app --host 127.0.0.1 --port 8766Error: 401 Unauthorized
Solution:
# Regenerate token
openssl rand -hex 32 > keys/mcp_api_token
# Restart server
pkill -f "uvicorn cloak.server"
uvicorn cloak.server:app --host 127.0.0.1 --port 8765Error: 429 Too Many Requests
Solution:
# Wait 60 seconds, or increase limit in mcp/server.py:
# default_limits=["20/minute"] # Increase from 10Error: cryptography.fernet.InvalidToken
Solution:
# Key file may be corrupted
# Restore from backup if available:
cp .backups/latest/keys/<slug>.key ~/.cloakmcp/keys/
# Or regenerate (WARNING: loses all vaulted secrets):
rm ~/.cloakmcp/vaults/<slug>.vault
rm ~/.cloakmcp/keys/<slug>.key
cloak pack --policy examples/mcp_policy.yaml --dir /projectWarning: Rate limiting disabled: slowapi not installed
Solution:
pip install slowapi
# Restart server to enable rate limiting- Never expose server to public internet — Use localhost or trusted LAN only
- Rotate API tokens regularly — Especially if server is LAN-accessible
- Backup vaults before major operations — Use
cloak vault-export - Monitor audit logs — Set up alerts for blocked operations
- Use strong HMAC keys — Minimum 32 bytes (256 bits)
- Enable HMAC key caching — Already enabled in v0.2.5 (100-1000× speedup)
- Use pack/unpack for batch operations — More efficient than per-file sanitize
- Tune rate limits — Adjust based on your IDE's request patterns
- Keep policy files small — Large regex lists slow down scanning
- Version control policy files — Track changes to detection rules
- Document custom rules — Add comments in YAML policy
- Test policies before deployment — Use
cloak scan --dry-run - Automate backups — Schedule
cloak vault-exportvia cron
A: Not recommended. CloakMCP is designed for local operation. Running remotely means secrets transit the network (defeating the purpose). If you must, use VPN + TLS.
A: ~/.cloakmcp/keys/<project-slug>.key on your local machine. Each project gets a unique encryption key.
A: Yes, but securely:
- Export vault:
cloak vault-export --dir /project --output backup.vault - Transfer encrypted file via secure channel (already encrypted)
- Import on teammate's machine:
cloak vault-import --dir /project --input backup.vault
A: Encrypted secrets are permanently unrecoverable. Always:
- Backup keys securely (e.g., password manager, encrypted USB)
- Keep original unmodified code as ultimate backup
A: No. Tags are deterministic hashes (SHA-256) truncated to 12 hex chars. Without the original secret or HMAC key, reversal is computationally infeasible (2^48 brute-force space minimum).
A: Only to audit logs (with hashes, not plaintext). Uvicorn access logs can be disabled:
uvicorn cloak.server:app --host 127.0.0.1 --port 8765 --log-level warning- ../README.md — Quick start and overview
- VSCODE_MANUAL.md — IDE integration guide
- QUICKREF.md — One-page command reference
- ../SECURITY.md — Security policy and disclosure
Prepared by: Olivier Vitrac — Adservio Innovation Lab Date: 2025-11-11 License: MIT Project: CloakMCP v0.3.1