MCP-Vault
Model Context Protocol (MCP) server for HashiCorp Vault secret management via claude-vault.
This MCP server exposes Vault operations as tools that Claude Code can use for AI-assisted secret management, while maintaining the existing security model with human confirmation for write operations.
Features
- ✅ 7 MCP Tools: Complete Vault operations (login, status, logout, list, get, set, inject)
- 🔐 Security-First: Human confirmation required for write operations
- 📝 Audit Logging: All operations logged to
.claude-vault-audit.log - ⏱️ Session-Based: 60-minute token expiry, no persistent credentials
- 🛡️ Input Validation: Prevents injection attacks and path traversal
- 🔍 Pattern Detection: Scans for dangerous patterns in secret values
Architecture
User authenticates → VAULT_TOKEN exported → MCP server reads env → Claude uses tools
Security Model:
- Human authenticates via OIDC + MFA (
source claude-vault login) - Token stored in environment variables (memory only, 60 min TTL)
- MCP server reads token from environment
- Write operations require human to type "yes"
- All operations audited
Quick Start
1. Installation
cd /path/to/claude-vault/packages/mcp-server
# Install in development mode
pip install -e .
# Or install from PyPI (when published)
pip install claude-vault-mcp
2. Configure MCP Server (One-time)
Option 1: Use .mcp.json (Project Scope - Recommended)
Copy the example configuration:
# Copy example to your project root
cp .mcp.json.example /your/project/.mcp.json
# Edit to set your Vault address
vim /your/project/.mcp.json
Edit .mcp.json to point to your claude-vault installation:
{
"mcpServers": {
"claude-vault": {
"type": "stdio",
"command": "uvx",
"args": [
"--from",
"/path/to/claude-vault/packages/mcp-server",
"claude-vault-mcp"
],
"env": {
"VAULT_ADDR": "https://vault.example.com"
}
}
}
}
Option 2: Add via Claude CLI
# Add MCP server with project scope
claude mcp add --transport stdio claude-vault --scope project \
--env VAULT_ADDR=https://vault.example.com \
-- uvx --from /path/to/claude-vault/packages/mcp-server claude-vault-mcp
Verify Configuration:
# Check MCP server status
claude mcp get claude-vault
# Should show: Status: ✓ Connected
3. Authenticate to Vault (Daily)
# Authenticate (opens browser for OIDC + MFA)
source claude-vault login
# Verify session (shows token expiry time)
claude-vault status
Session Management:
- Sessions are valid for 60 minutes
- VAULT_TOKEN is stored in environment variables (memory only)
- Claude Code inherits the token from your current shell
- If session expires: Re-authenticate with
source claude-vault login
4. Use Vault Tools in Claude Code
The MCP server exposes 7 tools that Claude can use automatically:
# Ask Claude to interact with Vault:
Claude, list all services in Vault
Claude, get the wifi_ssid secret for esphome
Claude, register DB credentials for myapp: DB_USER="admin" DB_PASS="secret"
Claude, inject esphome secrets to .env file
Available via /mcp command:
- Type
/mcpin Claude Code to see all available MCP servers and tools - Tools appear automatically in Claude's context when relevant
Available Tools
Authentication
vault_login - Guide user through OIDC authentication
- Provides instructions for
source claude-vault login - Cannot directly update environment (requires MCP restart)
vault_status - Check session validity
- Shows user, policies, time remaining
- Validates token with Vault
vault_logout - Revoke token
- Invalidates session in Vault
- Provides cleanup instructions
Read Operations
vault_list - List services or secrets
- No arguments: Lists all services
- With
service: Lists secret keys (names only)
vault_get - Retrieve secret values
- Required:
service - Optional:
key(specific secret) - ⚠️ Returns actual secret values
Write Operations
vault_set - Create or update secrets
- Required:
service,secrets(dict) - Optional:
dry_run(boolean) - Requires human confirmation (must type "yes")
- Validates inputs, detects dangerous patterns
- Logs to audit file
Injection
vault_inject - Generate .env or secrets.yaml
- Required:
service - Optional:
format(auto/env/yaml) - Backs up existing files
- Calls existing
inject-secrets.shscript
Security Features
Input Validation
- Service names:
^[a-zA-Z0-9_-]{1,64}$ - Key names:
^[a-zA-Z0-9_-]{1,128}$ - Value size: Max 8KB
- No path traversal: Rejects
..,/
Dangerous Pattern Detection
Scans secret values for:
- Command substitution:
$(...), backticks - Shell operators:
&&,||,; - Variable expansion:
${...} - Control characters: newlines, carriage returns
Confirmation Checkpoint
For vault_set, displays:
⚠️ SECURITY CHECKPOINT - MANUAL VALIDATION REQUIRED
You are about to write secrets to Vault:
Service: myapp
Action: CREATE
Path: secret/proxmox-services/myapp
Secrets to be written:
+ DB_PASSWORD
+ API_KEY
Type 'yes' to proceed, or anything else to abort:
Claude MUST wait for human response - cannot automatically confirm.
Audit Logging
Format: [timestamp] USER=mcp-server ACTION=X SERVICE=Y DETAILS=Z
Logged actions:
CONFIRMATION_REQUIRED- Waiting for userCONFIRMED- User typed "yes"ABORTED- User declinedSUCCESS- Write succeededFAILED- Write failedVALIDATION_FAILED- Input rejected
Daily Workflow
Morning Setup
# Authenticate (opens browser for OIDC + MFA)
source claude-vault login
# Verify session
claude-vault status
# Start working with Claude Code (MCP server auto-connects)
During Work
- Session valid for 60 minutes
- Claude Code automatically uses vault tools when relevant
- Write operations pause for confirmation (you must type "yes")
- Check available tools: Type
/mcpin Claude Code - If session expires: Re-authenticate with
source claude-vault login
End of Day
# Optional: Explicitly logout
source claude-vault logout
# Or: Session auto-expires after 60 minutes
Example Usage
List all services
Claude: "List all services in Vault"
→ vault_list (no arguments)
→ Shows: esphome, authentik, bitwarden, ...
Get secrets for a service
Claude: "Get the wifi_ssid secret for esphome"
→ vault_get(service="esphome", key="wifi_ssid")
→ Returns: "MyHomeWiFi"
Register new secrets
Claude: "Register DB credentials for myapp"
→ vault_set(service="myapp", secrets={"DB_USER": "admin", "DB_PASS": "secret"})
→ Displays confirmation prompt
→ User types "yes"
→ Writes to Vault
Inject to .env
Claude: "Inject esphome secrets to .env file"
→ vault_inject(service="esphome", format="env")
→ Creates esphome/.env with all secrets
Troubleshooting
"No Vault session found"
Cause: VAULT_TOKEN not in environment
Solution:
source claude-vault login
# Restart MCP server
"Session expired"
Cause: 60-minute TTL exceeded
Solution:
source claude-vault login
# MCP server will automatically reconnect with new token
"Permission denied" (HTTP 403)
Cause: Token lacks required policies
Solution:
- Verify policies in Vault UI
- Ensure token has
homelab-servicespolicy - Re-authenticate if needed
Tools not appearing in Claude Code
Cause: MCP server not started or misconfigured
Solution:
- Verify MCP server is configured:
claude mcp get claude-vault - Check connection status (should show "✓ Connected")
- Type
/mcpin Claude Code to see all available tools - If not working, try:
claude mcp remove claude-vault -s projectthen re-add - Check you're in the
/workspace/proxmox-servicesdirectory (where.mcp.jsonexists)
Development
Project Structure
claude-vault-mcp/
├── pyproject.toml # Package config
├── README.md # This file
├── src/
│ └── claude_vault_mcp/
│ ├── __init__.py # Entry point with main()
│ ├── server.py # MCP server setup
│ ├── session.py # Env-based auth
│ ├── vault_client.py # HTTP API client
│ ├── security.py # Validation & audit
│ └── tools/
│ ├── read.py # status, list, get
│ ├── write.py # set (with confirmation)
│ ├── auth.py # login, logout
│ └── inject.py # inject
Testing
# Install with dev dependencies
pip install -e ".[dev]"
# Run MCP Inspector for debugging
npx @modelcontextprotocol/inspector claude-vault-mcp
# Manual test
claude-vault-mcp
# (Starts stdio server, send JSON-RPC requests)
Adding a New Tool
- Create tool handler in appropriate file (read/write/auth/inject)
- Inherit from
ToolHandlerbase class - Implement
get_tool_description()andrun_tool() - Register in
server.pyTOOL_HANDLERS dict
Security Considerations
DO:
- ✅ Always require human confirmation for writes
- ✅ Validate all inputs
- ✅ Log all operations
- ✅ Use environment variables for tokens (memory only)
- ✅ Set short TTL (60 minutes)
DON'T:
- ❌ Store tokens in files
- ❌ Skip confirmation prompts
- ❌ Allow Claude to auto-confirm writes
- ❌ Disable input validation
- ❌ Ignore dangerous patterns
License
MIT
Contributing
- Fork the repository
- Create feature branch
- Add tests
- Submit pull request
Support
For issues or questions:
- Check troubleshooting section
- Review audit logs:
.claude-vault-audit.log - Verify Vault session:
claude-vault status - Check Claude logs for MCP errors
Metadata
Release files for claude-vault-mcp 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| claude_vault_mcp-1.4.0.tar.gz | 111.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| claude_vault_mcp-1.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 171.7 kB
Release files / claude_vault_mcp-1.4.0.tar.gz
| Download URL | claude_vault_mcp-1.4.0.tar.gz |
|---|---|
| Size | 111.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d02772cd411a8a5eef4bb11262a4340fcfe55198c4cdd7d26deeb44d62a5d28
|
|
BLAKE2b-256 checksum How to use checksums |
19aec00c12f1a91b5f99d298f5918de8dc2c8476b19d4745e0a27ab976725f15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / claude_vault_mcp-1.4.0-py3-none-any.whl
| Download URL | claude_vault_mcp-1.4.0-py3-none-any.whl |
|---|---|
| Size | 60.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ed526224ea54e70bb216ee71d126b02241c15fae4016657f39651cf5ef8cee2
|
|
BLAKE2b-256 checksum How to use checksums |
f8a23736ed718303fd87e5da8114585645013557083c8583062fb8477e379f5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|