Enpass MCP
Lê e grava cofres locais do Enpass: entradas, senhas e códigos TOTP, com a senha mestra obtida do chaveiro do sistema operacional para que nunca chegue ao modelo.
Documentação
enpass-mcp
Um servidor Model Context Protocol (MCP) que dá a um assistente de IA acesso controlado e local aos seus cofres de senhas do Enpass: desbloqueie um cofre, liste cofres, e liste e leia entradas. Criar e excluir entradas também é possível, mas fica desativado até que você habilite.
Executa localmente via stdio. Seu cofre do Enpass nunca sai da sua máquina, e sua senha mestra nunca passa pelo modelo: ela é armazenada no chaveiro do seu sistema operacional e lida diretamente pelo servidor.
Por que isso é seguro
- Senhas mestras ficam no chaveiro do SO (Keychain do macOS, Gerenciador de Credenciais do Windows, Secret Service do Linux), não em arquivos de configuração, não em variáveis de ambiente, e nunca como argumento de ferramenta. A ferramenta
unlock_vaultdeliberadamente não aceita parâmetro de senha, então a senha nunca pode acabar no contexto do modelo ou em logs. - O cofre permanece local. O servidor lê o arquivo
vault.enpassdbcriptografado diretamente com SQLCipher. Nada é enviado para lugar algum. - Leituras são explícitas. Listar entradas nunca retorna senhas. Segredos só são retornados por
get_item/get_password, quando você os solicita explicitamente. - Somente leitura, a menos que você diga o contrário. Por padrão, o servidor não pode alterar nada: as ferramentas de escrita nem são anunciadas. Defina
ENPASS_MCP_ALLOW_WRITES=1para habilitá-las (veja Escrita).
As senhas das entradas são, por design, retornadas ao assistente quando você as solicita, então conecte apenas a um assistente e cofres em que você confia.
Requisitos
- Node.js 18 ou mais recente
- Um cofre Enpass 6 / 7 / 8 (
vault.enpassdb, formato SQLCipher) - No Linux: um provedor de Secret Service (GNOME Keyring ou KWallet) para armazenamento de senhas
Dependências nativas (better-sqlite3-multiple-ciphers, @napi-rs/keyring) incluem binários pré-compilados para plataformas comuns, então nenhum compilador é necessário no caso normal.
Instalação
git clone https://github.com/bitterdev/enpass-mcp.git
cd enpass-mcp
npm install
npm link # optional: makes the `enpass-mcp` command available globally
Registre seus cofres (faça isso uma vez, em um terminal)
Este é o passo seguro que mantém a senha mestra longe do modelo. Você mesmo o executa; a senha é digitada em um prompt oculto e armazenada no chaveiro do SO.
# 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 se a senha realmente consegue desbloquear o cofre antes de salvá-la.
O arquivo do cofre geralmente é encontrado em:
| SO | Localização típica |
|---|---|
| macOS | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
| Windows | %USERPROFILE%\Documents\Enpass\Vaults\<vault>\vault.enpassdb |
| Linux | ~/Documents/Enpass/Vaults/<vault>/vault.enpassdb |
Se você sincroniza via Dropbox / OneDrive / WebDAV, aponte --path para a cópia sincronizada.
Conecte-o ao seu assistente
O servidor fala MCP via stdio. Aponte seu cliente MCP para enpass-mcp serve.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"enpass": {
"command": "enpass-mcp",
"args": ["serve"]
}
}
}
Se você não executou npm link, use o caminho absoluto:
{
"mcpServers": {
"enpass": {
"command": "node",
"args": ["/absolute/path/to/enpass-mcp/src/cli.js", "serve"]
}
}
}
Claude Code:
claude mcp add enpass -- enpass-mcp serve
Ferramentas
| Ferramenta | Descrição |
|---|---|
list_vaults | Lista cofres registrados, se o arquivo existe, se uma senha está armazenada e se estão desbloqueados. |
unlock_vault | Desbloqueia um cofre usando a senha mestra do chaveiro do SO. Aceita apenas um nome de cofre, nunca uma senha. |
lock_vault | Bloqueia um cofre e limpa sua chave derivada da memória. |
list_items | Lista entradas (título, nome de usuário, URL). Nunca retorna senhas. Suporta query, category, folder, limit. |
get_item | Retorna uma entrada completa, incluindo todos os valores de campos (senha, TOTP, etc.) e sua lista de anexos. |
get_password | Retorna a senha e, se presente, o código TOTP atual de uma entrada. |
get_otp | Gera o código TOTP / 2FA de uso único atual para uma entrada, com os segundos até a rotação. |
list_attachments | Lista os anexos de arquivo de uma entrada (nome, tamanho, MIME). |
export_attachment | Descriptografa um anexo; grava-o em disco e retorna o caminho (ou base64 inline para arquivos pequenos). |
sync_status | Lista os cofres que usam sincronização de pasta do Enpass e se a cópia na pasta de sincronização é mais recente. |
Com ENPASS_MCP_ALLOW_WRITES=1, mais três ferramentas aparecem (veja Escrita):
| Ferramenta | Descrição |
|---|---|
create_item | Cria uma entrada, incluindo campos personalizados; valores sensíveis são criptografados da forma que o Enpass faz. |
delete_item | Exclui uma entrada, ou a move para a lixeira, deixando o tombstone que o Enpass usa para que a exclusão seja sincronizada. |
sync_pull | Aceita uma cópia mais recente da pasta de sincronização, após fazer backup do cofre local. |
list_items / get_item funcionam para todos os tipos de entrada do Enpass (logins, cartões de crédito, notas seguras, identidades, etc.), não apenas logins, e retornam todos os campos.
Um fluxo típico de assistente: list_vaults → unlock_vault → list_items → get_password.
Como funciona
O Enpass armazena cada cofre como um banco de dados SQLCipher padrão (vault.enpassdb). A chave de criptografia bruta é derivada da sua senha mestra (opcionalmente combinada com um keyfile) e do salt de 16 bytes no início do arquivo:
- PBKDF2-HMAC-SHA512, 100000 iterações (cofres mais antigos) ou 320000 (cofres mais novos), os primeiros 32 bytes usados como chave SQLCipher bruta
- aberto com
cipher_compatibility4 (Enpass 6.8+) ou 3 (cofres mais antigos)
O servidor tenta essas combinações automaticamente, então funciona em todas as versões de cofre do Enpass. A chave derivada é mantida apenas em memória, durante a vida útil do processo do servidor, e nunca é gravada em disco ou retornada ao modelo.
Referências: Enpass Security Whitepaper, hazcod/enpass-cli.
Criptografia de campos por item
O Enpass criptografa cada valor marcado como "sensível" uma segunda vez, por baixo do SQLCipher, com uma chave que pertence à entrada, não ao cofre. Campos que carregam essa camada têm itemfield.algo_version = 1:
| Peça | Onde | Layout |
|---|---|---|
| Chave e nonce | item.key | 44 bytes: chave AES-256 de 32 bytes, depois um nonce GCM de 12 bytes |
| Valor | itemfield.value | hex de ciphertext || 16-byte GCM tag |
| Dados adicionais | o uuid da entrada | hífens removidos, hex-decodificado para 16 bytes brutos |
Vincular o AAD ao uuid da entrada é o que torna um valor inutilizável se for copiado para outra entrada. O Enpass não re-criptografou entradas existentes quando introduziu essa camada, então um cofre mistura texto cifrado e texto puro sob o mesmo algo_version; um valor é tratado como criptografado apenas quando tem a forma de um payload (hex puro, bytes inteiros, mais longo que o tag sozinho).
Um valor que parece criptografado, mas falha na autenticação, é retornado como null com decryptionFailed: true, nunca como o conteúdo bruto da coluna: texto cifrado armazenado é uma string de aparência plausível, e devolvê-lo passaria silenciosamente um segredo errado como se fosse real.
Códigos de dois fatores (TOTP)
Entradas com um segredo de senha de uso único (armazenado pelo Enpass como uma URI otpauth://) podem produzir um código 2FA ao vivo: get_otp retorna o código atual de 6 dígitos e os segundos até a rotação, e get_password inclui o código atual junto com a senha. Isso permite que um assistente preencha tanto a senha quanto o prompt de 2FA.
Anexos
O Enpass mantém anexos de arquivo criptografados. Arquivos pequenos (até 1 KB) ficam inline no cofre; arquivos maiores ficam em arquivos <uuid>.enpassattach SQLCipher separados ao lado do cofre, cada um criptografado com sua própria chave armazenada no cofre. export_attachment lida com ambos: descriptografa o arquivo e, por padrão, grava-o em disco e retorna o caminho, então funciona para arquivos de qualquer tamanho sem enviar dados binários pelo modelo.
O tratamento de anexos externos é implementado a partir do formato documentado do Enpass. Se você encontrar um cofre cujos anexos não descriptografam, abra uma issue com o esquema (não secreto) da sua tabela attachment.
Escrita (opt-in)
A escrita está desativada por padrão. Um cofre de senhas é o último lugar onde uma ferramenta deveria poder alterar dados só porque um modelo decidiu, então o servidor inicia somente leitura e nem lista create_item, delete_item e sync_pull até que você os ative:
ENPASS_MCP_ALLOW_WRITES=1
Defina-o no ambiente do servidor (na configuração do seu cliente MCP, ou no .env ao lado de vaults.json). Nada mais muda: a leitura funciona exatamente da mesma forma de qualquer maneira.
O Enpass deve estar fechado durante a escrita. O aplicativo mantém o banco de dados em memória e gravaria sua própria cópia em cache por cima de qualquer alteração feita por baixo. Toda ferramenta de escrita se recusa a executar enquanto o Enpass estiver aberto.
Versões anteriores deste README afirmavam que a escrita era impossível porque cofres recentes (schema versão 6) travam o Enpass quando entradas são inseridas diretamente. O travamento era real, o diagnóstico estava errado. Três regras concretas fazem funcionar, todas derivadas do que o próprio Enpass grava:
- O Enpass nunca armazena
NULL. O travamento éEXC_BAD_ACCESSemstrlenem um ponteiro nulo: uma coluna omitida doINSERTassume o padrãoNULL, e o aplicativo chamastrlennela. Toda coluna é gravada explicitamente, strings vazias em vez deNULL. - Um template tem um conjunto fixo de campos.
login.defaultsempre carrega os mesmos nove campos, na mesma ordem, com os mesmos uids de campo, mesmo quando a maioria está vazia. Gravar apenas os campos para os quais você tem um valor produz uma entrada que o aplicativo não consegue renderizar. - A chave por item é reproduzível.
item.keyé uma chave AES-256 de 32 bytes mais um nonce GCM de 12 bytes, armazenada comohex(ciphertext || tag)com o UUID do item como dados autenticados adicionais. Nada nela está ligado a internals do Enpass, então uma chave aleatória nova por item é suficiente.
Verificado de ponta a ponta contra um cofre real: gravado, lido de volta, descriptografado para o original, excluído, sincronizado em ambas as direções, e o Enpass abre o cofre sem travar.
Configuração
As senhas mestras estão no chaveiro do SO; apenas dados não secretos (nomes e caminhos de cofres) são armazenados em um pequeno vaults.json:
- macOS:
~/Library/Application Support/enpass-mcp/vaults.json - Windows:
%APPDATA%\enpass-mcp\vaults.json - Linux:
~/.config/enpass-mcp/vaults.json
Substitua o diretório com ENPASS_MCP_CONFIG_DIR.
Variáveis de ambiente:
| Variável | Efeito |
|---|---|
ENPASS_MCP_ALLOW_WRITES | 1, true, yes ou on habilita as ferramentas de escrita. Qualquer outra coisa, incluindo não definida, mantém o servidor somente leitura. |
ENPASS_MCP_CONFIG_DIR | Onde vaults.json e o opcional .env ficam. |
ENPASS_MASTER_PASSWORD | Senha mestra de fallback opcional para cofres sem entrada no chaveiro. Prefira o chaveiro. |
ENPASS_MASTER_PASSWORD_<VAULT> | O mesmo, para um cofre específico. |
Desenvolvimento
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) cria um cofre do zero com SQLCipher real, semeia entradas e anexos, e então executa a suíte de testes completa somente leitura no Node 18/20/22.
Notas de segurança e limitações
- Qualquer pessoa que possa falar com este servidor MCP pode ler todas as senhas de um cofre uma vez que ele esteja desbloqueado. Conecte apenas clientes confiáveis.
- O servidor não implementa sincronização do Enpass, histórico de itens ou lixeira.
- O servidor é somente leitura e nunca modifica um cofre. Criar ou editar entradas não é suportado intencionalmente, porque gravações diretas no banco de dados travam cofres recentes do Enpass (veja Por que não há suporte a escrita).
- Este é um projeto independente e não é afiliado ou endossado pelo Enpass.
Licença
MIT © Fabian Bitter