Enpass MCP
Lee y escribe bóvedas locales de Enpass: entradas, contraseñas y códigos TOTP, con la contraseña maestra tomada del llavero del sistema operativo para que nunca llegue al modelo.
Documentación
enpass-mcp
Un servidor Model Context Protocol (MCP) que brinda a un asistente de IA acceso controlado y local a tus Enpass bóvedas de contraseñas: desbloquear una bóveda, listar bóvedas, y listar y leer entradas. Crear y eliminar entradas también es posible, pero está desactivado hasta que lo habilites.
Se ejecuta localmente a través de stdio. Tu bóveda de Enpass nunca sale de tu máquina, y tu contraseña maestra nunca pasa por el modelo: se almacena en el llavero de tu sistema operativo y el servidor la lee directamente.
Por qué esto es seguro
- Las contraseñas maestras viven en el llavero del sistema operativo (Llavero de macOS, Administrador de credenciales de Windows,
Servicio secreto de Linux), no en archivos de configuración, no en variables de entorno,
y nunca como argumento de una herramienta. La herramienta
unlock_vaultdeliberadamente no toma parámetro de contraseña, por lo que la contraseña nunca puede terminar en el contexto del modelo ni en registros. - La bóveda permanece local. El servidor lee el archivo
vault.enpassdbcifrado directamente con SQLCipher. Nada se sube a ningún lugar. - Las lecturas son explícitas. Listar entradas nunca devuelve contraseñas. Los secretos solo se
devuelven mediante
get_item/get_password, cuando los solicitas explícitamente. - Solo lectura a menos que indiques lo contrario. De fábrica, el servidor no puede cambiar
nada: las herramientas de escritura ni siquiera se anuncian. Establece
ENPASS_MCP_ALLOW_WRITES=1para habilitarlas (consulta Escritura).
Las contraseñas de las entradas, por diseño, se devuelven al asistente cuando las solicitas, así que solo conecta esto a un asistente y bóvedas en los que confíes.
Requisitos
- Node.js 18 o más reciente
- Una bóveda de Enpass 6 / 7 / 8 (
vault.enpassdb, formato SQLCipher) - En Linux: un proveedor de Servicio secreto (GNOME Keyring o KWallet) para el almacenamiento de contraseñas
Las dependencias nativas (better-sqlite3-multiple-ciphers, @napi-rs/keyring) incluyen
binarios precompilados para plataformas comunes, por lo que no se requiere compilador en el caso normal.
Instalación
git clone https://github.com/bitterdev/enpass-mcp.git
cd enpass-mcp
npm install
npm link # optional: makes the `enpass-mcp` command available globally
Registra tus bóvedas (hazlo una vez, en una terminal)
Este es el paso seguro que mantiene la contraseña maestra alejada del modelo. Lo ejecutas tú mismo; la contraseña se escribe en un mensaje oculto y se almacena en el llavero del sistema operativo.
# Find your vault files automatically
enpass-mcp discover
# Register a vault (you will be prompted for the master password)
enpass-mcp add-vault personal --path "/Users/you/Documents/Enpass/Vaults/primary/vault.enpassdb"
enpass-mcp add-vault work --path "/path/to/work/vault.enpassdb"
# With a keyfile
enpass-mcp add-vault personal --path "/path/vault.enpassdb" --keyfile "/path/vault.keyfile"
# Manage
enpass-mcp list-vaults
enpass-mcp test-unlock personal
enpass-mcp remove-vault work
add-vault verifica que la contraseña realmente pueda desbloquear la bóveda antes de guardarla.
El archivo de la bóveda generalmente se encuentra en:
| SO | Ubicación típica |
|---|---|
| macOS | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
| Windows | %USERPROFILE%\Documents\Enpass\Vaults\<vault>\vault.enpassdb |
| Linux | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
Si sincronizas a través de Dropbox / OneDrive / WebDAV, apunta --path a la copia sincronizada.
Conéctalo a tu asistente
El servidor habla MCP a través de stdio. Apunta tu cliente MCP a enpass-mcp serve.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"enpass": {
"command": "enpass-mcp",
"args": ["serve"]
}
}
}
Si no ejecutaste npm link, usa la ruta absoluta en su lugar:
{
"mcpServers": {
"enpass": {
"command": "node",
"args": ["/absolute/path/to/enpass-mcp/src/cli.js", "serve"]
}
}
}
Claude Code:
claude mcp add enpass -- enpass-mcp serve
Herramientas
| Herramienta | Descripción |
|---|---|
list_vaults | Lista las bóvedas registradas, si su archivo existe, si hay una contraseña almacenada y si están desbloqueadas. |
unlock_vault | Desbloquea una bóveda usando la contraseña maestra del llavero del sistema operativo. Solo toma un nombre de bóveda, nunca una contraseña. |
lock_vault | Bloquea una bóveda y borra su clave derivada de la memoria. |
list_items | Lista entradas (título, nombre de usuario, URL). Nunca devuelve contraseñas. Admite query, category, folder, limit. |
get_item | Devuelve una entrada completa, incluidos todos los valores de campos (contraseña, TOTP, etc.) y su lista de adjuntos. |
get_password | Devuelve la contraseña y, si está presente, el código TOTP actual de una entrada. |
get_otp | Genera el código de un solo uso TOTP / 2FA actual para una entrada, con los segundos hasta que rote. |
list_attachments | Lista los adjuntos de archivo de una entrada (nombre, tamaño, MIME). |
export_attachment | Descifra un adjunto; lo escribe en disco y devuelve la ruta (o base64 en línea para archivos pequeños). |
sync_status | Lista las bóvedas que usan sincronización de carpetas de Enpass y si la copia en la carpeta de sincronización es más reciente. |
Con ENPASS_MCP_ALLOW_WRITES=1 aparecen tres herramientas más (consulta Escritura):
| Herramienta | Descripción |
|---|---|
create_item | Crea una entrada, incluidos campos personalizados; los valores sensibles se cifran de la manera que Enpass lo hace. |
delete_item | Elimina una entrada, o muévela a la papelera, dejando la marca que Enpass usa para que la eliminación se sincronice. |
sync_pull | Toma una copia más reciente de la carpeta de sincronización, después de respaldar la bóveda local. |
list_items / get_item funcionan para cada tipo de entrada de Enpass (inicios de sesión, tarjetas
de crédito, notas seguras, identidades, etc.), no solo inicios de sesión, y devuelven todos los campos.
Un flujo típico de asistente: list_vaults → unlock_vault → list_items → get_password.
Cómo funciona
Enpass almacena cada bóveda como una base de datos SQLCipher estándar (vault.enpassdb). La clave
de cifrado sin procesar se deriva de tu contraseña maestra (opcionalmente combinada con un
archivo de clave) y la sal de 16 bytes al inicio del archivo:
- PBKDF2-HMAC-SHA512, 100000 iteraciones (bóvedas más antiguas) o 320000 (bóvedas más nuevas), los primeros 32 bytes se usan como la clave SQLCipher sin procesar
- abierto con
cipher_compatibility4 (Enpass 6.8+) o 3 (bóvedas más antiguas)
El servidor prueba estas combinaciones automáticamente, por lo que funciona en todas las versiones de bóvedas de Enpass. La clave derivada se mantiene solo en memoria, durante la vida útil del proceso del servidor, y nunca se escribe en disco ni se devuelve al modelo.
Referencias: Libro blanco de seguridad de Enpass, hazcod/enpass-cli.
Cifrado de campos por elemento
Enpass cifra cada valor marcado como "sensible" una segunda vez, debajo
de SQLCipher, con una clave que pertenece a la entrada en lugar de a la bóveda. Los campos
que llevan esa capa tienen itemfield.algo_version = 1:
| Pieza | Dónde | Diseño |
|---|---|---|
| Clave y nonce | item.key | 44 bytes: clave AES-256 de 32 bytes, luego un nonce GCM de 12 bytes |
| Valor | itemfield.value | hexadecimal de ciphertext || 16-byte GCM tag |
| Datos adicionales | el uuid de la entrada | sin guiones, decodificado en hexadecimal a 16 bytes sin procesar |
Vincular el AAD al uuid de la entrada es lo que hace que un valor sea inutilizable si se copia en
otra entrada. Enpass no volvió a cifrar las entradas existentes cuando introdujo esta
capa, por lo que una bóveda mezcla texto cifrado y texto plano bajo el mismo algo_version; un
valor se trata como cifrado solo cuando tiene la forma de una carga útil (hexadecimal puro, bytes
completos, más largo que la etiqueta por sí solo).
Un valor que parece cifrado pero falla la autenticación se devuelve como null con
decryptionFailed: true, nunca como el contenido de la columna sin procesar: el texto cifrado almacenado es una
cadena de apariencia plausible, y devolverlo pasaría silenciosamente un secreto incorrecto
como uno real.
Códigos de dos factores (TOTP)
Las entradas con un secreto de contraseña de un solo uso (almacenado por Enpass como un URI otpauth://)
pueden producir un código 2FA en vivo: get_otp devuelve el código actual de 6 dígitos y los
segundos hasta que rote, y get_password incluye el código actual junto con la
contraseña. Esto permite que un asistente complete tanto la contraseña como el mensaje de 2FA.
Adjuntos
Enpass mantiene los adjuntos de archivos cifrados. Los archivos pequeños (hasta 1 KB) se encuentran en línea en la
bóveda; los archivos más grandes viven en archivos SQLCipher <uuid>.enpassattach separados junto a la
bóveda, cada uno cifrado con su propia clave almacenada en la bóveda. export_attachment maneja
ambos: descifra el archivo y, de forma predeterminada, lo escribe en disco y devuelve la ruta, por lo que
funciona para archivos de cualquier tamaño sin enviar datos binarios a través del modelo.
El manejo de adjuntos externos se implementa a partir del formato documentado de Enpass. Si encuentras
una bóveda cuyos adjuntos no se descifran, abre un problema con el esquema (no secreto) de tu tabla attachment.
Escritura (opt-in)
La escritura está desactivada de forma predeterminada. Una bóveda de contraseñas es el último lugar donde una herramienta
debería poder cambiar datos solo porque un modelo lo decidió, por lo que el servidor comienza
en modo solo lectura y ni siquiera lista create_item, delete_item y sync_pull hasta que
los actives:
ENPASS_MCP_ALLOW_WRITES=1
Establécelo en el entorno del servidor (en la configuración de tu cliente MCP, o en el .env junto a
vaults.json). Nada más cambia: la lectura funciona exactamente igual de cualquier manera.
Enpass debe estar cerrado mientras se escribe. La aplicación mantiene la base de datos en memoria y escribiría su propia copia en caché sobre cualquier cambio realizado debajo. Cada herramienta de escritura se niega a ejecutarse mientras Enpass esté abierto.
Las versiones anteriores de este README afirmaban que la escritura era imposible porque las bóvedas recientes (versión de esquema 6) hacen que Enpass se bloquee cuando se insertan entradas directamente. El bloqueo era real, el diagnóstico era incorrecto. Tres reglas concretas lo hacen funcionar, todas derivadas de lo que el propio Enpass escribe:
- Enpass nunca almacena
NULL. El bloqueo esEXC_BAD_ACCESSenstrlenen un puntero nulo: una columna omitida delINSERTpredetermina aNULL, y la aplicación llama astrlenen ella. Cada columna se escribe explícitamente, cadenas vacías en lugar deNULL. - Una plantilla tiene un conjunto de campos fijo.
login.defaultsiempre lleva los mismos nueve campos, en el mismo orden, con los mismos uids de campo, incluso cuando la mayoría están vacíos. Escribir solo los campos para los que tienes un valor produce una entrada que la aplicación no puede renderizar. - La clave por elemento es reproducible.
item.keyes una clave AES-256 de 32 bytes más un nonce GCM de 12 bytes, almacenada comohex(ciphertext || tag)con el UUID del elemento como datos autenticados adicionales. Nada en ella está vinculado a los internos de Enpass, por lo que una nueva clave aleatoria por elemento es suficiente.
Verificado de extremo a extremo contra una bóveda real: escrita, leída de vuelta, descifrada al original, eliminada, sincronizada en ambas direcciones, y Enpass abre la bóveda sin bloquearse.
Configuración
Las contraseñas maestras están en el llavero del sistema operativo; solo los datos no secretos (nombres y rutas de bóvedas)
se almacenan en un pequeño vaults.json:
- macOS:
~/Library/Application Support/enpass-mcp/vaults.json - Windows:
%APPDATA%\enpass-mcp\vaults.json - Linux:
~/.config/enpass-mcp/vaults.json
Anula el directorio con ENPASS_MCP_CONFIG_DIR.
Variables de entorno:
| Variable | Efecto |
|---|---|
ENPASS_MCP_ALLOW_WRITES | 1, true, yes o on habilita las herramientas de escritura. Cualquier otra cosa, incluido sin establecer, mantiene el servidor en solo lectura. |
ENPASS_MCP_CONFIG_DIR | Dónde viven vaults.json y el .env opcional. |
ENPASS_MASTER_PASSWORD | Contraseña maestra de respaldo opcional para bóvedas sin entrada de llavero. Prefiere el llavero. |
ENPASS_MASTER_PASSWORD_<VAULT> | Igual, para una bóveda específica. |
Desarrollo
npm test # runs against genuine SQLCipher fixtures in test/fixtures
# Rebuild the fixtures from scratch with real SQLCipher (vault + entries + attachments)
npm install --no-save @journeyapps/sqlcipher
npm run generate-fixtures
CI (GitHub Actions) crea una bóveda desde cero con SQLCipher real, siembra entradas y adjuntos, luego ejecuta la suite de pruebas completa de solo lectura en Node 18/20/22.
Notas de seguridad y limitaciones
- Cualquiera que pueda hablar con este servidor MCP puede leer cada contraseña en una bóveda una vez que esté desbloqueada. Solo conecta clientes de confianza.
- El servidor no implementa sincronización de Enpass, historial de elementos ni papelera.
- El servidor es de solo lectura y nunca modifica una bóveda. Crear o editar entradas está intencionalmente no soportado, porque las escrituras directas a la base de datos bloquean las bóvedas recientes de Enpass (consulta Por qué no hay soporte de escritura).
- Este es un proyecto independiente y no está afiliado ni respaldado por Enpass.
Licencia
MIT © Fabian Bitter